@esso0428/pi-subagents 0.17.5 → 0.17.7

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 +14 -0
  2. package/CONTRIBUTING.md +4 -0
  3. package/README.md +1 -1
  4. package/dist/abortable.d.ts +13 -0
  5. package/dist/abortable.d.ts.map +1 -0
  6. package/dist/abortable.js +43 -0
  7. package/dist/abortable.js.map +1 -0
  8. package/dist/agent-color.d.ts +36 -0
  9. package/dist/agent-color.d.ts.map +1 -0
  10. package/dist/agent-color.js +124 -0
  11. package/dist/agent-color.js.map +1 -0
  12. package/dist/agent-file-toggle.d.ts +126 -0
  13. package/dist/agent-file-toggle.d.ts.map +1 -0
  14. package/dist/agent-file-toggle.js +259 -0
  15. package/dist/agent-file-toggle.js.map +1 -0
  16. package/dist/agent-history.d.ts +4 -0
  17. package/dist/agent-history.d.ts.map +1 -1
  18. package/dist/agent-history.js +47 -1
  19. package/dist/agent-history.js.map +1 -1
  20. package/dist/agent-manager.d.ts +370 -56
  21. package/dist/agent-manager.d.ts.map +1 -1
  22. package/dist/agent-manager.js +1123 -409
  23. package/dist/agent-manager.js.map +1 -1
  24. package/dist/agent-runner.d.ts +100 -10
  25. package/dist/agent-runner.d.ts.map +1 -1
  26. package/dist/agent-runner.js +166 -21
  27. package/dist/agent-runner.js.map +1 -1
  28. package/dist/agent-types.d.ts +57 -5
  29. package/dist/agent-types.d.ts.map +1 -1
  30. package/dist/agent-types.js +164 -32
  31. package/dist/agent-types.js.map +1 -1
  32. package/dist/child-context.d.ts +3 -0
  33. package/dist/child-context.d.ts.map +1 -0
  34. package/dist/child-context.js +13 -0
  35. package/dist/child-context.js.map +1 -0
  36. package/dist/cross-extension-rpc.d.ts +23 -3
  37. package/dist/cross-extension-rpc.d.ts.map +1 -1
  38. package/dist/cross-extension-rpc.js +79 -17
  39. package/dist/cross-extension-rpc.js.map +1 -1
  40. package/dist/custom-agents.d.ts +38 -1
  41. package/dist/custom-agents.d.ts.map +1 -1
  42. package/dist/custom-agents.js +164 -12
  43. package/dist/custom-agents.js.map +1 -1
  44. package/dist/index.d.ts +34 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +1908 -495
  47. package/dist/index.js.map +1 -1
  48. package/dist/invocation-config.d.ts +87 -2
  49. package/dist/invocation-config.d.ts.map +1 -1
  50. package/dist/invocation-config.js +71 -3
  51. package/dist/invocation-config.js.map +1 -1
  52. package/dist/mention-clone.d.ts +88 -0
  53. package/dist/mention-clone.d.ts.map +1 -0
  54. package/dist/mention-clone.js +154 -0
  55. package/dist/mention-clone.js.map +1 -0
  56. package/dist/mention.d.ts +82 -0
  57. package/dist/mention.d.ts.map +1 -0
  58. package/dist/mention.js +132 -0
  59. package/dist/mention.js.map +1 -0
  60. package/dist/model-resolver.d.ts +17 -0
  61. package/dist/model-resolver.d.ts.map +1 -1
  62. package/dist/model-resolver.js +15 -0
  63. package/dist/model-resolver.js.map +1 -1
  64. package/dist/model-scope.d.ts +50 -0
  65. package/dist/model-scope.d.ts.map +1 -0
  66. package/dist/model-scope.js +49 -0
  67. package/dist/model-scope.js.map +1 -0
  68. package/dist/nested-tools.d.ts +57 -0
  69. package/dist/nested-tools.d.ts.map +1 -0
  70. package/dist/nested-tools.js +301 -0
  71. package/dist/nested-tools.js.map +1 -0
  72. package/dist/output-file.d.ts +22 -3
  73. package/dist/output-file.d.ts.map +1 -1
  74. package/dist/output-file.js +58 -7
  75. package/dist/output-file.js.map +1 -1
  76. package/dist/prompts.d.ts +23 -0
  77. package/dist/prompts.d.ts.map +1 -1
  78. package/dist/prompts.js +20 -2
  79. package/dist/prompts.js.map +1 -1
  80. package/dist/schedule.d.ts.map +1 -1
  81. package/dist/schedule.js +36 -15
  82. package/dist/schedule.js.map +1 -1
  83. package/dist/settings.d.ts +228 -2
  84. package/dist/settings.d.ts.map +1 -1
  85. package/dist/settings.js +94 -0
  86. package/dist/settings.js.map +1 -1
  87. package/dist/status-note.d.ts +49 -1
  88. package/dist/status-note.d.ts.map +1 -1
  89. package/dist/status-note.js +62 -1
  90. package/dist/status-note.js.map +1 -1
  91. package/dist/structured-output.d.ts +62 -0
  92. package/dist/structured-output.d.ts.map +1 -0
  93. package/dist/structured-output.js +113 -0
  94. package/dist/structured-output.js.map +1 -0
  95. package/dist/types.d.ts +176 -10
  96. package/dist/types.d.ts.map +1 -1
  97. package/dist/ui/agent-mention.d.ts +83 -0
  98. package/dist/ui/agent-mention.d.ts.map +1 -0
  99. package/dist/ui/agent-mention.js +188 -0
  100. package/dist/ui/agent-mention.js.map +1 -0
  101. package/dist/ui/agent-widget.d.ts +96 -75
  102. package/dist/ui/agent-widget.d.ts.map +1 -1
  103. package/dist/ui/agent-widget.js +397 -420
  104. package/dist/ui/agent-widget.js.map +1 -1
  105. package/dist/ui/conversation-blocks.d.ts.map +1 -1
  106. package/dist/ui/conversation-blocks.js +6 -0
  107. package/dist/ui/conversation-blocks.js.map +1 -1
  108. package/dist/ui/conversation-timeline.d.ts +10 -2
  109. package/dist/ui/conversation-timeline.d.ts.map +1 -1
  110. package/dist/ui/conversation-timeline.js +130 -23
  111. package/dist/ui/conversation-timeline.js.map +1 -1
  112. package/dist/ui/conversation-viewer.d.ts +20 -5
  113. package/dist/ui/conversation-viewer.d.ts.map +1 -1
  114. package/dist/ui/conversation-viewer.js +274 -73
  115. package/dist/ui/conversation-viewer.js.map +1 -1
  116. package/dist/ui/fleet-list.d.ts +198 -0
  117. package/dist/ui/fleet-list.d.ts.map +1 -0
  118. package/dist/ui/fleet-list.js +487 -0
  119. package/dist/ui/fleet-list.js.map +1 -0
  120. package/dist/ui/schedule-menu.d.ts.map +1 -1
  121. package/dist/ui/schedule-menu.js +6 -7
  122. package/dist/ui/schedule-menu.js.map +1 -1
  123. package/dist/ui/select-item.d.ts +28 -0
  124. package/dist/ui/select-item.d.ts.map +1 -0
  125. package/dist/ui/select-item.js +35 -0
  126. package/dist/ui/select-item.js.map +1 -0
  127. package/dist/ui/workflow-card.d.ts +176 -0
  128. package/dist/ui/workflow-card.d.ts.map +1 -0
  129. package/dist/ui/workflow-card.js +333 -0
  130. package/dist/ui/workflow-card.js.map +1 -0
  131. package/dist/ui/workflow-dialog.d.ts +306 -0
  132. package/dist/ui/workflow-dialog.d.ts.map +1 -0
  133. package/dist/ui/workflow-dialog.js +844 -0
  134. package/dist/ui/workflow-dialog.js.map +1 -0
  135. package/dist/ui/workflow-menu.d.ts +61 -0
  136. package/dist/ui/workflow-menu.d.ts.map +1 -0
  137. package/dist/ui/workflow-menu.js +148 -0
  138. package/dist/ui/workflow-menu.js.map +1 -0
  139. package/dist/usage.d.ts +86 -1
  140. package/dist/usage.d.ts.map +1 -1
  141. package/dist/usage.js +72 -1
  142. package/dist/usage.js.map +1 -1
  143. package/dist/workflow/collisions.d.ts +96 -0
  144. package/dist/workflow/collisions.d.ts.map +1 -0
  145. package/dist/workflow/collisions.js +89 -0
  146. package/dist/workflow/collisions.js.map +1 -0
  147. package/dist/workflow/entry.d.ts +33 -0
  148. package/dist/workflow/entry.d.ts.map +1 -0
  149. package/dist/workflow/entry.js +30 -0
  150. package/dist/workflow/entry.js.map +1 -0
  151. package/dist/workflow/host.d.ts +63 -0
  152. package/dist/workflow/host.d.ts.map +1 -0
  153. package/dist/workflow/host.js +363 -0
  154. package/dist/workflow/host.js.map +1 -0
  155. package/dist/workflow/journal.d.ts +98 -0
  156. package/dist/workflow/journal.d.ts.map +1 -0
  157. package/dist/workflow/journal.js +121 -0
  158. package/dist/workflow/journal.js.map +1 -0
  159. package/dist/workflow/json-schema.d.ts +52 -0
  160. package/dist/workflow/json-schema.d.ts.map +1 -0
  161. package/dist/workflow/json-schema.js +112 -0
  162. package/dist/workflow/json-schema.js.map +1 -0
  163. package/dist/workflow/meta.d.ts +68 -0
  164. package/dist/workflow/meta.d.ts.map +1 -0
  165. package/dist/workflow/meta.js +318 -0
  166. package/dist/workflow/meta.js.map +1 -0
  167. package/dist/workflow/progress.d.ts +225 -0
  168. package/dist/workflow/progress.d.ts.map +1 -0
  169. package/dist/workflow/progress.js +362 -0
  170. package/dist/workflow/progress.js.map +1 -0
  171. package/dist/workflow/runtime.d.ts +335 -0
  172. package/dist/workflow/runtime.d.ts.map +1 -0
  173. package/dist/workflow/runtime.js +831 -0
  174. package/dist/workflow/runtime.js.map +1 -0
  175. package/dist/workflow/saved.d.ts +91 -0
  176. package/dist/workflow/saved.d.ts.map +1 -0
  177. package/dist/workflow/saved.js +204 -0
  178. package/dist/workflow/saved.js.map +1 -0
  179. package/dist/workflow/task.d.ts +137 -0
  180. package/dist/workflow/task.d.ts.map +1 -0
  181. package/dist/workflow/task.js +208 -0
  182. package/dist/workflow/task.js.map +1 -0
  183. package/dist/workflow/tool-description.d.ts +39 -0
  184. package/dist/workflow/tool-description.d.ts.map +1 -0
  185. package/dist/workflow/tool-description.js +200 -0
  186. package/dist/workflow/tool-description.js.map +1 -0
  187. package/dist/workflow/worker-source.d.ts +48 -0
  188. package/dist/workflow/worker-source.d.ts.map +1 -0
  189. package/dist/workflow/worker-source.js +779 -0
  190. package/dist/workflow/worker-source.js.map +1 -0
  191. package/dist/worktree.d.ts +10 -3
  192. package/dist/worktree.d.ts.map +1 -1
  193. package/dist/worktree.js +58 -54
  194. package/dist/worktree.js.map +1 -1
  195. package/dist/xml.d.ts +11 -0
  196. package/dist/xml.d.ts.map +1 -0
  197. package/dist/xml.js +13 -0
  198. package/dist/xml.js.map +1 -0
  199. package/docs/rpc.md +183 -0
  200. package/docs/superpowers/plans/2026-09-30-conversation-viewer-scrollbar.md +216 -0
  201. package/docs/superpowers/plans/2026-09-30-upstream-event-workflow-partial-history.md +195 -0
  202. package/docs/superpowers/specs/2026-09-30-conversation-viewer-scrollbar-design.md +82 -0
  203. package/docs/superpowers/specs/2026-09-30-upstream-event-workflow-partial-history-design.md +49 -0
  204. package/docs/workflows.md +437 -0
  205. package/examples/agent-tool-description.md +7 -7
  206. package/examples/workflows/compose.js +51 -0
  207. package/examples/workflows/fan-out-audit.js +47 -0
  208. package/examples/workflows/gated-fix.js +60 -0
  209. package/examples/workflows/lib/count-child.js +27 -0
  210. package/examples/workflows/review-panel.js +63 -0
  211. package/examples/workflows/structured-findings.js +78 -0
  212. package/package.json +1 -1
  213. package/src/abortable.ts +43 -0
  214. package/src/agent-color.ts +161 -0
  215. package/src/agent-file-toggle.ts +269 -0
  216. package/src/agent-history.ts +54 -2
  217. package/src/agent-manager.ts +1263 -402
  218. package/src/agent-runner.ts +251 -27
  219. package/src/agent-types.ts +188 -32
  220. package/src/child-context.ts +15 -0
  221. package/src/cross-extension-rpc.ts +96 -20
  222. package/src/custom-agents.ts +170 -13
  223. package/src/index.ts +2024 -537
  224. package/src/invocation-config.ts +118 -3
  225. package/src/mention-clone.ts +196 -0
  226. package/src/mention.ts +141 -0
  227. package/src/model-resolver.ts +18 -0
  228. package/src/model-scope.ts +70 -0
  229. package/src/nested-tools.ts +424 -0
  230. package/src/output-file.ts +61 -6
  231. package/src/prompts.ts +45 -2
  232. package/src/schedule.ts +35 -14
  233. package/src/settings.ts +312 -2
  234. package/src/status-note.ts +66 -1
  235. package/src/structured-output.ts +130 -0
  236. package/src/types.ts +177 -10
  237. package/src/ui/agent-mention.ts +216 -0
  238. package/src/ui/agent-widget.ts +389 -441
  239. package/src/ui/conversation-blocks.ts +6 -0
  240. package/src/ui/conversation-timeline.ts +139 -25
  241. package/src/ui/conversation-viewer.ts +284 -69
  242. package/src/ui/fleet-list.ts +558 -0
  243. package/src/ui/schedule-menu.ts +9 -8
  244. package/src/ui/select-item.ts +45 -0
  245. package/src/ui/workflow-card.ts +470 -0
  246. package/src/ui/workflow-dialog.ts +1115 -0
  247. package/src/ui/workflow-menu.ts +193 -0
  248. package/src/usage.ts +109 -2
  249. package/src/workflow/collisions.ts +123 -0
  250. package/src/workflow/entry.ts +47 -0
  251. package/src/workflow/host.ts +403 -0
  252. package/src/workflow/journal.ts +164 -0
  253. package/src/workflow/json-schema.ts +128 -0
  254. package/src/workflow/meta.ts +325 -0
  255. package/src/workflow/progress.ts +550 -0
  256. package/src/workflow/runtime.ts +1219 -0
  257. package/src/workflow/saved.ts +217 -0
  258. package/src/workflow/task.ts +302 -0
  259. package/src/workflow/tool-description.ts +200 -0
  260. package/src/workflow/worker-source.ts +781 -0
  261. package/src/worktree.ts +69 -55
  262. package/src/xml.ts +13 -0
  263. package/vitest.config.ts +0 -18
@@ -0,0 +1,89 @@
1
+ /**
2
+ * collisions.ts — deciding what to do when another extension already offers a
3
+ * workflow tool.
4
+ *
5
+ * Workflows are on by default, so this extension can be the *second*
6
+ * orchestrator in a session rather than the only one. Two workflow tools in one
7
+ * spec is worse than either alone: the model has to guess which to call, and
8
+ * pays for both descriptions to find out. The other extension was installed
9
+ * deliberately; a default of ours should not compete with it.
10
+ *
11
+ * ## What counts as a conflict
12
+ *
13
+ * An exact name match against {@link FOREIGN_WORKFLOW_TOOL_NAMES}, from a tool
14
+ * that is not ours. Exact and not a substring on purpose: `Workflow` is a
15
+ * common word in tool names that have nothing to do with orchestration
16
+ * (`github_workflow_run`, `list_workflows`), and silently disabling the feature
17
+ * against one of those would be a bug nobody could see.
18
+ *
19
+ * Two shapes, both decided here:
20
+ *
21
+ * 1. **A foreign tool took our name.** Registration is first-wins across
22
+ * extensions (`getAllRegisteredTools` skips a name it already has), and the
23
+ * winner also overwrites a built-in of the same name. Nothing throws, and
24
+ * there is no tool-conflict diagnostic the way there is for shortcuts. Ours
25
+ * never reached the registry, so there is nothing to withdraw — but the rest
26
+ * of the feature (the menu, the CLI flag) is still live and would drive a
27
+ * tool the model cannot call. It comes down with it.
28
+ * 2. **A foreign tool sits beside ours** under a different name, typically
29
+ * Claude Code's bare `Workflow`. Both are registered and both are offered.
30
+ * That one the caller can actually withdraw — `withdraw` says so.
31
+ *
32
+ * Only one direction of case 1 is detectable. If ours registered first, the
33
+ * other extension's tool is the one dropped, and pi exposes no way to see a
34
+ * tool that lost — the registry keeps winners only.
35
+ *
36
+ * Split from the acting half deliberately: everything here is a pure function
37
+ * of the tool list, so the policy can be tested without a host that can be made
38
+ * to register a competing extension. The caller owns `getAllTools`, the notify
39
+ * and the `setActiveTools` — see `resolveWorkflowCollisions` in index.ts.
40
+ */
41
+ import { SUBAGENT_TOOL_NAMES } from "../agent-runner.js";
42
+ /**
43
+ * Tool names that mean "another extension already orchestrates subagents".
44
+ *
45
+ * Our own name, because pi resolves a duplicate registration silently, and
46
+ * Claude Code's bare `Workflow`, because a port of that tool is what a second
47
+ * workflow extension most likely calls itself. Lowercase `workflow` is the same
48
+ * tool by pi convention: it is what `@quintinshaw/pi-dynamic-workflows`
49
+ * registers, and the match here is exact, so the case has to be listed by hand.
50
+ */
51
+ export const FOREIGN_WORKFLOW_TOOL_NAMES = new Set([
52
+ SUBAGENT_TOOL_NAMES.WORKFLOW,
53
+ "Workflow",
54
+ "workflow",
55
+ ]);
56
+ /**
57
+ * Decide, from the registered tools alone.
58
+ *
59
+ * `ownDescription` identifies our own registration: this extension does not
60
+ * know its install path, and the description is the one field that is certainly
61
+ * ours. `pinned` is an explicit `workflowsEnabled` — a default yields to
62
+ * evidence, a choice does not.
63
+ */
64
+ export function decideWorkflowCollision(input) {
65
+ const foreign = input.tools.find(tool => FOREIGN_WORKFLOW_TOOL_NAMES.has(tool.name) && tool.description !== input.ownDescription);
66
+ if (foreign === undefined)
67
+ return { kind: "none" };
68
+ const source = foreign.sourceInfo?.source ?? "unknown source";
69
+ const tookOurName = foreign.name === SUBAGENT_TOOL_NAMES.WORKFLOW;
70
+ if (input.pinned) {
71
+ if (!tookOurName)
72
+ return { kind: "none" };
73
+ return {
74
+ kind: "report",
75
+ message: `Another extension (${source}) already registers a "${SUBAGENT_TOOL_NAMES.WORKFLOW}" tool. ` +
76
+ "Pi keeps the first registration, so this extension's workflow tool is not offered to the " +
77
+ "model. Disable one of the two.",
78
+ };
79
+ }
80
+ return {
81
+ kind: "standDown",
82
+ message: `Another extension (${source}) already provides a "${foreign.name}" tool, so this extension's ` +
83
+ "workflows are disabled for this session to avoid offering the model two orchestrators. " +
84
+ 'Set `"workflowsEnabled": true` in .pi/subagents.json to keep both.',
85
+ // Case 1: ours never reached the registry, so there is nothing to withdraw.
86
+ withdraw: !tookOurName,
87
+ };
88
+ }
89
+ //# sourceMappingURL=collisions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collisions.js","sourceRoot":"","sources":["../../src/workflow/collisions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAwB,IAAI,GAAG,CAAC;IACtE,mBAAmB,CAAC,QAAQ;IAC5B,UAAU;IACV,UAAU;CACX,CAAC,CAAC;AAyBH;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAIvC;IACC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAC9B,IAAI,CAAC,EAAE,CAAC,2BAA2B,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,cAAc,CAChG,CAAC;IACF,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAEnD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,MAAM,IAAI,gBAAgB,CAAC;IAC9D,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,KAAK,mBAAmB,CAAC,QAAQ,CAAC;IAElE,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,WAAW;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC1C,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,OAAO,EACL,sBAAsB,MAAM,0BAA0B,mBAAmB,CAAC,QAAQ,UAAU;gBAC5F,2FAA2F;gBAC3F,gCAAgC;SACnC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,OAAO,EACL,sBAAsB,MAAM,yBAAyB,OAAO,CAAC,IAAI,8BAA8B;YAC/F,yFAAyF;YACzF,oEAAoE;QACtE,4EAA4E;QAC5E,QAAQ,EAAE,CAAC,WAAW;KACvB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * entry.ts — what a finished workflow leaves behind in the session transcript.
3
+ *
4
+ * A workflow started from `--subagents-workflow-file` has no tool call to hang
5
+ * its result card on, so it appends a custom session entry instead. That entry
6
+ * has to survive a reload, which is why this is a plain-JSON snapshot rather
7
+ * than the live {@link WorkflowTask}: the task holds an `AbortController`, the
8
+ * script source and the run's control handle, none of which belongs in a
9
+ * session file.
10
+ *
11
+ * Deliberately free of any renderer import. The card this data renders through
12
+ * lives in `ui/workflow-card.ts` (`renderWorkflowEntryCard`), so the shape a
13
+ * session file stores does not depend on the code that draws it.
14
+ */
15
+ import type { WorkflowMeta } from "./meta.js";
16
+ import type { WorkflowEntry, WorkflowRunStatus } from "./progress.js";
17
+ import type { WorkflowTask } from "./task.js";
18
+ /** `customType` of the session entry a flag-launched workflow renders through. */
19
+ export declare const WORKFLOW_ENTRY_TYPE = "subagents:workflow";
20
+ /** The persisted snapshot of a settled run. */
21
+ export interface WorkflowEntryData {
22
+ name: string;
23
+ status: WorkflowRunStatus;
24
+ startTime: number;
25
+ endTime?: number;
26
+ progress: WorkflowEntry[];
27
+ agentCount: number;
28
+ totalTokens: number;
29
+ meta?: WorkflowMeta;
30
+ }
31
+ /** Snapshot a settled task for {@link WORKFLOW_ENTRY_TYPE}. */
32
+ export declare function workflowEntryData(task: WorkflowTask): WorkflowEntryData;
33
+ //# sourceMappingURL=entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/workflow/entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,uBAAuB,CAAC;AAExD,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,iBAAiB,CAWvE"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * entry.ts — what a finished workflow leaves behind in the session transcript.
3
+ *
4
+ * A workflow started from `--subagents-workflow-file` has no tool call to hang
5
+ * its result card on, so it appends a custom session entry instead. That entry
6
+ * has to survive a reload, which is why this is a plain-JSON snapshot rather
7
+ * than the live {@link WorkflowTask}: the task holds an `AbortController`, the
8
+ * script source and the run's control handle, none of which belongs in a
9
+ * session file.
10
+ *
11
+ * Deliberately free of any renderer import. The card this data renders through
12
+ * lives in `ui/workflow-card.ts` (`renderWorkflowEntryCard`), so the shape a
13
+ * session file stores does not depend on the code that draws it.
14
+ */
15
+ /** `customType` of the session entry a flag-launched workflow renders through. */
16
+ export const WORKFLOW_ENTRY_TYPE = "subagents:workflow";
17
+ /** Snapshot a settled task for {@link WORKFLOW_ENTRY_TYPE}. */
18
+ export function workflowEntryData(task) {
19
+ return {
20
+ name: task.workflowName ?? task.id,
21
+ status: task.status,
22
+ startTime: task.startTime,
23
+ endTime: task.endTime,
24
+ progress: task.workflowProgress,
25
+ agentCount: task.agentCount,
26
+ totalTokens: task.totalTokens,
27
+ ...(task.meta !== undefined ? { meta: task.meta } : {}),
28
+ };
29
+ }
30
+ //# sourceMappingURL=entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/workflow/entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,kFAAkF;AAClF,MAAM,CAAC,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AAcxD,+DAA+D;AAC/D,MAAM,UAAU,iBAAiB,CAAC,IAAkB;IAClD,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,EAAE;QAClC,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,gBAAgB;QAC/B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * host.ts — binds a workflow run to the real `AgentManager`.
3
+ *
4
+ * `runtime.ts` deliberately knows nothing about this extension: its only seam is
5
+ * the injected {@link WorkflowHost}, which is what keeps the runtime's tests
6
+ * free of sessions, models and git. This file is the other half of that seam —
7
+ * everything the script can reach through `agent()`, `resume` and `gate` ends up
8
+ * here, and nowhere else.
9
+ *
10
+ * Four mappings carry most of the weight:
11
+ *
12
+ * - **ids.** The runtime hands out its own `wf-agent-N` handles before
13
+ * anything spawns, because it needs a stable progress-entry identity. The
14
+ * manager issues a different id when the child actually starts. `records`
15
+ * is the translation, and it is kept for the whole run rather than cleared
16
+ * on completion: `resume` reaches back to a child that has already
17
+ * finished.
18
+ * - **agent type and model.** Resolved through `resolveSpawnType` and
19
+ * `getAgentConfig` — the same dispatch the `Agent` tool uses — so a
20
+ * workflow and a tool call disagree about nothing.
21
+ * - **failure.** A strict worktree-isolation failure throws out of
22
+ * `spawnAndWait`; the script must see that as an agent that failed
23
+ * (`{ok: false}` → `null`), not as an unhandled rejection that takes the
24
+ * run down.
25
+ * - **when a `gate` runs.** For an isolated child it cannot wait until the
26
+ * spawn resolves: the manager commits the worktree to a branch and deletes
27
+ * the copy inside the child's own settle, so by then the only tree left to
28
+ * run `npm test` in is the main one — which would report on code the child
29
+ * never wrote. So the gate runs from `onBeforeWorktreeCleanup`, inside that
30
+ * settle, and the verdict travels back on the spawn result. `runGate` still
31
+ * exists for a child that had no worktree; the runtime uses whichever of
32
+ * the two happened, never both.
33
+ */
34
+ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
35
+ import type { AgentManager } from "../agent-manager.js";
36
+ import type { WorkflowHost } from "./runtime.js";
37
+ /**
38
+ * Wall-clock bound on a `gate` command. Generous — a gate is routinely a test
39
+ * suite — but not unbounded: `pi.exec` reports a timeout as `killed`, and a
40
+ * gate that hangs forever would wedge the agent slot it is holding.
41
+ */
42
+ export declare const DEFAULT_GATE_TIMEOUT_MS: number;
43
+ export interface WorkflowHostOptions {
44
+ pi: ExtensionAPI;
45
+ ctx: ExtensionContext;
46
+ manager: AgentManager;
47
+ /** The run's abort signal, so killing the workflow kills its children. */
48
+ signal?: AbortSignal;
49
+ /** Groups child transcripts under the parent session. */
50
+ rootSessionId?: string;
51
+ /**
52
+ * The run id every child is stamped with.
53
+ *
54
+ * What makes them the workflow's rather than the session's: stamped children
55
+ * are filtered out of the fleet list, the widget, the `/agents` menus and
56
+ * `@handle` resolution, and they take no `maxConcurrent` slot. The run
57
+ * reports for them, and it has its own concurrency cap.
58
+ */
59
+ workflowId?: string;
60
+ gateTimeoutMs?: number;
61
+ }
62
+ export declare function createWorkflowHost(deps: WorkflowHostOptions): WorkflowHost;
63
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/workflow/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAMxD,OAAO,KAAK,EAAsB,YAAY,EAAuB,MAAM,cAAc,CAAC;AAG1F;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,QAAc,CAAC;AAEnD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,YAAY,CAAC;IACjB,GAAG,EAAE,gBAAgB,CAAC;IACtB,OAAO,EAAE,YAAY,CAAC;IACtB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAyFD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,YAAY,CAmP1E"}
@@ -0,0 +1,363 @@
1
+ /**
2
+ * host.ts — binds a workflow run to the real `AgentManager`.
3
+ *
4
+ * `runtime.ts` deliberately knows nothing about this extension: its only seam is
5
+ * the injected {@link WorkflowHost}, which is what keeps the runtime's tests
6
+ * free of sessions, models and git. This file is the other half of that seam —
7
+ * everything the script can reach through `agent()`, `resume` and `gate` ends up
8
+ * here, and nowhere else.
9
+ *
10
+ * Four mappings carry most of the weight:
11
+ *
12
+ * - **ids.** The runtime hands out its own `wf-agent-N` handles before
13
+ * anything spawns, because it needs a stable progress-entry identity. The
14
+ * manager issues a different id when the child actually starts. `records`
15
+ * is the translation, and it is kept for the whole run rather than cleared
16
+ * on completion: `resume` reaches back to a child that has already
17
+ * finished.
18
+ * - **agent type and model.** Resolved through `resolveSpawnType` and
19
+ * `getAgentConfig` — the same dispatch the `Agent` tool uses — so a
20
+ * workflow and a tool call disagree about nothing.
21
+ * - **failure.** A strict worktree-isolation failure throws out of
22
+ * `spawnAndWait`; the script must see that as an agent that failed
23
+ * (`{ok: false}` → `null`), not as an unhandled rejection that takes the
24
+ * run down.
25
+ * - **when a `gate` runs.** For an isolated child it cannot wait until the
26
+ * spawn resolves: the manager commits the worktree to a branch and deletes
27
+ * the copy inside the child's own settle, so by then the only tree left to
28
+ * run `npm test` in is the main one — which would report on code the child
29
+ * never wrote. So the gate runs from `onBeforeWorktreeCleanup`, inside that
30
+ * settle, and the verdict travels back on the spawn result. `runGate` still
31
+ * exists for a child that had no worktree; the runtime uses whichever of
32
+ * the two happened, never both.
33
+ */
34
+ import { existsSync } from "node:fs";
35
+ import { getAgentConfig, resolveSpawnType } from "../agent-types.js";
36
+ import { resolveModel } from "../model-resolver.js";
37
+ import { checkModelScope } from "../model-scope.js";
38
+ import { getLifetimeTotal } from "../usage.js";
39
+ import { resolveWorkflowSource } from "./saved.js";
40
+ /**
41
+ * Wall-clock bound on a `gate` command. Generous — a gate is routinely a test
42
+ * suite — but not unbounded: `pi.exec` reports a timeout as `killed`, and a
43
+ * gate that hangs forever would wedge the agent slot it is holding.
44
+ */
45
+ export const DEFAULT_GATE_TIMEOUT_MS = 10 * 60_000;
46
+ /**
47
+ * Where the child worked, when that directory still exists.
48
+ *
49
+ * The guard is not defensive padding. `cleanupWorktree` commits the child's
50
+ * changes to a branch and *removes* the copy before `spawnAndWait` resolves, so
51
+ * an isolated child's worktree is normally already gone by the time a result is
52
+ * built. That is exactly why a gate cannot wait until here — it runs from
53
+ * `onBeforeWorktreeCleanup` instead — and why this reports nothing rather than
54
+ * a path that no longer exists: handing a stale path to a command would fail
55
+ * every gated worktree agent with a spawn error instead of a test result.
56
+ */
57
+ function childCwd(record) {
58
+ // `path`, not `workPath`: a workflow spawn never passes a cwd, so the manager
59
+ // runs the child at the copied repo's root.
60
+ const path = record.worktree?.path;
61
+ return path !== undefined && existsSync(path) ? path : undefined;
62
+ }
63
+ /**
64
+ * Whether the child itself succeeded — the same condition {@link toSpawnResult}
65
+ * turns into `ok`, read from the live record so the pre-cleanup hook can tell a
66
+ * finished child from a failed one before the result exists.
67
+ */
68
+ function succeeded(record) {
69
+ return record?.status === "completed" || record?.status === "steered";
70
+ }
71
+ /** Translate a settled record into what the script sees. */
72
+ /**
73
+ * The effective-configuration half of a record, in the runtime's pi-free shape.
74
+ *
75
+ * `AgentRecord.invocation` is the one authoritative place for it (#168); this
76
+ * only renames the fields across the boundary. Returns undefined until the
77
+ * child's session has reported a model, which is when any of it is knowable.
78
+ */
79
+ function resolvedInfo(record) {
80
+ const invocation = record?.invocation;
81
+ if (invocation?.modelName === undefined)
82
+ return undefined;
83
+ return {
84
+ modelName: invocation.modelName,
85
+ modelId: invocation.modelId,
86
+ thinking: invocation.thinking,
87
+ requestedThinking: invocation.requestedThinking,
88
+ requestedModel: invocation.requestedModel,
89
+ };
90
+ }
91
+ function toSpawnResult(record) {
92
+ const tokens = getLifetimeTotal(record.lifetimeUsage);
93
+ // Reported separately from `tokens`, which is the lifetime total. The script's
94
+ // `budget` counts *output* tokens, as Claude Code's does — billing the input
95
+ // and cache reads a fan-out re-sends would over-report it by an order of
96
+ // magnitude and make the documented guards useless.
97
+ const outputTokens = record.lifetimeUsage?.output ?? 0;
98
+ const cwd = childCwd(record);
99
+ const common = {
100
+ ...(tokens > 0 ? { tokens } : {}),
101
+ ...(outputTokens > 0 ? { outputTokens } : {}),
102
+ ...(record.toolUses > 0 ? { toolCalls: record.toolUses } : {}),
103
+ ...(cwd !== undefined ? { cwd } : {}),
104
+ };
105
+ if (succeeded(record)) {
106
+ return {
107
+ ...common,
108
+ ok: true,
109
+ // The schema'd payload when there is one: `result` is prose, and for a
110
+ // worktree child it has had the branch note appended, so it would not
111
+ // parse. A child asked for a schema that produced none never reaches
112
+ // here — `runAgent` reports that through `failure`.
113
+ text: record.structuredJson ?? record.result ?? "",
114
+ ...(record.structuredRetried ? { structuredRetried: true } : {}),
115
+ };
116
+ }
117
+ // "stopped" is someone reaching in and stopping this child — /agents, the
118
+ // fleet list, a workflow abort. That is the same thing the workflows dialog's
119
+ // skip action means, so it renders as skipped rather than failed.
120
+ if (record.status === "stopped") {
121
+ return { ...common, ok: false, skipped: true, error: record.error ?? "Stopped." };
122
+ }
123
+ return { ...common, ok: false, error: record.error ?? `Agent ${record.status}.` };
124
+ }
125
+ /** Shell used to run a `gate` command, mirroring how a user would type it. */
126
+ const GATE_SHELL = process.platform === "win32" ? ["cmd", "/c"] : ["sh", "-c"];
127
+ export function createWorkflowHost(deps) {
128
+ const { pi, ctx, manager } = deps;
129
+ /** Runtime agent id → the manager record it spawned. Never pruned mid-run. */
130
+ const records = new Map();
131
+ /**
132
+ * scopeModels warnings already toasted, so a fan-out that pins one
133
+ * out-of-scope agent file raises one notification rather than one per child.
134
+ * Kept for the whole run: the same message is the same warning at agent 200
135
+ * as it was at agent 1.
136
+ */
137
+ const warnedScopeMessages = new Set();
138
+ /**
139
+ * Run a gate command in `cwd`. The only place a gate is executed — `runGate`
140
+ * and the pre-cleanup hook both come through here — so "gate passed" is
141
+ * decided from one behaviour, whichever route the command took.
142
+ */
143
+ async function executeGate(command, cwd) {
144
+ const result = await pi.exec(GATE_SHELL[0], [GATE_SHELL[1], command], {
145
+ cwd,
146
+ timeout: deps.gateTimeoutMs ?? DEFAULT_GATE_TIMEOUT_MS,
147
+ ...(deps.signal !== undefined ? { signal: deps.signal } : {}),
148
+ });
149
+ const output = [result.stdout, result.stderr]
150
+ .map(stream => stream.trim())
151
+ .filter(Boolean)
152
+ .join("\n");
153
+ // `pi.exec` reports a timeout as `killed` with exit code 0, so the code
154
+ // alone would read a killed gate as a passing one.
155
+ if (result.killed) {
156
+ return { ok: false, output: output || `Gate command timed out: ${command}` };
157
+ }
158
+ return { ok: result.code === 0, output };
159
+ }
160
+ return {
161
+ async spawnAgent(request) {
162
+ const dispatch = resolveSpawnType(request.agentType);
163
+ if (!dispatch.ok)
164
+ return { ok: false, error: dispatch.message };
165
+ // Same precedence as the Agent tool: the caller's model wins, the agent
166
+ // definition's is next, and the parent's is the floor. A model the script
167
+ // named and we cannot resolve is an error; one the definition named falls
168
+ // back to the parent silently, because the script never asked for it.
169
+ let model = ctx.model;
170
+ const config = getAgentConfig(dispatch.type);
171
+ const modelInput = request.model ?? config?.model;
172
+ if (modelInput !== undefined) {
173
+ const resolved = resolveModel(modelInput, ctx.modelRegistry);
174
+ if (typeof resolved === "string") {
175
+ if (request.model !== undefined)
176
+ return { ok: false, error: resolved };
177
+ }
178
+ else {
179
+ model = resolved;
180
+ }
181
+ }
182
+ // Same scopeModels policy as the Agent tool and the nested delegation
183
+ // tools: a script's `agent({ model })` is a runtime LLM choice, and the
184
+ // script is written by the model, so it must not reach a model the user's
185
+ // enabledModels list excludes. `callerSupplied` keys off `request.model`
186
+ // and NOT `modelInput` — the latter has already absorbed the agent file's
187
+ // own `model:`, which is user-authored config and so earns the
188
+ // warn-and-proceed branch rather than a refusal.
189
+ const scopeVerdict = checkModelScope({
190
+ model,
191
+ cwd: ctx.cwd,
192
+ modelRegistry: ctx.modelRegistry,
193
+ callerSupplied: request.model !== undefined,
194
+ agentLabel: config?.displayName ?? dispatch.type,
195
+ modelInput,
196
+ });
197
+ // This agent's failure, not the run's — the same shape a bad agent type
198
+ // takes above. The script sees `null` and its siblings carry on, which is
199
+ // the difference between one refused model and a discarded fan-out.
200
+ if (scopeVerdict.kind === "error")
201
+ return { ok: false, error: scopeVerdict.message };
202
+ if (scopeVerdict.kind === "warn" && !warnedScopeMessages.has(scopeVerdict.message)) {
203
+ warnedScopeMessages.add(scopeVerdict.message);
204
+ ctx.ui.notify(scopeVerdict.message, "warning");
205
+ }
206
+ /**
207
+ * The gate's verdict, set only if the hook below actually ran the command.
208
+ * Its presence is what stops the runtime running the gate a second time,
209
+ * so it is set on the failure route too — a gate we tried and could not
210
+ * complete is a failed gate, never an un-run one that then re-runs
211
+ * against the wrong tree.
212
+ */
213
+ let gate;
214
+ let spawnedId;
215
+ /**
216
+ * Hand the child's EFFECTIVE configuration back to the run.
217
+ *
218
+ * `AgentRecord.invocation` is the one authoritative place for it (#168),
219
+ * filled by the manager the moment the child's session exists — which is
220
+ * before this fires, so it is populated by the time we read it. Reading it
221
+ * rather than re-deriving "the session, else the request" is the whole
222
+ * point of that field existing.
223
+ */
224
+ let sessionReady = false;
225
+ const reportResolved = () => {
226
+ // Called from BOTH the session hook and the spawn hook, because their
227
+ // order is not guaranteed: the manager fires `onSpawned` after
228
+ // `runAgent` returns, but `runAgent` decides when its own
229
+ // `onSessionCreated` fires — synchronously, for a stub. Each fires once,
230
+ // so the first call finds a half missing and returns, and the second is
231
+ // the one that reports.
232
+ if (!sessionReady || spawnedId === undefined)
233
+ return;
234
+ const info = resolvedInfo(manager.getRecord(spawnedId));
235
+ if (info !== undefined)
236
+ request.onResolved?.(info);
237
+ };
238
+ const command = request.gate;
239
+ /**
240
+ * Verify the child's work while its worktree still exists.
241
+ *
242
+ * The manager destroys that copy inside the child's own settle, so this
243
+ * is the last (and only) moment at which `npm test` can mean "the code
244
+ * this child just wrote" rather than "whatever is in the main tree".
245
+ */
246
+ const onBeforeWorktreeCleanup = command === undefined
247
+ ? undefined
248
+ : async (worktreePath) => {
249
+ // A failed child's gate is never consulted — the runtime reports
250
+ // the child's own failure — so running it would be pure cost.
251
+ if (spawnedId === undefined || !succeeded(manager.getRecord(spawnedId)))
252
+ return;
253
+ try {
254
+ gate = await executeGate(command, worktreePath);
255
+ }
256
+ catch (error) {
257
+ gate = { ok: false, output: error instanceof Error ? error.message : String(error) };
258
+ }
259
+ };
260
+ try {
261
+ const { record } = await manager.spawnAndWait(pi, ctx, dispatch.type, request.prompt, {
262
+ description: request.label,
263
+ // The stamp is what keeps this child out of the session's
264
+ // `maxConcurrent` pool — see `occupiesPoolSlot`. The run already
265
+ // bounds how many of its agents run at once, and counting them
266
+ // twice would let one fan-out starve everything else the user is
267
+ // doing. No `bypassQueue` needed: an agent outside the pool is
268
+ // never queued behind it.
269
+ ...(deps.workflowId !== undefined ? { workflowId: deps.workflowId } : {}),
270
+ ...(model !== undefined ? { model } : {}),
271
+ // Validated worker-side against the same list pi accepts, so the
272
+ // cast asserts what the boundary has already checked. Left unset,
273
+ // the agent definition's `thinking` (then the parent's) still wins —
274
+ // same precedence as `model` above.
275
+ ...(request.effort !== undefined ? { thinkingLevel: request.effort } : {}),
276
+ // Seeded with the REQUEST, not the outcome. The manager overwrites
277
+ // the effective half at session creation; without a seed there is
278
+ // nothing for it to compare against, so a level pi clamped would be
279
+ // indistinguishable from one that was honoured.
280
+ //
281
+ // Only the level. #182's other half — a caller parameter an agent
282
+ // file outranked — cannot arise here: this path resolves
283
+ // `request.model ?? config?.model`, so the script always wins and
284
+ // therefore always got what it asked for. Seeding a `requestedModel`
285
+ // would describe a precedence this path does not have.
286
+ invocation: {
287
+ ...(request.effort !== undefined ? { thinking: request.effort } : {}),
288
+ },
289
+ // Fires once the child's session exists, which is where the model
290
+ // and the clamped thinking level first become knowable.
291
+ onSessionCreated: () => { sessionReady = true; reportResolved(); },
292
+ ...(request.schema !== undefined ? { structuredOutput: request.schema } : {}),
293
+ ...(request.isolation !== undefined ? { isolation: request.isolation } : {}),
294
+ ...(deps.signal !== undefined ? { signal: deps.signal } : {}),
295
+ ...(deps.rootSessionId !== undefined ? { rootSessionId: deps.rootSessionId } : {}),
296
+ ...(onBeforeWorktreeCleanup !== undefined ? { onBeforeWorktreeCleanup } : {}),
297
+ }, id => {
298
+ spawnedId = id;
299
+ records.set(request.agentId, id);
300
+ // Ahead of `reportResolved`, and not folded into it: that one waits
301
+ // for the child's session so it can name the effective model, while
302
+ // the record id is known here and is what the inspector opens a
303
+ // conversation on. A child that fails before its session resolves
304
+ // would otherwise never be openable at all.
305
+ request.onResolved?.({ recordId: id });
306
+ reportResolved();
307
+ });
308
+ return { ...toSpawnResult(record), ...(gate !== undefined ? { gate } : {}) };
309
+ }
310
+ catch (error) {
311
+ // Strict worktree isolation rejects out of `awaitStartup` — the child
312
+ // never ran. That is this agent's failure, not the run's: the script
313
+ // sees `null` and its siblings carry on.
314
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
315
+ }
316
+ },
317
+ abortAgent(agentId) {
318
+ const id = records.get(agentId);
319
+ // Nothing to abort before the manager has issued an id — the child is
320
+ // still in startup, and the run's own signal reaches it there.
321
+ if (id !== undefined)
322
+ manager.abort(id);
323
+ },
324
+ async resumeAgent(agentId, prompt, onResolved) {
325
+ const id = records.get(agentId);
326
+ if (id === undefined) {
327
+ return { ok: false, error: `Cannot resume "${agentId}" — it never started.` };
328
+ }
329
+ const record = await manager.resume(id, prompt, deps.signal);
330
+ if (record === undefined) {
331
+ return {
332
+ ok: false,
333
+ error: `Agent ${id} has no session left to resume — records are dropped ten minutes after they finish.`,
334
+ };
335
+ }
336
+ // The resumed row is built from scratch, so it has to be told the same
337
+ // thing the first one was — the child's session already exists, so this is
338
+ // simply read back rather than waited for. The id goes first for the same
339
+ // reason it does on the spawn path: it is knowable even when the rest is
340
+ // not.
341
+ onResolved?.({ recordId: id });
342
+ const info = resolvedInfo(record);
343
+ if (info !== undefined)
344
+ onResolved?.(info);
345
+ return toSpawnResult(record);
346
+ },
347
+ /**
348
+ * Resolve a nested `workflow()` reference. The runtime decides whether what
349
+ * comes back is a workflow; this only finds it.
350
+ */
351
+ loadWorkflow(ref) {
352
+ return resolveWorkflowSource(ref, ctx.cwd);
353
+ },
354
+ // Reached only for a gate the spawn did not already run — a child with no
355
+ // worktree of its own, or a host wired without the pre-cleanup hook.
356
+ async runGate(command, gate) {
357
+ // The child's worktree when it had one and it survived; otherwise the
358
+ // session's own directory, which is where a non-isolated child worked.
359
+ return await executeGate(command, gate.cwd ?? ctx.cwd);
360
+ },
361
+ };
362
+ }
363
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/workflow/host.ts"],"names":[],"mappings":"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"}