@kolisachint/hoocode-agent 0.4.31 → 0.4.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-pool.js","sourceRoot":"","sources":["../../src/core/subagent-pool.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { EventEmitter } from \"node:events\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { getDispatchTaskDir } from \"../config.js\";\nimport { waitForChildProcess } from \"../utils/child-process.js\";\nimport { MODEL_INHERIT } from \"./agent-frontmatter.js\";\nimport { type AgentRegistry, loadAgentRegistry } from \"./agent-registry.js\";\nimport { DispatchEvaluator } from \"./dispatch-evaluator.js\";\nimport { SubagentLifeguard } from \"./lifeguard.js\";\nimport { OutputVerifier } from \"./output-verifier.js\";\nimport { TokenBudget } from \"./token-budget.js\";\n\nexport interface SubagentPoolTask {\n\ttask_id: string;\n\tagent_type: string;\n\ttask: string;\n\tcontext?: string;\n\ttoken_budget?: number;\n\tcwd?: string;\n\tmodel?: string;\n\tprovider?: string;\n\t/**\n\t * Explicit session file for the child to persist/continue. When omitted the\n\t * child uses its own dispatch dir (`<dispatch>/<task_id>/session.jsonl`).\n\t * Resume reuses the original task's session file to continue the transcript.\n\t */\n\tsessionFile?: string;\n}\n\nexport interface SubagentSlot {\n\tpid: number;\n\tagent_type: string;\n\ttask_id: string;\n\tspawned_at: number;\n\ttoken_budget: number;\n\tprocess: ReturnType<typeof spawn>;\n}\n\nexport interface SubagentResult {\n\ttask_id: string;\n\tok: boolean;\n\tstdout: string;\n\tstderr: string;\n\texit_code: number | null;\n\terror?: string;\n\t/** True when the task exceeded its token budget and was hard-stopped. */\n\tbudget_exceeded?: boolean;\n\t/** Terminal status derived from how the task finished. */\n\tstatus?: \"complete\" | \"partial\" | \"failed\" | \"stalled\" | \"timeout\";\n\t/** Parsed result.json content when available (e.g. on partial completion). */\n\tresult_data?: Record<string, unknown>;\n}\n\nexport interface TaskResult {\n\t/** True when the evaluator decided the task is simple enough for inline handling. */\n\thandled_inline: boolean;\n\t/** Present when the task was delegated. */\n\ttask_id?: string;\n\tagent_type?: string;\n\treason?: string;\n\t/** Subagent result when delegated. */\n\tresult?: SubagentResult;\n\t/** Duration in milliseconds when delegated. */\n\tduration?: number;\n}\n\nexport interface DispatchOptions {\n\t/** Skip evaluation and force this agent type (user/explicit override).\n\t * Accepts any registry-defined agent name, not just the built-in modes. */\n\tforceAgent?: string;\n\t/** Context distilled from the calling agent, passed to the subagent. */\n\tcontext?: string;\n\t/** Model id for the subagent (defaults to the child's configured default). */\n\tmodel?: string;\n\t/** Provider for the subagent. */\n\tprovider?: string;\n\t/** Explicit session file to persist/continue (used by resume). */\n\tsessionFile?: string;\n}\n\nexport interface SubagentPoolOptions {\n\t/** Path to the hoocode executable (or the runtime, e.g. node, when prefixArgs is set). */\n\texecutable: string;\n\t/** Args inserted before task args (e.g. the CLI entry script for node/tsx). */\n\tprefixArgs?: string[];\n\t/** Maximum concurrent child processes. Defaults to 5. */\n\tmaxConcurrency?: number;\n\t/** Working directory for spawned processes. Defaults to process.cwd(). */\n\tcwd?: string;\n\t/** Environment variables. Defaults to process.env. */\n\tenv?: NodeJS.ProcessEnv;\n\t/** Default token budget per task. Defaults to 0. */\n\tdefaultTokenBudget?: number;\n\t/**\n\t * Non-default skill paths to forward to every spawned subagent via --skill.\n\t * Subagents auto-discover skills from standard locations; only paths that\n\t * won't be found by default discovery need to be forwarded here.\n\t */\n\tskillPaths?: string[];\n}\n\n/**\n * Default hard cap on assistant turns for a spawned subagent when its definition\n * does not set `maxTurns`. The token budget is advisory (it warns but never\n * kills), so this turn cap is the guaranteed hard stop for every subagent.\n */\nexport const DEFAULT_SUBAGENT_MAX_TURNS = 50;\n\n/**\n * Pool for running hoocode subagents as child processes with bounded concurrency,\n * FIFO queuing with priority support, and automatic slot refill.\n *\n * Events:\n * - \"task_done\" – task completed successfully and output was verified\n * - \"task_failed\" – task failed (spawn error, bad exit code, verification failure)\n * - \"task_stalled\" – heartbeat missed for 60s, process was SIGKILLed\n * - \"task_timeout\" – hard timeout exceeded, process was SIGKILLed\n * - \"budget_warning\" – token usage crossed 80% threshold (advisory)\n * - \"budget_exceeded\" – token usage crossed 100% threshold (advisory; never kills)\n */\nexport class SubagentPool extends EventEmitter {\n\tprivate readonly maxConcurrency: number;\n\tprivate readonly executable: string;\n\tprivate readonly prefixArgs: string[];\n\tprivate readonly cwd: string;\n\tprivate readonly env: NodeJS.ProcessEnv;\n\tprivate readonly defaultTokenBudget: number;\n\t/** Non-default skill paths forwarded to every spawned subagent via --skill. */\n\tprivate skillPaths: string[];\n\n\tprivate slots = new Map<string, SubagentSlot>();\n\tprivate queue: SubagentPoolTask[] = [];\n\tprivate completed = new Map<string, SubagentResult>();\n\tprivate waiters = new Map<string, { resolve: (result: SubagentResult) => void; reject: (err: Error) => void }>();\n\tprivate budgets = new Map<string, TokenBudget>();\n\tprivate verifier = new OutputVerifier();\n\tprivate lifeguard: SubagentLifeguard;\n\tprivate disposed = false;\n\t/** Lazily-loaded agent registry (frontmatter definitions) for this pool's cwd. */\n\tprivate registry?: AgentRegistry;\n\t/** Tracks why a task was killed (stalled / timeout) before exit handler fires. */\n\tprivate killReasons = new Map<string, \"stalled\" | \"timeout\">();\n\t/** Persistent terminal status map, survives wait_for consumption. */\n\tprivate taskStatus = new Map<string, \"done\" | \"failed\" | \"stalled\" | \"timeout\">();\n\n\tconstructor(options: SubagentPoolOptions) {\n\t\tsuper();\n\t\tthis.maxConcurrency = options.maxConcurrency ?? 5;\n\t\tthis.executable = options.executable;\n\t\tthis.prefixArgs = options.prefixArgs ?? [];\n\t\tthis.cwd = options.cwd ?? process.cwd();\n\t\tthis.env = options.env ?? process.env;\n\t\tthis.defaultTokenBudget = options.defaultTokenBudget ?? 0;\n\t\tthis.skillPaths = options.skillPaths ? [...options.skillPaths] : [];\n\t\tthis.verifier = new OutputVerifier(this.cwd);\n\t\tthis.lifeguard = new SubagentLifeguard(this.cwd);\n\t\tthis.lifeguard.on(\"stalled\", (data: { task_id: string; pid: number }) => {\n\t\t\tthis.killReasons.set(data.task_id, \"stalled\");\n\t\t\tthis.emit(\"task_stalled\", data);\n\t\t});\n\t\tthis.lifeguard.on(\"timeout\", (data: { task_id: string; pid: number }) => {\n\t\t\tthis.killReasons.set(data.task_id, \"timeout\");\n\t\t\tthis.emit(\"task_timeout\", data);\n\t\t});\n\t}\n\n\t/** Update the non-default skill paths forwarded to new subagents. */\n\tupdateSkillPaths(paths: string[]): void {\n\t\tthis.skillPaths = [...paths];\n\t}\n\n\t/** Lazily load the agent registry for this pool's cwd. */\n\tprivate getRegistry(): AgentRegistry {\n\t\tif (!this.registry) {\n\t\t\tthis.registry = loadAgentRegistry({ cwd: this.cwd });\n\t\t}\n\t\treturn this.registry;\n\t}\n\n\t/** Priority value: higher numbers run first. */\n\tprivate priorityOf(agent_type: string): number {\n\t\tswitch (agent_type) {\n\t\t\tcase \"explore\":\n\t\t\tcase \"review\":\n\t\t\t\treturn 2;\n\t\t\tcase \"doc\":\n\t\t\t\treturn 0;\n\t\t\tdefault:\n\t\t\t\treturn 1;\n\t\t}\n\t}\n\n\t/** Queue a task. It will run when a slot is free. */\n\tspawn(task: SubagentPoolTask): void {\n\t\tif (this.disposed) {\n\t\t\tthrow new Error(\"SubagentPool has been disposed\");\n\t\t}\n\t\tif (\n\t\t\tthis.slots.has(task.task_id) ||\n\t\t\tthis.queue.some((t) => t.task_id === task.task_id) ||\n\t\t\tthis.completed.has(task.task_id)\n\t\t) {\n\t\t\tthrow new Error(`Duplicate task_id: ${task.task_id}`);\n\t\t}\n\n\t\tconst p = this.priorityOf(task.agent_type);\n\t\tconst idx = this.queue.findIndex((t) => this.priorityOf(t.agent_type) < p);\n\t\tif (idx === -1) {\n\t\t\tthis.queue.push(task);\n\t\t} else {\n\t\t\tthis.queue.splice(idx, 0, task);\n\t\t}\n\t\tthis.pull();\n\t}\n\n\t/** Current status of a task. */\n\tget_status(task_id: string): \"running\" | \"queued\" | \"done\" | \"failed\" | \"stalled\" | \"timeout\" {\n\t\tif (this.slots.has(task_id)) return \"running\";\n\t\tif (this.queue.some((t) => t.task_id === task_id)) return \"queued\";\n\t\tconst persisted = this.taskStatus.get(task_id);\n\t\tif (persisted) return persisted;\n\t\tconst result = this.completed.get(task_id);\n\t\tif (result) {\n\t\t\tif (result.status === \"stalled\") return \"stalled\";\n\t\t\tif (result.status === \"timeout\") return \"timeout\";\n\t\t\tif (result.ok) return \"done\";\n\t\t\treturn \"failed\";\n\t\t}\n\t\treturn \"failed\";\n\t}\n\n\t/** Wait for a task to complete and return its result. */\n\twait_for(task_id: string): Promise<SubagentResult> {\n\t\tif (this.disposed) {\n\t\t\treturn Promise.reject(new Error(\"SubagentPool has been disposed\"));\n\t\t}\n\n\t\tconst existing = this.completed.get(task_id);\n\t\tif (existing) {\n\t\t\tthis.completed.delete(task_id);\n\t\t\treturn Promise.resolve(existing);\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.waiters.set(task_id, { resolve, reject });\n\t\t});\n\t}\n\n\t/** Number of currently running subagents. */\n\trunning_count(): number {\n\t\treturn this.slots.size;\n\t}\n\n\t/** Number of tasks waiting in the queue. */\n\tqueued_count(): number {\n\t\treturn this.queue.length;\n\t}\n\n\t/**\n\t * Dispatch a task through the evaluator.\n\t *\n\t * - If `options.forceAgent` is provided, skip evaluation and spawn directly.\n\t * - Otherwise evaluate the task. If it should be handled inline, return\n\t * `{ handled_inline: true }` immediately.\n\t * - If delegating, spawn the subagent, wait for completion, write\n\t * `output.json`, and return the result.\n\t */\n\tasync dispatch(task: string, options: DispatchOptions = {}): Promise<TaskResult> {\n\t\tif (this.disposed) {\n\t\t\treturn Promise.reject(new Error(\"SubagentPool has been disposed\"));\n\t\t}\n\t\tconst begin = this.beginDispatch(task, options);\n\t\tif (begin.handled_inline) {\n\t\t\treturn { handled_inline: true, reason: begin.reason };\n\t\t}\n\t\tconst result = await this.wait_for(begin.task_id);\n\t\treturn {\n\t\t\thandled_inline: false,\n\t\t\ttask_id: begin.task_id,\n\t\t\tagent_type: begin.agent_type,\n\t\t\treason: begin.reason,\n\t\t\tresult,\n\t\t\tduration: Date.now() - begin.startTime,\n\t\t};\n\t}\n\n\t/**\n\t * Fire-and-forget dispatch for background agents. Spawns the subagent and\n\t * returns its handle immediately; the caller polls get_status()/collect().\n\t */\n\tdispatchDetached(\n\t\ttask: string,\n\t\toptions: DispatchOptions = {},\n\t): { handled_inline: boolean; task_id?: string; agent_type?: string; reason?: string } {\n\t\tif (this.disposed) {\n\t\t\tthrow new Error(\"SubagentPool has been disposed\");\n\t\t}\n\t\tconst begin = this.beginDispatch(task, options);\n\t\tif (begin.handled_inline) {\n\t\t\treturn { handled_inline: true, reason: begin.reason };\n\t\t}\n\t\treturn { handled_inline: false, task_id: begin.task_id, agent_type: begin.agent_type, reason: begin.reason };\n\t}\n\n\t/**\n\t * Evaluate, log, and spawn a task without waiting. Shared by dispatch()\n\t * (blocking) and dispatchDetached() (background).\n\t */\n\tprivate beginDispatch(\n\t\ttask: string,\n\t\toptions: DispatchOptions,\n\t):\n\t\t| { handled_inline: true; reason?: string }\n\t\t| { handled_inline: false; task_id: string; agent_type: string; reason?: string; startTime: number } {\n\t\tconst { forceAgent, context, model, provider, sessionFile } = options;\n\t\tconst evaluator = new DispatchEvaluator();\n\t\tconst analysis = evaluator.evaluate(task);\n\n\t\tif (!forceAgent && !analysis.should_delegate) {\n\t\t\treturn { handled_inline: true, reason: analysis.reason };\n\t\t}\n\n\t\tconst agent_type = forceAgent ?? \"general-purpose\";\n\t\tconst task_id = `dispatch-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\t\tconst reason = forceAgent ? \"user_override\" : analysis.reason;\n\t\tconst complexity = analysis.estimated_complexity;\n\n\t\t// Pre-dispatch logging. Use stderr: stdout is reserved for the JSON event\n\t\t// stream / TUI render and must not be polluted.\n\t\tconsole.error(`[DISPATCH] agent=${agent_type} reason=${reason} complexity=${complexity} task_id=${task_id}`);\n\t\tthis.writeDispatchLog(task_id, agent_type, reason, complexity, task);\n\n\t\tconst poolTask: SubagentPoolTask = {\n\t\t\ttask_id,\n\t\t\tagent_type,\n\t\t\ttask,\n\t\t\tcontext,\n\t\t\tmodel,\n\t\t\tprovider,\n\t\t\tsessionFile,\n\t\t\tcwd: this.cwd,\n\t\t};\n\t\tconst startTime = Date.now();\n\t\tthis.spawn(poolTask);\n\t\treturn { handled_inline: false, task_id, agent_type, reason, startTime };\n\t}\n\n\t/**\n\t * Non-destructively read a completed task's result (for background polling).\n\t * Returns undefined while the task is still running/queued, or if its result\n\t * was already consumed via wait_for().\n\t */\n\tcollect(task_id: string): SubagentResult | undefined {\n\t\treturn this.completed.get(task_id);\n\t}\n\n\t/** Absolute path of the persisted session file for a task. */\n\tgetSessionFile(task_id: string, cwd: string = this.cwd): string {\n\t\treturn join(getDispatchTaskDir(cwd, task_id), \"session.jsonl\");\n\t}\n\n\t/**\n\t * Resume a previously dispatched subagent, continuing its persisted session\n\t * with a follow-up prompt. Recovers the original agent type from its dispatch\n\t * log. Rejects if no resumable session exists for the task.\n\t */\n\tasync resume(\n\t\ttask_id: string,\n\t\tprompt: string,\n\t\toptions: Omit<DispatchOptions, \"forceAgent\" | \"sessionFile\"> = {},\n\t): Promise<TaskResult> {\n\t\tif (this.disposed) {\n\t\t\treturn Promise.reject(new Error(\"SubagentPool has been disposed\"));\n\t\t}\n\t\tconst sessionFile = this.getSessionFile(task_id);\n\t\tif (!existsSync(sessionFile)) {\n\t\t\treturn Promise.reject(new Error(`No resumable session for task \"${task_id}\" (expected ${sessionFile}).`));\n\t\t}\n\t\tconst agent_type = this.readDispatchAgentType(task_id) ?? \"general-purpose\";\n\t\treturn this.dispatch(prompt, { ...options, forceAgent: agent_type, sessionFile });\n\t}\n\n\t/** Recover the agent type a task was dispatched with, from its dispatch log. */\n\tprivate readDispatchAgentType(task_id: string): string | undefined {\n\t\tconst path = join(getDispatchTaskDir(this.cwd, task_id), \"dispatch-log.json\");\n\t\tif (!existsSync(path)) return undefined;\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(readFileSync(path, \"utf-8\")) as { agent_type?: string };\n\t\t\treturn typeof parsed.agent_type === \"string\" ? parsed.agent_type : undefined;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate writeDispatchLog(\n\t\ttask_id: string,\n\t\tagent_type: string,\n\t\treason: string,\n\t\tcomplexity: string,\n\t\ttask: string,\n\t): void {\n\t\tconst log = {\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttask_id,\n\t\t\tagent_type,\n\t\t\treason,\n\t\t\tcomplexity,\n\t\t\ttask,\n\t\t};\n\t\tconst path = join(getDispatchTaskDir(this.cwd, task_id), \"dispatch-log.json\");\n\t\ttry {\n\t\t\tmkdirSync(dirname(path), { recursive: true });\n\t\t\twriteFileSync(path, JSON.stringify(log, null, 2));\n\t\t} catch {\n\t\t\t// Best-effort persistence\n\t\t}\n\t}\n\n\tprivate writeOutputJson(task_id: string, result: SubagentResult): void {\n\t\tconst output = {\n\t\t\ttask_id: result.task_id,\n\t\t\tok: result.ok,\n\t\t\texit_code: result.exit_code,\n\t\t\tstatus: result.status,\n\t\t\tstdout: result.stdout,\n\t\t\tstderr: result.stderr,\n\t\t\terror: result.error,\n\t\t\tbudget_exceeded: result.budget_exceeded,\n\t\t\tresult_data: result.result_data,\n\t\t};\n\t\tconst path = join(getDispatchTaskDir(this.cwd, task_id), \"output.json\");\n\t\ttry {\n\t\t\tmkdirSync(dirname(path), { recursive: true });\n\t\t\twriteFileSync(path, JSON.stringify(output, null, 2));\n\t\t} catch {\n\t\t\t// Best-effort persistence\n\t\t}\n\t}\n\n\t/**\n\t * Remove a task's dispatch dir after a clean, verified success. Best-effort:\n\t * a cleanup failure must never fail an otherwise successful task.\n\t */\n\tprivate cleanupDispatchDir(task_id: string, cwd: string): void {\n\t\ttry {\n\t\t\trmSync(getDispatchTaskDir(cwd, task_id), { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Best-effort cleanup\n\t\t}\n\t}\n\n\t/** Kill all running processes, clear the queue, and reject pending waiters. */\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\n\t\tfor (const slot of this.slots.values()) {\n\t\t\tif (!slot.process.killed) {\n\t\t\t\tslot.process.kill(\"SIGTERM\");\n\t\t\t}\n\t\t}\n\t\tthis.slots.clear();\n\t\tthis.queue = [];\n\n\t\tfor (const [task_id, waiter] of this.waiters) {\n\t\t\twaiter.reject(new Error(\"SubagentPool disposed\"));\n\t\t\tthis.waiters.delete(task_id);\n\t\t}\n\t\tthis.completed.clear();\n\t\tfor (const budget of this.budgets.values()) {\n\t\t\tbudget.removeAllListeners();\n\t\t}\n\t\tthis.budgets.clear();\n\t\tthis.killReasons.clear();\n\t\tthis.taskStatus.clear();\n\t\tthis.lifeguard.dispose();\n\t\tthis.removeAllListeners();\n\t}\n\n\t/** Pull tasks from the queue while slots are available. */\n\tprivate pull(): void {\n\t\twhile (this.slots.size < this.maxConcurrency && this.queue.length > 0) {\n\t\t\tconst task = this.queue.shift()!;\n\t\t\tthis.startTask(task, false);\n\t\t}\n\t}\n\n\t/** Build CLI arguments for a task. */\n\tprivate buildArgs(task: SubagentPoolTask): string[] {\n\t\t// Persist the child's session so a finished/interrupted subagent can be\n\t\t// resumed later (see resume()). SessionManager.open() creates the file on\n\t\t// first run and continues it on subsequent runs.\n\t\tconst sessionFile = task.sessionFile ?? this.getSessionFile(task.task_id, task.cwd ?? this.cwd);\n\t\tconst args: string[] = [\n\t\t\t...this.prefixArgs,\n\t\t\t\"--mode\",\n\t\t\t\"json\",\n\t\t\t\"--session\",\n\t\t\tsessionFile,\n\t\t\t\"--task-id\",\n\t\t\ttask.task_id,\n\t\t];\n\n\t\t// Prefer the data-driven agent definition from the registry; fall back to the\n\t\t// built-in mode prompt/allowlist for legacy modes not present in the registry.\n\t\tconst def = task.agent_type ? this.getRegistry().get(task.agent_type) : undefined;\n\n\t\tif (task.agent_type) {\n\t\t\tconst systemPrompt = def?.prompt;\n\t\t\tif (systemPrompt) {\n\t\t\t\targs.push(\"--system-prompt\", systemPrompt);\n\t\t\t}\n\t\t\t// Tool allowlist comes from the agent definition's frontmatter `tools`\n\t\t\t// field (read-only built-ins declare their own sandbox). When omitted, no\n\t\t\t// --tools is passed and the subagent inherits all parent tools.\n\t\t\tconst tools = def?.tools;\n\t\t\tif (tools && tools.length > 0) {\n\t\t\t\targs.push(\"--tools\", tools.join(\",\"));\n\t\t\t}\n\t\t}\n\n\t\t// Model precedence: a definition's explicit model wins (unless it is the\n\t\t// `inherit` sentinel), otherwise use the caller-provided model.\n\t\tconst explicitModel = def?.model && def.model !== MODEL_INHERIT ? def.model : undefined;\n\t\tconst modelToUse = explicitModel ?? task.model;\n\t\tif (modelToUse) {\n\t\t\targs.push(\"--model\", modelToUse);\n\t\t}\n\t\tif (task.provider) {\n\t\t\targs.push(\"--provider\", task.provider);\n\t\t}\n\n\t\t// Always give subagents a hard turn cap. With the token budget now advisory\n\t\t// (warn-only), this is the guaranteed hard stop for a runaway subagent.\n\t\tconst maxTurns = def?.maxTurns && def.maxTurns > 0 ? def.maxTurns : DEFAULT_SUBAGENT_MAX_TURNS;\n\t\targs.push(\"--max-turns\", String(maxTurns));\n\n\t\t// Forward non-default skill paths so the subagent has access to all parent skills.\n\t\t// Standard discovery locations (~/.hoocode/, .hoocode/, .claude/) are found automatically.\n\t\tfor (const skillPath of this.skillPaths) {\n\t\t\targs.push(\"--skill\", skillPath);\n\t\t}\n\n\t\tconst prompt = task.context?.trim()\n\t\t\t? `Context from the calling agent:\\n\\n${task.context.trim()}\\n\\nTask: ${task.task.trim()}`\n\t\t\t: `Task: ${task.task.trim()}`;\n\t\targs.push(prompt);\n\n\t\treturn args;\n\t}\n\n\t/** Start a task in a child process, with one retry on failure. */\n\tprivate startTask(task: SubagentPoolTask, isRetry: boolean): void {\n\t\t// Get or create a TokenBudget tracker. On retry, reuse the existing one\n\t\t// so cumulative usage persists across retries.\n\t\tlet budget = this.budgets.get(task.task_id);\n\t\tif (!budget) {\n\t\t\tbudget = new TokenBudget(task.task_id, task.agent_type, {\n\t\t\t\tlimit: task.token_budget,\n\t\t\t\tcwd: task.cwd ?? this.cwd,\n\t\t\t});\n\t\t\tbudget.on(\"budget_warning\", (data: { task_id: string; message: string; used: number; limit: number }) => {\n\t\t\t\tthis.emit(\"budget_warning\", data);\n\t\t\t});\n\t\t\t// The token budget is advisory: surface telemetry but never kill. The\n\t\t\t// guaranteed hard stop is the per-subagent turn cap (--max-turns); see\n\t\t\t// DEFAULT_SUBAGENT_MAX_TURNS.\n\t\t\tbudget.on(\"budget_exceeded\", (data: { task_id: string; used: number; limit: number }) => {\n\t\t\t\tthis.emit(\"budget_exceeded\", data);\n\t\t\t});\n\t\t\tthis.budgets.set(task.task_id, budget);\n\t\t}\n\n\t\tlet proc: ReturnType<typeof spawn>;\n\t\ttry {\n\t\t\tproc = spawn(this.executable, this.buildArgs(task), {\n\t\t\t\tcwd: task.cwd ?? this.cwd,\n\t\t\t\t// Mark the child as a subagent so its own DispatchEvaluator refuses to\n\t\t\t\t// spawn further subagents (depth guard).\n\t\t\t\tenv: { ...this.env, HOOCODE_SUBAGENT_DEPTH: \"1\" },\n\t\t\t\tshell: false,\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t});\n\t\t} catch {\n\t\t\tif (!isRetry) {\n\t\t\t\tthis.startTask(task, true);\n\t\t\t} else {\n\t\t\t\tthis.emit(\"task_failed\", {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\terror: \"Spawn failed synchronously\",\n\t\t\t\t});\n\t\t\t\tthis.resolveWaiter(task.task_id, {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tok: false,\n\t\t\t\t\tstdout: \"\",\n\t\t\t\t\tstderr: \"\",\n\t\t\t\t\texit_code: null,\n\t\t\t\t\terror: \"Spawn failed synchronously\",\n\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t});\n\t\t\t\tthis.pull();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst slot: SubagentSlot = {\n\t\t\tpid: proc.pid ?? 0,\n\t\t\tagent_type: task.agent_type,\n\t\t\ttask_id: task.task_id,\n\t\t\tspawned_at: Date.now(),\n\t\t\ttoken_budget: task.token_budget ?? this.defaultTokenBudget,\n\t\t\tprocess: proc,\n\t\t};\n\n\t\tthis.slots.set(task.task_id, slot);\n\t\tthis.lifeguard.monitor(task.task_id, task.agent_type, proc);\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tproc.stdout?.on(\"data\", (data: Buffer) => {\n\t\t\tconst chunk = data.toString();\n\t\t\tstdout += chunk;\n\t\t\tbudget.processStdout(chunk);\n\n\t\t\t// Heartbeat detection: look for {\"ping\":true} JSON lines\n\t\t\tfor (const raw of chunk.split(\"\\n\")) {\n\t\t\t\tconst line = raw.trim();\n\t\t\t\tif (!line.startsWith(\"{\")) continue;\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(line) as Record<string, unknown>;\n\t\t\t\t\tif (parsed.ping === true) {\n\t\t\t\t\t\tthis.lifeguard.recordHeartbeat(task.task_id);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Not a ping line, ignore\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tproc.stderr?.on(\"data\", (data: Buffer) => {\n\t\t\tstderr += data.toString();\n\t\t});\n\n\t\twaitForChildProcess(proc)\n\t\t\t.then((code) => {\n\t\t\t\tthis.slots.delete(task.task_id);\n\t\t\t\tbudget.flush();\n\n\t\t\t\tconst killReason = this.killReasons.get(task.task_id);\n\t\t\t\tthis.killReasons.delete(task.task_id);\n\n\t\t\t\tconst duration = Date.now() - slot.spawned_at;\n\t\t\t\tconst tokens_used = budget.getUsed();\n\t\t\t\tconst budgetExceeded = budget.isExceeded();\n\n\t\t\t\t// If killed by lifeguard, override exit handling\n\t\t\t\tif (killReason === \"stalled\" || killReason === \"timeout\") {\n\t\t\t\t\tconst result: SubagentResult = {\n\t\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tstdout,\n\t\t\t\t\t\tstderr,\n\t\t\t\t\t\texit_code: code,\n\t\t\t\t\t\tstatus: killReason,\n\t\t\t\t\t};\n\t\t\t\t\tthis.writeOutputJson(task.task_id, result);\n\t\t\t\t\tthis.emit(`task_${killReason}`, {\n\t\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\t\tduration,\n\t\t\t\t\t\ttokens_used,\n\t\t\t\t\t});\n\t\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst result: SubagentResult = {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tok: code === 0,\n\t\t\t\t\tstdout,\n\t\t\t\t\tstderr,\n\t\t\t\t\texit_code: code,\n\t\t\t\t\t// Advisory telemetry only: exceeding the budget never fails the task.\n\t\t\t\t\tbudget_exceeded: budgetExceeded,\n\t\t\t\t\tstatus: code === 0 ? \"complete\" : \"failed\",\n\t\t\t\t};\n\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tconst verification = this.verifier.verify(task.task_id, task.cwd ?? this.cwd);\n\t\t\t\t\tif (!verification.valid) {\n\t\t\t\t\t\tresult.ok = false;\n\t\t\t\t\t\tresult.error = verification.reason;\n\t\t\t\t\t\tresult.status = \"failed\";\n\t\t\t\t\t\tthis.writeOutputJson(task.task_id, result);\n\t\t\t\t\t\tthis.emit(\"task_failed\", {\n\t\t\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\t\t\tduration,\n\t\t\t\t\t\t\ttokens_used,\n\t\t\t\t\t\t\terror: verification.reason,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// Attach the verified result.json so callers can read the summary\n\t\t\t\t\t// without parsing the raw event stream.\n\t\t\t\t\tresult.result_data = this.tryReadResultJson(task.task_id, task.cwd ?? this.cwd);\n\n\t\t\t\t\t// Clean success: discard the per-task dispatch dir entirely\n\t\t\t\t\t// (session.jsonl, result.json, dispatch-log.json, budget.json). The\n\t\t\t\t\t// in-memory result already carries result_data, so callers lose\n\t\t\t\t\t// nothing. Trade-off: resume() only works for non-successful tasks.\n\t\t\t\t\tthis.cleanupDispatchDir(task.task_id, task.cwd ?? this.cwd);\n\n\t\t\t\t\tthis.emit(\"task_done\", {\n\t\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\t\tduration,\n\t\t\t\t\t\ttokens_used,\n\t\t\t\t\t\tstatus: \"complete\",\n\t\t\t\t\t});\n\t\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Failure path: keep the dispatch dir for debugging and persist output.\n\t\t\t\t// Attach the child's result.json (if any) and derive a concrete failure\n\t\t\t\t// reason so callers see the real cause (e.g. a provider usage/quota\n\t\t\t\t// error) instead of a generic \"subagent failed\".\n\t\t\t\tresult.result_data = this.tryReadResultJson(task.task_id, task.cwd ?? this.cwd);\n\t\t\t\tif (!result.error) {\n\t\t\t\t\tresult.error = this.deriveFailureReason(result);\n\t\t\t\t}\n\t\t\t\tthis.writeOutputJson(task.task_id, result);\n\t\t\t\tthis.emit(\"task_failed\", {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\tduration,\n\t\t\t\t\ttokens_used,\n\t\t\t\t\terror: result.error ?? `Exited with code ${code}`,\n\t\t\t\t});\n\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\tthis.slots.delete(task.task_id);\n\t\t\t\tbudget.flush();\n\t\t\t\tconst duration = Date.now() - slot.spawned_at;\n\t\t\t\tconst tokens_used = budget.getUsed();\n\t\t\t\tif (!isRetry) {\n\t\t\t\t\tthis.startTask(task, true);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst error = err instanceof Error ? err.message : String(err);\n\t\t\t\tconst result: SubagentResult = {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tok: false,\n\t\t\t\t\tstdout,\n\t\t\t\t\tstderr,\n\t\t\t\t\texit_code: null,\n\t\t\t\t\terror,\n\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t};\n\t\t\t\tthis.writeOutputJson(task.task_id, result);\n\t\t\t\tthis.emit(\"task_failed\", {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\tduration,\n\t\t\t\t\ttokens_used,\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tbudget.removeAllListeners();\n\t\t\t\tthis.budgets.delete(task.task_id);\n\t\t\t\tthis.pull();\n\t\t\t});\n\t}\n\n\t/**\n\t * Best-effort concrete failure reason for a non-zero-exit subagent. Prefers\n\t * the child's result.json summary (which carries the provider/model error\n\t * message on failure), then the tail of stderr, then the exit code.\n\t */\n\tprivate deriveFailureReason(result: SubagentResult): string {\n\t\tconst summary = (result.result_data as { summary?: string } | undefined)?.summary?.trim();\n\t\tif (summary) {\n\t\t\treturn summary;\n\t\t}\n\t\tconst stderrTail = result.stderr\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => line.trim())\n\t\t\t.filter((line) => line.length > 0)\n\t\t\t.slice(-5)\n\t\t\t.join(\"\\n\");\n\t\tif (stderrTail) {\n\t\t\treturn stderrTail;\n\t\t}\n\t\treturn `Exited with code ${result.exit_code}`;\n\t}\n\n\tprivate tryReadResultJson(task_id: string, cwd: string): Record<string, unknown> | undefined {\n\t\tconst path = join(getDispatchTaskDir(cwd, task_id), \"result.json\");\n\t\tif (!existsSync(path)) return undefined;\n\t\ttry {\n\t\t\tconst raw = readFileSync(path, \"utf-8\");\n\t\t\treturn JSON.parse(raw) as Record<string, unknown>;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate resolveWaiter(task_id: string, result: SubagentResult): void {\n\t\t// Persist terminal status for get_status() even after wait_for consumes the result\n\t\tif (result.status === \"stalled\") this.taskStatus.set(task_id, \"stalled\");\n\t\telse if (result.status === \"timeout\") this.taskStatus.set(task_id, \"timeout\");\n\t\telse if (result.ok) this.taskStatus.set(task_id, \"done\");\n\t\telse this.taskStatus.set(task_id, \"failed\");\n\n\t\tconst waiter = this.waiters.get(task_id);\n\t\tif (waiter) {\n\t\t\twaiter.resolve(result);\n\t\t\tthis.waiters.delete(task_id);\n\t\t\treturn;\n\t\t}\n\t\tthis.completed.set(task_id, result);\n\t}\n}\n"]}
1
+ {"version":3,"file":"subagent-pool.js","sourceRoot":"","sources":["../../src/core/subagent-pool.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { EventEmitter } from \"node:events\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { getDispatchTaskDir } from \"../config.js\";\nimport { waitForChildProcess } from \"../utils/child-process.js\";\nimport { MODEL_INHERIT } from \"./agent-frontmatter.js\";\nimport { type AgentRegistry, loadAgentRegistry } from \"./agent-registry.js\";\nimport { DispatchEvaluator } from \"./dispatch-evaluator.js\";\nimport { SubagentLifeguard } from \"./lifeguard.js\";\nimport { OutputVerifier } from \"./output-verifier.js\";\nimport { TokenBudget } from \"./token-budget.js\";\n\nexport interface SubagentPoolTask {\n\ttask_id: string;\n\tagent_type: string;\n\ttask: string;\n\tcontext?: string;\n\ttoken_budget?: number;\n\tcwd?: string;\n\tmodel?: string;\n\tprovider?: string;\n\t/**\n\t * Explicit session file for the child to persist/continue. When omitted the\n\t * child uses its own dispatch dir (`<dispatch>/<task_id>/session.jsonl`).\n\t * Resume reuses the original task's session file to continue the transcript.\n\t */\n\tsessionFile?: string;\n\t/** Internal: retry using the caller's model when a built-in agent's preferred model fails. */\n\tuseInheritedModelFallback?: boolean;\n}\n\nexport interface SubagentSlot {\n\tpid: number;\n\tagent_type: string;\n\ttask_id: string;\n\tspawned_at: number;\n\ttoken_budget: number;\n\tprocess: ReturnType<typeof spawn>;\n}\n\nexport interface SubagentResult {\n\ttask_id: string;\n\tok: boolean;\n\tstdout: string;\n\tstderr: string;\n\texit_code: number | null;\n\terror?: string;\n\t/** True when the task exceeded its token budget and was hard-stopped. */\n\tbudget_exceeded?: boolean;\n\t/** Terminal status derived from how the task finished. */\n\tstatus?: \"complete\" | \"partial\" | \"failed\" | \"stalled\" | \"timeout\";\n\t/** Parsed result.json content when available (e.g. on partial completion). */\n\tresult_data?: Record<string, unknown>;\n}\n\nexport interface TaskResult {\n\t/** True when the evaluator decided the task is simple enough for inline handling. */\n\thandled_inline: boolean;\n\t/** Present when the task was delegated. */\n\ttask_id?: string;\n\tagent_type?: string;\n\treason?: string;\n\t/** Subagent result when delegated. */\n\tresult?: SubagentResult;\n\t/** Duration in milliseconds when delegated. */\n\tduration?: number;\n}\n\nexport interface DispatchOptions {\n\t/** Skip evaluation and force this agent type (user/explicit override).\n\t * Accepts any registry-defined agent name, not just the built-in modes. */\n\tforceAgent?: string;\n\t/** Context distilled from the calling agent, passed to the subagent. */\n\tcontext?: string;\n\t/** Model id for the subagent (defaults to the child's configured default). */\n\tmodel?: string;\n\t/** Provider for the subagent. */\n\tprovider?: string;\n\t/** Explicit session file to persist/continue (used by resume). */\n\tsessionFile?: string;\n}\n\nexport interface SubagentPoolOptions {\n\t/** Path to the hoocode executable (or the runtime, e.g. node, when prefixArgs is set). */\n\texecutable: string;\n\t/** Args inserted before task args (e.g. the CLI entry script for node/tsx). */\n\tprefixArgs?: string[];\n\t/** Maximum concurrent child processes. Defaults to 5. */\n\tmaxConcurrency?: number;\n\t/** Working directory for spawned processes. Defaults to process.cwd(). */\n\tcwd?: string;\n\t/** Environment variables. Defaults to process.env. */\n\tenv?: NodeJS.ProcessEnv;\n\t/** Default token budget per task. Defaults to 0. */\n\tdefaultTokenBudget?: number;\n\t/**\n\t * Non-default skill paths to forward to every spawned subagent via --skill.\n\t * Subagents auto-discover skills from standard locations; only paths that\n\t * won't be found by default discovery need to be forwarded here.\n\t */\n\tskillPaths?: string[];\n}\n\n/**\n * Default hard cap on assistant turns for a spawned subagent when its definition\n * does not set `maxTurns`. The token budget is advisory (it warns but never\n * kills), so this turn cap is the guaranteed hard stop for every subagent.\n */\nexport const DEFAULT_SUBAGENT_MAX_TURNS = 50;\n\n/**\n * Pool for running hoocode subagents as child processes with bounded concurrency,\n * FIFO queuing with priority support, and automatic slot refill.\n *\n * Events:\n * - \"task_done\" – task completed successfully and output was verified\n * - \"task_failed\" – task failed (spawn error, bad exit code, verification failure)\n * - \"task_stalled\" – heartbeat missed for 60s, process was SIGKILLed\n * - \"task_timeout\" – hard timeout exceeded, process was SIGKILLed\n * - \"budget_warning\" – token usage crossed 80% threshold (advisory)\n * - \"budget_exceeded\" – token usage crossed 100% threshold (advisory; never kills)\n */\nexport class SubagentPool extends EventEmitter {\n\tprivate readonly maxConcurrency: number;\n\tprivate readonly executable: string;\n\tprivate readonly prefixArgs: string[];\n\tprivate readonly cwd: string;\n\tprivate readonly env: NodeJS.ProcessEnv;\n\tprivate readonly defaultTokenBudget: number;\n\t/** Non-default skill paths forwarded to every spawned subagent via --skill. */\n\tprivate skillPaths: string[];\n\n\tprivate slots = new Map<string, SubagentSlot>();\n\tprivate queue: SubagentPoolTask[] = [];\n\tprivate completed = new Map<string, SubagentResult>();\n\tprivate waiters = new Map<string, { resolve: (result: SubagentResult) => void; reject: (err: Error) => void }>();\n\tprivate budgets = new Map<string, TokenBudget>();\n\tprivate verifier = new OutputVerifier();\n\tprivate lifeguard: SubagentLifeguard;\n\tprivate disposed = false;\n\t/** Lazily-loaded agent registry (frontmatter definitions) for this pool's cwd. */\n\tprivate registry?: AgentRegistry;\n\t/** Tracks why a task was killed (stalled / timeout) before exit handler fires. */\n\tprivate killReasons = new Map<string, \"stalled\" | \"timeout\">();\n\t/** Persistent terminal status map, survives wait_for consumption. */\n\tprivate taskStatus = new Map<string, \"done\" | \"failed\" | \"stalled\" | \"timeout\">();\n\n\tconstructor(options: SubagentPoolOptions) {\n\t\tsuper();\n\t\tthis.maxConcurrency = options.maxConcurrency ?? 5;\n\t\tthis.executable = options.executable;\n\t\tthis.prefixArgs = options.prefixArgs ?? [];\n\t\tthis.cwd = options.cwd ?? process.cwd();\n\t\tthis.env = options.env ?? process.env;\n\t\tthis.defaultTokenBudget = options.defaultTokenBudget ?? 0;\n\t\tthis.skillPaths = options.skillPaths ? [...options.skillPaths] : [];\n\t\tthis.verifier = new OutputVerifier(this.cwd);\n\t\tthis.lifeguard = new SubagentLifeguard(this.cwd);\n\t\tthis.lifeguard.on(\"stalled\", (data: { task_id: string; pid: number }) => {\n\t\t\tthis.killReasons.set(data.task_id, \"stalled\");\n\t\t\tthis.emit(\"task_stalled\", data);\n\t\t});\n\t\tthis.lifeguard.on(\"timeout\", (data: { task_id: string; pid: number }) => {\n\t\t\tthis.killReasons.set(data.task_id, \"timeout\");\n\t\t\tthis.emit(\"task_timeout\", data);\n\t\t});\n\t}\n\n\t/** Update the non-default skill paths forwarded to new subagents. */\n\tupdateSkillPaths(paths: string[]): void {\n\t\tthis.skillPaths = [...paths];\n\t}\n\n\t/** Lazily load the agent registry for this pool's cwd. */\n\tprivate getRegistry(): AgentRegistry {\n\t\tif (!this.registry) {\n\t\t\tthis.registry = loadAgentRegistry({ cwd: this.cwd });\n\t\t}\n\t\treturn this.registry;\n\t}\n\n\t/** Priority value: higher numbers run first. */\n\tprivate priorityOf(agent_type: string): number {\n\t\tswitch (agent_type) {\n\t\t\tcase \"explore\":\n\t\t\tcase \"review\":\n\t\t\t\treturn 2;\n\t\t\tcase \"doc\":\n\t\t\t\treturn 0;\n\t\t\tdefault:\n\t\t\t\treturn 1;\n\t\t}\n\t}\n\n\t/** Queue a task. It will run when a slot is free. */\n\tspawn(task: SubagentPoolTask): void {\n\t\tif (this.disposed) {\n\t\t\tthrow new Error(\"SubagentPool has been disposed\");\n\t\t}\n\t\tif (\n\t\t\tthis.slots.has(task.task_id) ||\n\t\t\tthis.queue.some((t) => t.task_id === task.task_id) ||\n\t\t\tthis.completed.has(task.task_id)\n\t\t) {\n\t\t\tthrow new Error(`Duplicate task_id: ${task.task_id}`);\n\t\t}\n\n\t\tconst p = this.priorityOf(task.agent_type);\n\t\tconst idx = this.queue.findIndex((t) => this.priorityOf(t.agent_type) < p);\n\t\tif (idx === -1) {\n\t\t\tthis.queue.push(task);\n\t\t} else {\n\t\t\tthis.queue.splice(idx, 0, task);\n\t\t}\n\t\tthis.pull();\n\t}\n\n\t/** Current status of a task. */\n\tget_status(task_id: string): \"running\" | \"queued\" | \"done\" | \"failed\" | \"stalled\" | \"timeout\" {\n\t\tif (this.slots.has(task_id)) return \"running\";\n\t\tif (this.queue.some((t) => t.task_id === task_id)) return \"queued\";\n\t\tconst persisted = this.taskStatus.get(task_id);\n\t\tif (persisted) return persisted;\n\t\tconst result = this.completed.get(task_id);\n\t\tif (result) {\n\t\t\tif (result.status === \"stalled\") return \"stalled\";\n\t\t\tif (result.status === \"timeout\") return \"timeout\";\n\t\t\tif (result.ok) return \"done\";\n\t\t\treturn \"failed\";\n\t\t}\n\t\treturn \"failed\";\n\t}\n\n\t/** Wait for a task to complete and return its result. */\n\twait_for(task_id: string): Promise<SubagentResult> {\n\t\tif (this.disposed) {\n\t\t\treturn Promise.reject(new Error(\"SubagentPool has been disposed\"));\n\t\t}\n\n\t\tconst existing = this.completed.get(task_id);\n\t\tif (existing) {\n\t\t\tthis.completed.delete(task_id);\n\t\t\treturn Promise.resolve(existing);\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.waiters.set(task_id, { resolve, reject });\n\t\t});\n\t}\n\n\t/** Number of currently running subagents. */\n\trunning_count(): number {\n\t\treturn this.slots.size;\n\t}\n\n\t/** Number of tasks waiting in the queue. */\n\tqueued_count(): number {\n\t\treturn this.queue.length;\n\t}\n\n\t/**\n\t * Dispatch a task through the evaluator.\n\t *\n\t * - If `options.forceAgent` is provided, skip evaluation and spawn directly.\n\t * - Otherwise evaluate the task. If it should be handled inline, return\n\t * `{ handled_inline: true }` immediately.\n\t * - If delegating, spawn the subagent, wait for completion, write\n\t * `output.json`, and return the result.\n\t */\n\tasync dispatch(task: string, options: DispatchOptions = {}): Promise<TaskResult> {\n\t\tif (this.disposed) {\n\t\t\treturn Promise.reject(new Error(\"SubagentPool has been disposed\"));\n\t\t}\n\t\tconst begin = this.beginDispatch(task, options);\n\t\tif (begin.handled_inline) {\n\t\t\treturn { handled_inline: true, reason: begin.reason };\n\t\t}\n\t\tconst result = await this.wait_for(begin.task_id);\n\t\treturn {\n\t\t\thandled_inline: false,\n\t\t\ttask_id: begin.task_id,\n\t\t\tagent_type: begin.agent_type,\n\t\t\treason: begin.reason,\n\t\t\tresult,\n\t\t\tduration: Date.now() - begin.startTime,\n\t\t};\n\t}\n\n\t/**\n\t * Fire-and-forget dispatch for background agents. Spawns the subagent and\n\t * returns its handle immediately; the caller polls get_status()/collect().\n\t */\n\tdispatchDetached(\n\t\ttask: string,\n\t\toptions: DispatchOptions = {},\n\t): { handled_inline: boolean; task_id?: string; agent_type?: string; reason?: string } {\n\t\tif (this.disposed) {\n\t\t\tthrow new Error(\"SubagentPool has been disposed\");\n\t\t}\n\t\tconst begin = this.beginDispatch(task, options);\n\t\tif (begin.handled_inline) {\n\t\t\treturn { handled_inline: true, reason: begin.reason };\n\t\t}\n\t\treturn { handled_inline: false, task_id: begin.task_id, agent_type: begin.agent_type, reason: begin.reason };\n\t}\n\n\t/**\n\t * Evaluate, log, and spawn a task without waiting. Shared by dispatch()\n\t * (blocking) and dispatchDetached() (background).\n\t */\n\tprivate beginDispatch(\n\t\ttask: string,\n\t\toptions: DispatchOptions,\n\t):\n\t\t| { handled_inline: true; reason?: string }\n\t\t| { handled_inline: false; task_id: string; agent_type: string; reason?: string; startTime: number } {\n\t\tconst { forceAgent, context, model, provider, sessionFile } = options;\n\t\tconst evaluator = new DispatchEvaluator();\n\t\tconst analysis = evaluator.evaluate(task);\n\n\t\tif (!forceAgent && !analysis.should_delegate) {\n\t\t\treturn { handled_inline: true, reason: analysis.reason };\n\t\t}\n\n\t\tconst agent_type = forceAgent ?? \"general-purpose\";\n\t\tconst task_id = `dispatch-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\t\tconst reason = forceAgent ? \"user_override\" : analysis.reason;\n\t\tconst complexity = analysis.estimated_complexity;\n\n\t\t// Pre-dispatch logging. Use stderr: stdout is reserved for the JSON event\n\t\t// stream / TUI render and must not be polluted.\n\t\tconsole.error(`[DISPATCH] agent=${agent_type} reason=${reason} complexity=${complexity} task_id=${task_id}`);\n\t\tthis.writeDispatchLog(task_id, agent_type, reason, complexity, task);\n\n\t\tconst poolTask: SubagentPoolTask = {\n\t\t\ttask_id,\n\t\t\tagent_type,\n\t\t\ttask,\n\t\t\tcontext,\n\t\t\tmodel,\n\t\t\tprovider,\n\t\t\tsessionFile,\n\t\t\tcwd: this.cwd,\n\t\t};\n\t\tconst startTime = Date.now();\n\t\tthis.spawn(poolTask);\n\t\treturn { handled_inline: false, task_id, agent_type, reason, startTime };\n\t}\n\n\t/**\n\t * Non-destructively read a completed task's result (for background polling).\n\t * Returns undefined while the task is still running/queued, or if its result\n\t * was already consumed via wait_for().\n\t */\n\tcollect(task_id: string): SubagentResult | undefined {\n\t\treturn this.completed.get(task_id);\n\t}\n\n\t/** Absolute path of the persisted session file for a task. */\n\tgetSessionFile(task_id: string, cwd: string = this.cwd): string {\n\t\treturn join(getDispatchTaskDir(cwd, task_id), \"session.jsonl\");\n\t}\n\n\t/**\n\t * Resume a previously dispatched subagent, continuing its persisted session\n\t * with a follow-up prompt. Recovers the original agent type from its dispatch\n\t * log. Rejects if no resumable session exists for the task.\n\t */\n\tasync resume(\n\t\ttask_id: string,\n\t\tprompt: string,\n\t\toptions: Omit<DispatchOptions, \"forceAgent\" | \"sessionFile\"> = {},\n\t): Promise<TaskResult> {\n\t\tif (this.disposed) {\n\t\t\treturn Promise.reject(new Error(\"SubagentPool has been disposed\"));\n\t\t}\n\t\tconst sessionFile = this.getSessionFile(task_id);\n\t\tif (!existsSync(sessionFile)) {\n\t\t\treturn Promise.reject(new Error(`No resumable session for task \"${task_id}\" (expected ${sessionFile}).`));\n\t\t}\n\t\tconst agent_type = this.readDispatchAgentType(task_id) ?? \"general-purpose\";\n\t\treturn this.dispatch(prompt, { ...options, forceAgent: agent_type, sessionFile });\n\t}\n\n\t/** Recover the agent type a task was dispatched with, from its dispatch log. */\n\tprivate readDispatchAgentType(task_id: string): string | undefined {\n\t\tconst path = join(getDispatchTaskDir(this.cwd, task_id), \"dispatch-log.json\");\n\t\tif (!existsSync(path)) return undefined;\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(readFileSync(path, \"utf-8\")) as { agent_type?: string };\n\t\t\treturn typeof parsed.agent_type === \"string\" ? parsed.agent_type : undefined;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate writeDispatchLog(\n\t\ttask_id: string,\n\t\tagent_type: string,\n\t\treason: string,\n\t\tcomplexity: string,\n\t\ttask: string,\n\t): void {\n\t\tconst log = {\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttask_id,\n\t\t\tagent_type,\n\t\t\treason,\n\t\t\tcomplexity,\n\t\t\ttask,\n\t\t};\n\t\tconst path = join(getDispatchTaskDir(this.cwd, task_id), \"dispatch-log.json\");\n\t\ttry {\n\t\t\tmkdirSync(dirname(path), { recursive: true });\n\t\t\twriteFileSync(path, JSON.stringify(log, null, 2));\n\t\t} catch {\n\t\t\t// Best-effort persistence\n\t\t}\n\t}\n\n\tprivate writeOutputJson(task_id: string, result: SubagentResult): void {\n\t\tconst output = {\n\t\t\ttask_id: result.task_id,\n\t\t\tok: result.ok,\n\t\t\texit_code: result.exit_code,\n\t\t\tstatus: result.status,\n\t\t\tstdout: result.stdout,\n\t\t\tstderr: result.stderr,\n\t\t\terror: result.error,\n\t\t\tbudget_exceeded: result.budget_exceeded,\n\t\t\tresult_data: result.result_data,\n\t\t};\n\t\tconst path = join(getDispatchTaskDir(this.cwd, task_id), \"output.json\");\n\t\ttry {\n\t\t\tmkdirSync(dirname(path), { recursive: true });\n\t\t\twriteFileSync(path, JSON.stringify(output, null, 2));\n\t\t} catch {\n\t\t\t// Best-effort persistence\n\t\t}\n\t}\n\n\t/**\n\t * Remove a task's dispatch dir after a clean, verified success. Best-effort:\n\t * a cleanup failure must never fail an otherwise successful task.\n\t */\n\tprivate cleanupDispatchDir(task_id: string, cwd: string): void {\n\t\ttry {\n\t\t\trmSync(getDispatchTaskDir(cwd, task_id), { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Best-effort cleanup\n\t\t}\n\t}\n\n\t/** Kill all running processes, clear the queue, and reject pending waiters. */\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\n\t\tfor (const slot of this.slots.values()) {\n\t\t\tif (!slot.process.killed) {\n\t\t\t\tslot.process.kill(\"SIGTERM\");\n\t\t\t}\n\t\t}\n\t\tthis.slots.clear();\n\t\tthis.queue = [];\n\n\t\tfor (const [task_id, waiter] of this.waiters) {\n\t\t\twaiter.reject(new Error(\"SubagentPool disposed\"));\n\t\t\tthis.waiters.delete(task_id);\n\t\t}\n\t\tthis.completed.clear();\n\t\tfor (const budget of this.budgets.values()) {\n\t\t\tbudget.removeAllListeners();\n\t\t}\n\t\tthis.budgets.clear();\n\t\tthis.killReasons.clear();\n\t\tthis.taskStatus.clear();\n\t\tthis.lifeguard.dispose();\n\t\tthis.removeAllListeners();\n\t}\n\n\t/** Pull tasks from the queue while slots are available. */\n\tprivate pull(): void {\n\t\twhile (this.slots.size < this.maxConcurrency && this.queue.length > 0) {\n\t\t\tconst task = this.queue.shift()!;\n\t\t\tthis.startTask(task, false);\n\t\t}\n\t}\n\n\t/** Build CLI arguments for a task. */\n\tprivate buildArgs(task: SubagentPoolTask): string[] {\n\t\t// Persist the child's session so a finished/interrupted subagent can be\n\t\t// resumed later (see resume()). SessionManager.open() creates the file on\n\t\t// first run and continues it on subsequent runs.\n\t\tconst sessionFile = task.sessionFile ?? this.getSessionFile(task.task_id, task.cwd ?? this.cwd);\n\t\tconst args: string[] = [\n\t\t\t...this.prefixArgs,\n\t\t\t\"--mode\",\n\t\t\t\"json\",\n\t\t\t\"--session\",\n\t\t\tsessionFile,\n\t\t\t\"--task-id\",\n\t\t\ttask.task_id,\n\t\t];\n\n\t\t// Prefer the data-driven agent definition from the registry; fall back to the\n\t\t// built-in mode prompt/allowlist for legacy modes not present in the registry.\n\t\tconst def = task.agent_type ? this.getRegistry().get(task.agent_type) : undefined;\n\n\t\tif (task.agent_type) {\n\t\t\tconst systemPrompt = def?.prompt;\n\t\t\tif (systemPrompt) {\n\t\t\t\targs.push(\"--system-prompt\", systemPrompt);\n\t\t\t}\n\t\t\t// Tool allowlist comes from the agent definition's frontmatter `tools`\n\t\t\t// field (read-only built-ins declare their own sandbox). When omitted, no\n\t\t\t// --tools is passed and the subagent inherits all parent tools.\n\t\t\tconst tools = def?.tools;\n\t\t\tif (tools && tools.length > 0) {\n\t\t\t\targs.push(\"--tools\", tools.join(\",\"));\n\t\t\t}\n\t\t}\n\n\t\t// Model precedence: a definition's explicit model wins (unless it is the\n\t\t// `inherit` sentinel), otherwise use the caller-provided model. Built-in\n\t\t// agents can retry with the inherited model when their preferred model is\n\t\t// unavailable or quota-limited.\n\t\tconst explicitModel =\n\t\t\t!task.useInheritedModelFallback && def?.model && def.model !== MODEL_INHERIT ? def.model : undefined;\n\t\tconst modelToUse = explicitModel ?? task.model;\n\t\tif (modelToUse) {\n\t\t\targs.push(\"--model\", modelToUse);\n\t\t}\n\t\tif (task.provider) {\n\t\t\targs.push(\"--provider\", task.provider);\n\t\t}\n\n\t\t// Always give subagents a hard turn cap. With the token budget now advisory\n\t\t// (warn-only), this is the guaranteed hard stop for a runaway subagent.\n\t\tconst maxTurns = def?.maxTurns && def.maxTurns > 0 ? def.maxTurns : DEFAULT_SUBAGENT_MAX_TURNS;\n\t\targs.push(\"--max-turns\", String(maxTurns));\n\n\t\t// Forward non-default skill paths so the subagent has access to all parent skills.\n\t\t// Standard discovery locations (~/.hoocode/, .hoocode/, .claude/) are found automatically.\n\t\tfor (const skillPath of this.skillPaths) {\n\t\t\targs.push(\"--skill\", skillPath);\n\t\t}\n\n\t\tconst prompt = task.context?.trim()\n\t\t\t? `Context from the calling agent:\\n\\n${task.context.trim()}\\n\\nTask: ${task.task.trim()}`\n\t\t\t: `Task: ${task.task.trim()}`;\n\t\targs.push(prompt);\n\n\t\treturn args;\n\t}\n\n\t/** Start a task in a child process, with one retry on failure. */\n\tprivate startTask(task: SubagentPoolTask, isRetry: boolean): void {\n\t\t// Get or create a TokenBudget tracker. On retry, reuse the existing one\n\t\t// so cumulative usage persists across retries.\n\t\tlet budget = this.budgets.get(task.task_id);\n\t\tif (!budget) {\n\t\t\tbudget = new TokenBudget(task.task_id, task.agent_type, {\n\t\t\t\tlimit: task.token_budget,\n\t\t\t\tcwd: task.cwd ?? this.cwd,\n\t\t\t});\n\t\t\tbudget.on(\"budget_warning\", (data: { task_id: string; message: string; used: number; limit: number }) => {\n\t\t\t\tthis.emit(\"budget_warning\", data);\n\t\t\t});\n\t\t\t// The token budget is advisory: surface telemetry but never kill. The\n\t\t\t// guaranteed hard stop is the per-subagent turn cap (--max-turns); see\n\t\t\t// DEFAULT_SUBAGENT_MAX_TURNS.\n\t\t\tbudget.on(\"budget_exceeded\", (data: { task_id: string; used: number; limit: number }) => {\n\t\t\t\tthis.emit(\"budget_exceeded\", data);\n\t\t\t});\n\t\t\tthis.budgets.set(task.task_id, budget);\n\t\t}\n\n\t\tlet proc: ReturnType<typeof spawn>;\n\t\ttry {\n\t\t\tproc = spawn(this.executable, this.buildArgs(task), {\n\t\t\t\tcwd: task.cwd ?? this.cwd,\n\t\t\t\t// Mark the child as a subagent so its own DispatchEvaluator refuses to\n\t\t\t\t// spawn further subagents (depth guard).\n\t\t\t\tenv: { ...this.env, HOOCODE_SUBAGENT_DEPTH: \"1\" },\n\t\t\t\tshell: false,\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t});\n\t\t} catch {\n\t\t\tif (!isRetry) {\n\t\t\t\tthis.startTask(task, true);\n\t\t\t} else {\n\t\t\t\tthis.emit(\"task_failed\", {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\terror: \"Spawn failed synchronously\",\n\t\t\t\t});\n\t\t\t\tthis.resolveWaiter(task.task_id, {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tok: false,\n\t\t\t\t\tstdout: \"\",\n\t\t\t\t\tstderr: \"\",\n\t\t\t\t\texit_code: null,\n\t\t\t\t\terror: \"Spawn failed synchronously\",\n\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t});\n\t\t\t\tthis.pull();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst slot: SubagentSlot = {\n\t\t\tpid: proc.pid ?? 0,\n\t\t\tagent_type: task.agent_type,\n\t\t\ttask_id: task.task_id,\n\t\t\tspawned_at: Date.now(),\n\t\t\ttoken_budget: task.token_budget ?? this.defaultTokenBudget,\n\t\t\tprocess: proc,\n\t\t};\n\n\t\tthis.slots.set(task.task_id, slot);\n\t\tthis.lifeguard.monitor(task.task_id, task.agent_type, proc);\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tproc.stdout?.on(\"data\", (data: Buffer) => {\n\t\t\tconst chunk = data.toString();\n\t\t\tstdout += chunk;\n\t\t\tbudget.processStdout(chunk);\n\n\t\t\t// Heartbeat detection: look for {\"ping\":true} JSON lines\n\t\t\tfor (const raw of chunk.split(\"\\n\")) {\n\t\t\t\tconst line = raw.trim();\n\t\t\t\tif (!line.startsWith(\"{\")) continue;\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(line) as Record<string, unknown>;\n\t\t\t\t\tif (parsed.ping === true) {\n\t\t\t\t\t\tthis.lifeguard.recordHeartbeat(task.task_id);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Not a ping line, ignore\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tproc.stderr?.on(\"data\", (data: Buffer) => {\n\t\t\tstderr += data.toString();\n\t\t});\n\n\t\twaitForChildProcess(proc)\n\t\t\t.then((code) => {\n\t\t\t\tthis.slots.delete(task.task_id);\n\t\t\t\tbudget.flush();\n\n\t\t\t\tconst killReason = this.killReasons.get(task.task_id);\n\t\t\t\tthis.killReasons.delete(task.task_id);\n\n\t\t\t\tconst duration = Date.now() - slot.spawned_at;\n\t\t\t\tconst tokens_used = budget.getUsed();\n\t\t\t\tconst budgetExceeded = budget.isExceeded();\n\n\t\t\t\t// If killed by lifeguard, override exit handling\n\t\t\t\tif (killReason === \"stalled\" || killReason === \"timeout\") {\n\t\t\t\t\tconst result: SubagentResult = {\n\t\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tstdout,\n\t\t\t\t\t\tstderr,\n\t\t\t\t\t\texit_code: code,\n\t\t\t\t\t\tstatus: killReason,\n\t\t\t\t\t};\n\t\t\t\t\tthis.writeOutputJson(task.task_id, result);\n\t\t\t\t\tthis.emit(`task_${killReason}`, {\n\t\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\t\tduration,\n\t\t\t\t\t\ttokens_used,\n\t\t\t\t\t});\n\t\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst result: SubagentResult = {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tok: code === 0,\n\t\t\t\t\tstdout,\n\t\t\t\t\tstderr,\n\t\t\t\t\texit_code: code,\n\t\t\t\t\t// Advisory telemetry only: exceeding the budget never fails the task.\n\t\t\t\t\tbudget_exceeded: budgetExceeded,\n\t\t\t\t\tstatus: code === 0 ? \"complete\" : \"failed\",\n\t\t\t\t};\n\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tconst verification = this.verifier.verify(task.task_id, task.cwd ?? this.cwd);\n\t\t\t\t\tif (!verification.valid) {\n\t\t\t\t\t\tresult.ok = false;\n\t\t\t\t\t\tresult.error = verification.reason;\n\t\t\t\t\t\tresult.status = \"failed\";\n\t\t\t\t\t\tthis.writeOutputJson(task.task_id, result);\n\t\t\t\t\t\tthis.emit(\"task_failed\", {\n\t\t\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\t\t\tduration,\n\t\t\t\t\t\t\ttokens_used,\n\t\t\t\t\t\t\terror: verification.reason,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// Attach the verified result.json so callers can read the summary\n\t\t\t\t\t// without parsing the raw event stream.\n\t\t\t\t\tresult.result_data = this.tryReadResultJson(task.task_id, task.cwd ?? this.cwd);\n\n\t\t\t\t\t// Clean success: discard the per-task dispatch dir entirely\n\t\t\t\t\t// (session.jsonl, result.json, dispatch-log.json, budget.json). The\n\t\t\t\t\t// in-memory result already carries result_data, so callers lose\n\t\t\t\t\t// nothing. Trade-off: resume() only works for non-successful tasks.\n\t\t\t\t\tthis.cleanupDispatchDir(task.task_id, task.cwd ?? this.cwd);\n\n\t\t\t\t\tthis.emit(\"task_done\", {\n\t\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\t\tduration,\n\t\t\t\t\t\ttokens_used,\n\t\t\t\t\t\tstatus: \"complete\",\n\t\t\t\t\t});\n\t\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Failure path: keep the dispatch dir for debugging and persist output.\n\t\t\t\t// Attach the child's result.json (if any) and derive a concrete failure\n\t\t\t\t// reason so callers see the real cause (e.g. a provider usage/quota\n\t\t\t\t// error) instead of a generic \"subagent failed\".\n\t\t\t\tresult.result_data = this.tryReadResultJson(task.task_id, task.cwd ?? this.cwd);\n\t\t\t\tif (!result.error) {\n\t\t\t\t\tresult.error = this.deriveFailureReason(result);\n\t\t\t\t}\n\t\t\t\tif (this.shouldRetryWithInheritedModel(task, result)) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`[DISPATCH] agent=${task.agent_type} task_id=${task.task_id} preferred model failed; retrying with inherited model`,\n\t\t\t\t\t);\n\t\t\t\t\tthis.cleanupRetryArtifacts(task);\n\t\t\t\t\tthis.queue.unshift({ ...task, useInheritedModelFallback: true });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.writeOutputJson(task.task_id, result);\n\t\t\t\tthis.emit(\"task_failed\", {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\tduration,\n\t\t\t\t\ttokens_used,\n\t\t\t\t\terror: result.error ?? `Exited with code ${code}`,\n\t\t\t\t});\n\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\tthis.slots.delete(task.task_id);\n\t\t\t\tbudget.flush();\n\t\t\t\tconst duration = Date.now() - slot.spawned_at;\n\t\t\t\tconst tokens_used = budget.getUsed();\n\t\t\t\tif (!isRetry) {\n\t\t\t\t\tthis.startTask(task, true);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst error = err instanceof Error ? err.message : String(err);\n\t\t\t\tconst result: SubagentResult = {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tok: false,\n\t\t\t\t\tstdout,\n\t\t\t\t\tstderr,\n\t\t\t\t\texit_code: null,\n\t\t\t\t\terror,\n\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t};\n\t\t\t\tthis.writeOutputJson(task.task_id, result);\n\t\t\t\tthis.emit(\"task_failed\", {\n\t\t\t\t\ttask_id: task.task_id,\n\t\t\t\t\tagent_type: task.agent_type,\n\t\t\t\t\tduration,\n\t\t\t\t\ttokens_used,\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t\tthis.resolveWaiter(task.task_id, result);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tbudget.removeAllListeners();\n\t\t\t\tthis.budgets.delete(task.task_id);\n\t\t\t\tthis.pull();\n\t\t\t});\n\t}\n\n\t/** Whether a failed built-in subagent should be retried with `model: inherit`. */\n\tprivate shouldRetryWithInheritedModel(task: SubagentPoolTask, result: SubagentResult): boolean {\n\t\tif (task.useInheritedModelFallback) return false;\n\t\tif (task.sessionFile) return false;\n\t\tif (!task.model || !task.provider) return false;\n\n\t\tconst def = task.agent_type ? this.getRegistry().get(task.agent_type) : undefined;\n\t\tif (def?.source !== \"builtin\") return false;\n\t\tif (!def.model || def.model === MODEL_INHERIT) return false;\n\n\t\treturn this.isInheritedModelFallbackError(result);\n\t}\n\n\t/** Detect provider/model failures where inheriting the parent model can recover. */\n\tprivate isInheritedModelFallbackError(result: SubagentResult): boolean {\n\t\tconst text = [result.error, result.stderr, JSON.stringify(result.result_data ?? {})]\n\t\t\t.filter((part): part is string => typeof part === \"string\" && part.length > 0)\n\t\t\t.join(\"\\n\");\n\n\t\treturn /usage[_\\s-]?limit|subscription|quota|rate.?limit|too many requests|429|insufficient|out of credit|credit balance|billing|payment required|402|model[^\\n]*(not found|unavailable|not available|does not exist|invalid|unsupported)|no api key|no auth configured|authentication|unauthorized|forbidden|permission/i.test(\n\t\t\ttext,\n\t\t);\n\t}\n\n\t/** Remove failed attempt artifacts before rerunning the same task id. */\n\tprivate cleanupRetryArtifacts(task: SubagentPoolTask): void {\n\t\tconst cwd = task.cwd ?? this.cwd;\n\t\tconst taskDir = getDispatchTaskDir(cwd, task.task_id);\n\t\tconst sessionFile = task.sessionFile ?? this.getSessionFile(task.task_id, cwd);\n\t\ttry {\n\t\t\trmSync(sessionFile, { force: true });\n\t\t\trmSync(join(taskDir, \"result.json\"), { force: true });\n\t\t\trmSync(join(taskDir, \"output.json\"), { force: true });\n\t\t} catch {\n\t\t\t// Best-effort cleanup; retry can still proceed with existing artifacts.\n\t\t}\n\t}\n\n\t/**\n\t * Best-effort concrete failure reason for a non-zero-exit subagent. Prefers\n\t * the child's result.json summary (which carries the provider/model error\n\t * message on failure), then the tail of stderr, then the exit code.\n\t */\n\tprivate deriveFailureReason(result: SubagentResult): string {\n\t\tconst summary = (result.result_data as { summary?: string } | undefined)?.summary?.trim();\n\t\tif (summary) {\n\t\t\treturn summary;\n\t\t}\n\t\tconst stderrTail = result.stderr\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => line.trim())\n\t\t\t.filter((line) => line.length > 0)\n\t\t\t.slice(-5)\n\t\t\t.join(\"\\n\");\n\t\tif (stderrTail) {\n\t\t\treturn stderrTail;\n\t\t}\n\t\treturn `Exited with code ${result.exit_code}`;\n\t}\n\n\tprivate tryReadResultJson(task_id: string, cwd: string): Record<string, unknown> | undefined {\n\t\tconst path = join(getDispatchTaskDir(cwd, task_id), \"result.json\");\n\t\tif (!existsSync(path)) return undefined;\n\t\ttry {\n\t\t\tconst raw = readFileSync(path, \"utf-8\");\n\t\t\treturn JSON.parse(raw) as Record<string, unknown>;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate resolveWaiter(task_id: string, result: SubagentResult): void {\n\t\t// Persist terminal status for get_status() even after wait_for consumes the result\n\t\tif (result.status === \"stalled\") this.taskStatus.set(task_id, \"stalled\");\n\t\telse if (result.status === \"timeout\") this.taskStatus.set(task_id, \"timeout\");\n\t\telse if (result.ok) this.taskStatus.set(task_id, \"done\");\n\t\telse this.taskStatus.set(task_id, \"failed\");\n\n\t\tconst waiter = this.waiters.get(task_id);\n\t\tif (waiter) {\n\t\t\twaiter.resolve(result);\n\t\t\tthis.waiters.delete(task_id);\n\t\t\treturn;\n\t\t}\n\t\tthis.completed.set(task_id, result);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../../src/core/tools/subagent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAQ7D;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAwBrE;AASD;0EAC0E;AAC1E,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAoBvE;AAuBD,MAAM,WAAW,eAAe;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;CACZ;AAeD,gFAAgF;AAChF,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAsB,GAAG,cAAc,CA6IpF;AAmED;;;;GAIG;AACH,wBAAgB,8BAA8B,IAAI,cAAc,CAiD/D","sourcesContent":["/**\n * Task tool: delegate a focused task to a specialized subagent.\n *\n * Mirrors the Claude Code `Task` tool. The parent agent decides *when* to\n * delegate based on each agent's `description` (there is no deterministic gate)\n * and selects *which* agent via `subagent_type`. The chosen agent runs in a\n * fresh, isolated child process (SubagentPool) and only its final answer is\n * returned to the parent.\n *\n * It is an optional, opt-in tool (enabled via --enable-subagents or the\n * `enableSubagent` setting); see buildSessionOptions in main.ts.\n */\n\nimport { Text } from \"@kolisachint/hoocode-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { loadAgentRegistry } from \"../agent-registry.js\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { defineTool } from \"../extensions/types.js\";\nimport { getProviderExhaustion } from \"../provider-health.js\";\nimport type { SubagentPool, TaskResult } from \"../subagent-pool.js\";\nimport { getSubagentPool } from \"../subagent-pool-instance.js\";\nimport type { SubagentResultFile } from \"../subagent-result.js\";\nimport { taskStore } from \"../task-store.js\";\n\n/**\n * Condense a (possibly multi-line, bulleted) agent description into a single\n * useful one-liner for the agent picker list.\n *\n * Built-in agent descriptions open with a boilerplate header (\"Use this\n * subagent ONLY when:\") followed by \"when to use\" bullets and a \"DO NOT use\"\n * section. Taking the first line alone yields that identical header for every\n * agent, so instead surface the first meaningful bullets (or the first prose\n * line) from the positive \"when to use\" region.\n */\nexport function summarizeAgentDescription(description: string): string {\n\tconst lines = description\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0);\n\tif (lines.length === 0) return \"\";\n\n\t// Keep only the positive region: everything before a \"DO NOT use\" section.\n\tconst stop = lines.findIndex((line) => /^(do\\s*not|don'?t|avoid)\\b/i.test(line));\n\tconst region = stop === -1 ? lines : lines.slice(0, stop);\n\n\t// Drop a leading header line (e.g. \"Use this subagent ONLY when:\").\n\tconst body = region.length > 1 && region[0]!.endsWith(\":\") ? region.slice(1) : region;\n\n\tconst stripBullet = (line: string) => line.replace(/^[-*\\u2022]\\s+/, \"\").trim();\n\tconst bullets = body\n\t\t.filter((line) => /^[-*\\u2022]\\s+/.test(line))\n\t\t.map(stripBullet)\n\t\t.filter((line) => line.length > 0);\n\n\tconst summary = bullets.length > 0 ? bullets.slice(0, 3).join(\"; \") : (body[0] ?? lines[0] ?? \"\").replace(/:$/, \"\");\n\n\tconst MAX = 200;\n\treturn summary.length > MAX ? `${summary.slice(0, MAX - 1).trimEnd()}\\u2026` : summary;\n}\n\n/** Render the available agents as a \"- name: description\" list for prompts. */\nfunction describeAvailableAgents(cwd: string): string {\n\tconst agents = loadAgentRegistry({ cwd }).list();\n\tif (agents.length === 0) return \"(no agents available)\";\n\treturn agents.map((a) => `- ${a.name}: ${summarizeAgentDescription(a.description)}`).join(\"\\n\");\n}\n\n/** System prompt appendix for the main session when the Task tool is enabled.\n * Instructs the parent agent on when and how to delegate effectively. */\nexport function buildTaskMainPrompt(cwd: string = process.cwd()): string {\n\treturn `You have access to the **Task** tool. Use it to delegate self-contained tasks to specialized subagents that run in their own isolated context and return only their final answer.\n\nAvailable agents (choose one via \\`subagent_type\\`):\n${describeAvailableAgents(cwd)}\n\nWhen to delegate:\n1. The work is self-contained and you only need the final result, not intermediate steps.\n2. You want to investigate or edit something in parallel without losing your current context or reasoning chain.\n3. The task is a discrete unit (explore one module, run one test file, review one PR, fix one isolated bug).\n4. You need to run a long command or test suite and wait for its output without blocking your own reasoning.\n\nGuidelines:\n- Choose the agent whose description best matches the task.\n- Make every task specific and self-contained. The subagent cannot see this conversation; pass all necessary context (files, constraints, prior findings) in \\`prompt\\`.\n- Do NOT delegate tasks that require tight back-and-forth with your current reasoning, or edits to files you are actively reasoning about.\n- The subagent returns ONLY its final answer. Its intermediate reasoning, tool calls, and output are hidden from you.\n- Default to handling small, quick, or single-file work inline; delegate only self-contained units.\n- Some agents are configured to run in the background (non-blocking). For those, Task returns immediately with a task_id; use the **TaskOutput** tool with that task_id to check status and collect the final answer.\n- To continue a previous subagent (for example one that returned partial results), call Task again with \\`resume_task_id\\` set to its task_id; it resumes with its full prior transcript and \\`prompt\\` is your follow-up.`;\n}\n\nconst taskParams = Type.Object({\n\tdescription: Type.String({\n\t\tdescription: \"A short (3-5 word) description of the task, shown in the task panel.\",\n\t}),\n\tprompt: Type.String({\n\t\tdescription:\n\t\t\t\"The full, self-contained task for the subagent. It cannot see this conversation, so include all needed context, files, and constraints.\",\n\t}),\n\tsubagent_type: Type.String({\n\t\tdescription: \"The name of the specialized agent to delegate to. Must be one of the available agents.\",\n\t}),\n\tresume_task_id: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Optional. To continue a previous subagent run, pass its task_id (returned by an earlier Task or TaskOutput call). The subagent resumes with its full prior transcript and `prompt` is your follow-up instruction.\",\n\t\t}),\n\t),\n});\n\ntype TaskParams = Static<typeof taskParams>;\n\nexport interface TaskToolDetails {\n\tsubagent_type: string;\n\tok: boolean;\n\terror?: string;\n\ttaskId: number;\n\t/** Pool-level task id usable for resume/polling. */\n\tpoolTaskId?: string;\n\t/** True when dispatched as a non-blocking background task. */\n\tbackground?: boolean;\n}\n\nexport interface TaskOutputDetails {\n\ttask_id: string;\n\tstatus: string;\n\tok: boolean;\n}\n\n/**\n * A short, human-readable task name for the task panel: the first line limited\n * to ~8 words so it stays glanceable. A character cap guards a single long word.\n */\nfunction summarize(task: string): string {\n\tconst firstLine = (task.trim().split(\"\\n\")[0] ?? \"\").trim();\n\tif (!firstLine) return \"(task)\";\n\tconst words = firstLine.split(/\\s+/);\n\tlet name = words.length > 8 ? `${words.slice(0, 8).join(\" \")}…` : firstLine;\n\tif (name.length > 60) name = `${name.slice(0, 59)}…`;\n\treturn name;\n}\n\n/** Create the Task tool definition. Registered as a customTool when enabled. */\nexport function createTaskToolDefinition(cwd: string = process.cwd()): ToolDefinition {\n\tconst agentList = describeAvailableAgents(cwd);\n\treturn defineTool<typeof taskParams, TaskToolDetails>({\n\t\tname: \"Task\",\n\t\tlabel: \"Task\",\n\t\tdescription: [\n\t\t\t\"Delegate a focused task to a specialized subagent that runs in a fresh, isolated context (it cannot see this conversation).\",\n\t\t\t\"Select the agent via `subagent_type`; pass everything it needs via `prompt`. The subagent returns only its final answer.\",\n\t\t\t\"Available agents:\",\n\t\t\tagentList,\n\t\t\t\"WHEN TO USE: (1) self-contained work where you only need the final result;\",\n\t\t\t\"(2) parallel investigation/edits without losing your reasoning chain;\",\n\t\t\t\"(3) a discrete unit (explore one module, run one test file, review one PR, fix one isolated bug, write docs);\",\n\t\t\t\"(4) a long command or test suite you want to run without blocking your reasoning.\",\n\t\t\t\"Do NOT use for tasks needing tight back-and-forth with your current reasoning, or edits to files you are actively reasoning about.\",\n\t\t\t\"Prefer handling small, quick, or single-file tasks yourself; delegate only self-contained units of work.\",\n\t\t].join(\"\\n\"),\n\t\tpromptSnippet: \"delegate a self-contained task to a specialized subagent (choose via subagent_type)\",\n\t\tparameters: taskParams,\n\n\t\tasync execute(_toolCallId, params: TaskParams, _signal, _onUpdate, ctx) {\n\t\t\tconst pool = getSubagentPool(ctx.cwd);\n\n\t\t\t// Pre-flight: if the inherited provider recently exhausted its quota (the\n\t\t\t// parent's own turn failed with a usage/rate-limit error that did not\n\t\t\t// recover), skip the spawn. Subagents run on the same provider, so this\n\t\t\t// would only burn another failed attempt. The signal self-expires and is\n\t\t\t// cleared on the next successful response.\n\t\t\tconst provider = ctx.model?.provider;\n\t\t\tconst exhaustion = provider ? getProviderExhaustion(provider) : undefined;\n\t\t\tif (exhaustion) {\n\t\t\t\tconst skipped = taskStore.create(params.description?.trim() || summarize(params.prompt), {\n\t\t\t\t\tsubagentMode: params.subagent_type,\n\t\t\t\t});\n\t\t\t\ttaskStore.update(skipped.id, { status: \"failed\" });\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext:\n\t\t\t\t\t\t\t\t`Did not dispatch subagent \"${params.subagent_type}\": the \"${provider}\" provider appears ` +\n\t\t\t\t\t\t\t\t`exhausted or rate-limited (this session just failed with: ${exhaustion.message}). ` +\n\t\t\t\t\t\t\t\t`Subagents run on the same provider, so dispatching would fail too. Wait for the quota to ` +\n\t\t\t\t\t\t\t\t`reset or switch model/provider, then retry — or complete the work directly in this session.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { subagent_type: params.subagent_type, ok: false, taskId: skipped.id },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Resume path: continue a previously dispatched subagent with a follow-up\n\t\t\t// prompt, reusing its persisted session (full prior transcript).\n\t\t\tconst resumeId = params.resume_task_id?.trim();\n\t\t\tif (resumeId) {\n\t\t\t\tconst summary = params.description?.trim() || summarize(params.prompt);\n\t\t\t\tconst task = taskStore.create(summary, { subagentMode: params.subagent_type });\n\t\t\t\ttaskStore.update(task.id, { status: \"in_progress\" });\n\t\t\t\ttry {\n\t\t\t\t\tconst dispatchResult = await pool.resume(resumeId, params.prompt, {\n\t\t\t\t\t\tmodel: ctx.model?.id,\n\t\t\t\t\t\tprovider: ctx.model?.provider,\n\t\t\t\t\t});\n\t\t\t\t\t// The session lives under the original task id; keep it as the resume handle.\n\t\t\t\t\treturn finalizeForegroundResult(dispatchResult, params.subagent_type, task.id, resumeId);\n\t\t\t\t} catch (error) {\n\t\t\t\t\ttaskStore.update(task.id, { status: \"failed\" });\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// The model has already decided to delegate and which agent to use; honor\n\t\t\t// it. Validate the requested agent against the registry (no routing gate).\n\t\t\tconst registry = loadAgentRegistry({ cwd: ctx.cwd });\n\t\t\tconst def = registry.get(params.subagent_type);\n\t\t\tif (!def) {\n\t\t\t\tconst available = registry\n\t\t\t\t\t.list()\n\t\t\t\t\t.map((a) => a.name)\n\t\t\t\t\t.join(\", \");\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Unknown subagent_type: \"${params.subagent_type}\". Available agents: ${available || \"(none)\"}.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst summary = params.description?.trim() || summarize(params.prompt);\n\t\t\tconst task = taskStore.create(summary, { subagentMode: params.subagent_type });\n\n\t\t\t// Background agents: dispatch detached and return a handle immediately so\n\t\t\t// the parent keeps reasoning. The parent polls via the TaskOutput tool.\n\t\t\tif (def.background) {\n\t\t\t\ttaskStore.update(task.id, { status: \"in_progress\" });\n\t\t\t\tconst dispatched = pool.dispatchDetached(params.prompt, {\n\t\t\t\t\tforceAgent: params.subagent_type,\n\t\t\t\t\tcontext: \"\",\n\t\t\t\t\tmodel: ctx.model?.id,\n\t\t\t\t\tprovider: ctx.model?.provider,\n\t\t\t\t});\n\t\t\t\tconst poolTaskId = dispatched.task_id;\n\t\t\t\tif (poolTaskId) trackBackgroundTask(pool, poolTaskId, task.id);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `Background subagent (${params.subagent_type}) started with task_id \"${poolTaskId}\". It runs without blocking you. Call the TaskOutput tool with this task_id to check its status and collect the final answer.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tsubagent_type: params.subagent_type,\n\t\t\t\t\t\tok: true,\n\t\t\t\t\t\ttaskId: task.id,\n\t\t\t\t\t\tpoolTaskId,\n\t\t\t\t\t\tbackground: true,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\ttaskStore.update(task.id, { status: \"in_progress\" });\n\t\t\ttry {\n\t\t\t\tconst dispatchResult = await pool.dispatch(params.prompt, {\n\t\t\t\t\tforceAgent: params.subagent_type,\n\t\t\t\t\tcontext: \"\",\n\t\t\t\t\tmodel: ctx.model?.id,\n\t\t\t\t\tprovider: ctx.model?.provider,\n\t\t\t\t});\n\t\t\t\treturn finalizeForegroundResult(dispatchResult, params.subagent_type, task.id, dispatchResult.task_id);\n\t\t\t} catch (error) {\n\t\t\t\ttaskStore.update(task.id, { status: \"failed\" });\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\n\t\trenderCall(args, theme) {\n\t\t\tconst type = args.subagent_type ?? \"agent\";\n\t\t\tconst preview = summarize(args.description ?? args.prompt ?? \"\");\n\t\t\tconst text =\n\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(\"Task \")) +\n\t\t\t\ttheme.fg(\"accent\", `[${type}]`) +\n\t\t\t\ttheme.fg(\"dim\", ` ${preview}`);\n\t\t\treturn new Text(text, 0, 0);\n\t\t},\n\t});\n}\n\n/** Extract the final answer from a finished dispatch, updating the task panel. */\nfunction finalizeForegroundResult(\n\tdispatchResult: TaskResult,\n\tsubagentType: string,\n\ttaskStoreId: number,\n\tresumeHandle: string | undefined,\n): { content: Array<{ type: \"text\"; text: string }>; details: TaskToolDetails } {\n\tconst result = dispatchResult.result;\n\tconst resultData = result?.result_data as SubagentResultFile | undefined;\n\tconst usage = resultData?.usage;\n\n\tif (!result || !result.ok) {\n\t\t// Signal failure by throwing: the agent loop derives a tool's error state\n\t\t// from a thrown error, not from a returned flag.\n\t\ttaskStore.update(taskStoreId, { status: \"failed\", usage });\n\t\tconst reason = result?.error ?? (result?.status ? `subagent ${result.status}` : \"unknown error\");\n\t\tthrow new Error(`Subagent (${subagentType}) failed: ${reason}`);\n\t}\n\n\t// Leave the task in the store with its final status; it stays visible in the\n\t// task panel until the next user message arrives.\n\ttaskStore.update(taskStoreId, { status: \"done\", usage });\n\tlet answer = resultData?.summary || \"(subagent returned no output)\";\n\t// Partial results are resumable; surface the handle so the parent can continue.\n\tif (result.status === \"partial\" && resumeHandle) {\n\t\tanswer += `\\n\\n[Partial result. To continue this subagent, call Task again with resume_task_id=\"${resumeHandle}\".]`;\n\t}\n\treturn {\n\t\tcontent: [{ type: \"text\", text: answer }],\n\t\tdetails: { subagent_type: subagentType, ok: true, taskId: taskStoreId, poolTaskId: resumeHandle },\n\t};\n}\n\n/**\n * Keep the task panel in sync for a detached background subagent: when the pool\n * reports the task finished, update the stored task's status and detach.\n */\nfunction trackBackgroundTask(pool: SubagentPool, poolTaskId: string, taskStoreId: number): void {\n\tfunction finish(status: \"done\" | \"failed\"): void {\n\t\ttaskStore.update(taskStoreId, { status });\n\t\tpool.off(\"task_done\", onDone);\n\t\tpool.off(\"task_failed\", onFail);\n\t\tpool.off(\"task_stalled\", onFail);\n\t\tpool.off(\"task_timeout\", onFail);\n\t}\n\tfunction onDone(data: { task_id?: string }): void {\n\t\tif (data?.task_id === poolTaskId) finish(\"done\");\n\t}\n\tfunction onFail(data: { task_id?: string }): void {\n\t\tif (data?.task_id === poolTaskId) finish(\"failed\");\n\t}\n\tpool.on(\"task_done\", onDone);\n\tpool.on(\"task_failed\", onFail);\n\tpool.on(\"task_stalled\", onFail);\n\tpool.on(\"task_timeout\", onFail);\n}\n\nconst taskOutputParams = Type.Object({\n\ttask_id: Type.String({\n\t\tdescription: \"The task_id of a background (or previously dispatched) subagent, as returned by the Task tool.\",\n\t}),\n});\n\ntype TaskOutputParams = Static<typeof taskOutputParams>;\n\n/**\n * TaskOutput tool: poll a background subagent and collect its final answer.\n * Returns the current status while running, or the subagent's final answer once\n * complete. Registered alongside the Task tool when subagents are enabled.\n */\nexport function createTaskOutputToolDefinition(): ToolDefinition {\n\treturn defineTool<typeof taskOutputParams, TaskOutputDetails>({\n\t\tname: \"TaskOutput\",\n\t\tlabel: \"TaskOutput\",\n\t\tdescription: [\n\t\t\t\"Check the status of a background subagent and collect its final answer once it finishes.\",\n\t\t\t\"Pass the task_id returned by a background Task call. While the subagent runs this reports its status; once complete it returns only the subagent's final answer.\",\n\t\t].join(\"\\n\"),\n\t\tpromptSnippet: \"check status / collect the result of a background subagent\",\n\t\tparameters: taskOutputParams,\n\n\t\tasync execute(_toolCallId, params: TaskOutputParams, _signal, _onUpdate, ctx) {\n\t\t\tconst pool = getSubagentPool(ctx.cwd);\n\t\t\tconst status = pool.get_status(params.task_id);\n\t\t\tif (status === \"running\" || status === \"queued\") {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `Subagent task \"${params.task_id}\" is ${status}. Call TaskOutput again later to collect its result.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { task_id: params.task_id, status, ok: true },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst result = pool.collect(params.task_id);\n\t\t\tif (!result) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No result available for task \"${params.task_id}\" (status: ${status}). It may not exist or its result was already collected.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!result.ok) {\n\t\t\t\tconst reason = result.error ?? (result.status ? `subagent ${result.status}` : status);\n\t\t\t\tthrow new Error(`Background subagent \"${params.task_id}\" failed: ${reason}`);\n\t\t\t}\n\t\t\tconst resultData = result.result_data as SubagentResultFile | undefined;\n\t\t\tconst answer = resultData?.summary || \"(subagent returned no output)\";\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: answer }],\n\t\t\t\tdetails: { task_id: params.task_id, status: result.status ?? \"complete\", ok: true },\n\t\t\t};\n\t\t},\n\n\t\trenderCall(args, theme) {\n\t\t\tconst text = theme.fg(\"toolTitle\", theme.bold(\"TaskOutput \")) + theme.fg(\"dim\", String(args.task_id ?? \"\"));\n\t\t\treturn new Text(text, 0, 0);\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../../src/core/tools/subagent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAQ7D;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAwBrE;AASD;0EAC0E;AAC1E,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAoBvE;AAuBD,MAAM,WAAW,eAAe;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;CACZ;AAeD,gFAAgF;AAChF,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAsB,GAAG,cAAc,CA2HpF;AAoDD;;;;GAIG;AACH,wBAAgB,8BAA8B,IAAI,cAAc,CAiD/D","sourcesContent":["/**\n * Task tool: delegate a focused task to a specialized subagent.\n *\n * Mirrors the Claude Code `Task` tool. The parent agent decides *when* to\n * delegate based on each agent's `description` (there is no deterministic gate)\n * and selects *which* agent via `subagent_type`. The chosen agent runs in a\n * fresh, isolated child process (SubagentPool) and only its final answer is\n * returned to the parent.\n *\n * It is an optional, opt-in tool (enabled via --enable-subagents or the\n * `enableSubagent` setting); see buildSessionOptions in main.ts.\n */\n\nimport { Text } from \"@kolisachint/hoocode-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { loadAgentRegistry } from \"../agent-registry.js\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { defineTool } from \"../extensions/types.js\";\nimport { getProviderExhaustion } from \"../provider-health.js\";\nimport type { TaskResult } from \"../subagent-pool.js\";\nimport { getSubagentPool } from \"../subagent-pool-instance.js\";\nimport type { SubagentResultFile } from \"../subagent-result.js\";\nimport { taskStore } from \"../task-store.js\";\n\n/**\n * Condense a (possibly multi-line, bulleted) agent description into a single\n * useful one-liner for the agent picker list.\n *\n * Built-in agent descriptions open with a boilerplate header (\"Use this\n * subagent ONLY when:\") followed by \"when to use\" bullets and a \"DO NOT use\"\n * section. Taking the first line alone yields that identical header for every\n * agent, so instead surface the first meaningful bullets (or the first prose\n * line) from the positive \"when to use\" region.\n */\nexport function summarizeAgentDescription(description: string): string {\n\tconst lines = description\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0);\n\tif (lines.length === 0) return \"\";\n\n\t// Keep only the positive region: everything before a \"DO NOT use\" section.\n\tconst stop = lines.findIndex((line) => /^(do\\s*not|don'?t|avoid)\\b/i.test(line));\n\tconst region = stop === -1 ? lines : lines.slice(0, stop);\n\n\t// Drop a leading header line (e.g. \"Use this subagent ONLY when:\").\n\tconst body = region.length > 1 && region[0]!.endsWith(\":\") ? region.slice(1) : region;\n\n\tconst stripBullet = (line: string) => line.replace(/^[-*\\u2022]\\s+/, \"\").trim();\n\tconst bullets = body\n\t\t.filter((line) => /^[-*\\u2022]\\s+/.test(line))\n\t\t.map(stripBullet)\n\t\t.filter((line) => line.length > 0);\n\n\tconst summary = bullets.length > 0 ? bullets.slice(0, 3).join(\"; \") : (body[0] ?? lines[0] ?? \"\").replace(/:$/, \"\");\n\n\tconst MAX = 200;\n\treturn summary.length > MAX ? `${summary.slice(0, MAX - 1).trimEnd()}\\u2026` : summary;\n}\n\n/** Render the available agents as a \"- name: description\" list for prompts. */\nfunction describeAvailableAgents(cwd: string): string {\n\tconst agents = loadAgentRegistry({ cwd }).list();\n\tif (agents.length === 0) return \"(no agents available)\";\n\treturn agents.map((a) => `- ${a.name}: ${summarizeAgentDescription(a.description)}`).join(\"\\n\");\n}\n\n/** System prompt appendix for the main session when the Task tool is enabled.\n * Instructs the parent agent on when and how to delegate effectively. */\nexport function buildTaskMainPrompt(cwd: string = process.cwd()): string {\n\treturn `You have access to the **Task** tool. Use it to delegate self-contained tasks to specialized subagents that run in their own isolated context and return only their final answer.\n\nAvailable agents (choose one via \\`subagent_type\\`):\n${describeAvailableAgents(cwd)}\n\nWhen to delegate:\n1. The work is self-contained and you only need the final result, not intermediate steps.\n2. You want to investigate or edit something in parallel without losing your current context or reasoning chain.\n3. The task is a discrete unit (explore one module, run one test file, review one PR, fix one isolated bug).\n4. You need to run a long command or test suite and wait for its output without blocking your own reasoning.\n\nGuidelines:\n- Choose the agent whose description best matches the task.\n- Make every task specific and self-contained. The subagent cannot see this conversation; pass all necessary context (files, constraints, prior findings) in \\`prompt\\`.\n- Do NOT delegate tasks that require tight back-and-forth with your current reasoning, or edits to files you are actively reasoning about.\n- The subagent returns ONLY its final answer. Its intermediate reasoning, tool calls, and output are hidden from you.\n- Default to handling small, quick, or single-file work inline; delegate only self-contained units.\n- Some agents are configured to run in the background (non-blocking). For those, the Task call does not block your turn: you keep reasoning and producing output while the subagent runs, and its final answer is delivered to you automatically as a follow-up message once it finishes. You do not need to poll for it.\n- To continue a previous subagent (for example one that returned partial results), call Task again with \\`resume_task_id\\` set to its task_id; it resumes with its full prior transcript and \\`prompt\\` is your follow-up.`;\n}\n\nconst taskParams = Type.Object({\n\tdescription: Type.String({\n\t\tdescription: \"A short (3-5 word) description of the task, shown in the task panel.\",\n\t}),\n\tprompt: Type.String({\n\t\tdescription:\n\t\t\t\"The full, self-contained task for the subagent. It cannot see this conversation, so include all needed context, files, and constraints.\",\n\t}),\n\tsubagent_type: Type.String({\n\t\tdescription: \"The name of the specialized agent to delegate to. Must be one of the available agents.\",\n\t}),\n\tresume_task_id: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Optional. To continue a previous subagent run, pass its task_id (returned by an earlier Task or TaskOutput call). The subagent resumes with its full prior transcript and `prompt` is your follow-up instruction.\",\n\t\t}),\n\t),\n});\n\ntype TaskParams = Static<typeof taskParams>;\n\nexport interface TaskToolDetails {\n\tsubagent_type: string;\n\tok: boolean;\n\terror?: string;\n\ttaskId: number;\n\t/** Pool-level task id usable for resume/polling. */\n\tpoolTaskId?: string;\n\t/** True when dispatched as a non-blocking background task. */\n\tbackground?: boolean;\n}\n\nexport interface TaskOutputDetails {\n\ttask_id: string;\n\tstatus: string;\n\tok: boolean;\n}\n\n/**\n * A short, human-readable task name for the task panel: the first line limited\n * to ~8 words so it stays glanceable. A character cap guards a single long word.\n */\nfunction summarize(task: string): string {\n\tconst firstLine = (task.trim().split(\"\\n\")[0] ?? \"\").trim();\n\tif (!firstLine) return \"(task)\";\n\tconst words = firstLine.split(/\\s+/);\n\tlet name = words.length > 8 ? `${words.slice(0, 8).join(\" \")}…` : firstLine;\n\tif (name.length > 60) name = `${name.slice(0, 59)}…`;\n\treturn name;\n}\n\n/** Create the Task tool definition. Registered as a customTool when enabled. */\nexport function createTaskToolDefinition(cwd: string = process.cwd()): ToolDefinition {\n\tconst agentList = describeAvailableAgents(cwd);\n\t// Agents whose definitions opt into background execution. The agent loop reads\n\t// the tool's `background` flag per call and, for these, runs the dispatch\n\t// detached: the parent keeps reasoning and the subagent's answer is injected as\n\t// a follow-up message when it finishes (no polling needed).\n\tconst backgroundAgents = collectBackgroundAgentNames(cwd);\n\treturn defineTool<typeof taskParams, TaskToolDetails>({\n\t\tname: \"Task\",\n\t\tlabel: \"Task\",\n\t\tbackground: (toolCall) => backgroundAgents.has(String(toolCall.arguments?.subagent_type ?? \"\")),\n\t\tdescription: [\n\t\t\t\"Delegate a focused task to a specialized subagent that runs in a fresh, isolated context (it cannot see this conversation).\",\n\t\t\t\"Select the agent via `subagent_type`; pass everything it needs via `prompt`. The subagent returns only its final answer.\",\n\t\t\t\"Available agents:\",\n\t\t\tagentList,\n\t\t\t\"WHEN TO USE: (1) self-contained work where you only need the final result;\",\n\t\t\t\"(2) parallel investigation/edits without losing your reasoning chain;\",\n\t\t\t\"(3) a discrete unit (explore one module, run one test file, review one PR, fix one isolated bug, write docs);\",\n\t\t\t\"(4) a long command or test suite you want to run without blocking your reasoning.\",\n\t\t\t\"Do NOT use for tasks needing tight back-and-forth with your current reasoning, or edits to files you are actively reasoning about.\",\n\t\t\t\"Prefer handling small, quick, or single-file tasks yourself; delegate only self-contained units of work.\",\n\t\t].join(\"\\n\"),\n\t\tpromptSnippet: \"delegate a self-contained task to a specialized subagent (choose via subagent_type)\",\n\t\tparameters: taskParams,\n\n\t\tasync execute(_toolCallId, params: TaskParams, _signal, _onUpdate, ctx) {\n\t\t\tconst pool = getSubagentPool(ctx.cwd);\n\n\t\t\t// Pre-flight: if the inherited provider recently exhausted its quota (the\n\t\t\t// parent's own turn failed with a usage/rate-limit error that did not\n\t\t\t// recover), skip the spawn. Subagents run on the same provider, so this\n\t\t\t// would only burn another failed attempt. The signal self-expires and is\n\t\t\t// cleared on the next successful response.\n\t\t\tconst provider = ctx.model?.provider;\n\t\t\tconst exhaustion = provider ? getProviderExhaustion(provider) : undefined;\n\t\t\tif (exhaustion) {\n\t\t\t\tconst skipped = taskStore.create(params.description?.trim() || summarize(params.prompt), {\n\t\t\t\t\tsubagentMode: params.subagent_type,\n\t\t\t\t});\n\t\t\t\ttaskStore.update(skipped.id, { status: \"failed\" });\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext:\n\t\t\t\t\t\t\t\t`Did not dispatch subagent \"${params.subagent_type}\": the \"${provider}\" provider appears ` +\n\t\t\t\t\t\t\t\t`exhausted or rate-limited (this session just failed with: ${exhaustion.message}). ` +\n\t\t\t\t\t\t\t\t`Subagents run on the same provider, so dispatching would fail too. Wait for the quota to ` +\n\t\t\t\t\t\t\t\t`reset or switch model/provider, then retry — or complete the work directly in this session.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { subagent_type: params.subagent_type, ok: false, taskId: skipped.id },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Resume path: continue a previously dispatched subagent with a follow-up\n\t\t\t// prompt, reusing its persisted session (full prior transcript).\n\t\t\tconst resumeId = params.resume_task_id?.trim();\n\t\t\tif (resumeId) {\n\t\t\t\tconst summary = params.description?.trim() || summarize(params.prompt);\n\t\t\t\tconst task = taskStore.create(summary, { subagentMode: params.subagent_type });\n\t\t\t\ttaskStore.update(task.id, { status: \"in_progress\" });\n\t\t\t\ttry {\n\t\t\t\t\tconst dispatchResult = await pool.resume(resumeId, params.prompt, {\n\t\t\t\t\t\tmodel: ctx.model?.id,\n\t\t\t\t\t\tprovider: ctx.model?.provider,\n\t\t\t\t\t});\n\t\t\t\t\t// The session lives under the original task id; keep it as the resume handle.\n\t\t\t\t\treturn finalizeDispatchResult(dispatchResult, params.subagent_type, task.id, resumeId);\n\t\t\t\t} catch (error) {\n\t\t\t\t\ttaskStore.update(task.id, { status: \"failed\" });\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// The model has already decided to delegate and which agent to use; honor\n\t\t\t// it. Validate the requested agent against the registry (no routing gate).\n\t\t\tconst registry = loadAgentRegistry({ cwd: ctx.cwd });\n\t\t\tconst def = registry.get(params.subagent_type);\n\t\t\tif (!def) {\n\t\t\t\tconst available = registry\n\t\t\t\t\t.list()\n\t\t\t\t\t.map((a) => a.name)\n\t\t\t\t\t.join(\", \");\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Unknown subagent_type: \"${params.subagent_type}\". Available agents: ${available || \"(none)\"}.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst summary = params.description?.trim() || summarize(params.prompt);\n\t\t\tconst task = taskStore.create(summary, { subagentMode: params.subagent_type });\n\n\t\t\t// Always dispatch and await the subagent's full result here. Background\n\t\t\t// agents (def.background) are made non-blocking by the agent loop via this\n\t\t\t// tool's `background` flag: the loop runs this execute() detached, answers\n\t\t\t// the call with a placeholder, and injects the answer below as a follow-up\n\t\t\t// message when it resolves. Foreground agents block the turn as usual.\n\t\t\ttaskStore.update(task.id, { status: \"in_progress\" });\n\t\t\ttry {\n\t\t\t\tconst dispatchResult = await pool.dispatch(params.prompt, {\n\t\t\t\t\tforceAgent: params.subagent_type,\n\t\t\t\t\tcontext: \"\",\n\t\t\t\t\tmodel: ctx.model?.id,\n\t\t\t\t\tprovider: ctx.model?.provider,\n\t\t\t\t});\n\t\t\t\treturn finalizeDispatchResult(dispatchResult, params.subagent_type, task.id, dispatchResult.task_id);\n\t\t\t} catch (error) {\n\t\t\t\ttaskStore.update(task.id, { status: \"failed\" });\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\n\t\trenderCall(args, theme) {\n\t\t\tconst type = args.subagent_type ?? \"agent\";\n\t\t\tconst preview = summarize(args.description ?? args.prompt ?? \"\");\n\t\t\tconst text =\n\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(\"Task \")) +\n\t\t\t\ttheme.fg(\"accent\", `[${type}]`) +\n\t\t\t\ttheme.fg(\"dim\", ` ${preview}`);\n\t\t\treturn new Text(text, 0, 0);\n\t\t},\n\t});\n}\n\n/** Names of agents configured to run in the background (non-blocking). */\nfunction collectBackgroundAgentNames(cwd: string): Set<string> {\n\tconst names = new Set<string>();\n\tfor (const agent of loadAgentRegistry({ cwd }).list()) {\n\t\tif (agent.background) names.add(agent.name);\n\t}\n\treturn names;\n}\n\n/** Extract the final answer from a finished dispatch, updating the task panel. */\nfunction finalizeDispatchResult(\n\tdispatchResult: TaskResult,\n\tsubagentType: string,\n\ttaskStoreId: number,\n\tresumeHandle: string | undefined,\n): { content: Array<{ type: \"text\"; text: string }>; details: TaskToolDetails } {\n\tconst result = dispatchResult.result;\n\tconst resultData = result?.result_data as SubagentResultFile | undefined;\n\tconst usage = resultData?.usage;\n\n\tif (!result || !result.ok) {\n\t\t// Signal failure by throwing: the agent loop derives a tool's error state\n\t\t// from a thrown error, not from a returned flag.\n\t\ttaskStore.update(taskStoreId, { status: \"failed\", usage });\n\t\tconst reason = result?.error ?? (result?.status ? `subagent ${result.status}` : \"unknown error\");\n\t\tthrow new Error(`Subagent (${subagentType}) failed: ${reason}`);\n\t}\n\n\t// Leave the task in the store with its final status; it stays visible in the\n\t// task panel until the next user message arrives.\n\ttaskStore.update(taskStoreId, { status: \"done\", usage });\n\tlet answer = resultData?.summary || \"(subagent returned no output)\";\n\t// Partial results are resumable; surface the handle so the parent can continue.\n\tif (result.status === \"partial\" && resumeHandle) {\n\t\tanswer += `\\n\\n[Partial result. To continue this subagent, call Task again with resume_task_id=\"${resumeHandle}\".]`;\n\t}\n\treturn {\n\t\tcontent: [{ type: \"text\", text: answer }],\n\t\tdetails: { subagent_type: subagentType, ok: true, taskId: taskStoreId, poolTaskId: resumeHandle },\n\t};\n}\n\nconst taskOutputParams = Type.Object({\n\ttask_id: Type.String({\n\t\tdescription: \"The task_id of a background (or previously dispatched) subagent, as returned by the Task tool.\",\n\t}),\n});\n\ntype TaskOutputParams = Static<typeof taskOutputParams>;\n\n/**\n * TaskOutput tool: poll a background subagent and collect its final answer.\n * Returns the current status while running, or the subagent's final answer once\n * complete. Registered alongside the Task tool when subagents are enabled.\n */\nexport function createTaskOutputToolDefinition(): ToolDefinition {\n\treturn defineTool<typeof taskOutputParams, TaskOutputDetails>({\n\t\tname: \"TaskOutput\",\n\t\tlabel: \"TaskOutput\",\n\t\tdescription: [\n\t\t\t\"Check the status of a background subagent and collect its final answer once it finishes.\",\n\t\t\t\"Pass the task_id returned by a background Task call. While the subagent runs this reports its status; once complete it returns only the subagent's final answer.\",\n\t\t].join(\"\\n\"),\n\t\tpromptSnippet: \"check status / collect the result of a background subagent\",\n\t\tparameters: taskOutputParams,\n\n\t\tasync execute(_toolCallId, params: TaskOutputParams, _signal, _onUpdate, ctx) {\n\t\t\tconst pool = getSubagentPool(ctx.cwd);\n\t\t\tconst status = pool.get_status(params.task_id);\n\t\t\tif (status === \"running\" || status === \"queued\") {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `Subagent task \"${params.task_id}\" is ${status}. Call TaskOutput again later to collect its result.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { task_id: params.task_id, status, ok: true },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst result = pool.collect(params.task_id);\n\t\t\tif (!result) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No result available for task \"${params.task_id}\" (status: ${status}). It may not exist or its result was already collected.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!result.ok) {\n\t\t\t\tconst reason = result.error ?? (result.status ? `subagent ${result.status}` : status);\n\t\t\t\tthrow new Error(`Background subagent \"${params.task_id}\" failed: ${reason}`);\n\t\t\t}\n\t\t\tconst resultData = result.result_data as SubagentResultFile | undefined;\n\t\t\tconst answer = resultData?.summary || \"(subagent returned no output)\";\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: answer }],\n\t\t\t\tdetails: { task_id: params.task_id, status: result.status ?? \"complete\", ok: true },\n\t\t\t};\n\t\t},\n\n\t\trenderCall(args, theme) {\n\t\t\tconst text = theme.fg(\"toolTitle\", theme.bold(\"TaskOutput \")) + theme.fg(\"dim\", String(args.task_id ?? \"\"));\n\t\t\treturn new Text(text, 0, 0);\n\t\t},\n\t});\n}\n"]}
@@ -75,7 +75,7 @@ Guidelines:
75
75
  - Do NOT delegate tasks that require tight back-and-forth with your current reasoning, or edits to files you are actively reasoning about.
76
76
  - The subagent returns ONLY its final answer. Its intermediate reasoning, tool calls, and output are hidden from you.
77
77
  - Default to handling small, quick, or single-file work inline; delegate only self-contained units.
78
- - Some agents are configured to run in the background (non-blocking). For those, Task returns immediately with a task_id; use the **TaskOutput** tool with that task_id to check status and collect the final answer.
78
+ - Some agents are configured to run in the background (non-blocking). For those, the Task call does not block your turn: you keep reasoning and producing output while the subagent runs, and its final answer is delivered to you automatically as a follow-up message once it finishes. You do not need to poll for it.
79
79
  - To continue a previous subagent (for example one that returned partial results), call Task again with \`resume_task_id\` set to its task_id; it resumes with its full prior transcript and \`prompt\` is your follow-up.`;
80
80
  }
81
81
  const taskParams = Type.Object({
@@ -109,9 +109,15 @@ function summarize(task) {
109
109
  /** Create the Task tool definition. Registered as a customTool when enabled. */
110
110
  export function createTaskToolDefinition(cwd = process.cwd()) {
111
111
  const agentList = describeAvailableAgents(cwd);
112
+ // Agents whose definitions opt into background execution. The agent loop reads
113
+ // the tool's `background` flag per call and, for these, runs the dispatch
114
+ // detached: the parent keeps reasoning and the subagent's answer is injected as
115
+ // a follow-up message when it finishes (no polling needed).
116
+ const backgroundAgents = collectBackgroundAgentNames(cwd);
112
117
  return defineTool({
113
118
  name: "Task",
114
119
  label: "Task",
120
+ background: (toolCall) => backgroundAgents.has(String(toolCall.arguments?.subagent_type ?? "")),
115
121
  description: [
116
122
  "Delegate a focused task to a specialized subagent that runs in a fresh, isolated context (it cannot see this conversation).",
117
123
  "Select the agent via `subagent_type`; pass everything it needs via `prompt`. The subagent returns only its final answer.",
@@ -166,7 +172,7 @@ export function createTaskToolDefinition(cwd = process.cwd()) {
166
172
  provider: ctx.model?.provider,
167
173
  });
168
174
  // The session lives under the original task id; keep it as the resume handle.
169
- return finalizeForegroundResult(dispatchResult, params.subagent_type, task.id, resumeId);
175
+ return finalizeDispatchResult(dispatchResult, params.subagent_type, task.id, resumeId);
170
176
  }
171
177
  catch (error) {
172
178
  taskStore.update(task.id, { status: "failed" });
@@ -186,35 +192,11 @@ export function createTaskToolDefinition(cwd = process.cwd()) {
186
192
  }
187
193
  const summary = params.description?.trim() || summarize(params.prompt);
188
194
  const task = taskStore.create(summary, { subagentMode: params.subagent_type });
189
- // Background agents: dispatch detached and return a handle immediately so
190
- // the parent keeps reasoning. The parent polls via the TaskOutput tool.
191
- if (def.background) {
192
- taskStore.update(task.id, { status: "in_progress" });
193
- const dispatched = pool.dispatchDetached(params.prompt, {
194
- forceAgent: params.subagent_type,
195
- context: "",
196
- model: ctx.model?.id,
197
- provider: ctx.model?.provider,
198
- });
199
- const poolTaskId = dispatched.task_id;
200
- if (poolTaskId)
201
- trackBackgroundTask(pool, poolTaskId, task.id);
202
- return {
203
- content: [
204
- {
205
- type: "text",
206
- text: `Background subagent (${params.subagent_type}) started with task_id "${poolTaskId}". It runs without blocking you. Call the TaskOutput tool with this task_id to check its status and collect the final answer.`,
207
- },
208
- ],
209
- details: {
210
- subagent_type: params.subagent_type,
211
- ok: true,
212
- taskId: task.id,
213
- poolTaskId,
214
- background: true,
215
- },
216
- };
217
- }
195
+ // Always dispatch and await the subagent's full result here. Background
196
+ // agents (def.background) are made non-blocking by the agent loop via this
197
+ // tool's `background` flag: the loop runs this execute() detached, answers
198
+ // the call with a placeholder, and injects the answer below as a follow-up
199
+ // message when it resolves. Foreground agents block the turn as usual.
218
200
  taskStore.update(task.id, { status: "in_progress" });
219
201
  try {
220
202
  const dispatchResult = await pool.dispatch(params.prompt, {
@@ -223,7 +205,7 @@ export function createTaskToolDefinition(cwd = process.cwd()) {
223
205
  model: ctx.model?.id,
224
206
  provider: ctx.model?.provider,
225
207
  });
226
- return finalizeForegroundResult(dispatchResult, params.subagent_type, task.id, dispatchResult.task_id);
208
+ return finalizeDispatchResult(dispatchResult, params.subagent_type, task.id, dispatchResult.task_id);
227
209
  }
228
210
  catch (error) {
229
211
  taskStore.update(task.id, { status: "failed" });
@@ -240,8 +222,17 @@ export function createTaskToolDefinition(cwd = process.cwd()) {
240
222
  },
241
223
  });
242
224
  }
225
+ /** Names of agents configured to run in the background (non-blocking). */
226
+ function collectBackgroundAgentNames(cwd) {
227
+ const names = new Set();
228
+ for (const agent of loadAgentRegistry({ cwd }).list()) {
229
+ if (agent.background)
230
+ names.add(agent.name);
231
+ }
232
+ return names;
233
+ }
243
234
  /** Extract the final answer from a finished dispatch, updating the task panel. */
244
- function finalizeForegroundResult(dispatchResult, subagentType, taskStoreId, resumeHandle) {
235
+ function finalizeDispatchResult(dispatchResult, subagentType, taskStoreId, resumeHandle) {
245
236
  const result = dispatchResult.result;
246
237
  const resultData = result?.result_data;
247
238
  const usage = resultData?.usage;
@@ -265,31 +256,6 @@ function finalizeForegroundResult(dispatchResult, subagentType, taskStoreId, res
265
256
  details: { subagent_type: subagentType, ok: true, taskId: taskStoreId, poolTaskId: resumeHandle },
266
257
  };
267
258
  }
268
- /**
269
- * Keep the task panel in sync for a detached background subagent: when the pool
270
- * reports the task finished, update the stored task's status and detach.
271
- */
272
- function trackBackgroundTask(pool, poolTaskId, taskStoreId) {
273
- function finish(status) {
274
- taskStore.update(taskStoreId, { status });
275
- pool.off("task_done", onDone);
276
- pool.off("task_failed", onFail);
277
- pool.off("task_stalled", onFail);
278
- pool.off("task_timeout", onFail);
279
- }
280
- function onDone(data) {
281
- if (data?.task_id === poolTaskId)
282
- finish("done");
283
- }
284
- function onFail(data) {
285
- if (data?.task_id === poolTaskId)
286
- finish("failed");
287
- }
288
- pool.on("task_done", onDone);
289
- pool.on("task_failed", onFail);
290
- pool.on("task_stalled", onFail);
291
- pool.on("task_timeout", onFail);
292
- }
293
259
  const taskOutputParams = Type.Object({
294
260
  task_id: Type.String({
295
261
  description: "The task_id of a background (or previously dispatched) subagent, as returned by the Task tool.",