@bastani/atomic 0.9.12-alpha.1 → 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 (265) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +12 -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 +12 -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 +36 -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/CHANGELOG.md +6 -0
  82. package/dist/builtin/web-access/package.json +1 -1
  83. package/dist/builtin/workflows/CHANGELOG.md +38 -0
  84. package/dist/builtin/workflows/README.md +13 -3
  85. package/dist/builtin/workflows/package.json +1 -1
  86. package/dist/builtin/workflows/src/durable/backend.ts +7 -0
  87. package/dist/builtin/workflows/src/durable/dbos-metadata.ts +11 -1
  88. package/dist/builtin/workflows/src/durable/resume-runtime.ts +1 -0
  89. package/dist/builtin/workflows/src/durable/tool-primitive.ts +4 -28
  90. package/dist/builtin/workflows/src/durable/types.ts +5 -0
  91. package/dist/builtin/workflows/src/engine/run.ts +17 -1
  92. package/dist/builtin/workflows/src/extension/atomic-stage-session.ts +12 -39
  93. package/dist/builtin/workflows/src/extension/config-file-loader.ts +10 -1
  94. package/dist/builtin/workflows/src/extension/config-loader.ts +1 -1
  95. package/dist/builtin/workflows/src/extension/dispatcher.ts +4 -0
  96. package/dist/builtin/workflows/src/extension/index.bundle.mjs +1151 -737
  97. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +303 -38
  98. package/dist/builtin/workflows/src/extension/render-result.ts +4 -0
  99. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -3
  100. package/dist/builtin/workflows/src/extension/runtime.ts +7 -1
  101. package/dist/builtin/workflows/src/extension/wiring.ts +53 -11
  102. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +12 -3
  103. package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +5 -2
  104. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +9 -7
  105. package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +11 -0
  106. package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +18 -1
  107. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +10 -8
  108. package/dist/builtin/workflows/src/extension/workflow-tool.ts +9 -4
  109. package/dist/builtin/workflows/src/runs/background/quit.ts +28 -4
  110. package/dist/builtin/workflows/src/runs/background/resume-acknowledgements.ts +2 -1
  111. package/dist/builtin/workflows/src/runs/background/status.ts +55 -8
  112. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +4 -0
  113. package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +3 -1
  114. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +1 -1
  115. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +1 -1
  116. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +688 -38
  117. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +3 -1
  118. package/dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts +19 -514
  119. package/dist/builtin/workflows/src/runs/shared/retry.ts +44 -0
  120. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +5 -0
  121. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +6 -0
  122. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +5 -1
  123. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +5 -0
  124. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +5 -0
  125. package/dist/builtin/workflows/src/shared/persistence-restore.ts +3 -0
  126. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
  127. package/dist/builtin/workflows/src/shared/run-indicator-status.ts +75 -0
  128. package/dist/builtin/workflows/src/shared/store-public-types.ts +43 -7
  129. package/dist/builtin/workflows/src/shared/store-run-methods.ts +42 -8
  130. package/dist/builtin/workflows/src/shared/store-stage-methods.ts +31 -8
  131. package/dist/builtin/workflows/src/shared/store-types.ts +34 -0
  132. package/dist/builtin/workflows/src/shared/timing.ts +10 -0
  133. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +22 -2
  134. package/dist/builtin/workflows/src/tui/session-list.ts +1 -1
  135. package/dist/builtin/workflows/src/tui/session-overlays.ts +14 -10
  136. package/dist/builtin/workflows/src/tui/session-picker.ts +20 -4
  137. package/dist/builtin/workflows/src/tui/status-list.ts +31 -47
  138. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +9 -1
  139. package/dist/builtin/workflows/src/tui/widget.ts +16 -46
  140. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  141. package/dist/core/agent-session-auto-compaction.js +54 -11
  142. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  143. package/dist/core/agent-session-events.d.ts.map +1 -1
  144. package/dist/core/agent-session-events.js +49 -14
  145. package/dist/core/agent-session-events.js.map +1 -1
  146. package/dist/core/agent-session-methods.d.ts +13 -0
  147. package/dist/core/agent-session-methods.d.ts.map +1 -1
  148. package/dist/core/agent-session-methods.js.map +1 -1
  149. package/dist/core/agent-session-models.d.ts.map +1 -1
  150. package/dist/core/agent-session-models.js +12 -1
  151. package/dist/core/agent-session-models.js.map +1 -1
  152. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  153. package/dist/core/agent-session-prompt.js +4 -0
  154. package/dist/core/agent-session-prompt.js.map +1 -1
  155. package/dist/core/agent-session-retry.d.ts +21 -4
  156. package/dist/core/agent-session-retry.d.ts.map +1 -1
  157. package/dist/core/agent-session-retry.js +232 -106
  158. package/dist/core/agent-session-retry.js.map +1 -1
  159. package/dist/core/agent-session-state.d.ts.map +1 -1
  160. package/dist/core/agent-session-state.js +2 -1
  161. package/dist/core/agent-session-state.js.map +1 -1
  162. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  163. package/dist/core/agent-session-tool-hooks.js +12 -0
  164. package/dist/core/agent-session-tool-hooks.js.map +1 -1
  165. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  166. package/dist/core/agent-session-tool-registry.js +1 -1
  167. package/dist/core/agent-session-tool-registry.js.map +1 -1
  168. package/dist/core/agent-session-types.d.ts +3 -1
  169. package/dist/core/agent-session-types.d.ts.map +1 -1
  170. package/dist/core/agent-session-types.js.map +1 -1
  171. package/dist/core/agent-session.d.ts +12 -1
  172. package/dist/core/agent-session.d.ts.map +1 -1
  173. package/dist/core/agent-session.js +7 -0
  174. package/dist/core/agent-session.js.map +1 -1
  175. package/dist/core/extensions/context-types.d.ts +25 -0
  176. package/dist/core/extensions/context-types.d.ts.map +1 -1
  177. package/dist/core/extensions/context-types.js.map +1 -1
  178. package/dist/core/extensions/index.d.ts +1 -1
  179. package/dist/core/extensions/index.d.ts.map +1 -1
  180. package/dist/core/extensions/index.js.map +1 -1
  181. package/dist/core/extensions/runner-context.d.ts +2 -1
  182. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  183. package/dist/core/extensions/runner-context.js +4 -0
  184. package/dist/core/extensions/runner-context.js.map +1 -1
  185. package/dist/core/extensions/runner.d.ts +3 -2
  186. package/dist/core/extensions/runner.d.ts.map +1 -1
  187. package/dist/core/extensions/runner.js +3 -1
  188. package/dist/core/extensions/runner.js.map +1 -1
  189. package/dist/core/model-fallback-failures.d.ts +30 -0
  190. package/dist/core/model-fallback-failures.d.ts.map +1 -0
  191. package/dist/core/model-fallback-failures.js +610 -0
  192. package/dist/core/model-fallback-failures.js.map +1 -0
  193. package/dist/core/retry-policy.d.ts +30 -0
  194. package/dist/core/retry-policy.d.ts.map +1 -0
  195. package/dist/core/retry-policy.js +25 -0
  196. package/dist/core/retry-policy.js.map +1 -0
  197. package/dist/core/sdk-types.d.ts +8 -2
  198. package/dist/core/sdk-types.d.ts.map +1 -1
  199. package/dist/core/sdk-types.js.map +1 -1
  200. package/dist/core/sdk.d.ts.map +1 -1
  201. package/dist/core/sdk.js +6 -1
  202. package/dist/core/sdk.js.map +1 -1
  203. package/dist/core/session-manager-core.d.ts +2 -0
  204. package/dist/core/session-manager-core.d.ts.map +1 -1
  205. package/dist/core/session-manager-core.js +7 -0
  206. package/dist/core/session-manager-core.js.map +1 -1
  207. package/dist/index-extensions.d.ts +1 -1
  208. package/dist/index-extensions.d.ts.map +1 -1
  209. package/dist/index-extensions.js.map +1 -1
  210. package/dist/index.d.ts +3 -0
  211. package/dist/index.d.ts.map +1 -1
  212. package/dist/index.js +2 -0
  213. package/dist/index.js.map +1 -1
  214. package/docs/intercom.md +5 -10
  215. package/docs/settings.md +7 -1
  216. package/docs/subagents.md +19 -19
  217. package/docs/workflows.md +21 -5
  218. package/examples/extensions/gondolin/package-lock.json +3 -3
  219. package/npm-shrinkwrap.json +29 -29
  220. package/package.json +2 -2
  221. package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +0 -112
  222. package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +0 -543
  223. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +0 -140
  224. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +0 -279
  225. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +0 -99
  226. package/dist/builtin/subagents/src/runs/background/async-execution.ts +0 -17
  227. package/dist/builtin/subagents/src/runs/background/async-resume.ts +0 -402
  228. package/dist/builtin/subagents/src/runs/background/async-status.ts +0 -411
  229. package/dist/builtin/subagents/src/runs/background/completion-claims.ts +0 -196
  230. package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +0 -102
  231. package/dist/builtin/subagents/src/runs/background/parallel-groups.ts +0 -59
  232. package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +0 -300
  233. package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +0 -166
  234. package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +0 -77
  235. package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +0 -48
  236. package/dist/builtin/subagents/src/runs/background/result-status.ts +0 -87
  237. package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +0 -72
  238. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +0 -320
  239. package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +0 -105
  240. package/dist/builtin/subagents/src/runs/background/run-status.ts +0 -358
  241. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +0 -457
  242. package/dist/builtin/subagents/src/runs/background/subagent-runner-dynamic.ts +0 -376
  243. package/dist/builtin/subagents/src/runs/background/subagent-runner-finalize.ts +0 -150
  244. package/dist/builtin/subagents/src/runs/background/subagent-runner-output.ts +0 -109
  245. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel-helpers.ts +0 -128
  246. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel.ts +0 -309
  247. package/dist/builtin/subagents/src/runs/background/subagent-runner-sequential.ts +0 -173
  248. package/dist/builtin/subagents/src/runs/background/subagent-runner-state.ts +0 -578
  249. package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +0 -330
  250. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +0 -330
  251. package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +0 -210
  252. package/dist/builtin/subagents/src/runs/background/subagent-runner-utils.ts +0 -69
  253. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +0 -90
  254. package/dist/builtin/subagents/src/runs/background/top-level-async.ts +0 -12
  255. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-control.ts +0 -140
  256. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +0 -108
  257. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-types.ts +0 -17
  258. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +0 -558
  259. package/dist/builtin/subagents/src/runs/shared/attempt-watchdog.ts +0 -126
  260. package/dist/builtin/subagents/src/runs/shared/final-drain.ts +0 -39
  261. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +0 -339
  262. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +0 -165
  263. package/dist/builtin/subagents/src/runs/shared/spawn-env.ts +0 -21
  264. package/dist/builtin/subagents/src/shared/post-exit-stdio-guard.ts +0 -86
  265. /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 {}