@bastani/atomic 0.9.12 → 0.9.13-alpha.1

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 (264) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  3. package/dist/builtin/intercom/README.md +5 -12
  4. package/dist/builtin/intercom/broker/client.ts +11 -2
  5. package/dist/builtin/intercom/contact-supervisor-tool.ts +13 -3
  6. package/dist/builtin/intercom/index-heavy.ts +13 -3
  7. package/dist/builtin/intercom/index.ts +43 -19
  8. package/dist/builtin/intercom/intercom-utils.ts +15 -29
  9. package/dist/builtin/intercom/package.json +1 -1
  10. package/dist/builtin/intercom/source-ownership.ts +9 -12
  11. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  12. package/dist/builtin/mcp/README.md +3 -1
  13. package/dist/builtin/mcp/index.ts +10 -16
  14. package/dist/builtin/mcp/package.json +1 -1
  15. package/dist/builtin/mcp/startup-warmup.ts +20 -8
  16. package/dist/builtin/subagents/CHANGELOG.md +30 -0
  17. package/dist/builtin/subagents/README.md +22 -30
  18. package/dist/builtin/subagents/package.json +1 -1
  19. package/dist/builtin/subagents/src/extension/doctor.ts +1 -1
  20. package/dist/builtin/subagents/src/extension/fanout-child.ts +76 -56
  21. package/dist/builtin/subagents/src/extension/index.ts +23 -32
  22. package/dist/builtin/subagents/src/extension/startup-maintenance.ts +25 -44
  23. package/dist/builtin/subagents/src/intercom/result-intercom.ts +7 -7
  24. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +166 -434
  25. package/dist/builtin/subagents/src/runs/background/notify.ts +29 -8
  26. package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +2 -2
  27. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +4 -4
  28. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +2 -2
  29. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +2 -2
  30. package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +1 -281
  31. package/dist/builtin/subagents/src/runs/foreground/execution-structured-retries.ts +11 -75
  32. package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +457 -0
  33. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +119 -246
  34. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +1 -1
  35. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +18 -9
  36. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +1 -1
  37. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +4 -4
  38. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +1 -646
  39. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +2 -7
  40. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +5 -5
  41. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +7 -8
  42. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +14 -5
  43. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +158 -93
  44. package/dist/builtin/subagents/src/runs/inprocess/background-single.ts +179 -0
  45. package/dist/builtin/subagents/src/runs/inprocess/background.ts +89 -0
  46. package/dist/builtin/subagents/src/runs/inprocess/child-policy.ts +27 -0
  47. package/dist/builtin/subagents/src/runs/inprocess/control-registry.ts +55 -0
  48. package/dist/builtin/subagents/src/runs/inprocess/control-status.ts +106 -0
  49. package/dist/builtin/subagents/src/runs/inprocess/index.ts +50 -0
  50. package/dist/builtin/subagents/src/runs/inprocess/nested-routing.ts +218 -0
  51. package/dist/builtin/subagents/src/runs/{shared/subagent-prompt-runtime.ts → inprocess/prompt-behavior.ts} +37 -75
  52. package/dist/builtin/subagents/src/runs/inprocess/runner.ts +1138 -0
  53. package/dist/builtin/subagents/src/runs/{shared/nested-events.ts → inprocess/runtime-support/nested-api.ts} +13 -7
  54. package/dist/builtin/subagents/src/runs/{shared/nested-events-control.ts → inprocess/runtime-support/nested-control.ts} +18 -17
  55. package/dist/builtin/subagents/src/runs/{shared/nested-events-core.ts → inprocess/runtime-support/nested-core.ts} +14 -61
  56. package/dist/builtin/subagents/src/runs/{shared/nested-events-projection.ts → inprocess/runtime-support/nested-projection.ts} +4 -10
  57. package/dist/builtin/subagents/src/runs/{shared/nested-events-registry.ts → inprocess/runtime-support/nested-registry.ts} +19 -4
  58. package/dist/builtin/subagents/src/runs/{shared/nested-render.ts → inprocess/runtime-support/nested-rendering.ts} +3 -3
  59. package/dist/builtin/subagents/src/runs/{shared/nested-events-sanitize.ts → inprocess/runtime-support/nested-sanitize.ts} +3 -3
  60. package/dist/builtin/subagents/src/runs/inprocess.ts +1 -0
  61. package/dist/builtin/subagents/src/runs/shared/dynamic-fanout.ts +10 -4
  62. package/dist/builtin/subagents/src/runs/shared/model-candidate-filter.ts +0 -1
  63. package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +15 -492
  64. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +13 -11
  65. package/dist/builtin/subagents/src/runs/shared/run-history.ts +3 -5
  66. package/dist/builtin/subagents/src/runs/shared/single-output.ts +4 -4
  67. package/dist/builtin/subagents/src/runs/shared/workflow-graph.ts +5 -5
  68. package/dist/builtin/subagents/src/shared/types-async.ts +0 -1
  69. package/dist/builtin/subagents/src/shared/types-config.ts +18 -0
  70. package/dist/builtin/subagents/src/shared/types-results.ts +9 -2
  71. package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +2 -3
  72. package/dist/builtin/subagents/src/slash/slash-live-state.ts +2 -2
  73. package/dist/builtin/subagents/src/tui/render-chain-graph.ts +10 -4
  74. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +12 -11
  75. package/dist/builtin/subagents/src/tui/render-result-compact.ts +49 -12
  76. package/dist/builtin/subagents/src/tui/render-result.ts +46 -17
  77. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -1
  78. package/dist/builtin/subagents/src/tui/render-status-progress.ts +8 -5
  79. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +0 -8
  80. package/dist/builtin/subagents/src/tui/render-widget.ts +0 -24
  81. package/dist/builtin/web-access/package.json +1 -1
  82. package/dist/builtin/workflows/CHANGELOG.md +25 -0
  83. package/dist/builtin/workflows/README.md +13 -3
  84. package/dist/builtin/workflows/package.json +1 -1
  85. package/dist/builtin/workflows/src/durable/backend.ts +7 -0
  86. package/dist/builtin/workflows/src/durable/dbos-metadata.ts +11 -1
  87. package/dist/builtin/workflows/src/durable/resume-runtime.ts +1 -0
  88. package/dist/builtin/workflows/src/durable/tool-primitive.ts +4 -28
  89. package/dist/builtin/workflows/src/durable/types.ts +5 -0
  90. package/dist/builtin/workflows/src/engine/run.ts +17 -1
  91. package/dist/builtin/workflows/src/extension/atomic-stage-session.ts +12 -39
  92. package/dist/builtin/workflows/src/extension/config-file-loader.ts +10 -1
  93. package/dist/builtin/workflows/src/extension/config-loader.ts +1 -1
  94. package/dist/builtin/workflows/src/extension/dispatcher.ts +4 -0
  95. package/dist/builtin/workflows/src/extension/index.bundle.mjs +1151 -737
  96. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +303 -38
  97. package/dist/builtin/workflows/src/extension/render-result.ts +4 -0
  98. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -3
  99. package/dist/builtin/workflows/src/extension/runtime.ts +7 -1
  100. package/dist/builtin/workflows/src/extension/wiring.ts +53 -11
  101. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +12 -3
  102. package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +5 -2
  103. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +9 -7
  104. package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +11 -0
  105. package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +18 -1
  106. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +10 -8
  107. package/dist/builtin/workflows/src/extension/workflow-tool.ts +9 -4
  108. package/dist/builtin/workflows/src/runs/background/quit.ts +28 -4
  109. package/dist/builtin/workflows/src/runs/background/resume-acknowledgements.ts +2 -1
  110. package/dist/builtin/workflows/src/runs/background/status.ts +55 -8
  111. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +4 -0
  112. package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +3 -1
  113. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +1 -1
  114. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +1 -1
  115. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +688 -38
  116. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +3 -1
  117. package/dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts +19 -514
  118. package/dist/builtin/workflows/src/runs/shared/retry.ts +44 -0
  119. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +5 -0
  120. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +6 -0
  121. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +5 -1
  122. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +5 -0
  123. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +5 -0
  124. package/dist/builtin/workflows/src/shared/persistence-restore.ts +3 -0
  125. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
  126. package/dist/builtin/workflows/src/shared/run-indicator-status.ts +75 -0
  127. package/dist/builtin/workflows/src/shared/store-public-types.ts +43 -7
  128. package/dist/builtin/workflows/src/shared/store-run-methods.ts +42 -8
  129. package/dist/builtin/workflows/src/shared/store-stage-methods.ts +31 -8
  130. package/dist/builtin/workflows/src/shared/store-types.ts +34 -0
  131. package/dist/builtin/workflows/src/shared/timing.ts +10 -0
  132. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +22 -2
  133. package/dist/builtin/workflows/src/tui/session-list.ts +1 -1
  134. package/dist/builtin/workflows/src/tui/session-overlays.ts +14 -10
  135. package/dist/builtin/workflows/src/tui/session-picker.ts +20 -4
  136. package/dist/builtin/workflows/src/tui/status-list.ts +31 -47
  137. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +9 -1
  138. package/dist/builtin/workflows/src/tui/widget.ts +16 -46
  139. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  140. package/dist/core/agent-session-auto-compaction.js +54 -11
  141. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  142. package/dist/core/agent-session-events.d.ts.map +1 -1
  143. package/dist/core/agent-session-events.js +49 -14
  144. package/dist/core/agent-session-events.js.map +1 -1
  145. package/dist/core/agent-session-methods.d.ts +13 -0
  146. package/dist/core/agent-session-methods.d.ts.map +1 -1
  147. package/dist/core/agent-session-methods.js.map +1 -1
  148. package/dist/core/agent-session-models.d.ts.map +1 -1
  149. package/dist/core/agent-session-models.js +12 -1
  150. package/dist/core/agent-session-models.js.map +1 -1
  151. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  152. package/dist/core/agent-session-prompt.js +4 -0
  153. package/dist/core/agent-session-prompt.js.map +1 -1
  154. package/dist/core/agent-session-retry.d.ts +21 -4
  155. package/dist/core/agent-session-retry.d.ts.map +1 -1
  156. package/dist/core/agent-session-retry.js +232 -106
  157. package/dist/core/agent-session-retry.js.map +1 -1
  158. package/dist/core/agent-session-state.d.ts.map +1 -1
  159. package/dist/core/agent-session-state.js +2 -1
  160. package/dist/core/agent-session-state.js.map +1 -1
  161. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  162. package/dist/core/agent-session-tool-hooks.js +12 -0
  163. package/dist/core/agent-session-tool-hooks.js.map +1 -1
  164. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  165. package/dist/core/agent-session-tool-registry.js +1 -1
  166. package/dist/core/agent-session-tool-registry.js.map +1 -1
  167. package/dist/core/agent-session-types.d.ts +3 -1
  168. package/dist/core/agent-session-types.d.ts.map +1 -1
  169. package/dist/core/agent-session-types.js.map +1 -1
  170. package/dist/core/agent-session.d.ts +12 -1
  171. package/dist/core/agent-session.d.ts.map +1 -1
  172. package/dist/core/agent-session.js +7 -0
  173. package/dist/core/agent-session.js.map +1 -1
  174. package/dist/core/extensions/context-types.d.ts +25 -0
  175. package/dist/core/extensions/context-types.d.ts.map +1 -1
  176. package/dist/core/extensions/context-types.js.map +1 -1
  177. package/dist/core/extensions/index.d.ts +1 -1
  178. package/dist/core/extensions/index.d.ts.map +1 -1
  179. package/dist/core/extensions/index.js.map +1 -1
  180. package/dist/core/extensions/runner-context.d.ts +2 -1
  181. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  182. package/dist/core/extensions/runner-context.js +4 -0
  183. package/dist/core/extensions/runner-context.js.map +1 -1
  184. package/dist/core/extensions/runner.d.ts +3 -2
  185. package/dist/core/extensions/runner.d.ts.map +1 -1
  186. package/dist/core/extensions/runner.js +3 -1
  187. package/dist/core/extensions/runner.js.map +1 -1
  188. package/dist/core/model-fallback-failures.d.ts +30 -0
  189. package/dist/core/model-fallback-failures.d.ts.map +1 -0
  190. package/dist/core/model-fallback-failures.js +610 -0
  191. package/dist/core/model-fallback-failures.js.map +1 -0
  192. package/dist/core/retry-policy.d.ts +30 -0
  193. package/dist/core/retry-policy.d.ts.map +1 -0
  194. package/dist/core/retry-policy.js +25 -0
  195. package/dist/core/retry-policy.js.map +1 -0
  196. package/dist/core/sdk-types.d.ts +8 -2
  197. package/dist/core/sdk-types.d.ts.map +1 -1
  198. package/dist/core/sdk-types.js.map +1 -1
  199. package/dist/core/sdk.d.ts.map +1 -1
  200. package/dist/core/sdk.js +6 -1
  201. package/dist/core/sdk.js.map +1 -1
  202. package/dist/core/session-manager-core.d.ts +2 -0
  203. package/dist/core/session-manager-core.d.ts.map +1 -1
  204. package/dist/core/session-manager-core.js +7 -0
  205. package/dist/core/session-manager-core.js.map +1 -1
  206. package/dist/index-extensions.d.ts +1 -1
  207. package/dist/index-extensions.d.ts.map +1 -1
  208. package/dist/index-extensions.js.map +1 -1
  209. package/dist/index.d.ts +3 -0
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +2 -0
  212. package/dist/index.js.map +1 -1
  213. package/docs/intercom.md +5 -10
  214. package/docs/settings.md +7 -1
  215. package/docs/subagents.md +19 -19
  216. package/docs/workflows.md +21 -5
  217. package/examples/extensions/gondolin/package-lock.json +3 -3
  218. package/npm-shrinkwrap.json +29 -29
  219. package/package.json +2 -2
  220. package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +0 -112
  221. package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +0 -543
  222. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +0 -140
  223. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +0 -279
  224. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +0 -99
  225. package/dist/builtin/subagents/src/runs/background/async-execution.ts +0 -17
  226. package/dist/builtin/subagents/src/runs/background/async-resume.ts +0 -402
  227. package/dist/builtin/subagents/src/runs/background/async-status.ts +0 -411
  228. package/dist/builtin/subagents/src/runs/background/completion-claims.ts +0 -196
  229. package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +0 -102
  230. package/dist/builtin/subagents/src/runs/background/parallel-groups.ts +0 -59
  231. package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +0 -300
  232. package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +0 -166
  233. package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +0 -77
  234. package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +0 -48
  235. package/dist/builtin/subagents/src/runs/background/result-status.ts +0 -87
  236. package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +0 -72
  237. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +0 -320
  238. package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +0 -105
  239. package/dist/builtin/subagents/src/runs/background/run-status.ts +0 -358
  240. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +0 -457
  241. package/dist/builtin/subagents/src/runs/background/subagent-runner-dynamic.ts +0 -376
  242. package/dist/builtin/subagents/src/runs/background/subagent-runner-finalize.ts +0 -150
  243. package/dist/builtin/subagents/src/runs/background/subagent-runner-output.ts +0 -109
  244. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel-helpers.ts +0 -128
  245. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel.ts +0 -309
  246. package/dist/builtin/subagents/src/runs/background/subagent-runner-sequential.ts +0 -173
  247. package/dist/builtin/subagents/src/runs/background/subagent-runner-state.ts +0 -578
  248. package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +0 -330
  249. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +0 -330
  250. package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +0 -210
  251. package/dist/builtin/subagents/src/runs/background/subagent-runner-utils.ts +0 -69
  252. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +0 -90
  253. package/dist/builtin/subagents/src/runs/background/top-level-async.ts +0 -12
  254. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-control.ts +0 -140
  255. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +0 -108
  256. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-types.ts +0 -17
  257. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +0 -558
  258. package/dist/builtin/subagents/src/runs/shared/attempt-watchdog.ts +0 -126
  259. package/dist/builtin/subagents/src/runs/shared/final-drain.ts +0 -39
  260. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +0 -339
  261. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +0 -165
  262. package/dist/builtin/subagents/src/runs/shared/spawn-env.ts +0 -21
  263. package/dist/builtin/subagents/src/shared/post-exit-stdio-guard.ts +0 -86
  264. /package/dist/builtin/subagents/src/runs/{shared/nested-path.ts → inprocess/runtime-support/nested-paths.ts} +0 -0
@@ -1,543 +0,0 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import { getEnvValue } from "@bastani/atomic";
4
- import { buildSkillInjection, normalizeSkillInput, resolveSkillsWithFallback } from "../../agents/skills.ts";
5
- import {
6
- getSubagentCodexFastModeSettings,
7
- resolveSubagentCodexFastModeScope,
8
- resolveSubagentModelFastModeMetadata,
9
- } from "../../shared/fast-mode.ts";
10
- import { resolveEffectiveThinking } from "../../shared/model-info.ts";
11
- import {
12
- buildChainInstructions,
13
- isDynamicParallelStep,
14
- isParallelStep,
15
- type ResolvedStepBehavior,
16
- resolveStepBehavior,
17
- type SequentialStep,
18
- type StepOverrides,
19
- suppressProgressForReadOnlyTask,
20
- writeInitialProgressFile,
21
- } from "../../shared/settings.ts";
22
- import {
23
- ASYNC_DIR,
24
- RESULTS_DIR,
25
- resolveChildMaxSubagentDepth,
26
- SUBAGENT_ASYNC_STARTED_EVENT,
27
- } from "../../shared/types.ts";
28
- import { workflowSessionEnv } from "../../shared/types-depth.ts";
29
- import { resolveChildCwd } from "../../shared/utils.ts";
30
- import { ChainOutputValidationError, validateChainOutputBindings } from "../shared/chain-outputs.ts";
31
- import { resolveChildIntercomGroup, sharedAutoGroupForSet } from "../shared/intercom-group.ts";
32
- import { filterSpawnableModelCandidates } from "../shared/model-candidate-filter.ts";
33
- import { buildModelCandidates, resolveModelCandidate } from "../shared/model-fallback.ts";
34
- import {
35
- NESTED_RUNS_DIR,
36
- nestedResultsPath,
37
- resolveInheritedNestedRouteFromEnv,
38
- resolveNestedParentAddressFromEnv,
39
- writeNestedEvent,
40
- } from "../shared/nested-events.ts";
41
- import type { RunnerStep } from "../shared/parallel-utils.ts";
42
- import { applyThinkingSuffix, SUBAGENT_INTERCOM_SESSION_NAME_ENV } from "../shared/pi-args.ts";
43
- import {
44
- injectSingleOutputInstruction,
45
- resolveSingleOutputPath,
46
- validateFileOnlyOutputMode,
47
- } from "../shared/single-output.ts";
48
- import { createStructuredOutputRuntime } from "../shared/structured-output.ts";
49
- import { buildWorkflowGraphSnapshot } from "../shared/workflow-graph.ts";
50
- import { resolveExpectedWorktreeAgentCwd } from "../shared/worktree.ts";
51
- import {
52
- AsyncStartValidationError,
53
- spawnRunner as defaultSpawnRunner,
54
- formatAsyncStartError,
55
- formatAsyncStartedMessage,
56
- piPackageRoot,
57
- UNAVAILABLE_SUBAGENT_SKILL_ERROR,
58
- UnavailableSubagentSkillError,
59
- } from "./async-execution-common.ts";
60
- import type { AsyncChainParams, AsyncExecutionResult, AsyncSpawnResult } from "./async-execution-types.ts";
61
-
62
- /**
63
- * Execute a chain asynchronously
64
- */
65
- export function executeAsyncChain(id: string, params: AsyncChainParams): AsyncExecutionResult {
66
- const {
67
- chain,
68
- agents,
69
- ctx,
70
- cwd,
71
- maxOutput,
72
- artifactsDir,
73
- artifactConfig,
74
- shareEnabled,
75
- sessionRoot,
76
- sessionFilesByFlatIndex,
77
- maxSubagentDepth,
78
- workflowStageSubagentGuard,
79
- worktreeSetupHook,
80
- worktreeSetupHookTimeoutMs,
81
- controlConfig,
82
- controlIntercomTarget,
83
- childIntercomTarget,
84
- supervisorAuthorizations,
85
- dynamicSupervisorAuthorizations,
86
- nestedRoute,
87
- spawnRunner = defaultSpawnRunner,
88
- } = params;
89
- const resultMode = params.resultMode ?? "chain";
90
- const chainSkills = params.chainSkills ?? [];
91
- const availableModels = params.availableModels;
92
- const knownModelProviders = params.knownModelProviders;
93
- const fastModeScope = resolveSubagentCodexFastModeScope(workflowStageSubagentGuard);
94
- const runnerCwd = resolveChildCwd(ctx.cwd, cwd);
95
- const firstStep = chain[0];
96
- const originalTask =
97
- params.task ??
98
- (firstStep
99
- ? isParallelStep(firstStep)
100
- ? firstStep.parallel[0]?.task
101
- : isDynamicParallelStep(firstStep)
102
- ? firstStep.parallel.task
103
- : (firstStep as SequentialStep).task
104
- : undefined);
105
- try {
106
- validateChainOutputBindings(chain, { maxItems: params.dynamicFanoutMaxItems });
107
- } catch (error) {
108
- if (error instanceof ChainOutputValidationError) return formatAsyncStartError(resultMode, error.message);
109
- throw error;
110
- }
111
- const workflowGraph = buildWorkflowGraphSnapshot({ runId: id, mode: resultMode, steps: chain });
112
-
113
- for (const s of chain) {
114
- const stepAgents = isParallelStep(s)
115
- ? s.parallel.map((t) => t.agent)
116
- : isDynamicParallelStep(s)
117
- ? [s.parallel.agent]
118
- : [(s as SequentialStep).agent];
119
- for (const agentName of stepAgents) {
120
- if (!agents.find((x) => x.name === agentName)) {
121
- return {
122
- content: [{ type: "text", text: `Unknown agent: ${agentName}` }],
123
- isError: true,
124
- details: { mode: resultMode, results: [] },
125
- };
126
- }
127
- }
128
- }
129
-
130
- const inheritedNestedRoute = resolveInheritedNestedRouteFromEnv();
131
- const nestedAddress = inheritedNestedRoute ? resolveNestedParentAddressFromEnv() : undefined;
132
- const asyncDir = inheritedNestedRoute
133
- ? path.join(NESTED_RUNS_DIR, inheritedNestedRoute.rootRunId, id)
134
- : path.join(ASYNC_DIR, id);
135
- try {
136
- fs.mkdirSync(asyncDir, { recursive: true });
137
- } catch (error) {
138
- const message = error instanceof Error ? error.message : String(error);
139
- return {
140
- content: [{ type: "text", text: `Failed to create async run directory '${asyncDir}': ${message}` }],
141
- isError: true,
142
- details: { mode: resultMode, results: [] },
143
- };
144
- }
145
-
146
- let progressInstructionCreated = false;
147
- const buildStepOverrides = (s: SequentialStep): StepOverrides => {
148
- const stepSkillInput = normalizeSkillInput(s.skill);
149
- return {
150
- ...(s.output !== undefined ? { output: s.output } : {}),
151
- ...(s.outputMode !== undefined ? { outputMode: s.outputMode } : {}),
152
- ...(s.reads !== undefined ? { reads: s.reads } : {}),
153
- ...(s.progress !== undefined ? { progress: s.progress } : {}),
154
- ...(stepSkillInput !== undefined ? { skills: stepSkillInput } : {}),
155
- ...(s.model ? { model: s.model } : {}),
156
- };
157
- };
158
- const buildSeqStep = (
159
- s: SequentialStep,
160
- sessionFile?: string,
161
- behaviorCwd?: string,
162
- progressPrecreated = false,
163
- resolvedBehavior?: ResolvedStepBehavior,
164
- setGroup?: string | true,
165
- sharedAutoGroup?: string,
166
- ) => {
167
- const a = agents.find((x) => x.name === s.agent)!;
168
- const stepCwd = resolveChildCwd(runnerCwd, s.cwd);
169
- const instructionCwd = behaviorCwd ?? stepCwd;
170
- const behavior = suppressProgressForReadOnlyTask(
171
- resolvedBehavior ?? resolveStepBehavior(a, buildStepOverrides(s), chainSkills),
172
- s.task,
173
- originalTask,
174
- );
175
- const skillNames = behavior.skills === false ? [] : behavior.skills;
176
- const { resolved: resolvedSkills, missing: missingSkills } = resolveSkillsWithFallback(
177
- skillNames,
178
- stepCwd,
179
- ctx.cwd,
180
- );
181
- if (missingSkills.includes("subagent")) throw new UnavailableSubagentSkillError(UNAVAILABLE_SUBAGENT_SKILL_ERROR);
182
-
183
- let systemPrompt = a.systemPrompt?.trim() ?? "";
184
- if (resolvedSkills.length > 0) {
185
- const injection = buildSkillInjection(resolvedSkills);
186
- systemPrompt = systemPrompt ? `${systemPrompt}\n\n${injection}` : injection;
187
- }
188
-
189
- const readInstructions = buildChainInstructions(
190
- { ...behavior, output: false, progress: false },
191
- instructionCwd,
192
- false,
193
- );
194
- const isFirstProgressAgent = behavior.progress && !progressPrecreated && !progressInstructionCreated;
195
- if (behavior.progress) progressInstructionCreated = true;
196
- const progressInstructions = buildChainInstructions(
197
- { ...behavior, output: false, reads: false },
198
- runnerCwd,
199
- isFirstProgressAgent,
200
- );
201
- const outputPath = resolveSingleOutputPath(behavior.output, ctx.cwd, instructionCwd);
202
- const validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Async step (${s.agent})`);
203
- if (validationError) throw new AsyncStartValidationError(validationError);
204
- let taskTemplate = s.task ?? "{previous}";
205
- taskTemplate = taskTemplate.replace(/\{task\}/g, originalTask ?? "");
206
- taskTemplate = taskTemplate.replace(/\{chain_dir\}/g, runnerCwd);
207
- const task = injectSingleOutputInstruction(
208
- `${readInstructions.prefix}${taskTemplate}${progressInstructions.suffix}`,
209
- outputPath,
210
- );
211
-
212
- const primaryModel = resolveModelCandidate(behavior.model ?? a.model, availableModels, ctx.currentModelProvider);
213
- const model = applyThinkingSuffix(primaryModel, a.thinking);
214
- const rawModelCandidates = buildModelCandidates(
215
- behavior.model ?? a.model,
216
- a.fallbackModels,
217
- availableModels,
218
- ctx.currentModelProvider,
219
- ctx.currentModel,
220
- a.fallbackThinkingLevels,
221
- )
222
- .map((candidate) => applyThinkingSuffix(candidate, a.thinking))
223
- .filter((candidate): candidate is string => typeof candidate === "string");
224
- const filteredCandidates = filterSpawnableModelCandidates({
225
- candidates: rawModelCandidates,
226
- availableModels,
227
- knownModelProviders,
228
- currentModel: applyThinkingSuffix(ctx.currentModel, a.thinking),
229
- });
230
- const modelCandidates = filteredCandidates.candidates;
231
- const fastModeSettings = getSubagentCodexFastModeSettings(stepCwd);
232
- return {
233
- agent: s.agent,
234
- task,
235
- phase: s.phase,
236
- label: s.label,
237
- outputName: s.as,
238
- structured: Boolean(s.outputSchema),
239
- intercomGroup: resolveChildIntercomGroup(
240
- s.group ?? setGroup ?? params.group,
241
- ctx.intercomGroup,
242
- sharedAutoGroup,
243
- ),
244
- cwd: stepCwd,
245
- model,
246
- thinking: resolveEffectiveThinking(model, a.thinking),
247
- ...resolveSubagentModelFastModeMetadata({
248
- model,
249
- modelCandidates,
250
- cwd: stepCwd,
251
- settings: fastModeSettings,
252
- scope: fastModeScope,
253
- }),
254
- modelCandidates,
255
- modelAttempts: filteredCandidates.skippedAttempts,
256
- codexFastModeSettings: fastModeSettings,
257
- codexFastModeScope: fastModeScope,
258
- tools: a.tools,
259
- extensions: a.extensions,
260
- mcpDirectTools: a.mcpDirectTools,
261
- systemPrompt,
262
- systemPromptMode: a.systemPromptMode,
263
- inheritProjectContext: a.inheritProjectContext,
264
- inheritSkills: a.inheritSkills,
265
- skills: resolvedSkills.map((r) => r.name),
266
- outputPath,
267
- outputMode: behavior.outputMode,
268
- sessionFile,
269
- maxSubagentDepth: resolveChildMaxSubagentDepth(maxSubagentDepth, a.maxSubagentDepth),
270
- workflowStageSubagentGuard,
271
- ...(s.outputSchema ? { structuredOutputSchema: s.outputSchema } : {}),
272
- ...(s.outputSchema
273
- ? {
274
- structuredOutput: createStructuredOutputRuntime(
275
- s.outputSchema,
276
- path.join(asyncDir, "structured-output"),
277
- ),
278
- }
279
- : {}),
280
- };
281
- };
282
-
283
- let flatStepIndex = 0;
284
- const nextSessionFile = (): string | undefined => {
285
- const sessionFile = sessionFilesByFlatIndex?.[flatStepIndex];
286
- flatStepIndex++;
287
- return sessionFile;
288
- };
289
-
290
- let steps: RunnerStep[];
291
- try {
292
- steps = chain.map((s, stepIndex) => {
293
- if (isParallelStep(s)) {
294
- const setGroup = s.group ?? params.group;
295
- const sharedAutoGroup = sharedAutoGroupForSet(setGroup, s.parallel);
296
- const parallelBehaviors = s.parallel.map((task) => {
297
- const agent = agents.find((candidate) => candidate.name === task.agent)!;
298
- return suppressProgressForReadOnlyTask(
299
- resolveStepBehavior(agent, buildStepOverrides(task), chainSkills),
300
- task.task,
301
- originalTask,
302
- );
303
- });
304
- const progressPrecreated = parallelBehaviors.some((behavior) => behavior.progress);
305
- if (progressPrecreated) {
306
- if (!s.worktree) writeInitialProgressFile(runnerCwd);
307
- progressInstructionCreated = true;
308
- }
309
- return {
310
- parallel: s.parallel.map((t, taskIndex) => {
311
- let behaviorCwd: string | undefined;
312
- if (s.worktree) {
313
- try {
314
- behaviorCwd = resolveExpectedWorktreeAgentCwd(runnerCwd, `${id}-s${stepIndex}`, taskIndex);
315
- } catch {
316
- behaviorCwd = undefined;
317
- }
318
- }
319
- return buildSeqStep(
320
- t,
321
- nextSessionFile(),
322
- behaviorCwd,
323
- progressPrecreated,
324
- parallelBehaviors[taskIndex],
325
- setGroup,
326
- sharedAutoGroup,
327
- );
328
- }),
329
- concurrency: s.concurrency,
330
- failFast: s.failFast,
331
- worktree: s.worktree,
332
- };
333
- }
334
- if (isDynamicParallelStep(s)) {
335
- const setGroup = s.group ?? params.group;
336
- const sharedAutoGroup = sharedAutoGroupForSet(setGroup, [s.parallel]);
337
- const agent = agents.find((candidate) => candidate.name === s.parallel.agent)!;
338
- const behavior = suppressProgressForReadOnlyTask(
339
- resolveStepBehavior(agent, buildStepOverrides(s.parallel), chainSkills),
340
- s.parallel.task,
341
- originalTask,
342
- );
343
- const progressPrecreated = behavior.progress;
344
- if (progressPrecreated) {
345
- writeInitialProgressFile(runnerCwd);
346
- progressInstructionCreated = true;
347
- }
348
- return {
349
- expand: s.expand,
350
- parallel: buildSeqStep(
351
- s.parallel as SequentialStep,
352
- undefined,
353
- undefined,
354
- progressPrecreated,
355
- behavior,
356
- setGroup,
357
- sharedAutoGroup,
358
- ),
359
- collect: s.collect,
360
- concurrency: s.concurrency,
361
- failFast: s.failFast,
362
- phase: s.phase,
363
- label: s.label,
364
- };
365
- }
366
- return buildSeqStep(s as SequentialStep, nextSessionFile());
367
- });
368
- } catch (error) {
369
- if (error instanceof UnavailableSubagentSkillError || error instanceof AsyncStartValidationError)
370
- return formatAsyncStartError(resultMode, error.message);
371
- throw error;
372
- }
373
- let childTargetIndex = 0;
374
- const childIntercomTargets = childIntercomTarget
375
- ? steps.flatMap((step) => {
376
- if ("parallel" in step) {
377
- if (!Array.isArray(step.parallel)) {
378
- childTargetIndex++;
379
- return [undefined];
380
- }
381
- return step.parallel.map((task) => childIntercomTarget(task.agent, childTargetIndex++));
382
- }
383
- return [childIntercomTarget(step.agent, childTargetIndex++)];
384
- })
385
- : undefined;
386
-
387
- let spawnResult: AsyncSpawnResult = {};
388
- try {
389
- spawnResult = spawnRunner(
390
- {
391
- id,
392
- steps,
393
- resultPath: inheritedNestedRoute
394
- ? nestedResultsPath(inheritedNestedRoute.rootRunId, id)
395
- : path.join(RESULTS_DIR, `${id}.json`),
396
- cwd: runnerCwd,
397
- placeholder: "{previous}",
398
- maxOutput,
399
- artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
400
- artifactConfig,
401
- share: shareEnabled,
402
- sessionDir: sessionRoot ? path.join(sessionRoot, `async-${id}`) : undefined,
403
- asyncDir,
404
- sessionId: ctx.currentSessionId,
405
- piPackageRoot,
406
- piArgv1: process.argv[1],
407
- worktreeSetupHook,
408
- worktreeSetupHookTimeoutMs,
409
- controlConfig,
410
- controlIntercomTarget,
411
- childIntercomTargets,
412
- supervisorAuthorizations,
413
- dynamicSupervisorAuthorizations,
414
- resultMode,
415
- dynamicFanoutMaxItems: params.dynamicFanoutMaxItems,
416
- workflowGraph,
417
- nestedRoute: nestedRoute ?? inheritedNestedRoute,
418
- workflowStageSubagentGuard,
419
- nestedSelf:
420
- inheritedNestedRoute && nestedAddress
421
- ? {
422
- parentRunId: nestedAddress.parentRunId,
423
- parentStepIndex: nestedAddress.parentStepIndex,
424
- depth: nestedAddress.depth,
425
- path: nestedAddress.path,
426
- }
427
- : undefined,
428
- },
429
- id,
430
- runnerCwd,
431
- workflowSessionEnv(ctx.workflowSessionMetadata),
432
- );
433
- } catch (error) {
434
- const message = error instanceof Error ? error.message : String(error);
435
- return formatAsyncStartError(resultMode, `Failed to start async ${resultMode} '${id}': ${message}`);
436
- }
437
-
438
- if (spawnResult.error) {
439
- return formatAsyncStartError(resultMode, `Failed to start async ${resultMode} '${id}': ${spawnResult.error}`);
440
- }
441
-
442
- if (spawnResult.pid) {
443
- const firstStep = chain[0];
444
- const firstAgents = isParallelStep(firstStep)
445
- ? firstStep.parallel.map((t) => t.agent)
446
- : isDynamicParallelStep(firstStep)
447
- ? [firstStep.parallel.agent]
448
- : [(firstStep as SequentialStep).agent];
449
- const parallelGroups: Array<{ start: number; count: number; stepIndex: number }> = [];
450
- const flatAgents: string[] = [];
451
- let flatStepStart = 0;
452
- for (let stepIndex = 0; stepIndex < chain.length; stepIndex++) {
453
- const step = chain[stepIndex]!;
454
- if (isParallelStep(step)) {
455
- parallelGroups.push({ start: flatStepStart, count: step.parallel.length, stepIndex });
456
- flatAgents.push(...step.parallel.map((task) => task.agent));
457
- flatStepStart += step.parallel.length;
458
- } else if (isDynamicParallelStep(step)) {
459
- parallelGroups.push({ start: flatStepStart, count: 1, stepIndex });
460
- flatAgents.push(step.parallel.agent);
461
- flatStepStart++;
462
- } else {
463
- flatAgents.push((step as SequentialStep).agent);
464
- flatStepStart++;
465
- }
466
- }
467
- if (inheritedNestedRoute && nestedAddress) {
468
- const now = Date.now();
469
- try {
470
- writeNestedEvent(inheritedNestedRoute, {
471
- type: "subagent.nested.started",
472
- ts: now,
473
- parentRunId: nestedAddress.parentRunId,
474
- parentStepIndex: nestedAddress.parentStepIndex,
475
- child: {
476
- id,
477
- parentRunId: nestedAddress.parentRunId,
478
- parentStepIndex: nestedAddress.parentStepIndex,
479
- depth: nestedAddress.depth,
480
- path: nestedAddress.path,
481
- asyncDir,
482
- pid: spawnResult.pid,
483
- ownerIntercomTarget: getEnvValue(SUBAGENT_INTERCOM_SESSION_NAME_ENV),
484
- leafIntercomTarget: childIntercomTargets?.[0],
485
- intercomTarget: childIntercomTargets?.[0],
486
- ownerState: "live",
487
- mode: resultMode,
488
- state: "running",
489
- agent: firstAgents[0],
490
- agents: flatAgents,
491
- chainStepCount: chain.length,
492
- parallelGroups,
493
- startedAt: now,
494
- lastUpdate: now,
495
- },
496
- });
497
- } catch (error) {
498
- console.error("Failed to emit nested async start event:", error);
499
- }
500
- }
501
- ctx.pi.events.emit(SUBAGENT_ASYNC_STARTED_EVENT, {
502
- id,
503
- pid: spawnResult.pid,
504
- sessionId: ctx.currentSessionId,
505
- mode: resultMode,
506
- agent: firstAgents[0],
507
- agents: flatAgents,
508
- task: isParallelStep(firstStep)
509
- ? firstStep.parallel[0]?.task?.slice(0, 50)
510
- : isDynamicParallelStep(firstStep)
511
- ? firstStep.parallel.task?.slice(0, 50)
512
- : (firstStep as SequentialStep).task?.slice(0, 50),
513
- chain: chain.map((s) =>
514
- isParallelStep(s)
515
- ? `[${s.parallel.map((t) => t.agent).join("+")}]`
516
- : isDynamicParallelStep(s)
517
- ? `expand:${s.parallel.agent}`
518
- : (s as SequentialStep).agent,
519
- ),
520
- chainStepCount: chain.length,
521
- parallelGroups,
522
- workflowGraph,
523
- cwd: runnerCwd,
524
- asyncDir,
525
- nestedRoute,
526
- });
527
- }
528
-
529
- const chainDesc = chain
530
- .map((s) =>
531
- isParallelStep(s)
532
- ? `[${s.parallel.map((t) => t.agent).join("+")}]`
533
- : isDynamicParallelStep(s)
534
- ? `expand:${s.parallel.agent}`
535
- : (s as SequentialStep).agent,
536
- )
537
- .join(" -> ");
538
-
539
- return {
540
- content: [{ type: "text", text: formatAsyncStartedMessage(`Async ${resultMode}: ${chainDesc} [${id}]`) }],
541
- details: { mode: resultMode, runId: id, results: [], asyncId: id, asyncDir, workflowGraph },
542
- };
543
- }
@@ -1,140 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import * as fs from "node:fs";
3
- import { createRequire } from "node:module";
4
- import * as path from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import { APP_NAME } from "@bastani/atomic";
7
- import { getAsyncConfigPath, type SubagentRunMode, TEMP_ROOT_DIR } from "../../shared/types.ts";
8
- import { formatPiSpawnError, resolvePiPackageRoot, validatePiSpawnCwd } from "../shared/pi-spawn.ts";
9
- import { buildSubagentSpawnEnv } from "../shared/spawn-env.ts";
10
- import type { AsyncExecutionResult, AsyncSpawnResult } from "./async-execution-types.ts";
11
-
12
- const require = createRequire(import.meta.url);
13
- export const piPackageRoot = resolvePiPackageRoot();
14
-
15
- function resolveJitiCliFromPackageJson(packageJsonPath: string): string | undefined {
16
- if (!fs.existsSync(packageJsonPath)) return undefined;
17
- const packageRoot = path.dirname(packageJsonPath);
18
- const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")) as {
19
- bin?: string | Record<string, string>;
20
- };
21
- const binField = pkg.bin;
22
- const binPath = typeof binField === "string" ? binField : (binField?.jiti ?? Object.values(binField ?? {})[0]);
23
- const candidates = [binPath, "lib/jiti-cli.mjs"].filter((candidate): candidate is string => Boolean(candidate));
24
- for (const candidate of candidates) {
25
- const cliPath = path.resolve(packageRoot, candidate);
26
- if (fs.existsSync(cliPath)) return cliPath;
27
- }
28
- return undefined;
29
- }
30
-
31
- function resolveJitiCliPath(): string | undefined {
32
- const candidates: Array<() => string | undefined> = [
33
- () => require.resolve("jiti/package.json"),
34
- () =>
35
- piPackageRoot
36
- ? createRequire(path.join(piPackageRoot, "package.json")).resolve("jiti/package.json")
37
- : undefined,
38
- () => {
39
- if (!process.argv[1]) return undefined;
40
- const piEntry = fs.realpathSync(process.argv[1]);
41
- return createRequire(piEntry).resolve("jiti/package.json");
42
- },
43
- () => (piPackageRoot ? path.join(piPackageRoot, "node_modules", "jiti", "package.json") : undefined),
44
- ];
45
- for (const candidate of candidates) {
46
- try {
47
- const packageJsonPath = candidate();
48
- if (!packageJsonPath) continue;
49
- const cliPath = resolveJitiCliFromPackageJson(packageJsonPath);
50
- if (cliPath) return cliPath;
51
- } catch {
52
- // Candidate not available in this install, continue probing.
53
- }
54
- }
55
- return undefined;
56
- }
57
-
58
- const jitiCliPath = resolveJitiCliPath();
59
-
60
- export function formatAsyncStartedMessage(headline: string): string {
61
- return [
62
- `Launched: ${headline}`,
63
- "Completion pending; Pi will deliver the result when the detached run finishes.",
64
- "",
65
- "The async run is detached. Do not run sleep timers or polling loops just to wait for it.",
66
- "If you have independent work, continue that work. If you have nothing else to do until the async result arrives, end your turn now.",
67
- 'Use subagent({ action: "status", id: "..." }) when you need the current status/result, or to inspect a blocked/stale run. Do not poll just to wait.',
68
- ].join("\n");
69
- }
70
-
71
- /**
72
- * Check if jiti is available for async execution
73
- */
74
- export function isAsyncAvailable(): boolean {
75
- return jitiCliPath !== undefined;
76
- }
77
-
78
- /**
79
- * Spawn the async runner process
80
- */
81
- export function writeAsyncRunnerConfig(cfg: object, suffix: string): string {
82
- fs.mkdirSync(TEMP_ROOT_DIR, { recursive: true });
83
- const cfgPath = getAsyncConfigPath(suffix);
84
- fs.writeFileSync(cfgPath, JSON.stringify(cfg), { mode: 0o600 });
85
- return cfgPath;
86
- }
87
-
88
- export function spawnRunner(cfg: object, suffix: string, cwd: string, env?: Record<string, string>): AsyncSpawnResult {
89
- const cwdValidation = validatePiSpawnCwd(cwd);
90
- if (!cwdValidation.ok) return { error: cwdValidation.error };
91
-
92
- if (!jitiCliPath) {
93
- return {
94
- error: "upstream jiti for TypeScript execution could not be found; ensure package dependencies are installed",
95
- };
96
- }
97
-
98
- const cfgPath = writeAsyncRunnerConfig(cfg, suffix);
99
- const runner = path.join(path.dirname(fileURLToPath(import.meta.url)), "subagent-runner.ts");
100
-
101
- const spawnSpec = { command: process.execPath, args: [jitiCliPath, runner, cfgPath] };
102
- let proc: ReturnType<typeof spawn>;
103
- try {
104
- proc = spawn(spawnSpec.command, spawnSpec.args, {
105
- cwd,
106
- env: buildSubagentSpawnEnv(process.env, env),
107
- detached: true,
108
- stdio: "ignore",
109
- windowsHide: true,
110
- });
111
- } catch (error) {
112
- const spawnError = error instanceof Error ? error : new Error(String(error));
113
- return { error: formatPiSpawnError(spawnError, spawnSpec, cwd) };
114
- }
115
- proc.on("error", (error) => {
116
- console.error(`[${APP_NAME}-subagents] async spawn failed: ${formatPiSpawnError(error, spawnSpec, cwd)}`);
117
- });
118
- if (typeof proc.pid !== "number") {
119
- const noPidError = Object.assign(
120
- new Error(`spawn ${spawnSpec.command} failed before assigning a pid`),
121
- fs.existsSync(spawnSpec.command) ? {} : { code: "ENOENT" },
122
- );
123
- return { error: formatPiSpawnError(noPidError, spawnSpec, cwd) };
124
- }
125
- proc.unref();
126
- return { pid: proc.pid };
127
- }
128
-
129
- export function formatAsyncStartError(mode: SubagentRunMode, message: string): AsyncExecutionResult {
130
- return {
131
- content: [{ type: "text", text: message }],
132
- isError: true,
133
- details: { mode, results: [] },
134
- };
135
- }
136
-
137
- export const UNAVAILABLE_SUBAGENT_SKILL_ERROR = "Skills not found: subagent";
138
-
139
- export class UnavailableSubagentSkillError extends Error {}
140
- export class AsyncStartValidationError extends Error {}