@burtson-labs/host-kit 0.3.1

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.
Files changed (79) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +55 -0
  3. package/dist/backgroundTasks.d.ts +113 -0
  4. package/dist/backgroundTasks.d.ts.map +1 -0
  5. package/dist/backgroundTasks.js +137 -0
  6. package/dist/backgroundTasks.js.map +1 -0
  7. package/dist/checkpoints.d.ts +99 -0
  8. package/dist/checkpoints.d.ts.map +1 -0
  9. package/dist/checkpoints.js +227 -0
  10. package/dist/checkpoints.js.map +1 -0
  11. package/dist/hooks.d.ts +51 -0
  12. package/dist/hooks.d.ts.map +1 -0
  13. package/dist/hooks.js +152 -0
  14. package/dist/hooks.js.map +1 -0
  15. package/dist/index.d.ts +19 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +95 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/insights.d.ts +398 -0
  20. package/dist/insights.d.ts.map +1 -0
  21. package/dist/insights.js +1933 -0
  22. package/dist/insights.js.map +1 -0
  23. package/dist/mcp.d.ts +60 -0
  24. package/dist/mcp.d.ts.map +1 -0
  25. package/dist/mcp.js +281 -0
  26. package/dist/mcp.js.map +1 -0
  27. package/dist/mcpConnectors.d.ts +108 -0
  28. package/dist/mcpConnectors.d.ts.map +1 -0
  29. package/dist/mcpConnectors.js +217 -0
  30. package/dist/mcpConnectors.js.map +1 -0
  31. package/dist/mcpToolCache.d.ts +43 -0
  32. package/dist/mcpToolCache.d.ts.map +1 -0
  33. package/dist/mcpToolCache.js +150 -0
  34. package/dist/mcpToolCache.js.map +1 -0
  35. package/dist/mcpTrust.d.ts +22 -0
  36. package/dist/mcpTrust.d.ts.map +1 -0
  37. package/dist/mcpTrust.js +104 -0
  38. package/dist/mcpTrust.js.map +1 -0
  39. package/dist/memory.d.ts +38 -0
  40. package/dist/memory.d.ts.map +1 -0
  41. package/dist/memory.js +151 -0
  42. package/dist/memory.js.map +1 -0
  43. package/dist/memoryIndex.d.ts +38 -0
  44. package/dist/memoryIndex.d.ts.map +1 -0
  45. package/dist/memoryIndex.js +142 -0
  46. package/dist/memoryIndex.js.map +1 -0
  47. package/dist/mentions.d.ts +33 -0
  48. package/dist/mentions.d.ts.map +1 -0
  49. package/dist/mentions.js +126 -0
  50. package/dist/mentions.js.map +1 -0
  51. package/dist/ollamaModels.d.ts +36 -0
  52. package/dist/ollamaModels.d.ts.map +1 -0
  53. package/dist/ollamaModels.js +83 -0
  54. package/dist/ollamaModels.js.map +1 -0
  55. package/dist/permissions.d.ts +72 -0
  56. package/dist/permissions.d.ts.map +1 -0
  57. package/dist/permissions.js +271 -0
  58. package/dist/permissions.js.map +1 -0
  59. package/dist/tools/extraTools.d.ts +80 -0
  60. package/dist/tools/extraTools.d.ts.map +1 -0
  61. package/dist/tools/extraTools.js +471 -0
  62. package/dist/tools/extraTools.js.map +1 -0
  63. package/dist/tools/readMemoryTool.d.ts +3 -0
  64. package/dist/tools/readMemoryTool.d.ts.map +1 -0
  65. package/dist/tools/readMemoryTool.js +115 -0
  66. package/dist/tools/readMemoryTool.js.map +1 -0
  67. package/dist/tools/taskTool.d.ts +119 -0
  68. package/dist/tools/taskTool.d.ts.map +1 -0
  69. package/dist/tools/taskTool.js +466 -0
  70. package/dist/tools/taskTool.js.map +1 -0
  71. package/dist/tools/testRunTool.d.ts +59 -0
  72. package/dist/tools/testRunTool.d.ts.map +1 -0
  73. package/dist/tools/testRunTool.js +308 -0
  74. package/dist/tools/testRunTool.js.map +1 -0
  75. package/dist/turnLog.d.ts +89 -0
  76. package/dist/turnLog.d.ts.map +1 -0
  77. package/dist/turnLog.js +469 -0
  78. package/dist/turnLog.js.map +1 -0
  79. package/package.json +35 -0
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Task tool — spawns a focused subagent to investigate a scoped question or
3
+ * complete a bounded task without polluting the parent conversation.
4
+ *
5
+ * The subagent runs its own ToolUseLoop with:
6
+ * - A scoped system prompt (focused on the stated goal, asked for a synopsis)
7
+ * - Its own iteration budget (default 6, separate from the parent's)
8
+ * - Access to the parent's tools EXCEPT `task` itself (no recursion)
9
+ * - The parent's beforeToolExecute gate (so PreToolUse hooks still apply)
10
+ *
11
+ * The subagent's final response is returned as the tool result. The parent
12
+ * model sees only the synopsis — not the subagent's intermediate tool calls.
13
+ */
14
+ import { ToolRegistry, type AgentTool, type ChatFn, type ToolExecutionContext, type ToolUseLoopOptions } from '@burtson-labs/agent-core';
15
+ import type { BackgroundTaskStore } from '../backgroundTasks';
16
+ type SubagentLoopOptions = Pick<ToolUseLoopOptions, 'nativeTools' | 'nativeToolFailureFallback' | 'messageTokenBudget' | 'maxParallelTools' | 'maxTotalTools' | 'outputBudgetTokens' | 'outputBudgetRatio'>;
17
+ export interface TaskToolOptions {
18
+ /** Streaming chat function — same signature as the parent loop uses. */
19
+ chat: ChatFn;
20
+ /** The parent's tool registry. Subagent gets a copy minus `task` itself. */
21
+ parentRegistry: ToolRegistry;
22
+ /** Execution context the subagent should use (usually the parent's). */
23
+ ctx: ToolExecutionContext;
24
+ /** Max iterations for the subagent. Default: 6. */
25
+ maxIterations?: number;
26
+ /** Optional hook gate — typically forwarded from the parent. */
27
+ beforeToolExecute?: ToolUseLoopOptions['beforeToolExecute'];
28
+ /** Called with every subagent event. Hosts can display progress inline. */
29
+ onEvent?: (type: string, payload?: unknown) => void;
30
+ /**
31
+ * Optional background-task store. When present, the agent can pass
32
+ * `run_in_background: true` to the `task` tool and the subagent runs
33
+ * detached — the tool returns a task id immediately and the subagent
34
+ * eventually pushes its synopsis through this store. Hosts that don't
35
+ * supply a store get the legacy synchronous behaviour only.
36
+ */
37
+ backgroundStore?: BackgroundTaskStore;
38
+ /**
39
+ * Resolves the parent's full system prompt at subagent-spawn time.
40
+ * When provided, the subagent inherits this prompt verbatim and a
41
+ * thin scope wrapper is appended. This eliminates the dual-prompt
42
+ * drift that caused subagents to stall: the hand-rolled fallback
43
+ * below forbade `<tool_call>` markup in prose but never showed the
44
+ * format anywhere, so the model would close its reasoning fence and
45
+ * never emit a tool call (confirmed via diagnostic traces 2026-05-08
46
+ * across 8 subagents — `hasToolCallMarkup: false` on every retry).
47
+ *
48
+ * Accepts string OR getter so callers can register the task tool
49
+ * BEFORE per-turn prompt construction completes; the getter is
50
+ * resolved when the subagent actually spawns.
51
+ *
52
+ * Falls back to the legacy SUBAGENT_PROMPT_FALLBACK when not set.
53
+ */
54
+ parentSystemPrompt?: string | (() => string | undefined);
55
+ /**
56
+ * Parent loop tuning that should carry into spawned subagents.
57
+ * Critical for native-tool models such as bandit-logic/Qwen: without
58
+ * `nativeTools`, the subagent gets XML prompt instructions but no
59
+ * provider `tools` field, so the model reasons about tool calls without
60
+ * emitting one. Keep this narrow to transport budget/protocol settings,
61
+ * not lifecycle hooks owned by the task tool itself.
62
+ */
63
+ subagentLoopOptions?: SubagentLoopOptions | (() => SubagentLoopOptions | undefined);
64
+ /**
65
+ * Returns the parent loop's AbortSignal so subagents can honor it.
66
+ * v1.7.338+: without this hookup, hitting Stop in the IDE aborted
67
+ * the parent loop but background subagents kept running in their own
68
+ * loops — backgroundStore stayed "N running" and the only way to
69
+ * recover was to kill the extension process. With the getter wired
70
+ * up, every spawned subagent (foreground OR background) passes the
71
+ * parent signal as its loop's `signal`; when the parent aborts, the
72
+ * subagent loop sees it on its next iteration check and exits
73
+ * cleanly, the store records the task as cancelled, and the UI
74
+ * clears.
75
+ *
76
+ * Getter rather than value so subagents spawned mid-turn pick up the
77
+ * CURRENT turn's controller, not whichever one was active when the
78
+ * tool was registered.
79
+ */
80
+ getParentSignal?: () => AbortSignal | undefined;
81
+ /**
82
+ * Maximum number of background subagents that can be running at once.
83
+ * When the cap is hit, a `task(run_in_background)` call returns
84
+ * immediately with a non-error result telling the model how many are
85
+ * running and how to wait. Without this cap, the model can fan out
86
+ * unboundedly — with 7 concurrent subagents all
87
+ * hitting Ollama simultaneously, which starved the host's token
88
+ * budget and left the chat card stuck on 0 iter / 0 tools.
89
+ *
90
+ * Defaults to 3 (a reasonable floor for parallel investigation
91
+ * without overwhelming a local model server). Set to 0 to disable
92
+ * the cap entirely. Foreground (synchronous) tasks ignore this cap
93
+ * because they're already serial by construction.
94
+ */
95
+ maxConcurrentBackground?: number;
96
+ }
97
+ /**
98
+ * Build the `task` tool. Register it on the parent agent's registry so the
99
+ * model can delegate scoped work to a subagent.
100
+ */
101
+ export declare function buildTaskTool(opts: TaskToolOptions): AgentTool;
102
+ /**
103
+ * `check_task` tool — query the current state of a single background
104
+ * subagent. Returns a friendly status line + the synopsis when the
105
+ * task has completed. The agent rarely needs to call this because the
106
+ * host auto-injects completion events into the next turn, but it's
107
+ * here for explicit "are we there yet" polling and for cases where
108
+ * the agent wants to wait on a specific task before doing the next
109
+ * thing.
110
+ */
111
+ export declare function buildCheckTaskTool(store: BackgroundTaskStore): AgentTool;
112
+ /**
113
+ * `list_tasks` tool — list every background subagent task in the
114
+ * current session. Cheap status overview; the agent typically only
115
+ * calls this if the user asks "what's still running" or similar.
116
+ */
117
+ export declare function buildListTasksTool(store: BackgroundTaskStore): AgentTool;
118
+ export {};
119
+ //# sourceMappingURL=taskTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskTool.d.ts","sourceRoot":"","sources":["../../src/tools/taskTool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAEL,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,oBAAoB,EAEzB,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,KAAK,mBAAmB,GAAG,IAAI,CAC7B,kBAAkB,EAClB,aAAa,GAAG,2BAA2B,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,eAAe,GAAG,oBAAoB,GAAG,mBAAmB,CACvJ,CAAC;AA+BF,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,cAAc,EAAE,YAAY,CAAC;IAC7B,wEAAwE;IACxE,GAAG,EAAE,oBAAoB,CAAC;IAC1B,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;IAC5D,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC;;;;;;;;;;;;;;;OAeG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;IACzD;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,mBAAmB,GAAG,CAAC,MAAM,mBAAmB,GAAG,SAAS,CAAC,CAAC;IACpF;;;;;;;;;;;;;;;OAeG;IACH,eAAe,CAAC,EAAE,MAAM,WAAW,GAAG,SAAS,CAAC;IAChD;;;;;;;;;;;;;OAaG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAgCD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,GAAG,SAAS,CAsT9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,SAAS,CAmCxE;AAwBD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,SAAS,CAmBxE"}
@@ -0,0 +1,466 @@
1
+ "use strict";
2
+ /**
3
+ * Task tool — spawns a focused subagent to investigate a scoped question or
4
+ * complete a bounded task without polluting the parent conversation.
5
+ *
6
+ * The subagent runs its own ToolUseLoop with:
7
+ * - A scoped system prompt (focused on the stated goal, asked for a synopsis)
8
+ * - Its own iteration budget (default 6, separate from the parent's)
9
+ * - Access to the parent's tools EXCEPT `task` itself (no recursion)
10
+ * - The parent's beforeToolExecute gate (so PreToolUse hooks still apply)
11
+ *
12
+ * The subagent's final response is returned as the tool result. The parent
13
+ * model sees only the synopsis — not the subagent's intermediate tool calls.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.buildTaskTool = buildTaskTool;
17
+ exports.buildCheckTaskTool = buildCheckTaskTool;
18
+ exports.buildListTasksTool = buildListTasksTool;
19
+ const agent_core_1 = require("@burtson-labs/agent-core");
20
+ function resolveSubagentLoopOptions(value) {
21
+ const resolved = typeof value === 'function' ? value() : value;
22
+ return resolved ?? {};
23
+ }
24
+ /**
25
+ * Strip reasoning fences (```bandit-reasoning … ``` and <think>…</think>)
26
+ * from the subagent's final response so the synopsis the parent sees is
27
+ * the actual analysis, not the model's internal monologue. Observed
28
+ * 2026-05-06: subagents that stalled in reasoning without ever calling a
29
+ * tool returned a `finalResponse` that was JUST the reasoning fence, and
30
+ * the chat card in the IDE rendered "I need to actually emit tool calls.
31
+ * Let me start by reading the package.json…" as the synopsis — looked
32
+ * like the subagent had thoughts but hadn't shipped them. Now we strip
33
+ * the fences first; if nothing useful remains, we surface that as a
34
+ * "subagent stalled in reasoning" error instead of pretending we got an
35
+ * answer.
36
+ */
37
+ function sanitizeSubagentSynopsis(raw) {
38
+ return raw
39
+ .replace(/```bandit-reasoning\b[\s\S]*?```/gi, '')
40
+ .replace(/```bandit-reasoning\b[\s\S]*$/i, '')
41
+ .replace(/<think\b[\s\S]*?<\/think\s*>/gi, '')
42
+ .replace(/<think\b[\s\S]*$/i, '')
43
+ .trim();
44
+ }
45
+ const DEFAULT_MAX_CONCURRENT_BACKGROUND = 3;
46
+ /**
47
+ * Defensive fallback when the host doesn't pass `parentSystemPrompt`.
48
+ *
49
+ * Self-sufficient — works on its own without inheritance.
50
+ * tightening: the format example is INLINE on a single line after a
51
+ * colon (same pattern as the fix to extensionSystemPrompt.ts).
52
+ * Putting it on its own line surrounded by whitespace triggers
53
+ * Ollama's qwen parser as a real tool call, xml.Unmarshal hits EOF on
54
+ * the JSON inside, and upstream returns 500. Don't reformat this.
55
+ *
56
+ * Why explicit + emphatic: subagents on bandit-logic 27B would
57
+ * literally read the old prompt's "NEVER write <tool_call> markup"
58
+ * rule and comply by closing their reasoning fence and stopping —
59
+ * never emitting an actual tool call. The fix is to combine the
60
+ * format example (inline, parser-safe) with explicit "your FIRST
61
+ * response must emit one of these" framing so the model knows what
62
+ * to do AND that it's required.
63
+ */
64
+ const SUBAGENT_PROMPT_FALLBACK = `You are a focused coding subagent built by Burtson Labs. You have one bounded goal and the same tool registry as the parent agent (read, search, shell, write, git, todo_write) EXCEPT \`task\` — you cannot spawn further subagents.
65
+
66
+ Call tools by outputting on a single line: <tool_call>{"name": "tool_name", "params": {"key": "value"}}</tool_call>
67
+
68
+ Your FIRST response MUST contain a real tool call. Reasoning is fine — but the response must include an actual <tool_call> envelope, not just talk about one. The goal needs information you don't have; the only way to get it is via tools. Pick the most obvious starting tool (\`list_files\` for "what's in this dir", \`read_file\` for "what does X look like", \`search_code\` for "where is Y") and emit it.
69
+
70
+ When *describing* tool calls in prose (in synopsis or explanations), use words: "I called read_file with path=...". NEVER emit the literal angle-bracket markup outside an actual invocation — it breaks Ollama's qwen parser (xml.Unmarshal returns EOF on the JSON inside, upstream 500). Same rule for tool_result and think tokens: never as prose.
71
+
72
+ When the goal is complete, return a 2-6 line synopsis. No preamble. If the goal is ambiguous, make ONE reasonable interpretation and state it.`;
73
+ /**
74
+ * Build the `task` tool. Register it on the parent agent's registry so the
75
+ * model can delegate scoped work to a subagent.
76
+ */
77
+ function buildTaskTool(opts) {
78
+ // Tool registry the subagent uses — same one whether the call is
79
+ // foreground or background. Exclude `task` itself so subagents can't
80
+ // spawn further subagents (recursion + budget blowup).
81
+ const subRegistry = new agent_core_1.ToolRegistry();
82
+ for (const tool of opts.parentRegistry.getAll()) {
83
+ if (tool.name === 'task')
84
+ continue;
85
+ subRegistry.register(tool);
86
+ }
87
+ const maxIterations = opts.maxIterations ?? 6;
88
+ const emit = opts.onEvent ?? (() => undefined);
89
+ /** Run a subagent loop and return its result. Used by both the
90
+ * foreground and background paths so the actual run logic stays
91
+ * in one place. The `progressEmitter` is called per-iteration with
92
+ * the running iteration count + tool counts so the BackgroundTaskStore
93
+ * can keep its progress fields current. */
94
+ const runSubagent = async (goal, context, progressEmitter, taskId) => {
95
+ let iterations = 0;
96
+ let toolCalls = 0;
97
+ let lastTool;
98
+ const inheritedLoopOptions = resolveSubagentLoopOptions(opts.subagentLoopOptions);
99
+ const subagent = new agent_core_1.ToolUseLoop(subRegistry, opts.ctx, {
100
+ ...inheritedLoopOptions,
101
+ maxIterations,
102
+ beforeToolExecute: opts.beforeToolExecute,
103
+ // Mark this loop as a subagent so the loop's iter-0-no-tool-call
104
+ // detector can force a tool call when bandit-logic stalls in
105
+ // reasoning. Without this, the model emits prose + reasoning on
106
+ // iter 0 (not matching the announce-intent or narrate verb
107
+ // patterns), the loop treats it as a final answer, and the
108
+ // parent gets a 0-iteration "stalled in reasoning" failure.
109
+ isSubagent: true,
110
+ emitEvent: (type, payload) => {
111
+ // Track progress fields that hosts care about — iteration count,
112
+ // tool-call count, last tool name. Cheap counters, not the full
113
+ // event log; the latter would be too noisy for the status display
114
+ // that the agent / user actually look at.
115
+ //
116
+ // the loop never emits `iteration:start`. The
117
+ // canonical per-iteration marker is `tool_loop:llm_start`,
118
+ // whose payload carries the loop's own zero-indexed `iteration`
119
+ // counter. Pre-fix, this branch listened for `iteration:start`
120
+ // and the local counter never incremented, so every background
121
+ // task in the host's grouped UI showed "0 iter" forever. Read
122
+ // from the payload so the count tracks the loop's truth, not
123
+ // a hand-rolled increment.
124
+ if (type === 'tool_loop:llm_start') {
125
+ const iter = payload?.iteration;
126
+ if (typeof iter === 'number' && Number.isFinite(iter)) {
127
+ iterations = Math.max(iterations, iter + 1);
128
+ }
129
+ }
130
+ if (type === 'tool_loop:tool_execute') {
131
+ toolCalls += 1;
132
+ const name = payload?.name;
133
+ if (typeof name === 'string')
134
+ lastTool = name;
135
+ }
136
+ progressEmitter?.({ iterations, toolCalls, lastTool });
137
+ // Tag every relayed event with the owning taskId when this is a
138
+ // backgrounded run, so a host with multiple concurrent background
139
+ // subagents can route events to the right card. Without this all
140
+ // events arrive flat and the host can't tell tools-of-task-A from
141
+ // tools-of-task-B — with 7 concurrent tasks
142
+ // where the chat card stayed at 0 iter / 0 tools because the
143
+ // single global buffer was being clobbered by every task:start.
144
+ const tagged = taskId !== undefined && payload && typeof payload === 'object'
145
+ ? { ...payload, taskId }
146
+ : payload;
147
+ emit(`subagent:${type}`, tagged);
148
+ }
149
+ });
150
+ // Inherit the parent's system prompt verbatim when supplied — this is
151
+ // the fix for the recurring subagent stall. A hand-rolled
152
+ // subagent prompt always drifts from the parent's protocol (the
153
+ // legacy SUBAGENT_PROMPT forbade `<tool_call>` markup but never
154
+ // showed the format). Inheriting + appending a thin scope wrapper
155
+ // keeps tool-call format, behavior policies, and operational hints
156
+ // consistent across parent and subagent.
157
+ const inherited = typeof opts.parentSystemPrompt === 'function'
158
+ ? opts.parentSystemPrompt()
159
+ : opts.parentSystemPrompt;
160
+ const baseSystemPrompt = inherited && inherited.trim().length > 0
161
+ ? inherited
162
+ : SUBAGENT_PROMPT_FALLBACK;
163
+ const subagentScope = [
164
+ '',
165
+ '',
166
+ '## Subagent Scope',
167
+ 'You are operating as a SUBAGENT — a focused sub-process spawned by the parent agent to accomplish a single bounded goal.',
168
+ '',
169
+ `Your goal: ${goal}`,
170
+ context ? `\nContext: ${context}` : '',
171
+ '',
172
+ 'Subagent rules:',
173
+ '- Stay strictly on the goal. No adjacent work, refactors, or "while I\'m here" cleanups.',
174
+ '- When the goal is complete, return a 2-6 line synopsis. No preamble.',
175
+ '- You CANNOT spawn further subagents (the `task` tool is not in your registry).',
176
+ '- If the goal is ambiguous, make ONE reasonable interpretation and state it in your synopsis.',
177
+ '- If you cannot reach the goal (tool errors, missing files, etc.), return what you learned and why you stopped.'
178
+ ].filter((line, idx, arr) => !(line === '' && arr[idx - 1] === '')).join('\n');
179
+ const systemPrompt = `${baseSystemPrompt}${subagentScope}`;
180
+ // Telemetry: log the subagent's system prompt size +
181
+ // inheritance source. Lets us correlate "huge inherited prompt"
182
+ // with stalls/watchdog fires in the turn log without having to
183
+ // recompute the size from chunks. Surfaced via subagent:task:spawn
184
+ // event so hosts append it to the turn log alongside task:start.
185
+ emit('subagent:task:spawn', {
186
+ taskId,
187
+ goal,
188
+ systemPromptChars: systemPrompt.length,
189
+ inheritedFromParent: Boolean(inherited && inherited.trim().length > 0),
190
+ nativeTools: Boolean(inheritedLoopOptions.nativeTools),
191
+ registryToolCount: subRegistry.getAll().length
192
+ });
193
+ // Pass the parent loop's AbortSignal through so Stop in the host
194
+ // (Esc in CLI, cancel button in IDE) cascades down to in-flight
195
+ // subagents. v1.7.338+: without this, hitting Stop aborted the
196
+ // parent but every backgrounded subagent kept running and the
197
+ // user had to kill the process to recover. The getter is read at
198
+ // EACH spawn (not cached at registration time) so a subagent
199
+ // spawned mid-turn picks up the current turn's controller.
200
+ return subagent.run(goal, opts.chat, systemPrompt, {
201
+ signal: opts.getParentSignal?.()
202
+ });
203
+ };
204
+ return {
205
+ name: 'task',
206
+ description: 'Spawn a focused subagent to investigate a specific question or complete a bounded task. Do NOT use this for first-pass repo overviews like "what is this project" or "tell me about this repo" — answer those with direct list/read/search calls first. Use task for explicit exhaustive audits or a narrow branch of work whose intermediate details are not worth surfacing in the main conversation. The subagent returns a concise synopsis; its intermediate tool calls are hidden from you. Does NOT support nested task spawning. Pass run_in_background="true" for long-running or parallel investigations — the tool returns a task id immediately and the subagent\'s synopsis is delivered to you on a later turn so you can keep working with the user in the meantime.',
207
+ parameters: [
208
+ { name: 'goal', description: 'The specific question or task for the subagent. Be concrete — "find all call sites of foo() and list their files" beats "look at foo usage".', required: true },
209
+ { name: 'context', description: 'Optional: one or two sentences of background the subagent needs that is not obvious from the goal alone.', required: false },
210
+ { name: 'run_in_background', description: 'Optional. When "true", spawn the subagent in the background and return immediately with a task id. The subagent\'s synopsis is auto-injected into a later turn when it completes, so you can keep responding to the user while it runs. Use this for investigations that would otherwise take 30+ seconds and don\'t block the user\'s next question. Default: false (synchronous, parent waits).', required: false }
211
+ ],
212
+ async execute(params, _ctx) {
213
+ const goal = params.goal?.trim();
214
+ if (!goal) {
215
+ return { output: 'Error: goal parameter is required.', isError: true };
216
+ }
217
+ const context = params.context?.trim();
218
+ const wantsBackground = String(params.run_in_background ?? '').toLowerCase() === 'true';
219
+ // Background path: spawn detached, return immediately with a task
220
+ // id. Requires the host to have wired up a backgroundStore — fall
221
+ // back to synchronous if the store isn't available, with a note
222
+ // so the agent knows why it didn't actually go async.
223
+ if (wantsBackground && opts.backgroundStore) {
224
+ const store = opts.backgroundStore;
225
+ // Concurrency cap: refuse to spawn when the configured ceiling
226
+ // of in-flight backgrounds is already reached. This is flow
227
+ // control, not an error — isError stays false so the model can
228
+ // calmly pick from the offered options (wait, check_task on a
229
+ // running id, or re-issue without backgrounding) without the
230
+ // hallucination-prone "tool failed" framing.
231
+ const cap = opts.maxConcurrentBackground ?? DEFAULT_MAX_CONCURRENT_BACKGROUND;
232
+ if (cap > 0) {
233
+ const running = store.listByStatus('running');
234
+ if (running.length >= cap) {
235
+ emit('task:cap-hit', {
236
+ goal,
237
+ cap,
238
+ runningCount: running.length,
239
+ runningIds: running.map((r) => r.id)
240
+ });
241
+ const ids = running.map((r) => r.id).join(', ');
242
+ return {
243
+ output: `Background subagent limit reached (${running.length} / ${cap} already running). ` +
244
+ `Pick one: (a) wait for a running task to complete and call task(run_in_background="true") again, ` +
245
+ `(b) call check_task on one of [${ids}] to block on a specific task, or ` +
246
+ `(c) re-issue this task without run_in_background to run it inline now.`,
247
+ isError: false
248
+ };
249
+ }
250
+ }
251
+ const taskId = store.start(goal);
252
+ emit('task:start', { goal, maxIterations, background: true, taskId });
253
+ // Detached run. We deliberately do NOT await — the parent tool
254
+ // call returns synchronously below.
255
+ void (async () => {
256
+ try {
257
+ const result = await runSubagent(goal, context, (p) => {
258
+ store.progress(taskId, p);
259
+ }, taskId);
260
+ // Parent abort cascaded down — mark cancelled, NOT failed.
261
+ // (v1.7.338+) Without this branch, a parent-aborted subagent
262
+ // landed in the failure path with a misleading "stalled in
263
+ // reasoning, 0 iterations" message, because cancelled
264
+ // runs return finalResponse='[cancelled]' which strips to
265
+ // an empty synopsis.
266
+ if (result.cancelled) {
267
+ store.cancel(taskId);
268
+ emit('task:cancel', { goal, taskId, iterations: result.iterations });
269
+ return;
270
+ }
271
+ const synopsis = sanitizeSubagentSynopsis(result.finalResponse);
272
+ if (!synopsis) {
273
+ const reason = result.iterations === 0
274
+ ? 'Subagent stalled in reasoning without emitting a tool call or final answer (0 iterations). The model thought through the goal but never committed to an action.'
275
+ : `Subagent finished in ${result.iterations} iteration(s) but returned no synopsis.${result.hitLimit ? ' (Hit iteration limit.)' : ''}`;
276
+ store.fail(taskId, reason);
277
+ emit('task:error', { goal, taskId, error: reason });
278
+ return;
279
+ }
280
+ const limitNote = result.hitLimit ? `\n\n[Note: subagent hit ${maxIterations}-iteration limit, synopsis may be incomplete.]` : '';
281
+ // same directive wrap as the sync path so the
282
+ // parent's next turn treats the auto-injected background
283
+ // synopsis as "the answer to my delegation" rather than
284
+ // raw text it can ignore. See sync-path comment for the
285
+ // observed-failure context.
286
+ const bgDirective = '=== SUBAGENT REPORT — this is the answer to your delegation ===\n\n' +
287
+ 'The subagent you dispatched in the background has finished. The findings BELOW are what it found in the actual codebase. Synthesize THESE into your answer.\n\n' +
288
+ 'Do NOT speak as if the subagent is still running, restate your initial hypothesis, or invent gap categories that weren\'t in the report. DO cite the subagent\'s specific findings by name (file paths, function names, exact labels) and lead with anything it flagged as a real bug or missing capability.\n\n' +
289
+ '--- Subagent findings ---\n\n';
290
+ store.complete(taskId, `${bgDirective}${synopsis}${limitNote}`);
291
+ emit('task:done', { goal, taskId, iterations: result.iterations, hitLimit: result.hitLimit });
292
+ }
293
+ catch (err) {
294
+ const msg = err instanceof Error ? err.message : String(err);
295
+ store.fail(taskId, msg);
296
+ emit('task:error', { goal, taskId, error: msg });
297
+ }
298
+ })();
299
+ return {
300
+ output: `Spawned background subagent (task id: ${taskId}) — goal: "${goal}". ` +
301
+ `You'll receive a synthetic system message with the synopsis when it completes. ` +
302
+ `In the meantime, keep responding to the user. ` +
303
+ `Call check_task with this id if you need to poll, or list_tasks to see all background work.`,
304
+ isError: false
305
+ };
306
+ }
307
+ if (wantsBackground && !opts.backgroundStore) {
308
+ emit('task:warn', { goal, warning: 'background-not-supported' });
309
+ // Fall through to synchronous path with a note appended.
310
+ }
311
+ // Synchronous path — same as v1.7.x and earlier. Parent waits.
312
+ emit('task:start', { goal, maxIterations, background: false });
313
+ try {
314
+ const result = await runSubagent(goal, context);
315
+ emit('task:done', { goal, iterations: result.iterations, hitLimit: result.hitLimit });
316
+ const synopsis = sanitizeSubagentSynopsis(result.finalResponse);
317
+ if (!synopsis) {
318
+ const reason = result.iterations === 0
319
+ ? 'Subagent stalled in reasoning without emitting a tool call or final answer (0 iterations). The model thought through the goal but never committed to an action.'
320
+ : `Subagent finished in ${result.iterations} iteration(s) but returned no synopsis.${result.hitLimit ? ' (Hit iteration limit.)' : ''}`;
321
+ return { output: reason, isError: true };
322
+ }
323
+ const limitNote = result.hitLimit ? `\n\n[Note: subagent hit ${maxIterations}-iteration limit, synopsis may be incomplete.]` : '';
324
+ const fallbackNote = wantsBackground && !opts.backgroundStore
325
+ ? '\n\n[Note: run_in_background was requested but this host does not support background tasks; ran synchronously.]'
326
+ : '';
327
+ // wrap the synopsis with a directive header so the
328
+ // parent model treats this as "the answer to my delegation" and
329
+ // synthesizes it into the final response. Without this header,
330
+ // Gemma 4 (bandit-core-1) was ignoring real subagent findings
331
+ // and restating its iter-0 hypothesis as if the subagent were
332
+ // still running. turn 4kec: subagent
333
+ // returned 2.2 KB of concrete findings (Underutilized Git
334
+ // tools, missing LSP integration, semantic-search gap, real
335
+ // technical debt in resolveRepoPath); parent's iter-1
336
+ // response cloned the iter-0 prose with the same 4 invented
337
+ // gaps and present-tense "while it digs into the source."
338
+ // The header is structural ("=== SUBAGENT REPORT ===" + an
339
+ // explicit directive) so it's hard to overlook even when the
340
+ // model is in "restate-my-hypothesis" mode.
341
+ const directive = '=== SUBAGENT REPORT — this is the answer to your delegation ===\n\n' +
342
+ 'The subagent you dispatched has finished its investigation. The findings BELOW are what it found in the actual codebase. Synthesize THESE into your final answer.\n\n' +
343
+ 'Do NOT:\n' +
344
+ ' - Speak in present tense as if the subagent is still running ("while it digs into…").\n' +
345
+ ' - Restate your initial hypothesis about what the subagent might find.\n' +
346
+ ' - Invent gap categories that weren\'t in the report.\n\n' +
347
+ 'Do:\n' +
348
+ ' - Cite the subagent\'s specific findings by name (file paths, function names, exact gap labels it used).\n' +
349
+ ' - If the subagent flagged a real bug or missing capability, lead with that.\n' +
350
+ ' - If the subagent\'s report contradicted your initial hypothesis, update your answer accordingly.\n\n' +
351
+ '--- Subagent findings ---\n\n';
352
+ return { output: `${directive}${synopsis}${limitNote}${fallbackNote}`, isError: false };
353
+ }
354
+ catch (err) {
355
+ const msg = err instanceof Error ? err.message : String(err);
356
+ emit('task:error', { goal, error: msg });
357
+ // Categorize for the model so it knows whether to pivot
358
+ // (upstream/network — try a different approach OR the same one
359
+ // again later) or to give up (logic — won't get better on retry).
360
+ // The most common failure in practice is an upstream gateway 5xx
361
+ // during the subagent's chat call, which had been surfacing as
362
+ // "Subagent crashed: 500 Internal Server Error" — easy to read
363
+ // as a tool-denial issue. Now we tag it explicitly.
364
+ const looksLikeUpstream = /\b(5\d\d)\b|upstream|gateway|fetch failed|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|socket hang up|aborted/i.test(msg);
365
+ const tag = looksLikeUpstream
366
+ ? 'Subagent failed: upstream/model error (this is NOT a tool-permission issue — the subagent\'s call to the LLM provider failed with a 5xx / network error). You can retry the same task tool call once; if it fails again, fall back to doing the work in the parent agent without delegating.'
367
+ : 'Subagent crashed';
368
+ return { output: `${tag}: ${msg}`, isError: true };
369
+ }
370
+ }
371
+ };
372
+ }
373
+ /**
374
+ * `check_task` tool — query the current state of a single background
375
+ * subagent. Returns a friendly status line + the synopsis when the
376
+ * task has completed. The agent rarely needs to call this because the
377
+ * host auto-injects completion events into the next turn, but it's
378
+ * here for explicit "are we there yet" polling and for cases where
379
+ * the agent wants to wait on a specific task before doing the next
380
+ * thing.
381
+ */
382
+ function buildCheckTaskTool(store) {
383
+ return {
384
+ name: 'check_task',
385
+ description: 'Inspect the current state of a single background subagent task spawned via task(run_in_background="true"). Returns the running/completed/failed status, iteration count, and (when complete) the full synopsis. The output leads with the task\'s short title ("the security review is still running…") so when you narrate back to the user, use the title — not the raw id. Most of the time you do NOT need to call this — completed-task synopses are auto-injected as system messages on the next turn. Use this only when you want to explicitly wait on a specific task before doing the next thing.',
386
+ parameters: [
387
+ { name: 'task_id', description: 'The id returned from a previous task(run_in_background="true") call.', required: true }
388
+ ],
389
+ execute(params) {
390
+ const id = params.task_id?.trim();
391
+ if (!id)
392
+ return Promise.resolve({ output: 'Error: task_id parameter is required.', isError: true });
393
+ const record = store.get(id);
394
+ if (!record)
395
+ return Promise.resolve({ output: `No background task with id "${id}".`, isError: true });
396
+ const seconds = ((record.endedAt ?? Date.now()) - record.startedAt) / 1000;
397
+ const stamp = `${seconds.toFixed(1)}s, ${record.iterations} iter, ${record.toolCalls} tool calls`;
398
+ // Lead with the task's GOAL (short title) so the agent's narration
399
+ // back to the user reads "the security review is still running"
400
+ // instead of "task bg-mpr7i4jb-hths is still running". The raw id
401
+ // stays available in parentheses for explicit re-checks.
402
+ const title = formatTaskTitle(record.goal);
403
+ if (record.status === 'running') {
404
+ return Promise.resolve({ output: `"${title}" — still running (${stamp}). Last tool: ${record.lastTool ?? '—'}. (id: ${id})`, isError: false });
405
+ }
406
+ if (record.status === 'completed') {
407
+ store.markConsumed(id);
408
+ return Promise.resolve({ output: `"${title}" — completed (${stamp}). (id: ${id})\n\n${record.synopsis ?? '(no synopsis)'}`, isError: false });
409
+ }
410
+ if (record.status === 'failed') {
411
+ store.markConsumed(id);
412
+ return Promise.resolve({ output: `"${title}" — failed (${stamp}): ${record.error ?? 'unknown error'} (id: ${id})`, isError: true });
413
+ }
414
+ // cancelled
415
+ store.markConsumed(id);
416
+ return Promise.resolve({ output: `"${title}" — cancelled (${stamp}). (id: ${id})`, isError: false });
417
+ }
418
+ };
419
+ }
420
+ /**
421
+ * Format a task's goal into a short narratable title. Strips imperative
422
+ * verb scaffolding ("Do a", "Investigate", "Perform a") so the title
423
+ * reads naturally inside a sentence ("the security review is still
424
+ * running" instead of "the do-a-security-review is still running").
425
+ * Caps at 60 chars with an ellipsis so it stays in a single line of
426
+ * the agent's narration.
427
+ */
428
+ function formatTaskTitle(goal) {
429
+ let title = goal.trim();
430
+ // Strip common imperative openers so the title reads as a noun phrase.
431
+ title = title.replace(/^(do a|do an|perform a|perform an|investigate|investigate the|run a|run an|conduct a|conduct an)\s+/i, '');
432
+ // Trim trailing punctuation that's part of the goal sentence.
433
+ title = title.replace(/[.!?]+$/, '');
434
+ // Single line. Models sometimes wrap goals with newlines; flatten.
435
+ title = title.replace(/\s+/g, ' ');
436
+ if (title.length > 60) {
437
+ title = title.slice(0, 57).trimEnd() + '…';
438
+ }
439
+ return title || goal.slice(0, 60);
440
+ }
441
+ /**
442
+ * `list_tasks` tool — list every background subagent task in the
443
+ * current session. Cheap status overview; the agent typically only
444
+ * calls this if the user asks "what's still running" or similar.
445
+ */
446
+ function buildListTasksTool(store) {
447
+ return {
448
+ name: 'list_tasks',
449
+ description: 'List all background subagent tasks in this session (running and completed). Useful when the user asks "what\'s still running" or "what happened with that earlier task". Each entry leads with the task\'s short title (derived from its goal) — when narrating back to the user, refer to tasks by title ("the security review is still working") rather than by id.',
450
+ parameters: [],
451
+ execute() {
452
+ const tasks = store.list();
453
+ if (tasks.length === 0) {
454
+ return Promise.resolve({ output: 'No background tasks have been spawned in this session.', isError: false });
455
+ }
456
+ const lines = tasks.map((t) => {
457
+ const seconds = ((t.endedAt ?? Date.now()) - t.startedAt) / 1000;
458
+ const status = t.status === 'running' ? `running (${seconds.toFixed(0)}s)` : `${t.status} (${seconds.toFixed(1)}s)`;
459
+ const title = formatTaskTitle(t.goal);
460
+ return `- "${title}" · ${status} · ${t.iterations} iter (id: ${t.id})`;
461
+ });
462
+ return Promise.resolve({ output: lines.join('\n'), isError: false });
463
+ }
464
+ };
465
+ }
466
+ //# sourceMappingURL=taskTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskTool.js","sourceRoot":"","sources":["../../src/tools/taskTool.ts"],"names":[],"mappings":"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"}