@duckmind/dm-linux-x64 0.61.5 → 0.62.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 (285) hide show
  1. package/dm +0 -0
  2. package/extensions/.dm-extensions.json +215 -71
  3. package/extensions/dm-cua/bin/browser-cua.mjs +6 -1
  4. package/extensions/dm-cua/index.js +3 -2
  5. package/extensions/dm-cua/src/browser-cua-lib.mjs +69 -13
  6. package/extensions/dm-subagents/agents/claude-code-writer.md +15 -0
  7. package/extensions/dm-subagents/agents/claude-code.md +15 -0
  8. package/extensions/dm-subagents/agents/codex-exec-writer.md +15 -0
  9. package/extensions/dm-subagents/agents/codex-exec.md +15 -0
  10. package/extensions/dm-subagents/agents/cursor-agent-writer.md +14 -0
  11. package/extensions/dm-subagents/agents/cursor-agent.md +14 -0
  12. package/extensions/dm-subagents/agents/delegate.md +3 -2
  13. package/extensions/dm-subagents/agents/oracle.md +10 -5
  14. package/extensions/dm-subagents/agents/researcher.md +2 -2
  15. package/extensions/dm-subagents/agents/reviewer.md +17 -7
  16. package/extensions/dm-subagents/agents/scout.md +5 -5
  17. package/extensions/dm-subagents/agents/worker.md +6 -2
  18. package/extensions/dm-subagents/async-retention-discovery-worker.mjs +167 -0
  19. package/extensions/dm-subagents/index.js +4 -0
  20. package/extensions/dm-subagents/inspector-runner.mjs +10 -0
  21. package/extensions/dm-subagents/install.mjs +3 -2
  22. package/extensions/dm-subagents/package.json +2 -2
  23. package/extensions/dm-subagents/prompts/council.md +60 -0
  24. package/extensions/dm-subagents/prompts/parallel-review.md +5 -1
  25. package/extensions/dm-subagents/prompts/review-loop.md +13 -7
  26. package/extensions/dm-subagents/skills/council-mode/SKILL.md +59 -0
  27. package/extensions/dm-subagents/skills/council-mode/references/pass-contracts.md +150 -0
  28. package/extensions/dm-subagents/skills/dm-subagents/SKILL.md +96 -911
  29. package/extensions/dm-subagents/skills/dm-subagents/references/constraints-and-recipes.md +70 -0
  30. package/extensions/dm-subagents/skills/dm-subagents/references/execution-controls.md +539 -0
  31. package/extensions/dm-subagents/skills/dm-subagents/references/management-authoring-rpc.md +161 -0
  32. package/extensions/dm-subagents/skills/dm-subagents/references/multi-lane-orchestration.md +51 -0
  33. package/extensions/dm-subagents/skills/dm-subagents/references/prompting-and-roles.md +295 -0
  34. package/extensions/dm-subagents/skills/dm-subagents/references/review-and-validation.md +73 -0
  35. package/extensions/dm-subagents/src/agents/agent-management.js +716 -484
  36. package/extensions/dm-subagents/src/agents/agent-refinements.js +563 -0
  37. package/extensions/dm-subagents/src/agents/agent-serializer.js +70 -5
  38. package/extensions/dm-subagents/src/agents/agents.js +1447 -299
  39. package/extensions/dm-subagents/src/agents/builtin-names.js +15 -0
  40. package/extensions/dm-subagents/src/agents/chain-serializer.js +12 -7
  41. package/extensions/dm-subagents/src/agents/frontmatter.js +64 -14
  42. package/extensions/dm-subagents/src/agents/identity.js +1 -1
  43. package/extensions/dm-subagents/src/agents/proactive-skills.js +14 -11
  44. package/extensions/dm-subagents/src/agents/runtime-agent-events.js +49 -0
  45. package/extensions/dm-subagents/src/agents/runtime-agent-registry.js +412 -0
  46. package/extensions/dm-subagents/src/agents/skills.js +52 -35
  47. package/extensions/dm-subagents/src/api/agents.js +6 -0
  48. package/extensions/dm-subagents/src/api/background-work.js +151 -0
  49. package/extensions/dm-subagents/src/api/capability-ceiling.js +12 -0
  50. package/extensions/dm-subagents/src/api/control-channel.js +3 -0
  51. package/extensions/dm-subagents/src/api/delegation.js +5 -0
  52. package/extensions/dm-subagents/src/api/dm-args.js +3 -0
  53. package/extensions/dm-subagents/src/api/external-job-provider.js +137 -0
  54. package/extensions/dm-subagents/src/api/external-runs.js +233 -0
  55. package/extensions/dm-subagents/src/api/intercom-bridge.js +3 -0
  56. package/extensions/dm-subagents/src/api/preflight.js +322 -0
  57. package/extensions/dm-subagents/src/api/project-panes.js +11 -0
  58. package/extensions/dm-subagents/src/api/shared-types.js +4 -0
  59. package/extensions/dm-subagents/src/extension/config.js +175 -0
  60. package/extensions/dm-subagents/src/extension/control-notices.js +4 -43
  61. package/extensions/dm-subagents/src/extension/doctor.js +71 -17
  62. package/extensions/dm-subagents/src/extension/fanout-child.js +49 -32
  63. package/extensions/dm-subagents/src/extension/index.js +711 -265
  64. package/extensions/dm-subagents/src/extension/public-execution.js +114 -0
  65. package/extensions/dm-subagents/src/extension/rpc.js +427 -22
  66. package/extensions/dm-subagents/src/extension/schemas.js +158 -65
  67. package/extensions/dm-subagents/src/extension/steering-notices.js +23 -0
  68. package/extensions/dm-subagents/src/extension/subagent-guide.js +31 -0
  69. package/extensions/dm-subagents/src/extension/tool-description.js +92 -74
  70. package/extensions/dm-subagents/src/extension/tool-result.js +7 -0
  71. package/extensions/dm-subagents/src/inspectors/herdr/actions.js +218 -0
  72. package/extensions/dm-subagents/src/inspectors/herdr/client.js +123 -0
  73. package/extensions/dm-subagents/src/inspectors/herdr/focus.js +47 -0
  74. package/extensions/dm-subagents/src/inspectors/herdr/inspector-runner.js +160 -0
  75. package/extensions/dm-subagents/src/inspectors/herdr/project-panes.js +618 -0
  76. package/extensions/dm-subagents/src/inspectors/herdr/session-roots-codec.js +21 -0
  77. package/extensions/dm-subagents/src/inspectors/herdr/shell-command.js +15 -0
  78. package/extensions/dm-subagents/src/integrations/herdr-status.js +377 -0
  79. package/extensions/dm-subagents/src/intercom/intercom-bridge.js +17 -13
  80. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +371 -79
  81. package/extensions/dm-subagents/src/intercom/result-intercom.js +47 -7
  82. package/extensions/dm-subagents/src/missions/actions.js +394 -0
  83. package/extensions/dm-subagents/src/missions/goal-driver.js +149 -0
  84. package/extensions/dm-subagents/src/missions/lifecycle.js +331 -0
  85. package/extensions/dm-subagents/src/missions/store.js +548 -0
  86. package/extensions/dm-subagents/src/missions/types.js +9 -0
  87. package/extensions/dm-subagents/src/missions/workflow-state.js +245 -0
  88. package/extensions/dm-subagents/src/policy/authority.js +37 -0
  89. package/extensions/dm-subagents/src/profiles/profiles.js +36 -18
  90. package/extensions/dm-subagents/src/runs/background/active-async-capacity.js +427 -0
  91. package/extensions/dm-subagents/src/runs/background/active-run-index.js +122 -0
  92. package/extensions/dm-subagents/src/runs/background/async-execution.js +925 -137
  93. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +515 -148
  94. package/extensions/dm-subagents/src/runs/background/async-resume.js +378 -51
  95. package/extensions/dm-subagents/src/runs/background/async-retention.js +828 -0
  96. package/extensions/dm-subagents/src/runs/background/async-status-snapshot.js +31 -0
  97. package/extensions/dm-subagents/src/runs/background/async-status.js +259 -22
  98. package/extensions/dm-subagents/src/runs/background/auto-drain.js +46 -0
  99. package/extensions/dm-subagents/src/runs/background/chain-append.js +50 -15
  100. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +67 -12
  101. package/extensions/dm-subagents/src/runs/background/completion-batcher.js +5 -1
  102. package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +3 -11
  103. package/extensions/dm-subagents/src/runs/background/completion-replay.js +245 -0
  104. package/extensions/dm-subagents/src/runs/background/control-channel.js +423 -36
  105. package/extensions/dm-subagents/src/runs/background/fleet-view.js +132 -59
  106. package/extensions/dm-subagents/src/runs/background/index-segment.js +38 -0
  107. package/extensions/dm-subagents/src/runs/background/inspect-rpc.js +373 -0
  108. package/extensions/dm-subagents/src/runs/background/notify.js +357 -57
  109. package/extensions/dm-subagents/src/runs/background/owned-process-tree.js +86 -0
  110. package/extensions/dm-subagents/src/runs/background/process-terminal.js +269 -0
  111. package/extensions/dm-subagents/src/runs/background/result-delivery-ownership.js +34 -0
  112. package/extensions/dm-subagents/src/runs/background/result-files.js +469 -0
  113. package/extensions/dm-subagents/src/runs/background/result-watcher.js +540 -75
  114. package/extensions/dm-subagents/src/runs/background/resume-guidance.js +44 -0
  115. package/extensions/dm-subagents/src/runs/background/retained-children.js +119 -0
  116. package/extensions/dm-subagents/src/runs/background/run-id-query.js +5 -0
  117. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +93 -9
  118. package/extensions/dm-subagents/src/runs/background/run-status.js +303 -32
  119. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +784 -376
  120. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +75 -34
  121. package/extensions/dm-subagents/src/runs/background/steering.js +221 -0
  122. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +3106 -844
  123. package/extensions/dm-subagents/src/runs/background/subagent-wait.js +529 -0
  124. package/extensions/dm-subagents/src/runs/background/terminal-run-index.js +106 -0
  125. package/extensions/dm-subagents/src/runs/background/top-level-async.js +1 -1
  126. package/extensions/dm-subagents/src/runs/background/wait-completions.js +155 -0
  127. package/extensions/dm-subagents/src/runs/background/wait-config.js +46 -0
  128. package/extensions/dm-subagents/src/runs/background/wait-subscriptions.js +278 -0
  129. package/extensions/dm-subagents/src/runs/background/wait-tool.js +47 -0
  130. package/extensions/dm-subagents/src/runs/foreground/async-dismiss-action.js +81 -0
  131. package/extensions/dm-subagents/src/runs/foreground/async-steering-action.js +245 -0
  132. package/extensions/dm-subagents/src/runs/foreground/async-stop-action.js +74 -0
  133. package/extensions/dm-subagents/src/runs/foreground/execution.js +1401 -342
  134. package/extensions/dm-subagents/src/runs/foreground/foreground-control.js +133 -0
  135. package/extensions/dm-subagents/src/runs/foreground/foreground-history.js +148 -0
  136. package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +139 -0
  137. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +4278 -1441
  138. package/extensions/dm-subagents/src/runs/foreground/workflow-detach-reconcile.js +278 -0
  139. package/extensions/dm-subagents/src/runs/foreground/workflow-foreground-steering.js +155 -0
  140. package/extensions/dm-subagents/src/runs/shared/abort-recovery.js +97 -0
  141. package/extensions/dm-subagents/src/runs/shared/acceptance.js +597 -148
  142. package/extensions/dm-subagents/src/runs/shared/agent-contract.js +35 -0
  143. package/extensions/dm-subagents/src/runs/shared/async-status-projection.js +472 -0
  144. package/extensions/dm-subagents/src/runs/shared/background-process-options.js +6 -0
  145. package/extensions/dm-subagents/src/runs/shared/capability-ceiling.js +175 -0
  146. package/extensions/dm-subagents/src/runs/shared/child-identity.js +32 -0
  147. package/extensions/dm-subagents/src/runs/shared/child-launch-plan.js +65 -0
  148. package/extensions/dm-subagents/src/runs/shared/child-protocol.js +447 -0
  149. package/extensions/dm-subagents/src/runs/shared/claude-code-adapter.js +120 -0
  150. package/extensions/dm-subagents/src/runs/shared/codex-exec-adapter.js +129 -0
  151. package/extensions/dm-subagents/src/runs/shared/completion-evidence.js +40 -0
  152. package/extensions/dm-subagents/src/runs/shared/completion-guard.js +140 -83
  153. package/extensions/dm-subagents/src/runs/shared/context-mode.js +38 -0
  154. package/extensions/dm-subagents/src/runs/shared/cursor-agent-adapter.js +101 -0
  155. package/extensions/dm-subagents/src/runs/shared/dm-args.js +445 -72
  156. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +27 -16
  157. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +19 -6
  158. package/extensions/dm-subagents/src/runs/shared/extension-bindings.js +81 -0
  159. package/extensions/dm-subagents/src/runs/shared/external-cli-contract.js +134 -0
  160. package/extensions/dm-subagents/src/runs/shared/external-cli-preflight.js +98 -0
  161. package/extensions/dm-subagents/src/runs/shared/external-cli-runner.js +419 -0
  162. package/extensions/dm-subagents/src/runs/shared/external-job-bridge.js +404 -0
  163. package/extensions/dm-subagents/src/runs/shared/external-job-runner.js +334 -0
  164. package/extensions/dm-subagents/src/runs/shared/fast-mode-extension.js +8 -0
  165. package/extensions/dm-subagents/src/runs/shared/host-step-status.js +228 -0
  166. package/extensions/dm-subagents/src/runs/shared/lane-metadata.js +104 -0
  167. package/extensions/dm-subagents/src/runs/shared/launch-cwd.js +17 -0
  168. package/extensions/dm-subagents/src/runs/shared/llm-intent-arbiter.js +190 -0
  169. package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +48 -3
  170. package/extensions/dm-subagents/src/runs/shared/mcp-config-sources.js +387 -0
  171. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +212 -137
  172. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-grant.js +131 -0
  173. package/extensions/dm-subagents/src/runs/shared/model-exclusions.js +207 -0
  174. package/extensions/dm-subagents/src/runs/shared/model-fallback.js +225 -55
  175. package/extensions/dm-subagents/src/runs/shared/model-scope.js +85 -28
  176. package/extensions/dm-subagents/src/runs/shared/mutation-evidence.js +182 -0
  177. package/extensions/dm-subagents/src/runs/shared/nested-events.js +264 -102
  178. package/extensions/dm-subagents/src/runs/shared/nested-render.js +15 -5
  179. package/extensions/dm-subagents/src/runs/shared/orca-progress-tabs.js +505 -0
  180. package/extensions/dm-subagents/src/runs/shared/parallel-handoff.js +653 -0
  181. package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +29 -12
  182. package/extensions/dm-subagents/src/runs/shared/permissions.js +108 -0
  183. package/extensions/dm-subagents/src/runs/shared/process-signal.js +13 -0
  184. package/extensions/dm-subagents/src/runs/shared/run-fanout-budget.js +257 -0
  185. package/extensions/dm-subagents/src/runs/shared/run-history.js +133 -13
  186. package/extensions/dm-subagents/src/runs/shared/runtime-acknowledged-extensions.js +62 -0
  187. package/extensions/dm-subagents/src/runs/shared/session-lease.js +225 -0
  188. package/extensions/dm-subagents/src/runs/shared/single-output.js +129 -27
  189. package/extensions/dm-subagents/src/runs/shared/spawn-budget.js +95 -0
  190. package/extensions/dm-subagents/src/runs/shared/structured-output.js +129 -10
  191. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +66 -11
  192. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +548 -70
  193. package/extensions/dm-subagents/src/runs/shared/subagent-startup-retry.js +50 -0
  194. package/extensions/dm-subagents/src/runs/shared/task-intent.js +130 -0
  195. package/extensions/dm-subagents/src/runs/shared/tool-availability.js +59 -0
  196. package/extensions/dm-subagents/src/runs/shared/tool-budget.js +7 -5
  197. package/extensions/dm-subagents/src/runs/shared/tool-timeout.js +64 -0
  198. package/extensions/dm-subagents/src/runs/shared/usage-budget.js +74 -0
  199. package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +22 -0
  200. package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-plan.js +721 -0
  201. package/extensions/dm-subagents/src/runs/shared/worktree.js +168 -19
  202. package/extensions/dm-subagents/src/shared/accessible-dir.js +35 -0
  203. package/extensions/dm-subagents/src/shared/agent-stream-options.js +3 -0
  204. package/extensions/dm-subagents/src/shared/artifacts.js +170 -11
  205. package/extensions/dm-subagents/src/shared/atomic-json.js +36 -38
  206. package/extensions/dm-subagents/src/shared/capacity-resilient-json.js +77 -0
  207. package/extensions/dm-subagents/src/shared/child-session-name.js +15 -0
  208. package/extensions/dm-subagents/src/shared/child-transcript.js +57 -2
  209. package/extensions/dm-subagents/src/shared/completion-owner.js +7 -0
  210. package/extensions/dm-subagents/src/shared/display-text.js +142 -0
  211. package/extensions/dm-subagents/src/shared/extension-context.js +17 -0
  212. package/extensions/dm-subagents/src/shared/file-coalescer.js +9 -0
  213. package/extensions/dm-subagents/src/shared/file-system-retry.js +56 -0
  214. package/extensions/dm-subagents/src/shared/fork-context.js +96 -33
  215. package/extensions/dm-subagents/src/shared/formatters.js +21 -7
  216. package/extensions/dm-subagents/src/shared/launch-contract.js +94 -0
  217. package/extensions/dm-subagents/src/shared/model-info.js +10 -5
  218. package/extensions/dm-subagents/src/shared/node-executable.js +19 -0
  219. package/extensions/dm-subagents/src/shared/prompt-resources.js +10 -0
  220. package/extensions/dm-subagents/src/shared/pruned-fork.js +427 -0
  221. package/extensions/dm-subagents/src/shared/session-file-trust.js +19 -0
  222. package/extensions/dm-subagents/src/shared/session-tokens.js +14 -3
  223. package/extensions/dm-subagents/src/shared/settings.js +39 -47
  224. package/extensions/dm-subagents/src/shared/shortcuts.js +16 -0
  225. package/extensions/dm-subagents/src/shared/status-format.js +9 -2
  226. package/extensions/dm-subagents/src/shared/thinking-ceiling.js +41 -0
  227. package/extensions/dm-subagents/src/shared/types.js +47 -7
  228. package/extensions/dm-subagents/src/shared/utf8.js +12 -0
  229. package/extensions/dm-subagents/src/shared/utils.js +151 -131
  230. package/extensions/dm-subagents/src/shared/watch-strategy.js +3 -0
  231. package/extensions/dm-subagents/src/shared/workflow-child-permit.js +84 -0
  232. package/extensions/dm-subagents/src/slash/delegation-adapters.js +274 -0
  233. package/extensions/dm-subagents/src/slash/delegation-json.js +113 -0
  234. package/extensions/dm-subagents/src/slash/delegation-request.js +152 -0
  235. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +294 -243
  236. package/extensions/dm-subagents/src/slash/prompt-workflows.js +35 -73
  237. package/extensions/dm-subagents/src/slash/selector.js +101 -0
  238. package/extensions/dm-subagents/src/slash/slash-bridge.js +17 -1
  239. package/extensions/dm-subagents/src/slash/slash-commands.js +722 -732
  240. package/extensions/dm-subagents/src/slash/slash-live-state.js +37 -19
  241. package/extensions/dm-subagents/src/slash/subagents-admin.js +410 -0
  242. package/extensions/dm-subagents/src/tui/fleet-status.js +824 -0
  243. package/extensions/dm-subagents/src/tui/fleet-transcript.js +479 -0
  244. package/extensions/dm-subagents/src/tui/fleet.js +1326 -0
  245. package/extensions/dm-subagents/src/tui/render-helpers.js +22 -0
  246. package/extensions/dm-subagents/src/tui/render.js +1511 -261
  247. package/extensions/dm-subagents/src/watchdog/change-signature.js +220 -0
  248. package/extensions/dm-subagents/src/watchdog/child-status.js +151 -0
  249. package/extensions/dm-subagents/src/watchdog/emission-guard.js +90 -0
  250. package/extensions/dm-subagents/src/watchdog/lsp-diagnostics.js +484 -0
  251. package/extensions/dm-subagents/src/watchdog/model-selection.js +154 -0
  252. package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +138 -0
  253. package/extensions/dm-subagents/src/watchdog/register-child.js +112 -0
  254. package/extensions/dm-subagents/src/watchdog/register-main.js +419 -0
  255. package/extensions/dm-subagents/src/watchdog/render.js +54 -0
  256. package/extensions/dm-subagents/src/watchdog/review.js +251 -0
  257. package/extensions/dm-subagents/src/watchdog/runtime.js +803 -0
  258. package/extensions/dm-subagents/src/watchdog/scope.js +56 -0
  259. package/extensions/dm-subagents/src/watchdog/settings.js +515 -0
  260. package/extensions/dm-subagents/src/watchdog/tool-actions.js +151 -0
  261. package/extensions/dm-subagents/src/watchdog/turn-delta.js +169 -0
  262. package/extensions/dm-subagents/src/watchdog/types.js +29 -0
  263. package/extensions/dm-subagents/src/watchdog/warning-format.js +58 -0
  264. package/extensions/dm-subagents/src/workflows/chat-progress.js +116 -0
  265. package/extensions/dm-subagents/src/workflows/host-command.js +227 -0
  266. package/extensions/dm-subagents/src/workflows/scripted-workflow.js +2011 -0
  267. package/extensions/dm-subagents/src/workflows/workflow-child-summary.js +116 -0
  268. package/extensions/dm-subagents/src/workflows/workflow-preflight.js +243 -0
  269. package/extensions/dm-subagents/src/workflows/workflow-receipt.js +387 -0
  270. package/extensions/dm-subagents/src/workflows/workflow-settlement.js +189 -0
  271. package/extensions/greedysearch-dm/bin/cdp.mjs +28 -3
  272. package/extensions/greedysearch-dm/bin/launch.mjs +2 -3
  273. package/extensions/greedysearch-dm/src/search/constants.mjs +5 -2
  274. package/package.json +4 -3
  275. package/extensions/dm-fff/package.json +0 -21
  276. package/extensions/dm-fff/src/index.js +0 -691
  277. package/extensions/dm-fff/src/query.js +0 -60
  278. package/extensions/dm-subagents/agents/context-builder.md +0 -46
  279. package/extensions/dm-subagents/agents/planner.md +0 -55
  280. package/extensions/dm-subagents/prompts/parallel-context-build.md +0 -55
  281. package/extensions/dm-subagents/prompts/parallel-handoff-plan.md +0 -61
  282. package/extensions/dm-subagents/src/runs/background/wait.js +0 -206
  283. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +0 -1013
  284. package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +0 -981
  285. package/extensions/dm-subagents/src/runs/shared/turn-budget.js +0 -50
@@ -1,981 +0,0 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import { ChainClarifyComponent } from "./chain-clarify.js";
4
- import { toModelInfo } from "../../shared/model-info.js";
5
- import {
6
- resolveChainTemplates,
7
- createChainDir,
8
- removeChainDir,
9
- resolveStepBehavior,
10
- resolveParallelBehaviors,
11
- buildChainInstructions,
12
- writeInitialProgressFile,
13
- createParallelDirs,
14
- suppressProgressForReadOnlyTask,
15
- aggregateParallelOutputs,
16
- isDynamicParallelStep,
17
- isParallelStep
18
- } from "../../shared/settings.js";
19
- import { discoverAvailableSkills, normalizeSkillInput } from "../../agents/skills.js";
20
- import { INTERCOM_BRIDGE_MARKER } from "../../intercom/intercom-bridge.js";
21
- import { runSync } from "./execution.js";
22
- import { buildChainSummary } from "../../shared/formatters.js";
23
- import { compactForegroundDetails, getSingleResultOutput, mapConcurrent, resolveChildCwd, sumResultsCost, sumResultsUsage } from "../../shared/utils.js";
24
- import { DEFAULT_GLOBAL_CONCURRENCY_LIMIT, Semaphore } from "../shared/parallel-utils.js";
25
- import { recordRun } from "../shared/run-history.js";
26
- import {
27
- cleanupWorktrees,
28
- createWorktrees,
29
- diffWorktrees,
30
- findWorktreeTaskCwdConflict,
31
- formatWorktreeDiffSummary,
32
- formatWorktreeTaskCwdConflict
33
- } from "../shared/worktree.js";
34
- import {
35
- MAX_CONCURRENCY,
36
- resolveChildMaxSubagentDepth
37
- } from "../../shared/types.js";
38
- import { resolveSubagentModelOverride } from "../shared/model-fallback.js";
39
- import { validateFileOnlyOutputMode } from "../shared/single-output.js";
40
- import { buildWorkflowGraphSnapshot } from "../shared/workflow-graph.js";
41
- import { ChainOutputValidationError, outputEntryFromResult, resolveOutputReferences, validateChainOutputBindings } from "../shared/chain-outputs.js";
42
- import { createStructuredOutputRuntime } from "../shared/structured-output.js";
43
- import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.js";
44
- import { acceptanceFailureMessage, aggregateAcceptanceReport, evaluateAcceptance, resolveEffectiveAcceptance } from "../shared/acceptance.js";
45
- import { validateToolBudgetConfig } from "../shared/tool-budget.js";
46
- function buildChainExecutionDetails(input) {
47
- return compactForegroundDetails({
48
- mode: "chain",
49
- results: input.results,
50
- progress: input.includeProgress ? input.allProgress : undefined,
51
- artifacts: input.allArtifactPaths.length ? { dir: input.artifactsDir, files: input.allArtifactPaths } : undefined,
52
- chainAgents: input.chainAgents,
53
- totalSteps: input.totalSteps,
54
- currentStepIndex: input.currentStepIndex,
55
- outputs: input.outputs,
56
- totalChildUsage: sumResultsUsage(input.results),
57
- totalCost: sumResultsCost(input.results),
58
- workflowGraph: buildWorkflowGraphSnapshot({
59
- runId: input.runId,
60
- mode: "chain",
61
- steps: input.chainSteps,
62
- results: input.results,
63
- currentStepIndex: input.currentStepIndex,
64
- currentFlatIndex: input.currentFlatIndex,
65
- dynamicChildren: input.dynamicChildren,
66
- dynamicGroupStatuses: input.dynamicGroupStatuses
67
- })
68
- });
69
- }
70
- function buildChainExecutionErrorResult(message, input) {
71
- return {
72
- content: [{ type: "text", text: message }],
73
- isError: true,
74
- details: buildChainExecutionDetails(input)
75
- };
76
- }
77
- function ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors) {
78
- if (progressCreated || !parallelBehaviors.some((behavior) => behavior.progress)) {
79
- return progressCreated;
80
- }
81
- writeInitialProgressFile(chainDir);
82
- return true;
83
- }
84
- function appendParallelWorktreeSummary(output, worktreeSetup, diffsDir, agents) {
85
- if (!worktreeSetup)
86
- return output;
87
- const diffs = diffWorktrees(worktreeSetup, agents, diffsDir);
88
- const diffSummary = formatWorktreeDiffSummary(diffs);
89
- if (!diffSummary)
90
- return output;
91
- return `${output}
92
-
93
- ${diffSummary}`;
94
- }
95
- function resolveChainToolBudget(input) {
96
- if (input.stepBudget !== undefined) {
97
- const resolved = validateToolBudgetConfig(input.stepBudget, "toolBudget");
98
- return { toolBudget: resolved.budget, error: resolved.error };
99
- }
100
- if (input.runBudget !== undefined)
101
- return { toolBudget: input.runBudget };
102
- if (input.agentBudget !== undefined) {
103
- const resolved = validateToolBudgetConfig(input.agentBudget, "agent.toolBudget");
104
- return { toolBudget: resolved.budget, error: resolved.error };
105
- }
106
- const resolved = validateToolBudgetConfig(input.configBudget, "config.toolBudget");
107
- return { toolBudget: resolved.budget, error: resolved.error };
108
- }
109
- async function runParallelChainTasks(input) {
110
- const concurrency = input.step.concurrency ?? MAX_CONCURRENCY;
111
- const failFast = input.step.failFast ?? false;
112
- let aborted = false;
113
- const parallelResults = await mapConcurrent(input.step.parallel, concurrency, async (task, taskIndex) => {
114
- if (aborted && failFast) {
115
- return {
116
- agent: task.agent,
117
- task: "(skipped)",
118
- exitCode: -1,
119
- messages: [],
120
- usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 },
121
- error: "Skipped due to fail-fast"
122
- };
123
- }
124
- const taskTemplate = input.parallelTemplates[taskIndex] ?? "{previous}";
125
- const behavior = suppressProgressForReadOnlyTask(input.parallelBehaviors[taskIndex], taskTemplate, input.originalTask);
126
- const templateHasPrevious = taskTemplate.includes("{previous}");
127
- const { prefix, suffix } = buildChainInstructions(behavior, input.chainDir, false, templateHasPrevious ? undefined : input.prev);
128
- let taskStr = resolveOutputReferences(taskTemplate, input.outputs);
129
- taskStr = taskStr.replace(/\{task\}/g, input.originalTask);
130
- taskStr = taskStr.replace(/\{previous\}/g, input.prev);
131
- taskStr = taskStr.replace(/\{chain_dir\}/g, input.chainDir);
132
- const cleanTask = taskStr;
133
- taskStr = prefix + taskStr + suffix;
134
- const taskAgentConfig = input.agents.find((agent) => agent.name === task.agent);
135
- const effectiveModel = resolveSubagentModelOverride(task.model ?? taskAgentConfig?.model, input.ctx.model, input.availableModels, input.ctx.model?.provider, { scope: input.modelScope, source: task.model ? "explicit" : "inherited" });
136
- const maxSubagentDepth = resolveChildMaxSubagentDepth(input.maxSubagentDepth, taskAgentConfig?.maxSubagentDepth);
137
- const toolBudget = resolveChainToolBudget({ stepBudget: task.toolBudget, runBudget: input.toolBudget, agentBudget: taskAgentConfig?.toolBudget, configBudget: input.configToolBudget });
138
- if (toolBudget.error)
139
- throw new Error(toolBudget.error);
140
- const taskCwd = input.worktreeSetup ? input.worktreeSetup.worktrees[taskIndex].agentCwd : resolveChildCwd(input.cwd ?? input.ctx.cwd, task.cwd);
141
- const outputPath = typeof behavior.output === "string" ? path.isAbsolute(behavior.output) ? behavior.output : path.join(input.chainDir, behavior.output) : undefined;
142
- const interruptController = new AbortController;
143
- if (input.foregroundControl) {
144
- input.foregroundControl.currentAgent = task.agent;
145
- input.foregroundControl.currentIndex = input.globalTaskIndex + taskIndex;
146
- input.foregroundControl.currentActivityState = undefined;
147
- input.foregroundControl.updatedAt = Date.now();
148
- input.foregroundControl.interrupt = () => {
149
- if (interruptController.signal.aborted)
150
- return false;
151
- interruptController.abort();
152
- input.foregroundControl.currentActivityState = undefined;
153
- input.foregroundControl.updatedAt = Date.now();
154
- return true;
155
- };
156
- }
157
- const structuredRuntime = task.outputSchema ? createStructuredOutputRuntime(task.outputSchema, path.join(input.chainDir, "structured-output")) : undefined;
158
- const result = await runSync(input.ctx.cwd, input.agents, task.agent, taskStr, {
159
- parentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,
160
- cwd: taskCwd,
161
- signal: input.signal,
162
- interruptSignal: interruptController.signal,
163
- allowIntercomDetach: taskAgentConfig?.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,
164
- intercomEvents: input.intercomEvents,
165
- runId: input.runId,
166
- index: input.globalTaskIndex + taskIndex,
167
- sessionDir: input.sessionDirForIndex(input.globalTaskIndex + taskIndex),
168
- sessionFile: input.sessionFileForTask?.(task.agent, input.globalTaskIndex + taskIndex) ?? input.sessionFileForIndex?.(input.globalTaskIndex + taskIndex),
169
- thinkingOverride: input.thinkingOverrideForTask?.(task.agent, input.globalTaskIndex + taskIndex),
170
- share: input.shareEnabled,
171
- artifactsDir: input.artifactConfig.enabled ? input.artifactsDir : undefined,
172
- artifactConfig: input.artifactConfig,
173
- outputPath,
174
- outputMode: behavior.outputMode,
175
- maxSubagentDepth,
176
- controlConfig: input.controlConfig,
177
- onControlEvent: input.onControlEvent,
178
- intercomSessionName: input.childIntercomTarget?.(task.agent, input.globalTaskIndex + taskIndex),
179
- orchestratorIntercomTarget: input.orchestratorIntercomTarget,
180
- nestedRoute: input.nestedRoute,
181
- modelOverride: effectiveModel,
182
- availableModels: input.availableModels,
183
- preferredModelProvider: input.ctx.model?.provider,
184
- modelScope: input.modelScope,
185
- skills: behavior.skills === false ? [] : behavior.skills,
186
- structuredOutput: structuredRuntime,
187
- acceptance: task.acceptance,
188
- acceptanceContext: { mode: "chain" },
189
- timeoutMs: input.timeoutMs,
190
- deadlineAt: input.deadlineAt,
191
- turnBudget: input.turnBudget,
192
- onDetachedExit: input.onDetachedExit ? (result) => input.onDetachedExit?.(input.globalTaskIndex + taskIndex, result) : undefined,
193
- toolBudget: toolBudget.toolBudget,
194
- onUpdate: input.onUpdate ? (progressUpdate) => {
195
- const stepResults = progressUpdate.details?.results || [];
196
- const stepProgress = progressUpdate.details?.progress || [];
197
- if (input.foregroundControl && stepProgress.length > 0) {
198
- const current = stepProgress[0];
199
- input.foregroundControl.currentAgent = task.agent;
200
- input.foregroundControl.currentIndex = input.globalTaskIndex + taskIndex;
201
- input.foregroundControl.currentActivityState = current?.activityState;
202
- input.foregroundControl.lastActivityAt = current?.lastActivityAt;
203
- input.foregroundControl.currentTool = current?.currentTool;
204
- input.foregroundControl.currentToolStartedAt = current?.currentToolStartedAt;
205
- input.foregroundControl.currentPath = current?.currentPath;
206
- input.foregroundControl.turnCount = current?.turnCount;
207
- input.foregroundControl.tokens = current?.tokens;
208
- input.foregroundControl.toolCount = current?.toolCount;
209
- input.foregroundControl.updatedAt = Date.now();
210
- }
211
- input.onUpdate?.({
212
- ...progressUpdate,
213
- details: {
214
- mode: "chain",
215
- results: input.results.concat(stepResults),
216
- progress: input.allProgress.concat(stepProgress),
217
- controlEvents: progressUpdate.details?.controlEvents,
218
- chainAgents: input.chainAgents,
219
- totalSteps: input.totalSteps,
220
- currentStepIndex: input.stepIndex,
221
- outputs: input.outputs,
222
- workflowGraph: buildWorkflowGraphSnapshot({
223
- runId: input.runId,
224
- mode: "chain",
225
- steps: input.chainSteps,
226
- results: input.results.concat(stepResults),
227
- currentStepIndex: input.stepIndex,
228
- currentFlatIndex: input.globalTaskIndex + taskIndex,
229
- dynamicChildren: input.dynamicChildren,
230
- dynamicGroupStatuses: input.dynamicGroupStatuses
231
- })
232
- }
233
- });
234
- } : undefined
235
- });
236
- if (input.foregroundControl?.currentIndex === input.globalTaskIndex + taskIndex) {
237
- input.foregroundControl.interrupt = undefined;
238
- input.foregroundControl.updatedAt = Date.now();
239
- }
240
- if (result.exitCode !== 0 && failFast) {
241
- aborted = true;
242
- }
243
- recordRun(task.agent, cleanTask, result.exitCode, result.progressSummary?.durationMs ?? 0);
244
- return result;
245
- }, input.globalSemaphore);
246
- return parallelResults;
247
- }
248
- export async function executeChain(params) {
249
- const {
250
- chain: chainSteps,
251
- agents,
252
- ctx,
253
- signal,
254
- runId,
255
- cwd,
256
- shareEnabled,
257
- sessionDirForIndex,
258
- sessionFileForIndex,
259
- sessionFileForTask,
260
- thinkingOverrideForTask,
261
- artifactsDir,
262
- artifactConfig,
263
- includeProgress,
264
- clarify,
265
- onUpdate,
266
- onControlEvent,
267
- controlConfig,
268
- onDetachedExit,
269
- childIntercomTarget,
270
- orchestratorIntercomTarget,
271
- foregroundControl,
272
- intercomEvents,
273
- chainSkills: chainSkillsParam,
274
- chainDir: chainDirBase,
275
- modelScope
276
- } = params;
277
- const chainSkills = chainSkillsParam ?? [];
278
- const results = [];
279
- const outputs = {};
280
- const dynamicChildren = {};
281
- const dynamicGroupStatuses = {};
282
- const allProgress = [];
283
- const allArtifactPaths = [];
284
- const chainAgents = chainSteps.map((step) => isParallelStep(step) ? `[${step.parallel.map((t) => t.agent).join("+")}]` : isDynamicParallelStep(step) ? `expand:${step.parallel.agent}` : step.agent);
285
- const totalSteps = chainSteps.length;
286
- const makeDetailsInput = (overrides = {}) => ({
287
- results,
288
- ...includeProgress !== undefined ? { includeProgress } : {},
289
- allProgress,
290
- allArtifactPaths,
291
- artifactsDir,
292
- chainAgents,
293
- chainSteps,
294
- totalSteps,
295
- runId,
296
- outputs,
297
- dynamicChildren,
298
- dynamicGroupStatuses,
299
- ...overrides
300
- });
301
- const firstStep = chainSteps[0];
302
- const originalTask = params.task ?? (isParallelStep(firstStep) ? firstStep.parallel[0].task : isDynamicParallelStep(firstStep) ? firstStep.parallel.task : firstStep.task);
303
- try {
304
- validateChainOutputBindings(chainSteps, { maxItems: params.dynamicFanoutMaxItems });
305
- } catch (error) {
306
- if (error instanceof ChainOutputValidationError) {
307
- return {
308
- content: [{ type: "text", text: error.message }],
309
- isError: true,
310
- details: buildChainExecutionDetails(makeDetailsInput())
311
- };
312
- }
313
- throw error;
314
- }
315
- const chainDir = createChainDir(runId, chainDirBase);
316
- const hasParallelSteps = chainSteps.some((step) => isParallelStep(step) || isDynamicParallelStep(step));
317
- let templates = resolveChainTemplates(chainSteps);
318
- const shouldClarify = clarify === true && ctx.hasUI && !hasParallelSteps;
319
- let tuiBehaviorOverrides;
320
- const availableModels = ctx.modelRegistry.getAvailable().map(toModelInfo);
321
- const availableSkills = discoverAvailableSkills(cwd ?? ctx.cwd);
322
- if (shouldClarify) {
323
- const seqSteps = chainSteps;
324
- const agentConfigs = [];
325
- for (const step of seqSteps) {
326
- const config = agents.find((a) => a.name === step.agent);
327
- if (!config) {
328
- removeChainDir(chainDir);
329
- return {
330
- content: [{ type: "text", text: `Unknown agent: ${step.agent}` }],
331
- isError: true,
332
- details: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: seqSteps.indexOf(step) }))
333
- };
334
- }
335
- agentConfigs.push(config);
336
- }
337
- const stepOverrides = seqSteps.map((step) => ({
338
- output: step.output,
339
- outputMode: step.outputMode,
340
- reads: step.reads,
341
- progress: step.progress,
342
- skills: normalizeSkillInput(step.skill),
343
- model: step.model
344
- }));
345
- const resolvedBehaviors = agentConfigs.map((config, i) => resolveStepBehavior(config, stepOverrides[i], chainSkills));
346
- const flatTemplates = templates;
347
- const result = await ctx.ui.custom((tui, theme, _kb, done) => new ChainClarifyComponent(tui, theme, agentConfigs, flatTemplates, originalTask, chainDir, resolvedBehaviors, availableModels, ctx.model?.provider, availableSkills, done), {
348
- overlay: true,
349
- overlayOptions: { anchor: "center", width: 84, maxHeight: "80%" }
350
- });
351
- if (!result || !result.confirmed) {
352
- removeChainDir(chainDir);
353
- return {
354
- content: [{ type: "text", text: "Chain cancelled" }],
355
- details: buildChainExecutionDetails(makeDetailsInput())
356
- };
357
- }
358
- if (result.runInBackground) {
359
- removeChainDir(chainDir);
360
- const updatedChain = chainSteps.map((step, i) => {
361
- if (isParallelStep(step))
362
- return step;
363
- const override = result.behaviorOverrides[i];
364
- return {
365
- ...step,
366
- task: result.templates[i],
367
- ...override?.model ? { model: override.model } : {},
368
- ...override?.output !== undefined ? { output: override.output } : {},
369
- ..."outputMode" in step && step.outputMode !== undefined ? { outputMode: step.outputMode } : {},
370
- ...override?.reads !== undefined ? { reads: override.reads } : {},
371
- ...override?.progress !== undefined ? { progress: override.progress } : {},
372
- ...override?.skills !== undefined ? { skill: override.skills } : {}
373
- };
374
- });
375
- return {
376
- content: [{ type: "text", text: "Launching in background..." }],
377
- details: buildChainExecutionDetails(makeDetailsInput()),
378
- requestedAsync: { chain: updatedChain, chainSkills }
379
- };
380
- }
381
- templates = result.templates;
382
- tuiBehaviorOverrides = result.behaviorOverrides;
383
- }
384
- const deadlineAt = params.deadlineAt ?? (params.timeoutMs !== undefined ? Date.now() + params.timeoutMs : undefined);
385
- const globalSemaphore = new Semaphore(params.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT);
386
- let prev = "";
387
- let globalTaskIndex = 0;
388
- let progressCreated = false;
389
- for (let stepIndex = 0;stepIndex < chainSteps.length; stepIndex++) {
390
- const step = chainSteps[stepIndex];
391
- const stepTemplates = templates[stepIndex];
392
- if (isParallelStep(step)) {
393
- const parallelTemplates = stepTemplates;
394
- const parallelCwd = resolveChildCwd(cwd ?? ctx.cwd, step.cwd);
395
- let worktreeSetup;
396
- if (step.worktree) {
397
- const worktreeTaskCwdConflict = findWorktreeTaskCwdConflict(step.parallel, parallelCwd);
398
- if (worktreeTaskCwdConflict) {
399
- return buildChainExecutionErrorResult(`parallel chain step ${stepIndex + 1}: ${formatWorktreeTaskCwdConflict(worktreeTaskCwdConflict, parallelCwd)}`, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));
400
- }
401
- try {
402
- worktreeSetup = createWorktrees(parallelCwd, `${runId}-s${stepIndex}`, step.parallel.length, {
403
- agents: step.parallel.map((task) => task.agent),
404
- setupHook: params.worktreeSetupHook ? { hookPath: params.worktreeSetupHook, timeoutMs: params.worktreeSetupHookTimeoutMs } : undefined,
405
- baseDir: params.worktreeBaseDir
406
- });
407
- } catch (error) {
408
- const message = error instanceof Error ? error.message : String(error);
409
- return buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));
410
- }
411
- }
412
- try {
413
- const agentNames = step.parallel.map((task) => task.agent);
414
- const parallelBehaviors = resolveParallelBehaviors(step.parallel, agents, stepIndex, chainSkills).map((behavior, taskIndex) => suppressProgressForReadOnlyTask(behavior, parallelTemplates[taskIndex] ?? step.parallel[taskIndex]?.task, originalTask));
415
- for (let taskIndex = 0;taskIndex < step.parallel.length; taskIndex++) {
416
- const behavior = parallelBehaviors[taskIndex];
417
- const outputPath = typeof behavior.output === "string" ? path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output) : undefined;
418
- const validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Parallel chain step ${stepIndex + 1} task ${taskIndex + 1} (${step.parallel[taskIndex].agent})`);
419
- if (validationError)
420
- return buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }));
421
- }
422
- progressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);
423
- createParallelDirs(chainDir, stepIndex, step.parallel.length, agentNames);
424
- const parallelResults = await runParallelChainTasks({
425
- step,
426
- parallelTemplates,
427
- parallelBehaviors,
428
- agents,
429
- stepIndex,
430
- availableModels,
431
- modelScope,
432
- chainDir,
433
- prev,
434
- originalTask,
435
- ctx,
436
- intercomEvents,
437
- cwd,
438
- runId,
439
- globalTaskIndex,
440
- sessionDirForIndex,
441
- sessionFileForIndex,
442
- sessionFileForTask,
443
- thinkingOverrideForTask,
444
- shareEnabled,
445
- artifactConfig,
446
- artifactsDir,
447
- signal,
448
- onUpdate,
449
- results,
450
- allProgress,
451
- outputs,
452
- chainAgents,
453
- chainSteps,
454
- totalSteps,
455
- dynamicChildren,
456
- dynamicGroupStatuses,
457
- controlConfig,
458
- onControlEvent,
459
- childIntercomTarget,
460
- orchestratorIntercomTarget,
461
- foregroundControl,
462
- nestedRoute: params.nestedRoute,
463
- worktreeSetup,
464
- maxSubagentDepth: params.maxSubagentDepth,
465
- timeoutMs: params.timeoutMs,
466
- deadlineAt,
467
- turnBudget: params.turnBudget,
468
- onDetachedExit,
469
- toolBudget: params.toolBudget,
470
- configToolBudget: params.configToolBudget,
471
- globalSemaphore
472
- });
473
- globalTaskIndex += step.parallel.length;
474
- for (const result of parallelResults) {
475
- results.push(result);
476
- if (result.progress)
477
- allProgress.push(result.progress);
478
- if (result.artifactPaths)
479
- allArtifactPaths.push(result.artifactPaths);
480
- }
481
- const interruptedIndexInStep = parallelResults.findIndex((result) => result.interrupted);
482
- const interrupted = interruptedIndexInStep >= 0 ? parallelResults[interruptedIndexInStep] : undefined;
483
- if (interrupted) {
484
- return {
485
- content: [{ type: "text", text: `Chain paused after interrupt at step ${stepIndex + 1} (${interrupted.agent}). Waiting for explicit next action.` }],
486
- details: buildChainExecutionDetails(makeDetailsInput({
487
- currentStepIndex: stepIndex,
488
- currentFlatIndex: globalTaskIndex - step.parallel.length + interruptedIndexInStep
489
- }))
490
- };
491
- }
492
- const detachedIndexInStep = parallelResults.findIndex((result) => result.detached);
493
- const detached = detachedIndexInStep >= 0 ? parallelResults[detachedIndexInStep] : undefined;
494
- if (detached) {
495
- return {
496
- content: [{ type: "text", text: `Chain detached for intercom coordination at step ${stepIndex + 1} (${detached.agent}). Reply to the supervisor request first. After the child exits, start a fresh follow-up if needed.` }],
497
- details: buildChainExecutionDetails(makeDetailsInput({
498
- currentStepIndex: stepIndex,
499
- currentFlatIndex: globalTaskIndex - step.parallel.length + detachedIndexInStep
500
- }))
501
- };
502
- }
503
- const failures = parallelResults.map((result, originalIndex) => ({ ...result, originalIndex })).filter((result) => result.exitCode !== 0 && result.exitCode !== -1);
504
- if (failures.length > 0) {
505
- const failureSummary = failures.map((failure) => `- Task ${failure.originalIndex + 1} (${failure.agent}): ${failure.error || "failed"}`).join(`
506
- `);
507
- const errorMsg = `Parallel step ${stepIndex + 1} failed:
508
- ${failureSummary}`;
509
- const summary = buildChainSummary(chainSteps, results, chainDir, "failed", {
510
- index: stepIndex,
511
- error: errorMsg
512
- });
513
- return {
514
- content: [{ type: "text", text: summary }],
515
- isError: true,
516
- details: buildChainExecutionDetails(makeDetailsInput({
517
- currentStepIndex: stepIndex,
518
- currentFlatIndex: globalTaskIndex - step.parallel.length + failures[0].originalIndex
519
- }))
520
- };
521
- }
522
- for (let taskIndex = 0;taskIndex < parallelResults.length; taskIndex++) {
523
- const outputName = step.parallel[taskIndex]?.as;
524
- if (outputName)
525
- outputs[outputName] = outputEntryFromResult(parallelResults[taskIndex], stepIndex);
526
- }
527
- const taskResults = parallelResults.map((result, i) => {
528
- const outputTarget = parallelBehaviors[i]?.output;
529
- const outputTargetPath = typeof outputTarget === "string" ? path.isAbsolute(outputTarget) ? outputTarget : path.join(chainDir, outputTarget) : undefined;
530
- return {
531
- agent: result.agent,
532
- taskIndex: i,
533
- output: getSingleResultOutput(result),
534
- exitCode: result.exitCode,
535
- error: result.error,
536
- timedOut: result.timedOut,
537
- outputTargetPath,
538
- outputTargetExists: outputTargetPath ? fs.existsSync(outputTargetPath) : undefined
539
- };
540
- });
541
- prev = aggregateParallelOutputs(taskResults);
542
- prev = appendParallelWorktreeSummary(prev, worktreeSetup, path.join(chainDir, "worktree-diffs", `step-${stepIndex}`), agentNames);
543
- } finally {
544
- if (worktreeSetup)
545
- cleanupWorktrees(worktreeSetup);
546
- }
547
- } else if (isDynamicParallelStep(step)) {
548
- const dynamicStartIndex = globalTaskIndex;
549
- const reservedDynamicItems = step.expand.maxItems ?? params.dynamicFanoutMaxItems ?? 0;
550
- let materialized;
551
- try {
552
- materialized = materializeDynamicParallelStep(step, outputs, stepIndex, { maxItems: params.dynamicFanoutMaxItems });
553
- } catch (error) {
554
- const message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);
555
- dynamicGroupStatuses[stepIndex] = { status: "failed", error: message };
556
- return buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));
557
- }
558
- dynamicChildren[stepIndex] = materialized.items.map((item, itemIndex) => ({
559
- agent: step.parallel.agent,
560
- label: materialized.parallel[itemIndex]?.label,
561
- flatIndex: globalTaskIndex + itemIndex,
562
- itemKey: item.key,
563
- structured: Boolean(step.parallel.outputSchema)
564
- }));
565
- if (materialized.parallel.length === 0) {
566
- const collection = [];
567
- try {
568
- validateDynamicCollection(step.collect.outputSchema, collection);
569
- } catch (error) {
570
- const message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);
571
- dynamicGroupStatuses[stepIndex] = { status: "failed", error: message };
572
- return buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));
573
- }
574
- outputs[step.collect.as] = {
575
- text: JSON.stringify(collection),
576
- structured: collection,
577
- agent: step.parallel.agent,
578
- stepIndex
579
- };
580
- dynamicGroupStatuses[stepIndex] = { status: "completed" };
581
- if (step.acceptance !== undefined) {
582
- const effectiveGroupAcceptance = resolveEffectiveAcceptance({
583
- explicit: step.acceptance,
584
- agentName: step.parallel.agent,
585
- task: step.parallel.task ?? originalTask,
586
- mode: "chain",
587
- dynamicGroup: true
588
- });
589
- const groupAcceptance = await evaluateAcceptance({
590
- acceptance: effectiveGroupAcceptance,
591
- output: "",
592
- report: aggregateAcceptanceReport({
593
- results: [],
594
- notes: "Dynamic fanout produced 0 results."
595
- }),
596
- cwd: cwd ?? ctx.cwd
597
- });
598
- dynamicGroupStatuses[stepIndex].acceptance = groupAcceptance;
599
- const groupAcceptanceFailure = acceptanceFailureMessage(groupAcceptance);
600
- if (groupAcceptanceFailure) {
601
- dynamicGroupStatuses[stepIndex] = { status: "failed", error: groupAcceptanceFailure, acceptance: groupAcceptance };
602
- return buildChainExecutionErrorResult(groupAcceptanceFailure, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));
603
- }
604
- }
605
- prev = "Dynamic fanout produced 0 results.";
606
- globalTaskIndex = dynamicStartIndex + reservedDynamicItems;
607
- continue;
608
- }
609
- const dynamicParallelStep = {
610
- parallel: materialized.parallel,
611
- concurrency: step.concurrency,
612
- failFast: step.failFast
613
- };
614
- const parallelTemplates = materialized.parallel.map((task) => task.task ?? "{previous}");
615
- const parallelBehaviors = resolveParallelBehaviors(dynamicParallelStep.parallel, agents, stepIndex, chainSkills).map((behavior, taskIndex) => suppressProgressForReadOnlyTask(behavior, parallelTemplates[taskIndex] ?? dynamicParallelStep.parallel[taskIndex]?.task, originalTask));
616
- for (let taskIndex = 0;taskIndex < dynamicParallelStep.parallel.length; taskIndex++) {
617
- const behavior = parallelBehaviors[taskIndex];
618
- const outputPath = typeof behavior.output === "string" ? path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output) : undefined;
619
- const validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Dynamic chain step ${stepIndex + 1} item ${taskIndex + 1} (${dynamicParallelStep.parallel[taskIndex].agent})`);
620
- if (validationError) {
621
- dynamicGroupStatuses[stepIndex] = { status: "failed", error: validationError };
622
- return buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }));
623
- }
624
- }
625
- progressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);
626
- createParallelDirs(chainDir, stepIndex, dynamicParallelStep.parallel.length, dynamicParallelStep.parallel.map((task) => task.agent));
627
- const parallelResults = await runParallelChainTasks({
628
- step: dynamicParallelStep,
629
- parallelTemplates,
630
- parallelBehaviors,
631
- agents,
632
- stepIndex,
633
- availableModels,
634
- modelScope,
635
- chainDir,
636
- prev,
637
- originalTask,
638
- ctx,
639
- intercomEvents,
640
- cwd,
641
- runId,
642
- globalTaskIndex,
643
- sessionDirForIndex,
644
- sessionFileForIndex,
645
- sessionFileForTask,
646
- thinkingOverrideForTask,
647
- shareEnabled,
648
- artifactConfig,
649
- artifactsDir,
650
- signal,
651
- onUpdate,
652
- results,
653
- allProgress,
654
- outputs,
655
- chainAgents,
656
- chainSteps,
657
- totalSteps,
658
- dynamicChildren,
659
- dynamicGroupStatuses,
660
- controlConfig,
661
- onControlEvent,
662
- childIntercomTarget,
663
- orchestratorIntercomTarget,
664
- foregroundControl,
665
- nestedRoute: params.nestedRoute,
666
- maxSubagentDepth: params.maxSubagentDepth,
667
- timeoutMs: params.timeoutMs,
668
- deadlineAt,
669
- turnBudget: params.turnBudget,
670
- onDetachedExit,
671
- toolBudget: params.toolBudget,
672
- configToolBudget: params.configToolBudget,
673
- globalSemaphore
674
- });
675
- globalTaskIndex = dynamicStartIndex + reservedDynamicItems;
676
- for (const result of parallelResults) {
677
- results.push(result);
678
- if (result.progress)
679
- allProgress.push(result.progress);
680
- if (result.artifactPaths)
681
- allArtifactPaths.push(result.artifactPaths);
682
- }
683
- const collected = collectDynamicResults(step, materialized.items, parallelResults);
684
- const interruptedIndexInStep = parallelResults.findIndex((result) => result.interrupted);
685
- const interrupted = interruptedIndexInStep >= 0 ? parallelResults[interruptedIndexInStep] : undefined;
686
- if (interrupted) {
687
- return {
688
- content: [{ type: "text", text: `Chain paused after interrupt at step ${stepIndex + 1} (${interrupted.agent}). Waiting for explicit next action.` }],
689
- details: buildChainExecutionDetails(makeDetailsInput({
690
- currentStepIndex: stepIndex,
691
- currentFlatIndex: dynamicStartIndex + interruptedIndexInStep
692
- }))
693
- };
694
- }
695
- const detachedIndexInStep = parallelResults.findIndex((result) => result.detached);
696
- const detached = detachedIndexInStep >= 0 ? parallelResults[detachedIndexInStep] : undefined;
697
- if (detached) {
698
- return {
699
- content: [{ type: "text", text: `Chain detached for intercom coordination at step ${stepIndex + 1} (${detached.agent}). Reply to the supervisor request first. After the child exits, start a fresh follow-up if needed.` }],
700
- details: buildChainExecutionDetails(makeDetailsInput({
701
- currentStepIndex: stepIndex,
702
- currentFlatIndex: dynamicStartIndex + detachedIndexInStep
703
- }))
704
- };
705
- }
706
- const failures = parallelResults.map((result, originalIndex) => ({ ...result, originalIndex })).filter((result) => result.exitCode !== 0 && result.exitCode !== -1);
707
- if (failures.length > 0) {
708
- const failureSummary = failures.map((failure) => `- Item ${failure.originalIndex + 1} (${failure.agent}, key ${materialized.items[failure.originalIndex]?.key ?? failure.originalIndex}): ${failure.error || "failed"}`).join(`
709
- `);
710
- const errorMsg = `Dynamic step ${stepIndex + 1} failed:
711
- ${failureSummary}`;
712
- dynamicGroupStatuses[stepIndex] = { status: "failed", error: errorMsg };
713
- const summary = buildChainSummary(chainSteps, results, chainDir, "failed", {
714
- index: stepIndex,
715
- error: errorMsg
716
- });
717
- return {
718
- content: [{ type: "text", text: summary }],
719
- isError: true,
720
- details: buildChainExecutionDetails(makeDetailsInput({
721
- currentStepIndex: stepIndex,
722
- currentFlatIndex: dynamicStartIndex + failures[0].originalIndex
723
- }))
724
- };
725
- }
726
- try {
727
- validateDynamicCollection(step.collect.outputSchema, collected);
728
- } catch (error) {
729
- const message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);
730
- dynamicGroupStatuses[stepIndex] = { status: "failed", error: message };
731
- return buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: dynamicStartIndex }));
732
- }
733
- outputs[step.collect.as] = {
734
- text: JSON.stringify(collected),
735
- structured: collected,
736
- agent: step.parallel.agent,
737
- stepIndex
738
- };
739
- dynamicGroupStatuses[stepIndex] = { status: "completed" };
740
- const effectiveGroupAcceptance = resolveEffectiveAcceptance({
741
- explicit: step.acceptance,
742
- agentName: step.parallel.agent,
743
- task: step.parallel.task ?? originalTask,
744
- mode: "chain",
745
- dynamicGroup: true
746
- });
747
- const groupAcceptance = await evaluateAcceptance({
748
- acceptance: effectiveGroupAcceptance,
749
- output: "",
750
- report: aggregateAcceptanceReport({
751
- results: parallelResults,
752
- notes: `Dynamic fanout collected ${collected.length} result(s) into ${step.collect.as}.`
753
- }),
754
- cwd: cwd ?? ctx.cwd
755
- });
756
- dynamicGroupStatuses[stepIndex].acceptance = groupAcceptance;
757
- const groupAcceptanceFailure = acceptanceFailureMessage(groupAcceptance);
758
- if (groupAcceptanceFailure) {
759
- dynamicGroupStatuses[stepIndex] = { status: "failed", error: groupAcceptanceFailure, acceptance: groupAcceptance };
760
- return buildChainExecutionErrorResult(groupAcceptanceFailure, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex - dynamicParallelStep.parallel.length }));
761
- }
762
- const taskResults = parallelResults.map((result, i) => ({
763
- agent: result.agent,
764
- taskIndex: i,
765
- output: getSingleResultOutput(result),
766
- exitCode: result.exitCode,
767
- error: result.error,
768
- timedOut: result.timedOut
769
- }));
770
- prev = aggregateParallelOutputs(taskResults, (i, agent) => `=== Dynamic Item ${i + 1} (${agent}, key ${materialized.items[i]?.key ?? i}) ===`);
771
- } else {
772
- const seqStep = step;
773
- const stepTemplate = stepTemplates;
774
- const agentConfig = agents.find((a) => a.name === seqStep.agent);
775
- if (!agentConfig) {
776
- removeChainDir(chainDir);
777
- return {
778
- content: [{ type: "text", text: `Unknown agent: ${seqStep.agent}` }],
779
- isError: true,
780
- details: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }))
781
- };
782
- }
783
- const tuiOverride = tuiBehaviorOverrides?.[stepIndex];
784
- const stepOverride = {
785
- output: tuiOverride?.output !== undefined ? tuiOverride.output : seqStep.output,
786
- outputMode: seqStep.outputMode,
787
- reads: tuiOverride?.reads !== undefined ? tuiOverride.reads : seqStep.reads,
788
- progress: tuiOverride?.progress !== undefined ? tuiOverride.progress : seqStep.progress,
789
- skills: tuiOverride?.skills !== undefined ? tuiOverride.skills : normalizeSkillInput(seqStep.skill)
790
- };
791
- const behavior = suppressProgressForReadOnlyTask(resolveStepBehavior(agentConfig, stepOverride, chainSkills), stepTemplate, originalTask);
792
- const isFirstProgress = behavior.progress && !progressCreated;
793
- if (isFirstProgress) {
794
- progressCreated = true;
795
- }
796
- const templateHasPrevious = stepTemplate.includes("{previous}");
797
- const { prefix, suffix } = buildChainInstructions(behavior, chainDir, isFirstProgress, templateHasPrevious ? undefined : prev);
798
- let stepTask = resolveOutputReferences(stepTemplate, outputs);
799
- stepTask = stepTask.replace(/\{task\}/g, originalTask);
800
- stepTask = stepTask.replace(/\{previous\}/g, prev);
801
- stepTask = stepTask.replace(/\{chain_dir\}/g, chainDir);
802
- const cleanTask = stepTask;
803
- stepTask = prefix + stepTask + suffix;
804
- const explicitStepModel = tuiOverride?.model ?? seqStep.model;
805
- const effectiveModel = resolveSubagentModelOverride(explicitStepModel ?? agentConfig.model, ctx.model, availableModels, ctx.model?.provider, { scope: modelScope, source: explicitStepModel ? "explicit" : "inherited" });
806
- const outputPath = typeof behavior.output === "string" ? path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output) : undefined;
807
- const validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Chain step ${stepIndex + 1} (${seqStep.agent})`);
808
- if (validationError) {
809
- return buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));
810
- }
811
- const maxSubagentDepth = resolveChildMaxSubagentDepth(params.maxSubagentDepth, agentConfig.maxSubagentDepth);
812
- const childIndex = globalTaskIndex;
813
- const interruptController = new AbortController;
814
- if (foregroundControl) {
815
- foregroundControl.currentAgent = seqStep.agent;
816
- foregroundControl.currentIndex = childIndex;
817
- foregroundControl.currentActivityState = undefined;
818
- foregroundControl.updatedAt = Date.now();
819
- foregroundControl.interrupt = () => {
820
- if (interruptController.signal.aborted)
821
- return false;
822
- interruptController.abort();
823
- foregroundControl.currentActivityState = undefined;
824
- foregroundControl.updatedAt = Date.now();
825
- return true;
826
- };
827
- }
828
- const structuredRuntime = seqStep.outputSchema ? createStructuredOutputRuntime(seqStep.outputSchema, path.join(chainDir, "structured-output")) : undefined;
829
- const toolBudget = resolveChainToolBudget({ stepBudget: seqStep.toolBudget, runBudget: params.toolBudget, agentBudget: agentConfig?.toolBudget, configBudget: params.configToolBudget });
830
- if (toolBudget.error)
831
- return buildChainExecutionErrorResult(toolBudget.error, {
832
- results,
833
- includeProgress,
834
- allProgress,
835
- allArtifactPaths,
836
- artifactsDir: params.artifactsDir,
837
- chainAgents,
838
- chainSteps,
839
- totalSteps,
840
- currentStepIndex: stepIndex,
841
- runId: params.runId,
842
- outputs,
843
- currentFlatIndex: globalTaskIndex,
844
- dynamicChildren,
845
- dynamicGroupStatuses
846
- });
847
- const r = await runSync(ctx.cwd, agents, seqStep.agent, stepTask, {
848
- parentSessionId: ctx.sessionManager.getSessionId() ?? undefined,
849
- cwd: resolveChildCwd(cwd ?? ctx.cwd, seqStep.cwd),
850
- signal,
851
- interruptSignal: interruptController.signal,
852
- allowIntercomDetach: agentConfig.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,
853
- intercomEvents,
854
- runId,
855
- index: childIndex,
856
- sessionDir: sessionDirForIndex(childIndex),
857
- sessionFile: sessionFileForTask?.(seqStep.agent, childIndex) ?? sessionFileForIndex?.(childIndex),
858
- thinkingOverride: thinkingOverrideForTask?.(seqStep.agent, childIndex),
859
- share: shareEnabled,
860
- artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
861
- artifactConfig,
862
- outputPath,
863
- outputMode: behavior.outputMode,
864
- maxSubagentDepth,
865
- controlConfig,
866
- onControlEvent,
867
- intercomSessionName: childIntercomTarget?.(seqStep.agent, childIndex),
868
- orchestratorIntercomTarget,
869
- nestedRoute: params.nestedRoute,
870
- modelOverride: effectiveModel,
871
- availableModels,
872
- preferredModelProvider: ctx.model?.provider,
873
- modelScope,
874
- skills: behavior.skills === false ? [] : behavior.skills,
875
- structuredOutput: structuredRuntime,
876
- acceptance: seqStep.acceptance,
877
- acceptanceContext: { mode: "chain" },
878
- timeoutMs: params.timeoutMs,
879
- deadlineAt,
880
- turnBudget: params.turnBudget,
881
- onDetachedExit: onDetachedExit ? (result) => onDetachedExit(childIndex, result) : undefined,
882
- toolBudget: toolBudget.toolBudget,
883
- onUpdate: onUpdate ? (p) => {
884
- const stepResults = p.details?.results || [];
885
- const stepProgress = p.details?.progress || [];
886
- if (foregroundControl && stepProgress.length > 0) {
887
- const current = stepProgress[0];
888
- foregroundControl.currentAgent = seqStep.agent;
889
- foregroundControl.currentIndex = childIndex;
890
- foregroundControl.currentActivityState = current?.activityState;
891
- foregroundControl.lastActivityAt = current?.lastActivityAt;
892
- foregroundControl.currentTool = current?.currentTool;
893
- foregroundControl.currentToolStartedAt = current?.currentToolStartedAt;
894
- foregroundControl.currentPath = current?.currentPath;
895
- foregroundControl.turnCount = current?.turnCount;
896
- foregroundControl.tokens = current?.tokens;
897
- foregroundControl.toolCount = current?.toolCount;
898
- foregroundControl.updatedAt = Date.now();
899
- }
900
- onUpdate({
901
- ...p,
902
- details: {
903
- mode: "chain",
904
- results: results.concat(stepResults),
905
- progress: allProgress.concat(stepProgress),
906
- controlEvents: p.details?.controlEvents,
907
- chainAgents,
908
- totalSteps,
909
- currentStepIndex: stepIndex,
910
- outputs,
911
- workflowGraph: buildWorkflowGraphSnapshot({
912
- runId,
913
- mode: "chain",
914
- steps: chainSteps,
915
- results: results.concat(stepResults),
916
- currentStepIndex: stepIndex,
917
- currentFlatIndex: childIndex,
918
- dynamicChildren,
919
- dynamicGroupStatuses
920
- })
921
- }
922
- });
923
- } : undefined
924
- });
925
- if (foregroundControl?.currentIndex === childIndex) {
926
- foregroundControl.interrupt = undefined;
927
- foregroundControl.updatedAt = Date.now();
928
- }
929
- recordRun(seqStep.agent, cleanTask, r.exitCode, r.progressSummary?.durationMs ?? 0);
930
- globalTaskIndex++;
931
- results.push(r);
932
- if (r.progress)
933
- allProgress.push(r.progress);
934
- if (r.artifactPaths)
935
- allArtifactPaths.push(r.artifactPaths);
936
- if (r.interrupted) {
937
- return {
938
- content: [{ type: "text", text: `Chain paused after interrupt at step ${stepIndex + 1} (${r.agent}). Waiting for explicit next action.` }],
939
- details: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex }))
940
- };
941
- }
942
- if (r.detached) {
943
- return {
944
- content: [{ type: "text", text: `Chain detached for intercom coordination at step ${stepIndex + 1} (${r.agent}). Reply to the supervisor request first. After the child exits, start a fresh follow-up if needed.` }],
945
- details: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex }))
946
- };
947
- }
948
- if (r.exitCode !== 0) {
949
- const summary = buildChainSummary(chainSteps, results, chainDir, "failed", {
950
- index: stepIndex,
951
- error: r.error || "Chain failed"
952
- });
953
- return {
954
- content: [{ type: "text", text: summary }],
955
- details: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex })),
956
- isError: true
957
- };
958
- }
959
- if (behavior.output) {
960
- try {
961
- const expectedPath = path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output);
962
- if (!fs.existsSync(expectedPath)) {
963
- const dirFiles = fs.readdirSync(chainDir);
964
- const mdFiles = dirFiles.filter((file) => file.endsWith(".md") && file !== "progress.md");
965
- const warning = mdFiles.length > 0 ? `Agent wrote to different file(s): ${mdFiles.join(", ")} instead of ${behavior.output}` : `Agent did not create expected output file: ${behavior.output}`;
966
- r.error = r.error ? `${r.error}
967
- ${warning}` : warning;
968
- }
969
- } catch {}
970
- }
971
- if (seqStep.as)
972
- outputs[seqStep.as] = outputEntryFromResult(r, stepIndex);
973
- prev = getSingleResultOutput(r);
974
- }
975
- }
976
- const summary = buildChainSummary(chainSteps, results, chainDir, "completed");
977
- return {
978
- content: [{ type: "text", text: summary }],
979
- details: buildChainExecutionDetails(makeDetailsInput())
980
- };
981
- }