Add server-side client activity tracking for smart notifications
- Add client_heartbeat message type for clients to report activity - Add shouldNotify field to attention_required events - Track client activity (focusedAgentId, lastActivityAt) per session - WebSocketServer checks all sessions to determine shouldNotify - If any client is active on the agent (within 60s), shouldNotify=false - Add onAgentAttention callback to AgentManager for clean separation
This commit is contained in:
@@ -45,12 +45,19 @@ export type PersistedAgentQueryOptions = ListPersistedAgentsOptions & {
|
||||
provider?: AgentProvider;
|
||||
};
|
||||
|
||||
export type AgentAttentionCallback = (params: {
|
||||
agentId: string;
|
||||
provider: AgentProvider;
|
||||
reason: "finished" | "error" | "permission";
|
||||
}) => void;
|
||||
|
||||
export type AgentManagerOptions = {
|
||||
clients?: Partial<Record<AgentProvider, AgentClient>>;
|
||||
maxTimelineItems?: number;
|
||||
idFactory?: () => string;
|
||||
registry?: AgentRegistry;
|
||||
agentControlMcp?: AgentControlMcpConfig;
|
||||
onAgentAttention?: AgentAttentionCallback;
|
||||
};
|
||||
|
||||
export type WaitForAgentOptions = {
|
||||
@@ -176,6 +183,7 @@ export class AgentManager {
|
||||
private readonly registry?: AgentRegistry;
|
||||
private readonly previousStatuses = new Map<string, AgentLifecycleStatus>();
|
||||
private readonly agentControlMcp?: AgentControlMcpConfig;
|
||||
private onAgentAttention?: AgentAttentionCallback;
|
||||
|
||||
constructor(options?: AgentManagerOptions) {
|
||||
this.maxTimelineItems =
|
||||
@@ -183,6 +191,7 @@ export class AgentManager {
|
||||
this.idFactory = options?.idFactory ?? (() => randomUUID());
|
||||
this.registry = options?.registry;
|
||||
this.agentControlMcp = options?.agentControlMcp;
|
||||
this.onAgentAttention = options?.onAgentAttention;
|
||||
if (options?.clients) {
|
||||
for (const [provider, client] of Object.entries(options.clients)) {
|
||||
if (client) {
|
||||
@@ -196,6 +205,10 @@ export class AgentManager {
|
||||
this.clients.set(provider, client);
|
||||
}
|
||||
|
||||
setAgentAttentionCallback(callback: AgentAttentionCallback): void {
|
||||
this.onAgentAttention = callback;
|
||||
}
|
||||
|
||||
subscribe(callback: AgentSubscriber, options?: SubscribeOptions): () => void {
|
||||
const record: SubscriptionRecord = {
|
||||
callback,
|
||||
@@ -985,11 +998,10 @@ export class AgentManager {
|
||||
agent: ManagedAgent,
|
||||
reason: "finished" | "error" | "permission"
|
||||
): void {
|
||||
this.dispatchStream(agent.id, {
|
||||
type: "attention_required",
|
||||
this.onAgentAttention?.({
|
||||
agentId: agent.id,
|
||||
provider: agent.provider,
|
||||
reason,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user