@fitchmultz/pi-subagents 0.0.0-stage → 0.44.5

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 (347) hide show
  1. package/CHANGELOG.md +1654 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1533 -2
  4. package/agents/context-builder.md +97 -0
  5. package/agents/debugger.md +51 -0
  6. package/agents/delegate.md +13 -0
  7. package/agents/fixer.md +37 -0
  8. package/agents/oracle.md +71 -0
  9. package/agents/planner.md +72 -0
  10. package/agents/researcher.md +51 -0
  11. package/agents/reviewer-claude.md +69 -0
  12. package/agents/reviewer-gpt.md +68 -0
  13. package/agents/reviewer-ponytail.md +82 -0
  14. package/agents/reviewer-security.md +81 -0
  15. package/agents/reviewer.md +69 -0
  16. package/agents/scout.md +66 -0
  17. package/agents/ui-designer.md +51 -0
  18. package/agents/watcher.md +26 -0
  19. package/agents/worker.md +46 -0
  20. package/agents/writer.md +36 -0
  21. package/dist/agents/agent-management.js +923 -0
  22. package/dist/agents/agent-scope.js +7 -0
  23. package/dist/agents/agent-selection.js +20 -0
  24. package/dist/agents/agent-serializer.js +100 -0
  25. package/dist/agents/agents.js +752 -0
  26. package/dist/agents/chain-serializer.js +367 -0
  27. package/dist/agents/frontmatter.js +21 -0
  28. package/dist/agents/identity.js +29 -0
  29. package/dist/agents/skills.js +570 -0
  30. package/dist/extension/build-info.js +1 -0
  31. package/dist/extension/compact-tools.js +112 -0
  32. package/dist/extension/config.js +22 -0
  33. package/dist/extension/control-notices.js +29 -0
  34. package/dist/extension/doctor.js +143 -0
  35. package/dist/extension/fanout-child.js +326 -0
  36. package/dist/extension/index.js +577 -0
  37. package/dist/extension/schemas.js +416 -0
  38. package/dist/extension/tool-input.js +20 -0
  39. package/dist/extension/tool-result.js +14 -0
  40. package/dist/history/canonical-result.js +81 -0
  41. package/dist/history/database.js +72 -0
  42. package/dist/history/index.js +199 -0
  43. package/dist/history/ingest.js +468 -0
  44. package/dist/history/queries.js +350 -0
  45. package/dist/history/store.js +216 -0
  46. package/dist/history/types.js +4 -0
  47. package/dist/history/worker.js +466 -0
  48. package/dist/intercom/intercom-bridge.js +112 -0
  49. package/dist/intercom/live-intercom.js +94 -0
  50. package/dist/intercom/result-intercom.js +373 -0
  51. package/dist/pi-intercom/agent-dir.js +10 -0
  52. package/dist/pi-intercom/bridge.js +750 -0
  53. package/dist/pi-intercom/broker/broker.js +426 -0
  54. package/dist/pi-intercom/broker/client.js +492 -0
  55. package/dist/pi-intercom/broker/framing.js +65 -0
  56. package/dist/pi-intercom/broker/paths.js +42 -0
  57. package/dist/pi-intercom/broker/pid.js +66 -0
  58. package/dist/pi-intercom/broker/spawn.js +221 -0
  59. package/dist/pi-intercom/config.js +102 -0
  60. package/dist/pi-intercom/index.js +2942 -0
  61. package/dist/pi-intercom/reply-tracker.js +182 -0
  62. package/dist/pi-intercom/session-targets.js +128 -0
  63. package/dist/pi-intercom/subagent-live-events.js +132 -0
  64. package/dist/pi-intercom/topics.js +157 -0
  65. package/dist/pi-intercom/types.js +163 -0
  66. package/dist/pi-intercom/ui/compose.js +269 -0
  67. package/dist/pi-intercom/ui/inline-message.js +80 -0
  68. package/dist/pi-intercom/ui/session-list.js +124 -0
  69. package/dist/runs/background/async-control.js +95 -0
  70. package/dist/runs/background/async-execution.js +676 -0
  71. package/dist/runs/background/async-job-tracker.js +383 -0
  72. package/dist/runs/background/async-result-file.js +58 -0
  73. package/dist/runs/background/async-resume.js +305 -0
  74. package/dist/runs/background/async-status.js +442 -0
  75. package/dist/runs/background/completion-dedupe.js +69 -0
  76. package/dist/runs/background/completion-delivery.js +245 -0
  77. package/dist/runs/background/notify.js +71 -0
  78. package/dist/runs/background/parallel-groups.js +55 -0
  79. package/dist/runs/background/result-watcher.js +426 -0
  80. package/dist/runs/background/run-id-resolver.js +64 -0
  81. package/dist/runs/background/run-status.js +382 -0
  82. package/dist/runs/background/stale-run-reconciler.js +335 -0
  83. package/dist/runs/background/subagent-runner-launcher.js +55 -0
  84. package/dist/runs/background/subagent-runner.js +1872 -0
  85. package/dist/runs/background/top-level-async.js +5 -0
  86. package/dist/runs/foreground/chain-clarify.js +1152 -0
  87. package/dist/runs/foreground/clarify-invocation.js +72 -0
  88. package/dist/runs/foreground/execution-input.js +423 -0
  89. package/dist/runs/foreground/foreground-control.js +817 -0
  90. package/dist/runs/foreground/question-control.js +88 -0
  91. package/dist/runs/foreground/run-async-path.js +205 -0
  92. package/dist/runs/foreground/subagent-executor.js +442 -0
  93. package/dist/runs/foreground/subagent-params.js +165 -0
  94. package/dist/runs/foreground/wait-run.js +141 -0
  95. package/dist/runs/shared/acceptance-contract.js +253 -0
  96. package/dist/runs/shared/acceptance-evaluation.js +256 -0
  97. package/dist/runs/shared/acceptance-finalization.js +280 -0
  98. package/dist/runs/shared/acceptance-reports.js +147 -0
  99. package/dist/runs/shared/acceptance.js +4 -0
  100. package/dist/runs/shared/chain-outputs.js +110 -0
  101. package/dist/runs/shared/child-attempt.js +693 -0
  102. package/dist/runs/shared/child-execution-cwd.js +96 -0
  103. package/dist/runs/shared/child-observations.js +114 -0
  104. package/dist/runs/shared/claude-code.js +199 -0
  105. package/dist/runs/shared/completion-guard.js +31 -0
  106. package/dist/runs/shared/dynamic-fanout.js +274 -0
  107. package/dist/runs/shared/history-index.js +72 -0
  108. package/dist/runs/shared/mcp-direct-tool-allowlist.js +334 -0
  109. package/dist/runs/shared/model-fallback.js +185 -0
  110. package/dist/runs/shared/mutating-tool-guard.js +170 -0
  111. package/dist/runs/shared/native-finalization.js +101 -0
  112. package/dist/runs/shared/native-usage.js +153 -0
  113. package/dist/runs/shared/nested-events.js +700 -0
  114. package/dist/runs/shared/nested-path.js +48 -0
  115. package/dist/runs/shared/nested-render.js +108 -0
  116. package/dist/runs/shared/parallel-utils.js +61 -0
  117. package/dist/runs/shared/parent-receipts.js +68 -0
  118. package/dist/runs/shared/parent-usage.js +121 -0
  119. package/dist/runs/shared/pi-args.js +310 -0
  120. package/dist/runs/shared/pi-spawn.js +52 -0
  121. package/dist/runs/shared/run-history-queries.js +45 -0
  122. package/dist/runs/shared/run-history.js +110 -0
  123. package/dist/runs/shared/run-id-ambiguity.js +4 -0
  124. package/dist/runs/shared/run-records.js +679 -0
  125. package/dist/runs/shared/session-cwd-preload.js +33 -0
  126. package/dist/runs/shared/single-output.js +222 -0
  127. package/dist/runs/shared/streaming-text.js +15 -0
  128. package/dist/runs/shared/structured-output.js +55 -0
  129. package/dist/runs/shared/subagent-control.js +179 -0
  130. package/dist/runs/shared/subagent-prompt-runtime.js +197 -0
  131. package/dist/runs/shared/subagent-tool-loop-guard.js +66 -0
  132. package/dist/runs/shared/supervisor-questions.js +350 -0
  133. package/dist/runs/shared/workflow-graph.js +214 -0
  134. package/dist/runs/shared/workflow-policy.js +84 -0
  135. package/dist/runs/shared/worktree.js +525 -0
  136. package/dist/shared/agent-context-policy.js +126 -0
  137. package/dist/shared/artifacts.js +96 -0
  138. package/dist/shared/atomic-json.js +13 -0
  139. package/dist/shared/cooperative.js +20 -0
  140. package/dist/shared/execution-cwd.js +14 -0
  141. package/dist/shared/file-coalescer.js +21 -0
  142. package/dist/shared/fork-context.js +49 -0
  143. package/dist/shared/formatters.js +85 -0
  144. package/dist/shared/journal-reader.js +407 -0
  145. package/dist/shared/lazy-tools.js +32 -0
  146. package/dist/shared/model-info.js +68 -0
  147. package/dist/shared/native-session.js +15 -0
  148. package/dist/shared/native-tui.js +18 -0
  149. package/dist/shared/native-typebox.js +20 -0
  150. package/dist/shared/post-exit-stdio-guard.js +197 -0
  151. package/dist/shared/prompt-sections.js +8 -0
  152. package/dist/shared/session-entries.js +52 -0
  153. package/dist/shared/session-identity.js +14 -0
  154. package/dist/shared/settings.js +254 -0
  155. package/dist/shared/status-format.js +111 -0
  156. package/dist/shared/temp-root.js +114 -0
  157. package/dist/shared/types.js +207 -0
  158. package/dist/shared/ui-mode.js +3 -0
  159. package/dist/shared/utils.js +334 -0
  160. package/dist/slash/prompt-template-bridge.js +298 -0
  161. package/dist/slash/slash-bridge.js +116 -0
  162. package/dist/slash/slash-commands.js +607 -0
  163. package/dist/slash/slash-live-state.js +246 -0
  164. package/dist/tui/action-hints.js +75 -0
  165. package/dist/tui/agent-history.js +197 -0
  166. package/dist/tui/agent-view.js +1656 -0
  167. package/dist/tui/render.js +1515 -0
  168. package/docs/intercom-bridge.md +212 -0
  169. package/docs/intercom.md +581 -0
  170. package/docs/performance.md +121 -0
  171. package/package.json +102 -4
  172. package/prompts/gather-context-and-clarify.md +14 -0
  173. package/prompts/parallel-cleanup.md +62 -0
  174. package/prompts/parallel-context-build.md +56 -0
  175. package/prompts/parallel-handoff-plan.md +62 -0
  176. package/prompts/parallel-research.md +51 -0
  177. package/prompts/parallel-review.md +59 -0
  178. package/prompts/review-loop.md +42 -0
  179. package/scripts/build.mjs +134 -0
  180. package/scripts/check-compat.mjs +48 -0
  181. package/scripts/compat-host.mjs +19 -0
  182. package/scripts/intercom-bridge-credentials.mjs +143 -0
  183. package/scripts/intercom-remote.mjs +103 -0
  184. package/scripts/linux-smoke.sh +51 -0
  185. package/scripts/local-install-smoke.mjs +66 -0
  186. package/scripts/native-package-smoke.mjs +82 -0
  187. package/scripts/package-smoke.mjs +209 -0
  188. package/scripts/prepare.mjs +67 -0
  189. package/scripts/real-pi-smoke.mjs +415 -0
  190. package/scripts/run-tests.mjs +149 -0
  191. package/skills/pi-intercom/SKILL.md +113 -0
  192. package/skills/pi-intercom/evals/evals.json +29 -0
  193. package/skills/pi-intercom/evals/trigger-evals.json +47 -0
  194. package/skills/pi-intercom/references/peer-sessions.md +69 -0
  195. package/skills/pi-subagents/SKILL.md +76 -0
  196. package/skills/pi-subagents/evals/evals.json +29 -0
  197. package/skills/pi-subagents/evals/trigger-evals.json +42 -0
  198. package/skills/pi-subagents/references/full-orchestration-guide.md +863 -0
  199. package/src/agents/agent-management.ts +813 -0
  200. package/src/agents/agent-scope.ts +7 -0
  201. package/src/agents/agent-selection.ts +23 -0
  202. package/src/agents/agent-serializer.ts +99 -0
  203. package/src/agents/agents.ts +916 -0
  204. package/src/agents/chain-serializer.ts +329 -0
  205. package/src/agents/frontmatter.ts +21 -0
  206. package/src/agents/identity.ts +30 -0
  207. package/src/agents/skills.ts +637 -0
  208. package/src/extension/build-info.ts +2 -0
  209. package/src/extension/compact-tools.ts +114 -0
  210. package/src/extension/config.ts +23 -0
  211. package/src/extension/control-notices.ts +47 -0
  212. package/src/extension/doctor.ts +171 -0
  213. package/src/extension/fanout-child.ts +312 -0
  214. package/src/extension/index.ts +649 -0
  215. package/src/extension/schemas.ts +444 -0
  216. package/src/extension/tool-input.ts +19 -0
  217. package/src/extension/tool-result.ts +16 -0
  218. package/src/history/canonical-result.ts +62 -0
  219. package/src/history/database.ts +59 -0
  220. package/src/history/index.ts +156 -0
  221. package/src/history/ingest.ts +349 -0
  222. package/src/history/queries.ts +241 -0
  223. package/src/history/store.ts +203 -0
  224. package/src/history/types.ts +166 -0
  225. package/src/history/worker.ts +321 -0
  226. package/src/intercom/intercom-bridge.ts +123 -0
  227. package/src/intercom/live-intercom.ts +104 -0
  228. package/src/intercom/result-intercom.ts +429 -0
  229. package/src/pi-intercom/agent-dir.ts +9 -0
  230. package/src/pi-intercom/bridge.ts +668 -0
  231. package/src/pi-intercom/broker/broker.ts +463 -0
  232. package/src/pi-intercom/broker/client.ts +558 -0
  233. package/src/pi-intercom/broker/framing.ts +77 -0
  234. package/src/pi-intercom/broker/paths.ts +47 -0
  235. package/src/pi-intercom/broker/pid.ts +59 -0
  236. package/src/pi-intercom/broker/spawn.ts +248 -0
  237. package/src/pi-intercom/config.ts +142 -0
  238. package/src/pi-intercom/index.ts +2929 -0
  239. package/src/pi-intercom/reply-tracker.ts +211 -0
  240. package/src/pi-intercom/session-targets.ts +172 -0
  241. package/src/pi-intercom/subagent-live-events.ts +133 -0
  242. package/src/pi-intercom/topics.ts +125 -0
  243. package/src/pi-intercom/types.ts +271 -0
  244. package/src/pi-intercom/ui/compose.ts +289 -0
  245. package/src/pi-intercom/ui/inline-message.ts +92 -0
  246. package/src/pi-intercom/ui/session-list.ts +139 -0
  247. package/src/runs/background/async-control.ts +89 -0
  248. package/src/runs/background/async-execution.ts +850 -0
  249. package/src/runs/background/async-job-tracker.ts +385 -0
  250. package/src/runs/background/async-result-file.ts +62 -0
  251. package/src/runs/background/async-resume.ts +333 -0
  252. package/src/runs/background/async-status.ts +481 -0
  253. package/src/runs/background/completion-dedupe.ts +79 -0
  254. package/src/runs/background/completion-delivery.ts +195 -0
  255. package/src/runs/background/notify.ts +123 -0
  256. package/src/runs/background/parallel-groups.ts +53 -0
  257. package/src/runs/background/result-watcher.ts +423 -0
  258. package/src/runs/background/run-id-resolver.ts +69 -0
  259. package/src/runs/background/run-status.ts +384 -0
  260. package/src/runs/background/stale-run-reconciler.ts +369 -0
  261. package/src/runs/background/subagent-runner-launcher.ts +56 -0
  262. package/src/runs/background/subagent-runner.ts +2053 -0
  263. package/src/runs/background/top-level-async.ts +13 -0
  264. package/src/runs/foreground/chain-clarify.ts +1340 -0
  265. package/src/runs/foreground/clarify-invocation.ts +77 -0
  266. package/src/runs/foreground/execution-input.ts +467 -0
  267. package/src/runs/foreground/foreground-control.ts +821 -0
  268. package/src/runs/foreground/question-control.ts +82 -0
  269. package/src/runs/foreground/run-async-path.ts +243 -0
  270. package/src/runs/foreground/subagent-executor.ts +501 -0
  271. package/src/runs/foreground/subagent-params.ts +320 -0
  272. package/src/runs/foreground/wait-run.ts +124 -0
  273. package/src/runs/shared/acceptance-contract.ts +257 -0
  274. package/src/runs/shared/acceptance-evaluation.ts +275 -0
  275. package/src/runs/shared/acceptance-finalization.ts +353 -0
  276. package/src/runs/shared/acceptance-reports.ts +152 -0
  277. package/src/runs/shared/acceptance.ts +33 -0
  278. package/src/runs/shared/chain-outputs.ts +114 -0
  279. package/src/runs/shared/child-attempt.ts +623 -0
  280. package/src/runs/shared/child-execution-cwd.ts +91 -0
  281. package/src/runs/shared/child-observations.ts +99 -0
  282. package/src/runs/shared/claude-code.ts +243 -0
  283. package/src/runs/shared/completion-guard.ts +35 -0
  284. package/src/runs/shared/dynamic-fanout.ts +295 -0
  285. package/src/runs/shared/history-index.ts +69 -0
  286. package/src/runs/shared/mcp-direct-tool-allowlist.ts +376 -0
  287. package/src/runs/shared/model-fallback.ts +219 -0
  288. package/src/runs/shared/mutating-tool-guard.ts +194 -0
  289. package/src/runs/shared/native-finalization.ts +128 -0
  290. package/src/runs/shared/native-usage.ts +113 -0
  291. package/src/runs/shared/nested-events.ts +752 -0
  292. package/src/runs/shared/nested-path.ts +52 -0
  293. package/src/runs/shared/nested-render.ts +119 -0
  294. package/src/runs/shared/parallel-utils.ts +153 -0
  295. package/src/runs/shared/parent-receipts.ts +59 -0
  296. package/src/runs/shared/parent-usage.ts +121 -0
  297. package/src/runs/shared/pi-args.ts +350 -0
  298. package/src/runs/shared/pi-spawn.ts +52 -0
  299. package/src/runs/shared/run-history-queries.ts +44 -0
  300. package/src/runs/shared/run-history.ts +100 -0
  301. package/src/runs/shared/run-id-ambiguity.ts +4 -0
  302. package/src/runs/shared/run-records.ts +607 -0
  303. package/src/runs/shared/session-cwd-preload.ts +27 -0
  304. package/src/runs/shared/single-output.ts +267 -0
  305. package/src/runs/shared/streaming-text.ts +18 -0
  306. package/src/runs/shared/structured-output.ts +68 -0
  307. package/src/runs/shared/subagent-control.ts +219 -0
  308. package/src/runs/shared/subagent-prompt-runtime.ts +201 -0
  309. package/src/runs/shared/subagent-tool-loop-guard.ts +89 -0
  310. package/src/runs/shared/supervisor-questions.ts +415 -0
  311. package/src/runs/shared/workflow-graph.ts +220 -0
  312. package/src/runs/shared/workflow-policy.ts +125 -0
  313. package/src/runs/shared/worktree.ts +635 -0
  314. package/src/shared/agent-context-policy.ts +184 -0
  315. package/src/shared/artifacts.ts +95 -0
  316. package/src/shared/atomic-json.ts +16 -0
  317. package/src/shared/cooperative.ts +21 -0
  318. package/src/shared/execution-cwd.ts +14 -0
  319. package/src/shared/file-coalescer.ts +29 -0
  320. package/src/shared/fork-context.ts +68 -0
  321. package/src/shared/formatters.ts +84 -0
  322. package/src/shared/journal-reader.ts +333 -0
  323. package/src/shared/lazy-tools.ts +36 -0
  324. package/src/shared/model-info.ts +81 -0
  325. package/src/shared/native-session.ts +8 -0
  326. package/src/shared/native-tui.ts +10 -0
  327. package/src/shared/native-typebox.ts +14 -0
  328. package/src/shared/post-exit-stdio-guard.ts +204 -0
  329. package/src/shared/prompt-sections.ts +10 -0
  330. package/src/shared/session-entries.ts +49 -0
  331. package/src/shared/session-identity.ts +18 -0
  332. package/src/shared/settings.ts +384 -0
  333. package/src/shared/status-format.ts +123 -0
  334. package/src/shared/temp-root.ts +107 -0
  335. package/src/shared/types.ts +1260 -0
  336. package/src/shared/ui-mode.ts +5 -0
  337. package/src/shared/utils.ts +342 -0
  338. package/src/slash/prompt-template-bridge.ts +408 -0
  339. package/src/slash/slash-bridge.ts +178 -0
  340. package/src/slash/slash-commands.ts +617 -0
  341. package/src/slash/slash-live-state.ts +292 -0
  342. package/src/tui/action-hints.ts +69 -0
  343. package/src/tui/agent-history.ts +210 -0
  344. package/src/tui/agent-view.ts +1323 -0
  345. package/src/tui/render.ts +1550 -0
  346. package/tsconfig.build.json +12 -0
  347. package/tsconfig.json +19 -0
@@ -0,0 +1,298 @@
1
+ export const PROMPT_TEMPLATE_SUBAGENT_REQUEST_EVENT = "prompt-template:subagent:request";
2
+ export const PROMPT_TEMPLATE_SUBAGENT_STARTED_EVENT = "prompt-template:subagent:started";
3
+ export const PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT = "prompt-template:subagent:response";
4
+ export const PROMPT_TEMPLATE_SUBAGENT_UPDATE_EVENT = "prompt-template:subagent:update";
5
+ export const PROMPT_TEMPLATE_SUBAGENT_CANCEL_EVENT = "prompt-template:subagent:cancel";
6
+ function parseDelegationTasks(tasks) {
7
+ if (!Array.isArray(tasks))
8
+ return [];
9
+ const parsed = [];
10
+ for (const item of tasks) {
11
+ if (!item || typeof item !== "object")
12
+ return [];
13
+ const value = item;
14
+ if (typeof value.agent !== "string" || !value.agent.trim())
15
+ return [];
16
+ if (typeof value.task !== "string" || !value.task.trim())
17
+ return [];
18
+ const model = typeof value.model === "string" && value.model.trim().length > 0 ? value.model : undefined;
19
+ const cwd = typeof value.cwd === "string" && value.cwd.trim().length > 0 ? value.cwd : undefined;
20
+ parsed.push({
21
+ agent: value.agent,
22
+ task: value.task,
23
+ ...(model ? { model } : {}),
24
+ ...(cwd ? { cwd } : {}),
25
+ });
26
+ }
27
+ return parsed;
28
+ }
29
+ function parsePromptTemplateRequest(data) {
30
+ if (!data || typeof data !== "object")
31
+ return undefined;
32
+ const value = data;
33
+ if (typeof value.requestId !== "string" || !value.requestId)
34
+ return undefined;
35
+ if (typeof value.model !== "string" || !value.model)
36
+ return undefined;
37
+ if (typeof value.cwd !== "string" || !value.cwd)
38
+ return undefined;
39
+ if (value.context !== "fresh" && value.context !== "fork")
40
+ return undefined;
41
+ const tasks = parseDelegationTasks(value.tasks);
42
+ const worktree = value.worktree === true ? true : undefined;
43
+ const singleAgent = typeof value.agent === "string" && value.agent.length > 0 ? value.agent : undefined;
44
+ const singleTask = typeof value.task === "string" && value.task.length > 0 ? value.task : undefined;
45
+ const hasSingle = singleAgent !== undefined && singleTask !== undefined;
46
+ if (!hasSingle && tasks.length === 0)
47
+ return undefined;
48
+ const fallbackTask = tasks[0];
49
+ if (hasSingle) {
50
+ return {
51
+ requestId: value.requestId,
52
+ agent: singleAgent,
53
+ task: singleTask,
54
+ ...(tasks.length > 0 ? { tasks } : {}),
55
+ context: value.context,
56
+ model: value.model,
57
+ cwd: value.cwd,
58
+ ...(worktree ? { worktree } : {}),
59
+ };
60
+ }
61
+ if (!fallbackTask)
62
+ return undefined;
63
+ return {
64
+ requestId: value.requestId,
65
+ agent: fallbackTask.agent,
66
+ task: fallbackTask.task,
67
+ ...(tasks.length > 0 ? { tasks } : {}),
68
+ context: value.context,
69
+ model: value.model,
70
+ cwd: value.cwd,
71
+ ...(worktree ? { worktree } : {}),
72
+ };
73
+ }
74
+ function firstTextContent(content) {
75
+ if (!Array.isArray(content))
76
+ return undefined;
77
+ for (const part of content) {
78
+ if (!part || typeof part !== "object")
79
+ continue;
80
+ if (part.type !== "text")
81
+ continue;
82
+ const text = part.text;
83
+ if (typeof text === "string" && text.trim())
84
+ return text.trim();
85
+ }
86
+ return undefined;
87
+ }
88
+ function filterRecentOutput(lines) {
89
+ if (!lines || lines.length === 0)
90
+ return undefined;
91
+ const filtered = lines.filter((line) => typeof line === "string" && line.trim() && line.trim() !== "(running...)");
92
+ if (filtered.length === 0)
93
+ return undefined;
94
+ return filtered;
95
+ }
96
+ function sanitizeRecentTools(tools) {
97
+ if (!tools || tools.length === 0)
98
+ return undefined;
99
+ const sanitized = tools.flatMap((entry) => {
100
+ if (typeof entry.tool !== "string" || entry.tool.trim().length === 0)
101
+ return [];
102
+ return [{
103
+ tool: entry.tool,
104
+ args: typeof entry.args === "string" ? entry.args : String(entry.args ?? ""),
105
+ }];
106
+ });
107
+ return sanitized.length > 0 ? sanitized : undefined;
108
+ }
109
+ function resolveProgressModel(update, entry) {
110
+ const results = update.details?.results;
111
+ if (!results || results.length === 0)
112
+ return undefined;
113
+ if (typeof entry.index === "number" && entry.index >= 0) {
114
+ const byIndex = results[entry.index];
115
+ if (typeof byIndex?.model === "string")
116
+ return byIndex.model;
117
+ }
118
+ if (entry.agent) {
119
+ const byAgent = results.find((result) => result.agent === entry.agent && typeof result.model === "string");
120
+ if (byAgent?.model)
121
+ return byAgent.model;
122
+ }
123
+ const firstWithModel = results.find((result) => typeof result.model === "string");
124
+ return firstWithModel?.model;
125
+ }
126
+ function buildDelegationMessages(result, fallbackText) {
127
+ if (Array.isArray(result.messages) && result.messages.length > 0)
128
+ return result.messages;
129
+ const text = typeof result.finalOutput === "string" && result.finalOutput.trim().length > 0
130
+ ? result.finalOutput.trim()
131
+ : fallbackText;
132
+ if (!text)
133
+ return [];
134
+ return [{ role: "assistant", content: [{ type: "text", text }] }];
135
+ }
136
+ function toDelegationUpdate(requestId, update) {
137
+ const progress = update.details?.progress?.[0];
138
+ const taskProgress = update.details?.progress?.map((entry) => {
139
+ const lastOutput = entry.recentOutput?.[entry.recentOutput.length - 1];
140
+ const safeLastOutput = typeof lastOutput === "string" && lastOutput.trim() && lastOutput !== "(running...)"
141
+ ? lastOutput
142
+ : undefined;
143
+ return {
144
+ index: entry.index,
145
+ agent: entry.agent ?? "delegate",
146
+ status: entry.status,
147
+ currentTool: entry.currentTool,
148
+ currentToolArgs: entry.currentToolArgs,
149
+ recentOutput: safeLastOutput,
150
+ recentOutputLines: filterRecentOutput(entry.recentOutput),
151
+ recentTools: sanitizeRecentTools(entry.recentTools),
152
+ model: resolveProgressModel(update, entry),
153
+ toolCount: entry.toolCount,
154
+ durationMs: entry.durationMs,
155
+ tokens: entry.tokens,
156
+ };
157
+ });
158
+ if (!progress && (!taskProgress || taskProgress.length === 0))
159
+ return undefined;
160
+ const lastOutput = progress?.recentOutput?.[progress.recentOutput.length - 1];
161
+ const safeLastOutput = typeof lastOutput === "string" && lastOutput.trim() && lastOutput !== "(running...)"
162
+ ? lastOutput
163
+ : undefined;
164
+ return {
165
+ requestId,
166
+ currentTool: progress?.currentTool,
167
+ currentToolArgs: progress?.currentToolArgs,
168
+ recentOutput: safeLastOutput,
169
+ recentOutputLines: filterRecentOutput(progress?.recentOutput),
170
+ recentTools: sanitizeRecentTools(progress?.recentTools),
171
+ model: progress ? resolveProgressModel(update, progress) : undefined,
172
+ toolCount: progress?.toolCount,
173
+ durationMs: progress?.durationMs,
174
+ tokens: progress?.tokens,
175
+ taskProgress,
176
+ };
177
+ }
178
+ export function registerPromptTemplateDelegationBridge(options) {
179
+ const controllers = new Map();
180
+ const pendingCancels = new Set();
181
+ const subscriptions = [];
182
+ const subscribe = (event, handler) => {
183
+ const unsubscribe = options.events.on(event, handler);
184
+ if (typeof unsubscribe === "function")
185
+ subscriptions.push(unsubscribe);
186
+ };
187
+ subscribe(PROMPT_TEMPLATE_SUBAGENT_CANCEL_EVENT, (data) => {
188
+ if (!data || typeof data !== "object")
189
+ return;
190
+ const requestId = data.requestId;
191
+ if (typeof requestId !== "string")
192
+ return;
193
+ const controller = controllers.get(requestId);
194
+ if (controller) {
195
+ controller.abort();
196
+ return;
197
+ }
198
+ pendingCancels.add(requestId);
199
+ });
200
+ subscribe(PROMPT_TEMPLATE_SUBAGENT_REQUEST_EVENT, async (data) => {
201
+ const request = parsePromptTemplateRequest(data);
202
+ if (!request)
203
+ return;
204
+ const ctx = options.getContext();
205
+ if (!ctx) {
206
+ const response = {
207
+ ...request,
208
+ messages: [],
209
+ isError: true,
210
+ errorText: "No active extension context for delegated subagent execution.",
211
+ };
212
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
213
+ return;
214
+ }
215
+ const controller = new AbortController();
216
+ controllers.set(request.requestId, controller);
217
+ if (pendingCancels.delete(request.requestId)) {
218
+ controller.abort();
219
+ const response = {
220
+ ...request,
221
+ messages: [],
222
+ isError: true,
223
+ errorText: "Delegated prompt cancelled.",
224
+ };
225
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
226
+ controllers.delete(request.requestId);
227
+ return;
228
+ }
229
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_STARTED_EVENT, { requestId: request.requestId });
230
+ try {
231
+ const result = await options.execute(request.requestId, request, controller.signal, ctx, (update) => {
232
+ const payload = toDelegationUpdate(request.requestId, update);
233
+ if (!payload)
234
+ return;
235
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_UPDATE_EVENT, payload);
236
+ });
237
+ const contentText = firstTextContent(result.content);
238
+ const messages = buildDelegationMessages(result.details?.results?.[0] ?? {}, contentText);
239
+ const parallelResults = request.tasks
240
+ ? request.tasks.map((task, index) => {
241
+ const step = result.details?.results?.[index];
242
+ if (!step) {
243
+ return {
244
+ agent: task.agent,
245
+ messages: [],
246
+ isError: true,
247
+ errorText: "Missing result for delegated parallel task.",
248
+ };
249
+ }
250
+ const exitCode = typeof step.exitCode === "number" ? step.exitCode : undefined;
251
+ const errorText = step.error;
252
+ return {
253
+ agent: step.agent ?? task.agent,
254
+ messages: buildDelegationMessages(step),
255
+ isError: (exitCode !== undefined && exitCode !== 0) || !!errorText,
256
+ errorText: errorText || undefined,
257
+ };
258
+ })
259
+ : undefined;
260
+ const response = {
261
+ ...request,
262
+ messages,
263
+ ...(parallelResults ? { parallelResults } : {}),
264
+ ...(contentText ? { contentText } : {}),
265
+ isError: result.isError === true,
266
+ errorText: result.isError ? contentText : undefined,
267
+ };
268
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
269
+ }
270
+ catch (error) {
271
+ const response = {
272
+ ...request,
273
+ messages: [],
274
+ isError: true,
275
+ errorText: error instanceof Error ? error.message : String(error),
276
+ };
277
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
278
+ }
279
+ finally {
280
+ controllers.delete(request.requestId);
281
+ }
282
+ });
283
+ return {
284
+ cancelAll: () => {
285
+ for (const controller of controllers.values()) {
286
+ controller.abort();
287
+ }
288
+ controllers.clear();
289
+ pendingCancels.clear();
290
+ },
291
+ dispose: () => {
292
+ for (const unsubscribe of subscriptions)
293
+ unsubscribe();
294
+ subscriptions.length = 0;
295
+ pendingCancels.clear();
296
+ },
297
+ };
298
+ }
@@ -0,0 +1,116 @@
1
+ import { SLASH_SUBAGENT_CANCEL_EVENT, SLASH_SUBAGENT_REQUEST_EVENT, SLASH_SUBAGENT_RESPONSE_EVENT, SLASH_SUBAGENT_STARTED_EVENT, SLASH_SUBAGENT_UPDATE_EVENT, } from "../shared/types.js";
2
+ export function registerSlashSubagentBridge(options) {
3
+ const controllers = new Map();
4
+ const pendingCancels = new Set();
5
+ const subscriptions = [];
6
+ const subscribe = (event, handler) => {
7
+ const unsubscribe = options.events.on(event, handler);
8
+ if (typeof unsubscribe === "function")
9
+ subscriptions.push(unsubscribe);
10
+ };
11
+ subscribe(SLASH_SUBAGENT_CANCEL_EVENT, (data) => {
12
+ if (!data || typeof data !== "object")
13
+ return;
14
+ const requestId = data.requestId;
15
+ if (typeof requestId !== "string")
16
+ return;
17
+ const controller = controllers.get(requestId);
18
+ if (controller) {
19
+ controller.abort();
20
+ return;
21
+ }
22
+ pendingCancels.add(requestId);
23
+ });
24
+ subscribe(SLASH_SUBAGENT_REQUEST_EVENT, async (data) => {
25
+ if (!data || typeof data !== "object")
26
+ return;
27
+ const request = data;
28
+ if (typeof request.requestId !== "string" || !request.params)
29
+ return;
30
+ const { requestId, params } = request;
31
+ const ctx = options.getContext();
32
+ if (!ctx) {
33
+ const response = {
34
+ requestId,
35
+ result: {
36
+ content: [{ type: "text", text: "No active extension context for slash subagent execution." }],
37
+ details: { mode: "single", results: [] },
38
+ },
39
+ isError: true,
40
+ errorText: "No active extension context.",
41
+ };
42
+ options.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, response);
43
+ return;
44
+ }
45
+ const controller = new AbortController();
46
+ controllers.set(requestId, controller);
47
+ if (pendingCancels.delete(requestId)) {
48
+ controller.abort();
49
+ const response = {
50
+ requestId,
51
+ result: {
52
+ content: [{ type: "text", text: "Cancelled." }],
53
+ details: { mode: "single", results: [] },
54
+ },
55
+ isError: true,
56
+ errorText: "Cancelled before start.",
57
+ };
58
+ options.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, response);
59
+ controllers.delete(requestId);
60
+ return;
61
+ }
62
+ options.events.emit(SLASH_SUBAGENT_STARTED_EVENT, { requestId });
63
+ try {
64
+ const result = await options.execute(requestId, params, controller.signal, (update) => {
65
+ const progress = update.details?.progress;
66
+ const first = progress?.[0];
67
+ const payload = {
68
+ requestId,
69
+ progress,
70
+ currentTool: first?.currentTool,
71
+ toolCount: first?.toolCount,
72
+ };
73
+ options.events.emit(SLASH_SUBAGENT_UPDATE_EVENT, payload);
74
+ }, ctx, request.executionCwd);
75
+ const response = {
76
+ requestId,
77
+ result,
78
+ isError: result.isError === true,
79
+ errorText: result.isError
80
+ ? result.content.find((c) => c.type === "text")?.text
81
+ : undefined,
82
+ };
83
+ options.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, response);
84
+ }
85
+ catch (error) {
86
+ const response = {
87
+ requestId,
88
+ result: {
89
+ content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }],
90
+ details: { mode: "single", results: [] },
91
+ },
92
+ isError: true,
93
+ errorText: error instanceof Error ? error.message : String(error),
94
+ };
95
+ options.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, response);
96
+ }
97
+ finally {
98
+ controllers.delete(requestId);
99
+ }
100
+ });
101
+ return {
102
+ cancelAll: () => {
103
+ for (const controller of controllers.values()) {
104
+ controller.abort();
105
+ }
106
+ controllers.clear();
107
+ pendingCancels.clear();
108
+ },
109
+ dispose: () => {
110
+ for (const unsubscribe of subscriptions)
111
+ unsubscribe();
112
+ subscriptions.length = 0;
113
+ pendingCancels.clear();
114
+ },
115
+ };
116
+ }