@astralyn/pi 0.81.1-1 → 0.82.0

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 (185) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +690 -677
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +1 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/config-selector.d.ts.map +1 -1
  7. package/dist/cli/config-selector.js +1 -1
  8. package/dist/cli/config-selector.js.map +1 -1
  9. package/dist/cli/startup-ui.d.ts.map +1 -1
  10. package/dist/cli/startup-ui.js +1 -1
  11. package/dist/cli/startup-ui.js.map +1 -1
  12. package/dist/cli.js +0 -0
  13. package/dist/core/agent-session.d.ts +11 -0
  14. package/dist/core/agent-session.d.ts.map +1 -1
  15. package/dist/core/agent-session.js +7 -8
  16. package/dist/core/agent-session.js.map +1 -1
  17. package/dist/core/compaction/compaction.d.ts.map +1 -1
  18. package/dist/core/compaction/compaction.js +11 -3
  19. package/dist/core/compaction/compaction.js.map +1 -1
  20. package/dist/core/extensions/runner.d.ts.map +1 -1
  21. package/dist/core/extensions/runner.js +4 -0
  22. package/dist/core/extensions/runner.js.map +1 -1
  23. package/dist/core/extensions/types.d.ts +9 -1
  24. package/dist/core/extensions/types.d.ts.map +1 -1
  25. package/dist/core/extensions/types.js.map +1 -1
  26. package/dist/core/model-config.d.ts +30 -0
  27. package/dist/core/model-config.d.ts.map +1 -1
  28. package/dist/core/model-config.js +6 -0
  29. package/dist/core/model-config.js.map +1 -1
  30. package/dist/core/model-registry.d.ts.map +1 -1
  31. package/dist/core/model-registry.js +2 -2
  32. package/dist/core/model-registry.js.map +1 -1
  33. package/dist/core/model-resolver.d.ts.map +1 -1
  34. package/dist/core/model-resolver.js +7 -0
  35. package/dist/core/model-resolver.js.map +1 -1
  36. package/dist/core/model-runtime.d.ts +0 -1
  37. package/dist/core/model-runtime.d.ts.map +1 -1
  38. package/dist/core/model-runtime.js +3 -5
  39. package/dist/core/model-runtime.js.map +1 -1
  40. package/dist/core/remote-catalog-provider.d.ts +1 -1
  41. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  42. package/dist/core/remote-catalog-provider.js +5 -10
  43. package/dist/core/remote-catalog-provider.js.map +1 -1
  44. package/dist/core/settings-manager.d.ts +1 -1
  45. package/dist/core/settings-manager.d.ts.map +1 -1
  46. package/dist/core/settings-manager.js.map +1 -1
  47. package/dist/core/system-prompt.d.ts.map +1 -1
  48. package/dist/core/system-prompt.js +1 -1
  49. package/dist/core/system-prompt.js.map +1 -1
  50. package/dist/core/tools/bash.d.ts +2 -1
  51. package/dist/core/tools/bash.d.ts.map +1 -1
  52. package/dist/core/tools/bash.js +114 -24
  53. package/dist/core/tools/bash.js.map +1 -1
  54. package/dist/core/tools/find.d.ts.map +1 -1
  55. package/dist/core/tools/find.js +1 -0
  56. package/dist/core/tools/find.js.map +1 -1
  57. package/dist/core/tools/read.d.ts.map +1 -1
  58. package/dist/core/tools/read.js +4 -3
  59. package/dist/core/tools/read.js.map +1 -1
  60. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  61. package/dist/core/tools/tool-definition-wrapper.js +5 -1
  62. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  63. package/dist/extensions/index.d.ts.map +1 -1
  64. package/dist/extensions/index.js +2 -0
  65. package/dist/extensions/index.js.map +1 -1
  66. package/dist/extensions/llama/provider.d.ts.map +1 -1
  67. package/dist/extensions/llama/provider.js +1 -2
  68. package/dist/extensions/llama/provider.js.map +1 -1
  69. package/dist/extensions/subagent/activity.d.ts +16 -0
  70. package/dist/extensions/subagent/activity.d.ts.map +1 -0
  71. package/dist/extensions/subagent/activity.js +150 -0
  72. package/dist/extensions/subagent/activity.js.map +1 -0
  73. package/dist/extensions/subagent/agents.d.ts +7 -0
  74. package/dist/extensions/subagent/agents.d.ts.map +1 -0
  75. package/dist/extensions/subagent/agents.js +218 -0
  76. package/dist/extensions/subagent/agents.js.map +1 -0
  77. package/dist/extensions/subagent/constants.d.ts +22 -0
  78. package/dist/extensions/subagent/constants.d.ts.map +1 -0
  79. package/dist/extensions/subagent/constants.js +32 -0
  80. package/dist/extensions/subagent/constants.js.map +1 -0
  81. package/dist/extensions/subagent/index.d.ts +3 -0
  82. package/dist/extensions/subagent/index.d.ts.map +1 -0
  83. package/dist/extensions/subagent/index.js +249 -0
  84. package/dist/extensions/subagent/index.js.map +1 -0
  85. package/dist/extensions/subagent/picker.d.ts +31 -0
  86. package/dist/extensions/subagent/picker.d.ts.map +1 -0
  87. package/dist/extensions/subagent/picker.js +116 -0
  88. package/dist/extensions/subagent/picker.js.map +1 -0
  89. package/dist/extensions/subagent/render.d.ts +8 -0
  90. package/dist/extensions/subagent/render.d.ts.map +1 -0
  91. package/dist/extensions/subagent/render.js +322 -0
  92. package/dist/extensions/subagent/render.js.map +1 -0
  93. package/dist/extensions/subagent/resolve.d.ts +16 -0
  94. package/dist/extensions/subagent/resolve.d.ts.map +1 -0
  95. package/dist/extensions/subagent/resolve.js +103 -0
  96. package/dist/extensions/subagent/resolve.js.map +1 -0
  97. package/dist/extensions/subagent/runner.d.ts +30 -0
  98. package/dist/extensions/subagent/runner.d.ts.map +1 -0
  99. package/dist/extensions/subagent/runner.js +355 -0
  100. package/dist/extensions/subagent/runner.js.map +1 -0
  101. package/dist/extensions/subagent/schema.d.ts +28 -0
  102. package/dist/extensions/subagent/schema.d.ts.map +1 -0
  103. package/dist/extensions/subagent/schema.js +33 -0
  104. package/dist/extensions/subagent/schema.js.map +1 -0
  105. package/dist/extensions/subagent/sdk-runner.d.ts +14 -0
  106. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -0
  107. package/dist/extensions/subagent/sdk-runner.js +210 -0
  108. package/dist/extensions/subagent/sdk-runner.js.map +1 -0
  109. package/dist/extensions/subagent/settings.d.ts +9 -0
  110. package/dist/extensions/subagent/settings.d.ts.map +1 -0
  111. package/dist/extensions/subagent/settings.js +131 -0
  112. package/dist/extensions/subagent/settings.js.map +1 -0
  113. package/dist/extensions/subagent/types.d.ts +99 -0
  114. package/dist/extensions/subagent/types.d.ts.map +1 -0
  115. package/dist/extensions/subagent/types.js +2 -0
  116. package/dist/extensions/subagent/types.js.map +1 -0
  117. package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
  118. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  119. package/dist/modes/interactive/components/extension-editor.js +16 -46
  120. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  121. package/dist/modes/interactive/components/index.d.ts +1 -0
  122. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  123. package/dist/modes/interactive/components/index.js +1 -0
  124. package/dist/modes/interactive/components/index.js.map +1 -1
  125. package/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  126. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  127. package/dist/modes/interactive/components/tool-execution.js +25 -4
  128. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  129. package/dist/modes/interactive/components/tool-group.d.ts +16 -0
  130. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -0
  131. package/dist/modes/interactive/components/tool-group.js +64 -0
  132. package/dist/modes/interactive/components/tool-group.js.map +1 -0
  133. package/dist/modes/interactive/external-editor.d.ts +12 -0
  134. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  135. package/dist/modes/interactive/external-editor.js +37 -0
  136. package/dist/modes/interactive/external-editor.js.map +1 -0
  137. package/dist/modes/interactive/interactive-mode.d.ts +3 -1
  138. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  139. package/dist/modes/interactive/interactive-mode.js +61 -62
  140. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  141. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  142. package/dist/modes/rpc/rpc-mode.js +1 -0
  143. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  144. package/dist/rpc-entry.js +0 -0
  145. package/dist/utils/clipboard.d.ts.map +1 -1
  146. package/dist/utils/clipboard.js +19 -8
  147. package/dist/utils/clipboard.js.map +1 -1
  148. package/dist/utils/version-check.d.ts.map +1 -1
  149. package/dist/utils/version-check.js +3 -1
  150. package/dist/utils/version-check.js.map +1 -1
  151. package/docs/compaction.md +401 -401
  152. package/docs/containerization.md +111 -111
  153. package/docs/custom-provider.md +766 -763
  154. package/docs/environment-variables.md +88 -0
  155. package/docs/extensions.md +2961 -2953
  156. package/docs/index.md +80 -77
  157. package/docs/models.md +6 -2
  158. package/docs/packages.md +228 -228
  159. package/docs/providers.md +8 -1
  160. package/docs/quickstart.md +165 -165
  161. package/docs/rpc.md +1576 -1559
  162. package/docs/sdk.md +1186 -1186
  163. package/docs/session-format.md +436 -436
  164. package/docs/settings.md +1 -1
  165. package/docs/termux.md +127 -127
  166. package/docs/tui.md +942 -942
  167. package/docs/usage.md +0 -13
  168. package/examples/extensions/README.md +213 -213
  169. package/examples/extensions/custom-compaction.ts +3 -0
  170. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  171. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  172. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  173. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  174. package/examples/extensions/doom-overlay/doom/build.sh +0 -0
  175. package/examples/extensions/gondolin/package-lock.json +2 -2
  176. package/examples/extensions/gondolin/package.json +1 -1
  177. package/examples/extensions/handoff.ts +9 -1
  178. package/examples/extensions/sandbox/package-lock.json +2 -2
  179. package/examples/extensions/sandbox/package.json +1 -1
  180. package/examples/extensions/summarize.ts +3 -0
  181. package/examples/extensions/with-deps/package-lock.json +2 -2
  182. package/examples/extensions/with-deps/package.json +1 -1
  183. package/examples/sdk/README.md +140 -140
  184. package/npm-shrinkwrap.json +16 -15
  185. package/package.json +10 -4
@@ -0,0 +1,355 @@
1
+ import { boundText, emptyUsage, mergeUsage, toNestedUsage } from "./activity.js";
2
+ import { CHAIN_HANDOFF_LIMIT, DETAILS_ACTIVITY_LIMIT, DETAILS_OUTPUT_LIMIT, ERROR_TEXT_LIMIT, MAX_CONCURRENCY, MAX_TASKS, PARALLEL_OUTPUT_LIMIT, PARALLEL_TASK_OUTPUT_LIMIT, SINGLE_OUTPUT_LIMIT, } from "./constants.js";
3
+ import { resolveSubagentTask } from "./resolve.js";
4
+ import { runSdkTask } from "./sdk-runner.js";
5
+ const EMPTY_OUTPUT = "(Subagent completed but returned no output.)";
6
+ export class ConcurrencyGate {
7
+ active = 0;
8
+ waiters = [];
9
+ limit;
10
+ constructor(limit = MAX_CONCURRENCY) {
11
+ this.limit = limit;
12
+ }
13
+ acquire(signal) {
14
+ if (signal?.aborted)
15
+ return Promise.reject(new Error("Subagent was aborted while queued."));
16
+ if (this.active < this.limit) {
17
+ this.active++;
18
+ return Promise.resolve(() => this.release());
19
+ }
20
+ return new Promise((resolve, reject) => {
21
+ const waiter = { resolve, reject, signal };
22
+ if (signal) {
23
+ waiter.abortListener = () => {
24
+ const index = this.waiters.indexOf(waiter);
25
+ if (index >= 0)
26
+ this.waiters.splice(index, 1);
27
+ reject(new Error("Subagent was aborted while queued."));
28
+ };
29
+ signal.addEventListener("abort", waiter.abortListener, { once: true });
30
+ }
31
+ this.waiters.push(waiter);
32
+ });
33
+ }
34
+ release() {
35
+ this.active = Math.max(0, this.active - 1);
36
+ while (this.waiters.length > 0) {
37
+ const waiter = this.waiters.shift();
38
+ if (!waiter)
39
+ return;
40
+ if (waiter.signal?.aborted) {
41
+ waiter.abortListener?.();
42
+ continue;
43
+ }
44
+ waiter.signal?.removeEventListener("abort", waiter.abortListener);
45
+ this.active++;
46
+ waiter.resolve(() => this.release());
47
+ return;
48
+ }
49
+ }
50
+ }
51
+ function runId(index) {
52
+ return `subagent-${index + 1}`;
53
+ }
54
+ function createRun(task, index, step) {
55
+ return {
56
+ id: runId(index),
57
+ agent: task.agent.name,
58
+ agentSource: task.agent.source,
59
+ description: task.description,
60
+ prompt: task.prompt,
61
+ cwd: task.cwd,
62
+ model: `${task.model.provider}/${task.model.id}`,
63
+ thinking: task.thinking,
64
+ status: "queued",
65
+ activities: [],
66
+ liveText: "",
67
+ finalOutput: "",
68
+ usage: emptyUsage(),
69
+ step,
70
+ };
71
+ }
72
+ function aggregateUsage(runs) {
73
+ const usage = emptyUsage();
74
+ for (const run of runs)
75
+ mergeUsage(usage, run.usage);
76
+ return usage;
77
+ }
78
+ function detailsSize(details) {
79
+ return Buffer.byteLength(JSON.stringify(details), "utf8");
80
+ }
81
+ export function boundSubagentDetails(details) {
82
+ const perRunBudget = Math.max(1_024, Math.floor((DETAILS_OUTPUT_LIMIT - 8 * 1024) / Math.max(1, details.runs.length)));
83
+ const outputLimit = Math.min(SINGLE_OUTPUT_LIMIT, Math.max(1_024, perRunBudget - 7 * 1024));
84
+ const bounded = {
85
+ ...details,
86
+ runs: details.runs.map((run) => ({
87
+ ...run,
88
+ prompt: boundText(run.prompt, 1_024),
89
+ cwd: boundText(run.cwd, 1_024),
90
+ currentActivity: run.currentActivity ? boundText(run.currentActivity, 512) : undefined,
91
+ activities: run.activities.slice(-DETAILS_ACTIVITY_LIMIT).map((activity) => ({
92
+ ...activity,
93
+ summary: boundText(activity.summary, 256),
94
+ resultSummary: activity.resultSummary ? boundText(activity.resultSummary, 256) : undefined,
95
+ })),
96
+ liveText: boundText(run.liveText, 1_024),
97
+ finalOutput: boundText(run.finalOutput, outputLimit),
98
+ error: run.error ? boundText(run.error, 1_024) : undefined,
99
+ })),
100
+ };
101
+ const fields = [];
102
+ for (const run of bounded.runs) {
103
+ fields.push({
104
+ get: () => run.prompt,
105
+ set: (value) => {
106
+ run.prompt = value;
107
+ },
108
+ }, {
109
+ get: () => run.cwd,
110
+ set: (value) => {
111
+ run.cwd = value;
112
+ },
113
+ }, {
114
+ get: () => run.currentActivity ?? "",
115
+ set: (value) => {
116
+ run.currentActivity = value || undefined;
117
+ },
118
+ }, {
119
+ get: () => run.liveText,
120
+ set: (value) => {
121
+ run.liveText = value;
122
+ },
123
+ }, {
124
+ get: () => run.finalOutput,
125
+ set: (value) => {
126
+ run.finalOutput = value;
127
+ },
128
+ }, {
129
+ get: () => run.error ?? "",
130
+ set: (value) => {
131
+ run.error = value || undefined;
132
+ },
133
+ });
134
+ for (const activity of run.activities) {
135
+ fields.push({
136
+ get: () => activity.summary,
137
+ set: (value) => {
138
+ activity.summary = value;
139
+ },
140
+ }, {
141
+ get: () => activity.resultSummary ?? "",
142
+ set: (value) => {
143
+ activity.resultSummary = value || undefined;
144
+ },
145
+ });
146
+ }
147
+ }
148
+ while (detailsSize(bounded) > DETAILS_OUTPUT_LIMIT) {
149
+ const largest = fields
150
+ .map((field) => ({ field, size: Buffer.byteLength(field.get(), "utf8") }))
151
+ .sort((left, right) => right.size - left.size)[0];
152
+ if (!largest || largest.size === 0)
153
+ break;
154
+ const overflow = detailsSize(bounded) - DETAILS_OUTPUT_LIMIT;
155
+ largest.field.set(boundText(largest.field.get(), Math.max(0, largest.size - overflow)));
156
+ }
157
+ return bounded;
158
+ }
159
+ function statusOf(runs) {
160
+ if (runs.some((run) => run.status === "aborted"))
161
+ return "aborted";
162
+ if (runs.some((run) => run.status === "failed"))
163
+ return "failed";
164
+ if (runs.some((run) => run.status === "queued" || run.status === "running"))
165
+ return "running";
166
+ return "completed";
167
+ }
168
+ function statusText(details) {
169
+ const running = details.runs.filter((run) => run.status === "running").length;
170
+ const queued = details.runs.filter((run) => run.status === "queued").length;
171
+ const completed = details.runs.filter((run) => run.status === "completed").length;
172
+ const failed = details.runs.filter((run) => run.status === "failed").length;
173
+ const aborted = details.runs.filter((run) => run.status === "aborted").length;
174
+ if (details.mode === "single") {
175
+ const run = details.runs[0];
176
+ if (run?.currentActivity)
177
+ return run.currentActivity;
178
+ if (!run ||
179
+ (run.status === "running" && run.usage.turns === 0 && run.usage.toolUses === 0 && run.liveText.length === 0)) {
180
+ return "Initializing…";
181
+ }
182
+ return run.status === "running" ? "Thinking…" : run.status;
183
+ }
184
+ if (details.mode === "chain") {
185
+ const current = details.runs.find((run) => run.status === "running" || run.status === "queued");
186
+ return current
187
+ ? `Step ${current.step ?? 1}/${details.runs.length} · ${current.currentActivity ?? current.agent}`
188
+ : `${completed}/${details.runs.length} steps complete`;
189
+ }
190
+ return `${completed}/${details.runs.length} complete · ${running} running · ${queued} queued${failed ? ` · ${failed} failed` : ""}${aborted ? ` · ${aborted} aborted` : ""}`;
191
+ }
192
+ function emitDetails(mode, runs, startedAt, onUpdate) {
193
+ const details = {
194
+ mode,
195
+ status: statusOf(runs),
196
+ runs: [...runs],
197
+ startedAt,
198
+ usage: aggregateUsage(runs),
199
+ };
200
+ onUpdate?.(boundSubagentDetails(details));
201
+ return details;
202
+ }
203
+ function replacePrevious(prompt, previous) {
204
+ return prompt.replace(/\{previous\}/gu, boundText(previous, CHAIN_HANDOFF_LIMIT));
205
+ }
206
+ function validateTaskCount(tasks) {
207
+ if (tasks.length === 0)
208
+ throw new Error("Subagent task list must not be empty.");
209
+ if (tasks.length > MAX_TASKS)
210
+ throw new Error(`Subagent task list is limited to ${MAX_TASKS} tasks.`);
211
+ }
212
+ async function resolveTasks(tasks, options) {
213
+ validateTaskCount(tasks);
214
+ return Promise.all(tasks.map((task) => resolveSubagentTask(task, options.parentCwd, options.agents, options.parent, options.configAgentDir)));
215
+ }
216
+ async function runWithGate(task, run, options, onProgress) {
217
+ onProgress();
218
+ let release;
219
+ try {
220
+ release = await options.gate.acquire(options.signal);
221
+ if (options.signal?.aborted) {
222
+ run.status = "aborted";
223
+ run.error = "Subagent was aborted while queued.";
224
+ return run;
225
+ }
226
+ return await runSdkTask({
227
+ task,
228
+ run,
229
+ modelRuntime: options.modelRuntime,
230
+ agentDir: options.agentDir,
231
+ projectTrusted: options.projectTrusted,
232
+ signal: options.signal,
233
+ onProgress,
234
+ registerAbort: options.registerAbort,
235
+ });
236
+ }
237
+ catch (error) {
238
+ run.status = options.signal?.aborted ? "aborted" : "failed";
239
+ run.error = boundText(error instanceof Error ? error.message : String(error), ERROR_TEXT_LIMIT);
240
+ run.endedAt = Date.now();
241
+ onProgress();
242
+ return run;
243
+ }
244
+ finally {
245
+ release?.();
246
+ }
247
+ }
248
+ function resultContent(details) {
249
+ if (details.mode === "single") {
250
+ const run = details.runs[0];
251
+ if (!run)
252
+ return "Subagent produced no run.";
253
+ if (run.status === "failed" || run.status === "aborted") {
254
+ return boundText(`${run.status === "aborted" ? "Subagent aborted" : "Subagent failed"}: ${run.error ?? "unknown error"}${run.finalOutput ? `\n\nPartial response:\n${run.finalOutput}` : ""}`, SINGLE_OUTPUT_LIMIT);
255
+ }
256
+ return run.finalOutput || EMPTY_OUTPUT;
257
+ }
258
+ if (details.mode === "chain") {
259
+ const failed = details.runs.find((run) => run.status === "failed" || run.status === "aborted");
260
+ if (failed)
261
+ return boundText(`Chain stopped at step ${failed.step ?? "?"} (${failed.agent}): ${failed.error ?? "unknown error"}`, ERROR_TEXT_LIMIT);
262
+ const last = details.runs[details.runs.length - 1];
263
+ return last?.finalOutput || EMPTY_OUTPUT;
264
+ }
265
+ const sections = details.runs.map((run) => {
266
+ const output = run.finalOutput || run.error || EMPTY_OUTPUT;
267
+ return `### ${run.agent} · ${run.status}\n\n${boundText(output, PARALLEL_TASK_OUTPUT_LIMIT)}`;
268
+ });
269
+ return boundText(`Parallel results\n\n${sections.join("\n\n---\n\n")}`, PARALLEL_OUTPUT_LIMIT);
270
+ }
271
+ function invocationMode(params) {
272
+ const provided = [];
273
+ if (params.prompt != null)
274
+ provided.push("prompt");
275
+ if (params.tasks != null)
276
+ provided.push("tasks");
277
+ if (params.chain != null)
278
+ provided.push("chain");
279
+ if (provided.length !== 1) {
280
+ throw new Error(provided.length === 0
281
+ ? "Provide exactly one subagent mode: prompt (single), tasks (parallel), or chain (sequential); none was provided."
282
+ : `Provide exactly one subagent mode: received ${provided.join(", ")}. Keep one and set the unused mode fields to null or omit them.`);
283
+ }
284
+ if (params.tasks != null) {
285
+ return { mode: "parallel", tasks: params.tasks };
286
+ }
287
+ if (params.chain != null) {
288
+ return { mode: "chain", tasks: params.chain };
289
+ }
290
+ if (params.prompt == null) {
291
+ throw new Error("Provide exactly one subagent mode: prompt (single), tasks (parallel), or chain (sequential).");
292
+ }
293
+ if (!params.description)
294
+ throw new Error("description is required for single mode.");
295
+ return {
296
+ mode: "single",
297
+ tasks: [
298
+ {
299
+ agent: params.agent,
300
+ description: params.description,
301
+ prompt: params.prompt,
302
+ cwd: params.cwd,
303
+ },
304
+ ],
305
+ };
306
+ }
307
+ export async function runSubagentInvocation(options) {
308
+ const { mode, tasks } = invocationMode(options.params);
309
+ const resolved = await resolveTasks(tasks, options);
310
+ const runs = resolved.map((task, index) => createRun(task, index, mode === "chain" ? index + 1 : undefined));
311
+ const startedAt = Date.now();
312
+ let latestDetails = emitDetails(mode, runs, startedAt, options.onUpdate);
313
+ const progress = () => {
314
+ latestDetails = emitDetails(mode, runs, startedAt, options.onUpdate);
315
+ };
316
+ if (mode === "single") {
317
+ await runWithGate(resolved[0], runs[0], options, progress);
318
+ }
319
+ else if (mode === "parallel") {
320
+ await Promise.all(resolved.map((task, index) => runWithGate(task, runs[index], options, progress)));
321
+ }
322
+ else {
323
+ let previous = "";
324
+ for (let index = 0; index < resolved.length; index++) {
325
+ if (options.signal?.aborted) {
326
+ runs[index].status = "aborted";
327
+ runs[index].error = "Skipped because the parent subagent call was aborted.";
328
+ continue;
329
+ }
330
+ const task = { ...resolved[index], prompt: replacePrevious(resolved[index].prompt, previous) };
331
+ await runWithGate(task, runs[index], options, progress);
332
+ if (runs[index].status !== "completed") {
333
+ for (let skipped = index + 1; skipped < runs.length; skipped++) {
334
+ runs[skipped].status = options.signal?.aborted ? "aborted" : "failed";
335
+ runs[skipped].error = `Skipped because chain step ${index + 1} did not complete.`;
336
+ }
337
+ break;
338
+ }
339
+ previous = runs[index].finalOutput;
340
+ }
341
+ }
342
+ latestDetails = emitDetails(mode, runs, startedAt, undefined);
343
+ latestDetails.endedAt = Date.now();
344
+ const isError = latestDetails.status === "failed" || latestDetails.status === "aborted";
345
+ return {
346
+ content: resultContent(latestDetails),
347
+ details: boundSubagentDetails(latestDetails),
348
+ usage: toNestedUsage(latestDetails.usage),
349
+ isError,
350
+ };
351
+ }
352
+ export function statusSummary(details) {
353
+ return statusText(details);
354
+ }
355
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/extensions/subagent/runner.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ModelRuntime } from \"../../core/model-runtime.ts\";\nimport { boundText, emptyUsage, mergeUsage, toNestedUsage } from \"./activity.ts\";\nimport {\n\tCHAIN_HANDOFF_LIMIT,\n\tDETAILS_ACTIVITY_LIMIT,\n\tDETAILS_OUTPUT_LIMIT,\n\tERROR_TEXT_LIMIT,\n\tMAX_CONCURRENCY,\n\tMAX_TASKS,\n\tPARALLEL_OUTPUT_LIMIT,\n\tPARALLEL_TASK_OUTPUT_LIMIT,\n\tSINGLE_OUTPUT_LIMIT,\n} from \"./constants.ts\";\nimport { type ParentModelContext, resolveSubagentTask } from \"./resolve.ts\";\nimport type { SubagentParams, SubagentTask } from \"./schema.ts\";\nimport { runSdkTask } from \"./sdk-runner.ts\";\nimport type {\n\tAgentDefinition,\n\tResolvedSubagentTask,\n\tSubagentDetails,\n\tSubagentExecutionResult,\n\tSubagentRunDetails,\n\tSubagentUsage,\n} from \"./types.ts\";\n\nconst EMPTY_OUTPUT = \"(Subagent completed but returned no output.)\";\n\ninterface Waiter {\n\tresolve: (release: () => void) => void;\n\treject: (error: Error) => void;\n\tsignal?: AbortSignal;\n\tabortListener?: () => void;\n}\n\nexport class ConcurrencyGate {\n\tprivate active = 0;\n\tprivate readonly waiters: Waiter[] = [];\n\tprivate readonly limit: number;\n\n\tconstructor(limit = MAX_CONCURRENCY) {\n\t\tthis.limit = limit;\n\t}\n\n\tacquire(signal?: AbortSignal): Promise<() => void> {\n\t\tif (signal?.aborted) return Promise.reject(new Error(\"Subagent was aborted while queued.\"));\n\t\tif (this.active < this.limit) {\n\t\t\tthis.active++;\n\t\t\treturn Promise.resolve(() => this.release());\n\t\t}\n\t\treturn new Promise<() => void>((resolve, reject) => {\n\t\t\tconst waiter: Waiter = { resolve, reject, signal };\n\t\t\tif (signal) {\n\t\t\t\twaiter.abortListener = () => {\n\t\t\t\t\tconst index = this.waiters.indexOf(waiter);\n\t\t\t\t\tif (index >= 0) this.waiters.splice(index, 1);\n\t\t\t\t\treject(new Error(\"Subagent was aborted while queued.\"));\n\t\t\t\t};\n\t\t\t\tsignal.addEventListener(\"abort\", waiter.abortListener, { once: true });\n\t\t\t}\n\t\t\tthis.waiters.push(waiter);\n\t\t});\n\t}\n\n\tprivate release(): void {\n\t\tthis.active = Math.max(0, this.active - 1);\n\t\twhile (this.waiters.length > 0) {\n\t\t\tconst waiter = this.waiters.shift();\n\t\t\tif (!waiter) return;\n\t\t\tif (waiter.signal?.aborted) {\n\t\t\t\twaiter.abortListener?.();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\twaiter.signal?.removeEventListener(\"abort\", waiter.abortListener!);\n\t\t\tthis.active++;\n\t\t\twaiter.resolve(() => this.release());\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nexport interface SubagentInvocationOptions {\n\tparams: SubagentParams;\n\tparentCwd: string;\n\tagents: readonly AgentDefinition[];\n\tparent: ParentModelContext;\n\tmodelRuntime: ModelRuntime;\n\tagentDir: string;\n\tconfigAgentDir: string;\n\tprojectTrusted: boolean;\n\tsignal?: AbortSignal;\n\tgate: ConcurrencyGate;\n\tonUpdate?: (details: SubagentDetails) => void;\n\tregisterAbort?: (abort: () => Promise<void>) => () => void;\n}\n\nfunction runId(index: number): string {\n\treturn `subagent-${index + 1}`;\n}\n\nfunction createRun(task: ResolvedSubagentTask, index: number, step?: number): SubagentRunDetails {\n\treturn {\n\t\tid: runId(index),\n\t\tagent: task.agent.name,\n\t\tagentSource: task.agent.source,\n\t\tdescription: task.description,\n\t\tprompt: task.prompt,\n\t\tcwd: task.cwd,\n\t\tmodel: `${task.model.provider}/${task.model.id}`,\n\t\tthinking: task.thinking,\n\t\tstatus: \"queued\",\n\t\tactivities: [],\n\t\tliveText: \"\",\n\t\tfinalOutput: \"\",\n\t\tusage: emptyUsage(),\n\t\tstep,\n\t};\n}\n\nfunction aggregateUsage(runs: readonly SubagentRunDetails[]): SubagentUsage {\n\tconst usage = emptyUsage();\n\tfor (const run of runs) mergeUsage(usage, run.usage);\n\treturn usage;\n}\n\ninterface TextField {\n\tget: () => string;\n\tset: (value: string) => void;\n}\n\nfunction detailsSize(details: SubagentDetails): number {\n\treturn Buffer.byteLength(JSON.stringify(details), \"utf8\");\n}\n\nexport function boundSubagentDetails(details: SubagentDetails): SubagentDetails {\n\tconst perRunBudget = Math.max(\n\t\t1_024,\n\t\tMath.floor((DETAILS_OUTPUT_LIMIT - 8 * 1024) / Math.max(1, details.runs.length)),\n\t);\n\tconst outputLimit = Math.min(SINGLE_OUTPUT_LIMIT, Math.max(1_024, perRunBudget - 7 * 1024));\n\tconst bounded: SubagentDetails = {\n\t\t...details,\n\t\truns: details.runs.map((run) => ({\n\t\t\t...run,\n\t\t\tprompt: boundText(run.prompt, 1_024),\n\t\t\tcwd: boundText(run.cwd, 1_024),\n\t\t\tcurrentActivity: run.currentActivity ? boundText(run.currentActivity, 512) : undefined,\n\t\t\tactivities: run.activities.slice(-DETAILS_ACTIVITY_LIMIT).map((activity) => ({\n\t\t\t\t...activity,\n\t\t\t\tsummary: boundText(activity.summary, 256),\n\t\t\t\tresultSummary: activity.resultSummary ? boundText(activity.resultSummary, 256) : undefined,\n\t\t\t})),\n\t\t\tliveText: boundText(run.liveText, 1_024),\n\t\t\tfinalOutput: boundText(run.finalOutput, outputLimit),\n\t\t\terror: run.error ? boundText(run.error, 1_024) : undefined,\n\t\t})),\n\t};\n\tconst fields: TextField[] = [];\n\tfor (const run of bounded.runs) {\n\t\tfields.push(\n\t\t\t{\n\t\t\t\tget: () => run.prompt,\n\t\t\t\tset: (value) => {\n\t\t\t\t\trun.prompt = value;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tget: () => run.cwd,\n\t\t\t\tset: (value) => {\n\t\t\t\t\trun.cwd = value;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tget: () => run.currentActivity ?? \"\",\n\t\t\t\tset: (value) => {\n\t\t\t\t\trun.currentActivity = value || undefined;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tget: () => run.liveText,\n\t\t\t\tset: (value) => {\n\t\t\t\t\trun.liveText = value;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tget: () => run.finalOutput,\n\t\t\t\tset: (value) => {\n\t\t\t\t\trun.finalOutput = value;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tget: () => run.error ?? \"\",\n\t\t\t\tset: (value) => {\n\t\t\t\t\trun.error = value || undefined;\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\tfor (const activity of run.activities) {\n\t\t\tfields.push(\n\t\t\t\t{\n\t\t\t\t\tget: () => activity.summary,\n\t\t\t\t\tset: (value) => {\n\t\t\t\t\t\tactivity.summary = value;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tget: () => activity.resultSummary ?? \"\",\n\t\t\t\t\tset: (value) => {\n\t\t\t\t\t\tactivity.resultSummary = value || undefined;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\twhile (detailsSize(bounded) > DETAILS_OUTPUT_LIMIT) {\n\t\tconst largest = fields\n\t\t\t.map((field) => ({ field, size: Buffer.byteLength(field.get(), \"utf8\") }))\n\t\t\t.sort((left, right) => right.size - left.size)[0];\n\t\tif (!largest || largest.size === 0) break;\n\t\tconst overflow = detailsSize(bounded) - DETAILS_OUTPUT_LIMIT;\n\t\tlargest.field.set(boundText(largest.field.get(), Math.max(0, largest.size - overflow)));\n\t}\n\treturn bounded;\n}\n\nfunction statusOf(runs: readonly SubagentRunDetails[]): SubagentDetails[\"status\"] {\n\tif (runs.some((run) => run.status === \"aborted\")) return \"aborted\";\n\tif (runs.some((run) => run.status === \"failed\")) return \"failed\";\n\tif (runs.some((run) => run.status === \"queued\" || run.status === \"running\")) return \"running\";\n\treturn \"completed\";\n}\n\nfunction statusText(details: SubagentDetails): string {\n\tconst running = details.runs.filter((run) => run.status === \"running\").length;\n\tconst queued = details.runs.filter((run) => run.status === \"queued\").length;\n\tconst completed = details.runs.filter((run) => run.status === \"completed\").length;\n\tconst failed = details.runs.filter((run) => run.status === \"failed\").length;\n\tconst aborted = details.runs.filter((run) => run.status === \"aborted\").length;\n\tif (details.mode === \"single\") {\n\t\tconst run = details.runs[0];\n\t\tif (run?.currentActivity) return run.currentActivity;\n\t\tif (\n\t\t\t!run ||\n\t\t\t(run.status === \"running\" && run.usage.turns === 0 && run.usage.toolUses === 0 && run.liveText.length === 0)\n\t\t) {\n\t\t\treturn \"Initializing…\";\n\t\t}\n\t\treturn run.status === \"running\" ? \"Thinking…\" : run.status;\n\t}\n\tif (details.mode === \"chain\") {\n\t\tconst current = details.runs.find((run) => run.status === \"running\" || run.status === \"queued\");\n\t\treturn current\n\t\t\t? `Step ${current.step ?? 1}/${details.runs.length} · ${current.currentActivity ?? current.agent}`\n\t\t\t: `${completed}/${details.runs.length} steps complete`;\n\t}\n\treturn `${completed}/${details.runs.length} complete · ${running} running · ${queued} queued${failed ? ` · ${failed} failed` : \"\"}${aborted ? ` · ${aborted} aborted` : \"\"}`;\n}\n\nfunction emitDetails(\n\tmode: SubagentDetails[\"mode\"],\n\truns: SubagentRunDetails[],\n\tstartedAt: number,\n\tonUpdate: ((details: SubagentDetails) => void) | undefined,\n): SubagentDetails {\n\tconst details: SubagentDetails = {\n\t\tmode,\n\t\tstatus: statusOf(runs),\n\t\truns: [...runs],\n\t\tstartedAt,\n\t\tusage: aggregateUsage(runs),\n\t};\n\tonUpdate?.(boundSubagentDetails(details));\n\treturn details;\n}\n\nfunction replacePrevious(prompt: string, previous: string): string {\n\treturn prompt.replace(/\\{previous\\}/gu, boundText(previous, CHAIN_HANDOFF_LIMIT));\n}\n\nfunction validateTaskCount(tasks: readonly SubagentTask[]): void {\n\tif (tasks.length === 0) throw new Error(\"Subagent task list must not be empty.\");\n\tif (tasks.length > MAX_TASKS) throw new Error(`Subagent task list is limited to ${MAX_TASKS} tasks.`);\n}\n\nasync function resolveTasks(\n\ttasks: readonly SubagentTask[],\n\toptions: SubagentInvocationOptions,\n): Promise<ResolvedSubagentTask[]> {\n\tvalidateTaskCount(tasks);\n\treturn Promise.all(\n\t\ttasks.map((task) =>\n\t\t\tresolveSubagentTask(task, options.parentCwd, options.agents, options.parent, options.configAgentDir),\n\t\t),\n\t);\n}\n\nasync function runWithGate(\n\ttask: ResolvedSubagentTask,\n\trun: SubagentRunDetails,\n\toptions: SubagentInvocationOptions,\n\tonProgress: () => void,\n): Promise<SubagentRunDetails> {\n\tonProgress();\n\tlet release: (() => void) | undefined;\n\ttry {\n\t\trelease = await options.gate.acquire(options.signal);\n\t\tif (options.signal?.aborted) {\n\t\t\trun.status = \"aborted\";\n\t\t\trun.error = \"Subagent was aborted while queued.\";\n\t\t\treturn run;\n\t\t}\n\t\treturn await runSdkTask({\n\t\t\ttask,\n\t\t\trun,\n\t\t\tmodelRuntime: options.modelRuntime,\n\t\t\tagentDir: options.agentDir,\n\t\t\tprojectTrusted: options.projectTrusted,\n\t\t\tsignal: options.signal,\n\t\t\tonProgress,\n\t\t\tregisterAbort: options.registerAbort,\n\t\t});\n\t} catch (error) {\n\t\trun.status = options.signal?.aborted ? \"aborted\" : \"failed\";\n\t\trun.error = boundText(error instanceof Error ? error.message : String(error), ERROR_TEXT_LIMIT);\n\t\trun.endedAt = Date.now();\n\t\tonProgress();\n\t\treturn run;\n\t} finally {\n\t\trelease?.();\n\t}\n}\n\nfunction resultContent(details: SubagentDetails): string {\n\tif (details.mode === \"single\") {\n\t\tconst run = details.runs[0];\n\t\tif (!run) return \"Subagent produced no run.\";\n\t\tif (run.status === \"failed\" || run.status === \"aborted\") {\n\t\t\treturn boundText(\n\t\t\t\t`${run.status === \"aborted\" ? \"Subagent aborted\" : \"Subagent failed\"}: ${run.error ?? \"unknown error\"}${run.finalOutput ? `\\n\\nPartial response:\\n${run.finalOutput}` : \"\"}`,\n\t\t\t\tSINGLE_OUTPUT_LIMIT,\n\t\t\t);\n\t\t}\n\t\treturn run.finalOutput || EMPTY_OUTPUT;\n\t}\n\tif (details.mode === \"chain\") {\n\t\tconst failed = details.runs.find((run) => run.status === \"failed\" || run.status === \"aborted\");\n\t\tif (failed)\n\t\t\treturn boundText(\n\t\t\t\t`Chain stopped at step ${failed.step ?? \"?\"} (${failed.agent}): ${failed.error ?? \"unknown error\"}`,\n\t\t\t\tERROR_TEXT_LIMIT,\n\t\t\t);\n\t\tconst last = details.runs[details.runs.length - 1];\n\t\treturn last?.finalOutput || EMPTY_OUTPUT;\n\t}\n\tconst sections = details.runs.map((run) => {\n\t\tconst output = run.finalOutput || run.error || EMPTY_OUTPUT;\n\t\treturn `### ${run.agent} · ${run.status}\\n\\n${boundText(output, PARALLEL_TASK_OUTPUT_LIMIT)}`;\n\t});\n\treturn boundText(`Parallel results\\n\\n${sections.join(\"\\n\\n---\\n\\n\")}`, PARALLEL_OUTPUT_LIMIT);\n}\n\nfunction invocationMode(params: SubagentParams): { mode: SubagentDetails[\"mode\"]; tasks: SubagentTask[] } {\n\tconst provided: string[] = [];\n\tif (params.prompt != null) provided.push(\"prompt\");\n\tif (params.tasks != null) provided.push(\"tasks\");\n\tif (params.chain != null) provided.push(\"chain\");\n\tif (provided.length !== 1) {\n\t\tthrow new Error(\n\t\t\tprovided.length === 0\n\t\t\t\t? \"Provide exactly one subagent mode: prompt (single), tasks (parallel), or chain (sequential); none was provided.\"\n\t\t\t\t: `Provide exactly one subagent mode: received ${provided.join(\", \")}. Keep one and set the unused mode fields to null or omit them.`,\n\t\t);\n\t}\n\tif (params.tasks != null) {\n\t\treturn { mode: \"parallel\", tasks: params.tasks };\n\t}\n\tif (params.chain != null) {\n\t\treturn { mode: \"chain\", tasks: params.chain };\n\t}\n\tif (params.prompt == null) {\n\t\tthrow new Error(\"Provide exactly one subagent mode: prompt (single), tasks (parallel), or chain (sequential).\");\n\t}\n\tif (!params.description) throw new Error(\"description is required for single mode.\");\n\treturn {\n\t\tmode: \"single\",\n\t\ttasks: [\n\t\t\t{\n\t\t\t\tagent: params.agent,\n\t\t\t\tdescription: params.description,\n\t\t\t\tprompt: params.prompt,\n\t\t\t\tcwd: params.cwd,\n\t\t\t},\n\t\t],\n\t};\n}\n\nexport async function runSubagentInvocation(options: SubagentInvocationOptions): Promise<SubagentExecutionResult> {\n\tconst { mode, tasks } = invocationMode(options.params);\n\tconst resolved = await resolveTasks(tasks, options);\n\tconst runs = resolved.map((task, index) => createRun(task, index, mode === \"chain\" ? index + 1 : undefined));\n\tconst startedAt = Date.now();\n\tlet latestDetails = emitDetails(mode, runs, startedAt, options.onUpdate);\n\tconst progress = () => {\n\t\tlatestDetails = emitDetails(mode, runs, startedAt, options.onUpdate);\n\t};\n\n\tif (mode === \"single\") {\n\t\tawait runWithGate(resolved[0]!, runs[0]!, options, progress);\n\t} else if (mode === \"parallel\") {\n\t\tawait Promise.all(resolved.map((task, index) => runWithGate(task, runs[index]!, options, progress)));\n\t} else {\n\t\tlet previous = \"\";\n\t\tfor (let index = 0; index < resolved.length; index++) {\n\t\t\tif (options.signal?.aborted) {\n\t\t\t\truns[index]!.status = \"aborted\";\n\t\t\t\truns[index]!.error = \"Skipped because the parent subagent call was aborted.\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst task = { ...resolved[index]!, prompt: replacePrevious(resolved[index]!.prompt, previous) };\n\t\t\tawait runWithGate(task, runs[index]!, options, progress);\n\t\t\tif (runs[index]!.status !== \"completed\") {\n\t\t\t\tfor (let skipped = index + 1; skipped < runs.length; skipped++) {\n\t\t\t\t\truns[skipped]!.status = options.signal?.aborted ? \"aborted\" : \"failed\";\n\t\t\t\t\truns[skipped]!.error = `Skipped because chain step ${index + 1} did not complete.`;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprevious = runs[index]!.finalOutput;\n\t\t}\n\t}\n\tlatestDetails = emitDetails(mode, runs, startedAt, undefined);\n\tlatestDetails.endedAt = Date.now();\n\tconst isError = latestDetails.status === \"failed\" || latestDetails.status === \"aborted\";\n\treturn {\n\t\tcontent: resultContent(latestDetails),\n\t\tdetails: boundSubagentDetails(latestDetails),\n\t\tusage: toNestedUsage(latestDetails.usage),\n\t\tisError,\n\t};\n}\n\nexport function statusSummary(details: SubagentDetails): string {\n\treturn statusText(details);\n}\n"]}
@@ -0,0 +1,28 @@
1
+ import { type Static, Type } from "typebox";
2
+ export declare const TaskSchema: Type.TObject<{
3
+ agent: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
4
+ description: Type.TString;
5
+ prompt: Type.TString;
6
+ cwd: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
7
+ }>;
8
+ export declare const SubagentParamsSchema: Type.TObject<{
9
+ agent: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
10
+ description: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
11
+ prompt: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
12
+ cwd: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
13
+ tasks: Type.TOptional<Type.TUnion<[Type.TArray<Type.TObject<{
14
+ agent: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
15
+ description: Type.TString;
16
+ prompt: Type.TString;
17
+ cwd: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
18
+ }>>, Type.TNull]>>;
19
+ chain: Type.TOptional<Type.TUnion<[Type.TArray<Type.TObject<{
20
+ agent: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
21
+ description: Type.TString;
22
+ prompt: Type.TString;
23
+ cwd: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
24
+ }>>, Type.TNull]>>;
25
+ }>;
26
+ export type SubagentParams = Static<typeof SubagentParamsSchema>;
27
+ export type SubagentTask = Static<typeof TaskSchema>;
28
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgB,IAAI,EAAE,MAAM,SAAS,CAAC;AAY1D,eAAO,MAAM,UAAU;;;;;EAsBtB,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;EA4BhC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC","sourcesContent":["import { type Static, type TSchema, Type } from \"typebox\";\nimport { MAX_TASKS } from \"./constants.ts\";\n\n// Strict constrained-sampling providers treat every property as required\n// and reject bare unions at the top level, so the schema is a flat\n// `type: \"object\"` whose optional fields are also nullable: callers omit\n// a field when the grammar allows it and send null when it does not.\n// The exactly-one-mode rule is enforced at runtime in `invocationMode`.\nfunction nullable<T extends TSchema>(schema: T, description: string) {\n\treturn Type.Optional(Type.Union([schema, Type.Null()], { description }));\n}\n\nexport const TaskSchema = Type.Object(\n\t{\n\t\tagent: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 80 }),\n\t\t\t\"Agent profile from the list in the tool description; null or omit for general\",\n\t\t),\n\t\tdescription: Type.String({\n\t\t\tminLength: 1,\n\t\t\tmaxLength: 80,\n\t\t\tdescription: \"Concise 3-8 word UI label\",\n\t\t}),\n\t\tprompt: Type.String({\n\t\t\tminLength: 1,\n\t\t\tmaxLength: 20_000,\n\t\t\tdescription: \"Complete self-contained briefing; the worker cannot see the parent conversation\",\n\t\t}),\n\t\tcwd: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 4_096 }),\n\t\t\t\"Relative directory inside the parent working directory; null or omit to inherit it\",\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const SubagentParamsSchema = Type.Object(\n\t{\n\t\tagent: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 80 }),\n\t\t\t\"Agent profile from the list in the tool description (single mode); null or omit otherwise (defaults to general)\",\n\t\t),\n\t\tdescription: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 80 }),\n\t\t\t\"Concise 3-8 word UI label; required for single mode, null or omit otherwise\",\n\t\t),\n\t\tprompt: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 20_000 }),\n\t\t\t\"Complete self-contained briefing; providing it selects single mode — null or omit when using tasks or chain\",\n\t\t),\n\t\tcwd: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 4_096 }),\n\t\t\t\"Relative directory inside the parent working directory (single mode); null or omit otherwise\",\n\t\t),\n\t\ttasks: nullable(\n\t\t\tType.Array(TaskSchema, { minItems: 1, maxItems: MAX_TASKS }),\n\t\t\t\"Independent tasks run concurrently; providing it selects parallel mode — null or omit when using prompt or chain\",\n\t\t),\n\t\tchain: nullable(\n\t\t\tType.Array(TaskSchema, { minItems: 1, maxItems: MAX_TASKS }),\n\t\t\t\"Sequential tasks where {previous} in a later prompt is replaced by the prior result; providing it selects chain mode — null or omit otherwise\",\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type SubagentParams = Static<typeof SubagentParamsSchema>;\nexport type SubagentTask = Static<typeof TaskSchema>;\n"]}
@@ -0,0 +1,33 @@
1
+ import { Type } from "typebox";
2
+ import { MAX_TASKS } from "./constants.js";
3
+ // Strict constrained-sampling providers treat every property as required
4
+ // and reject bare unions at the top level, so the schema is a flat
5
+ // `type: "object"` whose optional fields are also nullable: callers omit
6
+ // a field when the grammar allows it and send null when it does not.
7
+ // The exactly-one-mode rule is enforced at runtime in `invocationMode`.
8
+ function nullable(schema, description) {
9
+ return Type.Optional(Type.Union([schema, Type.Null()], { description }));
10
+ }
11
+ export const TaskSchema = Type.Object({
12
+ agent: nullable(Type.String({ minLength: 1, maxLength: 80 }), "Agent profile from the list in the tool description; null or omit for general"),
13
+ description: Type.String({
14
+ minLength: 1,
15
+ maxLength: 80,
16
+ description: "Concise 3-8 word UI label",
17
+ }),
18
+ prompt: Type.String({
19
+ minLength: 1,
20
+ maxLength: 20_000,
21
+ description: "Complete self-contained briefing; the worker cannot see the parent conversation",
22
+ }),
23
+ cwd: nullable(Type.String({ minLength: 1, maxLength: 4_096 }), "Relative directory inside the parent working directory; null or omit to inherit it"),
24
+ }, { additionalProperties: false });
25
+ export const SubagentParamsSchema = Type.Object({
26
+ agent: nullable(Type.String({ minLength: 1, maxLength: 80 }), "Agent profile from the list in the tool description (single mode); null or omit otherwise (defaults to general)"),
27
+ description: nullable(Type.String({ minLength: 1, maxLength: 80 }), "Concise 3-8 word UI label; required for single mode, null or omit otherwise"),
28
+ prompt: nullable(Type.String({ minLength: 1, maxLength: 20_000 }), "Complete self-contained briefing; providing it selects single mode — null or omit when using tasks or chain"),
29
+ cwd: nullable(Type.String({ minLength: 1, maxLength: 4_096 }), "Relative directory inside the parent working directory (single mode); null or omit otherwise"),
30
+ tasks: nullable(Type.Array(TaskSchema, { minItems: 1, maxItems: MAX_TASKS }), "Independent tasks run concurrently; providing it selects parallel mode — null or omit when using prompt or chain"),
31
+ chain: nullable(Type.Array(TaskSchema, { minItems: 1, maxItems: MAX_TASKS }), "Sequential tasks where {previous} in a later prompt is replaced by the prior result; providing it selects chain mode — null or omit otherwise"),
32
+ }, { additionalProperties: false });
33
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/subagent/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,IAAI,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,yEAAyE;AACzE,mEAAmE;AACnE,yEAAyE;AACzE,qEAAqE;AACrE,wEAAwE;AACxE,SAAS,QAAQ,CAAoB,MAAS,EAAE,WAAmB,EAAE;IACpE,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;AAAA,CACzE;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CACpC;IACC,KAAK,EAAE,QAAQ,CACd,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,EAC5C,+EAA+E,CAC/E;IACD,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC;QACxB,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,EAAE;QACb,WAAW,EAAE,2BAA2B;KACxC,CAAC;IACF,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QACnB,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,MAAM;QACjB,WAAW,EAAE,iFAAiF;KAC9F,CAAC;IACF,GAAG,EAAE,QAAQ,CACZ,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAC/C,oFAAoF,CACpF;CACD,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,MAAM,CAC9C;IACC,KAAK,EAAE,QAAQ,CACd,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,EAC5C,iHAAiH,CACjH;IACD,WAAW,EAAE,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,EAC5C,6EAA6E,CAC7E;IACD,MAAM,EAAE,QAAQ,CACf,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAChD,+GAA6G,CAC7G;IACD,GAAG,EAAE,QAAQ,CACZ,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAC/C,8FAA8F,CAC9F;IACD,KAAK,EAAE,QAAQ,CACd,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAC5D,oHAAkH,CAClH;IACD,KAAK,EAAE,QAAQ,CACd,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAC5D,iJAA+I,CAC/I;CACD,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAC/B,CAAC","sourcesContent":["import { type Static, type TSchema, Type } from \"typebox\";\nimport { MAX_TASKS } from \"./constants.ts\";\n\n// Strict constrained-sampling providers treat every property as required\n// and reject bare unions at the top level, so the schema is a flat\n// `type: \"object\"` whose optional fields are also nullable: callers omit\n// a field when the grammar allows it and send null when it does not.\n// The exactly-one-mode rule is enforced at runtime in `invocationMode`.\nfunction nullable<T extends TSchema>(schema: T, description: string) {\n\treturn Type.Optional(Type.Union([schema, Type.Null()], { description }));\n}\n\nexport const TaskSchema = Type.Object(\n\t{\n\t\tagent: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 80 }),\n\t\t\t\"Agent profile from the list in the tool description; null or omit for general\",\n\t\t),\n\t\tdescription: Type.String({\n\t\t\tminLength: 1,\n\t\t\tmaxLength: 80,\n\t\t\tdescription: \"Concise 3-8 word UI label\",\n\t\t}),\n\t\tprompt: Type.String({\n\t\t\tminLength: 1,\n\t\t\tmaxLength: 20_000,\n\t\t\tdescription: \"Complete self-contained briefing; the worker cannot see the parent conversation\",\n\t\t}),\n\t\tcwd: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 4_096 }),\n\t\t\t\"Relative directory inside the parent working directory; null or omit to inherit it\",\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const SubagentParamsSchema = Type.Object(\n\t{\n\t\tagent: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 80 }),\n\t\t\t\"Agent profile from the list in the tool description (single mode); null or omit otherwise (defaults to general)\",\n\t\t),\n\t\tdescription: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 80 }),\n\t\t\t\"Concise 3-8 word UI label; required for single mode, null or omit otherwise\",\n\t\t),\n\t\tprompt: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 20_000 }),\n\t\t\t\"Complete self-contained briefing; providing it selects single mode — null or omit when using tasks or chain\",\n\t\t),\n\t\tcwd: nullable(\n\t\t\tType.String({ minLength: 1, maxLength: 4_096 }),\n\t\t\t\"Relative directory inside the parent working directory (single mode); null or omit otherwise\",\n\t\t),\n\t\ttasks: nullable(\n\t\t\tType.Array(TaskSchema, { minItems: 1, maxItems: MAX_TASKS }),\n\t\t\t\"Independent tasks run concurrently; providing it selects parallel mode — null or omit when using prompt or chain\",\n\t\t),\n\t\tchain: nullable(\n\t\t\tType.Array(TaskSchema, { minItems: 1, maxItems: MAX_TASKS }),\n\t\t\t\"Sequential tasks where {previous} in a later prompt is replaced by the prior result; providing it selects chain mode — null or omit otherwise\",\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type SubagentParams = Static<typeof SubagentParamsSchema>;\nexport type SubagentTask = Static<typeof TaskSchema>;\n"]}
@@ -0,0 +1,14 @@
1
+ import type { ModelRuntime } from "../../core/model-runtime.ts";
2
+ import type { ResolvedSubagentTask, SubagentRunDetails } from "./types.ts";
3
+ export interface SdkRunnerOptions {
4
+ task: ResolvedSubagentTask;
5
+ run: SubagentRunDetails;
6
+ modelRuntime: ModelRuntime;
7
+ agentDir: string;
8
+ projectTrusted: boolean;
9
+ signal?: AbortSignal;
10
+ onProgress?: () => void;
11
+ registerAbort?: (abort: () => Promise<void>) => () => void;
12
+ }
13
+ export declare function runSdkTask(options: SdkRunnerOptions): Promise<SubagentRunDetails>;
14
+ //# sourceMappingURL=sdk-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-runner.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/sdk-runner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAgBhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAgB,MAAM,YAAY,CAAC;AAEzF,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,GAAG,EAAE,kBAAkB,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC;CAC3D;AAgDD,wBAAsB,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkJvF","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AgentSessionEvent } from \"../../core/agent-session.ts\";\nimport type { ModelRuntime } from \"../../core/model-runtime.ts\";\nimport { DefaultResourceLoader } from \"../../core/resource-loader.ts\";\nimport { createAgentSession } from \"../../core/sdk.ts\";\nimport { SessionManager } from \"../../core/session-manager.ts\";\nimport { SettingsManager } from \"../../core/settings-manager.ts\";\nimport {\n\tactivitySummary,\n\taddUsage,\n\tappendActivity,\n\tassistantText,\n\tboundText,\n\tfinalAssistantText,\n\tresultSummary,\n\tsetLiveText,\n} from \"./activity.ts\";\nimport { ERROR_TEXT_LIMIT, LIVE_TEXT_LIMIT, SINGLE_OUTPUT_LIMIT } from \"./constants.ts\";\nimport type { ResolvedSubagentTask, SubagentRunDetails, ToolActivity } from \"./types.ts\";\n\nexport interface SdkRunnerOptions {\n\ttask: ResolvedSubagentTask;\n\trun: SubagentRunDetails;\n\tmodelRuntime: ModelRuntime;\n\tagentDir: string;\n\tprojectTrusted: boolean;\n\tsignal?: AbortSignal;\n\tonProgress?: () => void;\n\tregisterAbort?: (abort: () => Promise<void>) => () => void;\n}\n\nfunction workerSystemPrompt(base: string | undefined, task: ResolvedSubagentTask): string {\n\treturn [\n\t\tbase,\n\t\t`You are Pi subagent \"${task.agent.name}\", working independently on one delegated task.`,\n\t\t\"You cannot see the parent conversation; rely entirely on the task briefing and repository context available in your working directory.\",\n\t\t\"Complete the task fully—do not gold-plate it, but do not leave it half-done.\",\n\t\t\"Stay inside the assigned working directory and delegated scope.\",\n\t\t\"Do not ask the end user questions. If blocked, report the exact blocker and what would resolve it.\",\n\t\t\"Do not spawn subagents or invoke tools outside the configured tool list.\",\n\t\t\"When referencing files in the final report, use absolute paths so the caller can locate them unambiguously.\",\n\t\t\"End with a concise report covering findings or changes, verification performed, blockers, and unresolved risks. The caller will relay it to the user, so include only the essentials.\",\n\t\ttask.agent.systemPrompt,\n\t]\n\t\t.filter((part): part is string => Boolean(part?.trim()))\n\t\t.join(\"\\n\\n\");\n}\n\nfunction lastAssistantMessage(session: { messages: readonly AgentMessage[] }) {\n\tfor (let index = session.messages.length - 1; index >= 0; index--) {\n\t\tconst message = session.messages[index];\n\t\tif (message?.role === \"assistant\") return message;\n\t}\n\treturn undefined;\n}\n\nfunction assistantError(message: ReturnType<typeof lastAssistantMessage>): string | undefined {\n\tif (!message || message.role !== \"assistant\") return undefined;\n\treturn message.errorMessage;\n}\n\nfunction emitThrottled(onProgress: (() => void) | undefined): () => void {\n\tlet pending = false;\n\treturn () => {\n\t\tif (!onProgress || pending) return;\n\t\tpending = true;\n\t\tsetTimeout(() => {\n\t\t\tpending = false;\n\t\t\tonProgress();\n\t\t}, 80);\n\t};\n}\n\nfunction cancelThrottled(onProgress: () => void): void {\n\tonProgress();\n}\n\nexport async function runSdkTask(options: SdkRunnerOptions): Promise<SubagentRunDetails> {\n\tconst { task, run, modelRuntime, agentDir, projectTrusted, signal, onProgress } = options;\n\tconst emitTextProgress = emitThrottled(onProgress);\n\tlet unsubscribe: (() => void) | undefined;\n\tlet unregisterAbort: (() => void) | undefined;\n\tlet session: Awaited<ReturnType<typeof createAgentSession>>[\"session\"] | undefined;\n\tconst activeActivities = new Map<string, ToolActivity>();\n\tconst seenAssistantMessages = new Set<unknown>();\n\tconst markAbort = async (): Promise<void> => {\n\t\trun.status = \"aborted\";\n\t\tif (session) await session.abort();\n\t};\n\n\ttry {\n\t\tif (signal?.aborted) {\n\t\t\trun.status = \"aborted\";\n\t\t\trun.error = \"Subagent was aborted before it started.\";\n\t\t\treturn run;\n\t\t}\n\n\t\trun.status = \"running\";\n\t\trun.startedAt = Date.now();\n\t\tonProgress?.();\n\t\tconst settingsManager = SettingsManager.create(task.cwd, agentDir, { projectTrusted });\n\t\tconst resourceLoader = new DefaultResourceLoader({\n\t\t\tcwd: task.cwd,\n\t\t\tagentDir,\n\t\t\tsettingsManager,\n\t\t\tnoExtensions: true,\n\t\t\tnoSkills: true,\n\t\t\tnoPromptTemplates: true,\n\t\t\tnoThemes: true,\n\t\t\tsystemPromptOverride: (base) => workerSystemPrompt(base, task),\n\t\t});\n\t\tawait resourceLoader.reload();\n\t\tconst created = await createAgentSession({\n\t\t\tcwd: task.cwd,\n\t\t\tagentDir,\n\t\t\tmodelRuntime,\n\t\t\tmodel: task.model,\n\t\t\tthinkingLevel: task.thinking,\n\t\t\ttools: task.agent.tools,\n\t\t\tresourceLoader,\n\t\t\tsessionManager: SessionManager.inMemory(task.cwd),\n\t\t\tsettingsManager,\n\t\t});\n\t\tsession = created.session;\n\t\tconst emitImmediate = () => onProgress?.();\n\t\tconst emitText = emitTextProgress;\n\t\tunsubscribe = session.subscribe((event: AgentSessionEvent) => {\n\t\t\tif (event.type === \"turn_end\") {\n\t\t\t\trun.usage.turns++;\n\t\t\t\trun.currentActivity = undefined;\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"message_end\" && event.message.role === \"assistant\") {\n\t\t\t\tif (!seenAssistantMessages.has(event.message)) {\n\t\t\t\t\tseenAssistantMessages.add(event.message);\n\t\t\t\t\taddUsage(run.usage, event.message.usage);\n\t\t\t\t}\n\t\t\t\trun.liveText = setLiveText(assistantText(event.message));\n\t\t\t\temitText();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"message_update\") {\n\t\t\t\tif (event.message.role === \"assistant\") run.liveText = setLiveText(assistantText(event.message));\n\t\t\t\tif (event.assistantMessageEvent.type === \"thinking_delta\") run.currentActivity = \"Thinking…\";\n\t\t\t\tif (event.assistantMessageEvent.type === \"text_delta\") run.currentActivity = \"Writing response…\";\n\t\t\t\temitText();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\trun.usage.toolUses++;\n\t\t\t\tconst activity: ToolActivity = {\n\t\t\t\t\tid: event.toolCallId,\n\t\t\t\t\ttoolName: event.toolName,\n\t\t\t\t\tsummary: activitySummary(event.toolName, event.args),\n\t\t\t\t\tstatus: \"running\",\n\t\t\t\t\tstartedAt: Date.now(),\n\t\t\t\t};\n\t\t\t\tactiveActivities.set(event.toolCallId, activity);\n\t\t\t\tappendActivity(run.activities, activity);\n\t\t\t\trun.currentActivity = activity.summary;\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_update\") {\n\t\t\t\trun.currentActivity = activitySummary(event.toolName, event.args);\n\t\t\t\temitText();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_end\") {\n\t\t\t\tconst activity = activeActivities.get(event.toolCallId);\n\t\t\t\tif (activity) {\n\t\t\t\t\tactivity.status = event.isError ? \"failed\" : \"succeeded\";\n\t\t\t\t\tactivity.endedAt = Date.now();\n\t\t\t\t\tactivity.resultSummary = resultSummary(event.result);\n\t\t\t\t}\n\t\t\t\trun.currentActivity = undefined;\n\t\t\t\temitImmediate();\n\t\t\t}\n\t\t});\n\t\tconst abortListener = () => {\n\t\t\tvoid markAbort().catch(() => undefined);\n\t\t};\n\t\tunregisterAbort = options.registerAbort?.(markAbort);\n\t\tif (signal) signal.addEventListener(\"abort\", abortListener, { once: true });\n\t\ttry {\n\t\t\tawait session.prompt(task.prompt);\n\t\t} finally {\n\t\t\tif (signal) signal.removeEventListener(\"abort\", abortListener);\n\t\t}\n\t\tconst finalMessage = lastAssistantMessage(session);\n\t\trun.finalOutput = finalAssistantText(session.messages);\n\t\tconst error = assistantError(finalMessage);\n\t\tif (signal?.aborted || finalMessage?.stopReason === \"aborted\") {\n\t\t\trun.status = \"aborted\";\n\t\t\trun.error = boundText(error ?? \"Subagent was aborted.\", ERROR_TEXT_LIMIT);\n\t\t} else if (finalMessage?.stopReason === \"error\" || error) {\n\t\t\trun.status = \"failed\";\n\t\t\trun.error = boundText(error ?? \"Subagent failed.\", ERROR_TEXT_LIMIT);\n\t\t} else {\n\t\t\trun.status = \"completed\";\n\t\t}\n\t} catch (error) {\n\t\tif (signal?.aborted || run.status === \"aborted\") {\n\t\t\trun.status = \"aborted\";\n\t\t\trun.error = run.error ?? \"Subagent was aborted.\";\n\t\t} else {\n\t\t\trun.status = \"failed\";\n\t\t\trun.error = boundText(error instanceof Error ? error.message : String(error), ERROR_TEXT_LIMIT);\n\t\t}\n\t\tif (session) run.finalOutput = finalAssistantText(session.messages);\n\t} finally {\n\t\tcancelThrottled(emitTextProgress);\n\t\tunregisterAbort?.();\n\t\tunsubscribe?.();\n\t\tsession?.dispose();\n\t\trun.liveText = boundText(run.liveText, LIVE_TEXT_LIMIT);\n\t\trun.finalOutput = boundText(run.finalOutput, SINGLE_OUTPUT_LIMIT);\n\t\tif (run.error) run.error = boundText(run.error, ERROR_TEXT_LIMIT);\n\t\trun.endedAt = Date.now();\n\t\tonProgress?.();\n\t}\n\treturn run;\n}\n"]}