@code-yeongyu/senpi 2026.5.14 → 2026.5.15-2
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.
- package/CHANGELOG.md +1107 -1182
- package/README.md +1 -2
- package/dist/core/agent-session.d.ts +9 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +109 -7
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/dynamic-prompt/verification.d.ts +31 -0
- package/dist/core/dynamic-prompt/verification.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/verification.js +41 -0
- package/dist/core/dynamic-prompt/verification.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +157 -29
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +197 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.js +690 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/prompts.d.ts +3 -3
- package/dist/core/extensions/builtin/compaction/prompts.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/prompts.js +0 -22
- package/dist/core/extensions/builtin/compaction/prompts.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts +4 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js +48 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +3 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +82 -33
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts +8 -0
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.js +12 -6
- package/dist/core/extensions/builtin/compaction/todo-bridge.js.map +1 -1
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +0 -2
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/prompt.js +0 -5
- package/dist/core/extensions/builtin/permission-system/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/system-messages.d.ts +7 -7
- package/dist/core/extensions/builtin/system-messages.d.ts.map +1 -1
- package/dist/core/extensions/builtin/system-messages.js +10 -10
- package/dist/core/extensions/builtin/system-messages.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.js +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.js +1 -1
- package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/system-messages.d.ts +3 -3
- package/dist/core/extensions/builtin/todotools/system-messages.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/system-messages.js +6 -6
- package/dist/core/extensions/builtin/todotools/system-messages.js.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.js +8 -4
- package/dist/core/extensions/builtin/tool-pair-guard/index.js.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts +3 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js +89 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts +3 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js +122 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +18 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +22 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/messages.d.ts +3 -3
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +5 -10
- package/dist/core/messages.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -22
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +1 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +0 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/thinking-levels.d.ts +6 -0
- package/dist/core/thinking-levels.d.ts.map +1 -0
- package/dist/core/thinking-levels.js +36 -0
- package/dist/core/thinking-levels.js.map +1 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +15 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +20 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +3 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +11 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +96 -49
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/extensions.md +0 -1
- package/docs/index.md +0 -1
- package/docs/sdk.md +0 -1
- package/docs/settings.md +1 -29
- package/docs/termux.md +2 -2
- package/docs/usage.md +1 -1
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/overlay-qa-tests.ts +1 -1
- package/package.json +4 -4
- package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts +0 -10
- package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/cancel-tool.js +0 -109
- package/dist/core/extensions/builtin/background-task/cancel-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/index.d.ts +0 -3
- package/dist/core/extensions/builtin/background-task/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/index.js +0 -207
- package/dist/core/extensions/builtin/background-task/index.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/manager.d.ts +0 -17
- package/dist/core/extensions/builtin/background-task/manager.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/manager.js +0 -114
- package/dist/core/extensions/builtin/background-task/manager.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/notification.d.ts +0 -22
- package/dist/core/extensions/builtin/background-task/notification.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/notification.js +0 -105
- package/dist/core/extensions/builtin/background-task/notification.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/output-tool.d.ts +0 -11
- package/dist/core/extensions/builtin/background-task/output-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/output-tool.js +0 -127
- package/dist/core/extensions/builtin/background-task/output-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/spawner.d.ts +0 -8
- package/dist/core/extensions/builtin/background-task/spawner.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/spawner.js +0 -207
- package/dist/core/extensions/builtin/background-task/spawner.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/task-tool.d.ts +0 -20
- package/dist/core/extensions/builtin/background-task/task-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/task-tool.js +0 -302
- package/dist/core/extensions/builtin/background-task/task-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/types.d.ts +0 -72
- package/dist/core/extensions/builtin/background-task/types.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/types.js +0 -32
- package/dist/core/extensions/builtin/background-task/types.js.map +0 -1
- package/docs/agents.md +0 -348
- package/examples/extensions/subagent/README.md +0 -172
- package/examples/extensions/subagent/agents/planner.md +0 -37
- package/examples/extensions/subagent/agents/reviewer.md +0 -35
- package/examples/extensions/subagent/agents/scout.md +0 -50
- package/examples/extensions/subagent/agents/worker.md +0 -24
- package/examples/extensions/subagent/agents.ts +0 -126
- package/examples/extensions/subagent/index.ts +0 -987
- package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/examples/extensions/subagent/prompts/implement.md +0 -10
- package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import { APP_NAME } from "../../../../config.js";
|
|
5
|
-
import { AGENT_TYPE_ENV_VAR, DEPTH_ENV_VAR, MAX_SUBAGENT_DEPTH, } from "./types.js";
|
|
6
|
-
export function getPiInvocation(args) {
|
|
7
|
-
const currentScript = process.argv[1];
|
|
8
|
-
if (currentScript && fs.existsSync(currentScript)) {
|
|
9
|
-
return { command: process.execPath, args: [currentScript, ...args] };
|
|
10
|
-
}
|
|
11
|
-
const execName = path.basename(process.execPath).toLowerCase();
|
|
12
|
-
const isGenericRuntime = /^(node|bun)(\.exe)?$/.test(execName);
|
|
13
|
-
if (!isGenericRuntime) {
|
|
14
|
-
return { command: process.execPath, args };
|
|
15
|
-
}
|
|
16
|
-
return { command: APP_NAME, args };
|
|
17
|
-
}
|
|
18
|
-
const trackedPids = new Set();
|
|
19
|
-
let cleanupRegistered = false;
|
|
20
|
-
function ensureCleanupRegistered() {
|
|
21
|
-
if (cleanupRegistered)
|
|
22
|
-
return;
|
|
23
|
-
cleanupRegistered = true;
|
|
24
|
-
process.on("exit", () => {
|
|
25
|
-
for (const pid of trackedPids) {
|
|
26
|
-
try {
|
|
27
|
-
process.kill(pid, "SIGTERM");
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
/* process may already be dead */
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
function emitSpawnEvent(options, event) {
|
|
36
|
-
options.onEvent?.(event);
|
|
37
|
-
}
|
|
38
|
-
export function spawnSubagent(options) {
|
|
39
|
-
const currentDepth = parseInt(process.env[DEPTH_ENV_VAR] ?? "0", 10);
|
|
40
|
-
if (currentDepth >= MAX_SUBAGENT_DEPTH) {
|
|
41
|
-
throw new Error(`Maximum subagent depth (${MAX_SUBAGENT_DEPTH}) exceeded`);
|
|
42
|
-
}
|
|
43
|
-
const args = ["--mode", "json", "-p", options.prompt];
|
|
44
|
-
if (options.model) {
|
|
45
|
-
args.push("--model", options.model);
|
|
46
|
-
}
|
|
47
|
-
if (options.sessionPath) {
|
|
48
|
-
args.push("--session", options.sessionPath);
|
|
49
|
-
}
|
|
50
|
-
if (options.permissionFlag) {
|
|
51
|
-
args.push("--permission", options.permissionFlag);
|
|
52
|
-
}
|
|
53
|
-
const invocation = getPiInvocation(args);
|
|
54
|
-
const childEnv = {
|
|
55
|
-
...process.env,
|
|
56
|
-
[DEPTH_ENV_VAR]: String(currentDepth + 1),
|
|
57
|
-
...options.env,
|
|
58
|
-
};
|
|
59
|
-
if (options.agentType) {
|
|
60
|
-
childEnv[AGENT_TYPE_ENV_VAR] = options.agentType;
|
|
61
|
-
}
|
|
62
|
-
const proc = spawn(invocation.command, invocation.args, {
|
|
63
|
-
cwd: options.cwd,
|
|
64
|
-
shell: false,
|
|
65
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
66
|
-
env: childEnv,
|
|
67
|
-
});
|
|
68
|
-
if (proc.pid) {
|
|
69
|
-
trackedPids.add(proc.pid);
|
|
70
|
-
ensureCleanupRegistered();
|
|
71
|
-
}
|
|
72
|
-
let buffer = "";
|
|
73
|
-
const accumulatedText = [];
|
|
74
|
-
const updateText = [];
|
|
75
|
-
const processLine = (line) => {
|
|
76
|
-
if (!line.trim())
|
|
77
|
-
return;
|
|
78
|
-
let event;
|
|
79
|
-
try {
|
|
80
|
-
event = JSON.parse(line);
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
if (typeof event === "object" && event !== null && "type" in event && "message" in event) {
|
|
86
|
-
const typedEvent = event;
|
|
87
|
-
// Accumulate text from message_update events
|
|
88
|
-
if (typedEvent.type === "message_update") {
|
|
89
|
-
const message = typedEvent.message;
|
|
90
|
-
if (message.role === "assistant" && Array.isArray(message.content)) {
|
|
91
|
-
for (const part of message.content) {
|
|
92
|
-
if (part.type === "text" && part.text) {
|
|
93
|
-
updateText.push(part.text);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// Extract final result from message_end, or fall back to accumulated update text
|
|
99
|
-
if (typedEvent.type === "message_end") {
|
|
100
|
-
const message = typedEvent.message;
|
|
101
|
-
if (message.role === "assistant" && Array.isArray(message.content)) {
|
|
102
|
-
const endText = [];
|
|
103
|
-
for (const part of message.content) {
|
|
104
|
-
if (part.type === "text" && part.text) {
|
|
105
|
-
endText.push(part.text);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (endText.length > 0) {
|
|
109
|
-
// message_end has the final text - use it
|
|
110
|
-
accumulatedText.length = 0;
|
|
111
|
-
accumulatedText.push(...endText);
|
|
112
|
-
}
|
|
113
|
-
else if (updateText.length > 0) {
|
|
114
|
-
// Fall back to accumulated update text
|
|
115
|
-
accumulatedText.length = 0;
|
|
116
|
-
accumulatedText.push(...updateText);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
if (typeof event === "object" &&
|
|
122
|
-
event !== null &&
|
|
123
|
-
"type" in event &&
|
|
124
|
-
"toolCallId" in event &&
|
|
125
|
-
"toolName" in event) {
|
|
126
|
-
const typedEvent = event;
|
|
127
|
-
if (typeof typedEvent.toolCallId !== "string" || typeof typedEvent.toolName !== "string") {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (typedEvent.type === "tool_execution_start") {
|
|
131
|
-
emitSpawnEvent(options, {
|
|
132
|
-
type: "tool_execution_start",
|
|
133
|
-
toolCallId: typedEvent.toolCallId,
|
|
134
|
-
toolName: typedEvent.toolName,
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
if (typedEvent.type === "tool_execution_end") {
|
|
138
|
-
emitSpawnEvent(options, {
|
|
139
|
-
type: "tool_execution_end",
|
|
140
|
-
toolCallId: typedEvent.toolCallId,
|
|
141
|
-
toolName: typedEvent.toolName,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
proc.stdout.on("data", (data) => {
|
|
147
|
-
buffer += data.toString();
|
|
148
|
-
const lines = buffer.split("\n");
|
|
149
|
-
buffer = lines.pop() ?? "";
|
|
150
|
-
for (const line of lines) {
|
|
151
|
-
processLine(line);
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
if (options.signal) {
|
|
155
|
-
const killProc = () => {
|
|
156
|
-
if (proc.pid) {
|
|
157
|
-
try {
|
|
158
|
-
proc.kill("SIGTERM");
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
/* ignore */
|
|
162
|
-
}
|
|
163
|
-
setTimeout(() => {
|
|
164
|
-
if (!proc.killed && proc.pid) {
|
|
165
|
-
try {
|
|
166
|
-
proc.kill("SIGKILL");
|
|
167
|
-
}
|
|
168
|
-
catch {
|
|
169
|
-
/* ignore */
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}, 5000);
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
if (options.signal.aborted) {
|
|
176
|
-
killProc();
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
options.signal.addEventListener("abort", killProc, { once: true });
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
const result = new Promise((resolve) => {
|
|
183
|
-
proc.on("close", (code) => {
|
|
184
|
-
if (buffer.trim()) {
|
|
185
|
-
processLine(buffer);
|
|
186
|
-
}
|
|
187
|
-
if (proc.pid) {
|
|
188
|
-
trackedPids.delete(proc.pid);
|
|
189
|
-
}
|
|
190
|
-
resolve({
|
|
191
|
-
text: accumulatedText.join(""),
|
|
192
|
-
exitCode: code ?? 0,
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
proc.on("error", () => {
|
|
196
|
-
if (proc.pid) {
|
|
197
|
-
trackedPids.delete(proc.pid);
|
|
198
|
-
}
|
|
199
|
-
resolve({
|
|
200
|
-
text: accumulatedText.join(""),
|
|
201
|
-
exitCode: 1,
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
return { process: proc, result };
|
|
206
|
-
}
|
|
207
|
-
//# sourceMappingURL=spawner.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spawner.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/background-task/spawner.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { APP_NAME } from \"../../../../config.js\";\nimport {\n\tAGENT_TYPE_ENV_VAR,\n\tDEPTH_ENV_VAR,\n\tMAX_SUBAGENT_DEPTH,\n\ttype SpawnEvent,\n\ttype SpawnedAgent,\n\ttype SpawnOptions,\n} from \"./types.js\";\n\nexport type { SpawnOptions, SpawnedAgent };\n\nexport function getPiInvocation(args: string[]): { command: string; args: string[] } {\n\tconst currentScript = process.argv[1];\n\tif (currentScript && fs.existsSync(currentScript)) {\n\t\treturn { command: process.execPath, args: [currentScript, ...args] };\n\t}\n\n\tconst execName = path.basename(process.execPath).toLowerCase();\n\tconst isGenericRuntime = /^(node|bun)(\\.exe)?$/.test(execName);\n\tif (!isGenericRuntime) {\n\t\treturn { command: process.execPath, args };\n\t}\n\n\treturn { command: APP_NAME, args };\n}\n\nconst trackedPids = new Set<number>();\n\nlet cleanupRegistered = false;\nfunction ensureCleanupRegistered(): void {\n\tif (cleanupRegistered) return;\n\tcleanupRegistered = true;\n\tprocess.on(\"exit\", () => {\n\t\tfor (const pid of trackedPids) {\n\t\t\ttry {\n\t\t\t\tprocess.kill(pid, \"SIGTERM\");\n\t\t\t} catch {\n\t\t\t\t/* process may already be dead */\n\t\t\t}\n\t\t}\n\t});\n}\n\ntype MessagePart = { type: string; text?: string };\ntype NdjsonMessage = { role: string; content: MessagePart[] };\n\nfunction emitSpawnEvent(options: SpawnOptions, event: SpawnEvent): void {\n\toptions.onEvent?.(event);\n}\n\nexport function spawnSubagent(options: SpawnOptions): SpawnedAgent {\n\tconst currentDepth = parseInt(process.env[DEPTH_ENV_VAR] ?? \"0\", 10);\n\tif (currentDepth >= MAX_SUBAGENT_DEPTH) {\n\t\tthrow new Error(`Maximum subagent depth (${MAX_SUBAGENT_DEPTH}) exceeded`);\n\t}\n\n\tconst args: string[] = [\"--mode\", \"json\", \"-p\", options.prompt];\n\n\tif (options.model) {\n\t\targs.push(\"--model\", options.model);\n\t}\n\n\tif (options.sessionPath) {\n\t\targs.push(\"--session\", options.sessionPath);\n\t}\n\n\tif (options.permissionFlag) {\n\t\targs.push(\"--permission\", options.permissionFlag);\n\t}\n\n\tconst invocation = getPiInvocation(args);\n\n\tconst childEnv: Record<string, string | undefined> = {\n\t\t...process.env,\n\t\t[DEPTH_ENV_VAR]: String(currentDepth + 1),\n\t\t...options.env,\n\t};\n\n\tif (options.agentType) {\n\t\tchildEnv[AGENT_TYPE_ENV_VAR] = options.agentType;\n\t}\n\n\tconst proc = spawn(invocation.command, invocation.args, {\n\t\tcwd: options.cwd,\n\t\tshell: false,\n\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\tenv: childEnv,\n\t});\n\n\tif (proc.pid) {\n\t\ttrackedPids.add(proc.pid);\n\t\tensureCleanupRegistered();\n\t}\n\n\tlet buffer = \"\";\n\tconst accumulatedText: string[] = [];\n\tconst updateText: string[] = [];\n\n\tconst processLine = (line: string): void => {\n\t\tif (!line.trim()) return;\n\t\tlet event: unknown;\n\t\ttry {\n\t\t\tevent = JSON.parse(line);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof event === \"object\" && event !== null && \"type\" in event && \"message\" in event) {\n\t\t\tconst typedEvent = event as { type: string; message: NdjsonMessage };\n\n\t\t\t// Accumulate text from message_update events\n\t\t\tif (typedEvent.type === \"message_update\") {\n\t\t\t\tconst message = typedEvent.message;\n\t\t\t\tif (message.role === \"assistant\" && Array.isArray(message.content)) {\n\t\t\t\t\tfor (const part of message.content) {\n\t\t\t\t\t\tif (part.type === \"text\" && part.text) {\n\t\t\t\t\t\t\tupdateText.push(part.text);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Extract final result from message_end, or fall back to accumulated update text\n\t\t\tif (typedEvent.type === \"message_end\") {\n\t\t\t\tconst message = typedEvent.message;\n\t\t\t\tif (message.role === \"assistant\" && Array.isArray(message.content)) {\n\t\t\t\t\tconst endText: string[] = [];\n\t\t\t\t\tfor (const part of message.content) {\n\t\t\t\t\t\tif (part.type === \"text\" && part.text) {\n\t\t\t\t\t\t\tendText.push(part.text);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (endText.length > 0) {\n\t\t\t\t\t\t// message_end has the final text - use it\n\t\t\t\t\t\taccumulatedText.length = 0;\n\t\t\t\t\t\taccumulatedText.push(...endText);\n\t\t\t\t\t} else if (updateText.length > 0) {\n\t\t\t\t\t\t// Fall back to accumulated update text\n\t\t\t\t\t\taccumulatedText.length = 0;\n\t\t\t\t\t\taccumulatedText.push(...updateText);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (\n\t\t\ttypeof event === \"object\" &&\n\t\t\tevent !== null &&\n\t\t\t\"type\" in event &&\n\t\t\t\"toolCallId\" in event &&\n\t\t\t\"toolName\" in event\n\t\t) {\n\t\t\tconst typedEvent = event as {\n\t\t\t\ttype: string;\n\t\t\t\ttoolCallId: unknown;\n\t\t\t\ttoolName: unknown;\n\t\t\t};\n\n\t\t\tif (typeof typedEvent.toolCallId !== \"string\" || typeof typedEvent.toolName !== \"string\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (typedEvent.type === \"tool_execution_start\") {\n\t\t\t\temitSpawnEvent(options, {\n\t\t\t\t\ttype: \"tool_execution_start\",\n\t\t\t\t\ttoolCallId: typedEvent.toolCallId,\n\t\t\t\t\ttoolName: typedEvent.toolName,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (typedEvent.type === \"tool_execution_end\") {\n\t\t\t\temitSpawnEvent(options, {\n\t\t\t\t\ttype: \"tool_execution_end\",\n\t\t\t\t\ttoolCallId: typedEvent.toolCallId,\n\t\t\t\t\ttoolName: typedEvent.toolName,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\n\tproc.stdout.on(\"data\", (data: Buffer) => {\n\t\tbuffer += data.toString();\n\t\tconst lines = buffer.split(\"\\n\");\n\t\tbuffer = lines.pop() ?? \"\";\n\t\tfor (const line of lines) {\n\t\t\tprocessLine(line);\n\t\t}\n\t});\n\n\tif (options.signal) {\n\t\tconst killProc = (): void => {\n\t\t\tif (proc.pid) {\n\t\t\t\ttry {\n\t\t\t\t\tproc.kill(\"SIGTERM\");\n\t\t\t\t} catch {\n\t\t\t\t\t/* ignore */\n\t\t\t\t}\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (!proc.killed && proc.pid) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tproc.kill(\"SIGKILL\");\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* ignore */\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, 5000);\n\t\t\t}\n\t\t};\n\n\t\tif (options.signal.aborted) {\n\t\t\tkillProc();\n\t\t} else {\n\t\t\toptions.signal.addEventListener(\"abort\", killProc, { once: true });\n\t\t}\n\t}\n\n\tconst result = new Promise<{ text: string; exitCode: number }>((resolve) => {\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (buffer.trim()) {\n\t\t\t\tprocessLine(buffer);\n\t\t\t}\n\n\t\t\tif (proc.pid) {\n\t\t\t\ttrackedPids.delete(proc.pid);\n\t\t\t}\n\n\t\t\tresolve({\n\t\t\t\ttext: accumulatedText.join(\"\"),\n\t\t\t\texitCode: code ?? 0,\n\t\t\t});\n\t\t});\n\n\t\tproc.on(\"error\", () => {\n\t\t\tif (proc.pid) {\n\t\t\t\ttrackedPids.delete(proc.pid);\n\t\t\t}\n\t\t\tresolve({\n\t\t\t\ttext: accumulatedText.join(\"\"),\n\t\t\t\texitCode: 1,\n\t\t\t});\n\t\t});\n\t});\n\n\treturn { process: proc, result };\n}\n"]}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Type } from "typebox";
|
|
2
|
-
import type { ExtensionAPI, ToolDefinition } from "../../types.js";
|
|
3
|
-
import type { BackgroundManager } from "./manager.js";
|
|
4
|
-
import type { spawnSubagent } from "./spawner.js";
|
|
5
|
-
type TaskToolDetails = {
|
|
6
|
-
agentType?: string;
|
|
7
|
-
model?: string;
|
|
8
|
-
activeToolNames?: string[];
|
|
9
|
-
};
|
|
10
|
-
declare const TaskToolParams: Type.TObject<{
|
|
11
|
-
description: Type.TString;
|
|
12
|
-
prompt: Type.TString;
|
|
13
|
-
run_in_background: Type.TBoolean;
|
|
14
|
-
session_id: Type.TOptional<Type.TString>;
|
|
15
|
-
model: Type.TOptional<Type.TString>;
|
|
16
|
-
agent_type: Type.TOptional<Type.TString>;
|
|
17
|
-
}>;
|
|
18
|
-
export declare function createTaskTool(manager: BackgroundManager, spawner: typeof spawnSubagent, pi: ExtensionAPI, agentDescriptions?: string): ToolDefinition<typeof TaskToolParams, TaskToolDetails>;
|
|
19
|
-
export {};
|
|
20
|
-
//# sourceMappingURL=task-tool.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"task-tool.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/background-task/task-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAoB,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlD,KAAK,eAAe,GAAG;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAmCF,QAAA,MAAM,cAAc;;;;;;;EAmBlB,CAAC;AA8BH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,OAAO,aAAa,EAC7B,EAAE,EAAE,YAAY,EAChB,iBAAiB,CAAC,EAAE,MAAM,GACxB,cAAc,CAAC,OAAO,cAAc,EAAE,eAAe,CAAC,CA+RxD","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport { Type } from \"typebox\";\nimport type { ExtensionAPI, ExtensionContext, ToolDefinition } from \"../../types.js\";\nimport type { BackgroundManager } from \"./manager.js\";\nimport type { spawnSubagent } from \"./spawner.js\";\nimport { DEPTH_ENV_VAR, MAX_SUBAGENT_DEPTH, TASK_ENTRY_TYPE } from \"./types.js\";\n\ntype TaskToolDetails = {\n\tagentType?: string;\n\tmodel?: string;\n\tactiveToolNames?: string[];\n};\n\nfunction buildTaskMetadata(args: {\n\tdescription: string;\n\trunInBackground: boolean;\n\tagentType?: string;\n\tmodel?: string;\n\tactiveToolNames?: string[];\n}): { headline: string; overview?: string } {\n\tconst overview = [\n\t\targs.agentType,\n\t\targs.model,\n\t\targs.activeToolNames && args.activeToolNames.length > 0 ? `tools: ${args.activeToolNames.join(\", \")}` : undefined,\n\t].filter((value): value is string => typeof value === \"string\" && value.length > 0);\n\n\treturn {\n\t\theadline: `${args.description}${args.runInBackground ? \" [async]\" : \" [sync]\"}`,\n\t\t...(overview.length > 0 ? { overview: overview.join(\" · \") } : {}),\n\t};\n}\n\nfunction buildTaskOverviewItems(details: TaskToolDetails | undefined): string[] {\n\tif (!details) {\n\t\treturn [];\n\t}\n\n\treturn [\n\t\tdetails.agentType,\n\t\tdetails.model,\n\t\tdetails.activeToolNames && details.activeToolNames.length > 0\n\t\t\t? `tools: ${details.activeToolNames.join(\", \")}`\n\t\t\t: undefined,\n\t].filter((value): value is string => typeof value === \"string\" && value.length > 0);\n}\n\nconst TaskToolParams = Type.Object({\n\tdescription: Type.String({\n\t\tdescription: \"A short (3-5 words) description of the task\",\n\t}),\n\tprompt: Type.String({\n\t\tdescription: \"The task for the agent to perform\",\n\t}),\n\trun_in_background: Type.Boolean({\n\t\tdescription:\n\t\t\t\"REQUIRED. true=async (returns task_id, system notifies on completion), false=sync (waits for result).\",\n\t}),\n\tsession_id: Type.Optional(Type.String({ description: \"Existing Task session to continue\" })),\n\tmodel: Type.Optional(Type.String({ description: \"Model to use for this task\" })),\n\tagent_type: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Agent type to use for this task (e.g. 'explore', 'general'). Determines available tools and permissions.\",\n\t\t}),\n\t),\n});\n\nfunction createErrorResult(text: string): {\n\tcontent: [{ type: \"text\"; text: string }];\n\tdetails: TaskToolDetails;\n\tisError: true;\n} {\n\treturn {\n\t\tcontent: [{ type: \"text\", text }],\n\t\tdetails: {},\n\t\tisError: true,\n\t};\n}\n\nfunction resolveModel(params: { model?: string }, ctx: ExtensionContext): string | undefined {\n\tif (params.model) {\n\t\treturn params.model;\n\t}\n\n\tif (!ctx.model) {\n\t\treturn undefined;\n\t}\n\n\treturn `${ctx.model.provider}/${ctx.model.id}`;\n}\n\nfunction isCancelledTask(manager: BackgroundManager, taskId: string): boolean {\n\treturn manager.getTask(taskId)?.status === \"cancelled\";\n}\n\nexport function createTaskTool(\n\tmanager: BackgroundManager,\n\tspawner: typeof spawnSubagent,\n\tpi: ExtensionAPI,\n\tagentDescriptions?: string,\n): ToolDefinition<typeof TaskToolParams, TaskToolDetails> {\n\tconst baseDescription = `Run a sub-agent in sync or async mode.\n\nSync mode (run_in_background=false): waits for the sub-agent to finish and returns its text output directly.\nAsync mode (run_in_background=true): starts the sub-agent, returns a task_id immediately. System sends a notification when done.\n\nsession_id is optional and continues an existing session when provided.\nmodel is optional and defaults to the current model.`;\n\n\tconst fullDescription = agentDescriptions\n\t\t? `${baseDescription}\\n\\nAvailable agent types:\\n${agentDescriptions}`\n\t\t: baseDescription;\n\n\tconst taskTool: ToolDefinition<typeof TaskToolParams, TaskToolDetails> = {\n\t\tname: \"task\",\n\t\tlabel: \"Task\",\n\t\tdescription: fullDescription,\n\t\tpromptSnippet:\n\t\t\t\"Run a sub-agent either synchronously for direct output or asynchronously for a background task_id.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use run_in_background=false when you need the sub-agent result in the same turn.\",\n\t\t\t\"Use run_in_background=true for parallel work. System notifies on completion via <system-reminder>.\",\n\t\t\t\"After launching a background task, do NOT call background_output - wait for the <system-reminder> notification first.\",\n\t\t\t\"Pass session_id to continue an existing sub-agent session.\",\n\t\t],\n\t\tparameters: TaskToolParams,\n\t\tasync execute(_toolCallId, params, signal, onUpdate, ctx) {\n\t\t\tif (!params.description.trim()) {\n\t\t\t\treturn createErrorResult(\"Error: description is required\");\n\t\t\t}\n\n\t\t\tconst currentDepth = Number.parseInt(process.env[DEPTH_ENV_VAR] ?? \"0\", 10);\n\t\t\tif (currentDepth >= MAX_SUBAGENT_DEPTH) {\n\t\t\t\treturn createErrorResult(`Error: max subagent depth (${MAX_SUBAGENT_DEPTH}) exceeded`);\n\t\t\t}\n\n\t\t\tconst model = resolveModel(params, ctx);\n\t\t\tconst taskDetails: TaskToolDetails = {\n\t\t\t\tagentType: params.agent_type,\n\t\t\t\tmodel,\n\t\t\t\tactiveToolNames: [],\n\t\t\t};\n\n\t\t\tconst permissionFlag =\n\t\t\t\ttypeof pi.getFlag === \"function\"\n\t\t\t\t\t? ((pi.getFlag(\"permission\") as string | undefined) ?? undefined)\n\t\t\t\t\t: undefined;\n\n\t\t\tif (!params.run_in_background) {\n\t\t\t\tconst spawned = spawner({\n\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\tcwd: ctx.cwd,\n\t\t\t\t\tmodel,\n\t\t\t\t\tagentType: params.agent_type,\n\t\t\t\t\tsessionPath: params.session_id,\n\t\t\t\t\tpermissionFlag: permissionFlag ?? undefined,\n\t\t\t\t\tsignal,\n\t\t\t\t});\n\t\t\t\tconst result = await spawned.result;\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: result.text || \"(no output)\" }],\n\t\t\t\t\tdetails: taskDetails,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet executeReturned = false;\n\t\t\ttry {\n\t\t\t\tconst task = manager.launch({\n\t\t\t\t\tdescription: params.description,\n\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\tmodel,\n\t\t\t\t\tagentType: params.agent_type,\n\t\t\t\t\tpid: undefined,\n\t\t\t\t\tsessionPath: params.session_id,\n\t\t\t\t\tactiveToolNames: [],\n\t\t\t\t\tcompletedAt: undefined,\n\t\t\t\t\tresult: undefined,\n\t\t\t\t\terror: undefined,\n\t\t\t\t\tparentSessionId: \"unknown\",\n\t\t\t\t});\n\n\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, task);\n\n\t\t\t\tconst spawned = spawner({\n\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\tcwd: ctx.cwd,\n\t\t\t\t\tmodel,\n\t\t\t\t\tagentType: params.agent_type,\n\t\t\t\t\tsessionPath: params.session_id,\n\t\t\t\t\tpermissionFlag: permissionFlag ?? undefined,\n\t\t\t\t\tsignal,\n\t\t\t\t\tonEvent: (() => {\n\t\t\t\t\t\tconst activeToolCalls = new Map<string, string>();\n\t\t\t\t\t\treturn (event) => {\n\t\t\t\t\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\t\t\t\t\tactiveToolCalls.set(event.toolCallId, event.toolName);\n\t\t\t\t\t\t\t} else if (event.type === \"tool_execution_end\") {\n\t\t\t\t\t\t\t\tactiveToolCalls.delete(event.toolCallId);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst currentTask = manager.getTask(task.id);\n\t\t\t\t\t\t\tif (!currentTask) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst activeToolNames = Array.from(activeToolCalls.values());\n\n\t\t\t\t\t\t\tmanager.updateTask(task.id, {\n\t\t\t\t\t\t\t\tactiveToolNames,\n\t\t\t\t\t\t\t\t...(activeToolCalls.size > 0 && currentTask.status === \"pending\" ? { status: \"running\" } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (!executeReturned) {\n\t\t\t\t\t\t\t\tonUpdate?.({\n\t\t\t\t\t\t\t\t\tcontent: [],\n\t\t\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\t\t\t...taskDetails,\n\t\t\t\t\t\t\t\t\t\tactiveToolNames,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst activeTask = manager.getTask(task.id);\n\t\t\t\t\t\t\tif (activeTask) {\n\t\t\t\t\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, activeTask);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t})(),\n\t\t\t\t});\n\n\t\t\t\tif (spawned.process.pid !== undefined) {\n\t\t\t\t\tmanager.updateTask(task.id, { pid: spawned.process.pid, status: \"running\" });\n\t\t\t\t\tonUpdate?.({ content: [], details: taskDetails });\n\t\t\t\t\tconst runningTask = manager.getTask(task.id);\n\t\t\t\t\tif (runningTask) {\n\t\t\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, runningTask);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tspawned.result\n\t\t\t\t\t.then((result) => {\n\t\t\t\t\t\tif (isCancelledTask(manager, task.id)) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmanager.updateTask(task.id, {\n\t\t\t\t\t\t\tstatus: result.exitCode === 0 ? \"completed\" : \"error\",\n\t\t\t\t\t\t\tcompletedAt: new Date(),\n\t\t\t\t\t\t\tactiveToolNames: [],\n\t\t\t\t\t\t\tresult: result.text,\n\t\t\t\t\t\t\terror: result.exitCode === 0 ? undefined : `Sub-agent exited with code ${result.exitCode}`,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst completedTask = manager.getTask(task.id);\n\t\t\t\t\t\tif (completedTask) {\n\t\t\t\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, completedTask);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpi.sendMessage(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcustomType: \"background-task.complete\",\n\t\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\t\ttext: [\n\t\t\t\t\t\t\t\t\t\t\t`Task ${task.id} completed: ${params.description}`,\n\t\t\t\t\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\t\t\t\t\"Result:\",\n\t\t\t\t\t\t\t\t\t\t\tresult.text || \"(no output)\",\n\t\t\t\t\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ triggerTurn: true, deliverAs: \"followUp\" },\n\t\t\t\t\t\t);\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\tif (isCancelledTask(manager, task.id)) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmanager.updateTask(task.id, {\n\t\t\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\t\t\tcompletedAt: new Date(),\n\t\t\t\t\t\t\tactiveToolNames: [],\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst erroredTask = manager.getTask(task.id);\n\t\t\t\t\t\tif (erroredTask) {\n\t\t\t\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, erroredTask);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\tpi.sendMessage(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcustomType: \"background-task.complete\",\n\t\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\t\ttext: [`Task ${task.id} failed: ${params.description}`, \"\", \"Error:\", errorMsg].join(\n\t\t\t\t\t\t\t\t\t\t\t\"\\n\",\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ triggerTurn: true, deliverAs: \"followUp\" },\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\n\t\t\t\texecuteReturned = true;\n\n\t\t\t\tconst sessionIdBlock = params.session_id\n\t\t\t\t\t? `\\n\\n<task_metadata>\\nsession_id: ${params.session_id}\\ntask_id: ${task.id}\\nbackground_task_id: ${task.id}\\n</task_metadata>\\n\\nto continue: task(session_id=\"${params.session_id}\", run_in_background=false, prompt=\"...\")`\n\t\t\t\t\t: `\\n\\n<task_metadata>\\ntask_id: ${task.id}\\nbackground_task_id: ${task.id}\\n</task_metadata>`;\n\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\",\n\t\t\t\t\t\t\ttext: `Background task launched.\n\nBackground Task ID: ${task.id}\nDescription: ${params.description}\nAgent: ${params.agent_type ?? \"default\"}\nStatus: ${task.status}\n\nSystem notifies on completion. Use \\`background_output\\` with task_id=\"${task.id}\" to check.\n\nDo NOT call background_output now. Wait for <system-reminder> notification first.${sessionIdBlock}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: taskDetails,\n\t\t\t\t};\n\t\t\t} catch (error: unknown) {\n\t\t\t\treturn createErrorResult(error instanceof Error ? error.message : String(error));\n\t\t\t}\n\t\t},\n\t\trenderCall(args, theme) {\n\t\t\tconst metadata = buildTaskMetadata({\n\t\t\t\tdescription: args.description,\n\t\t\t\trunInBackground: args.run_in_background,\n\t\t\t\tagentType: args.agent_type,\n\t\t\t\tmodel: args.model,\n\t\t\t});\n\t\t\treturn new Text(\n\t\t\t\t[\n\t\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(\"Task \")) + theme.fg(\"accent\", metadata.headline),\n\t\t\t\t\t...(metadata.overview ? [theme.fg(\"muted\", ` ${metadata.overview}`)] : []),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst firstContent = result.content[0];\n\t\t\tconst text = firstContent?.type === \"text\" ? firstContent.text : undefined;\n\t\t\tconst argDetails: TaskToolDetails = {\n\t\t\t\tagentType: context.args.agent_type,\n\t\t\t\tmodel: context.args.model,\n\t\t\t};\n\t\t\tconst callOverviewItems = new Set(buildTaskOverviewItems(argDetails));\n\t\t\tconst extraOverviewItems = buildTaskOverviewItems(result.details).filter(\n\t\t\t\t(item) => !callOverviewItems.has(item),\n\t\t\t);\n\t\t\tconst overview = extraOverviewItems.length > 0 ? extraOverviewItems.join(\" · \") : undefined;\n\n\t\t\tif (!text && !overview) {\n\t\t\t\treturn new Text(\"\", 0, 0);\n\t\t\t}\n\n\t\t\tif (options.isPartial && !text) {\n\t\t\t\treturn new Text(overview ? theme.fg(\"muted\", overview) : \"\", 0, 0);\n\t\t\t}\n\n\t\t\treturn new Text(\n\t\t\t\t[...(overview ? [theme.fg(\"muted\", overview)] : []), ...(text ? [theme.fg(\"muted\", text)] : [])].join(\n\t\t\t\t\t\"\\n\\n\",\n\t\t\t\t),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t},\n\t};\n\n\treturn taskTool;\n}\n"]}
|
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
2
|
-
import { Type } from "typebox";
|
|
3
|
-
import { DEPTH_ENV_VAR, MAX_SUBAGENT_DEPTH, TASK_ENTRY_TYPE } from "./types.js";
|
|
4
|
-
function buildTaskMetadata(args) {
|
|
5
|
-
const overview = [
|
|
6
|
-
args.agentType,
|
|
7
|
-
args.model,
|
|
8
|
-
args.activeToolNames && args.activeToolNames.length > 0 ? `tools: ${args.activeToolNames.join(", ")}` : undefined,
|
|
9
|
-
].filter((value) => typeof value === "string" && value.length > 0);
|
|
10
|
-
return {
|
|
11
|
-
headline: `${args.description}${args.runInBackground ? " [async]" : " [sync]"}`,
|
|
12
|
-
...(overview.length > 0 ? { overview: overview.join(" · ") } : {}),
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
function buildTaskOverviewItems(details) {
|
|
16
|
-
if (!details) {
|
|
17
|
-
return [];
|
|
18
|
-
}
|
|
19
|
-
return [
|
|
20
|
-
details.agentType,
|
|
21
|
-
details.model,
|
|
22
|
-
details.activeToolNames && details.activeToolNames.length > 0
|
|
23
|
-
? `tools: ${details.activeToolNames.join(", ")}`
|
|
24
|
-
: undefined,
|
|
25
|
-
].filter((value) => typeof value === "string" && value.length > 0);
|
|
26
|
-
}
|
|
27
|
-
const TaskToolParams = Type.Object({
|
|
28
|
-
description: Type.String({
|
|
29
|
-
description: "A short (3-5 words) description of the task",
|
|
30
|
-
}),
|
|
31
|
-
prompt: Type.String({
|
|
32
|
-
description: "The task for the agent to perform",
|
|
33
|
-
}),
|
|
34
|
-
run_in_background: Type.Boolean({
|
|
35
|
-
description: "REQUIRED. true=async (returns task_id, system notifies on completion), false=sync (waits for result).",
|
|
36
|
-
}),
|
|
37
|
-
session_id: Type.Optional(Type.String({ description: "Existing Task session to continue" })),
|
|
38
|
-
model: Type.Optional(Type.String({ description: "Model to use for this task" })),
|
|
39
|
-
agent_type: Type.Optional(Type.String({
|
|
40
|
-
description: "Agent type to use for this task (e.g. 'explore', 'general'). Determines available tools and permissions.",
|
|
41
|
-
})),
|
|
42
|
-
});
|
|
43
|
-
function createErrorResult(text) {
|
|
44
|
-
return {
|
|
45
|
-
content: [{ type: "text", text }],
|
|
46
|
-
details: {},
|
|
47
|
-
isError: true,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function resolveModel(params, ctx) {
|
|
51
|
-
if (params.model) {
|
|
52
|
-
return params.model;
|
|
53
|
-
}
|
|
54
|
-
if (!ctx.model) {
|
|
55
|
-
return undefined;
|
|
56
|
-
}
|
|
57
|
-
return `${ctx.model.provider}/${ctx.model.id}`;
|
|
58
|
-
}
|
|
59
|
-
function isCancelledTask(manager, taskId) {
|
|
60
|
-
return manager.getTask(taskId)?.status === "cancelled";
|
|
61
|
-
}
|
|
62
|
-
export function createTaskTool(manager, spawner, pi, agentDescriptions) {
|
|
63
|
-
const baseDescription = `Run a sub-agent in sync or async mode.
|
|
64
|
-
|
|
65
|
-
Sync mode (run_in_background=false): waits for the sub-agent to finish and returns its text output directly.
|
|
66
|
-
Async mode (run_in_background=true): starts the sub-agent, returns a task_id immediately. System sends a notification when done.
|
|
67
|
-
|
|
68
|
-
session_id is optional and continues an existing session when provided.
|
|
69
|
-
model is optional and defaults to the current model.`;
|
|
70
|
-
const fullDescription = agentDescriptions
|
|
71
|
-
? `${baseDescription}\n\nAvailable agent types:\n${agentDescriptions}`
|
|
72
|
-
: baseDescription;
|
|
73
|
-
const taskTool = {
|
|
74
|
-
name: "task",
|
|
75
|
-
label: "Task",
|
|
76
|
-
description: fullDescription,
|
|
77
|
-
promptSnippet: "Run a sub-agent either synchronously for direct output or asynchronously for a background task_id.",
|
|
78
|
-
promptGuidelines: [
|
|
79
|
-
"Use run_in_background=false when you need the sub-agent result in the same turn.",
|
|
80
|
-
"Use run_in_background=true for parallel work. System notifies on completion via <system-reminder>.",
|
|
81
|
-
"After launching a background task, do NOT call background_output - wait for the <system-reminder> notification first.",
|
|
82
|
-
"Pass session_id to continue an existing sub-agent session.",
|
|
83
|
-
],
|
|
84
|
-
parameters: TaskToolParams,
|
|
85
|
-
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
86
|
-
if (!params.description.trim()) {
|
|
87
|
-
return createErrorResult("Error: description is required");
|
|
88
|
-
}
|
|
89
|
-
const currentDepth = Number.parseInt(process.env[DEPTH_ENV_VAR] ?? "0", 10);
|
|
90
|
-
if (currentDepth >= MAX_SUBAGENT_DEPTH) {
|
|
91
|
-
return createErrorResult(`Error: max subagent depth (${MAX_SUBAGENT_DEPTH}) exceeded`);
|
|
92
|
-
}
|
|
93
|
-
const model = resolveModel(params, ctx);
|
|
94
|
-
const taskDetails = {
|
|
95
|
-
agentType: params.agent_type,
|
|
96
|
-
model,
|
|
97
|
-
activeToolNames: [],
|
|
98
|
-
};
|
|
99
|
-
const permissionFlag = typeof pi.getFlag === "function"
|
|
100
|
-
? (pi.getFlag("permission") ?? undefined)
|
|
101
|
-
: undefined;
|
|
102
|
-
if (!params.run_in_background) {
|
|
103
|
-
const spawned = spawner({
|
|
104
|
-
prompt: params.prompt,
|
|
105
|
-
cwd: ctx.cwd,
|
|
106
|
-
model,
|
|
107
|
-
agentType: params.agent_type,
|
|
108
|
-
sessionPath: params.session_id,
|
|
109
|
-
permissionFlag: permissionFlag ?? undefined,
|
|
110
|
-
signal,
|
|
111
|
-
});
|
|
112
|
-
const result = await spawned.result;
|
|
113
|
-
return {
|
|
114
|
-
content: [{ type: "text", text: result.text || "(no output)" }],
|
|
115
|
-
details: taskDetails,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
let executeReturned = false;
|
|
119
|
-
try {
|
|
120
|
-
const task = manager.launch({
|
|
121
|
-
description: params.description,
|
|
122
|
-
prompt: params.prompt,
|
|
123
|
-
model,
|
|
124
|
-
agentType: params.agent_type,
|
|
125
|
-
pid: undefined,
|
|
126
|
-
sessionPath: params.session_id,
|
|
127
|
-
activeToolNames: [],
|
|
128
|
-
completedAt: undefined,
|
|
129
|
-
result: undefined,
|
|
130
|
-
error: undefined,
|
|
131
|
-
parentSessionId: "unknown",
|
|
132
|
-
});
|
|
133
|
-
pi.appendEntry(TASK_ENTRY_TYPE, task);
|
|
134
|
-
const spawned = spawner({
|
|
135
|
-
prompt: params.prompt,
|
|
136
|
-
cwd: ctx.cwd,
|
|
137
|
-
model,
|
|
138
|
-
agentType: params.agent_type,
|
|
139
|
-
sessionPath: params.session_id,
|
|
140
|
-
permissionFlag: permissionFlag ?? undefined,
|
|
141
|
-
signal,
|
|
142
|
-
onEvent: (() => {
|
|
143
|
-
const activeToolCalls = new Map();
|
|
144
|
-
return (event) => {
|
|
145
|
-
if (event.type === "tool_execution_start") {
|
|
146
|
-
activeToolCalls.set(event.toolCallId, event.toolName);
|
|
147
|
-
}
|
|
148
|
-
else if (event.type === "tool_execution_end") {
|
|
149
|
-
activeToolCalls.delete(event.toolCallId);
|
|
150
|
-
}
|
|
151
|
-
const currentTask = manager.getTask(task.id);
|
|
152
|
-
if (!currentTask) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
const activeToolNames = Array.from(activeToolCalls.values());
|
|
156
|
-
manager.updateTask(task.id, {
|
|
157
|
-
activeToolNames,
|
|
158
|
-
...(activeToolCalls.size > 0 && currentTask.status === "pending" ? { status: "running" } : {}),
|
|
159
|
-
});
|
|
160
|
-
if (!executeReturned) {
|
|
161
|
-
onUpdate?.({
|
|
162
|
-
content: [],
|
|
163
|
-
details: {
|
|
164
|
-
...taskDetails,
|
|
165
|
-
activeToolNames,
|
|
166
|
-
},
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
const activeTask = manager.getTask(task.id);
|
|
170
|
-
if (activeTask) {
|
|
171
|
-
pi.appendEntry(TASK_ENTRY_TYPE, activeTask);
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
})(),
|
|
175
|
-
});
|
|
176
|
-
if (spawned.process.pid !== undefined) {
|
|
177
|
-
manager.updateTask(task.id, { pid: spawned.process.pid, status: "running" });
|
|
178
|
-
onUpdate?.({ content: [], details: taskDetails });
|
|
179
|
-
const runningTask = manager.getTask(task.id);
|
|
180
|
-
if (runningTask) {
|
|
181
|
-
pi.appendEntry(TASK_ENTRY_TYPE, runningTask);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
spawned.result
|
|
185
|
-
.then((result) => {
|
|
186
|
-
if (isCancelledTask(manager, task.id)) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
manager.updateTask(task.id, {
|
|
190
|
-
status: result.exitCode === 0 ? "completed" : "error",
|
|
191
|
-
completedAt: new Date(),
|
|
192
|
-
activeToolNames: [],
|
|
193
|
-
result: result.text,
|
|
194
|
-
error: result.exitCode === 0 ? undefined : `Sub-agent exited with code ${result.exitCode}`,
|
|
195
|
-
});
|
|
196
|
-
const completedTask = manager.getTask(task.id);
|
|
197
|
-
if (completedTask) {
|
|
198
|
-
pi.appendEntry(TASK_ENTRY_TYPE, completedTask);
|
|
199
|
-
}
|
|
200
|
-
pi.sendMessage({
|
|
201
|
-
customType: "background-task.complete",
|
|
202
|
-
display: true,
|
|
203
|
-
content: [
|
|
204
|
-
{
|
|
205
|
-
type: "text",
|
|
206
|
-
text: [
|
|
207
|
-
`Task ${task.id} completed: ${params.description}`,
|
|
208
|
-
"",
|
|
209
|
-
"Result:",
|
|
210
|
-
result.text || "(no output)",
|
|
211
|
-
].join("\n"),
|
|
212
|
-
},
|
|
213
|
-
],
|
|
214
|
-
}, { triggerTurn: true, deliverAs: "followUp" });
|
|
215
|
-
})
|
|
216
|
-
.catch((error) => {
|
|
217
|
-
if (isCancelledTask(manager, task.id)) {
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
manager.updateTask(task.id, {
|
|
221
|
-
status: "error",
|
|
222
|
-
completedAt: new Date(),
|
|
223
|
-
activeToolNames: [],
|
|
224
|
-
error: error instanceof Error ? error.message : String(error),
|
|
225
|
-
});
|
|
226
|
-
const erroredTask = manager.getTask(task.id);
|
|
227
|
-
if (erroredTask) {
|
|
228
|
-
pi.appendEntry(TASK_ENTRY_TYPE, erroredTask);
|
|
229
|
-
}
|
|
230
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
231
|
-
pi.sendMessage({
|
|
232
|
-
customType: "background-task.complete",
|
|
233
|
-
display: true,
|
|
234
|
-
content: [
|
|
235
|
-
{
|
|
236
|
-
type: "text",
|
|
237
|
-
text: [`Task ${task.id} failed: ${params.description}`, "", "Error:", errorMsg].join("\n"),
|
|
238
|
-
},
|
|
239
|
-
],
|
|
240
|
-
}, { triggerTurn: true, deliverAs: "followUp" });
|
|
241
|
-
});
|
|
242
|
-
executeReturned = true;
|
|
243
|
-
const sessionIdBlock = params.session_id
|
|
244
|
-
? `\n\n<task_metadata>\nsession_id: ${params.session_id}\ntask_id: ${task.id}\nbackground_task_id: ${task.id}\n</task_metadata>\n\nto continue: task(session_id="${params.session_id}", run_in_background=false, prompt="...")`
|
|
245
|
-
: `\n\n<task_metadata>\ntask_id: ${task.id}\nbackground_task_id: ${task.id}\n</task_metadata>`;
|
|
246
|
-
return {
|
|
247
|
-
content: [
|
|
248
|
-
{
|
|
249
|
-
type: "text",
|
|
250
|
-
text: `Background task launched.
|
|
251
|
-
|
|
252
|
-
Background Task ID: ${task.id}
|
|
253
|
-
Description: ${params.description}
|
|
254
|
-
Agent: ${params.agent_type ?? "default"}
|
|
255
|
-
Status: ${task.status}
|
|
256
|
-
|
|
257
|
-
System notifies on completion. Use \`background_output\` with task_id="${task.id}" to check.
|
|
258
|
-
|
|
259
|
-
Do NOT call background_output now. Wait for <system-reminder> notification first.${sessionIdBlock}`,
|
|
260
|
-
},
|
|
261
|
-
],
|
|
262
|
-
details: taskDetails,
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
catch (error) {
|
|
266
|
-
return createErrorResult(error instanceof Error ? error.message : String(error));
|
|
267
|
-
}
|
|
268
|
-
},
|
|
269
|
-
renderCall(args, theme) {
|
|
270
|
-
const metadata = buildTaskMetadata({
|
|
271
|
-
description: args.description,
|
|
272
|
-
runInBackground: args.run_in_background,
|
|
273
|
-
agentType: args.agent_type,
|
|
274
|
-
model: args.model,
|
|
275
|
-
});
|
|
276
|
-
return new Text([
|
|
277
|
-
theme.fg("toolTitle", theme.bold("Task ")) + theme.fg("accent", metadata.headline),
|
|
278
|
-
...(metadata.overview ? [theme.fg("muted", ` ${metadata.overview}`)] : []),
|
|
279
|
-
].join("\n"), 0, 0);
|
|
280
|
-
},
|
|
281
|
-
renderResult(result, options, theme, context) {
|
|
282
|
-
const firstContent = result.content[0];
|
|
283
|
-
const text = firstContent?.type === "text" ? firstContent.text : undefined;
|
|
284
|
-
const argDetails = {
|
|
285
|
-
agentType: context.args.agent_type,
|
|
286
|
-
model: context.args.model,
|
|
287
|
-
};
|
|
288
|
-
const callOverviewItems = new Set(buildTaskOverviewItems(argDetails));
|
|
289
|
-
const extraOverviewItems = buildTaskOverviewItems(result.details).filter((item) => !callOverviewItems.has(item));
|
|
290
|
-
const overview = extraOverviewItems.length > 0 ? extraOverviewItems.join(" · ") : undefined;
|
|
291
|
-
if (!text && !overview) {
|
|
292
|
-
return new Text("", 0, 0);
|
|
293
|
-
}
|
|
294
|
-
if (options.isPartial && !text) {
|
|
295
|
-
return new Text(overview ? theme.fg("muted", overview) : "", 0, 0);
|
|
296
|
-
}
|
|
297
|
-
return new Text([...(overview ? [theme.fg("muted", overview)] : []), ...(text ? [theme.fg("muted", text)] : [])].join("\n\n"), 0, 0);
|
|
298
|
-
},
|
|
299
|
-
};
|
|
300
|
-
return taskTool;
|
|
301
|
-
}
|
|
302
|
-
//# sourceMappingURL=task-tool.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"task-tool.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/background-task/task-tool.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport { Type } from \"typebox\";\nimport type { ExtensionAPI, ExtensionContext, ToolDefinition } from \"../../types.js\";\nimport type { BackgroundManager } from \"./manager.js\";\nimport type { spawnSubagent } from \"./spawner.js\";\nimport { DEPTH_ENV_VAR, MAX_SUBAGENT_DEPTH, TASK_ENTRY_TYPE } from \"./types.js\";\n\ntype TaskToolDetails = {\n\tagentType?: string;\n\tmodel?: string;\n\tactiveToolNames?: string[];\n};\n\nfunction buildTaskMetadata(args: {\n\tdescription: string;\n\trunInBackground: boolean;\n\tagentType?: string;\n\tmodel?: string;\n\tactiveToolNames?: string[];\n}): { headline: string; overview?: string } {\n\tconst overview = [\n\t\targs.agentType,\n\t\targs.model,\n\t\targs.activeToolNames && args.activeToolNames.length > 0 ? `tools: ${args.activeToolNames.join(\", \")}` : undefined,\n\t].filter((value): value is string => typeof value === \"string\" && value.length > 0);\n\n\treturn {\n\t\theadline: `${args.description}${args.runInBackground ? \" [async]\" : \" [sync]\"}`,\n\t\t...(overview.length > 0 ? { overview: overview.join(\" · \") } : {}),\n\t};\n}\n\nfunction buildTaskOverviewItems(details: TaskToolDetails | undefined): string[] {\n\tif (!details) {\n\t\treturn [];\n\t}\n\n\treturn [\n\t\tdetails.agentType,\n\t\tdetails.model,\n\t\tdetails.activeToolNames && details.activeToolNames.length > 0\n\t\t\t? `tools: ${details.activeToolNames.join(\", \")}`\n\t\t\t: undefined,\n\t].filter((value): value is string => typeof value === \"string\" && value.length > 0);\n}\n\nconst TaskToolParams = Type.Object({\n\tdescription: Type.String({\n\t\tdescription: \"A short (3-5 words) description of the task\",\n\t}),\n\tprompt: Type.String({\n\t\tdescription: \"The task for the agent to perform\",\n\t}),\n\trun_in_background: Type.Boolean({\n\t\tdescription:\n\t\t\t\"REQUIRED. true=async (returns task_id, system notifies on completion), false=sync (waits for result).\",\n\t}),\n\tsession_id: Type.Optional(Type.String({ description: \"Existing Task session to continue\" })),\n\tmodel: Type.Optional(Type.String({ description: \"Model to use for this task\" })),\n\tagent_type: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Agent type to use for this task (e.g. 'explore', 'general'). Determines available tools and permissions.\",\n\t\t}),\n\t),\n});\n\nfunction createErrorResult(text: string): {\n\tcontent: [{ type: \"text\"; text: string }];\n\tdetails: TaskToolDetails;\n\tisError: true;\n} {\n\treturn {\n\t\tcontent: [{ type: \"text\", text }],\n\t\tdetails: {},\n\t\tisError: true,\n\t};\n}\n\nfunction resolveModel(params: { model?: string }, ctx: ExtensionContext): string | undefined {\n\tif (params.model) {\n\t\treturn params.model;\n\t}\n\n\tif (!ctx.model) {\n\t\treturn undefined;\n\t}\n\n\treturn `${ctx.model.provider}/${ctx.model.id}`;\n}\n\nfunction isCancelledTask(manager: BackgroundManager, taskId: string): boolean {\n\treturn manager.getTask(taskId)?.status === \"cancelled\";\n}\n\nexport function createTaskTool(\n\tmanager: BackgroundManager,\n\tspawner: typeof spawnSubagent,\n\tpi: ExtensionAPI,\n\tagentDescriptions?: string,\n): ToolDefinition<typeof TaskToolParams, TaskToolDetails> {\n\tconst baseDescription = `Run a sub-agent in sync or async mode.\n\nSync mode (run_in_background=false): waits for the sub-agent to finish and returns its text output directly.\nAsync mode (run_in_background=true): starts the sub-agent, returns a task_id immediately. System sends a notification when done.\n\nsession_id is optional and continues an existing session when provided.\nmodel is optional and defaults to the current model.`;\n\n\tconst fullDescription = agentDescriptions\n\t\t? `${baseDescription}\\n\\nAvailable agent types:\\n${agentDescriptions}`\n\t\t: baseDescription;\n\n\tconst taskTool: ToolDefinition<typeof TaskToolParams, TaskToolDetails> = {\n\t\tname: \"task\",\n\t\tlabel: \"Task\",\n\t\tdescription: fullDescription,\n\t\tpromptSnippet:\n\t\t\t\"Run a sub-agent either synchronously for direct output or asynchronously for a background task_id.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use run_in_background=false when you need the sub-agent result in the same turn.\",\n\t\t\t\"Use run_in_background=true for parallel work. System notifies on completion via <system-reminder>.\",\n\t\t\t\"After launching a background task, do NOT call background_output - wait for the <system-reminder> notification first.\",\n\t\t\t\"Pass session_id to continue an existing sub-agent session.\",\n\t\t],\n\t\tparameters: TaskToolParams,\n\t\tasync execute(_toolCallId, params, signal, onUpdate, ctx) {\n\t\t\tif (!params.description.trim()) {\n\t\t\t\treturn createErrorResult(\"Error: description is required\");\n\t\t\t}\n\n\t\t\tconst currentDepth = Number.parseInt(process.env[DEPTH_ENV_VAR] ?? \"0\", 10);\n\t\t\tif (currentDepth >= MAX_SUBAGENT_DEPTH) {\n\t\t\t\treturn createErrorResult(`Error: max subagent depth (${MAX_SUBAGENT_DEPTH}) exceeded`);\n\t\t\t}\n\n\t\t\tconst model = resolveModel(params, ctx);\n\t\t\tconst taskDetails: TaskToolDetails = {\n\t\t\t\tagentType: params.agent_type,\n\t\t\t\tmodel,\n\t\t\t\tactiveToolNames: [],\n\t\t\t};\n\n\t\t\tconst permissionFlag =\n\t\t\t\ttypeof pi.getFlag === \"function\"\n\t\t\t\t\t? ((pi.getFlag(\"permission\") as string | undefined) ?? undefined)\n\t\t\t\t\t: undefined;\n\n\t\t\tif (!params.run_in_background) {\n\t\t\t\tconst spawned = spawner({\n\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\tcwd: ctx.cwd,\n\t\t\t\t\tmodel,\n\t\t\t\t\tagentType: params.agent_type,\n\t\t\t\t\tsessionPath: params.session_id,\n\t\t\t\t\tpermissionFlag: permissionFlag ?? undefined,\n\t\t\t\t\tsignal,\n\t\t\t\t});\n\t\t\t\tconst result = await spawned.result;\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: result.text || \"(no output)\" }],\n\t\t\t\t\tdetails: taskDetails,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet executeReturned = false;\n\t\t\ttry {\n\t\t\t\tconst task = manager.launch({\n\t\t\t\t\tdescription: params.description,\n\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\tmodel,\n\t\t\t\t\tagentType: params.agent_type,\n\t\t\t\t\tpid: undefined,\n\t\t\t\t\tsessionPath: params.session_id,\n\t\t\t\t\tactiveToolNames: [],\n\t\t\t\t\tcompletedAt: undefined,\n\t\t\t\t\tresult: undefined,\n\t\t\t\t\terror: undefined,\n\t\t\t\t\tparentSessionId: \"unknown\",\n\t\t\t\t});\n\n\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, task);\n\n\t\t\t\tconst spawned = spawner({\n\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\tcwd: ctx.cwd,\n\t\t\t\t\tmodel,\n\t\t\t\t\tagentType: params.agent_type,\n\t\t\t\t\tsessionPath: params.session_id,\n\t\t\t\t\tpermissionFlag: permissionFlag ?? undefined,\n\t\t\t\t\tsignal,\n\t\t\t\t\tonEvent: (() => {\n\t\t\t\t\t\tconst activeToolCalls = new Map<string, string>();\n\t\t\t\t\t\treturn (event) => {\n\t\t\t\t\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\t\t\t\t\tactiveToolCalls.set(event.toolCallId, event.toolName);\n\t\t\t\t\t\t\t} else if (event.type === \"tool_execution_end\") {\n\t\t\t\t\t\t\t\tactiveToolCalls.delete(event.toolCallId);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst currentTask = manager.getTask(task.id);\n\t\t\t\t\t\t\tif (!currentTask) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst activeToolNames = Array.from(activeToolCalls.values());\n\n\t\t\t\t\t\t\tmanager.updateTask(task.id, {\n\t\t\t\t\t\t\t\tactiveToolNames,\n\t\t\t\t\t\t\t\t...(activeToolCalls.size > 0 && currentTask.status === \"pending\" ? { status: \"running\" } : {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (!executeReturned) {\n\t\t\t\t\t\t\t\tonUpdate?.({\n\t\t\t\t\t\t\t\t\tcontent: [],\n\t\t\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\t\t\t...taskDetails,\n\t\t\t\t\t\t\t\t\t\tactiveToolNames,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst activeTask = manager.getTask(task.id);\n\t\t\t\t\t\t\tif (activeTask) {\n\t\t\t\t\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, activeTask);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t})(),\n\t\t\t\t});\n\n\t\t\t\tif (spawned.process.pid !== undefined) {\n\t\t\t\t\tmanager.updateTask(task.id, { pid: spawned.process.pid, status: \"running\" });\n\t\t\t\t\tonUpdate?.({ content: [], details: taskDetails });\n\t\t\t\t\tconst runningTask = manager.getTask(task.id);\n\t\t\t\t\tif (runningTask) {\n\t\t\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, runningTask);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tspawned.result\n\t\t\t\t\t.then((result) => {\n\t\t\t\t\t\tif (isCancelledTask(manager, task.id)) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmanager.updateTask(task.id, {\n\t\t\t\t\t\t\tstatus: result.exitCode === 0 ? \"completed\" : \"error\",\n\t\t\t\t\t\t\tcompletedAt: new Date(),\n\t\t\t\t\t\t\tactiveToolNames: [],\n\t\t\t\t\t\t\tresult: result.text,\n\t\t\t\t\t\t\terror: result.exitCode === 0 ? undefined : `Sub-agent exited with code ${result.exitCode}`,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst completedTask = manager.getTask(task.id);\n\t\t\t\t\t\tif (completedTask) {\n\t\t\t\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, completedTask);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpi.sendMessage(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcustomType: \"background-task.complete\",\n\t\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\t\ttext: [\n\t\t\t\t\t\t\t\t\t\t\t`Task ${task.id} completed: ${params.description}`,\n\t\t\t\t\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\t\t\t\t\"Result:\",\n\t\t\t\t\t\t\t\t\t\t\tresult.text || \"(no output)\",\n\t\t\t\t\t\t\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ triggerTurn: true, deliverAs: \"followUp\" },\n\t\t\t\t\t\t);\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\tif (isCancelledTask(manager, task.id)) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmanager.updateTask(task.id, {\n\t\t\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\t\t\tcompletedAt: new Date(),\n\t\t\t\t\t\t\tactiveToolNames: [],\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst erroredTask = manager.getTask(task.id);\n\t\t\t\t\t\tif (erroredTask) {\n\t\t\t\t\t\t\tpi.appendEntry(TASK_ENTRY_TYPE, erroredTask);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\tpi.sendMessage(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcustomType: \"background-task.complete\",\n\t\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\t\ttext: [`Task ${task.id} failed: ${params.description}`, \"\", \"Error:\", errorMsg].join(\n\t\t\t\t\t\t\t\t\t\t\t\"\\n\",\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ triggerTurn: true, deliverAs: \"followUp\" },\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\n\t\t\t\texecuteReturned = true;\n\n\t\t\t\tconst sessionIdBlock = params.session_id\n\t\t\t\t\t? `\\n\\n<task_metadata>\\nsession_id: ${params.session_id}\\ntask_id: ${task.id}\\nbackground_task_id: ${task.id}\\n</task_metadata>\\n\\nto continue: task(session_id=\"${params.session_id}\", run_in_background=false, prompt=\"...\")`\n\t\t\t\t\t: `\\n\\n<task_metadata>\\ntask_id: ${task.id}\\nbackground_task_id: ${task.id}\\n</task_metadata>`;\n\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\",\n\t\t\t\t\t\t\ttext: `Background task launched.\n\nBackground Task ID: ${task.id}\nDescription: ${params.description}\nAgent: ${params.agent_type ?? \"default\"}\nStatus: ${task.status}\n\nSystem notifies on completion. Use \\`background_output\\` with task_id=\"${task.id}\" to check.\n\nDo NOT call background_output now. Wait for <system-reminder> notification first.${sessionIdBlock}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: taskDetails,\n\t\t\t\t};\n\t\t\t} catch (error: unknown) {\n\t\t\t\treturn createErrorResult(error instanceof Error ? error.message : String(error));\n\t\t\t}\n\t\t},\n\t\trenderCall(args, theme) {\n\t\t\tconst metadata = buildTaskMetadata({\n\t\t\t\tdescription: args.description,\n\t\t\t\trunInBackground: args.run_in_background,\n\t\t\t\tagentType: args.agent_type,\n\t\t\t\tmodel: args.model,\n\t\t\t});\n\t\t\treturn new Text(\n\t\t\t\t[\n\t\t\t\t\ttheme.fg(\"toolTitle\", theme.bold(\"Task \")) + theme.fg(\"accent\", metadata.headline),\n\t\t\t\t\t...(metadata.overview ? [theme.fg(\"muted\", ` ${metadata.overview}`)] : []),\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst firstContent = result.content[0];\n\t\t\tconst text = firstContent?.type === \"text\" ? firstContent.text : undefined;\n\t\t\tconst argDetails: TaskToolDetails = {\n\t\t\t\tagentType: context.args.agent_type,\n\t\t\t\tmodel: context.args.model,\n\t\t\t};\n\t\t\tconst callOverviewItems = new Set(buildTaskOverviewItems(argDetails));\n\t\t\tconst extraOverviewItems = buildTaskOverviewItems(result.details).filter(\n\t\t\t\t(item) => !callOverviewItems.has(item),\n\t\t\t);\n\t\t\tconst overview = extraOverviewItems.length > 0 ? extraOverviewItems.join(\" · \") : undefined;\n\n\t\t\tif (!text && !overview) {\n\t\t\t\treturn new Text(\"\", 0, 0);\n\t\t\t}\n\n\t\t\tif (options.isPartial && !text) {\n\t\t\t\treturn new Text(overview ? theme.fg(\"muted\", overview) : \"\", 0, 0);\n\t\t\t}\n\n\t\t\treturn new Text(\n\t\t\t\t[...(overview ? [theme.fg(\"muted\", overview)] : []), ...(text ? [theme.fg(\"muted\", text)] : [])].join(\n\t\t\t\t\t\"\\n\\n\",\n\t\t\t\t),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t},\n\t};\n\n\treturn taskTool;\n}\n"]}
|