@astralyn/pi 0.84.4 → 0.84.6

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 (263) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/cli/args.d.ts +1 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +11 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/auth-command.d.ts.map +1 -1
  7. package/dist/cli/auth-command.js +5 -4
  8. package/dist/cli/auth-command.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +6 -1
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +11 -6
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/experimental.d.ts +4 -0
  14. package/dist/core/experimental.d.ts.map +1 -1
  15. package/dist/core/experimental.js +4 -0
  16. package/dist/core/experimental.js.map +1 -1
  17. package/dist/core/extensions/index.d.ts +1 -1
  18. package/dist/core/extensions/index.d.ts.map +1 -1
  19. package/dist/core/extensions/index.js.map +1 -1
  20. package/dist/core/extensions/runner.d.ts +1 -0
  21. package/dist/core/extensions/runner.d.ts.map +1 -1
  22. package/dist/core/extensions/runner.js +10 -0
  23. package/dist/core/extensions/runner.js.map +1 -1
  24. package/dist/core/extensions/types.d.ts +19 -1
  25. package/dist/core/extensions/types.d.ts.map +1 -1
  26. package/dist/core/extensions/types.js.map +1 -1
  27. package/dist/core/keybindings.d.ts +29 -0
  28. package/dist/core/keybindings.d.ts.map +1 -1
  29. package/dist/core/keybindings.js +4 -0
  30. package/dist/core/keybindings.js.map +1 -1
  31. package/dist/core/model-config.d.ts +5 -0
  32. package/dist/core/model-config.d.ts.map +1 -1
  33. package/dist/core/model-config.js +1 -0
  34. package/dist/core/model-config.js.map +1 -1
  35. package/dist/core/model-registry.d.ts +2 -0
  36. package/dist/core/model-registry.d.ts.map +1 -1
  37. package/dist/core/model-registry.js +4 -0
  38. package/dist/core/model-registry.js.map +1 -1
  39. package/dist/core/project-trust.js +2 -2
  40. package/dist/core/project-trust.js.map +1 -1
  41. package/dist/core/sdk.d.ts +5 -3
  42. package/dist/core/sdk.d.ts.map +1 -1
  43. package/dist/core/sdk.js +2 -1
  44. package/dist/core/sdk.js.map +1 -1
  45. package/dist/core/session-manager.js +2 -2
  46. package/dist/core/session-manager.js.map +1 -1
  47. package/dist/core/settings-manager.d.ts +6 -0
  48. package/dist/core/settings-manager.d.ts.map +1 -1
  49. package/dist/core/settings-manager.js +12 -0
  50. package/dist/core/settings-manager.js.map +1 -1
  51. package/dist/core/system-prompt.js +1 -1
  52. package/dist/core/system-prompt.js.map +1 -1
  53. package/dist/core/tools/bash.d.ts +7 -1
  54. package/dist/core/tools/bash.d.ts.map +1 -1
  55. package/dist/core/tools/bash.js +4 -2
  56. package/dist/core/tools/bash.js.map +1 -1
  57. package/dist/core/tools/edit.d.ts.map +1 -1
  58. package/dist/core/tools/edit.js +2 -0
  59. package/dist/core/tools/edit.js.map +1 -1
  60. package/dist/core/tools/find.js +1 -1
  61. package/dist/core/tools/find.js.map +1 -1
  62. package/dist/core/tools/grep.js +1 -1
  63. package/dist/core/tools/grep.js.map +1 -1
  64. package/dist/core/tools/read.d.ts.map +1 -1
  65. package/dist/core/tools/read.js +2 -0
  66. package/dist/core/tools/read.js.map +1 -1
  67. package/dist/core/tools/write.d.ts.map +1 -1
  68. package/dist/core/tools/write.js +2 -0
  69. package/dist/core/tools/write.js.map +1 -1
  70. package/dist/extensions/background/index.d.ts +149 -0
  71. package/dist/extensions/background/index.d.ts.map +1 -0
  72. package/dist/extensions/background/index.js +666 -0
  73. package/dist/extensions/background/index.js.map +1 -0
  74. package/dist/extensions/background/manager.d.ts +95 -0
  75. package/dist/extensions/background/manager.d.ts.map +1 -0
  76. package/dist/extensions/background/manager.js +421 -0
  77. package/dist/extensions/background/manager.js.map +1 -0
  78. package/dist/extensions/background/registry.d.ts +220 -0
  79. package/dist/extensions/background/registry.d.ts.map +1 -0
  80. package/dist/extensions/background/registry.js +589 -0
  81. package/dist/extensions/background/registry.js.map +1 -0
  82. package/dist/extensions/background/render.d.ts +50 -0
  83. package/dist/extensions/background/render.d.ts.map +1 -0
  84. package/dist/extensions/background/render.js +260 -0
  85. package/dist/extensions/background/render.js.map +1 -0
  86. package/dist/extensions/index.d.ts.map +1 -1
  87. package/dist/extensions/index.js +2 -0
  88. package/dist/extensions/index.js.map +1 -1
  89. package/dist/extensions/subagent/activity.d.ts +3 -6
  90. package/dist/extensions/subagent/activity.d.ts.map +1 -1
  91. package/dist/extensions/subagent/activity.js +9 -93
  92. package/dist/extensions/subagent/activity.js.map +1 -1
  93. package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
  94. package/dist/extensions/subagent/agents-command.js +270 -169
  95. package/dist/extensions/subagent/agents-command.js.map +1 -1
  96. package/dist/extensions/subagent/agents.d.ts +5 -6
  97. package/dist/extensions/subagent/agents.d.ts.map +1 -1
  98. package/dist/extensions/subagent/agents.js +28 -192
  99. package/dist/extensions/subagent/agents.js.map +1 -1
  100. package/dist/extensions/subagent/budget.d.ts +15 -0
  101. package/dist/extensions/subagent/budget.d.ts.map +1 -0
  102. package/dist/extensions/subagent/budget.js +96 -0
  103. package/dist/extensions/subagent/budget.js.map +1 -0
  104. package/dist/extensions/subagent/cancellation.d.ts +29 -0
  105. package/dist/extensions/subagent/cancellation.d.ts.map +1 -0
  106. package/dist/extensions/subagent/cancellation.js +73 -0
  107. package/dist/extensions/subagent/cancellation.js.map +1 -0
  108. package/dist/extensions/subagent/constants.d.ts +4 -5
  109. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  110. package/dist/extensions/subagent/constants.js +11 -7
  111. package/dist/extensions/subagent/constants.js.map +1 -1
  112. package/dist/extensions/subagent/index.d.ts +0 -3
  113. package/dist/extensions/subagent/index.d.ts.map +1 -1
  114. package/dist/extensions/subagent/index.js +59 -208
  115. package/dist/extensions/subagent/index.js.map +1 -1
  116. package/dist/extensions/subagent/model-selection.d.ts +16 -0
  117. package/dist/extensions/subagent/model-selection.d.ts.map +1 -0
  118. package/dist/extensions/subagent/model-selection.js +51 -0
  119. package/dist/extensions/subagent/model-selection.js.map +1 -0
  120. package/dist/extensions/subagent/render.d.ts +7 -2
  121. package/dist/extensions/subagent/render.d.ts.map +1 -1
  122. package/dist/extensions/subagent/render.js +219 -576
  123. package/dist/extensions/subagent/render.js.map +1 -1
  124. package/dist/extensions/subagent/resolve.d.ts +2 -2
  125. package/dist/extensions/subagent/resolve.d.ts.map +1 -1
  126. package/dist/extensions/subagent/resolve.js +24 -35
  127. package/dist/extensions/subagent/resolve.js.map +1 -1
  128. package/dist/extensions/subagent/runner.d.ts +4 -6
  129. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  130. package/dist/extensions/subagent/runner.js +101 -316
  131. package/dist/extensions/subagent/runner.js.map +1 -1
  132. package/dist/extensions/subagent/schema.d.ts +4 -10
  133. package/dist/extensions/subagent/schema.d.ts.map +1 -1
  134. package/dist/extensions/subagent/schema.js +8 -13
  135. package/dist/extensions/subagent/schema.js.map +1 -1
  136. package/dist/extensions/subagent/sdk-runner.d.ts +13 -11
  137. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  138. package/dist/extensions/subagent/sdk-runner.js +169 -161
  139. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  140. package/dist/extensions/subagent/settings.d.ts +2 -2
  141. package/dist/extensions/subagent/settings.d.ts.map +1 -1
  142. package/dist/extensions/subagent/settings.js +27 -14
  143. package/dist/extensions/subagent/settings.js.map +1 -1
  144. package/dist/extensions/subagent/state.d.ts +89 -0
  145. package/dist/extensions/subagent/state.d.ts.map +1 -0
  146. package/dist/extensions/subagent/state.js +294 -0
  147. package/dist/extensions/subagent/state.js.map +1 -0
  148. package/dist/extensions/subagent/text.d.ts +7 -0
  149. package/dist/extensions/subagent/text.d.ts.map +1 -0
  150. package/dist/extensions/subagent/text.js +91 -0
  151. package/dist/extensions/subagent/text.js.map +1 -0
  152. package/dist/extensions/subagent/types.d.ts +16 -43
  153. package/dist/extensions/subagent/types.d.ts.map +1 -1
  154. package/dist/extensions/subagent/types.js.map +1 -1
  155. package/dist/extensions/subagent/ui/choices.d.ts +36 -0
  156. package/dist/extensions/subagent/ui/choices.d.ts.map +1 -0
  157. package/dist/extensions/subagent/ui/choices.js +54 -0
  158. package/dist/extensions/subagent/ui/choices.js.map +1 -0
  159. package/dist/extensions/subagent/ui/model-list.d.ts +4 -3
  160. package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
  161. package/dist/extensions/subagent/ui/model-list.js +20 -22
  162. package/dist/extensions/subagent/ui/model-list.js.map +1 -1
  163. package/dist/index.d.ts +2 -2
  164. package/dist/index.d.ts.map +1 -1
  165. package/dist/index.js.map +1 -1
  166. package/dist/main.d.ts.map +1 -1
  167. package/dist/main.js +5 -1
  168. package/dist/main.js.map +1 -1
  169. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  170. package/dist/modes/interactive/components/model-selector.js +2 -1
  171. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  172. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  173. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/settings-selector.js +10 -0
  175. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  176. package/dist/modes/interactive/interactive-mode.d.ts +8 -2
  177. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  178. package/dist/modes/interactive/interactive-mode.js +77 -25
  179. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  180. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  181. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  182. package/dist/modes/interactive/model-catalog-refresh.js +36 -0
  183. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  184. package/dist/modes/interactive/theme/dark.json +2 -0
  185. package/dist/modes/interactive/theme/light.json +2 -0
  186. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  187. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  188. package/dist/modes/interactive/theme/theme-controller.js +23 -10
  189. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  190. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  191. package/dist/modes/interactive/theme/theme.d.ts +5 -3
  192. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  193. package/dist/modes/interactive/theme/theme.js +12 -2
  194. package/dist/modes/interactive/theme/theme.js.map +1 -1
  195. package/dist/modes/json-event.d.ts +4 -1
  196. package/dist/modes/json-event.d.ts.map +1 -1
  197. package/dist/modes/json-event.js +5 -2
  198. package/dist/modes/json-event.js.map +1 -1
  199. package/dist/package-manager-cli.js +1 -1
  200. package/dist/package-manager-cli.js.map +1 -1
  201. package/dist/server/create-harness.d.ts.map +1 -1
  202. package/dist/server/create-harness.js +2 -0
  203. package/dist/server/create-harness.js.map +1 -1
  204. package/dist/utils/tools-manager.d.ts +10 -1
  205. package/dist/utils/tools-manager.d.ts.map +1 -1
  206. package/dist/utils/tools-manager.js +14 -19
  207. package/dist/utils/tools-manager.js.map +1 -1
  208. package/docs/bundled/README.md +1 -0
  209. package/docs/bundled/extensions/background.md +99 -0
  210. package/docs/bundled/extensions/subagent.md +83 -71
  211. package/docs/compaction.md +6 -6
  212. package/docs/custom-provider.md +1 -1
  213. package/docs/docs.json +4 -0
  214. package/docs/environment-variables.md +8 -2
  215. package/docs/extensions.md +19 -2
  216. package/docs/json.md +6 -4
  217. package/docs/keybindings.md +9 -2
  218. package/docs/rpc.md +15 -4
  219. package/docs/sdk.md +9 -0
  220. package/docs/settings.md +31 -0
  221. package/docs/terminal-setup.md +23 -2
  222. package/docs/themes.md +24 -3
  223. package/docs/tui.md +2 -2
  224. package/docs/usage.md +4 -3
  225. package/examples/README.md +1 -1
  226. package/examples/extensions/README.md +0 -1
  227. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  228. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  229. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  230. package/examples/extensions/gondolin/package-lock.json +2 -2
  231. package/examples/extensions/gondolin/package.json +1 -1
  232. package/examples/extensions/sandbox/package-lock.json +2 -2
  233. package/examples/extensions/sandbox/package.json +1 -1
  234. package/examples/extensions/with-deps/package-lock.json +2 -2
  235. package/examples/extensions/with-deps/package.json +1 -1
  236. package/npm-shrinkwrap.json +170 -221
  237. package/package.json +6 -6
  238. package/dist/extensions/subagent/display-name.d.ts +0 -6
  239. package/dist/extensions/subagent/display-name.d.ts.map +0 -1
  240. package/dist/extensions/subagent/display-name.js +0 -13
  241. package/dist/extensions/subagent/display-name.js.map +0 -1
  242. package/dist/extensions/subagent/retry.d.ts +0 -17
  243. package/dist/extensions/subagent/retry.d.ts.map +0 -1
  244. package/dist/extensions/subagent/retry.js +0 -41
  245. package/dist/extensions/subagent/retry.js.map +0 -1
  246. package/dist/extensions/subagent/ui/profile-editor.d.ts +0 -54
  247. package/dist/extensions/subagent/ui/profile-editor.d.ts.map +0 -1
  248. package/dist/extensions/subagent/ui/profile-editor.js +0 -154
  249. package/dist/extensions/subagent/ui/profile-editor.js.map +0 -1
  250. package/dist/extensions/subagent/ui/profile-picker.d.ts +0 -32
  251. package/dist/extensions/subagent/ui/profile-picker.d.ts.map +0 -1
  252. package/dist/extensions/subagent/ui/profile-picker.js +0 -149
  253. package/dist/extensions/subagent/ui/profile-picker.js.map +0 -1
  254. package/examples/extensions/subagent/README.md +0 -175
  255. package/examples/extensions/subagent/agents/planner.md +0 -37
  256. package/examples/extensions/subagent/agents/reviewer.md +0 -35
  257. package/examples/extensions/subagent/agents/scout.md +0 -50
  258. package/examples/extensions/subagent/agents/worker.md +0 -24
  259. package/examples/extensions/subagent/agents.ts +0 -126
  260. package/examples/extensions/subagent/index.ts +0 -1009
  261. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  262. package/examples/extensions/subagent/prompts/implement.md +0 -10
  263. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
@@ -1,13 +1,12 @@
1
- import { relative } from "node:path";
2
1
  import { isRetryableAssistantError } from "@earendil-works/pi-ai/compat";
3
- import { sleep } from "../../utils/sleep.js";
4
- import { boundText, emptyUsage, mergeUsage, tailText, toNestedUsage } from "./activity.js";
5
- import { DETAILS_ACTIVITY_LIMIT, DETAILS_OUTPUT_LIMIT, ERROR_TEXT_LIMIT, MAX_CONCURRENCY, MAX_TASKS, PARALLEL_OUTPUT_LIMIT, PARALLEL_TASK_OUTPUT_LIMIT, RETRY_ERROR_TEXT_LIMIT, SINGLE_OUTPUT_LIMIT, TASK_RETRY_BASE_DELAY_MS, TASK_RETRY_LIMIT, } from "./constants.js";
2
+ import { emptyUsage, mergeUsage, toNestedUsage } from "./activity.js";
3
+ import { boundSubagentDetails, resultContent } from "./budget.js";
4
+ import { abortableSleep, createRunCancellation } from "./cancellation.js";
5
+ import { MAX_CONCURRENCY, MAX_TASKS, TASK_RETRY_BASE_DELAY_MS, TASK_RETRY_LIMIT } from "./constants.js";
6
6
  import { resolveSubagentTask } from "./resolve.js";
7
- import { beginSubagentRetry, clearSubagentRetry } from "./retry.js";
8
7
  import { runSdkTask } from "./sdk-runner.js";
9
8
  import { loadSubagentConfig } from "./settings.js";
10
- const EMPTY_OUTPUT = "(Subagent completed but returned no output.)";
9
+ import { createRunState, isSubagentError as isSubagentErrorSelector, reduceRun, statusOf, toRunDetails, versionSum, } from "./state.js";
11
10
  export class ConcurrencyGate {
12
11
  constructor(limit = MAX_CONCURRENCY) {
13
12
  this.active = 0;
@@ -50,159 +49,16 @@ export class ConcurrencyGate {
50
49
  }
51
50
  }
52
51
  }
53
- function runId(index) {
54
- return `subagent-${index + 1}`;
55
- }
56
- function createRun(task, index, parentCwd) {
57
- return {
58
- id: runId(index),
59
- agent: task.agent.name,
60
- agentSource: task.agent.source,
61
- description: task.description,
62
- prompt: task.prompt,
63
- // Display-only relative path; the worker session itself uses the
64
- // resolved absolute task.cwd. Empty means "same as the parent".
65
- cwd: relative(parentCwd, task.cwd),
66
- model: `${task.model.provider}/${task.model.id}`,
67
- thinking: task.thinking,
68
- status: "queued",
69
- activities: [],
70
- liveText: "",
71
- finalOutput: "",
72
- usage: emptyUsage(),
73
- };
74
- }
75
52
  function aggregateUsage(runs) {
76
53
  const usage = emptyUsage();
77
54
  for (const run of runs)
78
55
  mergeUsage(usage, run.usage);
79
56
  return usage;
80
57
  }
81
- function detailsSize(details) {
82
- return Buffer.byteLength(JSON.stringify(details), "utf8");
83
- }
84
- export function boundSubagentDetails(details) {
85
- const perRunBudget = Math.max(1_024, Math.floor((DETAILS_OUTPUT_LIMIT - 8 * 1024) / Math.max(1, details.runs.length)));
86
- const outputLimit = Math.min(SINGLE_OUTPUT_LIMIT, Math.max(1_024, perRunBudget - 7 * 1024));
87
- const bounded = {
88
- ...details,
89
- runs: details.runs.map((run) => ({
90
- ...run,
91
- prompt: boundText(run.prompt, 1_024),
92
- cwd: boundText(run.cwd, 1_024),
93
- currentActivity: run.currentActivity ? boundText(run.currentActivity, 512) : undefined,
94
- retry: run.retry ? { ...run.retry, error: boundText(run.retry.error, RETRY_ERROR_TEXT_LIMIT) } : undefined,
95
- activities: run.activities.slice(-DETAILS_ACTIVITY_LIMIT).map((activity) => ({
96
- ...activity,
97
- summary: boundText(activity.summary, 256),
98
- resultSummary: activity.resultSummary ? boundText(activity.resultSummary, 256) : undefined,
99
- })),
100
- // liveText is a tail by construction: keep the newest lines, not the
101
- // head, or the transcript's live tail would freeze at the 1KB mark.
102
- liveText: tailText(run.liveText, 1_024),
103
- finalOutput: boundText(run.finalOutput, outputLimit),
104
- error: run.error ? boundText(run.error, 1_024) : undefined,
105
- })),
106
- };
107
- const fields = [];
108
- for (const run of bounded.runs) {
109
- fields.push({
110
- get: () => run.prompt,
111
- set: (value) => {
112
- run.prompt = value;
113
- },
114
- }, {
115
- get: () => run.cwd,
116
- set: (value) => {
117
- run.cwd = value;
118
- },
119
- }, {
120
- get: () => run.currentActivity ?? "",
121
- set: (value) => {
122
- run.currentActivity = value || undefined;
123
- },
124
- }, {
125
- get: () => run.liveText,
126
- set: (value) => {
127
- run.liveText = value;
128
- },
129
- }, {
130
- get: () => run.finalOutput,
131
- set: (value) => {
132
- run.finalOutput = value;
133
- },
134
- }, {
135
- get: () => run.error ?? "",
136
- set: (value) => {
137
- run.error = value || undefined;
138
- },
139
- });
140
- for (const activity of run.activities) {
141
- fields.push({
142
- get: () => activity.summary,
143
- set: (value) => {
144
- activity.summary = value;
145
- },
146
- }, {
147
- get: () => activity.resultSummary ?? "",
148
- set: (value) => {
149
- activity.resultSummary = value || undefined;
150
- },
151
- });
152
- }
153
- }
154
- while (detailsSize(bounded) > DETAILS_OUTPUT_LIMIT) {
155
- const largest = fields
156
- .map((field) => ({ field, size: Buffer.byteLength(field.get(), "utf8") }))
157
- .sort((left, right) => right.size - left.size)[0];
158
- if (!largest || largest.size === 0)
159
- break;
160
- const overflow = detailsSize(bounded) - DETAILS_OUTPUT_LIMIT;
161
- largest.field.set(boundText(largest.field.get(), Math.max(0, largest.size - overflow)));
162
- }
163
- return bounded;
164
- }
165
- function statusOf(runs) {
166
- if (runs.some((run) => run.status === "aborted"))
167
- return "aborted";
168
- if (runs.some((run) => run.status === "failed"))
169
- return "failed";
170
- if (runs.some((run) => run.status === "queued" || run.status === "running"))
171
- return "running";
172
- return "completed";
173
- }
174
- function statusText(details) {
175
- const running = details.runs.filter((run) => run.status === "running").length;
176
- const queued = details.runs.filter((run) => run.status === "queued").length;
177
- const completed = details.runs.filter((run) => run.status === "completed").length;
178
- const failed = details.runs.filter((run) => run.status === "failed").length;
179
- const aborted = details.runs.filter((run) => run.status === "aborted").length;
180
- if (details.mode === "single") {
181
- const run = details.runs[0];
182
- if (run?.currentActivity)
183
- return run.currentActivity;
184
- if (!run ||
185
- (run.status === "running" && run.usage.turns === 0 && run.usage.toolUses === 0 && run.liveText.length === 0)) {
186
- return "Initializing…";
187
- }
188
- return run.status === "running" ? "Thinking…" : run.status;
189
- }
190
- const parts = [`${completed}/${details.runs.length} complete`];
191
- if (running)
192
- parts.push(`${running} running`);
193
- if (queued)
194
- parts.push(`${queued} queued`);
195
- if (failed)
196
- parts.push(`${failed} failed`);
197
- if (aborted)
198
- parts.push(`${aborted} aborted`);
199
- return parts.join(" · ");
200
- }
201
- function emitDetails(mode, runs, startedAt, onUpdate) {
58
+ function emitDetails(runs, startedAt, onUpdate) {
202
59
  const details = {
203
- mode,
204
60
  status: statusOf(runs),
205
- runs: [...runs],
61
+ runs: runs.map(toRunDetails),
206
62
  startedAt,
207
63
  usage: aggregateUsage(runs),
208
64
  };
@@ -217,8 +73,14 @@ function validateTaskCount(tasks) {
217
73
  }
218
74
  async function resolveTasks(tasks, options) {
219
75
  validateTaskCount(tasks);
76
+ // One config load and one resolution pass for the whole batch: every
77
+ // task/profile/cwd/model is settled before any run is created or any
78
+ // worker starts, so a failing task cannot strand half-initialized runs.
220
79
  const config = await loadSubagentConfig(options.agentDir);
221
- return Promise.all(tasks.map((task) => resolveSubagentTask(task, options.parentCwd, options.agents, options.parent, options.agentDir, config)));
80
+ return Promise.all(tasks.map((task, index) => resolveSubagentTask(task, options.parentCwd, options.parent, options.agentDir, config).catch((error) => {
81
+ const message = error instanceof Error ? error.message : String(error);
82
+ throw new Error(`Subagent task tasks[${index}] failed to resolve: ${message}`);
83
+ })));
222
84
  }
223
85
  // Reuses pi-ai's provider-error classification by wrapping the stored error
224
86
  // text in the assistant-message shape it inspects.
@@ -235,188 +97,111 @@ function isRetryableRunError(error) {
235
97
  function shouldRetryTask(run) {
236
98
  return (run.status === "failed" && run.usage.turns === 0 && run.usage.toolUses === 0 && isRetryableRunError(run.error));
237
99
  }
238
- function resetRunForRetry(run, attempt, maxAttempts, delayMs) {
239
- const error = run.error ?? "Subagent failed before retry.";
240
- run.status = "queued";
241
- run.error = undefined;
242
- run.startedAt = undefined;
243
- run.endedAt = undefined;
244
- run.finalOutput = "";
245
- run.liveText = "";
246
- run.activities.length = 0;
247
- run.usage = emptyUsage();
248
- beginSubagentRetry(run, { attempt, maxAttempts, delayMs, error });
249
- }
250
- async function waitForTaskRetry(delayMs, options) {
251
- const controller = new AbortController();
252
- const abort = async () => controller.abort();
253
- const unregisterAbort = options.registerAbort?.(abort);
254
- const abortListener = () => controller.abort();
255
- if (options.signal?.aborted)
256
- controller.abort();
257
- else
258
- options.signal?.addEventListener("abort", abortListener, { once: true });
259
- try {
260
- await sleep(delayMs, controller.signal);
261
- }
262
- finally {
263
- options.signal?.removeEventListener("abort", abortListener);
264
- unregisterAbort?.();
265
- }
266
- }
267
- async function runWithGate(task, run, options, onProgress) {
268
- onProgress();
269
- let release;
270
- try {
271
- release = await options.gate.acquire(options.signal);
272
- if (options.signal?.aborted) {
273
- run.status = "aborted";
274
- run.error = "Subagent was aborted while queued.";
275
- return run;
276
- }
277
- const baseDelayMs = options.taskRetryBaseDelayMs ?? TASK_RETRY_BASE_DELAY_MS;
278
- for (let attempt = 0;; attempt++) {
279
- clearSubagentRetry(run);
280
- const result = await runSdkTask({
100
+ // The gate slot is held only while a worker session actually runs. Backoff
101
+ // waits outside the slot (release, sleep, reacquire) so a retrying task
102
+ // cannot starve queued tasks, and aborting during the wait settles the run
103
+ // without occupying the gate.
104
+ async function runWithGate(task, scope, options, dispatch, getState, onProgress) {
105
+ const baseDelayMs = options.taskRetryBaseDelayMs ?? TASK_RETRY_BASE_DELAY_MS;
106
+ for (let attempt = 0;; attempt++) {
107
+ dispatch({ type: "retry_started" });
108
+ let release;
109
+ let delayMs = 0;
110
+ try {
111
+ release = await options.gate.acquire(scope.signal);
112
+ if (scope.signal.aborted) {
113
+ dispatch({ type: "abort_while_queued", endedAt: Date.now() });
114
+ return;
115
+ }
116
+ dispatch({ type: "slot_acquired", startedAt: Date.now() });
117
+ await runSdkTask({
281
118
  task,
282
- run,
119
+ scope,
120
+ dispatch,
283
121
  modelRuntime: options.modelRuntime,
284
122
  agentDir: options.agentDir,
285
123
  projectTrusted: options.projectTrusted,
286
- signal: options.signal,
287
124
  onProgress,
288
- registerAbort: options.registerAbort,
289
125
  });
290
- if (attempt >= TASK_RETRY_LIMIT || options.signal?.aborted || !shouldRetryTask(result))
291
- return result;
292
- const delayMs = baseDelayMs * 2 ** attempt;
293
- resetRunForRetry(run, attempt + 1, TASK_RETRY_LIMIT, delayMs);
294
- onProgress();
295
- try {
296
- await waitForTaskRetry(delayMs, options);
126
+ const state = getState();
127
+ if (attempt >= TASK_RETRY_LIMIT || scope.signal.aborted || !shouldRetryTask(state))
128
+ return;
129
+ delayMs = baseDelayMs * 2 ** attempt;
130
+ dispatch({
131
+ type: "retry_scheduled",
132
+ attempt: attempt + 1,
133
+ maxAttempts: TASK_RETRY_LIMIT,
134
+ deadline: Date.now() + delayMs,
135
+ error: state.error,
136
+ });
137
+ }
138
+ catch (error) {
139
+ if (scope.signal.aborted) {
140
+ dispatch({ type: "abort_while_queued", endedAt: Date.now() });
297
141
  }
298
- catch {
299
- clearSubagentRetry(run);
300
- run.status = "aborted";
301
- run.error = "Subagent was aborted while waiting to retry.";
302
- run.endedAt = Date.now();
303
- onProgress();
304
- return run;
142
+ else {
143
+ dispatch({
144
+ type: "settle",
145
+ verdict: "failed",
146
+ report: "",
147
+ error: error instanceof Error ? error.message : String(error),
148
+ endedAt: Date.now(),
149
+ });
305
150
  }
151
+ return;
306
152
  }
307
- }
308
- catch (error) {
309
- clearSubagentRetry(run);
310
- run.status = options.signal?.aborted ? "aborted" : "failed";
311
- run.error = boundText(error instanceof Error ? error.message : String(error), ERROR_TEXT_LIMIT);
312
- run.endedAt = Date.now();
313
- onProgress();
314
- return run;
315
- }
316
- finally {
317
- release?.();
318
- }
319
- }
320
- function resultContent(details) {
321
- if (details.mode === "single") {
322
- const run = details.runs[0];
323
- if (!run)
324
- return "Subagent produced no run.";
325
- if (run.status === "failed" || run.status === "aborted") {
326
- return boundText(`${run.status === "aborted" ? "Subagent aborted" : "Subagent failed"}: ${run.error ?? "unknown error"}${run.finalOutput ? `\n\nPartial response:\n${run.finalOutput}` : ""}`, SINGLE_OUTPUT_LIMIT);
153
+ finally {
154
+ release?.();
155
+ }
156
+ try {
157
+ await abortableSleep(delayMs, scope);
158
+ }
159
+ catch {
160
+ dispatch({ type: "abort_while_retrying", endedAt: Date.now() });
161
+ return;
327
162
  }
328
- return run.finalOutput || EMPTY_OUTPUT;
329
- }
330
- const sections = details.runs.map((run) => {
331
- const output = run.finalOutput || run.error || EMPTY_OUTPUT;
332
- return `### ${run.description} (${run.agent}) — ${run.status}\n\n${boundText(output, PARALLEL_TASK_OUTPUT_LIMIT)}`;
333
- });
334
- return boundText(sections.join("\n\n---\n\n"), PARALLEL_OUTPUT_LIMIT);
335
- }
336
- function invocationMode(params) {
337
- const provided = [];
338
- if (params.prompt != null)
339
- provided.push("prompt");
340
- if (params.tasks != null)
341
- provided.push("tasks");
342
- if (provided.length !== 1) {
343
- throw new Error(provided.length === 0
344
- ? "Provide exactly one subagent mode: prompt (single task) or tasks (parallel tasks); none was provided."
345
- : `Provide exactly one subagent mode: received ${provided.join(", ")}. Keep one and set the unused mode fields to null or omit them.`);
346
- }
347
- if (params.tasks != null) {
348
- return { mode: "parallel", tasks: params.tasks };
349
163
  }
350
- if (!params.description)
351
- throw new Error("description is required for single mode.");
352
- return {
353
- mode: "single",
354
- tasks: [
355
- {
356
- agent: params.agent,
357
- description: params.description,
358
- prompt: params.prompt,
359
- cwd: params.cwd,
360
- },
361
- ],
362
- };
363
- }
364
- // Cheap change detector: consecutive events that alter nothing user-visible
365
- // skip the bounded-details serialization in emitDetails entirely. Every
366
- // activity contributes its status, not just the last one: agent-core can end
367
- // parallel tool executions out of order, and a mid-list row settling then
368
- // would otherwise slip past the detector.
369
- export function progressKey(runs) {
370
- return runs
371
- .map((run) => {
372
- return [
373
- run.status,
374
- run.currentActivity ?? "",
375
- run.activities.length,
376
- run.activities.map((activity) => `${activity.status}:${activity.resultSummary ?? ""}`).join(","),
377
- run.retry?.attempt ?? "",
378
- run.retry?.maxAttempts ?? "",
379
- run.retry?.deadline ?? "",
380
- run.retry?.error ?? "",
381
- run.liveText.length,
382
- run.liveText.slice(-24),
383
- run.finalOutput.length,
384
- run.usage.turns,
385
- run.usage.toolUses,
386
- run.usage.totalTokens,
387
- run.error ?? "",
388
- ].join("|");
389
- })
390
- .join("~");
391
- }
392
- export function isSubagentError(details) {
393
- if (details.status !== "failed" && details.status !== "aborted")
394
- return false;
395
- // A batch with any successful run is a partial result, not an error:
396
- // per-run status is already reported in the content sections.
397
- return !details.runs.some((run) => run.status === "completed");
398
164
  }
399
165
  export async function runSubagentInvocation(options) {
400
- const { mode, tasks } = invocationMode(options.params);
166
+ // Defensive count check: the schema already enforces 1..MAX_TASKS, but
167
+ // strict providers can bypass minItems, so validate before any work.
168
+ const tasks = options.params.tasks ?? [];
401
169
  const resolved = await resolveTasks(tasks, options);
402
- const runs = resolved.map((task, index) => createRun(task, index, options.parentCwd));
170
+ const runs = resolved.map((task, index) => createRunState(task, index, options.batchId, options.parentCwd));
403
171
  const startedAt = Date.now();
404
- let latestDetails = emitDetails(mode, runs, startedAt, options.onUpdate);
405
- let lastProgressKey = progressKey(runs);
172
+ // Every run's cancellation scope exists and is registered before any
173
+ // gate work starts, so a shutdown snapshot can never miss a queued task.
174
+ const scopes = runs.map(() => createRunCancellation(options.signal));
175
+ const unregisterScopes = scopes.map((scope) => options.registerAbort?.(scope.abort));
176
+ let lastVersion = versionSum(runs);
406
177
  const progress = () => {
407
- const key = progressKey(runs);
408
- if (key === lastProgressKey)
178
+ const version = versionSum(runs);
179
+ if (version === lastVersion)
409
180
  return;
410
- lastProgressKey = key;
411
- latestDetails = emitDetails(mode, runs, startedAt, options.onUpdate);
181
+ lastVersion = version;
182
+ emitDetails(runs, startedAt, options.onUpdate);
183
+ };
184
+ const dispatch = (index, event) => {
185
+ runs[index] = reduceRun(runs[index], event);
186
+ progress();
412
187
  };
413
- if (mode === "single") {
414
- await runWithGate(resolved[0], runs[0], options, progress);
188
+ let latestDetails = emitDetails(runs, startedAt, options.onUpdate);
189
+ // Every task runs concurrently through the shared gate; Promise.all keeps
190
+ // result order identical to input order. There is no single-task branch:
191
+ // one task is just a batch of one.
192
+ try {
193
+ await Promise.all(resolved.map((task, index) => {
194
+ const dispatchToRun = (event) => dispatch(index, event);
195
+ return runWithGate(task, scopes[index], options, dispatchToRun, () => runs[index], progress);
196
+ }));
415
197
  }
416
- else {
417
- await Promise.all(resolved.map((task, index) => runWithGate(task, runs[index], options, progress)));
198
+ finally {
199
+ for (const unregister of unregisterScopes)
200
+ unregister?.();
201
+ for (const scope of scopes)
202
+ scope.dispose();
418
203
  }
419
- latestDetails = emitDetails(mode, runs, startedAt, undefined);
204
+ latestDetails = emitDetails(runs, startedAt, undefined);
420
205
  latestDetails.endedAt = Date.now();
421
206
  // Error classification lives in the tool_result handler (index.ts), the
422
207
  // only channel that reaches the session transcript and export.
@@ -426,7 +211,7 @@ export async function runSubagentInvocation(options) {
426
211
  usage: toNestedUsage(latestDetails.usage),
427
212
  };
428
213
  }
429
- export function statusSummary(details) {
430
- return statusText(details);
214
+ export function isSubagentError(details) {
215
+ return isSubagentErrorSelector(details);
431
216
  }
432
217
  //# sourceMappingURL=runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/extensions/subagent/runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { relative } from \"node:path\";\nimport { isRetryableAssistantError } from \"@earendil-works/pi-ai/compat\";\nimport type { ModelRuntime } from \"../../core/model-runtime.ts\";\nimport { sleep } from \"../../utils/sleep.ts\";\nimport { boundText, emptyUsage, mergeUsage, tailText, toNestedUsage } from \"./activity.ts\";\nimport {\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\tRETRY_ERROR_TEXT_LIMIT,\n\tSINGLE_OUTPUT_LIMIT,\n\tTASK_RETRY_BASE_DELAY_MS,\n\tTASK_RETRY_LIMIT,\n} from \"./constants.ts\";\nimport { type ParentModelContext, resolveSubagentTask } from \"./resolve.ts\";\nimport { beginSubagentRetry, clearSubagentRetry } from \"./retry.ts\";\nimport type { SubagentParams, SubagentTask } from \"./schema.ts\";\nimport { runSdkTask } from \"./sdk-runner.ts\";\nimport { loadSubagentConfig } from \"./settings.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.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\tprojectTrusted: boolean;\n\tsignal?: AbortSignal;\n\tgate: ConcurrencyGate;\n\tonUpdate?: (details: SubagentDetails) => void;\n\tregisterAbort?: (abort: () => Promise<void>) => () => void;\n\t/** Test hook: overrides the task-retry backoff base delay. */\n\ttaskRetryBaseDelayMs?: number;\n}\n\nfunction runId(index: number): string {\n\treturn `subagent-${index + 1}`;\n}\n\nfunction createRun(task: ResolvedSubagentTask, index: number, parentCwd: string): 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\t// Display-only relative path; the worker session itself uses the\n\t\t// resolved absolute task.cwd. Empty means \"same as the parent\".\n\t\tcwd: relative(parentCwd, 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};\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\tretry: run.retry ? { ...run.retry, error: boundText(run.retry.error, RETRY_ERROR_TEXT_LIMIT) } : 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\t// liveText is a tail by construction: keep the newest lines, not the\n\t\t\t// head, or the transcript's live tail would freeze at the 1KB mark.\n\t\t\tliveText: tailText(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\tconst parts = [`${completed}/${details.runs.length} complete`];\n\tif (running) parts.push(`${running} running`);\n\tif (queued) parts.push(`${queued} queued`);\n\tif (failed) parts.push(`${failed} failed`);\n\tif (aborted) parts.push(`${aborted} aborted`);\n\treturn parts.join(\" · \");\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 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\tconst config = await loadSubagentConfig(options.agentDir);\n\treturn Promise.all(\n\t\ttasks.map((task) =>\n\t\t\tresolveSubagentTask(task, options.parentCwd, options.agents, options.parent, options.agentDir, config),\n\t\t),\n\t);\n}\n\n// Reuses pi-ai's provider-error classification by wrapping the stored error\n// text in the assistant-message shape it inspects.\nfunction isRetryableRunError(error: string | undefined): boolean {\n\tif (!error) return false;\n\tconst probe = { role: \"assistant\", content: [], stopReason: \"error\", errorMessage: error };\n\treturn isRetryableAssistantError(probe as unknown as Parameters<typeof isRetryableAssistantError>[0]);\n}\n\n// Session-level auto-retry already covers errors that happen inside the agent\n// loop; this catches the paths that bypass it (preflight throws such as auth\n// checks). Only a run that produced nothing is retried, so partial work is\n// never discarded.\nfunction shouldRetryTask(run: SubagentRunDetails): boolean {\n\treturn (\n\t\trun.status === \"failed\" && run.usage.turns === 0 && run.usage.toolUses === 0 && isRetryableRunError(run.error)\n\t);\n}\n\nfunction resetRunForRetry(run: SubagentRunDetails, attempt: number, maxAttempts: number, delayMs: number): void {\n\tconst error = run.error ?? \"Subagent failed before retry.\";\n\trun.status = \"queued\";\n\trun.error = undefined;\n\trun.startedAt = undefined;\n\trun.endedAt = undefined;\n\trun.finalOutput = \"\";\n\trun.liveText = \"\";\n\trun.activities.length = 0;\n\trun.usage = emptyUsage();\n\tbeginSubagentRetry(run, { attempt, maxAttempts, delayMs, error });\n}\n\nasync function waitForTaskRetry(\n\tdelayMs: number,\n\toptions: Pick<SubagentInvocationOptions, \"signal\" | \"registerAbort\">,\n): Promise<void> {\n\tconst controller = new AbortController();\n\tconst abort = async (): Promise<void> => controller.abort();\n\tconst unregisterAbort = options.registerAbort?.(abort);\n\tconst abortListener = () => controller.abort();\n\tif (options.signal?.aborted) controller.abort();\n\telse options.signal?.addEventListener(\"abort\", abortListener, { once: true });\n\ttry {\n\t\tawait sleep(delayMs, controller.signal);\n\t} finally {\n\t\toptions.signal?.removeEventListener(\"abort\", abortListener);\n\t\tunregisterAbort?.();\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\tconst baseDelayMs = options.taskRetryBaseDelayMs ?? TASK_RETRY_BASE_DELAY_MS;\n\t\tfor (let attempt = 0; ; attempt++) {\n\t\t\tclearSubagentRetry(run);\n\t\t\tconst result = await runSdkTask({\n\t\t\t\ttask,\n\t\t\t\trun,\n\t\t\t\tmodelRuntime: options.modelRuntime,\n\t\t\t\tagentDir: options.agentDir,\n\t\t\t\tprojectTrusted: options.projectTrusted,\n\t\t\t\tsignal: options.signal,\n\t\t\t\tonProgress,\n\t\t\t\tregisterAbort: options.registerAbort,\n\t\t\t});\n\t\t\tif (attempt >= TASK_RETRY_LIMIT || options.signal?.aborted || !shouldRetryTask(result)) return result;\n\t\t\tconst delayMs = baseDelayMs * 2 ** attempt;\n\t\t\tresetRunForRetry(run, attempt + 1, TASK_RETRY_LIMIT, delayMs);\n\t\t\tonProgress();\n\t\t\ttry {\n\t\t\t\tawait waitForTaskRetry(delayMs, options);\n\t\t\t} catch {\n\t\t\t\tclearSubagentRetry(run);\n\t\t\t\trun.status = \"aborted\";\n\t\t\t\trun.error = \"Subagent was aborted while waiting to retry.\";\n\t\t\t\trun.endedAt = Date.now();\n\t\t\t\tonProgress();\n\t\t\t\treturn run;\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tclearSubagentRetry(run);\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\tconst sections = details.runs.map((run) => {\n\t\tconst output = run.finalOutput || run.error || EMPTY_OUTPUT;\n\t\treturn `### ${run.description} (${run.agent}) — ${run.status}\\n\\n${boundText(output, PARALLEL_TASK_OUTPUT_LIMIT)}`;\n\t});\n\treturn boundText(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 (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 task) or tasks (parallel tasks); 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.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\n// Cheap change detector: consecutive events that alter nothing user-visible\n// skip the bounded-details serialization in emitDetails entirely. Every\n// activity contributes its status, not just the last one: agent-core can end\n// parallel tool executions out of order, and a mid-list row settling then\n// would otherwise slip past the detector.\nexport function progressKey(runs: readonly SubagentRunDetails[]): string {\n\treturn runs\n\t\t.map((run) => {\n\t\t\treturn [\n\t\t\t\trun.status,\n\t\t\t\trun.currentActivity ?? \"\",\n\t\t\t\trun.activities.length,\n\t\t\t\trun.activities.map((activity) => `${activity.status}:${activity.resultSummary ?? \"\"}`).join(\",\"),\n\t\t\t\trun.retry?.attempt ?? \"\",\n\t\t\t\trun.retry?.maxAttempts ?? \"\",\n\t\t\t\trun.retry?.deadline ?? \"\",\n\t\t\t\trun.retry?.error ?? \"\",\n\t\t\t\trun.liveText.length,\n\t\t\t\trun.liveText.slice(-24),\n\t\t\t\trun.finalOutput.length,\n\t\t\t\trun.usage.turns,\n\t\t\t\trun.usage.toolUses,\n\t\t\t\trun.usage.totalTokens,\n\t\t\t\trun.error ?? \"\",\n\t\t\t].join(\"|\");\n\t\t})\n\t\t.join(\"~\");\n}\n\nexport function isSubagentError(details: Pick<SubagentDetails, \"status\" | \"runs\">): boolean {\n\tif (details.status !== \"failed\" && details.status !== \"aborted\") return false;\n\t// A batch with any successful run is a partial result, not an error:\n\t// per-run status is already reported in the content sections.\n\treturn !details.runs.some((run) => run.status === \"completed\");\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, options.parentCwd));\n\tconst startedAt = Date.now();\n\tlet latestDetails = emitDetails(mode, runs, startedAt, options.onUpdate);\n\tlet lastProgressKey = progressKey(runs);\n\tconst progress = () => {\n\t\tconst key = progressKey(runs);\n\t\tif (key === lastProgressKey) return;\n\t\tlastProgressKey = key;\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 {\n\t\tawait Promise.all(resolved.map((task, index) => runWithGate(task, runs[index]!, options, progress)));\n\t}\n\tlatestDetails = emitDetails(mode, runs, startedAt, undefined);\n\tlatestDetails.endedAt = Date.now();\n\t// Error classification lives in the tool_result handler (index.ts), the\n\t// only channel that reaches the session transcript and export.\n\treturn {\n\t\tcontent: resultContent(latestDetails),\n\t\tdetails: boundSubagentDetails(latestDetails),\n\t\tusage: toNestedUsage(latestDetails.usage),\n\t};\n}\n\nexport function statusSummary(details: SubagentDetails): string {\n\treturn statusText(details);\n}\n"]}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/extensions/subagent/runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { isRetryableAssistantError } from \"@earendil-works/pi-ai/compat\";\nimport type { ModelRuntime } from \"../../core/model-runtime.ts\";\nimport { emptyUsage, mergeUsage, toNestedUsage } from \"./activity.ts\";\nimport { boundSubagentDetails, resultContent } from \"./budget.ts\";\nimport { abortableSleep, createRunCancellation, type RunCancellation } from \"./cancellation.ts\";\nimport { MAX_CONCURRENCY, MAX_TASKS, TASK_RETRY_BASE_DELAY_MS, TASK_RETRY_LIMIT } from \"./constants.ts\";\nimport { type ParentModelContext, resolveSubagentTask } from \"./resolve.ts\";\nimport type { SubagentParams, SubagentTask } from \"./schema.ts\";\nimport { runSdkTask } from \"./sdk-runner.ts\";\nimport { loadSubagentConfig } from \"./settings.ts\";\nimport {\n\tcreateRunState,\n\tisSubagentError as isSubagentErrorSelector,\n\treduceRun,\n\ttype SubagentRunEvent,\n\ttype SubagentRunState,\n\tstatusOf,\n\ttoRunDetails,\n\tversionSum,\n} from \"./state.ts\";\nimport type { ResolvedSubagentTask, SubagentDetails, SubagentExecutionResult, SubagentUsage } from \"./types.ts\";\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.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\tparent: ParentModelContext;\n\tmodelRuntime: ModelRuntime;\n\tagentDir: string;\n\tprojectTrusted: boolean;\n\tsignal?: AbortSignal;\n\tgate: ConcurrencyGate;\n\tonUpdate?: (details: SubagentDetails) => void;\n\tregisterAbort?: (abort: () => Promise<void>) => () => void;\n\t/** Test hook: overrides the task-retry backoff base delay. */\n\ttaskRetryBaseDelayMs?: number;\n\t/** Tool-call id of the invoking call; prefixes per-run ids for readability. */\n\tbatchId?: string;\n}\n\nfunction aggregateUsage(runs: readonly SubagentRunState[]): SubagentUsage {\n\tconst usage = emptyUsage();\n\tfor (const run of runs) mergeUsage(usage, run.usage);\n\treturn usage;\n}\n\nfunction emitDetails(\n\truns: SubagentRunState[],\n\tstartedAt: number,\n\tonUpdate: ((details: SubagentDetails) => void) | undefined,\n): SubagentDetails {\n\tconst details: SubagentDetails = {\n\t\tstatus: statusOf(runs),\n\t\truns: runs.map(toRunDetails),\n\t\tstartedAt,\n\t\tusage: aggregateUsage(runs),\n\t};\n\tonUpdate?.(boundSubagentDetails(details));\n\treturn details;\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\t// One config load and one resolution pass for the whole batch: every\n\t// task/profile/cwd/model is settled before any run is created or any\n\t// worker starts, so a failing task cannot strand half-initialized runs.\n\tconst config = await loadSubagentConfig(options.agentDir);\n\treturn Promise.all(\n\t\ttasks.map((task, index) =>\n\t\t\tresolveSubagentTask(task, options.parentCwd, options.parent, options.agentDir, config).catch((error) => {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(`Subagent task tasks[${index}] failed to resolve: ${message}`);\n\t\t\t}),\n\t\t),\n\t);\n}\n\n// Reuses pi-ai's provider-error classification by wrapping the stored error\n// text in the assistant-message shape it inspects.\nfunction isRetryableRunError(error: string | undefined): boolean {\n\tif (!error) return false;\n\tconst probe = { role: \"assistant\", content: [], stopReason: \"error\", errorMessage: error };\n\treturn isRetryableAssistantError(probe as unknown as Parameters<typeof isRetryableAssistantError>[0]);\n}\n\n// Session-level auto-retry already covers errors that happen inside the agent\n// loop; this catches the paths that bypass it (preflight throws such as auth\n// checks). Only a run that produced nothing is retried, so partial work is\n// never discarded.\nfunction shouldRetryTask(run: SubagentRunState): boolean {\n\treturn (\n\t\trun.status === \"failed\" && run.usage.turns === 0 && run.usage.toolUses === 0 && isRetryableRunError(run.error)\n\t);\n}\n\n// The gate slot is held only while a worker session actually runs. Backoff\n// waits outside the slot (release, sleep, reacquire) so a retrying task\n// cannot starve queued tasks, and aborting during the wait settles the run\n// without occupying the gate.\nasync function runWithGate(\n\ttask: ResolvedSubagentTask,\n\tscope: RunCancellation,\n\toptions: SubagentInvocationOptions,\n\tdispatch: (event: SubagentRunEvent) => void,\n\tgetState: () => SubagentRunState,\n\tonProgress: () => void,\n): Promise<void> {\n\tconst baseDelayMs = options.taskRetryBaseDelayMs ?? TASK_RETRY_BASE_DELAY_MS;\n\tfor (let attempt = 0; ; attempt++) {\n\t\tdispatch({ type: \"retry_started\" });\n\t\tlet release: (() => void) | undefined;\n\t\tlet delayMs = 0;\n\t\ttry {\n\t\t\trelease = await options.gate.acquire(scope.signal);\n\t\t\tif (scope.signal.aborted) {\n\t\t\t\tdispatch({ type: \"abort_while_queued\", endedAt: Date.now() });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdispatch({ type: \"slot_acquired\", startedAt: Date.now() });\n\t\t\tawait runSdkTask({\n\t\t\t\ttask,\n\t\t\t\tscope,\n\t\t\t\tdispatch,\n\t\t\t\tmodelRuntime: options.modelRuntime,\n\t\t\t\tagentDir: options.agentDir,\n\t\t\t\tprojectTrusted: options.projectTrusted,\n\t\t\t\tonProgress,\n\t\t\t});\n\t\t\tconst state = getState();\n\t\t\tif (attempt >= TASK_RETRY_LIMIT || scope.signal.aborted || !shouldRetryTask(state)) return;\n\t\t\tdelayMs = baseDelayMs * 2 ** attempt;\n\t\t\tdispatch({\n\t\t\t\ttype: \"retry_scheduled\",\n\t\t\t\tattempt: attempt + 1,\n\t\t\t\tmaxAttempts: TASK_RETRY_LIMIT,\n\t\t\t\tdeadline: Date.now() + delayMs,\n\t\t\t\terror: state.error,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (scope.signal.aborted) {\n\t\t\t\tdispatch({ type: \"abort_while_queued\", endedAt: Date.now() });\n\t\t\t} else {\n\t\t\t\tdispatch({\n\t\t\t\t\ttype: \"settle\",\n\t\t\t\t\tverdict: \"failed\",\n\t\t\t\t\treport: \"\",\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\tendedAt: Date.now(),\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t} finally {\n\t\t\trelease?.();\n\t\t}\n\t\ttry {\n\t\t\tawait abortableSleep(delayMs, scope);\n\t\t} catch {\n\t\t\tdispatch({ type: \"abort_while_retrying\", endedAt: Date.now() });\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nexport async function runSubagentInvocation(options: SubagentInvocationOptions): Promise<SubagentExecutionResult> {\n\t// Defensive count check: the schema already enforces 1..MAX_TASKS, but\n\t// strict providers can bypass minItems, so validate before any work.\n\tconst tasks = options.params.tasks ?? [];\n\tconst resolved = await resolveTasks(tasks, options);\n\tconst runs = resolved.map((task, index) => createRunState(task, index, options.batchId, options.parentCwd));\n\tconst startedAt = Date.now();\n\t// Every run's cancellation scope exists and is registered before any\n\t// gate work starts, so a shutdown snapshot can never miss a queued task.\n\tconst scopes = runs.map(() => createRunCancellation(options.signal));\n\tconst unregisterScopes = scopes.map((scope) => options.registerAbort?.(scope.abort));\n\tlet lastVersion = versionSum(runs);\n\tconst progress = (): void => {\n\t\tconst version = versionSum(runs);\n\t\tif (version === lastVersion) return;\n\t\tlastVersion = version;\n\t\temitDetails(runs, startedAt, options.onUpdate);\n\t};\n\tconst dispatch = (index: number, event: SubagentRunEvent): void => {\n\t\truns[index] = reduceRun(runs[index]!, event);\n\t\tprogress();\n\t};\n\tlet latestDetails = emitDetails(runs, startedAt, options.onUpdate);\n\n\t// Every task runs concurrently through the shared gate; Promise.all keeps\n\t// result order identical to input order. There is no single-task branch:\n\t// one task is just a batch of one.\n\ttry {\n\t\tawait Promise.all(\n\t\t\tresolved.map((task, index) => {\n\t\t\t\tconst dispatchToRun = (event: SubagentRunEvent): void => dispatch(index, event);\n\t\t\t\treturn runWithGate(task, scopes[index]!, options, dispatchToRun, () => runs[index]!, progress);\n\t\t\t}),\n\t\t);\n\t} finally {\n\t\tfor (const unregister of unregisterScopes) unregister?.();\n\t\tfor (const scope of scopes) scope.dispose();\n\t}\n\tlatestDetails = emitDetails(runs, startedAt, undefined);\n\tlatestDetails.endedAt = Date.now();\n\t// Error classification lives in the tool_result handler (index.ts), the\n\t// only channel that reaches the session transcript and export.\n\treturn {\n\t\tcontent: resultContent(latestDetails),\n\t\tdetails: boundSubagentDetails(latestDetails),\n\t\tusage: toNestedUsage(latestDetails.usage),\n\t};\n}\n\nexport function isSubagentError(details: Pick<SubagentDetails, \"status\" | \"runs\">): boolean {\n\treturn isSubagentErrorSelector(details);\n}\n"]}
@@ -1,21 +1,15 @@
1
1
  import { type Static, Type } from "typebox";
2
2
  export declare const TaskSchema: Type.TObject<{
3
- agent: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
4
- description: Type.TString;
3
+ agent: Type.TOptional<Type.TUnion<[Type.TUnsafe<"explorer" | "general">, Type.TNull]>>;
5
4
  prompt: Type.TString;
6
5
  cwd: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
7
6
  }>;
8
7
  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;
8
+ tasks: Type.TArray<Type.TObject<{
9
+ agent: Type.TOptional<Type.TUnion<[Type.TUnsafe<"explorer" | "general">, Type.TNull]>>;
16
10
  prompt: Type.TString;
17
11
  cwd: Type.TOptional<Type.TUnion<[Type.TString, Type.TNull]>>;
18
- }>>, Type.TNull]>>;
12
+ }>>;
19
13
  }>;
20
14
  export type SubagentParams = Static<typeof SubagentParamsSchema>;
21
15
  export type SubagentTask = Static<typeof TaskSchema>;
@@ -1 +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;;;;;;;;;;;EAwBhC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAgB,IAAI,EAAE,MAAM,SAAS,CAAC;AAW1D,eAAO,MAAM,UAAU;;;;EAiBtB,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;;;EAShC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC"}