/** * Subagent inbox: the notify-and-pull bookkeeping behind background `Task` * dispatch and the `TaskOutput` tool. * * Background dispatches don't push their full result into the parent's context. * Instead the parent gets a compact notification ("explore#1 finished") and the * body is retained here, keyed by task id, until the model explicitly pulls it * with TaskOutput. This keeps a wide swarm of subagents from flooding the * context with N full summaries, and gives the model a queryable liveness view * (running / done / failed + last activity) so it can tell a working subagent * from a rogue one. The same surface works at every delegation depth. * * Lifecycle per task: * running ──▶ done (body retained) ──collect──▶ collected (body dropped) * ├─▶ failed * ├─▶ stalled * └─▶ timeout */ import type { SubagentPool, TaskResult } from "./subagent-pool.js"; type TaskLifecycle = "running" | "done" | "failed" | "stalled" | "timeout" | "cancelled" | "collected"; export interface InboxRecord { taskId: string; /** Friendly handle shown to the model, e.g. "explore#1". */ label: string; agentType: string; lifecycle: TaskLifecycle; startedAt: number; endedAt?: number; /** Tool the subagent is currently running, from the pool's progress stream. */ lastActivity?: string; /** First line of the result/summary, kept even after the body is collected. */ summaryLine?: string; /** Full subagent summary, retained only while `done` and uncollected. */ body?: string; /** Failure reason when the task did not succeed. */ error?: string; } declare class SubagentInbox { private records; /** Insertion order of task ids, for stable listing and pruning. */ private order; private labelCounters; private observedPools; /** One-shot callbacks fired after any record settles, for the wait helpers. */ private settleListeners; private notifySettle; /** * Resolve once the given task settles (or immediately if already settled / * unknown), bounded by `timeoutMs`. Backs TaskOutput's per-task wait. */ waitFor(handle: string, timeoutMs: number): Promise; /** Resolve once nothing is outstanding (the swarm barrier), bounded by `timeoutMs`. */ waitForAll(timeoutMs: number): Promise; /** Allocate the next friendly label for an agent type (`explore#1`, `explore#2`, …). */ nextLabel(agentType: string): string; /** * Track a pool's `task_progress` events so running records carry a live * `lastActivity`. Idempotent per pool, so callers can wire it on every dispatch. */ observe(pool: SubagentPool): void; /** Register a freshly dispatched background task as running. */ start(taskId: string, label: string, agentType: string): InboxRecord; /** Settle a task from its dispatch result: retain the body on success, the reason on failure. */ finish(taskId: string, result: TaskResult): InboxRecord | undefined; /** Settle a task that never produced a TaskResult (e.g. a thrown dispatch error). */ fail(taskId: string, reason: string, lifecycle?: TaskLifecycle): InboxRecord | undefined; /** Look up a record by task id or by friendly label. */ get(handle: string): InboxRecord | undefined; /** * Read a done task's body and mark it collected, dropping the body so it is not * re-fed to the model. Returns the record (with `body` still populated for this * one read) or undefined for an unknown handle. */ collect(handle: string): { record: InboxRecord; body: string; } | undefined; /** All records, oldest first. */ list(): InboxRecord[]; /** Records still doing work. */ outstanding(): InboxRecord[]; /** Test/teardown helper. */ clear(): void; /** Drop the oldest settled records once past the cap; running records are kept. */ private prune; } /** Process-wide subagent inbox shared by the Task and TaskOutput tools. */ export declare const subagentInbox: SubagentInbox; export {}; //# sourceMappingURL=subagent-inbox.d.ts.map