/** * Agent Attention Registry * * In-process record of which agent sessions are currently blocked on a human * (waiting_on_human, #815). The ActivityMonitor writes it on every poll; the * reconciler reads it to build AgentHealth.waitingOnHumanSince. * * Kept separate from both services so neither has to import the other's * singleton. State is in memory on purpose: after a backend restart the * first monitor poll (≤30s) re-detects a prompt that is still on screen. * * KNOWN GAP (#820, filed as #851): the other direction is not yet handled — * if the owner answers the prompt WHILE the backend is down, this registry * comes back up empty and never learns the session was waiting. The durable * `agent_waiting_on_human` escalation opened before the restart * (EscalationRouterService.recordAgentWaitingOnHuman) is then never closed, * because ActivityMonitorService.clearAttention only calls * `resolveAgentWaitingOnHuman` when `clearWaiting()` here finds a matching * entry. The affected WorkItem itself is unaffected — its blocked->running * transition self-heals independently via the reconciler's next poll — only * the owner-facing escalation record can go stale. See #851 for why this * was documented rather than fixed inline (a correct fix costs a * listPending() read on every poll of every non-waiting agent unless done * as a one-time startup reconciliation instead). * * @module services/monitoring/agent-attention-registry */ import type { WaitingKind } from './agent-attention.js'; /** One agent's current waiting state. */ export interface WaitingEntry { /** Session that is waiting. */ sessionName: string; /** What it is waiting on. */ kind: WaitingKind; /** ISO time the wait was first observed. */ since: string; /** Rule evidence from the verdict. */ evidence: string[]; /** Task label from the terminal title, if any. */ titleLabel?: string; } /** * Record that a session is waiting. Keeps the original `since` (and kind) * when the session was already waiting, so the wait duration is not reset by * each poll. * * @param entry - The waiting state; `since` is used only for a new wait * @returns True when this starts a new wait, false when it continues one */ export declare function markWaiting(entry: WaitingEntry): boolean; /** * Record that a session is no longer waiting. * * @param sessionName - The session * @returns The entry that was cleared, or undefined when it was not waiting */ export declare function clearWaiting(sessionName: string): WaitingEntry | undefined; /** * Get a session's current waiting state. * * @param sessionName - The session * @returns The entry, or undefined when the session is not waiting */ export declare function getWaiting(sessionName: string): WaitingEntry | undefined; /** * List every session currently waiting. * * @returns Snapshot of all waiting entries */ export declare function listWaiting(): WaitingEntry[]; /** * Forget all state (tests only). */ export declare function resetWaitingRegistry(): void; //# sourceMappingURL=agent-attention-registry.d.ts.map