@duckmind/dm-windows-x64 0.60.4 → 0.60.8

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 (197) hide show
  1. package/dm.exe +0 -0
  2. package/extensions/.dm-extensions.json +70 -123
  3. package/extensions/dm-9router-ext/src/index.js +410 -5
  4. package/extensions/dm-caveman/extensions/caveman.js +283 -12
  5. package/extensions/dm-cliproxy/index.js +182 -2
  6. package/extensions/dm-cliproxy/scripts/check-config-migration.js +66 -8
  7. package/extensions/dm-cliproxy/src/apply.js +228 -1
  8. package/extensions/dm-cliproxy/src/cache.js +42 -1
  9. package/extensions/dm-cliproxy/src/commands.js +50 -2
  10. package/extensions/dm-cliproxy/src/compat.js +81 -1
  11. package/extensions/dm-cliproxy/src/config.js +192 -2
  12. package/extensions/dm-cliproxy/src/conflicts.js +46 -1
  13. package/extensions/dm-cliproxy/src/fetch-models.js +190 -1
  14. package/extensions/dm-cliproxy/src/fetch-usage.js +41 -1
  15. package/extensions/dm-cliproxy/src/log.js +23 -1
  16. package/extensions/dm-cliproxy/src/status-quota.js +77 -1
  17. package/extensions/dm-cliproxy/src/ui-frame.js +50 -1
  18. package/extensions/dm-cliproxy/src/ui-hub/hub.js +199 -2
  19. package/extensions/dm-cliproxy/src/ui-hub/index.js +26 -2
  20. package/extensions/dm-cliproxy/src/ui-hub/shell.js +46 -1
  21. package/extensions/dm-cliproxy/src/ui-hub/view-diagnostics.js +69 -1
  22. package/extensions/dm-cliproxy/src/ui-hub/view-models.js +379 -1
  23. package/extensions/dm-cliproxy/src/ui-hub/view-usage.js +106 -1
  24. package/extensions/dm-cliproxy/src/ui-picker/catalog.js +41 -1
  25. package/extensions/dm-cliproxy/src/ui-picker/mutate.js +115 -1
  26. package/extensions/dm-cliproxy/src/ui-picker/prompt-confirm.js +35 -1
  27. package/extensions/dm-cliproxy/src/ui-picker/prompt-name.js +62 -1
  28. package/extensions/dm-cliproxy/src/ui-picker/providers.js +45 -1
  29. package/extensions/dm-cliproxy/src/ui-picker/render-text.js +34 -1
  30. package/extensions/dm-cliproxy/src/ui-picker/rows.js +57 -1
  31. package/extensions/dm-cliproxy/src/ui-setup.js +260 -2
  32. package/extensions/dm-cliproxy/src/ui-usage.js +151 -1
  33. package/extensions/dm-cliproxy/src/usage-shared-cache.js +97 -1
  34. package/extensions/dm-context/src/context.js +144 -1
  35. package/extensions/dm-context/src/index.js +339 -7
  36. package/extensions/dm-context/src/utils.js +9 -1
  37. package/extensions/dm-cua/bin/browser-cua.mjs +73 -8
  38. package/extensions/dm-cua/index.js +75 -6
  39. package/extensions/dm-cua/src/browser-cua-lib.mjs +490 -6
  40. package/extensions/dm-cua/src/browser-install.mjs +331 -2
  41. package/extensions/dm-fff/src/index.js +688 -12
  42. package/extensions/dm-fff/src/query.js +60 -1
  43. package/extensions/dm-goal/src/goal.js +894 -23
  44. package/extensions/dm-image2/index.js +103 -9
  45. package/extensions/dm-image2/src/image-lib.mjs +1275 -8
  46. package/extensions/dm-subagents/install.mjs +62 -8
  47. package/extensions/dm-subagents/src/agents/agent-management.js +1190 -36
  48. package/extensions/dm-subagents/src/agents/agent-memory.js +216 -6
  49. package/extensions/dm-subagents/src/agents/agent-scope.js +5 -1
  50. package/extensions/dm-subagents/src/agents/agent-selection.js +20 -1
  51. package/extensions/dm-subagents/src/agents/agent-serializer.js +120 -5
  52. package/extensions/dm-subagents/src/agents/agents.js +1139 -11
  53. package/extensions/dm-subagents/src/agents/chain-serializer.js +299 -11
  54. package/extensions/dm-subagents/src/agents/frontmatter.js +65 -6
  55. package/extensions/dm-subagents/src/agents/identity.js +29 -1
  56. package/extensions/dm-subagents/src/agents/proactive-skills.js +141 -1
  57. package/extensions/dm-subagents/src/agents/skills.js +614 -6
  58. package/extensions/dm-subagents/src/extension/config.js +35 -2
  59. package/extensions/dm-subagents/src/extension/control-notices.js +69 -4
  60. package/extensions/dm-subagents/src/extension/doctor.js +172 -15
  61. package/extensions/dm-subagents/src/extension/fanout-child.js +158 -231
  62. package/extensions/dm-subagents/src/extension/index.js +521 -359
  63. package/extensions/dm-subagents/src/extension/rpc.js +266 -7
  64. package/extensions/dm-subagents/src/extension/schemas.js +275 -1
  65. package/extensions/dm-subagents/src/extension/tool-description.js +111 -6
  66. package/extensions/dm-subagents/src/intercom/intercom-bridge.js +126 -4
  67. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +452 -5
  68. package/extensions/dm-subagents/src/intercom/result-intercom.js +319 -3
  69. package/extensions/dm-subagents/src/profiles/profiles.js +458 -3
  70. package/extensions/dm-subagents/src/runs/background/async-execution.js +834 -40
  71. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +435 -14
  72. package/extensions/dm-subagents/src/runs/background/async-resume.js +334 -8
  73. package/extensions/dm-subagents/src/runs/background/async-status.js +313 -12
  74. package/extensions/dm-subagents/src/runs/background/chain-append.js +245 -2
  75. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +136 -1
  76. package/extensions/dm-subagents/src/runs/background/completion-batcher.js +94 -1
  77. package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +54 -1
  78. package/extensions/dm-subagents/src/runs/background/control-channel.js +190 -1
  79. package/extensions/dm-subagents/src/runs/background/fleet-view.js +483 -17
  80. package/extensions/dm-subagents/src/runs/background/notify.js +129 -3
  81. package/extensions/dm-subagents/src/runs/background/parallel-groups.js +34 -1
  82. package/extensions/dm-subagents/src/runs/background/result-watcher.js +236 -6
  83. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +76 -4
  84. package/extensions/dm-subagents/src/runs/background/run-status.js +427 -23
  85. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +487 -4
  86. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +306 -9
  87. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +2849 -73
  88. package/extensions/dm-subagents/src/runs/background/top-level-async.js +5 -1
  89. package/extensions/dm-subagents/src/runs/background/wait.js +206 -11
  90. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +1013 -12
  91. package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +980 -101
  92. package/extensions/dm-subagents/src/runs/foreground/execution.js +1165 -45
  93. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +3157 -222
  94. package/extensions/dm-subagents/src/runs/shared/acceptance.js +835 -3
  95. package/extensions/dm-subagents/src/runs/shared/chain-outputs.js +104 -1
  96. package/extensions/dm-subagents/src/runs/shared/completion-guard.js +116 -3
  97. package/extensions/dm-subagents/src/runs/shared/dm-args.js +208 -1
  98. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +90 -1
  99. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +282 -1
  100. package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +148 -1
  101. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +305 -1
  102. package/extensions/dm-subagents/src/runs/shared/model-fallback.js +194 -1
  103. package/extensions/dm-subagents/src/runs/shared/model-scope.js +65 -1
  104. package/extensions/dm-subagents/src/runs/shared/nested-events.js +851 -8
  105. package/extensions/dm-subagents/src/runs/shared/nested-path.js +41 -1
  106. package/extensions/dm-subagents/src/runs/shared/nested-render.js +105 -1
  107. package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +81 -4
  108. package/extensions/dm-subagents/src/runs/shared/run-history.js +51 -4
  109. package/extensions/dm-subagents/src/runs/shared/single-output.js +149 -8
  110. package/extensions/dm-subagents/src/runs/shared/structured-output.js +58 -1
  111. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +166 -5
  112. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +329 -13
  113. package/extensions/dm-subagents/src/runs/shared/tool-budget.js +73 -1
  114. package/extensions/dm-subagents/src/runs/shared/turn-budget.js +47 -4
  115. package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +196 -1
  116. package/extensions/dm-subagents/src/runs/shared/worktree.js +435 -3
  117. package/extensions/dm-subagents/src/shared/artifacts.js +92 -2
  118. package/extensions/dm-subagents/src/shared/atomic-json.js +55 -1
  119. package/extensions/dm-subagents/src/shared/child-transcript.js +167 -5
  120. package/extensions/dm-subagents/src/shared/file-coalescer.js +25 -1
  121. package/extensions/dm-subagents/src/shared/fork-context.js +147 -4
  122. package/extensions/dm-subagents/src/shared/formatters.js +98 -7
  123. package/extensions/dm-subagents/src/shared/jsonl-writer.js +56 -2
  124. package/extensions/dm-subagents/src/shared/model-info.js +62 -1
  125. package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +68 -1
  126. package/extensions/dm-subagents/src/shared/session-identity.js +6 -1
  127. package/extensions/dm-subagents/src/shared/session-tokens.js +39 -2
  128. package/extensions/dm-subagents/src/shared/settings.js +198 -11
  129. package/extensions/dm-subagents/src/shared/status-format.js +53 -1
  130. package/extensions/dm-subagents/src/shared/types.js +184 -6
  131. package/extensions/dm-subagents/src/shared/utils.js +462 -2
  132. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +288 -1
  133. package/extensions/dm-subagents/src/slash/prompt-workflows.js +297 -7
  134. package/extensions/dm-subagents/src/slash/slash-bridge.js +118 -1
  135. package/extensions/dm-subagents/src/slash/slash-commands.js +1287 -31
  136. package/extensions/dm-subagents/src/slash/slash-live-state.js +240 -4
  137. package/extensions/dm-subagents/src/tui/render-helpers.js +64 -1
  138. package/extensions/dm-subagents/src/tui/render.js +1542 -4
  139. package/extensions/dm-usage/index.js +1294 -9
  140. package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +40 -9
  141. package/extensions/greedysearch-dm/bin/cdp-headless.mjs +5 -2
  142. package/extensions/greedysearch-dm/bin/cdp-visible.mjs +5 -2
  143. package/extensions/greedysearch-dm/bin/cdp.mjs +896 -30
  144. package/extensions/greedysearch-dm/bin/gschrome.mjs +30 -2
  145. package/extensions/greedysearch-dm/bin/kill-visible.mjs +7 -2
  146. package/extensions/greedysearch-dm/bin/launch-visible.mjs +13 -2
  147. package/extensions/greedysearch-dm/bin/launch.mjs +282 -10
  148. package/extensions/greedysearch-dm/bin/mcp.mjs +386 -361
  149. package/extensions/greedysearch-dm/bin/search.mjs +620 -540
  150. package/extensions/greedysearch-dm/bin/visible.mjs +22 -2
  151. package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +329 -579
  152. package/extensions/greedysearch-dm/extractors/chatgpt.mjs +301 -583
  153. package/extensions/greedysearch-dm/extractors/common.mjs +408 -32
  154. package/extensions/greedysearch-dm/extractors/consensus.mjs +376 -365
  155. package/extensions/greedysearch-dm/extractors/consent.mjs +303 -14
  156. package/extensions/greedysearch-dm/extractors/gemini.mjs +228 -592
  157. package/extensions/greedysearch-dm/extractors/google-ai.mjs +78 -499
  158. package/extensions/greedysearch-dm/extractors/logically.mjs +270 -347
  159. package/extensions/greedysearch-dm/extractors/perplexity.mjs +243 -581
  160. package/extensions/greedysearch-dm/extractors/selectors.mjs +32 -1
  161. package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +130 -317
  162. package/extensions/greedysearch-dm/index.js +123 -23
  163. package/extensions/greedysearch-dm/src/fetcher.mjs +576 -2
  164. package/extensions/greedysearch-dm/src/formatters/results.js +95 -10
  165. package/extensions/greedysearch-dm/src/formatters/sources.js +57 -1
  166. package/extensions/greedysearch-dm/src/formatters/synthesis.js +49 -1
  167. package/extensions/greedysearch-dm/src/github.mjs +222 -7
  168. package/extensions/greedysearch-dm/src/reddit.mjs +145 -14
  169. package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +340 -9
  170. package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +112 -4
  171. package/extensions/greedysearch-dm/src/search/chrome.mjs +486 -285
  172. package/extensions/greedysearch-dm/src/search/constants.mjs +109 -8
  173. package/extensions/greedysearch-dm/src/search/defaults.mjs +10 -1
  174. package/extensions/greedysearch-dm/src/search/engines.mjs +79 -9
  175. package/extensions/greedysearch-dm/src/search/fetch-source.mjs +441 -349
  176. package/extensions/greedysearch-dm/src/search/file-sources.mjs +29 -7
  177. package/extensions/greedysearch-dm/src/search/minimize.mjs +86 -1
  178. package/extensions/greedysearch-dm/src/search/output.mjs +51 -5
  179. package/extensions/greedysearch-dm/src/search/paths.mjs +48 -1
  180. package/extensions/greedysearch-dm/src/search/pdf.mjs +63 -2
  181. package/extensions/greedysearch-dm/src/search/port-pid.mjs +69 -1
  182. package/extensions/greedysearch-dm/src/search/progress.mjs +109 -2
  183. package/extensions/greedysearch-dm/src/search/query.mjs +21 -1
  184. package/extensions/greedysearch-dm/src/search/recovery.mjs +49 -1
  185. package/extensions/greedysearch-dm/src/search/research.mjs +2227 -458
  186. package/extensions/greedysearch-dm/src/search/scale-aware.mjs +61 -11
  187. package/extensions/greedysearch-dm/src/search/simple-research.mjs +396 -805
  188. package/extensions/greedysearch-dm/src/search/sources.mjs +412 -1
  189. package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +127 -12
  190. package/extensions/greedysearch-dm/src/search/synthesis.mjs +202 -12
  191. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +209 -23
  192. package/extensions/greedysearch-dm/src/tools/shared.js +226 -10
  193. package/extensions/greedysearch-dm/src/utils/content.mjs +35 -4
  194. package/extensions/greedysearch-dm/src/utils/helpers.js +22 -1
  195. package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +10 -1
  196. package/extensions/greedysearch-dm/src/utils/system-cmds.mjs +61 -1
  197. package/package.json +1 -1
@@ -1,80 +1,2856 @@
1
- import{spawn as w5,spawnSync as u8}from"node:child_process";import*as e from"node:fs";import*as r from"node:path";import{pathToFileURL as I5}from"node:url";import*as j2 from"node:fs";import*as K0 from"node:path";var J2=[10,25,50,100,200,500,1000,2000,4000],Z2=new Set(["EACCES","EBUSY","EPERM"]),uj=typeof SharedArrayBuffer<"u"?new SharedArrayBuffer(4):void 0,lj=uj?new Int32Array(uj):void 0;function Q2($){if($<=0)return;if(lj)try{Atomics.wait(lj,0,0,$);return}catch{}let j=Date.now()+$;while(Date.now()<j);}function X2($){let j=$?.code;return typeof j==="string"&&Z2.has(j)}function Y2($,j,J,Z,Q){for(let X=0;;X++)try{$.renameSync(j,J);return}catch(W){let U=Z[X];if(U===void 0||!X2(W))throw W;Q(U)}}function W2($={}){let j=$.fs??j2,J=$.now??Date.now,Z=$.pid??process.pid,Q=$.random??Math.random,W=$.retryRenameErrors??process.platform==="win32"?$.retryDelaysMs??J2:[],U=$.wait??Q2;return(G,B)=>{j.mkdirSync(K0.dirname(G),{recursive:!0});let q=K0.join(K0.dirname(G),`.${K0.basename(G)}.${Z}.${J()}.${Q().toString(36).slice(2)}.tmp`);try{j.writeFileSync(q,JSON.stringify(B,null,2),"utf-8"),Y2(j,q,G,W,U)}finally{j.rmSync(q,{force:!0})}}}var D$=W2();import*as U0 from"node:fs";import*as XJ from"node:path";import*as C$ from"node:fs";import*as b0 from"node:os";import*as h$ from"node:path";import*as J0 from"node:fs";import*as $1 from"node:path";import*as q0 from"node:os";import*as F0 from"node:path";var S0=1;var nj={bytes:204800,lines:5000};function a0($){return $.trim().replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}function H2($){let j=$?.env??process.env,J=$&&Object.hasOwn($,"getuid")?$.getuid:process.getuid?.bind(process);if(typeof J==="function")return`uid-${J()}`;for(let W of["USERNAME","USER","LOGNAME"]){let U=j[W];if(U)return`user-${a0(U)}`}let Z=$&&Object.hasOwn($,"userInfo")?$.userInfo:q0.userInfo;try{let W=Z?.().username;if(W)return`user-${a0(W)}`}catch{}let Q=j.USERPROFILE??j.HOME;if(Q)return`home-${a0(Q)}`;let X=$&&Object.hasOwn($,"homedir")?$.homedir:q0.homedir;try{let W=X?.();if(W)return`home-${a0(W)}`}catch{}return"shared"}var r$=F0.join(q0.tmpdir(),`dm-subagents-${H2()}`),V2=F0.join(r$,"async-subagent-results"),K2=F0.join(r$,"async-subagent-runs"),U2=F0.join(r$,"chain-runs"),z2=F0.join(r$,"artifacts");var ij=250;var G2=2;function B2($){let j=typeof $==="number"?$:typeof $==="string"?Number($):NaN;if(!Number.isInteger(j)||j<0)return;return j}function I1($){return B2($)}function _2($){return I1(process.env.DM_SUBAGENT_MAX_DEPTH)??I1($)??G2}function rj($){let j=Number(process.env.DM_SUBAGENT_DEPTH??"0"),J=Number.isFinite(j)?j+1:1;return{DM_SUBAGENT_DEPTH:String(J),DM_SUBAGENT_MAX_DEPTH:String(I1($)??_2())}}function pj($){if($<1024)return`${$}B`;if($<1048576)return`${($/1024).toFixed(1)}KB`;return`${($/1048576).toFixed(1)}MB`}function sj($,j,J){let Z=$.split(`
2
- `),Q=Buffer.byteLength($,"utf-8");if(Q<=j.bytes&&Z.length<=j.lines)return{text:$,truncated:!1};let X=Z;if(Z.length>j.lines)X=Z.slice(0,j.lines);let W=X.join(`
3
- `);if(Buffer.byteLength(W,"utf-8")>j.bytes){let B=0,q=W.length;while(B<q){let O=Math.floor((B+q+1)/2);if(Buffer.byteLength(W.slice(0,O),"utf-8")<=j.bytes)B=O;else q=O-1}W=W.slice(0,B)}return{text:`[TRUNCATED: showing first ${W.split(`
4
- `).length} of ${Z.length} lines, ${pj(Buffer.byteLength(W))} of ${pj(Q)}${J?` - full output at ${J}`:""}]
5
- `+W,truncated:!0,originalBytes:Q,originalLines:Z.length,artifactPath:J}}function $0($){return"parallel"in $&&Array.isArray($.parallel)}function j0($){return"expand"in $&&"collect"in $&&"parallel"in $&&!Array.isArray($.parallel)}function aj($){let j=[];for(let J of $)if($0(J))for(let Z of J.parallel)j.push(Z);else if(j0(J))continue;else j.push(J);return j}var tj=20;class y1{available;queue=[];constructor($){this.available=Math.max(1,Math.floor($)||1)}acquire(){if(this.available>0)return this.available--,Promise.resolve();return new Promise(($)=>{this.queue.push($)})}release(){let $=this.queue.shift();if($)$();else this.available++}}async function t0($,j,J,Z){let Q=Math.max(1,Math.floor(j)||1),X=Array($.length),W=0;async function U(G){while(W<$.length){let B=W++;if(Z){await Z.acquire();try{X[B]=await J($[B],B)}finally{Z.release()}}else X[B]=await J($[B],B)}}return await Promise.all(Array.from({length:Math.min(Q,$.length)},(G,B)=>U(B))),X}function e0($,j=(J,Z)=>`=== Parallel Task ${J+1} (${Z}) ===`){return $.map((J,Z)=>{let Q=j(J.taskIndex??Z,J.agent),X=Boolean(J.output?.trim()),W=J.timedOut?`TIMED OUT${J.error?`: ${J.error}`:""}`:J.exitCode===-1?"SKIPPED":J.exitCode!==0&&J.exitCode!==null?`FAILED (exit code ${J.exitCode})${J.error?`: ${J.error}`:""}`:J.error?`WARNING: ${J.error}`:!X&&J.outputTargetPath&&J.outputTargetExists===!1?`EMPTY OUTPUT (expected output file missing: ${J.outputTargetPath})`:!X&&!J.outputTargetPath?"EMPTY OUTPUT (no textual response returned)":"",U=W?X?`${W}
6
- ${J.output}`:W:J.output;return`${Q}
7
- ${U}`}).join(`
1
+ import { spawn, spawnSync } from "node:child_process";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { writeAtomicJson } from "../../shared/atomic-json.js";
6
+ import { createChildTranscriptWriter } from "../../shared/child-transcript.js";
7
+ import { consumeInterruptRequest, deliverInterruptRequest, deliverTimeoutRequest, enqueueStepSteer, stepSteerInboxDir, watchAsyncControlInbox } from "./control-channel.js";
8
+ import { appendJsonl as appendRawJsonl, getArtifactPaths } from "../../shared/artifacts.js";
9
+ import { PI_CODING_AGENT_PACKAGE, getPiSpawnCommand, resolveInstalledPiPackageRoot } from "../shared/dm-spawn.js";
10
+ import { captureSingleOutputSnapshot, finalizeSingleOutput, formatSavedOutputReference, resolveSingleOutput } from "../shared/single-output.js";
11
+ import {
12
+ DEFAULT_MAX_OUTPUT,
13
+ SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
14
+ truncateOutput,
15
+ getSubagentDepthEnv
16
+ } from "../../shared/types.js";
17
+ import {
18
+ DEFAULT_CONTROL_CONFIG,
19
+ buildControlEvent,
20
+ deriveActivityState,
21
+ claimControlNotification,
22
+ formatControlIntercomMessage,
23
+ formatControlNoticeMessage
24
+ } from "../shared/subagent-control.js";
25
+ import {
26
+ isDynamicRunnerGroup,
27
+ isParallelGroup,
28
+ flattenSteps,
29
+ mapConcurrent,
30
+ aggregateParallelOutputs,
31
+ MAX_PARALLEL_CONCURRENCY,
32
+ DEFAULT_GLOBAL_CONCURRENCY_LIMIT,
33
+ Semaphore
34
+ } from "../shared/parallel-utils.js";
35
+ import { applyThinkingSuffix, buildPiArgs, cleanupTempDir } from "../shared/dm-args.js";
36
+ import { outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.js";
37
+ import { createStructuredOutputRuntime, readStructuredOutput } from "../shared/structured-output.js";
38
+ import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.js";
39
+ import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.js";
40
+ import { formatModelAttemptNote, isRetryableModelFailure } from "../shared/model-fallback.js";
41
+ import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.js";
42
+ import { detectSubagentError, extractTextFromContent, extractToolArgsPreview, getFinalOutput, readStatus } from "../../shared/utils.js";
43
+ import { evaluateCompletionMutationGuard } from "../shared/completion-guard.js";
44
+ import {
45
+ createMutatingFailureState,
46
+ didMutatingToolFail,
47
+ isMutatingTool,
48
+ nextLongRunningTrigger,
49
+ recordMutatingFailure,
50
+ resetMutatingFailureState,
51
+ resolveCurrentPath,
52
+ shouldEscalateMutatingFailures,
53
+ summarizeRecentMutatingFailures
54
+ } from "../shared/long-running-guard.js";
55
+ import { parseSessionTokens } from "../../shared/session-tokens.js";
56
+ import {
57
+ cleanupWorktrees,
58
+ createWorktrees,
59
+ diffWorktrees,
60
+ findWorktreeTaskCwdConflict,
61
+ formatWorktreeDiffSummary,
62
+ formatWorktreeTaskCwdConflict
63
+ } from "../shared/worktree.js";
64
+ import { resolveEffectiveThinking } from "../../shared/model-info.js";
65
+ import { writeInitialProgressFile } from "../../shared/settings.js";
66
+ import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.js";
67
+ import { acceptanceFailureMessage, aggregateAcceptanceReport, evaluateAcceptance, formatAcceptancePrompt, stripAcceptanceReport } from "../shared/acceptance.js";
68
+ import { waitForImportedAsyncRoot } from "./chain-root-attachment.js";
69
+ import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests } from "./chain-append.js";
70
+ import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, shouldAbortForTurnBudget, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.js";
71
+ import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.js";
72
+ const ASYNC_INTERRUPT_SIGNAL = process.platform === "win32" ? "SIGBREAK" : "SIGUSR2";
73
+ const DEFAULT_MAX_ASYNC_EVENTS_BYTES = 50 * 1024 * 1024;
74
+ const ASYNC_EVENTS_MAX_BYTES_ENV = "DM_SUBAGENT_ASYNC_EVENTS_MAX_BYTES";
75
+ const TRUNCATED_EVENT_TYPE = "subagent.events.truncated";
76
+ const TRUNCATION_MARKER_RESERVE_BYTES = 512;
77
+ const asyncEventLogStates = new Map;
78
+ function maxAsyncEventsBytes() {
79
+ const raw = process.env[ASYNC_EVENTS_MAX_BYTES_ENV];
80
+ if (!raw)
81
+ return DEFAULT_MAX_ASYNC_EVENTS_BYTES;
82
+ const parsed = Number(raw);
83
+ if (!Number.isFinite(parsed) || parsed < 0)
84
+ return DEFAULT_MAX_ASYNC_EVENTS_BYTES;
85
+ return Math.floor(parsed);
86
+ }
87
+ function eventLogState(filePath) {
88
+ let state = asyncEventLogStates.get(filePath);
89
+ if (state)
90
+ return state;
91
+ let bytes = 0;
92
+ try {
93
+ bytes = fs.statSync(filePath).size;
94
+ } catch (error) {
95
+ if (error.code !== "ENOENT") {}
96
+ }
97
+ state = { bytes, diagnosticsTruncated: false };
98
+ asyncEventLogStates.set(filePath, state);
99
+ return state;
100
+ }
101
+ function appendJsonl(filePath, line) {
102
+ try {
103
+ appendRawJsonl(filePath, line);
104
+ const state = asyncEventLogStates.get(filePath);
105
+ if (state)
106
+ state.bytes += Buffer.byteLength(`${line}
107
+ `, "utf-8");
108
+ } catch {}
109
+ }
110
+ function appendDiagnosticJsonl(filePath, line, droppedEventType) {
111
+ if (!line.trim())
112
+ return;
113
+ const state = eventLogState(filePath);
114
+ if (state.diagnosticsTruncated)
115
+ return;
116
+ const maxBytes = maxAsyncEventsBytes();
117
+ const chunkBytes = Buffer.byteLength(`${line}
118
+ `, "utf-8");
119
+ const diagnosticBudget = Math.max(0, maxBytes - TRUNCATION_MARKER_RESERVE_BYTES);
120
+ if (state.bytes + chunkBytes <= diagnosticBudget) {
121
+ appendJsonl(filePath, line);
122
+ return;
123
+ }
124
+ const marker = JSON.stringify({
125
+ type: TRUNCATED_EVENT_TYPE,
126
+ ts: Date.now(),
127
+ maxBytes,
128
+ droppedEventType
129
+ });
130
+ if (state.bytes + Buffer.byteLength(`${marker}
131
+ `, "utf-8") <= maxBytes) {
132
+ appendJsonl(filePath, marker);
133
+ }
134
+ state.diagnosticsTruncated = true;
135
+ }
136
+ function shouldPersistChildEvent(event) {
137
+ return event.type !== "message_update";
138
+ }
139
+ function findLatestSessionFile(sessionDir) {
140
+ try {
141
+ const files = fs.readdirSync(sessionDir).filter((f) => f.endsWith(".jsonl")).map((f) => path.join(sessionDir, f));
142
+ if (files.length === 0)
143
+ return null;
144
+ files.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs);
145
+ return files[0] ?? null;
146
+ } catch {
147
+ return null;
148
+ }
149
+ }
150
+ function emptyUsage() {
151
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
152
+ }
153
+ function tokenUsageFromAttempts(attempts) {
154
+ if (!attempts || attempts.length === 0)
155
+ return null;
156
+ let input = 0;
157
+ let output = 0;
158
+ for (const attempt of attempts) {
159
+ input += attempt.usage?.input ?? 0;
160
+ output += attempt.usage?.output ?? 0;
161
+ }
162
+ const total = input + output;
163
+ return total > 0 ? { input, output, total } : null;
164
+ }
165
+ function costSummaryFromAttempts(attempts) {
166
+ if (!attempts || attempts.length === 0)
167
+ return;
168
+ let inputTokens = 0;
169
+ let outputTokens = 0;
170
+ let costUsd = 0;
171
+ for (const attempt of attempts) {
172
+ inputTokens += attempt.usage?.input ?? 0;
173
+ outputTokens += attempt.usage?.output ?? 0;
174
+ costUsd += attempt.usage?.cost ?? 0;
175
+ }
176
+ return inputTokens > 0 || outputTokens > 0 || costUsd > 0 ? { inputTokens, outputTokens, costUsd } : undefined;
177
+ }
178
+ function appendRecentStepOutput(step, lines) {
179
+ const nonEmpty = lines.filter((line) => line.trim());
180
+ if (nonEmpty.length === 0)
181
+ return;
182
+ step.recentOutput ??= [];
183
+ step.recentOutput.push(...nonEmpty);
184
+ if (step.recentOutput.length > 50) {
185
+ step.recentOutput.splice(0, step.recentOutput.length - 50);
186
+ }
187
+ }
188
+ function isTerminalAssistantStop(message) {
189
+ const stopReason = message.stopReason;
190
+ const hasToolCall = Array.isArray(message.content) && message.content.some((part) => part.type === "toolCall");
191
+ return stopReason === "stop" && !hasToolCall;
192
+ }
193
+ function resetStepLiveDetail(step) {
194
+ step.currentTool = undefined;
195
+ step.currentToolArgs = undefined;
196
+ step.currentToolStartedAt = undefined;
197
+ step.currentPath = undefined;
198
+ step.recentTools = [];
199
+ step.recentOutput = [];
200
+ }
201
+ function runPiStreaming(args, cwd, outputFile, env, piPackageRoot, piArgv1, maxSubagentDepth, childEventContext, registerInterrupt, onChildEvent, transcriptWriter, registerTimeout, timeoutMessage, registerTurnBudgetAbort) {
202
+ return new Promise((resolve) => {
203
+ const outputStream = fs.createWriteStream(outputFile, { flags: "w" });
204
+ const spawnEnv = { ...process.env, ...env ?? {}, ...getSubagentDepthEnv(maxSubagentDepth) };
205
+ const spawnSpec = getPiSpawnCommand(args, {
206
+ ...piPackageRoot ? { piPackageRoot } : {},
207
+ ...piArgv1 ? { argv1: piArgv1 } : {}
208
+ });
209
+ const child = spawn(spawnSpec.command, spawnSpec.args, {
210
+ cwd,
211
+ stdio: ["ignore", "pipe", "pipe"],
212
+ env: spawnEnv,
213
+ windowsHide: true
214
+ });
215
+ let stderr = "";
216
+ let stdoutBuf = "";
217
+ let stderrBuf = "";
218
+ const messages = [];
219
+ const usage = emptyUsage();
220
+ let model;
221
+ let error;
222
+ let assistantError;
223
+ let interrupted = false;
224
+ let timedOut = false;
225
+ let turnBudgetExceeded = false;
226
+ let turnBudgetMessage;
227
+ let turnBudget;
228
+ let observedMutationAttempt = false;
229
+ const rawStdoutLines = [];
230
+ const writeOutputLine = (line) => {
231
+ if (!line.trim())
232
+ return;
233
+ outputStream.write(`${line}
234
+ `);
235
+ };
236
+ const writeOutputText = (text) => {
237
+ for (const line of text.split(`
238
+ `)) {
239
+ writeOutputLine(line);
240
+ }
241
+ };
242
+ const appendChildEvent = (event) => {
243
+ if (!childEventContext)
244
+ return;
245
+ if (!shouldPersistChildEvent(event))
246
+ return;
247
+ appendDiagnosticJsonl(childEventContext.eventsPath, JSON.stringify({
248
+ ...event,
249
+ subagentSource: "child",
250
+ subagentRunId: childEventContext.runId,
251
+ subagentStepIndex: childEventContext.stepIndex,
252
+ subagentAgent: childEventContext.agent,
253
+ observedAt: Date.now()
254
+ }), typeof event.type === "string" ? event.type : undefined);
255
+ };
256
+ const appendChildLine = (type, line) => {
257
+ appendChildEvent({ type, line });
258
+ if (type === "subagent.child.stdout")
259
+ transcriptWriter?.writeStdoutLine(line);
260
+ else
261
+ transcriptWriter?.writeStderrLine(line);
262
+ };
263
+ const processStdoutLine = (line) => {
264
+ if (!line.trim())
265
+ return;
266
+ let event;
267
+ try {
268
+ event = JSON.parse(line);
269
+ } catch {
270
+ rawStdoutLines.push(line);
271
+ writeOutputLine(line);
272
+ appendChildLine("subagent.child.stdout", line);
273
+ return;
274
+ }
275
+ appendChildEvent(event);
276
+ transcriptWriter?.writeChildEvent(event);
277
+ onChildEvent?.(event);
278
+ if (event.type === "tool_execution_start" && event.toolName) {
279
+ observedMutationAttempt = observedMutationAttempt || isMutatingTool(event.toolName, event.args);
280
+ const toolArgs = extractToolArgsPreview(event.args ?? {});
281
+ writeOutputLine(toolArgs ? `${event.toolName}: ${toolArgs}` : event.toolName);
282
+ return;
283
+ }
284
+ if ((event.type === "message_end" || event.type === "tool_result_end") && event.message) {
285
+ messages.push(event.message);
286
+ const text = extractTextFromContent(event.message.content);
287
+ if (text)
288
+ writeOutputText(text);
289
+ if (event.type !== "message_end" || event.message.role !== "assistant")
290
+ return;
291
+ if (event.message.model)
292
+ model = event.message.model;
293
+ if (event.message.errorMessage)
294
+ assistantError = event.message.errorMessage;
295
+ const eventUsage = event.message.usage;
296
+ if (eventUsage) {
297
+ usage.turns++;
298
+ usage.input += eventUsage.input ?? eventUsage.inputTokens ?? 0;
299
+ usage.output += eventUsage.output ?? eventUsage.outputTokens ?? 0;
300
+ usage.cacheRead += eventUsage.cacheRead ?? 0;
301
+ usage.cacheWrite += eventUsage.cacheWrite ?? 0;
302
+ usage.cost += eventUsage.cost?.total ?? 0;
303
+ }
304
+ if (isTerminalAssistantStop(event.message)) {
305
+ if (!event.message.errorMessage && extractTextFromContent(event.message.content).trim())
306
+ assistantError = undefined;
307
+ cleanTerminalAssistantStopReceived ||= !event.message.errorMessage;
308
+ startFinalDrain();
309
+ }
310
+ }
311
+ };
312
+ const processStderrText = (text) => {
313
+ stderr += text;
314
+ stderrBuf += text;
315
+ outputStream.write(text);
316
+ if (!childEventContext)
317
+ return;
318
+ const lines = stderrBuf.split(`
319
+ `);
320
+ stderrBuf = lines.pop() || "";
321
+ for (const line of lines) {
322
+ if (!line.trim())
323
+ continue;
324
+ appendChildLine("subagent.child.stderr", line);
325
+ }
326
+ };
327
+ const FINAL_STOP_GRACE_MS = 1000;
328
+ const HARD_KILL_MS = 3000;
329
+ const TIMEOUT_HARD_KILL_MS = 3000;
330
+ let childExited = false;
331
+ let forcedTerminationSignal = false;
332
+ let cleanTerminalAssistantStopReceived = false;
333
+ let finalDrainTimer;
334
+ let finalHardKillTimer;
335
+ let timeoutHardKillTimer;
336
+ let turnBudgetTerminationTimer;
337
+ let turnBudgetHardKillTimer;
338
+ let settled = false;
339
+ const clearStdioGuard = attachPostExitStdioGuard(child, { idleMs: 2000, hardMs: 8000 });
340
+ child.stdout.on("data", (chunk) => {
341
+ const text = chunk.toString();
342
+ stdoutBuf += text;
343
+ const lines = stdoutBuf.split(`
344
+ `);
345
+ stdoutBuf = lines.pop() || "";
346
+ for (const line of lines)
347
+ processStdoutLine(line);
348
+ });
349
+ child.stderr.on("data", (chunk) => {
350
+ processStderrText(chunk.toString());
351
+ });
352
+ registerInterrupt?.(() => {
353
+ if (settled || timedOut)
354
+ return;
355
+ interrupted = true;
356
+ if (!error)
357
+ error = "Interrupted. Waiting for explicit next action.";
358
+ trySignalChild(child, "SIGINT");
359
+ setTimeout(() => {
360
+ if (!settled && !timedOut)
361
+ trySignalChild(child, "SIGTERM");
362
+ }, 1000).unref?.();
363
+ });
364
+ registerTimeout?.(() => {
365
+ if (settled || timedOut)
366
+ return;
367
+ timedOut = true;
368
+ interrupted = false;
369
+ error = timeoutMessage ?? "Subagent timed out.";
370
+ trySignalChild(child, "SIGTERM");
371
+ timeoutHardKillTimer = setTimeout(() => {
372
+ if (!settled)
373
+ trySignalChild(child, "SIGKILL");
374
+ }, TIMEOUT_HARD_KILL_MS);
375
+ timeoutHardKillTimer.unref?.();
376
+ });
377
+ registerTurnBudgetAbort?.((message, state) => {
378
+ if (settled || timedOut || turnBudgetExceeded)
379
+ return;
380
+ turnBudgetExceeded = true;
381
+ turnBudgetMessage = message;
382
+ turnBudget = state;
383
+ interrupted = false;
384
+ error = message;
385
+ trySignalChild(child, "SIGINT");
386
+ turnBudgetTerminationTimer = setTimeout(() => {
387
+ if (!settled && !timedOut)
388
+ trySignalChild(child, "SIGTERM");
389
+ }, 1000);
390
+ turnBudgetTerminationTimer.unref?.();
391
+ turnBudgetHardKillTimer = setTimeout(() => {
392
+ if (!settled && !timedOut)
393
+ trySignalChild(child, "SIGKILL");
394
+ }, 4000);
395
+ turnBudgetHardKillTimer.unref?.();
396
+ });
397
+ const clearDrainTimers = () => {
398
+ if (finalDrainTimer) {
399
+ clearTimeout(finalDrainTimer);
400
+ finalDrainTimer = undefined;
401
+ }
402
+ if (finalHardKillTimer) {
403
+ clearTimeout(finalHardKillTimer);
404
+ finalHardKillTimer = undefined;
405
+ }
406
+ if (timeoutHardKillTimer) {
407
+ clearTimeout(timeoutHardKillTimer);
408
+ timeoutHardKillTimer = undefined;
409
+ }
410
+ if (turnBudgetTerminationTimer) {
411
+ clearTimeout(turnBudgetTerminationTimer);
412
+ turnBudgetTerminationTimer = undefined;
413
+ }
414
+ if (turnBudgetHardKillTimer) {
415
+ clearTimeout(turnBudgetHardKillTimer);
416
+ turnBudgetHardKillTimer = undefined;
417
+ }
418
+ };
419
+ function startFinalDrain() {
420
+ if (childExited || finalDrainTimer || settled)
421
+ return;
422
+ finalDrainTimer = setTimeout(() => {
423
+ if (settled)
424
+ return;
425
+ const termSent = trySignalChild(child, "SIGTERM");
426
+ if (!termSent)
427
+ return;
428
+ forcedTerminationSignal = true;
429
+ if (!cleanTerminalAssistantStopReceived && !error && !assistantError) {
430
+ error = `Subagent process did not exit within ${FINAL_STOP_GRACE_MS}ms after its final message. Forcing termination.`;
431
+ }
432
+ finalHardKillTimer = setTimeout(() => {
433
+ if (settled)
434
+ return;
435
+ forcedTerminationSignal = trySignalChild(child, "SIGKILL") || forcedTerminationSignal;
436
+ }, HARD_KILL_MS);
437
+ finalHardKillTimer.unref?.();
438
+ }, FINAL_STOP_GRACE_MS);
439
+ finalDrainTimer.unref?.();
440
+ }
441
+ child.on("exit", () => {
442
+ childExited = true;
443
+ clearDrainTimers();
444
+ });
445
+ child.on("close", (exitCode, signal) => {
446
+ settled = true;
447
+ registerInterrupt?.(undefined);
448
+ registerTimeout?.(undefined);
449
+ registerTurnBudgetAbort?.(undefined);
450
+ clearDrainTimers();
451
+ clearStdioGuard();
452
+ if (stdoutBuf.trim())
453
+ processStdoutLine(stdoutBuf);
454
+ if (stderrBuf.trim())
455
+ appendChildLine("subagent.child.stderr", stderrBuf);
456
+ outputStream.end();
457
+ const finalOutput = getFinalOutput(messages) || rawStdoutLines.join(`
458
+ `).trim();
459
+ const finalError = error ?? assistantError;
460
+ const forcedDrainAfterFinalSuccess = forcedTerminationSignal && cleanTerminalAssistantStopReceived && !finalError;
461
+ resolve({
462
+ stderr,
463
+ exitCode: timedOut ? 1 : turnBudgetExceeded ? 1 : interrupted || forcedDrainAfterFinalSuccess ? 0 : forcedTerminationSignal || signal ? exitCode ?? 1 : exitCode,
464
+ messages,
465
+ usage,
466
+ model,
467
+ error: timedOut ? timeoutMessage ?? "Subagent timed out." : turnBudgetExceeded ? turnBudgetMessage : interrupted || forcedDrainAfterFinalSuccess ? undefined : finalError,
468
+ finalOutput: timedOut && !finalOutput.trim() ? timeoutMessage ?? "Subagent timed out." : finalOutput,
469
+ interrupted,
470
+ timedOut,
471
+ turnBudget,
472
+ turnBudgetExceeded,
473
+ wrapUpRequested: turnBudget?.outcome === "wrap-up-requested" || turnBudgetExceeded || undefined,
474
+ observedMutationAttempt
475
+ });
476
+ });
477
+ child.on("error", (spawnError) => {
478
+ settled = true;
479
+ registerInterrupt?.(undefined);
480
+ registerTimeout?.(undefined);
481
+ registerTurnBudgetAbort?.(undefined);
482
+ clearDrainTimers();
483
+ clearStdioGuard();
484
+ outputStream.end();
485
+ const finalOutput = getFinalOutput(messages) || rawStdoutLines.join(`
486
+ `).trim();
487
+ const spawnErrorMessage = spawnError instanceof Error ? spawnError.message : String(spawnError);
488
+ resolve({ stderr, exitCode: 1, messages, usage, model, error: timedOut ? timeoutMessage ?? "Subagent timed out." : turnBudgetExceeded ? turnBudgetMessage : error ?? assistantError ?? spawnErrorMessage, finalOutput: timedOut && !finalOutput.trim() ? timeoutMessage ?? "Subagent timed out." : finalOutput, timedOut, turnBudget, turnBudgetExceeded, wrapUpRequested: turnBudget?.outcome === "wrap-up-requested" || turnBudgetExceeded || undefined, observedMutationAttempt });
489
+ });
490
+ });
491
+ }
492
+ function resolvePiPackageRootFallback() {
493
+ const root = resolveInstalledPiPackageRoot();
494
+ if (root)
495
+ return root;
496
+ throw new Error(`Could not resolve ${PI_CODING_AGENT_PACKAGE} package root`);
497
+ }
498
+ async function exportSessionHtml(sessionFile, outputDir, piPackageRoot) {
499
+ const pkgRoot = piPackageRoot ?? resolvePiPackageRootFallback();
500
+ const exportModulePath = path.join(pkgRoot, "dist", "core", "export-html", "index.js");
501
+ const moduleUrl = pathToFileURL(exportModulePath).href;
502
+ const mod = await import(moduleUrl);
503
+ const exportFromFile = mod.exportFromFile;
504
+ if (typeof exportFromFile !== "function") {
505
+ throw new Error("exportFromFile not available");
506
+ }
507
+ const outputPath = path.join(outputDir, `${path.basename(sessionFile, ".jsonl")}.html`);
508
+ return exportFromFile(sessionFile, { outputPath });
509
+ }
510
+ function createShareLink(htmlPath) {
511
+ try {
512
+ const auth = spawnSync("gh", ["auth", "status"], { encoding: "utf-8" });
513
+ if (auth.status !== 0) {
514
+ return { error: "GitHub CLI is not logged in. Run 'gh auth login' first." };
515
+ }
516
+ } catch {
517
+ return { error: "GitHub CLI (gh) is not installed." };
518
+ }
519
+ try {
520
+ const result = spawnSync("gh", ["gist", "create", htmlPath], { encoding: "utf-8" });
521
+ if (result.status !== 0) {
522
+ const err = (result.stderr || "").trim() || "Failed to create gist.";
523
+ return { error: err };
524
+ }
525
+ const gistUrl = (result.stdout || "").trim();
526
+ const gistId = gistUrl.split("/").pop();
527
+ if (!gistId)
528
+ return { error: "Failed to parse gist ID." };
529
+ const shareUrl = `https://shittycodingagent.ai/session/?${gistId}`;
530
+ return { shareUrl, gistUrl };
531
+ } catch (err) {
532
+ return { error: String(err) };
533
+ }
534
+ }
535
+ function formatDuration(ms) {
536
+ if (ms < 1000)
537
+ return `${ms}ms`;
538
+ if (ms < 60000)
539
+ return `${(ms / 1000).toFixed(1)}s`;
540
+ const minutes = Math.floor(ms / 60000);
541
+ const seconds = Math.floor(ms % 60000 / 1000);
542
+ return `${minutes}m${seconds}s`;
543
+ }
544
+ function writeRunLog(logPath, input) {
545
+ const lines = [];
546
+ lines.push(`# Subagent run ${input.id}`);
547
+ lines.push("");
548
+ lines.push(`- **Mode:** ${input.mode}`);
549
+ lines.push(`- **CWD:** ${input.cwd}`);
550
+ lines.push(`- **Started:** ${new Date(input.startedAt).toISOString()}`);
551
+ lines.push(`- **Ended:** ${new Date(input.endedAt).toISOString()}`);
552
+ lines.push(`- **Duration:** ${formatDuration(input.endedAt - input.startedAt)}`);
553
+ if (input.sessionFile)
554
+ lines.push(`- **Session:** ${input.sessionFile}`);
555
+ if (input.shareUrl)
556
+ lines.push(`- **Share:** ${input.shareUrl}`);
557
+ if (input.shareError)
558
+ lines.push(`- **Share error:** ${input.shareError}`);
559
+ if (input.artifactsDir)
560
+ lines.push(`- **Artifacts:** ${input.artifactsDir}`);
561
+ lines.push("");
562
+ lines.push("## Steps");
563
+ lines.push("| Step | Agent | Status | Duration |");
564
+ lines.push("| --- | --- | --- | --- |");
565
+ input.steps.forEach((step, i) => {
566
+ const duration = step.durationMs !== undefined ? formatDuration(step.durationMs) : "-";
567
+ lines.push(`| ${i + 1} | ${step.agent} | ${step.status} | ${duration} |`);
568
+ });
569
+ lines.push("");
570
+ lines.push("## Summary");
571
+ if (input.truncated) {
572
+ lines.push("_Output truncated_");
573
+ lines.push("");
574
+ }
575
+ lines.push(input.summary.trim() || "(no output)");
576
+ lines.push("");
577
+ fs.writeFileSync(logPath, lines.join(`
578
+ `), "utf-8");
579
+ }
580
+ async function runSingleStep(step, ctx) {
581
+ if (step.importAsyncRoot) {
582
+ let importTimedOut = false;
583
+ ctx.registerTimeout?.(() => {
584
+ importTimedOut = true;
585
+ let pid;
586
+ try {
587
+ pid = readStatus(step.importAsyncRoot.asyncDir)?.pid;
588
+ } catch {
589
+ pid = undefined;
590
+ }
591
+ try {
592
+ deliverTimeoutRequest({ asyncDir: step.importAsyncRoot.asyncDir, pid, source: "ancestor-timeout" });
593
+ } catch {}
594
+ });
595
+ try {
596
+ const imported = await waitForImportedAsyncRoot(step.importAsyncRoot, {
597
+ shouldAbort: () => importTimedOut || ctx.timeoutSignal?.aborted === true || ctx.skipAcceptance?.() === true,
598
+ timeoutMessage: ctx.timeoutMessage
599
+ });
600
+ try {
601
+ fs.writeFileSync(ctx.outputFile, imported.output, "utf-8");
602
+ } catch {}
603
+ const timedOut = importTimedOut || imported.timedOut === true || ctx.timeoutSignal?.aborted === true || ctx.skipAcceptance?.() === true;
604
+ return {
605
+ agent: imported.agent,
606
+ output: timedOut ? ctx.timeoutMessage ?? "Subagent timed out." : imported.output,
607
+ exitCode: timedOut ? 1 : imported.exitCode,
608
+ error: timedOut ? ctx.timeoutMessage ?? "Subagent timed out." : imported.error,
609
+ timedOut: timedOut ? true : undefined,
610
+ sessionFile: imported.sessionFile,
611
+ intercomTarget: imported.intercomTarget,
612
+ model: imported.model,
613
+ attemptedModels: imported.attemptedModels,
614
+ modelAttempts: imported.modelAttempts,
615
+ totalCost: imported.totalCost,
616
+ structuredOutput: timedOut ? undefined : imported.structuredOutput,
617
+ structuredOutputPath: timedOut ? undefined : imported.structuredOutputPath,
618
+ structuredOutputSchemaPath: timedOut ? undefined : imported.structuredOutputSchemaPath,
619
+ acceptance: timedOut ? undefined : imported.acceptance
620
+ };
621
+ } finally {
622
+ ctx.registerTimeout?.(undefined);
623
+ }
624
+ }
625
+ const effectiveStructuredOutput = step.structuredOutput ?? (step.structuredOutputSchema ? createStructuredOutputRuntime(step.structuredOutputSchema, path.join(path.dirname(ctx.outputFile), "structured-output")) : undefined);
626
+ const placeholderRegex = new RegExp(ctx.placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
627
+ let task = step.task.replace(placeholderRegex, () => ctx.previousOutput);
628
+ task = resolveOutputReferences(task, ctx.outputs ?? {});
629
+ const taskForCompletionGuard = task;
630
+ if (step.effectiveAcceptance) {
631
+ const acceptancePrompt = formatAcceptancePrompt(step.effectiveAcceptance);
632
+ if (acceptancePrompt)
633
+ task = `${task}
634
+ ${acceptancePrompt}`;
635
+ }
636
+ const sessionEnabled = Boolean(step.sessionFile) || ctx.sessionEnabled;
637
+ const sessionDir = step.sessionFile ? undefined : ctx.sessionDir;
638
+ let artifactPaths;
639
+ let transcriptWriter;
640
+ if (ctx.artifactsDir && ctx.artifactConfig?.enabled !== false) {
641
+ const index = ctx.flatStepCount > 1 ? ctx.flatIndex : undefined;
642
+ artifactPaths = getArtifactPaths(ctx.artifactsDir, ctx.id, step.agent, index);
643
+ fs.mkdirSync(ctx.artifactsDir, { recursive: true });
644
+ if (ctx.artifactConfig?.includeInput !== false) {
645
+ fs.writeFileSync(artifactPaths.inputPath, `# Task for ${step.agent}
8
646
 
9
- `)}var k1=4;var M2=`# Progress
10
-
11
- ## Status
12
- In Progress
13
-
14
- ## Tasks
15
-
16
- ## Files Changed
17
-
18
- ## Notes
19
- `;function ej($){J0.mkdirSync($,{recursive:!0}),J0.writeFileSync($1.join($,"progress.md"),M2)}var f1=["off","minimal","low","medium","high","xhigh"];function O0($,j){if(!$)return;let{thinkingSuffix:J}=P1($);if(J)return J.slice(1);return f1.find((Z)=>Z===j)}function P1($){let j=$.lastIndexOf(":");if(j===-1)return{baseModel:$,thinkingSuffix:""};let J=f1.find((Z)=>Z===$.substring(j+1));if(!J)return{baseModel:$,thinkingSuffix:""};return{baseModel:$.substring(0,j),thinkingSuffix:`:${J}`}}var F2=".dm",O2="@duckmind/dm-coding-agent",A2="DM_SUBAGENTS_PI_CODING_AGENT_PACKAGE_ROOT";function JJ($){return typeof $==="string"&&$.trim()?$:void 0}function $J($){if(!$)return;try{let j=JSON.parse(C$.readFileSync(h$.join($,"package.json"),"utf-8"));if(j.name!==O2)return;return JJ(j.piConfig?.configDir)}catch{return}}function N2($=process.argv[1],j=process.env[A2]){let J=$J(j);if(J)return J;if(!$)return;try{let Z=h$.dirname(C$.realpathSync($));while(Z!==h$.dirname(Z)){let Q=$J(Z);if(Q)return Q;Z=h$.dirname(Z)}}catch{}return}function C2($,j,J){return($&&typeof $==="object"?JJ($.CONFIG_DIR_NAME):void 0)??N2(j,J)??F2}function ZJ(){return C2()}function w1($){return h$.join($,ZJ())}function L0(){let $=process.env.DM_CODING_AGENT_DIR;if($==="~")return b0.homedir();if($?.startsWith("~/"))return h$.join(b0.homedir(),$.slice(2));return $||h$.join(b0.homedir(),ZJ(),"agent")}var D0=new Map;function x1($){return $ instanceof Error?$.message:String($)}function jJ($){return typeof $==="object"&&$!==null&&"code"in $&&$.code==="ENOENT"}function R0($){let j=h$.join($,"status.json"),J;try{J=C$.statSync(j)}catch(W){if(jJ(W))return null;throw Error(`Failed to inspect async status file '${j}': ${x1(W)}`,{cause:W instanceof Error?W:void 0})}let Z=D0.get(j);if(Z&&Z.mtime===J.mtimeMs)return Z.status;let Q;try{Q=C$.readFileSync(j,"utf-8")}catch(W){if(jJ(W))return null;throw Error(`Failed to read async status file '${j}': ${x1(W)}`,{cause:W instanceof Error?W:void 0})}let X;try{X=JSON.parse(Q)}catch(W){throw Error(`Failed to parse async status file '${j}': ${x1(W)}`,{cause:W instanceof Error?W:void 0})}if(D0.set(j,{mtime:J.mtimeMs,status:X}),D0.size>50){let W=D0.keys().next().value;if(W)D0.delete(W)}return X}function j1($){let j=[];for(let J=$.length-1;J>=0;J--){let Z=$[J];if(Z.role!=="assistant")continue;if("errorMessage"in Z&&typeof Z.errorMessage==="string"&&Z.errorMessage.length>0||"stopReason"in Z&&Z.stopReason==="error")continue;for(let X=Z.content.length-1;X>=0;X--){let W=Z.content[X];if(W.type!=="text"||W.text.trim().length===0)continue;if(j.push(W.text),/```acceptance-report\s*\n[\s\S]*?```/i.test(W.text))return W.text;for(let U of W.text.matchAll(/```(?:json|jsonc|json5)\s*\n([\s\S]*?)```/gi)){let G=U[1]??"";if(/"criteriaSatisfied"/.test(G)&&/"(?:changedFiles|testsAddedOrUpdated|commandsRun|validationOutput|residualRisks|noStagedFiles|diffSummary|reviewFindings|manualNotes)"/.test(G))return W.text}if(/ACCEPTANCE_REPORT\s*:/i.test(W.text))return W.text}}return j[0]??""}function h1($){return $.finalOutput??j1($.messages??[])}function QJ($){let j=-1;for(let Z=$.length-1;Z>=0;Z--){let Q=$[Z];if(Q.role==="assistant"){if(Array.isArray(Q.content)&&Q.content.some((W)=>W.type==="text"&&("text"in W)&&typeof W.text==="string"&&W.text.trim().length>0)){j=Z;break}}}let J=j>=0?j+1:0;for(let Z=$.length-1;Z>=J;Z--){let Q=$[Z];if(Q.role!=="toolResult")continue;let X="toolName"in Q&&typeof Q.toolName==="string"?Q.toolName:void 0;if("isError"in Q&&Q.isError===!0){let O=Q.content.find((h)=>h.type==="text"),T=O&&"text"in O?O.text:void 0,y=T?.match(/exit(?:ed)?\s*(?:with\s*)?(?:code|status)?\s*[:\s]?\s*(\d+)/i);return{hasError:!0,exitCode:y?parseInt(y[1],10):1,errorType:X||"tool",details:T?.slice(0,200)}}if(X!=="bash")continue;let U=Q.content.find((O)=>O.type==="text");if(!U||!("text"in U))continue;let G=U.text,B=G.match(/exit(?:ed)?\s*(?:with\s*)?(?:code|status)?\s*[:\s]?\s*(\d+)/i);if(B){let O=parseInt(B[1],10);if(O!==0)return{hasError:!0,exitCode:O,errorType:"bash",details:G.slice(0,200)}}let q=[/command not found/i,/permission denied/i,/no such file or directory/i,/segmentation fault/i,/killed|terminated/i,/out of memory/i,/connection refused/i,/timeout/i];for(let O of q)if(O.test(G))return{hasError:!0,exitCode:1,errorType:"bash",details:G.slice(0,200)}}return{hasError:!1}}function w0($){let j=(U,G)=>U.length>G?`${U.slice(0,G-3)}...`:U,J=(U)=>{if(typeof U==="string"&&U.trim().length>0)return U;if(typeof U==="number"||typeof U==="boolean")return String(U);return},Z=(U)=>{if(!Array.isArray(U)||U.length===0)return;let G=J(U[0]);if(!G)return;let B=U.length>1?` (+${U.length-1} more)`:"";return`${G}${B}`};if($.tool&&typeof $.tool==="string"){let U=$.server&&typeof $.server==="string"?`${$.server}/`:"",G=$.args&&typeof $.args==="string"?` ${$.args.slice(0,40)}`:"";return`${U}${$.tool}${G}`}let Q=Z($.queries);if(Q)return j(Q,60);if(typeof $.query==="string"&&$.query.trim().length>0)return j($.query,60);if(typeof $.workflow==="string"&&$.workflow.trim().length>0)return`workflow=${j($.workflow,48)}`;if(typeof $.url==="string"&&$.url.trim().length>0)return j($.url,60);let X=Z($.urls);if(X)return j(X,60);if(typeof $.prompt==="string"&&$.prompt.trim().length>0)return j($.prompt,60);let W=["command","path","file_path","pattern","query","url","task","describe","search"];for(let U of W)if($[U]&&typeof $[U]==="string"){let G=$[U];return j(G,60)}for(let[U,G]of Object.entries($)){let B=Z(G);if(B)return`${U}=${j(B,50)}`;if(typeof G==="string"&&G.length>0){let q=j(G,50);return`${U}=${q}`}}return""}function s$($){if(!$)return"";if(typeof $==="string")return $;if(!Array.isArray($))return"";let j=[];for(let J of $)if(J&&typeof J==="object"){if("type"in J&&J.type==="text"&&"text"in J)j.push(String(J.text));else if("type"in J&&J.type==="tool_result"&&"content"in J){let Z=s$(J.content);if(Z)j.push(Z)}else if("text"in J)j.push(String(J.text))}return j.join(`
20
- `)}var T2=1,E2=52428800;function v1($){return $ instanceof Error?$.message:String($)}function Z0($){return typeof $==="number"&&Number.isFinite($)?$:void 0}function S2($){if(!$||typeof $!=="object")return;let j=$,J=j.cost,Z=J&&typeof J==="object"?Z0(J.total)??0:Z0(J)??0;return{input:Z0(j.input)??Z0(j.inputTokens)??0,output:Z0(j.output)??Z0(j.outputTokens)??0,cacheRead:Z0(j.cacheRead)??0,cacheWrite:Z0(j.cacheWrite)??0,cost:Z}}function D2($){return $.args&&typeof $.args==="object"&&!Array.isArray($.args)?$.args:{}}function YJ($){let j=0,J,Z=!1,Q=$.maxBytes??E2,X=(B)=>{let q=Date.now();return{version:T2,recordType:B,source:$.source,runId:$.runId,agent:$.agent,...$.childIndex!==void 0?{childIndex:$.childIndex}:{},cwd:$.cwd,ts:q,timestamp:new Date(q).toISOString()}},W=()=>{Z=!0;let B=`${JSON.stringify({...X("truncated"),maxBytes:Q,message:`Child transcript exceeded ${Q} bytes; further records were omitted.`})}
21
- `,q=Buffer.byteLength(B,"utf-8");if(j+q>Q)return!1;try{return U0.appendFileSync($.transcriptPath,B,"utf-8"),j+=q,!0}catch(O){return J=`Failed to write child transcript '${$.transcriptPath}': ${v1(O)}`,!1}},U=(B)=>{if(J||Z)return;let q=`${JSON.stringify(B)}
22
- `,O=Buffer.byteLength(q,"utf-8");if(j+O>Q){W();return}let T=`${JSON.stringify({...X("truncated"),maxBytes:Q,message:`Child transcript exceeded ${Q} bytes; further records were omitted.`})}
23
- `;if(j+O+Buffer.byteLength(T,"utf-8")>Q){W();return}try{U0.appendFileSync($.transcriptPath,q,"utf-8"),j+=O}catch(y){J=`Failed to write child transcript '${$.transcriptPath}': ${v1(y)}`}};try{U0.mkdirSync(XJ.dirname($.transcriptPath),{recursive:!0}),U0.writeFileSync($.transcriptPath,"","utf-8")}catch(B){J=`Failed to initialize child transcript '${$.transcriptPath}': ${v1(B)}`}let G=(B,q)=>{let O=s$(q.content);U({...X("message"),sourceEventType:B,role:q.role,...O?{text:O}:{},...q.model?{model:q.model}:{},...q.stopReason?{stopReason:q.stopReason}:{},...q.errorMessage?{errorMessage:q.errorMessage}:{},...q.usage?{usage:S2(q.usage)}:{},message:q})};return{path:$.transcriptPath,writeInitialUserMessage(B){U({...X("message"),sourceEventType:"initial_prompt",role:"user",text:B,message:{role:"user",content:[{type:"text",text:B}]}})},writeChildEvent(B){if((B.type==="message_end"||B.type==="tool_result_end")&&B.message){G(B.type,B.message);return}if(B.type==="tool_execution_start"&&B.toolName){let q=D2(B);U({...X("tool_start"),sourceEventType:B.type,toolName:B.toolName,...Object.keys(q).length>0?{argsPreview:w0(q)}:{}});return}if(B.type==="tool_execution_end")U({...X("tool_end"),sourceEventType:B.type,...B.toolName?{toolName:B.toolName}:{}})},writeStdoutLine(B){if(!B.trim())return;U({...X("stdout"),text:B})},writeStderrLine(B){if(!B.trim())return;U({...X("stderr"),text:B})},writeStderrText(B){for(let q of B.split(/\r?\n/))this.writeStderrLine(q)},getError(){return J}}}import*as z0 from"node:fs";import*as Q0 from"node:path";var b2=process.platform==="win32"?"SIGBREAK":"SIGUSR2",R2="steer-requests",w2="steer-targets";function I0($){return Q0.join($,"control")}function WJ($){return Q0.join(I0($),"interrupt.json")}function HJ($){return Q0.join(I0($),"timeout.json")}function I2($){return Q0.join(I0($),R2)}function y0($,j){return Q0.join(I0($),w2,String(j))}function y2($){return`${String($.ts).padStart(13,"0")}-${Buffer.from($.id).toString("base64url")}.json`}function k2($,j){let J=Q0.join($,y2(j));return D$(J,j),J}function f2($,j={},J={}){let Z=WJ($),Q={...j,ts:j.ts??J.now?.()??Date.now(),type:"interrupt"};return D$(Z,Q),Z}function P2($,j={},J={}){let Z=HJ($),Q={...j,ts:j.ts??J.now?.()??Date.now(),type:"timeout"};return D$(Z,Q),Z}function VJ($,j,J){if(!Number.isInteger(j)||j<0)throw Error("steer child index must be a non-negative integer.");return k2(y0($,j),{...J,targetIndex:j,type:"steer"})}function x2($){if(!$||typeof $!=="object"||Array.isArray($))return;let j=$;if(j.type!=="steer")return;if(typeof j.id!=="string"||!j.id.trim())return;if(typeof j.ts!=="number"||!Number.isFinite(j.ts))return;if(typeof j.message!=="string"||!j.message.trim())return;if(j.targetIndex!==void 0&&(!Number.isInteger(j.targetIndex)||j.targetIndex<0))return;return{type:"steer",id:j.id.trim(),ts:j.ts,message:j.message.trim(),...j.targetIndex!==void 0?{targetIndex:j.targetIndex}:{},...typeof j.source==="string"&&j.source.trim()?{source:j.source}:{}}}function h2($,j=z0){if(!j.existsSync($))return[];let J=[];for(let Z of j.readdirSync($).filter((Q)=>Q.endsWith(".json")).sort()){let Q=Q0.join($,Z),X;try{X=x2(JSON.parse(j.readFileSync(Q,"utf-8")))}catch{X=void 0}try{j.rmSync(Q,{recursive:!0})}catch{continue}if(X)J.push(X)}return J.sort((Z,Q)=>Z.ts-Q.ts||Z.id.localeCompare(Q.id))}function v2($,j=z0){return h2(I2($),j)}function g1($,j=z0){let J=WJ($);if(!j.existsSync(J))return!1;try{j.rmSync(J,{force:!0,recursive:!0})}catch{}return!0}function g2($,j=z0){let J=HJ($);if(!j.existsSync(J))return!1;try{j.rmSync(J,{force:!0,recursive:!0})}catch{}return!0}function KJ($){let j=f2($.asyncDir,$.source?{source:$.source}:{},{now:$.now});if(typeof $.pid==="number"&&$.pid>0)try{($.kill??process.kill)($.pid,$.signal??b2)}catch(J){if(J?.code==="ENOSYS")return;try{z0.rmSync(j,{force:!0})}catch{}throw J}}function m1($){P2($.asyncDir,$.source?{source:$.source}:{},{now:$.now})}function UJ($,j){let J=j.fs??z0,Z=j.timers??{setInterval,clearInterval},Q=I0($);try{J.mkdirSync(Q,{recursive:!0})}catch{}let X=!1,W=()=>{if(X)return;try{if(g2($,J))j.onTimeout?.();if(g1($,J))j.onInterrupt();for(let B of v2($,J))j.onSteer?.(B)}catch{}};W();let U;try{U=J.watch(Q,()=>W()),U.on?.("error",()=>{})}catch{U=void 0}let G=Z.setInterval(W,j.pollIntervalMs??ij);return G.unref?.(),()=>{if(X)return;X=!0;try{U?.close()}catch{}Z.clearInterval(G)}}import*as X0 from"node:fs";import*as G0 from"node:path";function c1($,j,J,Z){let Q=Z!==void 0?`_${Z}`:"",X=J.replace(/[^\w.-]/g,"_"),W=`${j}_${X}${Q}`;return{inputPath:G0.join($,`${W}_input.md`),outputPath:G0.join($,`${W}_output.md`),jsonlPath:G0.join($,`${W}.jsonl`),transcriptPath:G0.join($,`${W}_transcript.jsonl`),metadataPath:G0.join($,`${W}_meta.json`)}}function d1($,j){X0.appendFileSync($,`${j}
24
- `)}import*as Y0 from"node:fs";import*as T$ from"node:path";import{fileURLToPath as m2}from"node:url";var k0="@duckmind/dm-coding-agent",c2="DM_SUBAGENT_PI_BINARY";function o1($){let j=T$.dirname($);while(j!==T$.dirname(j)){let J=T$.join(j,"package.json");if(Y0.existsSync(J)){if(JSON.parse(Y0.readFileSync(J,"utf-8")).name===k0)return j}j=T$.dirname(j)}return}function u1(){return o1(m2(import.meta.resolve(k0)))}function d2(){try{let $=process.argv[1];return $?o1(Y0.realpathSync($)):void 0}catch{return}}function zJ($,j){if(!j($))return!1;return/\.(?:mjs|cjs|js)$/i.test($)}function o2($){return T$.isAbsolute($)?$:T$.resolve($)}function u2($={}){let j=$.existsSync??Y0.existsSync,J=$.readFileSync??((Q,X)=>Y0.readFileSync(Q,X)),Z=$.argv1??process.argv[1];if(Z){let Q=o2(Z);if(zJ(Q,j))return Q}try{let X=($.resolvePackageJson??(()=>{let q=$.piPackageRoot??d2();if(q)return T$.join(q,"package.json");let O=$.resolvePackageEntry?o1($.resolvePackageEntry()):u1();if(!O)throw Error(`Could not resolve ${k0} package root`);return T$.join(O,"package.json")}))(),U=JSON.parse(J(X,"utf-8")).bin,G=typeof U==="string"?U:U?.pi??Object.values(U??{})[0];if(!G)return;let B=T$.resolve(T$.dirname(X),G);if(zJ(B,j))return B}catch{return}return}function GJ($,j={}){let Z=(j.env??process.env)[c2]?.trim();if(Z)return{command:Z,args:$};if((j.platform??process.platform)==="win32"){let X=u2(j);if(X)return{command:j.execPath??process.execPath,args:[X,...$]}}return{command:"dm",args:$}}import*as a$ from"node:fs";import*as f0 from"node:path";function l2($){if(!$)return 0;return($.match(/\r\n|\r|\n/g)?.length??0)+(/[\r\n]$/.test($)?0:1)}function p2($){if($<1024)return`${$} B`;let j=["KB","MB","GB","TB"],J=$/1024,Z=0;while(J>=1024&&Z<j.length-1)J/=1024,Z++;return`${J.toFixed(1)} ${j[Z]}`}function l1($,j){let J=f0.resolve($),Z=Buffer.byteLength(j,"utf-8"),Q=l2(j);return{path:J,bytes:Z,lines:Q,message:`Output saved to: ${J} (${p2(Z)}, ${Q} ${Q===1?"line":"lines"}). Read this file if needed.`}}function BJ($){if(!$)return;try{let j=a$.statSync($);return{exists:!0,mtimeMs:j.mtimeMs,size:j.size}}catch{return{exists:!1}}}function n2($,j){if(!$)return{};try{return a$.mkdirSync(f0.dirname($),{recursive:!0}),a$.writeFileSync($,j,"utf-8"),{savedPath:$}}catch(J){return{error:J instanceof Error?J.message:String(J)}}}function _J($,j,J){if(!$)return{fullOutput:j};let Z=!1;try{let X=a$.statSync($);Z=!J?.exists||X.mtimeMs!==J.mtimeMs||X.size!==J.size}catch(X){let W=X&&typeof X==="object"&&"code"in X?X.code:void 0;if(W!=="ENOENT"&&W!=="ENOTDIR")return{fullOutput:j,saveError:`Failed to inspect output file: ${X instanceof Error?X.message:String(X)}`}}if(Z)try{return{fullOutput:a$.readFileSync($,"utf-8"),savedPath:$}}catch(X){return{fullOutput:j,saveError:`Failed to read changed output file: ${X instanceof Error?X.message:String(X)}`}}let Q=n2($,j);if(Q.savedPath)return{fullOutput:j,savedPath:Q.savedPath};return{fullOutput:j,saveError:Q.error}}function MJ($){let j=$.truncatedOutput||$.fullOutput;if($.exitCode===0&&$.savedPath){let J=$.outputReference??l1($.savedPath,$.fullOutput);if($.outputMode==="file-only")return{displayOutput:J.message,savedPath:$.savedPath,outputReference:J};return j+=`
25
-
26
- ${J.message}`,{displayOutput:j,savedPath:$.savedPath,outputReference:J}}if($.exitCode===0&&$.saveError&&$.outputPath)return j+=`
27
-
28
- Output file error: ${$.outputPath}
29
- ${$.saveError}`,{displayOutput:j,saveError:$.saveError};return{displayOutput:j}}var i2=["event","async","intercom"],r2=["active_long_running","needs_attention"],LJ={enabled:!0,needsAttentionAfterMs:60000,activeNoticeAfterMs:240000,failedToolAttemptsBeforeAttention:3,notifyOn:r2,notifyChannels:i2};function qJ($){if(!$.config.enabled)return;let j=$.now??Date.now(),J=$.lastActivityAt??$.startedAt;return Math.max(0,j-J)>$.config.needsAttentionAfterMs?"needs_attention":void 0}function A0($){let j=$.ts??Date.now(),J=$.type??($.to==="active_long_running"?"active_long_running":"needs_attention"),Z=$.elapsedMs??($.lastActivityAt?Math.max(0,j-$.lastActivityAt):void 0),Q=Z!==void 0?Math.floor(Z/1000):void 0,X=$.message??(J==="active_long_running"?`${$.agent} is still active but long-running`:Q!==void 0?`${$.agent} needs attention (no observed activity for ${Q}s)`:`${$.agent} needs attention`);return{type:J,...$.from?{from:$.from}:{},to:$.to,ts:j,runId:$.runId,agent:$.agent,...$.index!==void 0?{index:$.index}:{},message:X,reason:$.reason??(J==="active_long_running"?"active_long_running":"idle"),...$.turns!==void 0?{turns:$.turns}:{},...$.tokens!==void 0?{tokens:$.tokens}:{},...$.toolCount!==void 0?{toolCount:$.toolCount}:{},...$.currentTool?{currentTool:$.currentTool}:{},...$.currentToolDurationMs!==void 0?{currentToolDurationMs:$.currentToolDurationMs}:{},...$.currentPath?{currentPath:$.currentPath}:{},...Z!==void 0?{elapsedMs:Z}:{},...$.recentFailureSummary?{recentFailureSummary:$.recentFailureSummary}:{}}}function s2($,j){return $.enabled&&$.notifyOn.includes(j.type)}function a2($,j){return`${j??($.index!==void 0?`${$.runId}:${$.index}`:$.runId)}:${$.type}:${$.reason??"idle"}`}function FJ($,j,J,Z){if(!s2($,j))return!1;let Q=a2(j,Z);if(J.has(Q))return!1;return J.add(Q),!0}function t2($){let j=[];if($.elapsedMs!==void 0)j.push(`elapsed ${Math.floor(Math.max(0,$.elapsedMs)/1000)}s`);if($.turns!==void 0)j.push(`${$.turns} turns`);if($.tokens!==void 0)j.push(`${$.tokens} tokens`);if($.toolCount!==void 0)j.push(`${$.toolCount} tools`);if($.currentTool)j.push(`tool ${$.currentTool}${$.currentToolDurationMs!==void 0?` ${Math.floor(Math.max(0,$.currentToolDurationMs)/1000)}s`:""}`);if($.currentPath)j.push(`path ${$.currentPath}`);return j.length>0?j.join(" | "):void 0}function p1($,j){let J=$.runId;if($.reason==="completion_guard")return[`Subagent failed: ${$.agent}`,`Run: ${J}${$.index!==void 0?` step ${$.index+1}`:""}`,`Signal: ${$.message}`,"Next: read the output artifact or session from the subagent result, then retry with a more explicit implementation prompt or handle the fix directly.",j?`Run intercom target (may be inactive): ${j}`:void 0].filter((X)=>Boolean(X)).join(`
30
- `);let Z="What are you blocked on? Reply with the smallest next step or ask for a decision.",Q=`subagent({ action: "resume", id: "${J}", ${$.index!==void 0?`index: ${$.index}, `:""}message: "${Z}" })`;if($.type==="active_long_running"){let X=t2($);return[`Subagent active but long-running: ${$.agent}`,`Run: ${J}${$.index!==void 0?` step ${$.index+1}`:""}`,`Signal: ${$.message}`,X?`Facts: ${X}`:void 0,"Hint: Inspect status, then nudge if the work seems stuck. Live async nudges interrupt the child before sending the follow-up.",`Nudge: ${Q}`,j?`Direct intercom target: ${j}`:void 0,`Status: subagent({ action: "status", id: "${J}" })`,`Interrupt: subagent({ action: "interrupt", id: "${J}" })`].filter((W)=>Boolean(W)).join(`
31
- `)}return[`Subagent needs attention: ${$.agent}`,`Run: ${J}${$.index!==void 0?` step ${$.index+1}`:""}`,`Signal: ${$.message}`,$.recentFailureSummary?`Recent failures: ${$.recentFailureSummary}`:void 0,"Hint: Inspect status first unless the run is clearly blocked. Live async nudges interrupt the child before sending the follow-up.",`Nudge: ${Q}`,j?`Direct intercom target: ${j}`:void 0,`Status: subagent({ action: "status", id: "${J}" })`,`Interrupt: subagent({ action: "interrupt", id: "${J}" })`].filter((X)=>Boolean(X)).join(`
32
- `)}function OJ($,j){return[$.reason==="completion_guard"?"subagent failed":$.type==="active_long_running"?"subagent active but long-running":"subagent needs attention","",$.reason==="completion_guard"?`${$.agent} failed in run ${$.runId}.`:$.type==="active_long_running"?`${$.agent} is still active but long-running in run ${$.runId}.`:`${$.agent} needs attention in run ${$.runId}.`,"",p1($,j)].join(`
33
- `)}import*as b$ from"node:fs";import*as t1 from"node:os";import*as B$ from"node:path";import{fileURLToPath as dJ}from"node:url";import*as CJ from"node:path";var e2=128,$6=4;function n1($){return typeof $==="string"&&$.length>0&&$.length<=e2&&!CJ.isAbsolute($)&&!$.includes("/")&&!$.includes("\\")&&!$.includes("..")}function AJ($){return typeof $==="number"&&Number.isFinite($)?$:void 0}function NJ($,j){return typeof $==="string"&&$.length>0?$.slice(0,j):void 0}function J1($){if(!Array.isArray($))return[];return $.map((j)=>{if(!j||typeof j!=="object")return;let J=j;if(!n1(J.runId))return;return{runId:J.runId,...AJ(J.stepIndex)!==void 0?{stepIndex:AJ(J.stepIndex)}:{},...NJ(J.agent,128)?{agent:NJ(J.agent,128)}:{}}}).filter((j)=>Boolean(j)).slice(0,$6)}function i1($){if(!$)return[];try{return J1(JSON.parse($))}catch{return[]}}function TJ($){let j=J1($);return j.length?JSON.stringify(j):""}import{createHash as j6}from"node:crypto";import*as N0 from"node:fs";import*as m$ from"node:os";import*as O$ from"node:path";var J6=1,Z6=604800000,EJ=new Set(["read","bash","edit","write","grep","find","ls","mcp"]),SJ=O$.join(m$.homedir(),".config","mcp","mcp.json"),RJ={cursor:[O$.join(m$.homedir(),".cursor","mcp.json")],"claude-code":[O$.join(m$.homedir(),".claude","mcp.json"),O$.join(m$.homedir(),".claude.json"),O$.join(m$.homedir(),".claude","claude_desktop_config.json")],"claude-desktop":[O$.join(m$.homedir(),"Library","Application Support","Claude","claude_desktop_config.json")],codex:[O$.join(m$.homedir(),".codex","config.json")],windsurf:[O$.join(m$.homedir(),".windsurf","mcp.json")],vscode:[".vscode/mcp.json"]};function wJ($,j=process.cwd()){if(!$?.length)return[];try{let J=X6(j),Z=Q6();if(!Z)return[];return G6(J,Z,L6(J.settings?.toolPrefix),$)}catch{return[]}}function Q6(){let $=O$.join(L0(),"mcp-cache.json"),j;try{j=JSON.parse(N0.readFileSync($,"utf-8"))}catch{return null}if(!j||typeof j!=="object")return null;let J=j;if(J.version!==J6||!J.servers||typeof J.servers!=="object"||Array.isArray(J.servers))return null;return J}function X6($){let j={mcpServers:{}};for(let J of Y6($)){let Z=W6(J);if(!Z)continue;j=V6(j,K6(Z,$))}return j}function Y6($){let j=O$.join(L0(),"mcp.json"),J=O$.resolve($,".mcp.json"),Z=O$.resolve(w1($),"mcp.json"),Q=[];if(SJ!==j)Q.push(SJ);if(Q.push(j),J!==j)Q.push(J);if(Z!==j&&Z!==J)Q.push(Z);return Q}function W6($){let j;try{j=JSON.parse(N0.readFileSync($,"utf-8"))}catch{return null}return H6(j)}function H6($){if(!$||typeof $!=="object"||Array.isArray($))return{mcpServers:{}};let j=$,J=j.mcpServers??j["mcp-servers"]??{};return{mcpServers:J&&typeof J==="object"&&!Array.isArray(J)?J:{},imports:Array.isArray(j.imports)?j.imports.filter((Z)=>q6(Z)):void 0,settings:j.settings&&typeof j.settings==="object"&&!Array.isArray(j.settings)?j.settings:void 0}}function V6($,j){let J=[...$.imports??[],...j.imports??[]];return{mcpServers:{...$.mcpServers,...j.mcpServers},imports:J.length?[...new Set(J)]:void 0,settings:j.settings?{...$.settings,...j.settings}:$.settings}}function K6($,j){if(!$.imports?.length)return $;let J={};for(let Z of $.imports){let Q=U6(Z,j);if(!Q)continue;let X;try{X=JSON.parse(N0.readFileSync(Q,"utf-8"))}catch{continue}for(let[W,U]of Object.entries(z6(X,Z)))if(!J[W])J[W]=U}return{imports:$.imports,settings:$.settings,mcpServers:{...J,...$.mcpServers}}}function U6($,j){for(let J of RJ[$]){let Z=J.startsWith(".")?O$.resolve(j,J):J;if(N0.existsSync(Z))return Z}return null}function z6($,j){if(!$||typeof $!=="object"||Array.isArray($))return{};let J=$,Z=j==="cursor"||j==="windsurf"||j==="vscode"?J.mcpServers??J["mcp-servers"]:J.mcpServers;return Z&&typeof Z==="object"&&!Array.isArray(Z)?Z:{}}function G6($,j,J,Z){let Q=[],X=new Set,{servers:W,tools:U}=B6(Z);for(let[G,B]of Object.entries($.mcpServers)){let q=j.servers[G];if(!_6(q,B))continue;let O=W.has(G)?!0:U.get(G);if(!O)continue;for(let T of Array.isArray(q.tools)?q.tools:[]){if(typeof T?.name!=="string"||!T.name)continue;if(O!==!0&&!O.has(T.name))continue;if(DJ(T.name,G,J,B.excludeTools))continue;let y=x0(T.name,G,J);if(EJ.has(y)||X.has(y))continue;X.add(y),Q.push(y)}if(B.exposeResources===!1)continue;for(let T of Array.isArray(q.resources)?q.resources:[]){if(typeof T?.name!=="string"||!T.name||typeof T.uri!=="string"||!T.uri)continue;let y=`get_${O6(T.name)}`;if(O!==!0&&!O.has(y))continue;if(DJ(y,G,J,B.excludeTools))continue;let h=x0(y,G,J);if(EJ.has(h)||X.has(h))continue;X.add(h),Q.push(h)}}return Q}function B6($){let j=new Set,J=new Map;for(let Z of $)if(Z=Z.replace(/\/+$/,""),Z.includes("/")){let[Q,X]=Z.split("/",2);if(Q&&X){if(!J.has(Q))J.set(Q,new Set);J.get(Q).add(X)}else if(Q)j.add(Q)}else if(Z)j.add(Z);return{servers:j,tools:J}}function _6($,j){if(!$||$.configHash!==M6(j))return!1;if(!$.cachedAt||typeof $.cachedAt!=="number")return!1;return Date.now()-$.cachedAt<=Z6}function M6($){let j={command:$.command,args:$.args,env:bJ($.env),cwd:A6($.cwd),url:$.url,headers:bJ($.headers),auth:$.auth,bearerToken:N6($),bearerTokenEnv:$.bearerTokenEnv,exposeResources:$.exposeResources,excludeTools:$.excludeTools};return j6("sha256").update(r1(j)).digest("hex")}function L6($){return $==="none"||$==="short"||$==="server"?$:"server"}function q6($){return typeof $==="string"&&Object.hasOwn(RJ,$)}function F6($,j){if(j==="none")return"";if(j==="short")return $.replace(/-?mcp$/i,"").replace(/-/g,"_")||"mcp";return $.replace(/-/g,"_")}function x0($,j,J){let Z=F6(j,J);return Z?`${Z}_${$}`:$}function DJ($,j,J,Z){if(!Array.isArray(Z)||Z.length===0)return!1;let Q=new Set([P0($),P0(x0($,j,J)),P0(x0($,j,"server")),P0(x0($,j,"short"))]);return Z.some((X)=>typeof X==="string"&&Q.has(P0(X)))}function P0($){return $.replace(/-/g,"_")}function O6($){let j=$.replace(/[^a-zA-Z0-9]/g,"_").replace(/_+/g,"_").replace(/^_+/,"").replace(/_+$/,"").toLowerCase();if(!j||/^\d/.test(j))j=`resource${j?`_${j}`:""}`;return j}function bJ($){if(!$||typeof $!=="object"||Array.isArray($))return;let j={};for(let[J,Z]of Object.entries($))if(typeof Z==="string")j[J]=s1(Z);return j}function s1($){return $.replace(/\$\{(\w+)\}/g,(j,J)=>process.env[J]??"").replace(/\$env:(\w+)/g,(j,J)=>process.env[J]??"")}function A6($){if(typeof $!=="string")return;let j=s1($);if(j==="~")return m$.homedir();if(j.startsWith("~/")||j.startsWith("~\\"))return O$.join(m$.homedir(),j.slice(2));return j}function N6($){if(typeof $.bearerToken==="string")return s1($.bearerToken);return typeof $.bearerTokenEnv==="string"?process.env[$.bearerTokenEnv]:void 0}function r1($){if($===null||$===void 0||typeof $!=="object"){let J=JSON.stringify($);return J===void 0?"undefined":J}if(Array.isArray($))return`[${$.map((J)=>r1(J)).join(",")}]`;let j=$;return`{${Object.keys(j).sort().map((J)=>`${JSON.stringify(J)}:${r1(j[J])}`).join(",")}}`}import*as c$ from"node:fs";import*as IJ from"node:os";import*as h0 from"node:path";import{Compile as C6}from"typebox/compile";var yJ="DM_SUBAGENT_STRUCTURED_OUTPUT_SCHEMA",kJ="DM_SUBAGENT_STRUCTURED_OUTPUT_CAPTURE";function T6($,j="outputSchema"){if(!$||typeof $!=="object"||Array.isArray($))throw Error(`${j} must be a JSON Schema object.`)}function fJ($,j){T6($);let J=j??IJ.tmpdir();c$.mkdirSync(J,{recursive:!0});let Z=c$.mkdtempSync(h0.join(J,"dm-subagent-structured-")),Q=h0.join(Z,"schema.json"),X=h0.join(Z,"output.json");return c$.writeFileSync(Q,JSON.stringify($),{mode:384}),{schema:$,schemaPath:Q,outputPath:X}}function a1($,j){let J;try{J=C6($)}catch(Q){return{status:"invalid",message:`invalid outputSchema: ${Q instanceof Error?Q.message:String(Q)}`}}if(J.Check(j))return{status:"valid"};return{status:"invalid",message:[...J.Errors(j)].slice(0,8).map((Q)=>{return`${Q.instancePath?Q.instancePath.replace(/^\//,"").replace(/\//g,"."):"root"}: ${Q.message}`}).join("; ")||"schema validation failed"}}function PJ($){if(!c$.existsSync($.outputPath))return{error:"Missing structured_output call; this step has outputSchema and must finish by calling structured_output."};let j;try{j=JSON.parse(c$.readFileSync($.outputPath,"utf-8"))}catch(Z){return{error:`Failed to read structured output: ${Z instanceof Error?Z.message:String(Z)}`}}let J=a1($.schema,j);if(J.status==="invalid")return{error:`Structured output validation failed: ${J.message}`};return{value:j}}var xJ="DM_SUBAGENT_TOOL_BUDGET";function C0($){return{...$,toolCount:0,outcome:"within-budget"}}function Z1($,j,J){let Z=j>$.hard,Q=$.soft!==void 0&&j>=$.soft;return{...$,toolCount:j,outcome:Z?"hard-blocked":Q?"soft-reached":"within-budget",...Q?{softReachedAt:$.soft}:{},...Z?{hardReachedAt:$.hard,blockedTool:J}:{}}}function hJ($){return $?JSON.stringify($):void 0}var E6=["off","minimal","low","medium","high","xhigh"],S6=8000;function oJ($,j){let J=dJ($),Z=B$.extname(J),Q=[".js",".mjs",".cjs",".ts",".mts",".cts"].includes(Z)?Z:".ts";return B$.join(B$.dirname(J),`${j}${Q}`)}function uJ($){return B$.basename(dJ($)).startsWith("dm-args.")}function D6($=import.meta.url){let j=uJ($)?"subagent-prompt-runtime":B$.join("..","runs","shared","subagent-prompt-runtime");return oJ($,j)}function b6($=import.meta.url){let j=uJ($)?B$.join("..","..","extension","fanout-child"):"fanout-child";return oJ($,j)}var vJ=D6(),R6=b6(),w6="DM_SUBAGENT_CHILD",I6="DM_SUBAGENT_ORCHESTRATOR_TARGET",y6="DM_SUBAGENT_ORCHESTRATOR_SESSION_ID",k6="DM_SUBAGENT_SUPERVISOR_CHANNEL_DIR",gJ="DM_SUBAGENT_RUN_ID",f6="DM_SUBAGENT_CHILD_AGENT",P6="DM_SUBAGENT_CHILD_INDEX",x6="DM_SUBAGENT_FANOUT_CHILD",Q1="DM_SUBAGENT_PARENT_EVENT_SINK",e1="DM_SUBAGENT_PARENT_CONTROL_INBOX",X1="DM_SUBAGENT_PARENT_ROOT_RUN_ID",$j="DM_SUBAGENT_PARENT_RUN_ID",jj="DM_SUBAGENT_PARENT_CHILD_INDEX",Jj="DM_SUBAGENT_PARENT_DEPTH",Zj="DM_SUBAGENT_PARENT_PATH",Y1="DM_SUBAGENT_PARENT_CAPABILITY_TOKEN",mJ="DM_SUBAGENT_PARENT_SESSION",h6="DM_SUBAGENT_STEER_INBOX";function cJ($){return $.trim().replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}function v6($,j,J){return B$.join(r$,"supervisor-channels",`${cJ($)}-${cJ(j)}-${J}`)}function W1($,j,J=!1){if(!$||!j)return $;let Z=$.lastIndexOf(":");if(Z!==-1&&E6.includes($.substring(Z+1)))return J?`${$.slice(0,Z)}:${j}`:$;return`${$}:${j}`}function lJ($){let j=[...$.baseArgs];if($.sessionFile)b$.mkdirSync(B$.dirname($.sessionFile),{recursive:!0}),j.push("--session",$.sessionFile);else{if(!$.sessionEnabled)j.push("--no-session");if($.sessionDir)b$.mkdirSync($.sessionDir,{recursive:!0}),j.push("--session-dir",$.sessionDir)}let J=W1($.model,$.thinking);if(J)j.push("--model",J);let Z=$.tools?.filter((k)=>!(k.includes("/")||k.endsWith(".ts")||k.endsWith(".js")))??[],Q=$.requireReadTool&&$.tools?.length&&!Z.includes("read")?["read",...Z]:Z,X=Q.includes("subagent"),W=[];if($.tools?.length){let k=[...Q];for(let f of $.tools)if(!Q.includes(f)&&(f.includes("/")||f.endsWith(".ts")||f.endsWith(".js")))W.push(f);if(k.length>0){if($.mcpDirectTools?.length)k.push(...wJ($.mcpDirectTools,$.cwd));j.push("--tools",k.join(","))}}let U=X?[vJ,R6]:[vJ];if($.extensions!==void 0){j.push("--no-extensions");for(let k of[...new Set([...U,...W,...$.extensions,...$.subagentOnlyExtensions??[]])])j.push("--extension",k)}else for(let k of[...new Set([...U,...W,...$.subagentOnlyExtensions??[]])])j.push("--extension",k);if(!$.inheritSkills)j.push("--no-skills");let G;if($.systemPrompt!==void 0&&$.systemPrompt!==null){G=b$.mkdtempSync(B$.join(t1.tmpdir(),"dm-subagent-"));let k=($.promptFileStem??"prompt").replace(/[^\w.-]/g,"_"),f=B$.join(G,`${k}.md`);b$.writeFileSync(f,$.systemPrompt,{mode:384}),j.push($.systemPromptMode==="replace"?"--system-prompt":"--append-system-prompt",f)}if($.task.length>S6){if(!G)G=b$.mkdtempSync(B$.join(t1.tmpdir(),"dm-subagent-"));let k=B$.join(G,"task.md");b$.writeFileSync(k,`Task: ${$.task}`,{mode:384}),j.push(`@${k}`)}else j.push(`Task: ${$.task}`);let B={};B[w6]="1",B[x6]=X?"1":"0";let q=Boolean(process.env[Q1]&&process.env[X1]&&process.env[Y1]),O=$.parentRunId??$.runId??(q?process.env[gJ]:void 0)??process.env[$j]??"",T=$.parentChildIndex!==void 0?String($.parentChildIndex):$.childIndex!==void 0?String($.childIndex):process.env[jj]??"",y=Number(process.env[Jj]),h=$.parentDepth??(q&&Number.isFinite(y)?y+1:1),S=$.parentPath??[...i1(process.env[Zj]),...O?[{runId:O,...T&&/^\d+$/.test(T)?{stepIndex:Number(T)}:{},...$.childAgentName?{agent:$.childAgentName}:{}}]:[]];if(B[Q1]=X?$.parentEventSink??process.env[Q1]??"":"",B[e1]=X?$.parentControlInbox??process.env[e1]??"":"",B[X1]=X?$.parentRootRunId??process.env[X1]??$.runId??"":"",B[$j]=X?O:"",B[jj]=X?T:"",B[Jj]=X?String(h):"",B[Zj]=X?TJ(S):"",B[Y1]=X?$.parentCapabilityToken??process.env[Y1]??"":"",B.DM_SUBAGENT_INHERIT_PROJECT_CONTEXT=$.inheritProjectContext?"1":"0",B.DM_SUBAGENT_INHERIT_SKILLS=$.inheritSkills?"1":"0",$.intercomSessionName)B.DM_SUBAGENT_INTERCOM_SESSION_NAME=$.intercomSessionName;if($.orchestratorIntercomTarget)B[I6]=$.orchestratorIntercomTarget;if($.parentSessionId)B[y6]=$.parentSessionId;if($.orchestratorIntercomTarget&&$.parentSessionId&&$.runId&&$.childAgentName){let k=$.childIndex??0,f=v6($.runId,$.childAgentName,k);b$.mkdirSync(B$.join(f,"requests"),{recursive:!0}),b$.mkdirSync(B$.join(f,"replies"),{recursive:!0}),B[k6]=f}if($.runId)B[gJ]=$.runId;if($.childAgentName)B[f6]=$.childAgentName;if($.childIndex!==void 0)B[P6]=String($.childIndex);if($.mcpDirectTools?.length)B.MCP_DIRECT_TOOLS=$.mcpDirectTools.join(",");else B.MCP_DIRECT_TOOLS="__none__";if($.structuredOutput)B[kJ]=$.structuredOutput.outputPath,B[yJ]=$.structuredOutput.schemaPath;if($.steerInboxDir)B[h6]=$.steerInboxDir;let v$=hJ($.toolBudget);if(v$)B[xJ]=v$;return B[mJ]=$.parentSessionId??process.env[mJ]??"",{args:j,env:B,tempDir:G}}function pJ($){if(!$)return;try{b$.rmSync($,{recursive:!0,force:!0})}catch{}}class x extends Error{}var g6=/^[A-Za-z_][A-Za-z0-9_]*$/,m6=/^[A-Za-z_][A-Za-z0-9_]*$/,g0=/\{([A-Za-z_][A-Za-z0-9_]*)(?:\.([^{}]+))?\}/g,c6=new Set(["task","previous","chain_dir","outputs"]),rJ=new Set(["expand","parallel","collect","concurrency","failFast","phase","label","acceptance"]),d6=new Set([...rJ,"effectiveAcceptance","sessionFiles","thinkingOverrides"]),o6=new Set(["from","item","key","maxItems","onEmpty"]),u6=new Set(["output","path"]),sJ=new Set(["agent","task","phase","label","outputSchema","cwd","output","outputMode","reads","progress","skill","model","toolBudget","acceptance"]),l6=new Set([...sJ,"outputName","structured","inheritProjectContext","inheritSkills","skills","outputPath","maxSubagentDepth","structuredOutput","structuredOutputSchema","tools","extensions","subagentOnlyExtensions","mcpDirectTools","completionGuard","systemPrompt","systemPromptMode","thinking","modelCandidates","sessionFile","effectiveAcceptance","parentSessionId"]),p6=new Set(["as","outputSchema"]);function nJ($){return g6.test($)}function Qj($,j){if($==="")return;if(!$.startsWith("/"))throw new x(`${j} must be a JSON Pointer starting with '/'.`);for(let J of $.slice(1).split("/"))if(/~(?![01])/.test(J))throw new x(`${j} contains invalid JSON Pointer escape.`)}function n6($){return $.replace(/~1/g,"/").replace(/~0/g,"~")}function Xj($,j,J){if(Qj(j,J),j==="")return $;let Z=$;for(let Q of j.slice(1).split("/")){let X=n6(Q);if(Array.isArray(Z)){if(!/^(0|[1-9][0-9]*)$/.test(X))throw new x(`${J} segment '${X}' does not address an array index.`);let U=Number(X);if(U>=Z.length)throw new x(`${J} does not exist.`);Z=Z[U];continue}if(!Z||typeof Z!=="object")throw new x(`${J} does not exist.`);let W=Z;if(!Object.prototype.hasOwnProperty.call(W,X))throw new x(`${J} does not exist.`);Z=W[X]}return Z}function i6($,j){if(typeof $==="string"||typeof $==="number"||typeof $==="boolean"){let J=String($);if(!J.trim())throw new x(`${j} resolved to an empty key.`);if(/[\u0000-\u001F\u007F]/.test(J))throw new x(`${j} resolved to an unsafe key.`);if(J.length>200)throw new x(`${j} resolved to a key longer than 200 characters.`);return J}throw new x(`${j} must resolve to a string, number, or boolean.`)}function r6($){return $.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"item"}function s6($,j){if($===void 0)throw new x(`Unresolved item reference '${j}'.`);if(typeof $==="string")return $;if(typeof $==="number"||typeof $==="boolean"||$===null)return String($);return JSON.stringify($)}function a6($,j,J){if(!j)return $;let Z=`/${j.split(".").map((Q)=>Q.replace(/~/g,"~0").replace(/\//g,"~1")).join("/")}`;return Xj($,Z,J)}function iJ($,j,J){return $.replace(g0,(Z,Q,X)=>{if(Q!==j)return Z;if(X!==void 0&&(!X.trim()||X.includes("..")))throw new x(`Invalid item reference '${Z}'.`);return s6(a6(J,X,Z),Z)})}function v0($,j,J){if(!$||typeof $!=="object"||Array.isArray($))throw new x(`${J} must be an object.`);for(let Z of Object.keys($))if(!j.has(Z))throw new x(`${J} does not support field '${Z}'.`)}function t6($,j,J){for(let Z of $.matchAll(/\{([^{}]*)\}/g)){let Q=Z[0],X=Z[1];if(X===j||X.startsWith(`${j}.`)){if(!g0.test(Q)||X===`${j}.`||X.includes(".."))throw new x(`Invalid item reference '${Q}' in ${J}.`);g0.lastIndex=0;continue}g0.lastIndex=0;let W=X.match(/^[A-Za-z_][A-Za-z0-9_]*/)?.[0];if(W===j)throw new x(`Invalid item reference '${Q}' in ${J}.`);if(W&&c6.has(W))continue;if(W)throw new x(`Unsupported template reference '${Q}' in ${J}.`)}if(g0.lastIndex=0,$.includes(`{${j}.}`)||new RegExp(`\\{${j}(?:\\.|$)[^}]*$`).test($))throw new x(`Invalid item reference in ${J}.`)}function aJ($,j,J={}){let Z=`Dynamic chain step ${j+1}`;if(v0($,J.allowRunnerFields?d6:rJ,Z),!$.expand||!$.expand.from)throw new x(`${Z} requires expand.from.`);if(v0($.expand,o6,`${Z} expand`),v0($.expand.from,u6,`${Z} expand.from`),!nJ($.expand.from.output))throw new x(`${Z} has invalid expand.from.output '${$.expand.from.output}'.`);if(Qj($.expand.from.path,`${Z} expand.from.path`),$.expand.key!==void 0)Qj($.expand.key,`${Z} expand.key`);let Q=$.expand.item??"item";if(!m6.test(Q))throw new x(`${Z} has invalid expand.item '${Q}'.`);if($.expand.maxItems===void 0&&J.maxItems===void 0)throw new x(`${Z} requires expand.maxItems or config.chain.dynamicFanout.maxItems.`);if($.expand.maxItems!==void 0&&(!Number.isInteger($.expand.maxItems)||$.expand.maxItems<0))throw new x(`${Z} expand.maxItems must be an integer >= 0.`);if(J.maxItems!==void 0&&(!Number.isInteger(J.maxItems)||J.maxItems<0))throw new x("config.chain.dynamicFanout.maxItems must be an integer >= 0.");if(!$.parallel||Array.isArray($.parallel))throw new x(`${Z} requires a single parallel template object and cannot mix dynamic expand/collect with static parallel arrays.`);if(v0($.parallel,J.allowRunnerFields?l6:sJ,`${Z} parallel`),"expand"in $.parallel)throw new x(`${Z} does not support nested dynamic fanout.`);if(!$.parallel.agent)throw new x(`${Z} parallel.agent is required.`);if(!$.collect?.as||!nJ($.collect.as))throw new x(`${Z} requires collect.as with a safe output name.`);v0($.collect,p6,`${Z} collect`);for(let[X,W]of[["parallel.task",$.parallel.task],["parallel.label",$.parallel.label]])if(W)t6(W,Q,`${Z} ${X}`)}function e6($,j,J,Z={}){aJ($,J,Z);let Q=$.expand.from.output,X=j[Q];if(!X)throw new x(`Dynamic chain step ${J+1} references unknown output '${Q}'.`);if(X.structured===void 0)throw new x(`Dynamic chain step ${J+1} requires structured output '${Q}'.`);let W=Xj(X.structured,$.expand.from.path,`Dynamic chain step ${J+1} expand.from.path`);if(!Array.isArray(W))throw new x(`Dynamic chain step ${J+1} expand.from.path must resolve to an array.`);let U=$.expand.maxItems??Z.maxItems;if(U===void 0)throw new x(`Dynamic chain step ${J+1} requires an effective maxItems.`);if(W.length>U)throw new x(`Dynamic chain step ${J+1} resolved ${W.length} items, exceeding maxItems ${U}.`);let G=new Set,B=new Set;return W.map((q,O)=>{let T=$.expand.key===void 0?String(O):i6(Xj(q,$.expand.key,`Dynamic chain step ${J+1} expand.key`),`Dynamic chain step ${J+1} expand.key`);if(G.has(T))throw new x(`Dynamic chain step ${J+1} produced duplicate item key '${T}'.`);G.add(T);let y=r6(T);if(B.has(y))throw new x(`Dynamic chain step ${J+1} produced colliding item id '${y}'.`);return B.add(y),{index:O,key:T,idKey:y,item:q}})}function tJ($,j,J,Z={}){let Q=e6($,j,J,Z);if(Q.length===0){if(($.expand.onEmpty??"skip")==="fail")throw new x(`Dynamic chain step ${J+1} source array is empty.`);return{items:Q,parallel:[],collectedOnEmpty:[]}}let X=$.expand.item??"item",W=Q.map((U)=>{let G=iJ($.parallel.task??"{previous}",X,U.item),B=$.parallel.label?iJ($.parallel.label,X,U.item):void 0;return{...$.parallel,task:G,...B!==void 0?{label:B}:{}}});return{items:Q,parallel:W}}function eJ($,j,J){return j.map((Z,Q)=>{let X=J[Q],W=X?"output"in X&&typeof X.output==="string"?X.output:h1(X):"";return{key:Z.key,index:Z.index,item:Z.item,agent:X?.agent??$.parallel.agent,exitCode:X?.exitCode??null,text:W,...X?.structuredOutput!==void 0?{structured:X.structuredOutput}:{},...X?.error?{error:X.error}:{},...X?.timedOut?{timedOut:!0}:{},...X?.savedOutputPath?{outputPath:X.savedOutputPath}:{},...X?.artifactPaths?{artifactPaths:X.artifactPaths}:{}}})}function Yj($,j){if(!$)return;let J=a1($,j);if(J.status==="invalid")throw new x(`Collected output validation failed: ${J.message}`)}var $4=/\{outputs\.([^}]*)\}/g,j4=/^[A-Za-z_][A-Za-z0-9_]*$/;class Wj extends Error{}function $8($,j){return $.replace($4,(J,Z)=>{if(!j4.test(Z))throw new Wj(`Invalid chain output reference '${J}'. Use {outputs.name} with /^[A-Za-z_][A-Za-z0-9_]*$/ names.`);let Q=j[Z];if(!Q)throw new Wj(`Unknown chain output reference '${J}'.`);return Q.text})}function J4($){return JSON.stringify($)}function Hj($,j){return{text:$.structuredOutput!==void 0?J4($.structuredOutput):$.output,...$.structuredOutput!==void 0?{structured:$.structuredOutput}:{},agent:$.agent,stepIndex:j}}import{randomUUID as Z4}from"node:crypto";import*as R$ from"node:fs";import*as Q$ from"node:path";var j8=Q$.join(r$,"nested-subagent-events");var Q4="registry.json",Gj=65536,Vj=12,V1=16,Kj=3;function K1($){return n1($)}function X4($,j){if(!K1(j))throw Error(`${$} must be a non-empty safe id token.`)}function J8($,j){X4($,j)}function Uj($,j){let J=Q$.resolve($),Z=Q$.resolve(j);return Z===J||Z.startsWith(`${J}${Q$.sep}`)}function Q8($){return Q$.dirname(Q$.resolve($.eventSink))}function Bj($){if(J8("rootRunId",$.rootRunId),J8("capabilityToken",$.capabilityToken),!Uj(j8,$.eventSink))throw Error("Nested event sink is outside the subagent nested event root.");if(!Uj(j8,$.controlInbox))throw Error("Nested control inbox is outside the subagent nested event root.");if(Q8($)!==Q$.dirname(Q$.resolve($.controlInbox)))throw Error("Nested event sink and control inbox must share one route root.")}function _j($,j){if(!j.asyncDir)return;let J=Q$.resolve(j.asyncDir),Z=Q$.resolve(r$,"nested-subagent-runs",$,j.id),Q=Q$.relative(Z,J);return J===Z||!Q.startsWith("..")&&!Q$.isAbsolute(Q)?J:void 0}function b($){return typeof $==="number"&&Number.isFinite($)?$:void 0}function m($,j=512){return typeof $==="string"&&$.length>0?$.slice(0,j):void 0}function Y4($){if(!$||typeof $!=="object")return;let j=$,J=b(j.input),Z=b(j.output),Q=b(j.total);return J!==void 0&&Z!==void 0&&Q!==void 0?{input:J,output:Z,total:Q}:void 0}function W4($){if(!$||typeof $!=="object")return;let j=$,J=b(j.inputTokens),Z=b(j.outputTokens),Q=b(j.costUsd);return J!==void 0&&Z!==void 0&&Q!==void 0?{inputTokens:J,outputTokens:Z,costUsd:Q}:void 0}function U1($){if(!$||typeof $!=="object")return;let j=$,J=b(j.maxTurns),Z=b(j.graceTurns),Q=b(j.turnCount),X=j.outcome==="within-budget"||j.outcome==="wrap-up-requested"||j.outcome==="exceeded"?j.outcome:void 0;if(J===void 0||Z===void 0||Q===void 0||!X)return;return{maxTurns:J,graceTurns:Z,turnCount:Q,outcome:X,...b(j.wrapUpRequestedAtTurn)!==void 0?{wrapUpRequestedAtTurn:b(j.wrapUpRequestedAtTurn)}:{},...b(j.exceededAtTurn)!==void 0?{exceededAtTurn:b(j.exceededAtTurn)}:{}}}function H4($,j){return $==="queued"||$==="running"||$==="complete"||$==="failed"||$==="paused"?$:j}function V4($,j){if(!$||typeof $!=="object")return;let J=$,Z=m(J.agent,128);if(!Z)return;let Q=J.status==="pending"||J.status==="running"||J.status==="complete"||J.status==="completed"||J.status==="failed"||J.status==="paused"?J.status:"pending";return{agent:Z,status:Q,...m(J.sessionFile,2048)?{sessionFile:m(J.sessionFile,2048)}:{},...J.activityState==="active_long_running"||J.activityState==="needs_attention"?{activityState:J.activityState}:{},...b(J.lastActivityAt)!==void 0?{lastActivityAt:b(J.lastActivityAt)}:{},...m(J.currentTool,128)?{currentTool:m(J.currentTool,128)}:{},...b(J.currentToolStartedAt)!==void 0?{currentToolStartedAt:b(J.currentToolStartedAt)}:{},...m(J.currentPath,2048)?{currentPath:m(J.currentPath,2048)}:{},...b(J.turnCount)!==void 0?{turnCount:b(J.turnCount)}:{},...b(J.toolCount)!==void 0?{toolCount:b(J.toolCount)}:{},...b(J.startedAt)!==void 0?{startedAt:b(J.startedAt)}:{},...b(J.endedAt)!==void 0?{endedAt:b(J.endedAt)}:{},...m(J.error,1024)?{error:m(J.error,1024)}:{},...J.timedOut===!0?{timedOut:!0}:{},...U1(J.turnBudget)?{turnBudget:U1(J.turnBudget)}:{},...J.turnBudgetExceeded===!0?{turnBudgetExceeded:!0}:{},...J.wrapUpRequested===!0?{wrapUpRequested:!0}:{},...j<Kj&&Array.isArray(J.children)?{children:J.children.map((X)=>z1(X,j+1)).filter((X)=>Boolean(X)).slice(0,V1)}:{}}}function z1($,j=0){if(!$||typeof $!=="object")return;let J=$;if(!K1(J.id)||!K1(J.parentRunId))return;let Z=J1(J.path),Q=Array.isArray(J.steps)?J.steps.map((U)=>V4(U,j+1)).filter((U)=>Boolean(U)).slice(0,Vj):void 0,X=Y4(J.totalTokens),W=W4(J.totalCost);return{id:J.id,parentRunId:J.parentRunId,...b(J.parentStepIndex)!==void 0?{parentStepIndex:b(J.parentStepIndex)}:{},...m(J.parentAgent,128)?{parentAgent:m(J.parentAgent,128)}:{},depth:Math.min(Math.max(0,b(J.depth)??0),Kj),path:Z,state:H4(J.state,"running"),...m(J.asyncDir,2048)?{asyncDir:m(J.asyncDir,2048)}:{},...b(J.pid)!==void 0&&b(J.pid)>0&&Number.isInteger(b(J.pid))?{pid:b(J.pid)}:{},...m(J.sessionId,256)?{sessionId:m(J.sessionId,256)}:{},...m(J.sessionFile,2048)?{sessionFile:m(J.sessionFile,2048)}:{},...m(J.intercomTarget,256)?{intercomTarget:m(J.intercomTarget,256)}:{},...m(J.ownerIntercomTarget,256)?{ownerIntercomTarget:m(J.ownerIntercomTarget,256)}:{},...m(J.leafIntercomTarget,256)?{leafIntercomTarget:m(J.leafIntercomTarget,256)}:{},...J.ownerState==="live"||J.ownerState==="gone"||J.ownerState==="unknown"?{ownerState:J.ownerState}:{},...m(J.controlInbox,2048)?{controlInbox:m(J.controlInbox,2048)}:{},...m(J.capabilityToken,128)?{capabilityToken:m(J.capabilityToken,128)}:{},...J.mode==="single"||J.mode==="parallel"||J.mode==="chain"?{mode:J.mode}:{},...m(J.agent,128)?{agent:m(J.agent,128)}:{},...Array.isArray(J.agents)?{agents:J.agents.map((U)=>m(U,128)).filter((U)=>Boolean(U)).slice(0,Vj)}:{},...b(J.currentStep)!==void 0?{currentStep:b(J.currentStep)}:{},...b(J.chainStepCount)!==void 0?{chainStepCount:b(J.chainStepCount)}:{},...J.activityState==="active_long_running"||J.activityState==="needs_attention"?{activityState:J.activityState}:{},...b(J.lastActivityAt)!==void 0?{lastActivityAt:b(J.lastActivityAt)}:{},...m(J.currentTool,128)?{currentTool:m(J.currentTool,128)}:{},...b(J.currentToolStartedAt)!==void 0?{currentToolStartedAt:b(J.currentToolStartedAt)}:{},...m(J.currentPath,2048)?{currentPath:m(J.currentPath,2048)}:{},...b(J.turnCount)!==void 0?{turnCount:b(J.turnCount)}:{},...b(J.toolCount)!==void 0?{toolCount:b(J.toolCount)}:{},...X?{totalTokens:X}:{},...W?{totalCost:W}:{},...b(J.startedAt)!==void 0?{startedAt:b(J.startedAt)}:{},...b(J.endedAt)!==void 0?{endedAt:b(J.endedAt)}:{},...b(J.lastUpdate)!==void 0?{lastUpdate:b(J.lastUpdate)}:{},...b(J.timeoutMs)!==void 0?{timeoutMs:b(J.timeoutMs)}:{},...b(J.deadlineAt)!==void 0?{deadlineAt:b(J.deadlineAt)}:{},...J.timedOut===!0?{timedOut:!0}:{},...U1(J.turnBudget)?{turnBudget:U1(J.turnBudget)}:{},...J.turnBudgetExceeded===!0?{turnBudgetExceeded:!0}:{},...J.wrapUpRequested===!0?{wrapUpRequested:!0}:{},...m(J.error,1024)?{error:m(J.error,1024)}:{},...Q&&Q.length>0?{steps:Q}:{},...j<Kj&&Array.isArray(J.children)?{children:J.children.map((U)=>z1(U,j+1)).filter((U)=>Boolean(U)).slice(0,V1)}:{}}}function zj($,j){if(Buffer.byteLength($,"utf-8")>Gj)return;let J;try{J=JSON.parse($)}catch{return}if(!J||typeof J!=="object")return;let Z=J;if(Z.type!=="subagent.nested.started"&&Z.type!=="subagent.nested.updated"&&Z.type!=="subagent.nested.completed")return;if(Z.rootRunId!==j.rootRunId||Z.capabilityToken!==j.capabilityToken)return;if(!K1(Z.parentRunId))return;let Q=b(Z.ts);if(Q===void 0)return;let X=z1(Z.child);if(!X||X.id===j.rootRunId)return;let W={...X,controlInbox:j.controlInbox,capabilityToken:j.capabilityToken,ownerState:X.ownerState??"unknown"};return{type:Z.type,ts:Q,rootRunId:j.rootRunId,parentRunId:Z.parentRunId,...b(Z.parentStepIndex)!==void 0?{parentStepIndex:b(Z.parentStepIndex)}:{},capabilityToken:j.capabilityToken,child:W}}function K4($,j){if(!$.includes(`
34
- `)){let J=zj($.trim(),j);return J?[J]:[]}return $.split(`
35
- `).slice(0,$.endsWith(`
36
- `)?void 0:-1).map((J)=>J.trim()?zj(J,j):void 0).filter((J)=>Boolean(J))}function H1($){return $==="complete"||$==="failed"||$==="paused"}function Z8($,j){let J=j.type==="subagent.nested.completed"&&j.child.state==="running"?"complete":j.child.state,Z={...j.child,state:J,lastUpdate:j.child.lastUpdate??j.ts};if(!$)return Z;let Q=$.lastUpdate??0,X=Z.lastUpdate??j.ts;if(X<Q)return $;if(H1($.state)&&!H1(Z.state))return $;if(H1($.state)&&H1(Z.state)&&X===Q)return $;return{...$,...Z,state:Z.state,lastUpdate:Math.max(Q,X)}}function U4($,j){let J=!1,Z=(U)=>U.map((G)=>{if(G.id===j.parentRunId){let q=G.children??[],O=q.findIndex((h)=>h.id===j.child.id),T=Z8(O>=0?q[O]:void 0,j),y=O>=0?q.map((h,S)=>S===O?T:h):[...q,T];return J=!0,{...G,children:y.slice(0,V1),lastUpdate:Math.max(G.lastUpdate??0,j.ts)}}if(!G.children?.length)return G;let B=Z(G.children);return B===G.children?G:{...G,children:B}}),Q=Z($);if(J)return Q;let X=Q.findIndex((U)=>U.id===j.child.id),W=Z8(X>=0?Q[X]:void 0,j);return X>=0?Q.map((U,G)=>G===X?W:U):[...Q,W].slice(0,V1)}function z4($,j){return{...$,updatedAt:Math.max($.updatedAt,j.ts),children:U4($.children,j)}}function X8($){return Q$.join(Q8($),Q4)}function G4($){Bj($);try{let j=JSON.parse(R$.readFileSync(X8($),"utf-8"));return{rootRunId:$.rootRunId,updatedAt:typeof j.updatedAt==="number"?j.updatedAt:0,children:Array.isArray(j.children)?j.children.map((J)=>z1(J)).filter((J)=>Boolean(J)):[],processedEvents:Array.isArray(j.processedEvents)?j.processedEvents.filter((J)=>typeof J==="string"):[]}}catch(j){if(j.code!=="ENOENT")throw j;return{rootRunId:$.rootRunId,updatedAt:0,children:[],processedEvents:[]}}}function Mj($){Bj($);let j=G4($),J=new Set(j.processedEvents),Z=!1,Q=[];try{Q=R$.readdirSync($.eventSink).filter((X)=>X.endsWith(".json")||X.endsWith(".jsonl")).sort()}catch(X){if(X.code!=="ENOENT")throw X}for(let X of Q){if(J.has(X))continue;let W=Q$.join($.eventSink,X);if(!Uj($.eventSink,W))continue;let U;try{let G=R$.statSync(W);if(!G.isFile()||G.size>Gj)continue;U=R$.readFileSync(W,"utf-8")}catch{continue}for(let G of K4(U,$))j=z4(j,G),Z=!0;J.add(X),Z=!0}if(Z)j={...j,processedEvents:[...J].slice(-1000)},D$(X8($),j);return j}function B4($,j,J){let Z=`${JSON.stringify(J)}
37
- `;if(Buffer.byteLength(Z,"utf-8")>Gj)throw Error("Nested route record exceeds the maximum size.");R$.mkdirSync($,{recursive:!0,mode:448});let Q=`${String(j).padStart(13,"0")}-${Z4()}.json`,X=Q$.join($,`.${Q}.tmp`),W=Q$.join($,Q);return R$.writeFileSync(X,Z,{mode:384}),R$.renameSync(X,W),W}function Y8($,j){Bj($);let J={...j,rootRunId:$.rootRunId,capabilityToken:$.capabilityToken},Z=zj(JSON.stringify(J),$);if(!Z)throw Error("Nested event record failed validation.");B4($.eventSink,Z.ts,Z)}function W8($,j,J){return{id:$.runId||J.id,parentRunId:J.parentRunId,...J.parentStepIndex!==void 0?{parentStepIndex:J.parentStepIndex}:{},depth:J.depth,path:J.path??[{runId:J.parentRunId,...J.parentStepIndex!==void 0?{stepIndex:J.parentStepIndex}:{}}],asyncDir:j,...$.pid?{pid:$.pid}:{},...$.sessionId?{sessionId:$.sessionId}:{},mode:$.mode??J.mode,state:$.state,...$.currentStep!==void 0?{currentStep:$.currentStep}:{},...$.chainStepCount!==void 0?{chainStepCount:$.chainStepCount}:{},...$.activityState?{activityState:$.activityState}:{},...$.lastActivityAt!==void 0?{lastActivityAt:$.lastActivityAt}:{},...$.currentTool?{currentTool:$.currentTool}:{},...$.currentToolStartedAt!==void 0?{currentToolStartedAt:$.currentToolStartedAt}:{},...$.currentPath?{currentPath:$.currentPath}:{},...$.turnCount!==void 0?{turnCount:$.turnCount}:{},...$.toolCount!==void 0?{toolCount:$.toolCount}:{},...$.totalTokens?{totalTokens:$.totalTokens}:{},...$.timeoutMs!==void 0?{timeoutMs:$.timeoutMs}:{},...$.deadlineAt!==void 0?{deadlineAt:$.deadlineAt}:{},...$.timedOut!==void 0?{timedOut:$.timedOut}:{},...$.turnBudget?{turnBudget:$.turnBudget}:{},...$.turnBudgetExceeded!==void 0?{turnBudgetExceeded:$.turnBudgetExceeded}:{},...$.wrapUpRequested!==void 0?{wrapUpRequested:$.wrapUpRequested}:{},...$.error?{error:$.error}:{},...$.startedAt!==void 0?{startedAt:$.startedAt}:{startedAt:J.ts},...$.endedAt!==void 0?{endedAt:$.endedAt}:{},lastUpdate:$.lastUpdate??J.ts,...$.sessionFile?{sessionFile:$.sessionFile}:{},...$.steps?.length?{steps:$.steps.map((Z)=>({agent:Z.agent,status:Z.status,...Z.sessionFile?{sessionFile:Z.sessionFile}:{},...Z.activityState?{activityState:Z.activityState}:{},...Z.lastActivityAt!==void 0?{lastActivityAt:Z.lastActivityAt}:{},...Z.currentTool?{currentTool:Z.currentTool}:{},...Z.currentToolStartedAt!==void 0?{currentToolStartedAt:Z.currentToolStartedAt}:{},...Z.currentPath?{currentPath:Z.currentPath}:{},...Z.turnCount!==void 0?{turnCount:Z.turnCount}:{},...Z.toolCount!==void 0?{toolCount:Z.toolCount}:{},...Z.startedAt!==void 0?{startedAt:Z.startedAt}:{},...Z.endedAt!==void 0?{endedAt:Z.endedAt}:{},...Z.error?{error:Z.error}:{},...Z.timedOut!==void 0?{timedOut:Z.timedOut}:{},...Z.turnBudget?{turnBudget:Z.turnBudget}:{},...Z.turnBudgetExceeded!==void 0?{turnBudgetExceeded:Z.turnBudgetExceeded}:{},...Z.wrapUpRequested!==void 0?{wrapUpRequested:Z.wrapUpRequested}:{}})).slice(0,Vj)}:{}}}var _4=[/rate\s*limit/i,/too many requests/i,/\b429\b/,/quota/i,/billing/i,/credit/i,/auth(?:entication)?/i,/unauthori[sz]ed/i,/forbidden/i,/api key/i,/token expired/i,/invalid key/i,/provider.*unavailable/i,/model.*unavailable/i,/model.*disabled/i,/model.*not found/i,/unknown model/i,/overloaded/i,/service unavailable/i,/temporar(?:ily)? unavailable/i,/connection refused/i,/fetch failed/i,/network error/i,/socket hang up/i,/upstream/i,/timed? out/i,/timeout/i,/\b502\b/,/\b503\b/,/\b504\b/,/cold.?start/i,/empty response/i,/no output/i,/model.*(?:load|fail|error)/i];function H8($){if(!$)return!1;return _4.some((j)=>j.test($))}function V8($,j){let J=$.error?.trim()||`exit ${$.exitCode??1}`;return j?`[fallback] ${$.model} failed: ${J}. Retrying with ${j}.`:`[fallback] ${$.model} failed: ${J}.`}function n$($,j){try{return $.kill(j)}catch{return!1}}function K8($,j){let{idleMs:J,hardMs:Z}=j,Q=!1,X=!1,W=!1,U,G,B=()=>{if(!X)try{$.stdout?.destroy()}catch{}if(!W)try{$.stderr?.destroy()}catch{}},q=()=>{if(U)clearTimeout(U),U=void 0;if(G)clearTimeout(G),G=void 0},O=()=>{if(!Q)return;if(U)clearTimeout(U);U=setTimeout(B,J),U.unref?.()};return $.stdout?.on("data",O),$.stderr?.on("data",O),$.stdout?.on("end",()=>{if(X=!0,X&&W)q()}),$.stderr?.on("end",()=>{if(W=!0,X&&W)q()}),$.on("exit",()=>{if(Q=!0,O(),G)return;G=setTimeout(B,Z),G.unref?.()}),$.on("close",q),$.on("error",q),q}var M4=[/(^|[;&|()\s])rm\s+/,/(^|[;&|()\s])mv\s+/,/(^|[;&|()\s])cp\s+/,/(^|[;&|()\s])mkdir\s+/,/(^|[;&|()\s])touch\s+/,/(^|[;&|()\s])git\s+apply\b/,/(^|[;&|()\s])patch\s+/,/(^|[;&|()\s])sed\s+[^\n;&|]*\s-i\b/,/(^|[;&|()\s])perl\s+[^\n;&|]*\s-pi\b/,/(^|[;&|()]|\n)\s*tee\s+[^|&;]+/,/\b(writeFile|writeFileSync|appendFile|appendFileSync)\b/,/\bwrite_text\s*\(/,/\bopen\s*\([^)]*,\s*["'][wa]/],L4=["failed","error","no exact match","did not match","malformed","rejected","unable","cannot","could not"];function U8($,j){if(!$||!j)return;let J=["path","file","filename","target","cwd"];for(let Z of J){let Q=j[Z];if(typeof Q==="string"&&Q.trim())return Q.trim()}if($==="bash"){let Z=typeof j.command==="string"?j.command:void 0;if(!Z)return;let Q=Z.match(/(?:>|>>|tee\s+)(\S+)/);if(Q?.[1])return Q[1]}return}function q4($){let j=!1,J=!1;for(let Z=0;Z<$.length;Z++){let Q=$[Z];if(Q==="'"&&!J){j=!j;continue}if(Q==='"'&&!j){J=!J;continue}if(j||J)continue;if(Q!==">")continue;if($[Z-1]==="-")continue;let X=$[Z+1]===">",W=Z+(X?2:1);while(W<$.length&&/\s/.test($[W]))W++;if(W>=$.length)continue;let U=$[W];if(U==="&"||U==="|"||U===";")continue;if(U==="("||U===")")continue;return!0}return!1}function Lj($){return q4($)||M4.some((j)=>j.test($))}function qj($,j){if(!$)return!1;if($==="edit"||$==="write")return!0;if($!=="bash")return!1;let J=typeof j?.command==="string"?j.command:"";if(!J.trim())return!1;return Lj(J)}function z8($){let j=$.toLowerCase();return L4.some((J)=>j.includes(J))}function G8($,j){if(j.now-j.startedAt>=$.activeNoticeAfterMs)return"time_threshold";if($.activeNoticeAfterTurns!==void 0&&j.turns>=$.activeNoticeAfterTurns)return"turn_threshold";if($.activeNoticeAfterTokens!==void 0&&j.tokens>=$.activeNoticeAfterTokens)return"token_threshold";return}function B8($){$.consecutiveFailures=0,$.lastFailureAt=void 0,$.recentFailures=[],$.lastMutatingPath=void 0,$.repeatedPathFailures=0}function G1(){return{consecutiveFailures:0,recentFailures:[],repeatedPathFailures:0}}function _8($,j,J){if($.lastFailureAt===void 0||j.ts-$.lastFailureAt>J)$.consecutiveFailures=0,$.recentFailures=[],$.repeatedPathFailures=0,$.lastMutatingPath=void 0;if($.lastFailureAt=j.ts,$.consecutiveFailures+=1,j.path&&$.lastMutatingPath===j.path)$.repeatedPathFailures+=1;else if(j.path)$.lastMutatingPath=j.path,$.repeatedPathFailures=1;if($.recentFailures.push(j),$.recentFailures.length>3)$.recentFailures.shift()}function M8($,j){return $.consecutiveFailures>=j||$.repeatedPathFailures>=j}function L8($){if($.recentFailures.length===0)return;return $.recentFailures.map((j)=>`${j.tool}${j.path?`(${j.path})`:""}: ${j.error}`).join(" | ")}var F4=[/\breview only\b/i,/\bsuggest fixes only\b/i,/\bonly return findings\b/i,/\breturn findings only\b/i],O4=[/\bmust\s+(?:edit|modify|change|fix|patch|apply)\b/i,/\brequired\s+to\s+(?:edit|modify|change|fix|patch|apply)\b/i,/\bregardless\s+of\s+findings\b/i,/\balways\s+(?:edit|modify|change|fix|patch|apply)\b/i,/\bapply\s+(?:the\s+)?fix(?:es)?\s+directly\b/i,/\bmake\s+(?:the\s+)?code\s+changes\b/i],A4=[/\bdo not edit\b/i,/\bdon't edit\b/i,/\bdo not modify\b/i,/\bdo not change files\b/i],N4=[/\bdo not edit files?\s+outside\b/i,/\bdo not edit\s+outside\b/i,/\bdo not edit\s+unrelated files?\b/i,/\bdo not change\s+unrelated files?\b/i,/\bdo not modify\s+unrelated files?\b/i],C4=[/\binvestigate\b/i,/\bscout\b/i,/\bresearch(?:er)?\b/i],T4=[/\b(?:implement|fix|edit|modify|patch|refactor|delete)\b/i,/\b(?:update|add|remove|replace|create)\b(?!\s+(?:(?:a|an|the)\s+)?(?:report|summary|findings?)(?:\b|$))/i,/\bapply\s+(?:the\s+)?(?:changes?|fix(?:es)?|patch)\b/i,/\bmake\s+(?:the\s+)?changes\b/i,/\bdo those fixes\b/i],E4=[/\b(?:implement|fix|edit|modify|patch|refactor)\b/i,/\bapply\s+(?:the\s+)?(?:changes?|fix(?:es)?|patch)\b/i,/\bmake\s+(?:the\s+)?changes\b/i,/\bdo those fixes\b/i,/\b(?:update|add|remove|replace|delete|create)\s+(?:the\s+)?(?:file|files|code|source|implementation|test|tests|component|function|module|class|method|logic|import|imports|readme|docs?|changelog|package\.json|config|manifest|extension|prompt|command)\b/i],S4=new Set(["read","grep","find","ls","web_search","fetch_content","get_search_content","intercom","contact_supervisor"]);function D4($){return $.split(`
38
- `).filter((j)=>!/^\s*\[(?:Write to|Read from):/i.test(j)).filter((j)=>!/^\s*(?:Create and maintain progress at:|Update progress at:|\*\*Output:\*\*|Write your findings to(?: exactly this path)?:|This path is authoritative for this run\.|Ignore any other output filename or output path mentioned elsewhere)/i.test(j)).join(`
39
- `)}function b4($){let j=$;for(let J of N4)j=j.replace(J," ");return j}function R4($,j){return $!==void 0&&$.length>0&&(j?.length??0)===0&&$.every((J)=>S4.has(J))}function w4($,j){let J=D4(j),Z=b4(J);if(F4.some((X)=>X.test(Z)))return!1;if(A4.some((X)=>X.test(Z)))return!1;if(C4.some((X)=>X.test($)))return!1;if(/\breviewer\b/i.test($))return O4.some((X)=>X.test(J));if($==="worker"&&T4.some((X)=>X.test(J)))return!0;return E4.some((X)=>X.test(J))}function I4($){for(let j of $){if(j.role!=="assistant")continue;for(let J of j.content){if(J.type!=="toolCall")continue;if(J.name==="edit"||J.name==="write")return!0;if(J.name!=="bash")continue;let Z=typeof J.arguments==="object"&&J.arguments!==null&&!Array.isArray(J.arguments)?J.arguments:{};if(typeof Z.command==="string"&&Lj(Z.command))return!0}}return!1}function q8($){let j=R4($.tools,$.mcpDirectTools)?!1:w4($.agent,$.task),J=I4($.messages);return{expectedMutation:j,attemptedMutation:J,triggered:j&&!J}}import*as B0 from"node:fs";import*as F8 from"node:path";function y4($){try{let j=B0.readdirSync($).filter((J)=>J.endsWith(".jsonl")).map((J)=>F8.join($,J));if(j.length===0)return null;return j.sort((J,Z)=>B0.statSync(Z).mtimeMs-B0.statSync(J).mtimeMs),j[0]??null}catch{return null}}function Fj($){let j=y4($);if(!j)return null;try{let J=B0.readFileSync(j,"utf-8"),Z=0,Q=0;for(let X of J.split(`
40
- `)){if(!X.trim())continue;try{let W=JSON.parse(X),U=W.usage??W.message?.usage;if(U)Z+=U.inputTokens??U.input??0,Q+=U.outputTokens??U.output??0}catch{}}return{input:Z,output:Q,total:Z+Q}}catch{return null}}import{spawnSync as A8}from"node:child_process";import*as J$ from"node:fs";import*as m0 from"node:os";import*as l from"node:path";var k4=30000;function B1($,j){let J=A8("git",["-C",$,...j],{encoding:"utf-8"});return{stdout:J.stdout??"",stderr:J.stderr??"",status:J.status}}function w$($,j){let J=B1($,j);if(J.status!==0){let Z=`git -C ${$} ${j.join(" ")}`,Q=J.stderr.trim()||J.stdout.trim()||`${Z} failed`;throw Error(Q)}return J.stdout}function f4($){let j=g4($),J=w$($,["rev-parse","--show-toplevel"]).trim();if(w$(J,["status","--porcelain"]).trim().length>0)throw Error("worktree isolation requires a clean git working tree. Commit or stash changes first.");let Q=w$(J,["rev-parse","HEAD"]).trim();return{toplevel:J,cwdRelative:j,baseCommit:Q}}function O8($){let j=l.resolve($);try{return J$.realpathSync(j)}catch{return j}}function N8($,j){let J=O8(j);for(let Z=0;Z<$.length;Z++){let Q=$[Z];if(!Q.cwd)continue;let X=l.isAbsolute(Q.cwd)?Q.cwd:l.resolve(j,Q.cwd);if(O8(X)===J)continue;return{index:Z,agent:Q.agent,cwd:Q.cwd}}return}function C8($,j){return`worktree isolation uses the shared cwd (${j}); task ${$.index+1} (${$.agent}) sets cwd to ${$.cwd}. Remove task-level cwd overrides or disable worktree.`}function P4($){return $.replace(/[^\w.-]/g,"_")}function x4($,j){return`dm-parallel-${$}-${j}`}function h4($,j){let J=$??process.env.DM_SUBAGENTS_WORKTREE_DIR;if(J===void 0)return m0.tmpdir();let Z=J.trim();if(!Z)throw Error("worktree base directory cannot be empty");let Q=Z.startsWith("~/")?l.join(m0.homedir(),Z.slice(2)):Z,X=l.isAbsolute(Q)?Q:l.resolve(j,Q);try{J$.mkdirSync(X,{recursive:!0})}catch(W){let U=W instanceof Error?W.message:String(W);throw Error(`failed to create worktree base directory ${X}: ${U}`)}return X}function v4($,j,J){return l.join($,`dm-worktree-${j}-${J}`)}function g4($){let j=B1($,["rev-parse","--is-inside-work-tree"]);if(j.status!==0||j.stdout.trim()!=="true")throw Error("worktree isolation requires a git repository");let J=w$($,["rev-parse","--show-prefix"]).trim(),Z=J?l.normalize(J.replace(/[\\/]+$/,"")):"";return Z==="."?"":Z}function m4($,j){let J=l.join($,"node_modules"),Z=l.join(j,"node_modules");if(!J$.existsSync(J)||J$.existsSync(Z))return!1;try{return J$.symlinkSync(J,Z),!0}catch{return!1}}function c4($){if($===void 0)return k4;if(!Number.isInteger($)||$<=0)throw Error("worktree setup hook timeout must be an integer greater than 0");return $}function d4($,j){if(!j)return;let J=j.hookPath.trim();if(!J)throw Error("worktree setup hook path cannot be empty");let Z=J.startsWith("~/")?l.join(m0.homedir(),J.slice(2)):J,Q;if(l.isAbsolute(Z))Q=Z;else if(Z.includes("/")||Z.includes("\\"))Q=l.resolve($,Z);else throw Error("worktree setup hook must be an absolute path or a repo-relative path");if(!J$.existsSync(Q))throw Error(`worktree setup hook not found: ${Q}`);if(J$.statSync(Q).isDirectory())throw Error(`worktree setup hook must be a file, got directory: ${Q}`);return{hookPath:Q,timeoutMs:c4(j.timeoutMs)}}function o4($,j){let J=j.trim();if(!J)throw Error("synthetic path cannot be empty");if(l.isAbsolute(J))throw Error(`synthetic path must be relative: ${j}`);let Z=l.resolve($,J),Q=l.relative($,Z);if(!Q||Q===".")throw Error(`synthetic path cannot target the worktree root: ${j}`);if(Q===".."||Q.startsWith(`..${l.sep}`)||l.isAbsolute(Q))throw Error(`synthetic path escapes the worktree root: ${j}`);return l.normalize(Q)}function u4($,j){let J=B1($,["ls-files","--",j]);return J.status===0&&J.stdout.trim().length>0}function l4($){let j=$.trim();if(!j)throw Error("worktree setup hook returned empty stdout; expected JSON object");let J;try{J=JSON.parse(j)}catch(Z){let Q=Z instanceof Error?Z.message:String(Z);throw Error(`worktree setup hook returned invalid JSON: ${Q}`)}if(!J||typeof J!=="object"||Array.isArray(J))throw Error("worktree setup hook stdout must be a JSON object");return J}function p4($,j){let J=A8($.hookPath,[],{cwd:j.worktreePath,encoding:"utf-8",input:JSON.stringify(j),timeout:$.timeoutMs,shell:!1});if(J.error){if(("code"in J.error?J.error.code:void 0)==="ETIMEDOUT")throw Error(`worktree setup hook timed out after ${$.timeoutMs}ms`);throw Error(`worktree setup hook failed: ${J.error.message}`)}if(J.status!==0){let X=J.stderr.trim()||J.stdout.trim()||"no output";throw Error(`worktree setup hook failed with exit code ${J.status}: ${X}`)}let Z=l4(J.stdout);if(Z.syntheticPaths===void 0)return[];if(!Array.isArray(Z.syntheticPaths))throw Error("worktree setup hook output field 'syntheticPaths' must be an array of relative paths");let Q=new Set;for(let X of Z.syntheticPaths){if(typeof X!=="string")throw Error("worktree setup hook output field 'syntheticPaths' must contain only strings");let W=o4(j.worktreePath,X);if(u4(j.worktreePath,W))throw Error(`worktree setup hook cannot mark tracked paths as synthetic: ${W}`);Q.add(W)}return[...Q]}function n4($,j,J,Z,Q,X,W,U){let G=x4(J,Z),B=v4(U,J,Z),q=B1($,["worktree","add",B,"-b",G,"HEAD"]);if(q.status!==0){let T=q.stderr.trim()||q.stdout.trim()||`failed to create worktree ${B}`;throw Error(T)}let O=j?l.join(B,j):B;try{let T=m4($,B),y=T?["node_modules"]:[];if(X){let h=p4(X,{version:1,repoRoot:$,worktreePath:B,agentCwd:O,branch:G,index:Z,runId:J,baseCommit:Q,agent:W});y.push(...h)}return{path:B,agentCwd:O,branch:G,index:Z,nodeModulesLinked:T,syntheticPaths:y}}catch(T){try{w$($,["worktree","remove","--force",B])}catch{}try{w$($,["branch","-D",G])}catch{}throw T}}function i4($,j){let J=l.resolve($.path,j),Z=l.relative($.path,J);if(!Z||Z==="."||Z===".."||Z.startsWith(`..${l.sep}`)||l.isAbsolute(Z))return;let Q;try{Q=J$.lstatSync(J)}catch(X){if((X&&typeof X==="object"&&"code"in X?X.code:void 0)==="ENOENT")return;throw X}if(Q.isSymbolicLink()){J$.unlinkSync(J);return}if(Q.isDirectory()){J$.rmSync(J,{recursive:!0,force:!0});return}J$.rmSync(J,{force:!0})}function r4($){if($.syntheticPaths.length===0)return;let j=new Set;for(let J of $.syntheticPaths){if(j.has(J))continue;j.add(J),i4($,J)}}function T8($,j,J,Z){return{index:$,agent:j,branch:J,diffStat:"",filesChanged:0,insertions:0,deletions:0,patchPath:Z}}function s4($){let j=$.split(`
41
- `).map((X)=>X.trim()).filter(Boolean),J=0,Z=0,Q=0;for(let X of j){let[W,U]=X.split("\t");if(W===void 0||U===void 0)continue;if(J++,/^\d+$/.test(W))Z+=parseInt(W,10);if(/^\d+$/.test(U))Q+=parseInt(U,10)}return{filesChanged:J,insertions:Z,deletions:Q}}function a4($,j,J,Z){r4(j),w$(j.path,["add","-A"]);let Q=w$(j.path,["diff","--cached","--stat",$.baseCommit]).trim(),X=w$(j.path,["diff","--cached",$.baseCommit]),W=w$(j.path,["diff","--cached","--numstat",$.baseCommit]);if(J$.writeFileSync(Z,X,"utf-8"),!X.trim())return T8(j.index,J,j.branch,Z);let U=s4(W);return{index:j.index,agent:J,branch:j.branch,diffStat:Q,filesChanged:U.filesChanged,insertions:U.insertions,deletions:U.deletions,patchPath:Z}}function t4($){try{J$.writeFileSync($,"","utf-8")}catch{}}function e4($,j){try{w$($,["worktree","remove","--force",j.path])}catch{}try{w$($,["branch","-D",j.branch])}catch{}}function $5($){return $.filesChanged>0||$.insertions>0||$.deletions>0||$.diffStat.trim().length>0}function E8($,j,J,Z){let Q=f4($),X=d4(Q.toplevel,Z?.setupHook),W=h4(Z?.baseDir,Q.toplevel),U=[];try{for(let G=0;G<J;G++)U.push(n4(Q.toplevel,Q.cwdRelative,j,G,Q.baseCommit,X,Z?.agents?.[G],W))}catch(G){throw Oj({cwd:Q.toplevel,worktrees:U,baseCommit:Q.baseCommit}),G}return{cwd:Q.toplevel,worktrees:U,baseCommit:Q.baseCommit}}function S8($,j,J){try{J$.mkdirSync(J,{recursive:!0})}catch{return[]}let Z=[];for(let Q=0;Q<$.worktrees.length;Q++){let X=$.worktrees[Q],W=j[Q]??`task-${Q+1}`,U=l.join(J,`task-${Q}-${P4(W)}.patch`);try{Z.push(a4($,X,W,U))}catch{t4(U),Z.push(T8(Q,W,X.branch,U))}}return Z}function Oj($){for(let j=$.worktrees.length-1;j>=0;j--)e4($.cwd,$.worktrees[j]);try{w$($.cwd,["worktree","prune"])}catch{}}function D8($){let j=$.filter($5);if(j.length===0)return"";let J=["=== Worktree Changes ===",""];for(let Q of j){if(J.push(`--- Task ${Q.index+1} (${Q.agent}): ${Q.filesChanged} files changed, +${Q.insertions} -${Q.deletions} ---`),Q.diffStat.trim().length>0)J.push(Q.diffStat);J.push("")}let Z=l.dirname(j[0].patchPath);return J.push(`Full patches: ${Z}`),J.join(`
42
- `).trimEnd()}function b8($){return $.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")||"agent"}function Aj($,j,J){let Z=J!==void 0?`-${J+1}`:"";return`subagent-${b8(j)}-${b8($)}${Z}`}import{spawn as j5}from"node:child_process";import{spawnSync as J5}from"node:child_process";import*as w8 from"node:path";var _1={none:0,attested:1,checked:2,verified:3,reviewed:4};function Z5($){return[...new Set($)]}function I8($){if($.level==="none")return"";let j=["","## Acceptance Contract",`Acceptance level: ${$.level}`,"Completion is not accepted from prose alone. End with a structured acceptance report.","","Criteria:",...$.criteria.length?$.criteria.map((J)=>`- ${J.id}: ${J.must}`):["- Return the requested result."],"",`Required evidence: ${$.evidence.join(", ")||"none"}`];if($.verify.length>0){j.push("","Runtime verification commands configured by parent:");for(let J of $.verify)j.push(`- ${J.id}: ${J.command}`)}if($.review&&$.review!==!1){if(j.push("",`Review gate: ${$.review.required===!1?"optional":"required"}${$.review.agent?` by ${$.review.agent}`:""}.`),$.review.focus)j.push(`Review focus: ${$.review.focus}`)}if($.stopRules.length>0)j.push("","Stop rules:",...$.stopRules.map((J)=>`- ${J}`));return j.push("","Finish with a fenced JSON block tagged `acceptance-report` in this shape:","Use empty arrays when no items apply; array fields contain strings unless object entries are shown.","```acceptance-report",JSON.stringify({criteriaSatisfied:[{id:"criterion-1",status:"satisfied",evidence:"specific proof"}],changedFiles:["src/file.ts"],testsAddedOrUpdated:["test/file.test.ts"],commandsRun:[{command:"command",result:"passed",summary:"short result"}],validationOutput:["validation output or concise summary"],residualRisks:["none"],noStagedFiles:!0,diffSummary:"short description of the diff",reviewFindings:["blocker: file.ts:12 - issue found, or no blockers"],manualNotes:"anything else the parent should know"},null,2),"```"),j.join(`
43
- `)}function y8($,j){let J=0,Z=!1,Q=!1;for(let X=j;X<$.length;X++){let W=$[X];if(Z){if(Q)Q=!1;else if(W==="\\")Q=!0;else if(W==='"')Z=!1;continue}if(W==='"'){Z=!0;continue}if(W==="{")J++;if(W==="}"){if(J--,J===0)return $.slice(j,X+1)}}return}function Nj($){if(!$||typeof $!=="object"||Array.isArray($))return $;let j=$;if("acceptance"in j)return j.acceptance;if("acceptance-report"in j)return j["acceptance-report"];return $}function Q5($){return Array.isArray($)&&$.every((j)=>{if(!j||typeof j!=="object"||Array.isArray(j))return!1;let J=j;return typeof J.command==="string"&&(J.result==="passed"||J.result==="failed"||J.result==="not-run")&&typeof J.summary==="string"})}function X5($){if(!$||typeof $!=="object"||Array.isArray($))return!1;let j=$;return"criteriaSatisfied"in j&&(i$(j.changedFiles)||i$(j.testsAddedOrUpdated)||Q5(j.commandsRun)||i$(j.validationOutput)||i$(j.residualRisks)||typeof j.noStagedFiles==="boolean"||typeof j.diffSummary==="string"||i$(j.reviewFindings)||typeof j.manualNotes==="string")}function k8($){let j=$.trim();try{return JSON.parse(j)}catch(J){let Z=j.indexOf("{");if(Z>0){let Q=y8(j,Z);if(Q)return JSON.parse(Q)}throw J}}function R8($,j){return[...$.matchAll(new RegExp(`\`\`\`${j}\\s*\\n([\\s\\S]*?)\`\`\``,"gi"))].map((J)=>J[1]?.trim()).filter((J)=>Boolean(J))}function f8($){if(!$||typeof $!=="object"||Array.isArray($))return"";let j=$;if("acceptance"in j)return"acceptance";if("acceptance-report"in j)return"acceptance-report";return""}function Y5($){let j=k8($),J=Nj(j);return Tj(J,f8(j))}function P8($){let j=k8($),J=Nj(j),Z=Tj(J);if(!Z.report)return;return X5(Z.report)?Z.report:void 0}function W5($){let j=R8($,"acceptance-report"),J=[];for(let Q of j)try{let X=Y5(Q);if(X.report)return{report:X.report};J.push(`Invalid acceptance-report: ${X.errors.join("; ")}`)}catch(X){J.push(X instanceof Error?X.message:String(X))}if(J.length>0)return{error:`Failed to parse acceptance-report: ${J.join("; ")}`};for(let Q of R8($,"(?:json|jsonc|json5)"))try{let X=P8(Q);if(X)return{report:X}}catch{}let Z=$.search(/ACCEPTANCE_REPORT\s*:/i);if(Z!==-1){let Q=$.indexOf("{",Z);if(Q!==-1){let X=y8($,Q);if(X)try{let W=JSON.parse(X),U=Nj(W),G=Tj(U,f8(W));if(G.report)return{report:G.report};return{error:`Failed to parse acceptance-report: Invalid acceptance-report: ${G.errors.join("; ")}`}}catch(W){return{error:W instanceof Error?W.message:String(W)}}}}return{error:"Structured acceptance report not found."}}function Cj($){let j=/\n?```(acceptance-report|json|jsonc|json5)\s*\n([\s\S]*?)```\s*/gi,J;for(let Z of $.matchAll(j)){let Q=(Z.index??0)+Z[0].length;if($.slice(Q).trim().length===0&&Z[1]&&Z[2])J={index:Z.index??0,tag:Z[1].toLowerCase(),body:Z[2]}}if(J){if(J.tag==="acceptance-report")return $.slice(0,J.index).trimEnd();try{if(P8(J.body))return $.slice(0,J.index).trimEnd()}catch{}}return $.replace(/\n?```acceptance-report\s*\n[\s\S]*?```\s*$/i,"").replace(/\n?ACCEPTANCE_REPORT\s*:\s*\{[\s\S]*\}\s*$/i,"").trimEnd()}function i$($){return Array.isArray($)&&$.every((j)=>typeof j==="string")}function I$($,j){return $?`${$}.${j}`:j}function H5($){if($===void 0)return"missing";if($===null)return"null";if(Array.isArray($))return"array";if(typeof $==="object")return"object";if(typeof $==="string"){let j=$.length>80?`${$.slice(0,77)}...`:$;return JSON.stringify(j)}return`${typeof $} ${String($)}`}function L$($,j,J,Z){$.push(`${j}: expected ${J}; got ${H5(Z)}`)}function c0($,j,J){if(!Array.isArray(j)){L$($,J,"string[]",j);return}for(let[Z,Q]of j.entries())if(typeof Q!=="string")L$($,`${J}[${Z}]`,"string",Q)}function Tj($,j=""){let J=[];if(!$||typeof $!=="object"||Array.isArray($))return L$(J,j||"acceptance-report","object",$),{errors:J};let Z=$;if(Z.criteriaSatisfied!==void 0)if(!Array.isArray(Z.criteriaSatisfied))L$(J,I$(j,"criteriaSatisfied"),"array",Z.criteriaSatisfied);else for(let[X,W]of Z.criteriaSatisfied.entries()){let U=`${I$(j,"criteriaSatisfied")}[${X}]`;if(!W||typeof W!=="object"||Array.isArray(W)){L$(J,U,"object",W);continue}let G=W;if(G.id!==void 0&&typeof G.id!=="string")L$(J,`${U}.id`,"string",G.id);if(G.status!=="satisfied"&&G.status!=="not-satisfied"&&G.status!=="not-applicable")L$(J,`${U}.status`,'one of "satisfied", "not-satisfied", "not-applicable"',G.status);if(typeof G.evidence!=="string"||!G.evidence.trim())L$(J,`${U}.evidence`,"non-empty string",G.evidence)}if(Z.changedFiles!==void 0)c0(J,Z.changedFiles,I$(j,"changedFiles"));if(Z.testsAddedOrUpdated!==void 0)c0(J,Z.testsAddedOrUpdated,I$(j,"testsAddedOrUpdated"));if(Z.commandsRun!==void 0)if(!Array.isArray(Z.commandsRun))L$(J,I$(j,"commandsRun"),"array",Z.commandsRun);else for(let[X,W]of Z.commandsRun.entries()){let U=`${I$(j,"commandsRun")}[${X}]`;if(!W||typeof W!=="object"||Array.isArray(W)){L$(J,U,"object",W);continue}let G=W;if(typeof G.command!=="string"||!G.command.trim())L$(J,`${U}.command`,"non-empty string",G.command);if(G.result!=="passed"&&G.result!=="failed"&&G.result!=="not-run")L$(J,`${U}.result`,'one of "passed", "failed", "not-run"',G.result);if(typeof G.summary!=="string")L$(J,`${U}.summary`,"string",G.summary)}if(Z.validationOutput!==void 0)c0(J,Z.validationOutput,I$(j,"validationOutput"));if(Z.residualRisks!==void 0)c0(J,Z.residualRisks,I$(j,"residualRisks"));if(Z.noStagedFiles!==void 0&&typeof Z.noStagedFiles!=="boolean")L$(J,I$(j,"noStagedFiles"),"boolean",Z.noStagedFiles);if(Z.diffSummary!==void 0&&typeof Z.diffSummary!=="string")L$(J,I$(j,"diffSummary"),"string",Z.diffSummary);if(Z.reviewFindings!==void 0)c0(J,Z.reviewFindings,I$(j,"reviewFindings"));if(Z.manualNotes!==void 0&&typeof Z.manualNotes!=="string")L$(J,I$(j,"manualNotes"),"string",Z.manualNotes);if(Z.notes!==void 0&&typeof Z.notes!=="string")L$(J,I$(j,"notes"),"string",Z.notes);if(J.length>0)return{errors:J};return Z.criteriaSatisfied!==void 0||Z.changedFiles!==void 0||Z.testsAddedOrUpdated!==void 0||Z.commandsRun!==void 0||Z.validationOutput!==void 0||Z.residualRisks!==void 0||Z.noStagedFiles!==void 0||Z.diffSummary!==void 0||Z.manualNotes!==void 0||Z.notes!==void 0||Z.reviewFindings!==void 0?{report:Z,errors:J}:{errors:[`${j||"acceptance-report"}: expected at least one acceptance report field`]}}function V5($,j){let J=new Map((j.criteriaSatisfied??[]).filter((Z)=>Z.id).map((Z)=>[Z.id,Z]));return $.filter((Z)=>Z.severity!=="recommended").map((Z)=>{let Q=J.get(Z.id);if(!Q)return{id:`criterion:${Z.id}`,status:"failed",message:`Required criterion '${Z.id}' was not reported.`};if(Q.status!=="satisfied")return{id:`criterion:${Z.id}`,status:"failed",message:`Required criterion '${Z.id}' was reported as ${Q.status}.`};return{id:`criterion:${Z.id}`,status:"passed",message:`Required criterion '${Z.id}' satisfied.`}})}function K5($,j){switch(j){case"changed-files":return i$($.changedFiles)&&$.changedFiles.length>0;case"tests-added":return i$($.testsAddedOrUpdated)&&$.testsAddedOrUpdated.length>0;case"commands-run":return Array.isArray($.commandsRun)&&$.commandsRun.length>0;case"validation-output":return i$($.validationOutput)&&$.validationOutput.length>0;case"residual-risks":return i$($.residualRisks);case"no-staged-files":return $.noStagedFiles===!0;case"diff-summary":return typeof $.diffSummary==="string"&&$.diffSummary.trim().length>0;case"review-findings":return i$($.reviewFindings);case"manual-notes":return Boolean(($.manualNotes??$.notes)?.trim())}}function U5($){let j=J5("git",["status","--short"],{cwd:$,encoding:"utf-8"});if(j.status!==0)return{id:"no-staged-files",status:"not-applicable",message:"git status unavailable; no staged-files check skipped"};let J=j.stdout.split(/\r?\n/).filter((Z)=>Z.length>=2&&Z[0]!==" "&&Z[0]!=="?");return J.length===0?{id:"no-staged-files",status:"passed",message:"No staged files detected."}:{id:"no-staged-files",status:"failed",message:`Staged files present: ${J.join(", ")}`}}function z5($,j,J){let Z=[];for(let Q of $.evidence){let X=K5(j,Q);Z.push({id:`evidence:${Q}`,status:X?"passed":"failed",message:X?`${Q} evidence present.`:`${Q} evidence missing from child report.`})}if($.evidence.includes("no-staged-files"))Z.push(U5(J));return Z}function d0($){let j=$.trim();if(!j)return;return j.length>12000?`${j.slice(0,12000)}
44
- ...[truncated]`:j}function o0($){return Z5($.map((j)=>j?.trim()).filter((j)=>Boolean(j)))}function Ej($){let j=$.results.map((Q)=>Q.acceptance?.childReport).filter((Q)=>Boolean(Q)),J=$.results.filter((Q)=>Q.exitCode!==0||Q.acceptance?.status==="rejected"),Z=$.results.length>0&&J.length===0;return{criteriaSatisfied:[{id:"criterion-1",status:Z?"satisfied":"not-satisfied",evidence:Z?`All ${$.results.length} dynamic child run(s) completed without child or acceptance blockers.`:"Dynamic fanout produced no accepted child evidence."},{id:"criterion-2",status:Z?"satisfied":"not-satisfied",evidence:Z?"Collected child acceptance evidence for aggregate review.":"Dynamic fanout produced no aggregate review evidence."},...$.results.map((Q,X)=>({id:`child-${X+1}`,status:Q.exitCode===0&&Q.acceptance?.status!=="rejected"?"satisfied":"not-satisfied",evidence:`${Q.agent}: acceptance ${Q.acceptance?.status??"unreported"}${Q.error?` (${Q.error})`:""}`}))],changedFiles:o0(j.flatMap((Q)=>Q.changedFiles??[])),testsAddedOrUpdated:o0(j.flatMap((Q)=>Q.testsAddedOrUpdated??[])),commandsRun:j.flatMap((Q)=>Q.commandsRun??[]),validationOutput:o0(j.flatMap((Q)=>Q.validationOutput??[])),residualRisks:o0([...j.flatMap((Q)=>Q.residualRisks??[]),...J.map((Q)=>`${Q.agent}: ${Q.error??"child or acceptance gate failed"}`)]),noStagedFiles:j.length>0&&j.every((Q)=>Q.noStagedFiles===!0),reviewFindings:o0(j.flatMap((Q)=>Q.reviewFindings??[])),manualNotes:$.notes??`Aggregated acceptance evidence from ${$.results.length} dynamic fanout child run(s).`,notes:$.notes}}function G5($,j,J={}){return new Promise((Z)=>{let Q=Date.now(),X=$.cwd?w8.resolve(j,$.cwd):j,W="",U="",G=!1,B=!1,q,O=j5($.command,{cwd:X,env:{...process.env,...$.env??{}},shell:!0,stdio:["ignore","pipe","pipe"],windowsHide:!0}),T=(S)=>{if(B)return;if(B=!0,clearTimeout(h),q)clearTimeout(q);J.signal?.removeEventListener("abort",y),Z({id:$.id,command:$.command,cwd:X,durationMs:Date.now()-Q,...S})},y=()=>{if(B||G)return;G=!0,O.kill("SIGTERM"),q=setTimeout(()=>{O.kill("SIGKILL"),T({exitCode:null,status:"timed-out",stdout:d0(W),stderr:d0(U||J.abortMessage||"Acceptance verification timed out.")})},1000),q.unref?.()},h=setTimeout(y,$.timeoutMs??120000);if(h.unref?.(),J.signal?.aborted)y();else J.signal?.addEventListener("abort",y,{once:!0});O.stdout.on("data",(S)=>{W+=S.toString()}),O.stderr.on("data",(S)=>{U+=S.toString()}),O.on("close",(S)=>{T({exitCode:S,status:G?"timed-out":S===0&&!G?"passed":$.allowFailure?"allowed-failure":"failed",stdout:d0(W),stderr:d0(U||(G?J.abortMessage??"":""))})}),O.on("error",(S)=>{T({exitCode:G?null:1,status:G?"timed-out":$.allowFailure?"allowed-failure":"failed",stderr:G?d0(U||J.abortMessage||"Acceptance verification timed out."):S instanceof Error?S.message:String(S)})})})}async function M1($){let j=$.acceptance,J={status:j.level==="none"?"not-required":"claimed",explicit:j.explicit,effectiveAcceptance:j,inferredReason:j.inferredReason,criteria:j.criteria,runtimeChecks:[],verifyRuns:[]};if(j.level==="none")return J;let Z=$.report?{report:$.report}:W5($.output);if(Z.report)J.childReport=Z.report,J.status="attested";else return J.childReportParseError=Z.error,J.runtimeChecks.push({id:"attestation",status:"failed",message:Z.error??"Structured acceptance report missing."}),J.status="rejected",J;if(_1[j.level]>=_1.checked){if(J.runtimeChecks=[...V5(j.criteria,Z.report),...z5(j,Z.report,$.cwd)],J.runtimeChecks.some((Q)=>Q.status==="failed"))return J.status="rejected",J;J.status="checked"}if(_1[j.level]>=_1.verified&&(j.level==="verified"||j.verify.length>0)){if(j.level==="verified"&&j.verify.length===0)return J.runtimeChecks.push({id:"verification-config",status:"failed",message:"verified acceptance requires runtime verify commands."}),J.status="rejected",J;J.verifyRuns=[];for(let Q of j.verify)if(J.verifyRuns.push(await G5(Q,$.cwd,{signal:$.signal,abortMessage:$.abortMessage})),$.signal?.aborted)break;if(J.verifyRuns.some((Q)=>Q.status==="failed"||Q.status==="timed-out"))return J.status="rejected",J;J.status="verified"}if(j.level==="reviewed")if($.reviewResult)J.reviewResult=$.reviewResult,J.status=$.reviewResult.status==="no-blockers"?"reviewed":"rejected";else{let Q=j.review&&j.review!==!1&&j.review.required===!1;if(J.reviewResult={status:"needs-parent-decision",findings:[{severity:j.explicit&&!Q?"blocker":"non-blocking",issue:"Reviewed acceptance requires an independent reviewer result.",rationale:"The run cannot be marked reviewed from child evidence alone."}]},j.review===!1||j.explicit&&!Q)J.status="rejected"}return J}function L1($){if($.status!=="rejected")return;let j=$.runtimeChecks.find((Z)=>Z.status==="failed");if(j)return`Acceptance rejected: ${j.message}`;let J=$.verifyRuns.find((Z)=>Z.status==="failed"||Z.status==="timed-out");if(J)return`Acceptance verification '${J.id}' ${J.status}.`;if($.reviewResult?.status==="needs-parent-decision")return"Acceptance review required but no automatic reviewer result is available.";if($.reviewResult?.status==="blockers")return"Acceptance review found blockers.";return"Acceptance rejected."}import*as q1 from"node:fs";var B5=new Set(["complete","failed","paused"]),_5=new Set(["complete","completed","failed","paused"]);function M5($){try{return JSON.parse(q1.readFileSync($,"utf-8"))}catch(j){if(typeof j==="object"&&j!==null&&"code"in j&&j.code==="ENOENT")return;throw j}}function F1($,j){return $?.steps?.[j]}function L5($,j){if(!$)return!1;let J=F1($,j);if(J&&_5.has(J.status))return!0;return B5.has($.state)}function q5($,j){if(!$)return;if(j?.success===!0)return"complete";if(j?.success===!1)return $.state==="paused"?"paused":"failed";if($.state==="complete"||$.state==="failed"||$.state==="paused")return $.state;if($.success===!0)return"complete";if($.success===!1)return"failed";return}function F5($,j,J){let Z=J?.agent??j.steps?.[$.index]?.agent??"subagent",Q=J?.timedOut===!0||j.timedOut===!0,X=J?.error??j.error??`Attached async root ${$.runId} ended without a result file at ${$.resultPath}.`;return{agent:Z,output:X,success:!1,exitCode:1,error:X,...Q?{timedOut:!0}:{},...J?.sessionFile??j.sessionFile?{sessionFile:J?.sessionFile??j.sessionFile}:{},...J?.model?{model:J.model}:{},...J?.attemptedModels?{attemptedModels:J.attemptedModels}:{},...J?.modelAttempts?{modelAttempts:J.modelAttempts}:{},...J?.totalCost?{totalCost:J.totalCost}:{},...J?.structuredOutput!==void 0?{structuredOutput:J.structuredOutput}:{},...J?.structuredOutputPath?{structuredOutputPath:J.structuredOutputPath}:{},...J?.structuredOutputSchemaPath?{structuredOutputSchemaPath:J.structuredOutputSchemaPath}:{},...J?.acceptance?{acceptance:J.acceptance}:{}}}function O5($,j,J){let Z=F1(j,$.index);return{agent:Z?.agent??j?.steps?.[$.index]?.agent??"subagent",output:J,success:!1,exitCode:1,error:J,timedOut:!0,...Z?.sessionFile??j?.sessionFile?{sessionFile:Z?.sessionFile??j?.sessionFile}:{},...Z?.model?{model:Z.model}:{},...Z?.attemptedModels?{attemptedModels:Z.attemptedModels}:{},...Z?.modelAttempts?{modelAttempts:Z.modelAttempts}:{},...Z?.totalCost?{totalCost:Z.totalCost}:{}}}function A5($,j,J){let Z=J.results?.[$.index],Q=F1(j,$.index),X=q5(J,Z),W=Z?.agent??Q?.agent??j?.steps?.[$.index]?.agent??"subagent",U=Z?.output??J.summary??"",G=Z?.timedOut===!0||Q?.timedOut===!0||J.timedOut===!0||j?.timedOut===!0,B=X==="complete"&&!G,q=Z?.error??(B?void 0:J.error??J.summary??j?.error??`Attached async root ${$.runId} did not complete successfully.`);return{agent:W,output:B?U:U||q||"",success:B,exitCode:B?0:1,...q?{error:q}:{},...G?{timedOut:!0}:{},...Z?.sessionFile??Q?.sessionFile??j?.sessionFile?{sessionFile:Z?.sessionFile??Q?.sessionFile??j?.sessionFile}:{},...Z?.intercomTarget?{intercomTarget:Z.intercomTarget}:{},...Z?.model??Q?.model?{model:Z?.model??Q?.model}:{},...Z?.attemptedModels??Q?.attemptedModels?{attemptedModels:Z?.attemptedModels??Q?.attemptedModels}:{},...Z?.modelAttempts??Q?.modelAttempts?{modelAttempts:Z?.modelAttempts??Q?.modelAttempts}:{},...Z?.totalCost??Q?.totalCost?{totalCost:Z?.totalCost??Q?.totalCost}:{},...Z?.structuredOutput!==void 0?{structuredOutput:Z.structuredOutput}:Q?.structuredOutput!==void 0?{structuredOutput:Q.structuredOutput}:{},...Z?.structuredOutputPath??Q?.structuredOutputPath?{structuredOutputPath:Z?.structuredOutputPath??Q?.structuredOutputPath}:{},...Z?.structuredOutputSchemaPath??Q?.structuredOutputSchemaPath?{structuredOutputSchemaPath:Z?.structuredOutputSchemaPath??Q?.structuredOutputSchemaPath}:{},...Z?.acceptance??Q?.acceptance?{acceptance:Z?.acceptance??Q?.acceptance}:{}}}async function x8($,j={}){let J=j.pollIntervalMs??500,Z=j.terminalResultGraceMs??1000,Q=j.now??Date.now,X;for(;;){let W=R0($.asyncDir);if(j.shouldAbort?.())return O5($,W,j.timeoutMessage??"Subagent timed out.");let U=M5($.resultPath);if(U)return A5($,W,U);if(L5(W,$.index)){if(X??=Q(),Q()-X>=Z)return F5($,W,F1(W,$.index))}else X=void 0;if(!W&&!q1.existsSync($.asyncDir))throw Error(`Attached async root '${$.runId}' directory does not exist: ${$.asyncDir}`);await new Promise((G)=>setTimeout(G,J))}}import*as _0 from"node:fs";import*as Sj from"node:path";var N5="append-requests";function C5($){return Sj.join($,N5)}function v8($){let j=C5($);try{return _0.readdirSync(j).filter((J)=>J.endsWith(".json")).map((J)=>Sj.join(j,J)).sort()}catch(J){if(J.code==="ENOENT")return[];throw J}}function Dj($){return v8($).length}function T5($){let j=JSON.parse(_0.readFileSync($,"utf-8"));if(!j.id||typeof j.id!=="string")return;if(!Number.isFinite(j.createdAt))return;if(!Array.isArray(j.steps)||j.steps.length===0)return;return{id:j.id,createdAt:j.createdAt,steps:j.steps}}function g8($){let j=[];for(let J of v8($)){let Z=T5(J);try{_0.unlinkSync(J)}catch{}if(Z)j.push(Z)}return j.sort((J,Z)=>J.createdAt-Z.createdAt||J.id.localeCompare(Z.id))}function h8($){return{agent:$.agent,phase:$.phase,label:$.label,outputName:$.outputName,structured:$.structured,status:"pending",...$.sessionFile?{sessionFile:$.sessionFile}:{},skills:$.skills,model:$.model,thinking:$.thinking,attemptedModels:$.modelCandidates&&$.modelCandidates.length>0?$.modelCandidates:$.model?[$.model]:void 0,recentTools:[],recentOutput:[]}}function E5($){if($0($))return $.parallel.map(h8);if(j0($))return[{agent:`expand:${$.parallel.agent}`,phase:$.phase??$.parallel.phase,label:$.label??$.parallel.label??`Dynamic fanout (${$.collect.as})`,outputName:$.collect.as,structured:Boolean($.collect.outputSchema),status:"pending",recentTools:[],recentOutput:[]}];return[h8($)]}function m8($,j,J){if(!j)return;let Z=$.phases.find((Q)=>Q.title===j);if(!Z)Z={title:j,nodeIds:[]},$.phases.push(Z);Z.nodeIds.push(J)}function S5($,j,J){return{id:`step-${j}`,kind:"step",agent:$.agent,phase:$.phase,label:$.label?.trim()||$.agent||`Step ${j+1}`,status:"pending",flatIndex:J,stepIndex:j,outputName:$.outputName,structured:$.structured}}function D5($,j,J,Z){let Q=$.parallel.map((X,W)=>{let U=`step-${j}-agent-${W}`;return m8(Z,X.phase,U),{id:U,kind:"agent",agent:X.agent,phase:X.phase,label:X.label?.trim()||X.agent||`Agent ${W+1}`,status:"pending",flatIndex:J+W,stepIndex:j,outputName:X.outputName,structured:X.structured}});return{id:`step-${j}`,kind:"parallel-group",label:$.parallel.length===1?"Parallel task":`Parallel group (${$.parallel.length})`,status:"pending",stepIndex:j,children:Q}}function b5($,j){return{id:`step-${j}`,kind:"dynamic-parallel-group",label:$.label?.trim()||$.parallel.label?.trim()||`Dynamic fanout (${$.collect.as})`,status:"pending",stepIndex:j,outputName:$.collect.as,structured:Boolean($.collect.outputSchema),dynamic:{sourceOutput:$.expand.from.output,sourcePath:$.expand.from.path,itemName:$.expand.item??"item",maxItems:$.expand.maxItems,collectAs:$.collect.as},children:[]}}function R5($,j,J,Z){if(!$)return;if($0(j)){$.nodes.push(D5(j,J,Z,$));return}if(j0(j)){$.nodes.push(b5(j,J));return}let Q=S5(j,J,Z);$.nodes.push(Q),m8($,j.phase,Q.id)}function c8($){let j=0,J=0;for(let Z of $.steps){let Q=$.status.chainStepCount??$.status.steps?.length??0,X=$.status.steps?.length??0,W=E5(Z);if($.status.steps??=[],$.status.steps.push(...W),$0(Z))$.status.parallelGroups??=[],$.status.parallelGroups.push({start:X,count:Z.parallel.length,stepIndex:Q});else if(j0(Z))$.status.parallelGroups??=[],$.status.parallelGroups.push({start:X,count:1,stepIndex:Q});R5($.status.workflowGraph,Z,Q,X),$.status.chainStepCount=Q+1,j++,J+=W.length}return $.status.pendingAppends=$.pendingAppends??0,$.status.lastUpdate=$.now??Date.now(),{addedChainSteps:j,addedFlatSteps:J}}function d8($,j){if(!j)return $;let J=j.graceTurns===1?"1 additional assistant turn":`${j.graceTurns} additional assistant turns`,Z=["## Turn budget",`This child run has a soft budget of ${j.maxTurns} assistant turn${j.maxTurns===1?"":"s"}.`,`After that, ${J} may be allowed only for a final wrap-up.`,"When you approach or reach the soft budget, stop starting new tool work and return the final answer immediately.","This runner uses process-mode execution, so live steering after launch may be unavailable; treat this instruction as the wrap-up request.","If you continue past the soft budget plus grace turns, the supervisor may abort the process and return only partial output."].join(`
45
- `);return $.trim()?`${$.trim()}
46
-
47
- ${Z}`:Z}function bj($,j){return`Turn budget wrap-up was requested after ${j} assistant turn${j===1?"":"s"} (soft limit ${$.maxTurns}, grace ${$.graceTurns}). Process-mode live steering is unavailable, so the child was warned at launch to wrap up by this budget. Output may be partial.`}function u0($,j){return`Subagent exceeded turn budget after ${j} assistant turn${j===1?"":"s"} (soft limit ${$.maxTurns} + grace ${$.graceTurns}).`}function o8($,j){return j.trim()?`${$}
48
-
49
- Partial output before turn-budget abort:
50
- ${j}`:$}function Rj($){return{...$,outcome:"within-budget",turnCount:0}}function O1($,j,J){return{...$,turnCount:j,outcome:J?"exceeded":"wrap-up-requested",wrapUpRequestedAtTurn:$.maxTurns,...J?{exceededAtTurn:j}:{}}}function wj($,j,J){let Z=$.maxTurns+$.graceTurns;if(j<Z)return!1;if(j>Z)return!0;return!J}var y5=process.platform==="win32"?"SIGBREAK":"SIGUSR2",l8=52428800,k5="DM_SUBAGENT_ASYNC_EVENTS_MAX_BYTES",f5="subagent.events.truncated",P5=512,xj=new Map;function x5(){let $=process.env[k5];if(!$)return l8;let j=Number($);if(!Number.isFinite(j)||j<0)return l8;return Math.floor(j)}function h5($){let j=xj.get($);if(j)return j;let J=0;try{J=e.statSync($).size}catch(Z){if(Z.code!=="ENOENT");}return j={bytes:J,diagnosticsTruncated:!1},xj.set($,j),j}function $$($,j){try{d1($,j);let J=xj.get($);if(J)J.bytes+=Buffer.byteLength(`${j}
51
- `,"utf-8")}catch{}}function v5($,j,J){if(!j.trim())return;let Z=h5($);if(Z.diagnosticsTruncated)return;let Q=x5(),X=Buffer.byteLength(`${j}
52
- `,"utf-8"),W=Math.max(0,Q-P5);if(Z.bytes+X<=W){$$($,j);return}let U=JSON.stringify({type:f5,ts:Date.now(),maxBytes:Q,droppedEventType:J});if(Z.bytes+Buffer.byteLength(`${U}
53
- `,"utf-8")<=Q)$$($,U);Z.diagnosticsTruncated=!0}function g5($){return $.type!=="message_update"}function m5($){try{let j=e.readdirSync($).filter((J)=>J.endsWith(".jsonl")).map((J)=>r.join($,J));if(j.length===0)return null;return j.sort((J,Z)=>e.statSync(Z).mtimeMs-e.statSync(J).mtimeMs),j[0]??null}catch{return null}}function c5(){return{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,turns:0}}function p8($){if(!$||$.length===0)return null;let j=0,J=0;for(let Q of $)j+=Q.usage?.input??0,J+=Q.usage?.output??0;let Z=j+J;return Z>0?{input:j,output:J,total:Z}:null}function d5($){if(!$||$.length===0)return;let j=0,J=0,Z=0;for(let Q of $)j+=Q.usage?.input??0,J+=Q.usage?.output??0,Z+=Q.usage?.cost??0;return j>0||J>0||Z>0?{inputTokens:j,outputTokens:J,costUsd:Z}:void 0}function Ij($,j){let J=j.filter((Z)=>Z.trim());if(J.length===0)return;if($.recentOutput??=[],$.recentOutput.push(...J),$.recentOutput.length>50)$.recentOutput.splice(0,$.recentOutput.length-50)}function hj($){let j=$.stopReason,J=Array.isArray($.content)&&$.content.some((Z)=>Z.type==="toolCall");return j==="stop"&&!J}function yj($){$.currentTool=void 0,$.currentToolArgs=void 0,$.currentToolStartedAt=void 0,$.currentPath=void 0,$.recentTools=[],$.recentOutput=[]}function o5($,j,J,Z,Q,X,W,U,G,B,q,O,T,y){return new Promise((h)=>{let S=e.createWriteStream(J,{flags:"w"}),v$={...process.env,...Z??{},...rj(W)},k=GJ($,{...Q?{piPackageRoot:Q}:{},...X?{argv1:X}:{}}),f=w5(k.command,k.args,{cwd:j,stdio:["ignore","pipe","pipe"],env:v$,windowsHide:!0}),n="",d$="",W$="",y$=[],K$=c5(),g$,A$,s,E$=!1,X$=!1,_$=!1,E,t,p=!1,q$=[],Y$=(P)=>{if(!P.trim())return;S.write(`${P}
54
- `)},o$=(P)=>{for(let D of P.split(`
55
- `))Y$(D)},u$=(P)=>{if(!U)return;if(!g5(P))return;v5(U.eventsPath,JSON.stringify({...P,subagentSource:"child",subagentRunId:U.runId,subagentStepIndex:U.stepIndex,subagentAgent:U.agent,observedAt:Date.now()}),typeof P.type==="string"?P.type:void 0)},j$=(P,D)=>{if(u$({type:P,line:D}),P==="subagent.child.stdout")q?.writeStdoutLine(D);else q?.writeStderrLine(D)},c=(P)=>{if(!P.trim())return;let D;try{D=JSON.parse(P)}catch{q$.push(P),Y$(P),j$("subagent.child.stdout",P);return}if(u$(D),q?.writeChildEvent(D),B?.(D),D.type==="tool_execution_start"&&D.toolName){p=p||qj(D.toolName,D.args);let i=w0(D.args??{});Y$(i?`${D.toolName}: ${i}`:D.toolName);return}if((D.type==="message_end"||D.type==="tool_result_end")&&D.message){y$.push(D.message);let i=s$(D.message.content);if(i)o$(i);if(D.type!=="message_end"||D.message.role!=="assistant")return;if(D.message.model)g$=D.message.model;if(D.message.errorMessage)s=D.message.errorMessage;let M$=D.message.usage;if(M$)K$.turns++,K$.input+=M$.input??M$.inputTokens??0,K$.output+=M$.output??M$.outputTokens??0,K$.cacheRead+=M$.cacheRead??0,K$.cacheWrite+=M$.cacheWrite??0,K$.cost+=M$.cost?.total??0;if(hj(D.message)){if(!D.message.errorMessage&&s$(D.message.content).trim())s=void 0;a||=!D.message.errorMessage,e$()}}},H$=(P)=>{if(n+=P,W$+=P,S.write(P),!U)return;let D=W$.split(`
56
- `);W$=D.pop()||"";for(let i of D){if(!i.trim())continue;j$("subagent.child.stderr",i)}},k$=1000,W0=3000,Y=3000,u=!1,U$=!1,a=!1,N$,f$,S$,t$,P$,V$=!1,l$=K8(f,{idleMs:2000,hardMs:8000});f.stdout.on("data",(P)=>{let D=P.toString();d$+=D;let i=d$.split(`
57
- `);d$=i.pop()||"";for(let M$ of i)c(M$)}),f.stderr.on("data",(P)=>{H$(P.toString())}),G?.(()=>{if(V$||X$)return;if(E$=!0,!A$)A$="Interrupted. Waiting for explicit next action.";n$(f,"SIGINT"),setTimeout(()=>{if(!V$&&!X$)n$(f,"SIGTERM")},1000).unref?.()}),O?.(()=>{if(V$||X$)return;X$=!0,E$=!1,A$=T??"Subagent timed out.",n$(f,"SIGTERM"),S$=setTimeout(()=>{if(!V$)n$(f,"SIGKILL")},Y),S$.unref?.()}),y?.((P,D)=>{if(V$||X$||_$)return;_$=!0,E=P,t=D,E$=!1,A$=P,n$(f,"SIGINT"),t$=setTimeout(()=>{if(!V$&&!X$)n$(f,"SIGTERM")},1000),t$.unref?.(),P$=setTimeout(()=>{if(!V$&&!X$)n$(f,"SIGKILL")},4000),P$.unref?.()});let p$=()=>{if(N$)clearTimeout(N$),N$=void 0;if(f$)clearTimeout(f$),f$=void 0;if(S$)clearTimeout(S$),S$=void 0;if(t$)clearTimeout(t$),t$=void 0;if(P$)clearTimeout(P$),P$=void 0};function e$(){if(u||N$||V$)return;N$=setTimeout(()=>{if(V$)return;if(!n$(f,"SIGTERM"))return;if(U$=!0,!a&&!A$&&!s)A$=`Subagent process did not exit within ${k$}ms after its final message. Forcing termination.`;f$=setTimeout(()=>{if(V$)return;U$=n$(f,"SIGKILL")||U$},W0),f$.unref?.()},k$),N$.unref?.()}f.on("exit",()=>{u=!0,p$()}),f.on("close",(P,D)=>{if(V$=!0,G?.(void 0),O?.(void 0),y?.(void 0),p$(),l$(),d$.trim())c(d$);if(W$.trim())j$("subagent.child.stderr",W$);S.end();let i=j1(y$)||q$.join(`
58
- `).trim(),M$=A$??s,l0=U$&&a&&!M$;h({stderr:n,exitCode:X$?1:_$?1:E$||l0?0:U$||D?P??1:P,messages:y$,usage:K$,model:g$,error:X$?T??"Subagent timed out.":_$?E:E$||l0?void 0:M$,finalOutput:X$&&!i.trim()?T??"Subagent timed out.":i,interrupted:E$,timedOut:X$,turnBudget:t,turnBudgetExceeded:_$,wrapUpRequested:t?.outcome==="wrap-up-requested"||_$||void 0,observedMutationAttempt:p})}),f.on("error",(P)=>{V$=!0,G?.(void 0),O?.(void 0),y?.(void 0),p$(),l$(),S.end();let D=j1(y$)||q$.join(`
59
- `).trim(),i=P instanceof Error?P.message:String(P);h({stderr:n,exitCode:1,messages:y$,usage:K$,model:g$,error:X$?T??"Subagent timed out.":_$?E:A$??s??i,finalOutput:X$&&!D.trim()?T??"Subagent timed out.":D,timedOut:X$,turnBudget:t,turnBudgetExceeded:_$,wrapUpRequested:t?.outcome==="wrap-up-requested"||_$||void 0,observedMutationAttempt:p})})})}function u5(){let $=u1();if($)return $;throw Error(`Could not resolve ${k0} package root`)}async function l5($,j,J){let Z=J??u5(),Q=r.join(Z,"dist","core","export-html","index.js"),U=(await import(I5(Q).href)).exportFromFile;if(typeof U!=="function")throw Error("exportFromFile not available");let G=r.join(j,`${r.basename($,".jsonl")}.html`);return U($,{outputPath:G})}function p5($){try{if(u8("gh",["auth","status"],{encoding:"utf-8"}).status!==0)return{error:"GitHub CLI is not logged in. Run 'gh auth login' first."}}catch{return{error:"GitHub CLI (gh) is not installed."}}try{let j=u8("gh",["gist","create",$],{encoding:"utf-8"});if(j.status!==0)return{error:(j.stderr||"").trim()||"Failed to create gist."};let J=(j.stdout||"").trim(),Z=J.split("/").pop();if(!Z)return{error:"Failed to parse gist ID."};return{shareUrl:`https://shittycodingagent.ai/session/?${Z}`,gistUrl:J}}catch(j){return{error:String(j)}}}function n8($){if($<1000)return`${$}ms`;if($<60000)return`${($/1000).toFixed(1)}s`;let j=Math.floor($/60000),J=Math.floor($%60000/1000);return`${j}m${J}s`}function n5($,j){let J=[];if(J.push(`# Subagent run ${j.id}`),J.push(""),J.push(`- **Mode:** ${j.mode}`),J.push(`- **CWD:** ${j.cwd}`),J.push(`- **Started:** ${new Date(j.startedAt).toISOString()}`),J.push(`- **Ended:** ${new Date(j.endedAt).toISOString()}`),J.push(`- **Duration:** ${n8(j.endedAt-j.startedAt)}`),j.sessionFile)J.push(`- **Session:** ${j.sessionFile}`);if(j.shareUrl)J.push(`- **Share:** ${j.shareUrl}`);if(j.shareError)J.push(`- **Share error:** ${j.shareError}`);if(j.artifactsDir)J.push(`- **Artifacts:** ${j.artifactsDir}`);if(J.push(""),J.push("## Steps"),J.push("| Step | Agent | Status | Duration |"),J.push("| --- | --- | --- | --- |"),j.steps.forEach((Z,Q)=>{let X=Z.durationMs!==void 0?n8(Z.durationMs):"-";J.push(`| ${Q+1} | ${Z.agent} | ${Z.status} | ${X} |`)}),J.push(""),J.push("## Summary"),j.truncated)J.push("_Output truncated_"),J.push("");J.push(j.summary.trim()||"(no output)"),J.push(""),e.writeFileSync($,J.join(`
60
- `),"utf-8")}async function kj($,j){if($.importAsyncRoot){let j$=!1;j.registerTimeout?.(()=>{j$=!0;let c;try{c=R0($.importAsyncRoot.asyncDir)?.pid}catch{c=void 0}try{m1({asyncDir:$.importAsyncRoot.asyncDir,pid:c,source:"ancestor-timeout"})}catch{}});try{let c=await x8($.importAsyncRoot,{shouldAbort:()=>j$||j.timeoutSignal?.aborted===!0||j.skipAcceptance?.()===!0,timeoutMessage:j.timeoutMessage});try{e.writeFileSync(j.outputFile,c.output,"utf-8")}catch{}let H$=j$||c.timedOut===!0||j.timeoutSignal?.aborted===!0||j.skipAcceptance?.()===!0;return{agent:c.agent,output:H$?j.timeoutMessage??"Subagent timed out.":c.output,exitCode:H$?1:c.exitCode,error:H$?j.timeoutMessage??"Subagent timed out.":c.error,timedOut:H$?!0:void 0,sessionFile:c.sessionFile,intercomTarget:c.intercomTarget,model:c.model,attemptedModels:c.attemptedModels,modelAttempts:c.modelAttempts,totalCost:c.totalCost,structuredOutput:H$?void 0:c.structuredOutput,structuredOutputPath:H$?void 0:c.structuredOutputPath,structuredOutputSchemaPath:H$?void 0:c.structuredOutputSchemaPath,acceptance:H$?void 0:c.acceptance}}finally{j.registerTimeout?.(void 0)}}let J=$.structuredOutput??($.structuredOutputSchema?fJ($.structuredOutputSchema,r.join(r.dirname(j.outputFile),"structured-output")):void 0),Z=new RegExp(j.placeholder.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),Q=$.task.replace(Z,()=>j.previousOutput);Q=$8(Q,j.outputs??{});let X=Q;if($.effectiveAcceptance){let j$=I8($.effectiveAcceptance);if(j$)Q=`${Q}
61
- ${j$}`}let W=Boolean($.sessionFile)||j.sessionEnabled,U=$.sessionFile?void 0:j.sessionDir,G,B;if(j.artifactsDir&&j.artifactConfig?.enabled!==!1){let j$=j.flatStepCount>1?j.flatIndex:void 0;if(G=c1(j.artifactsDir,j.id,$.agent,j$),e.mkdirSync(j.artifactsDir,{recursive:!0}),j.artifactConfig?.includeInput!==!1)e.writeFileSync(G.inputPath,`# Task for ${$.agent}
62
-
63
- ${Q}`,"utf-8");if(j.artifactConfig?.includeTranscript!==!1)B=YJ({transcriptPath:G.transcriptPath,source:"async",runId:j.id,agent:$.agent,childIndex:j.flatIndex,cwd:$.cwd??j.cwd})}B?.writeInitialUserMessage(Q);let q=$.modelCandidates&&$.modelCandidates.length>0?$.modelCandidates:$.model?[$.model]:[void 0],O=[],T=[],y=[],h=r.join(r.dirname(j.outputFile),"events.jsonl"),S,v$,k=!1,f=j.turnBudget?Rj(j.turnBudget):void 0,n=$.toolBudget?C0($.toolBudget):void 0,d$=!1;for(let j$=0;j$<q.length;j$++){if(j.timeoutSignal?.aborted||j.skipAcceptance?.())break;let c=q[j$];j.onAttemptStart?.({model:c,thinking:O0(c,$.thinking)});let H$=BJ($.outputPath);if(J)try{if(e.existsSync(J.outputPath))e.unlinkSync(J.outputPath)}catch{}let{args:k$,env:W0,tempDir:Y}=lJ({parentSessionId:$.parentSessionId,baseArgs:["--mode","json","-p"],task:Q,sessionEnabled:W,sessionDir:U,sessionFile:$.sessionFile,model:c,inheritProjectContext:$.inheritProjectContext,inheritSkills:$.inheritSkills,requireReadTool:Boolean($.skills?.length),tools:$.tools,extensions:$.extensions,subagentOnlyExtensions:$.subagentOnlyExtensions,systemPrompt:d8($.systemPrompt??"",j.turnBudget),systemPromptMode:$.systemPromptMode,mcpDirectTools:$.mcpDirectTools,cwd:$.cwd??j.cwd,promptFileStem:$.agent,intercomSessionName:j.childIntercomTarget,orchestratorIntercomTarget:j.orchestratorIntercomTarget,runId:j.id,childAgentName:$.agent,childIndex:j.flatIndex,parentEventSink:j.nestedRoute?.eventSink,parentControlInbox:j.nestedRoute?.controlInbox,parentRootRunId:j.nestedRoute?.rootRunId,parentCapabilityToken:j.nestedRoute?.capabilityToken,steerInboxDir:j.steerInboxDir,structuredOutput:J,toolBudget:$.toolBudget}),u=await o5(k$,$.cwd??j.cwd,j.outputFile,W0,j.piPackageRoot,j.piArgv1,$.maxSubagentDepth,{eventsPath:h,runId:j.id,stepIndex:j.flatIndex,agent:$.agent},j.registerInterrupt,j.onChildEvent,B,j.registerTimeout,j.timeoutMessage,j.registerTurnBudgetAbort);if(u.turnBudget)f=u.turnBudget;else if(j.turnBudget){let P=u.messages.filter((M$)=>M$.role==="assistant"),D=P.length,i=P.at(-1);if(D>0&&D<j.turnBudget.maxTurns)f={...j.turnBudget,outcome:"within-budget",turnCount:D};else if(D>=j.turnBudget.maxTurns)f=O1(j.turnBudget,D,wj(j.turnBudget,D,i?hj(i):!1))}pJ(Y);let U$=u.exitCode===0&&!u.error?QJ(u.messages):null,a=J?!e.existsSync(J.outputPath):!1,N$=u.exitCode===0&&!u.error&&!U$?.hasError&&!u.finalOutput.trim()&&(!J||a)?"Subagent produced no output (possible model cold-start or empty response).":void 0,f$,S$;if(J&&u.exitCode===0&&!u.error&&!U$?.hasError&&!N$){let P=PJ({schema:J.schema,schemaPath:J.schemaPath,outputPath:J.outputPath});if(P.error)S$=P.error;else f$=P.value}let P$=(u.exitCode===0&&!u.error&&!U$?.hasError&&!N$&&$.completionGuard!==!1?q8({agent:$.agent,task:X,messages:u.messages,tools:$.tools,mcpDirectTools:$.mcpDirectTools}):void 0)?.triggered===!0&&!u.observedMutationAttempt,V$=P$?`Subagent completed without making edits for an implementation task.
64
- It appears to have returned planning or scratchpad output instead of applying changes.`:void 0,l$=P$?1:S$?1:U$?.hasError?U$.exitCode??1:N$?1:u.error&&u.exitCode===0?1:u.exitCode,p$=V$??S$??(U$?.hasError?U$.details?`${U$.errorType} failed (exit ${l$}): ${U$.details}`:`${U$.errorType} failed with exit code ${l$}`:N$??(u.error||(u.exitCode!==0&&u.stderr.trim()?u.stderr.trim():void 0))),e$={model:c??u.model??$.model??"default",success:l$===0&&!p$,exitCode:l$,error:p$,usage:u.usage};if(T.push(e$),c)O.push(c);if(k=P$,v$=H$,$.toolBudget){let P=u.messages.filter((i)=>i.role==="toolResult"),D=P.find((i)=>s$(i.content).includes("Tool budget hard limit reached"));d$=Boolean(D),n=Z1($.toolBudget,P.length,D?D.toolName:void 0)}if(S={...u,exitCode:l$,model:c??u.model,error:p$,structuredOutput:f$},u.turnBudgetExceeded)break;if(u.timedOut||j.timeoutSignal?.aborted||j.skipAcceptance?.())break;if(e$.success||P$)break;if(!H8(p$)||j$===q.length-1)break;y.push(V8(e$,q[j$+1]))}let W$=S?.finalOutput??"",y$=Cj(W$),K$=$.outputPath&&S?.exitCode===0?_J($.outputPath,y$,v$):{fullOutput:y$},g$=K$.fullOutput,A$=K$.savedPath?l1(K$.savedPath,g$):void 0,s=g$;if(y.length>0)s=`${y.join(`
647
+ ${task}`, "utf-8");
648
+ }
649
+ if (ctx.artifactConfig?.includeTranscript !== false) {
650
+ transcriptWriter = createChildTranscriptWriter({
651
+ transcriptPath: artifactPaths.transcriptPath,
652
+ source: "async",
653
+ runId: ctx.id,
654
+ agent: step.agent,
655
+ childIndex: ctx.flatIndex,
656
+ cwd: step.cwd ?? ctx.cwd
657
+ });
658
+ }
659
+ }
660
+ transcriptWriter?.writeInitialUserMessage(task);
661
+ const candidates = step.modelCandidates && step.modelCandidates.length > 0 ? step.modelCandidates : step.model ? [step.model] : [undefined];
662
+ const attemptedModels = [];
663
+ const modelAttempts = [];
664
+ const attemptNotes = [];
665
+ const eventsPath = path.join(path.dirname(ctx.outputFile), "events.jsonl");
666
+ let finalResult;
667
+ let finalOutputSnapshot;
668
+ let completionGuardTriggeredFinal = false;
669
+ let turnBudget = ctx.turnBudget ? initialTurnBudgetState(ctx.turnBudget) : undefined;
670
+ let toolBudget = step.toolBudget ? initialToolBudgetState(step.toolBudget) : undefined;
671
+ let toolBudgetBlocked = false;
672
+ for (let index = 0;index < candidates.length; index++) {
673
+ if (ctx.timeoutSignal?.aborted || ctx.skipAcceptance?.())
674
+ break;
675
+ const candidate = candidates[index];
676
+ ctx.onAttemptStart?.({ model: candidate, thinking: resolveEffectiveThinking(candidate, step.thinking) });
677
+ const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
678
+ if (effectiveStructuredOutput) {
679
+ try {
680
+ if (fs.existsSync(effectiveStructuredOutput.outputPath))
681
+ fs.unlinkSync(effectiveStructuredOutput.outputPath);
682
+ } catch {}
683
+ }
684
+ const { args, env, tempDir } = buildPiArgs({
685
+ parentSessionId: step.parentSessionId,
686
+ baseArgs: ["--mode", "json", "-p"],
687
+ task,
688
+ sessionEnabled,
689
+ sessionDir,
690
+ sessionFile: step.sessionFile,
691
+ model: candidate,
692
+ inheritProjectContext: step.inheritProjectContext,
693
+ inheritSkills: step.inheritSkills,
694
+ requireReadTool: Boolean(step.skills?.length),
695
+ tools: step.tools,
696
+ extensions: step.extensions,
697
+ subagentOnlyExtensions: step.subagentOnlyExtensions,
698
+ systemPrompt: appendTurnBudgetSystemPrompt(step.systemPrompt ?? "", ctx.turnBudget),
699
+ systemPromptMode: step.systemPromptMode,
700
+ mcpDirectTools: step.mcpDirectTools,
701
+ cwd: step.cwd ?? ctx.cwd,
702
+ promptFileStem: step.agent,
703
+ intercomSessionName: ctx.childIntercomTarget,
704
+ orchestratorIntercomTarget: ctx.orchestratorIntercomTarget,
705
+ runId: ctx.id,
706
+ childAgentName: step.agent,
707
+ childIndex: ctx.flatIndex,
708
+ parentEventSink: ctx.nestedRoute?.eventSink,
709
+ parentControlInbox: ctx.nestedRoute?.controlInbox,
710
+ parentRootRunId: ctx.nestedRoute?.rootRunId,
711
+ parentCapabilityToken: ctx.nestedRoute?.capabilityToken,
712
+ steerInboxDir: ctx.steerInboxDir,
713
+ structuredOutput: effectiveStructuredOutput,
714
+ toolBudget: step.toolBudget
715
+ });
716
+ const run = await runPiStreaming(args, step.cwd ?? ctx.cwd, ctx.outputFile, env, ctx.piPackageRoot, ctx.piArgv1, step.maxSubagentDepth, { eventsPath, runId: ctx.id, stepIndex: ctx.flatIndex, agent: step.agent }, ctx.registerInterrupt, ctx.onChildEvent, transcriptWriter, ctx.registerTimeout, ctx.timeoutMessage, ctx.registerTurnBudgetAbort);
717
+ if (run.turnBudget)
718
+ turnBudget = run.turnBudget;
719
+ else if (ctx.turnBudget) {
720
+ const assistantMessages = run.messages.filter((message) => message.role === "assistant");
721
+ const turnCount = assistantMessages.length;
722
+ const lastAssistantMessage = assistantMessages.at(-1);
723
+ if (turnCount > 0 && turnCount < ctx.turnBudget.maxTurns) {
724
+ turnBudget = { ...ctx.turnBudget, outcome: "within-budget", turnCount };
725
+ } else if (turnCount >= ctx.turnBudget.maxTurns) {
726
+ turnBudget = turnBudgetState(ctx.turnBudget, turnCount, shouldAbortForTurnBudget(ctx.turnBudget, turnCount, lastAssistantMessage ? isTerminalAssistantStop(lastAssistantMessage) : false));
727
+ }
728
+ }
729
+ cleanupTempDir(tempDir);
730
+ const hiddenError = run.exitCode === 0 && !run.error ? detectSubagentError(run.messages) : null;
731
+ const missingStructuredOutput = effectiveStructuredOutput ? !fs.existsSync(effectiveStructuredOutput.outputPath) : false;
732
+ const emptyOutputError = run.exitCode === 0 && !run.error && !hiddenError?.hasError && !run.finalOutput.trim() && (!effectiveStructuredOutput || missingStructuredOutput) ? "Subagent produced no output (possible model cold-start or empty response)." : undefined;
733
+ let structuredOutput;
734
+ let structuredError;
735
+ if (effectiveStructuredOutput && run.exitCode === 0 && !run.error && !hiddenError?.hasError && !emptyOutputError) {
736
+ const structured = readStructuredOutput({
737
+ schema: effectiveStructuredOutput.schema,
738
+ schemaPath: effectiveStructuredOutput.schemaPath,
739
+ outputPath: effectiveStructuredOutput.outputPath
740
+ });
741
+ if (structured.error)
742
+ structuredError = structured.error;
743
+ else
744
+ structuredOutput = structured.value;
745
+ }
746
+ const completionGuard = run.exitCode === 0 && !run.error && !hiddenError?.hasError && !emptyOutputError && step.completionGuard !== false ? evaluateCompletionMutationGuard({
747
+ agent: step.agent,
748
+ task: taskForCompletionGuard,
749
+ messages: run.messages,
750
+ tools: step.tools,
751
+ mcpDirectTools: step.mcpDirectTools
752
+ }) : undefined;
753
+ const completionGuardTriggered = completionGuard?.triggered === true && !run.observedMutationAttempt;
754
+ const completionGuardError = completionGuardTriggered ? `Subagent completed without making edits for an implementation task.
755
+ It appears to have returned planning or scratchpad output instead of applying changes.` : undefined;
756
+ const effectiveExitCode = completionGuardTriggered ? 1 : structuredError ? 1 : hiddenError?.hasError ? hiddenError.exitCode ?? 1 : emptyOutputError ? 1 : run.error && run.exitCode === 0 ? 1 : run.exitCode;
757
+ const error = completionGuardError ?? structuredError ?? (hiddenError?.hasError ? hiddenError.details ? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}` : `${hiddenError.errorType} failed with exit code ${effectiveExitCode}` : emptyOutputError ?? (run.error || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined)));
758
+ const attempt = {
759
+ model: candidate ?? run.model ?? step.model ?? "default",
760
+ success: effectiveExitCode === 0 && !error,
761
+ exitCode: effectiveExitCode,
762
+ error,
763
+ usage: run.usage
764
+ };
765
+ modelAttempts.push(attempt);
766
+ if (candidate)
767
+ attemptedModels.push(candidate);
768
+ completionGuardTriggeredFinal = completionGuardTriggered;
769
+ finalOutputSnapshot = outputSnapshot;
770
+ if (step.toolBudget) {
771
+ const toolMessages = run.messages.filter((message) => message.role === "toolResult");
772
+ const blockedMessage = toolMessages.find((message) => extractTextFromContent(message.content).includes("Tool budget hard limit reached"));
773
+ toolBudgetBlocked = Boolean(blockedMessage);
774
+ toolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? blockedMessage.toolName : undefined);
775
+ }
776
+ finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput };
777
+ if (run.turnBudgetExceeded)
778
+ break;
779
+ if (run.timedOut || ctx.timeoutSignal?.aborted || ctx.skipAcceptance?.())
780
+ break;
781
+ if (attempt.success || completionGuardTriggered)
782
+ break;
783
+ if (!isRetryableModelFailure(error) || index === candidates.length - 1)
784
+ break;
785
+ attemptNotes.push(formatModelAttemptNote(attempt, candidates[index + 1]));
786
+ }
787
+ const rawOutput = finalResult?.finalOutput ?? "";
788
+ const outputForPersistence = stripAcceptanceReport(rawOutput);
789
+ const resolvedOutput = step.outputPath && finalResult?.exitCode === 0 ? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot) : { fullOutput: outputForPersistence };
790
+ const output = resolvedOutput.fullOutput;
791
+ const outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, output) : undefined;
792
+ let outputForSummary = output;
793
+ if (attemptNotes.length > 0) {
794
+ outputForSummary = `${attemptNotes.join(`
65
795
  `)}
66
796
 
67
- ${s}`.trim();if(!S?.timedOut&&S?.turnBudgetExceeded&&f)s=o8(u0(f,f.turnCount),s);else if(!S?.timedOut&&f?.outcome==="wrap-up-requested"){let j$=bj(f,f.wrapUpRequestedAtTurn??f.turnCount);s=s.trim()?`${j$}
797
+ ${outputForSummary}`.trim();
798
+ }
799
+ if (!finalResult?.timedOut && finalResult?.turnBudgetExceeded && turnBudget) {
800
+ outputForSummary = formatTurnBudgetOutput(turnBudgetExceededMessage(turnBudget, turnBudget.turnCount), outputForSummary);
801
+ } else if (!finalResult?.timedOut && turnBudget?.outcome === "wrap-up-requested") {
802
+ const note = turnBudgetSoftNote(turnBudget, turnBudget.wrapUpRequestedAtTurn ?? turnBudget.turnCount);
803
+ outputForSummary = outputForSummary.trim() ? `${note}
68
804
 
69
- ${s}`:j$}let E$=W$;s=MJ({fullOutput:s,outputPath:$.outputPath,outputMode:$.outputMode,exitCode:S?.exitCode??1,savedPath:K$.savedPath,outputReference:A$,saveError:K$.saveError}).displayOutput;let _$=$.effectiveAcceptance&&!S?.turnBudgetExceeded&&!j.timeoutSignal?.aborted&&!j.skipAcceptance?.()?await M1({acceptance:$.effectiveAcceptance,output:E$,cwd:$.cwd??j.cwd,signal:j.timeoutSignal,abortMessage:j.timeoutMessage??"Subagent timed out."}):void 0,E=S?.timedOut===!0||j.timeoutSignal?.aborted===!0||j.skipAcceptance?.()===!0,t=S?.turnBudgetExceeded===!0,p=E||t?void 0:_$,q$=p?L1(p):void 0,Y$=q$&&p?.explicit&&(S?.exitCode??1)===0&&!S?.interrupted&&!E&&!t,o$=E||t?1:Y$?1:S?.exitCode??1,u$=E?j.timeoutMessage??"Subagent timed out.":t?S?.error??(f?u0(f,f.turnCount):"Subagent exceeded turn budget."):Y$?S?.error?`${S.error}
70
- ${q$}`:q$:S?.error;if(G&&j.artifactConfig?.enabled!==!1){if(j.artifactConfig?.includeOutput!==!1)e.writeFileSync(G.outputPath,g$,"utf-8");if(j.artifactConfig?.includeMetadata!==!1)e.writeFileSync(G.metadataPath,JSON.stringify({runId:j.id,agent:$.agent,task:Q,exitCode:o$,model:S?.model,attemptedModels:O.length>0?O:void 0,modelAttempts:T,...B?{transcriptPath:G.transcriptPath}:{},transcriptError:B?.getError(),skills:$.skills,timestamp:Date.now()},null,2),"utf-8")}return{agent:$.agent,output:s,exitCode:o$,error:u$,sessionFile:$.sessionFile,intercomTarget:j.childIntercomTarget,model:S?.model,attemptedModels:O.length>0?O:void 0,modelAttempts:T,totalCost:d5(T),artifactPaths:G,transcriptPath:B?G?.transcriptPath:void 0,transcriptError:B?.getError(),interrupted:E||t?!1:S?.interrupted,timedOut:E?!0:S?.timedOut,turnBudget:f,turnBudgetExceeded:t||void 0,wrapUpRequested:S?.wrapUpRequested||f?.outcome==="wrap-up-requested"||t||void 0,toolBudget:n,toolBudgetBlocked:d$||void 0,completionGuardTriggered:k,structuredOutput:E||t?void 0:S?.structuredOutput,structuredOutputPath:E||t?void 0:J?.outputPath,structuredOutputSchemaPath:E||t?void 0:J?.schemaPath,acceptance:p}}function i8($){for(let j=0;j<$.group.parallel.length;j++){let J=$.groupStartFlatIndex+j;$.statusPayload.steps[J].status="failed",$.statusPayload.steps[J].startedAt=$.failedAt,$.statusPayload.steps[J].endedAt=$.failedAt,$.statusPayload.steps[J].durationMs=0,$.statusPayload.steps[J].exitCode=1,$.results.push({agent:$.group.parallel[j].agent,output:$.setupError,success:!1,exitCode:1,sessionFile:$.group.parallel[j].sessionFile})}$.statusPayload.currentStep=$.groupStartFlatIndex,$.statusPayload.lastUpdate=$.failedAt,$.statusPayload.outputFile=r.join($.asyncDir,`output-${$.groupStartFlatIndex}.log`),D$($.statusPath,$.statusPayload),$$($.eventsPath,JSON.stringify({type:"subagent.parallel.completed",ts:$.failedAt,runId:$.runId,stepIndex:$.stepIndex,success:!1}))}function i5($){for(let j=0;j<$.group.parallel.length;j++){let J=$.groupStartFlatIndex+j;$.statusPayload.steps[J].status="pending",$.statusPayload.steps[J].startedAt=void 0,$.statusPayload.steps[J].endedAt=void 0,$.statusPayload.steps[J].durationMs=void 0,$.statusPayload.steps[J].lastActivityAt=void 0,$.statusPayload.steps[J].activityState=void 0,$.statusPayload.steps[J].error=void 0}$.statusPayload.currentStep=$.groupStartFlatIndex,$.statusPayload.activityState=void 0,$.statusPayload.lastActivityAt=$.groupStartTime,$.statusPayload.lastUpdate=$.groupStartTime,$.statusPayload.outputFile=r.join($.asyncDir,`output-${$.groupStartFlatIndex}.log`),D$($.statusPath,$.statusPayload),$$($.eventsPath,JSON.stringify({type:"subagent.parallel.started",ts:$.groupStartTime,runId:$.runId,stepIndex:$.stepIndex,agents:$.group.parallel.map((j)=>j.agent),count:$.group.parallel.length}))}function r5($,j,J,Z){if(!J)return{taskForRun:$,taskCwd:j};return{taskForRun:{...$,cwd:void 0},taskCwd:J.worktrees[Z].agentCwd}}function s5($,j,J,Z,Q){if(!j)return $;let X=r.join(J,"worktree-diffs",`step-${Z}`),W=S8(j,Q.parallel.map((G)=>G.agent),X),U=D8(W);if(!U)return $;return`${$}
805
+ ${outputForSummary}` : note;
806
+ }
807
+ const outputForAcceptance = rawOutput;
808
+ const finalizedOutput = finalizeSingleOutput({
809
+ fullOutput: outputForSummary,
810
+ outputPath: step.outputPath,
811
+ outputMode: step.outputMode,
812
+ exitCode: finalResult?.exitCode ?? 1,
813
+ savedPath: resolvedOutput.savedPath,
814
+ outputReference,
815
+ saveError: resolvedOutput.saveError
816
+ });
817
+ outputForSummary = finalizedOutput.displayOutput;
818
+ const acceptance = step.effectiveAcceptance && !finalResult?.turnBudgetExceeded && !ctx.timeoutSignal?.aborted && !ctx.skipAcceptance?.() ? await evaluateAcceptance({
819
+ acceptance: step.effectiveAcceptance,
820
+ output: outputForAcceptance,
821
+ cwd: step.cwd ?? ctx.cwd,
822
+ signal: ctx.timeoutSignal,
823
+ abortMessage: ctx.timeoutMessage ?? "Subagent timed out."
824
+ }) : undefined;
825
+ const timedOutAfterAcceptance = finalResult?.timedOut === true || ctx.timeoutSignal?.aborted === true || ctx.skipAcceptance?.() === true;
826
+ const turnBudgetExceeded = finalResult?.turnBudgetExceeded === true;
827
+ const effectiveAcceptance = timedOutAfterAcceptance || turnBudgetExceeded ? undefined : acceptance;
828
+ const acceptanceFailure = effectiveAcceptance ? acceptanceFailureMessage(effectiveAcceptance) : undefined;
829
+ const acceptanceCanFailRun = acceptanceFailure && effectiveAcceptance?.explicit && (finalResult?.exitCode ?? 1) === 0 && !finalResult?.interrupted && !timedOutAfterAcceptance && !turnBudgetExceeded;
830
+ const effectiveFinalExitCode = timedOutAfterAcceptance || turnBudgetExceeded ? 1 : acceptanceCanFailRun ? 1 : finalResult?.exitCode ?? 1;
831
+ const effectiveFinalError = timedOutAfterAcceptance ? ctx.timeoutMessage ?? "Subagent timed out." : turnBudgetExceeded ? finalResult?.error ?? (turnBudget ? turnBudgetExceededMessage(turnBudget, turnBudget.turnCount) : "Subagent exceeded turn budget.") : acceptanceCanFailRun ? finalResult?.error ? `${finalResult.error}
832
+ ${acceptanceFailure}` : acceptanceFailure : finalResult?.error;
833
+ if (artifactPaths && ctx.artifactConfig?.enabled !== false) {
834
+ if (ctx.artifactConfig?.includeOutput !== false) {
835
+ fs.writeFileSync(artifactPaths.outputPath, output, "utf-8");
836
+ }
837
+ if (ctx.artifactConfig?.includeMetadata !== false) {
838
+ fs.writeFileSync(artifactPaths.metadataPath, JSON.stringify({
839
+ runId: ctx.id,
840
+ agent: step.agent,
841
+ task,
842
+ exitCode: effectiveFinalExitCode,
843
+ model: finalResult?.model,
844
+ attemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,
845
+ modelAttempts,
846
+ ...transcriptWriter ? { transcriptPath: artifactPaths.transcriptPath } : {},
847
+ transcriptError: transcriptWriter?.getError(),
848
+ skills: step.skills,
849
+ timestamp: Date.now()
850
+ }, null, 2), "utf-8");
851
+ }
852
+ }
853
+ return {
854
+ agent: step.agent,
855
+ output: outputForSummary,
856
+ exitCode: effectiveFinalExitCode,
857
+ error: effectiveFinalError,
858
+ sessionFile: step.sessionFile,
859
+ intercomTarget: ctx.childIntercomTarget,
860
+ model: finalResult?.model,
861
+ attemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,
862
+ modelAttempts,
863
+ totalCost: costSummaryFromAttempts(modelAttempts),
864
+ artifactPaths,
865
+ transcriptPath: transcriptWriter ? artifactPaths?.transcriptPath : undefined,
866
+ transcriptError: transcriptWriter?.getError(),
867
+ interrupted: timedOutAfterAcceptance || turnBudgetExceeded ? false : finalResult?.interrupted,
868
+ timedOut: timedOutAfterAcceptance ? true : finalResult?.timedOut,
869
+ turnBudget,
870
+ turnBudgetExceeded: turnBudgetExceeded || undefined,
871
+ wrapUpRequested: finalResult?.wrapUpRequested || turnBudget?.outcome === "wrap-up-requested" || turnBudgetExceeded || undefined,
872
+ toolBudget,
873
+ toolBudgetBlocked: toolBudgetBlocked || undefined,
874
+ completionGuardTriggered: completionGuardTriggeredFinal,
875
+ structuredOutput: timedOutAfterAcceptance || turnBudgetExceeded ? undefined : finalResult?.structuredOutput,
876
+ structuredOutputPath: timedOutAfterAcceptance || turnBudgetExceeded ? undefined : effectiveStructuredOutput?.outputPath,
877
+ structuredOutputSchemaPath: timedOutAfterAcceptance || turnBudgetExceeded ? undefined : effectiveStructuredOutput?.schemaPath,
878
+ acceptance: effectiveAcceptance
879
+ };
880
+ }
881
+ function markParallelGroupSetupFailure(input) {
882
+ for (let taskIndex = 0;taskIndex < input.group.parallel.length; taskIndex++) {
883
+ const flatTaskIndex = input.groupStartFlatIndex + taskIndex;
884
+ input.statusPayload.steps[flatTaskIndex].status = "failed";
885
+ input.statusPayload.steps[flatTaskIndex].startedAt = input.failedAt;
886
+ input.statusPayload.steps[flatTaskIndex].endedAt = input.failedAt;
887
+ input.statusPayload.steps[flatTaskIndex].durationMs = 0;
888
+ input.statusPayload.steps[flatTaskIndex].exitCode = 1;
889
+ input.results.push({ agent: input.group.parallel[taskIndex].agent, output: input.setupError, success: false, exitCode: 1, sessionFile: input.group.parallel[taskIndex].sessionFile });
890
+ }
891
+ input.statusPayload.currentStep = input.groupStartFlatIndex;
892
+ input.statusPayload.lastUpdate = input.failedAt;
893
+ input.statusPayload.outputFile = path.join(input.asyncDir, `output-${input.groupStartFlatIndex}.log`);
894
+ writeAtomicJson(input.statusPath, input.statusPayload);
895
+ appendJsonl(input.eventsPath, JSON.stringify({
896
+ type: "subagent.parallel.completed",
897
+ ts: input.failedAt,
898
+ runId: input.runId,
899
+ stepIndex: input.stepIndex,
900
+ success: false
901
+ }));
902
+ }
903
+ function markParallelGroupRunning(input) {
904
+ for (let taskIndex = 0;taskIndex < input.group.parallel.length; taskIndex++) {
905
+ const flatTaskIndex = input.groupStartFlatIndex + taskIndex;
906
+ input.statusPayload.steps[flatTaskIndex].status = "pending";
907
+ input.statusPayload.steps[flatTaskIndex].startedAt = undefined;
908
+ input.statusPayload.steps[flatTaskIndex].endedAt = undefined;
909
+ input.statusPayload.steps[flatTaskIndex].durationMs = undefined;
910
+ input.statusPayload.steps[flatTaskIndex].lastActivityAt = undefined;
911
+ input.statusPayload.steps[flatTaskIndex].activityState = undefined;
912
+ input.statusPayload.steps[flatTaskIndex].error = undefined;
913
+ }
914
+ input.statusPayload.currentStep = input.groupStartFlatIndex;
915
+ input.statusPayload.activityState = undefined;
916
+ input.statusPayload.lastActivityAt = input.groupStartTime;
917
+ input.statusPayload.lastUpdate = input.groupStartTime;
918
+ input.statusPayload.outputFile = path.join(input.asyncDir, `output-${input.groupStartFlatIndex}.log`);
919
+ writeAtomicJson(input.statusPath, input.statusPayload);
920
+ appendJsonl(input.eventsPath, JSON.stringify({
921
+ type: "subagent.parallel.started",
922
+ ts: input.groupStartTime,
923
+ runId: input.runId,
924
+ stepIndex: input.stepIndex,
925
+ agents: input.group.parallel.map((task) => task.agent),
926
+ count: input.group.parallel.length
927
+ }));
928
+ }
929
+ function prepareParallelTaskRun(task, cwd, worktreeSetup, taskIndex) {
930
+ if (!worktreeSetup)
931
+ return { taskForRun: task, taskCwd: cwd };
932
+ return {
933
+ taskForRun: { ...task, cwd: undefined },
934
+ taskCwd: worktreeSetup.worktrees[taskIndex].agentCwd
935
+ };
936
+ }
937
+ function appendParallelWorktreeSummary(previousOutput, worktreeSetup, asyncDir, stepIndex, group) {
938
+ if (!worktreeSetup)
939
+ return previousOutput;
940
+ const diffsDir = path.join(asyncDir, "worktree-diffs", `step-${stepIndex}`);
941
+ const diffs = diffWorktrees(worktreeSetup, group.parallel.map((task) => task.agent), diffsDir);
942
+ const diffSummary = formatWorktreeDiffSummary(diffs);
943
+ if (!diffSummary)
944
+ return previousOutput;
945
+ return `${previousOutput}
71
946
 
72
- ${U}`}function a5($,j){let J=r.join($,"progress.md");if(!j.parallel.some((Z)=>Z.task.includes(`Update progress at: ${J}`)))return;ej($)}function fj($){if(!$.artifactsDir||$.artifactConfig?.enabled===!1||$.artifactConfig?.includeTranscript===!1)return;return c1($.artifactsDir,$.runId,$.agent,$.flatStepCount>1?$.flatIndex:void 0).transcriptPath}async function r8($){let{id:j,steps:J,resultPath:Z,cwd:Q,placeholder:X,taskIndex:W,totalTasks:U,maxOutput:G,artifactsDir:B,artifactConfig:q}=$,O=new y1($.globalConcurrencyLimit??tj),T="",y={},h=[],S=Date.now(),v$=$.share===!0,k=$.asyncDir,f=r.join(k,"status.json"),n=r.join(k,"events.jsonl"),d$=r.join(k,`subagent-log-${j}.md`),W$=$.controlConfig??LJ,y$=new Map,K$=new Map,g$=new Map,A$=[],s=!1,E$,X$,_$,E=!1,t=!1,p=$.timeoutMs!==void 0?`Subagent timed out after ${$.timeoutMs}ms.`:void 0,q$=new AbortController,Y$={input:0,output:0,total:0},o$,u$=aj(J),j$=u$.length,c=[],H$=[],k$=0;for(let H=0;H<J.length;H++){let V=J[H];if($0(V)){c.push({start:k$,count:V.parallel.length,stepIndex:H});for(let K of V.parallel){let _=k$,z=fj({artifactsDir:B,artifactConfig:q,runId:j,agent:K.agent,flatIndex:_,flatStepCount:j$});H$.push({agent:K.agent,phase:K.phase,label:K.label,outputName:K.outputName,structured:K.structured,status:"pending",...K.toolBudget?{toolBudget:C0(K.toolBudget)}:{},...K.sessionFile?{sessionFile:K.sessionFile}:{},...z?{transcriptPath:z}:{},skills:K.skills,model:K.model,thinking:K.thinking,attemptedModels:K.modelCandidates&&K.modelCandidates.length>0?K.modelCandidates:K.model?[K.model]:void 0,recentTools:[],recentOutput:[]}),k$++}}else if(j0(V))c.push({start:k$,count:1,stepIndex:H}),H$.push({agent:`expand:${V.parallel.agent}`,phase:V.phase??V.parallel.phase,label:V.label??V.parallel.label??`Dynamic fanout (${V.collect.as})`,outputName:V.collect.as,structured:Boolean(V.collect.outputSchema),status:"pending",...V.parallel.toolBudget?{toolBudget:C0(V.parallel.toolBudget)}:{},recentTools:[],recentOutput:[]}),k$++;else{let K=k$,_=fj({artifactsDir:B,artifactConfig:q,runId:j,agent:V.agent,flatIndex:K,flatStepCount:j$});H$.push({agent:V.agent,phase:V.phase,label:V.label,outputName:V.outputName,structured:V.structured,status:"pending",...V.toolBudget?{toolBudget:C0(V.toolBudget)}:{},...V.sessionFile?{sessionFile:V.sessionFile}:{},..._?{transcriptPath:_}:{},skills:V.skills,model:V.model,thinking:V.thinking,attemptedModels:V.modelCandidates&&V.modelCandidates.length>0?V.modelCandidates:V.model?[V.model]:void 0,recentTools:[],recentOutput:[]}),k$++}}let W0=Boolean($.sessionDir)||v$||u$.some((H)=>Boolean(H.sessionFile)),Y={lifecycleArtifactVersion:S0,runId:j,...$.sessionId?{sessionId:$.sessionId}:{},mode:$.resultMode??(u$.length>1?"chain":"single"),state:"running",lastActivityAt:S,startedAt:S,lastUpdate:S,...$.timeoutMs!==void 0?{timeoutMs:$.timeoutMs}:{},...$.deadlineAt!==void 0?{deadlineAt:$.deadlineAt}:{},...$.turnBudget?{turnBudget:Rj($.turnBudget)}:{},...$.toolBudget?{toolBudget:C0($.toolBudget)}:{},pid:process.pid,cwd:Q,currentStep:0,chainStepCount:J.length,parallelGroups:c,workflowGraph:$.workflowGraph,steps:H$,artifactsDir:B,sessionDir:$.sessionDir,outputFile:r.join(k,"output-0.log")};e.mkdirSync(k,{recursive:!0}),D$(f,Y);let u=(H)=>{if(!$.nestedRoute||!$.nestedSelf)return;try{Y8($.nestedRoute,{type:H,ts:Date.now(),parentRunId:$.nestedSelf.parentRunId,parentStepIndex:$.nestedSelf.parentStepIndex,child:W8(Y,k,{id:j,parentRunId:$.nestedSelf.parentRunId,parentStepIndex:$.nestedSelf.parentStepIndex,depth:$.nestedSelf.depth,path:$.nestedSelf.path,mode:Y.mode,ts:Date.now()})})}catch(V){console.error("Failed to emit nested async status event:",V)}},U$=()=>{if(!$.workflowGraph)return;let H=structuredClone(Y.workflowGraph??$.workflowGraph),V=(_)=>{if(_==="complete"||_==="completed")return"completed";if(_==="running"||_==="failed"||_==="paused"||_==="pending")return _;return"pending"},K=(_)=>{if(_.flatIndex!==void 0){let z=Y.steps[_.flatIndex];if(z)_.status=V(z.status),_.error=z.error,_.acceptanceStatus=z.acceptance?.status;if(Y.currentStep===_.flatIndex)H.currentNodeId=_.id}for(let z of _.children??[])K(z);if(_.children?.length){if(_.children.every((z)=>z.status==="completed"))_.status="completed";else if(_.children.some((z)=>z.status==="running"))_.status="running";else if(_.children.some((z)=>z.status==="failed"))_.status="failed";else if(_.children.some((z)=>z.status==="paused"))_.status="paused"}if(_.error)_.status="failed"};for(let _ of H.nodes)K(_);Y.workflowGraph=H},a=()=>{U$(),D$(f,Y),u(Y.state==="running"||Y.state==="queued"?"subagent.nested.updated":"subagent.nested.completed")},N$=(H,V)=>{if(!V){y$.delete(H);return}if(y$.set(H,V),s)V()},f$=(H,V)=>{if(!V){K$.delete(H);return}if(K$.set(H,V),E)V()},S$=(H,V)=>{if(!V){g$.delete(H);return}g$.set(H,V)},t$=()=>{for(let H of[...y$.values()])H()},P$=()=>{for(let H of[...K$.values()])H()},V$=function*(H){for(let V of H??[])yield V,yield*V$(V.children),yield*V$(V.steps?.flatMap((K)=>K.children??[]))},l$=()=>{if(!$.nestedRoute)return;let H;try{H=Mj($.nestedRoute)}catch(V){$$(n,JSON.stringify({type:"subagent.nested.interrupt_failed",ts:Date.now(),runId:j,message:V instanceof Error?V.message:String(V)}));return}for(let V of V$(H.children)){if(V.state!=="running"&&V.state!=="queued")continue;let K=V.asyncDir??_j($.nestedRoute.rootRunId,V);if(!K)continue;try{KJ({asyncDir:K,pid:V.pid,source:"ancestor-interrupt"})}catch(_){$$(n,JSON.stringify({type:"subagent.nested.interrupt_failed",ts:Date.now(),runId:j,targetRunId:V.id,message:_ instanceof Error?_.message:String(_)}))}}},p$=()=>{if(!$.nestedRoute)return;let H;try{H=Mj($.nestedRoute)}catch(V){$$(n,JSON.stringify({type:"subagent.nested.timeout_failed",ts:Date.now(),runId:j,message:V instanceof Error?V.message:String(V)}));return}for(let V of V$(H.children)){if(V.state!=="running"&&V.state!=="queued")continue;let K=V.asyncDir??_j($.nestedRoute.rootRunId,V);if(!K)continue;try{m1({asyncDir:K,pid:V.pid,source:"ancestor-timeout"})}catch(_){$$(n,JSON.stringify({type:"subagent.nested.timeout_failed",ts:Date.now(),runId:j,targetRunId:V.id,message:_ instanceof Error?_.message:String(_)}))}}},e$=(H)=>({agent:H,output:"Paused after interrupt. Waiting for explicit next action.",exitCode:0,interrupted:!0}),P=(H)=>({agent:H,output:p??"Subagent timed out.",error:p??"Subagent timed out.",exitCode:1,timedOut:!0}),D=()=>{if(Y.mode!=="chain"||Y.state!=="running")return;let H=g8(k);if(H.length===0){let N=Dj(k);if((Y.pendingAppends??0)!==N)Y.pendingAppends=N,Y.lastUpdate=Date.now(),a();return}let V=H.flatMap((N)=>N.steps);J.push(...V);let K=Date.now(),_=Dj(k),z=c8({status:Y,steps:V,now:K,pendingAppends:_});if(p0.push(...Array.from({length:z.addedFlatSteps},()=>G1())),T0.push(...Array.from({length:z.addedFlatSteps},()=>{return})),$.childIntercomTargets)$.childIntercomTargets=Y.steps.map((N,w)=>Aj(j,N.agent,w));a();for(let N of H)$$(n,JSON.stringify({type:"subagent.chain.append.accepted",ts:K,runId:j,requestId:N.id,stepCount:N.steps.length,pendingAppends:_}))},i=(H,V,K,_)=>{let z=Y.workflowGraph?.nodes.find((N)=>N.id===`step-${H}`);if(!z)return;z.status=V,z.error=K,z.acceptanceStatus=_?.status??z.acceptanceStatus},M$=(H)=>{let V=Y.steps[H],K=V?.lastActivityAt??V?.startedAt??S,_=r.join(k,`output-${H}.log`);try{K=Math.max(K,e.statSync(_).mtimeMs)}catch(z){if(z.code!=="ENOENT")console.error(`Failed to inspect async output file '${_}':`,z)}return K},l0=new Set,vj=new Set,p0=H$.map(()=>G1()),T0=H$.map(()=>{return}),s8=300000,E0=(H)=>{if(!W$.enabled)return;let V=$.childIntercomTargets?.[H.index??Y.currentStep],K=H.type==="active_long_running"?W$.notifyChannels.filter((_)=>_!=="intercom"):W$.notifyChannels;if(K.length===0||!FJ(W$,H,l0,V))return;$$(n,JSON.stringify({type:"subagent.control",event:H,channels:K,childIntercomTarget:V,noticeText:p1(H,V),...$.controlIntercomTarget&&K.includes("intercom")?{intercom:{to:$.controlIntercomTarget,message:OJ(H,V)}}:{}}))},A1=()=>{let H=Y.steps.filter((V)=>V.status==="running"&&typeof V.currentTool==="string"&&V.currentTool.length>0).sort((V,K)=>(K.currentToolStartedAt??0)-(V.currentToolStartedAt??0))[0];Y.currentTool=H?.currentTool,Y.currentToolStartedAt=H?.currentToolStartedAt,Y.currentPath=H?.currentPath},gj=(H,V)=>{if(!W$.enabled||vj.has(H))return!1;let K=Y.steps[H];if(!K||K.status!=="running"||K.activityState==="needs_attention")return!1;let _=G8(W$,{startedAt:K.startedAt??S,now:V,turns:K.turnCount??0,tokens:K.tokens?.total??0});if(!_)return!1;vj.add(H);let z=K.activityState;K.activityState="active_long_running",Y.activityState=Y.activityState==="needs_attention"?"needs_attention":"active_long_running";let N=A0({type:"active_long_running",from:z,to:"active_long_running",runId:j,agent:K.agent,index:H,ts:V,message:`${K.agent} is still active but long-running`,reason:_,turns:K.turnCount,tokens:K.tokens?.total,toolCount:K.toolCount,currentTool:K.currentTool,currentToolDurationMs:K.currentToolStartedAt?Math.max(0,V-K.currentToolStartedAt):void 0,currentPath:K.currentPath,elapsedMs:V-(K.startedAt??S)});return E0(N),!0},N1=(H)=>{if(Y.state!=="running")return;let V=Y.steps.map((w,d)=>({step:w,index:d})).filter(({step:w})=>w.status==="running").map(({index:w})=>w),K=H.targetIndex!==void 0?[H.targetIndex]:V,_=Date.now(),z=[],N=[];for(let w of K){let d=Y.steps[w];if(!d){N.push({index:w,reason:"child index out of range"});continue}if(d.status!=="running"){N.push({index:w,reason:`child is ${d.status}`});continue}VJ(k,w,H),d.steerCount=(d.steerCount??0)+1,d.lastSteerAt=_,z.push(w)}if(z.length>0)Y.steerCount=(Y.steerCount??0)+z.length,Y.lastSteerAt=_,Y.lastUpdate=_,a();$$(n,JSON.stringify({type:"subagent.steer.requested",ts:_,runId:j,requestId:H.id,message:H.message,...H.source?{source:H.source}:{},...H.targetIndex!==void 0?{targetIndex:H.targetIndex}:{},acceptedIndexes:z,...N.length?{rejected:N}:{}}))},C1=(H)=>{let V=[];for(let K of A$.splice(0))if(K.targetIndex===void 0)N1({...K,targetIndex:H});else if(K.targetIndex===H)N1(K);else V.push(K);A$.push(...V)},T1=(H,V,K,_=Date.now())=>{let z=Y.steps[H];if(!z)return;z.model=V,z.thinking=K,Y.lastUpdate=_,a()},a8=(H,V,K,_)=>{let z=$.turnBudget,N=Y.steps[H];if(!z||!N||E||t||N.turnBudgetExceeded)return;if(V<z.maxTurns){let v={...z,outcome:"within-budget",turnCount:V};N.turnBudget=v,Y.turnBudget=v;return}let w=O1(z,V,!1);if(N.turnBudget=w,Y.turnBudget=w,!N.wrapUpRequested)N.wrapUpRequested=!0,Y.wrapUpRequested=!0,Ij(N,[bj(z,V)]);if(!wj(z,V,_))return;let d=O1(z,V,!0),Z$=u0(z,V);N.turnBudget=d,N.turnBudgetExceeded=!0,N.wrapUpRequested=!0,N.error=Z$,t=!0,Y.turnBudget=d,Y.turnBudgetExceeded=!0,Y.wrapUpRequested=!0,Y.error=Z$,Y.lastUpdate=K,$$(n,JSON.stringify({type:"subagent.step.turn_budget_exceeded",ts:K,runId:j,stepIndex:H,agent:N.agent,turnCount:V,maxTurns:z.maxTurns,graceTurns:z.graceTurns,message:Z$})),g$.get(H)?.(Z$,d)},E1=(H,V)=>{let K=Y.steps[H];if(!K)return;let _=Date.now();if(Y.currentStep=H,V.type==="tool_execution_start"&&V.toolName){let z=qj(V.toolName,V.args),N=U8(V.toolName,V.args);K.toolCount=(K.toolCount??0)+1;let w=u$[H]?.toolBudget;if(w)K.toolBudget=Z1(w,K.toolCount),Y.toolBudget=K.toolBudget;K.currentTool=V.toolName,K.currentToolArgs=w0(V.args??{}),K.currentToolStartedAt=_,K.currentPath=N,T0[H]={tool:V.toolName,path:N,mutates:z,startedAt:_},Y.toolCount=(Y.toolCount??0)+1,A1()}else if(V.type==="tool_execution_end"){if(K.currentTool)K.recentTools??=[],K.recentTools.push({tool:K.currentTool,args:K.currentToolArgs||"",endMs:_});K.currentTool=void 0,K.currentToolArgs=void 0,K.currentToolStartedAt=void 0,K.currentPath=void 0,A1()}else if(V.type==="tool_result_end"&&V.message){let z=T0[H];T0[H]=void 0;let N=s$(V.message.content);if(z&&N.includes("Tool budget hard limit reached")){let w=u$[H]?.toolBudget;if(w)K.toolBudget=Z1(w,K.toolCount??0,z.tool),K.toolBudgetBlocked=!0,Y.toolBudget=K.toolBudget,Y.toolBudgetBlocked=!0}if(Ij(K,N.split(`
73
- `).slice(-10)),z?.mutates&&z8(N)){let w=p0[H];if(_8(w,{tool:z.tool,path:z.path,error:N.split(`
74
- `).find((d)=>d.trim())?.trim().slice(0,180)??"mutating tool failed",ts:_},s8),W$.enabled&&M8(w,W$.failedToolAttemptsBeforeAttention)&&K.activityState!=="needs_attention"){let d=K.activityState;K.activityState="needs_attention",Y.activityState="needs_attention",E0(A0({type:"needs_attention",from:d,to:"needs_attention",runId:j,agent:K.agent,index:H,ts:_,message:`${K.agent} needs attention after repeated mutating tool failures`,reason:"tool_failures",turns:K.turnCount,tokens:K.tokens?.total,toolCount:K.toolCount,currentTool:z.tool,currentToolDurationMs:z.startedAt?Math.max(0,_-z.startedAt):void 0,currentPath:z.path,recentFailureSummary:L8(w)}))}}else if(z?.mutates)B8(p0[H])}else if(V.type==="message_end"&&V.message?.role==="assistant"){Ij(K,Cj(s$(V.message.content)).split(`
75
- `).slice(-10)),K.turnCount=(K.turnCount??0)+1;let z=V.message.usage;if(z){let N=z.input??z.inputTokens??0,w=z.output??z.outputTokens??0,d=K.tokens?.input??0,Z$=K.tokens?.output??0;K.tokens={input:d+N,output:Z$+w,total:d+Z$+N+w};let v=Y.totalTokens?.input??0,F=Y.totalTokens?.output??0;Y.totalTokens={input:v+N,output:F+w,total:v+F+N+w}}Y.turnCount=Math.max(Y.turnCount??0,K.turnCount),a8(H,K.turnCount,_,hj(V.message))}A1(),K.lastActivityAt=_,Y.lastActivityAt=_,Y.lastUpdate=_,gj(H,_),a()},t8=(H)=>{if(!W$.enabled)return!1;let V=!1,K=Y.lastActivityAt??S;for(let z=0;z<Y.steps.length;z++){let N=Y.steps[z];if(N.status!=="running")continue;let w=M$(z);if(K=Math.max(K,w),N.lastActivityAt!==w)N.lastActivityAt=w,V=!0;if(qJ({config:W$,startedAt:N.startedAt??S,lastActivityAt:w,now:H})==="needs_attention"){let Z$=N.activityState;if(N.activityState="needs_attention",Z$!=="needs_attention")E0(A0({from:Z$,to:"needs_attention",runId:j,agent:N.agent,index:z,ts:H,lastActivityAt:w})),V=!0}else if(gj(z,H))V=!0}if(Y.lastActivityAt!==K)Y.lastActivityAt=K,V=!0;let _=Y.steps.some((z)=>z.activityState==="needs_attention")?"needs_attention":Y.steps.some((z)=>z.activityState==="active_long_running")?"active_long_running":void 0;if(_!==E$)E$=_,Y.activityState=_,V=!0;if(Y.lastUpdate=H,V)a();return V};if(W$.enabled)X$=setInterval(()=>{if(Y.state!=="running")return;let H=Date.now();t8(H)},1000),X$.unref?.();let mj=()=>{if(g1(k),s||Y.state!=="running")return;s=!0;let H=Date.now();Y.state="paused",E$=void 0,Y.activityState=void 0,Y.lastUpdate=H;for(let V of Y.steps)if(V.status==="running")V.status="paused",V.activityState=void 0,V.endedAt=H,V.durationMs=V.startedAt?H-V.startedAt:void 0,V.lastActivityAt=H;a(),$$(n,JSON.stringify({type:"subagent.run.paused",ts:H,runId:j})),l$(),t$()},cj=()=>{if(E||s||Y.state!=="running")return;E=!0;let H=Date.now(),V=p??"Subagent timed out.";Y.state="failed",Y.timedOut=!0,Y.error=V,E$=void 0,Y.activityState=void 0,Y.lastUpdate=H;for(let K of Y.steps){if(K.status!=="running"&&K.status!=="pending")continue;K.status="failed",K.error=V,K.exitCode=1,K.timedOut=!0,K.activityState=void 0,K.endedAt=H,K.durationMs=K.startedAt?H-K.startedAt:0,K.lastActivityAt=H}a(),$$(n,JSON.stringify({type:"subagent.run.timed_out",ts:H,runId:j,timeoutMs:$.timeoutMs,deadlineAt:$.deadlineAt,message:V})),q$.abort(),p$(),P$()};process.on(y5,mj);let e8=UJ(k,{onInterrupt:mj,onTimeout:cj,onSteer:(H)=>{if((H.targetIndex!==void 0?Y.steps[H.targetIndex]:void 0)?.status==="pending")A$.push(H);else if(H.targetIndex!==void 0||Y.steps.some((K)=>K.status==="running"))N1(H);else A$.push(H)}});if($.deadlineAt!==void 0){let H=Math.max(0,$.deadlineAt-Date.now());_$=setTimeout(cj,H),_$.unref?.()}$$(n,JSON.stringify({type:"subagent.run.started",lifecycleArtifactVersion:S0,ts:S,runId:j,mode:Y.mode,cwd:Q,pid:process.pid}));let R=0,dj=0;while(!0){if(s||E||t)break;if(D(),dj>=J.length)break;let H=dj++,V=J[H];if(j0(V)){let K=R,_;try{if(_=tJ(V,y,H,{maxItems:$.dynamicFanoutMaxItems,allowRunnerFields:!0}),_.collectedOnEmpty)Yj(V.collect.outputSchema,_.collectedOnEmpty)}catch(M){let o=Date.now(),L=M instanceof x?M.message:M instanceof Error?M.message:String(M);Y.state="failed",Y.error=L,Y.currentStep=R;let A=Y.steps[K];if(A)A.status="failed",A.error=L,A.startedAt=o,A.endedAt=o,A.durationMs=0,A.exitCode=1;Y.lastUpdate=o,i(H,"failed",L),a(),h.push({agent:V.parallel.agent,output:L,error:L,success:!1,exitCode:1});break}if(_.parallel.length===0){let M=Date.now(),o=_.collectedOnEmpty??[];y[V.collect.as]={text:JSON.stringify(o),structured:o,agent:V.parallel.agent,stepIndex:H},Y.outputs=y;let L=Y.steps[K];if(L)L.status="complete",L.startedAt=M,L.endedAt=M,L.durationMs=0;T="Dynamic fanout produced 0 results.";let A=V.effectiveAcceptance?.explicit&&!E?await M1({acceptance:V.effectiveAcceptance,output:"",report:Ej({results:[],notes:"Dynamic fanout produced 0 results."}),cwd:Q,signal:q$.signal,abortMessage:p??"Subagent timed out."}):void 0,I=E||q$.signal.aborted,G$=I?void 0:A;if(L&&G$)L.acceptance=G$;let x$=G$?L1(G$):void 0;if(I||x$){let g=I?p??"Subagent timed out.":x$;if(Y.state="failed",Y.error=g,L)L.status="failed",L.error=g,L.exitCode=1,L.timedOut=I?!0:void 0;i(H,"failed",g,G$),Y.lastUpdate=Date.now(),a(),h.push({agent:V.parallel.agent,output:g,error:g,success:!1,exitCode:1,timedOut:I?!0:void 0,acceptance:G$});break}R++,Y.lastUpdate=M,i(H,"completed",void 0,G$),a();continue}let z=_.parallel.map((M,o)=>{let L=V.thinkingOverrides?.[o],A=L?W1(V.parallel.model,L,!0):V.parallel.model,I=L?O0(A,L):void 0;return{...V.parallel,task:M.task??V.parallel.task,label:M.label??V.parallel.label,...V.sessionFiles?.[o]?{sessionFile:V.sessionFiles[o]}:{},...L?{...A?{model:A}:{},...I?{thinking:I}:{},...V.parallel.modelCandidates?{modelCandidates:V.parallel.modelCandidates.map((G$)=>W1(G$,L,!0))}:{}}:{},structuredOutput:void 0,structuredOutputSchema:V.parallel.structuredOutputSchema??V.parallel.structuredOutput?.schema}}),N=Math.max(Y.steps.length-1+z.length,1),w=z.map((M,o)=>{let L=fj({artifactsDir:B,artifactConfig:q,runId:j,agent:M.agent,flatIndex:K+o,flatStepCount:N});return{agent:M.agent,phase:M.phase??V.phase,label:M.label,outputName:void 0,structured:Boolean(M.structuredOutputSchema),status:"pending",...M.sessionFile?{sessionFile:M.sessionFile}:{},...L?{transcriptPath:L}:{},skills:M.skills,model:M.model,thinking:M.thinking,attemptedModels:M.modelCandidates&&M.modelCandidates.length>0?M.modelCandidates:M.model?[M.model]:void 0,recentTools:[],recentOutput:[]}});if(Y.steps.splice(K,1,...w),$.childIntercomTargets)$.childIntercomTargets=Y.steps.map((M,o)=>Aj(j,M.agent,o));p0.splice(K,1,...w.map(()=>G1())),T0.splice(K,1,...w.map(()=>{return}));let d=w.length-1;for(let M of Y.parallelGroups)if(M.stepIndex===H)M.start=K,M.count=w.length;else if(M.start>K)M.start+=d;if(Y.workflowGraph){let M=(L)=>{for(let A of L){if(A.stepIndex!==void 0&&A.stepIndex>H&&A.flatIndex!==void 0&&A.flatIndex>=K)A.flatIndex+=w.length;if(A.children)M(A.children)}};M(Y.workflowGraph.nodes);let o=Y.workflowGraph.nodes.find((L)=>L.id===`step-${H}`);if(o)o.children=_.items.map((L,A)=>({id:`step-${H}-item-${L.idKey}`,kind:"agent",agent:V.parallel.agent,phase:z[A]?.phase??V.phase,label:z[A]?.label?.trim()||`${V.parallel.agent} ${L.key}`,status:"pending",flatIndex:K+A,stepIndex:H,itemKey:L.key,structured:Boolean(z[A]?.structuredOutputSchema)}))}a();let Z$=V.concurrency??k1,v=V.failFast??!1,F=!1,F$=await t0(z,Z$,async(M,o)=>{let L=K+o;if(E)return P(M.agent);if(s)return e$(M.agent);if(F&&v){let g=Date.now();return Y.steps[L].status="failed",Y.steps[L].error="Skipped due to fail-fast",Y.steps[L].startedAt=g,Y.steps[L].endedAt=g,Y.steps[L].durationMs=0,Y.steps[L].exitCode=-1,Y.lastUpdate=g,a(),{agent:M.agent,output:"(skipped — fail-fast)",exitCode:-1,skipped:!0}}let A=Date.now();Y.currentStep=L,Y.steps[L].status="running",Y.steps[L].error=void 0,Y.steps[L].activityState=void 0,yj(Y.steps[L]),Y.steps[L].startedAt=A,Y.steps[L].lastActivityAt=A,Y.outputFile=r.join(k,`output-${L}.log`),Y.lastActivityAt=A,Y.lastUpdate=A,a(),$$(n,JSON.stringify({type:"subagent.step.started",ts:A,runId:j,stepIndex:L,agent:M.agent})),C1(L);let I=await kj(M,{previousOutput:T,placeholder:X,cwd:Q,sessionEnabled:W0,outputs:y,sessionDir:$.sessionDir?r.join($.sessionDir,`dynamic-${H}-${o}`):void 0,artifactsDir:B,artifactConfig:q,id:j,flatIndex:L,flatStepCount:Math.max(Y.steps.length,1),outputFile:r.join(k,`output-${L}.log`),steerInboxDir:y0(k,L),piPackageRoot:$.piPackageRoot,piArgv1:$.piArgv1,childIntercomTarget:$.childIntercomTargets?.[L],orchestratorIntercomTarget:$.controlIntercomTarget,nestedRoute:$.nestedRoute,registerInterrupt:(g)=>N$(L,g),registerTimeout:(g)=>f$(L,g),registerTurnBudgetAbort:(g)=>S$(L,g),timeoutSignal:q$.signal,timeoutMessage:p,turnBudget:$.turnBudget,onAttemptStart:(g)=>T1(L,g.model,g.thinking),onChildEvent:(g)=>E1(L,g),skipAcceptance:()=>E}),G$=Date.now(),x$=I.interrupted===!0;if(Y.steps[L].status=E?"failed":x$?"paused":I.exitCode===0?"complete":"failed",Y.steps[L].endedAt=G$,Y.steps[L].durationMs=G$-A,Y.steps[L].exitCode=E?1:x$?0:I.exitCode,Y.steps[L].timedOut=E||I.timedOut?!0:void 0,Y.steps[L].turnBudget=I.turnBudget,Y.steps[L].turnBudgetExceeded=I.turnBudgetExceeded,Y.steps[L].wrapUpRequested=I.wrapUpRequested,Y.steps[L].toolBudget=I.toolBudget,Y.steps[L].toolBudgetBlocked=I.toolBudgetBlocked,I.toolBudget)Y.toolBudget=I.toolBudget;if(I.toolBudgetBlocked)Y.toolBudgetBlocked=!0;if(I.turnBudget)Y.turnBudget=I.turnBudget;if(I.turnBudgetExceeded)Y.turnBudgetExceeded=!0;if(I.wrapUpRequested)Y.wrapUpRequested=!0;if(Y.steps[L].model=I.model,Y.steps[L].thinking=O0(I.model,Y.steps[L].thinking),Y.steps[L].attemptedModels=I.attemptedModels,Y.steps[L].modelAttempts=I.modelAttempts,Y.steps[L].totalCost=I.totalCost,Y.steps[L].error=E?p??"Subagent timed out.":I.error,Y.steps[L].transcriptPath=I.transcriptPath??Y.steps[L].transcriptPath,Y.steps[L].transcriptError=I.transcriptError,Y.steps[L].structuredOutput=I.structuredOutput,Y.steps[L].structuredOutputPath=I.structuredOutputPath,Y.steps[L].structuredOutputSchemaPath=I.structuredOutputSchemaPath,Y.steps[L].acceptance=I.acceptance,Y.lastUpdate=G$,a(),$$(n,JSON.stringify({type:E?"subagent.step.failed":x$?"subagent.step.paused":I.exitCode===0?"subagent.step.completed":"subagent.step.failed",ts:G$,runId:j,stepIndex:L,agent:M.agent,exitCode:E?1:x$?0:I.exitCode,durationMs:G$-A})),I.exitCode!==0&&v)F=!0;return E?{...I,output:p??"Subagent timed out.",error:p??"Subagent timed out.",exitCode:1,interrupted:!1,timedOut:!0,skipped:!1}:{...I,skipped:!1}},O);R+=z.length;for(let M of F$)h.push({agent:M.agent,output:M.output,error:M.error,success:M.interrupted!==!0&&M.exitCode===0,exitCode:M.interrupted===!0?0:M.exitCode,skipped:M.skipped,interrupted:M.interrupted,timedOut:M.timedOut,turnBudget:M.turnBudget,turnBudgetExceeded:M.turnBudgetExceeded,wrapUpRequested:M.wrapUpRequested,toolBudget:M.toolBudget,toolBudgetBlocked:M.toolBudgetBlocked,sessionFile:M.sessionFile,intercomTarget:M.intercomTarget,model:M.model,attemptedModels:M.attemptedModels,modelAttempts:M.modelAttempts,totalCost:M.totalCost,artifactPaths:M.artifactPaths,transcriptPath:M.transcriptPath,transcriptError:M.transcriptError,structuredOutput:M.structuredOutput,structuredOutputPath:M.structuredOutputPath,structuredOutputSchemaPath:M.structuredOutputSchemaPath,acceptance:M.acceptance});let C=eJ(V,_.items,F$),z$=F$.filter((M)=>M.exitCode!==0&&M.exitCode!==-1);if(z$.length===0)try{Yj(V.collect.outputSchema,C),y[V.collect.as]={text:JSON.stringify(C),structured:C,agent:V.parallel.agent,stepIndex:H},Y.outputs=y;let M=V.effectiveAcceptance&&!E?await M1({acceptance:V.effectiveAcceptance,output:"",report:Ej({results:F$,notes:`Dynamic fanout collected ${C.length} result(s) into ${V.collect.as}.`}),cwd:Q,signal:q$.signal,abortMessage:p??"Subagent timed out."}):void 0,o=E||q$.signal.aborted,L=o?void 0:M,A=L?L1(L):void 0,I=o?p??"Subagent timed out.":A;if(i(H,I?"failed":"completed",I,L),I)h.push({agent:V.parallel.agent,output:I,error:I,success:!1,exitCode:1,timedOut:o?!0:void 0,structuredOutput:C,acceptance:L}),Y.error=I}catch(M){let o=M instanceof x?M.message:M instanceof Error?M.message:String(M);h.push({agent:V.parallel.agent,output:o,error:o,success:!1,exitCode:1,structuredOutput:C}),Y.error=o,i(H,"failed",o)}if(T=e0(F$.map((M,o)=>({agent:M.agent,taskIndex:o,output:M.output,exitCode:M.exitCode,error:M.error})),(M,o)=>`=== Dynamic Item ${M+1} (${o}, key ${_.items[M]?.key??M}) ===`),$$(n,JSON.stringify({type:"subagent.dynamic.completed",ts:Date.now(),runId:j,stepIndex:H,success:z$.length===0})),z$.length>0)i(H,"failed",z$[0]?.error??"Dynamic fanout child failed.");if(Y.lastUpdate=Date.now(),a(),z$.length>0||Y.error)break;continue}if($0(V)){let K=V,_=K.concurrency??k1,z=K.failFast??!1,N=R,w=!1,d;if(K.worktree){let Z$=N8(K.parallel,Q);if(Z$){let v=Date.now();i8({statusPayload:Y,results:h,group:K,groupStartFlatIndex:N,setupError:C8(Z$,Q),failedAt:v,statusPath:f,eventsPath:n,asyncDir:k,runId:j,stepIndex:H}),R+=K.parallel.length;break}try{d=E8(Q,`${j}-s${H}`,K.parallel.length,{agents:K.parallel.map((v)=>v.agent),setupHook:$.worktreeSetupHook?{hookPath:$.worktreeSetupHook,timeoutMs:$.worktreeSetupHookTimeoutMs}:void 0,baseDir:$.worktreeBaseDir})}catch(v){let F=v instanceof Error?v.message:String(v),F$=Date.now();i8({statusPayload:Y,results:h,group:K,groupStartFlatIndex:N,setupError:F,failedAt:F$,statusPath:f,eventsPath:n,asyncDir:k,runId:j,stepIndex:H}),R+=K.parallel.length;break}}try{if(K.worktree)a5(Q,K);let Z$=Date.now();i5({statusPayload:Y,group:K,groupStartFlatIndex:N,groupStartTime:Z$,statusPath:f,eventsPath:n,asyncDir:k,runId:j,stepIndex:H});let v=await t0(K.parallel,_,async(F,F$)=>{let C=N+F$;if(E)return P(F.agent);if(s)return e$(F.agent);if(w&&z){let g=Date.now();return Y.steps[C].status="failed",Y.steps[C].error="Skipped due to fail-fast",Y.steps[C].startedAt=g,Y.steps[C].endedAt=g,Y.steps[C].durationMs=0,Y.steps[C].exitCode=-1,Y.steps[C].activityState=void 0,Y.lastUpdate=g,a(),$$(n,JSON.stringify({type:"subagent.step.failed",ts:g,runId:j,stepIndex:C,agent:F.agent,exitCode:-1,durationMs:0})),{agent:F.agent,output:"(skipped — fail-fast)",exitCode:-1,skipped:!0}}let z$=Date.now();Y.currentStep=C,Y.steps[C].status="running",Y.steps[C].error=void 0,Y.steps[C].activityState=void 0,yj(Y.steps[C]),Y.steps[C].startedAt=z$,Y.steps[C].endedAt=void 0,Y.steps[C].durationMs=void 0,Y.steps[C].lastActivityAt=z$,Y.outputFile=r.join(k,`output-${C}.log`),Y.lastActivityAt=z$,Y.lastUpdate=z$,a(),$$(n,JSON.stringify({type:"subagent.step.started",ts:z$,runId:j,stepIndex:C,agent:F.agent}));let M=$.sessionDir?r.join($.sessionDir,`parallel-${F$}`):void 0,{taskForRun:o,taskCwd:L}=r5(F,Q,d,F$);C1(C);let A=await kj(o,{previousOutput:T,placeholder:X,cwd:L,sessionEnabled:W0,outputs:y,sessionDir:M,artifactsDir:B,artifactConfig:q,id:j,flatIndex:C,flatStepCount:Math.max(Y.steps.length,1),outputFile:r.join(k,`output-${C}.log`),steerInboxDir:y0(k,C),piPackageRoot:$.piPackageRoot,piArgv1:$.piArgv1,childIntercomTarget:$.childIntercomTargets?.[C],orchestratorIntercomTarget:$.controlIntercomTarget,nestedRoute:$.nestedRoute,registerInterrupt:(g)=>N$(C,g),registerTimeout:(g)=>f$(C,g),registerTurnBudgetAbort:(g)=>S$(C,g),timeoutSignal:q$.signal,timeoutMessage:p,turnBudget:$.turnBudget,onAttemptStart:(g)=>T1(C,g.model,g.thinking),onChildEvent:(g)=>E1(C,g),skipAcceptance:()=>E});if(F.sessionFile)o$=F.sessionFile;let I=Date.now(),G$=I-z$,x$=A.interrupted===!0;if(Y.steps[C].status=E?"failed":x$?"paused":A.exitCode===0?"complete":"failed",Y.steps[C].endedAt=I,Y.steps[C].durationMs=G$,Y.steps[C].exitCode=E?1:x$?0:A.exitCode,Y.steps[C].timedOut=E||A.timedOut?!0:void 0,Y.steps[C].turnBudget=A.turnBudget,Y.steps[C].turnBudgetExceeded=A.turnBudgetExceeded,Y.steps[C].wrapUpRequested=A.wrapUpRequested,Y.steps[C].toolBudget=A.toolBudget,Y.steps[C].toolBudgetBlocked=A.toolBudgetBlocked,A.toolBudget)Y.toolBudget=A.toolBudget;if(A.toolBudgetBlocked)Y.toolBudgetBlocked=!0;if(A.turnBudget)Y.turnBudget=A.turnBudget;if(A.turnBudgetExceeded)Y.turnBudgetExceeded=!0;if(A.wrapUpRequested)Y.wrapUpRequested=!0;if(Y.steps[C].model=A.model,Y.steps[C].thinking=O0(A.model,Y.steps[C].thinking),Y.steps[C].attemptedModels=A.attemptedModels,Y.steps[C].modelAttempts=A.modelAttempts,Y.steps[C].totalCost=A.totalCost,Y.steps[C].error=E?p??"Subagent timed out.":A.error,Y.steps[C].transcriptPath=A.transcriptPath??Y.steps[C].transcriptPath,Y.steps[C].transcriptError=A.transcriptError,Y.steps[C].structuredOutput=A.structuredOutput,Y.steps[C].structuredOutputPath=A.structuredOutputPath,Y.steps[C].structuredOutputSchemaPath=A.structuredOutputSchemaPath,Y.steps[C].acceptance=A.acceptance,Y.lastUpdate=I,a(),$$(n,JSON.stringify({type:E?"subagent.step.failed":x$?"subagent.step.paused":A.exitCode===0?"subagent.step.completed":"subagent.step.failed",ts:I,runId:j,stepIndex:C,agent:F.agent,exitCode:E?1:x$?0:A.exitCode,durationMs:G$})),A.completionGuardTriggered){let g=A0({from:Y.steps[C].activityState,to:"needs_attention",runId:j,agent:F.agent,index:C,ts:I,message:`${F.agent} completed without making edits for an implementation task`,reason:"completion_guard"});E0(g)}if(A.exitCode!==0&&z)w=!0;return E?{...A,output:p??"Subagent timed out.",error:p??"Subagent timed out.",exitCode:1,interrupted:!1,timedOut:!0,skipped:!1}:{...A,skipped:!1}},O);R+=K.parallel.length;for(let F=0;F<K.parallel.length;F++){let F$=N+F,z$=($.sessionDir?Fj(r.join($.sessionDir,`parallel-${F}`)):null)??p8(v[F]?.modelAttempts);if(!z$)continue;Y.steps[F$].tokens=z$,Y$={input:Y$.input+z$.input,output:Y$.output+z$.output,total:Y$.total+z$.total}}Y.totalTokens={...Y$},Y.lastUpdate=Date.now(),a();for(let F of v)h.push({agent:F.agent,output:F.output,error:F.error,success:F.interrupted!==!0&&F.exitCode===0,exitCode:F.interrupted===!0?0:F.exitCode,skipped:F.skipped,interrupted:F.interrupted,timedOut:F.timedOut,turnBudget:F.turnBudget,turnBudgetExceeded:F.turnBudgetExceeded,wrapUpRequested:F.wrapUpRequested,toolBudget:F.toolBudget,toolBudgetBlocked:F.toolBudgetBlocked,sessionFile:F.sessionFile,intercomTarget:F.intercomTarget,model:F.model,attemptedModels:F.attemptedModels,modelAttempts:F.modelAttempts,totalCost:F.totalCost,artifactPaths:F.artifactPaths,transcriptPath:F.transcriptPath,transcriptError:F.transcriptError,structuredOutput:F.structuredOutput,structuredOutputPath:F.structuredOutputPath,structuredOutputSchemaPath:F.structuredOutputSchemaPath,acceptance:F.acceptance});for(let F=0;F<K.parallel.length;F++){let F$=K.parallel[F]?.outputName;if(F$)y[F$]=Hj({agent:v[F].agent,output:v[F].output,structuredOutput:v[F].structuredOutput},H)}if(Y.outputs=y,T=e0(v.map((F)=>({agent:F.agent,output:F.output,exitCode:F.exitCode,error:F.error,model:F.model,attemptedModels:F.attemptedModels}))),T=s5(T,d,k,H,K),$$(n,JSON.stringify({type:"subagent.parallel.completed",ts:Date.now(),runId:j,stepIndex:H,success:v.every((F)=>F.exitCode===0||F.exitCode===-1)})),v.some((F)=>F.exitCode!==0&&F.exitCode!==-1))break}finally{if(d)Oj(d)}}else{let K=V,_=Date.now();Y.currentStep=R,Y.steps[R].status="running",Y.steps[R].activityState=void 0,Y.activityState=void 0,yj(Y.steps[R]),Y.steps[R].skills=K.skills,Y.steps[R].startedAt=_,Y.steps[R].lastActivityAt=_,Y.lastActivityAt=_,Y.lastUpdate=_,Y.outputFile=r.join(k,`output-${R}.log`),a(),$$(n,JSON.stringify({type:"subagent.step.started",ts:_,runId:j,stepIndex:R,agent:K.agent})),C1(R);let z=await kj(K,{previousOutput:T,placeholder:X,cwd:Q,sessionEnabled:W0,outputs:y,sessionDir:$.sessionDir,artifactsDir:B,artifactConfig:q,id:j,flatIndex:R,flatStepCount:Math.max(Y.steps.length,1),outputFile:r.join(k,`output-${R}.log`),steerInboxDir:y0(k,R),piPackageRoot:$.piPackageRoot,piArgv1:$.piArgv1,childIntercomTarget:$.childIntercomTargets?.[R],orchestratorIntercomTarget:$.controlIntercomTarget,nestedRoute:$.nestedRoute,registerInterrupt:(v)=>N$(R,v),registerTimeout:(v)=>f$(R,v),registerTurnBudgetAbort:(v)=>S$(R,v),timeoutSignal:q$.signal,timeoutMessage:p,turnBudget:$.turnBudget,onAttemptStart:(v)=>T1(R,v.model,v.thinking),onChildEvent:(v)=>E1(R,v),skipAcceptance:()=>E});if(K.sessionFile)o$=K.sessionFile;if(T=z.output,h.push({agent:z.agent,output:E?p??"Subagent timed out.":z.output,error:E?p??"Subagent timed out.":z.error,success:!E&&z.interrupted!==!0&&z.exitCode===0,exitCode:E?1:z.interrupted===!0?0:z.exitCode,sessionFile:z.sessionFile,intercomTarget:z.intercomTarget,model:z.model,attemptedModels:z.attemptedModels,modelAttempts:z.modelAttempts,totalCost:z.totalCost,artifactPaths:z.artifactPaths,transcriptPath:z.transcriptPath,transcriptError:z.transcriptError,structuredOutput:z.structuredOutput,structuredOutputPath:z.structuredOutputPath,structuredOutputSchemaPath:z.structuredOutputSchemaPath,acceptance:z.acceptance,interrupted:z.interrupted,timedOut:E||z.timedOut?!0:void 0,turnBudget:z.turnBudget,turnBudgetExceeded:z.turnBudgetExceeded,wrapUpRequested:z.wrapUpRequested,toolBudget:z.toolBudget,toolBudgetBlocked:z.toolBudgetBlocked}),K.outputName)y[K.outputName]=Hj({agent:z.agent,output:z.output,structuredOutput:z.structuredOutput},H);Y.outputs=y;let N=$.sessionDir?Fj($.sessionDir):null,w=N?{input:N.input-Y$.input,output:N.output-Y$.output,total:N.total-Y$.total}:null;if(N)Y$=N;else if(w=p8(z.modelAttempts),w)Y$={input:Y$.input+w.input,output:Y$.output+w.output,total:Y$.total+w.total};let d=Date.now(),Z$=z.interrupted===!0;if(Y.steps[R].status=E?"failed":Z$?"paused":z.exitCode===0?"complete":"failed",Y.steps[R].endedAt=d,Y.steps[R].durationMs=d-_,Y.steps[R].exitCode=E?1:Z$?0:z.exitCode,Y.steps[R].timedOut=E||z.timedOut?!0:void 0,Y.steps[R].turnBudget=z.turnBudget,Y.steps[R].turnBudgetExceeded=z.turnBudgetExceeded,Y.steps[R].wrapUpRequested=z.wrapUpRequested,Y.steps[R].toolBudget=z.toolBudget,Y.steps[R].toolBudgetBlocked=z.toolBudgetBlocked,z.toolBudget)Y.toolBudget=z.toolBudget;if(z.toolBudgetBlocked)Y.toolBudgetBlocked=!0;if(z.turnBudget)Y.turnBudget=z.turnBudget;if(z.turnBudgetExceeded)Y.turnBudgetExceeded=!0;if(z.wrapUpRequested)Y.wrapUpRequested=!0;if(Y.steps[R].model=z.model,Y.steps[R].thinking=O0(z.model,Y.steps[R].thinking),Y.steps[R].attemptedModels=z.attemptedModels,Y.steps[R].modelAttempts=z.modelAttempts,Y.steps[R].totalCost=z.totalCost,Y.steps[R].error=E?p??"Subagent timed out.":z.error,Y.steps[R].transcriptPath=z.transcriptPath??Y.steps[R].transcriptPath,Y.steps[R].transcriptError=z.transcriptError,Y.steps[R].structuredOutput=z.structuredOutput,Y.steps[R].structuredOutputPath=z.structuredOutputPath,Y.steps[R].structuredOutputSchemaPath=z.structuredOutputSchemaPath,Y.steps[R].acceptance=z.acceptance,w)Y.steps[R].tokens=w,Y.totalTokens={...Y$};if(Y.lastUpdate=d,a(),$$(n,JSON.stringify({type:E?"subagent.step.failed":Z$?"subagent.step.paused":z.exitCode===0?"subagent.step.completed":"subagent.step.failed",ts:d,runId:j,stepIndex:R,agent:K.agent,exitCode:E?1:Z$?0:z.exitCode,durationMs:d-_,tokens:w})),z.completionGuardTriggered){let v=A0({from:Y.steps[R].activityState,to:"needs_attention",runId:j,agent:K.agent,index:R,ts:d,message:`${K.agent} completed without making edits for an implementation task`,reason:"completion_guard"});E0(v)}if(R++,z.exitCode!==0)break}}let n0=h.map((H)=>{let V=H.output.trim(),K=V?H.error?`${V}
947
+ ${diffSummary}`;
948
+ }
949
+ function ensureParallelProgressFile(cwd, group) {
950
+ const progressPath = path.join(cwd, "progress.md");
951
+ if (!group.parallel.some((task) => task.task.includes(`Update progress at: ${progressPath}`)))
952
+ return;
953
+ writeInitialProgressFile(cwd);
954
+ }
955
+ function resolveAsyncStepTranscriptPath(input) {
956
+ if (!input.artifactsDir || input.artifactConfig?.enabled === false || input.artifactConfig?.includeTranscript === false)
957
+ return;
958
+ return getArtifactPaths(input.artifactsDir, input.runId, input.agent, input.flatStepCount > 1 ? input.flatIndex : undefined).transcriptPath;
959
+ }
960
+ async function runSubagent(config) {
961
+ const { id, steps, resultPath, cwd, placeholder, taskIndex, totalTasks, maxOutput, artifactsDir, artifactConfig } = config;
962
+ const globalSemaphore = new Semaphore(config.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT);
963
+ let previousOutput = "";
964
+ const outputs = {};
965
+ const results = [];
966
+ const overallStartTime = Date.now();
967
+ const shareEnabled = config.share === true;
968
+ const asyncDir = config.asyncDir;
969
+ const statusPath = path.join(asyncDir, "status.json");
970
+ const eventsPath = path.join(asyncDir, "events.jsonl");
971
+ const logPath = path.join(asyncDir, `subagent-log-${id}.md`);
972
+ const controlConfig = config.controlConfig ?? DEFAULT_CONTROL_CONFIG;
973
+ const activeChildInterrupts = new Map;
974
+ const activeChildTimeouts = new Map;
975
+ const activeChildTurnBudgetAborts = new Map;
976
+ const pendingStepSteers = [];
977
+ let interrupted = false;
978
+ let currentActivityState;
979
+ let activityTimer;
980
+ let timeoutTimer;
981
+ let timedOut = false;
982
+ let turnBudgetExceeded = false;
983
+ const timeoutMessage = config.timeoutMs !== undefined ? `Subagent timed out after ${config.timeoutMs}ms.` : undefined;
984
+ const timeoutAbortController = new AbortController;
985
+ let previousCumulativeTokens = { input: 0, output: 0, total: 0 };
986
+ let latestSessionFile;
987
+ const flatSteps = flattenSteps(steps);
988
+ const initialFlatStepCount = flatSteps.length;
989
+ const parallelGroups = [];
990
+ const initialStatusSteps = [];
991
+ let flatStepCount = 0;
992
+ for (let stepIndex = 0;stepIndex < steps.length; stepIndex++) {
993
+ const step = steps[stepIndex];
994
+ if (isParallelGroup(step)) {
995
+ parallelGroups.push({ start: flatStepCount, count: step.parallel.length, stepIndex });
996
+ for (const task of step.parallel) {
997
+ const taskFlatIndex = flatStepCount;
998
+ const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: taskFlatIndex, flatStepCount: initialFlatStepCount });
999
+ initialStatusSteps.push({
1000
+ agent: task.agent,
1001
+ phase: task.phase,
1002
+ label: task.label,
1003
+ outputName: task.outputName,
1004
+ structured: task.structured,
1005
+ status: "pending",
1006
+ ...task.toolBudget ? { toolBudget: initialToolBudgetState(task.toolBudget) } : {},
1007
+ ...task.sessionFile ? { sessionFile: task.sessionFile } : {},
1008
+ ...transcriptPath ? { transcriptPath } : {},
1009
+ skills: task.skills,
1010
+ model: task.model,
1011
+ thinking: task.thinking,
1012
+ attemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,
1013
+ recentTools: [],
1014
+ recentOutput: []
1015
+ });
1016
+ flatStepCount++;
1017
+ }
1018
+ } else if (isDynamicRunnerGroup(step)) {
1019
+ parallelGroups.push({ start: flatStepCount, count: 1, stepIndex });
1020
+ initialStatusSteps.push({
1021
+ agent: `expand:${step.parallel.agent}`,
1022
+ phase: step.phase ?? step.parallel.phase,
1023
+ label: step.label ?? step.parallel.label ?? `Dynamic fanout (${step.collect.as})`,
1024
+ outputName: step.collect.as,
1025
+ structured: Boolean(step.collect.outputSchema),
1026
+ status: "pending",
1027
+ ...step.parallel.toolBudget ? { toolBudget: initialToolBudgetState(step.parallel.toolBudget) } : {},
1028
+ recentTools: [],
1029
+ recentOutput: []
1030
+ });
1031
+ flatStepCount++;
1032
+ } else {
1033
+ const stepFlatIndex = flatStepCount;
1034
+ const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: step.agent, flatIndex: stepFlatIndex, flatStepCount: initialFlatStepCount });
1035
+ initialStatusSteps.push({
1036
+ agent: step.agent,
1037
+ phase: step.phase,
1038
+ label: step.label,
1039
+ outputName: step.outputName,
1040
+ structured: step.structured,
1041
+ status: "pending",
1042
+ ...step.toolBudget ? { toolBudget: initialToolBudgetState(step.toolBudget) } : {},
1043
+ ...step.sessionFile ? { sessionFile: step.sessionFile } : {},
1044
+ ...transcriptPath ? { transcriptPath } : {},
1045
+ skills: step.skills,
1046
+ model: step.model,
1047
+ thinking: step.thinking,
1048
+ attemptedModels: step.modelCandidates && step.modelCandidates.length > 0 ? step.modelCandidates : step.model ? [step.model] : undefined,
1049
+ recentTools: [],
1050
+ recentOutput: []
1051
+ });
1052
+ flatStepCount++;
1053
+ }
1054
+ }
1055
+ const sessionEnabled = Boolean(config.sessionDir) || shareEnabled || flatSteps.some((step) => Boolean(step.sessionFile));
1056
+ const statusPayload = {
1057
+ lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
1058
+ runId: id,
1059
+ ...config.sessionId ? { sessionId: config.sessionId } : {},
1060
+ mode: config.resultMode ?? (flatSteps.length > 1 ? "chain" : "single"),
1061
+ state: "running",
1062
+ lastActivityAt: overallStartTime,
1063
+ startedAt: overallStartTime,
1064
+ lastUpdate: overallStartTime,
1065
+ ...config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {},
1066
+ ...config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {},
1067
+ ...config.turnBudget ? { turnBudget: initialTurnBudgetState(config.turnBudget) } : {},
1068
+ ...config.toolBudget ? { toolBudget: initialToolBudgetState(config.toolBudget) } : {},
1069
+ pid: process.pid,
1070
+ cwd,
1071
+ currentStep: 0,
1072
+ chainStepCount: steps.length,
1073
+ parallelGroups,
1074
+ workflowGraph: config.workflowGraph,
1075
+ steps: initialStatusSteps,
1076
+ artifactsDir,
1077
+ sessionDir: config.sessionDir,
1078
+ outputFile: path.join(asyncDir, "output-0.log")
1079
+ };
1080
+ fs.mkdirSync(asyncDir, { recursive: true });
1081
+ writeAtomicJson(statusPath, statusPayload);
1082
+ const emitNestedSelfEvent = (type) => {
1083
+ if (!config.nestedRoute || !config.nestedSelf)
1084
+ return;
1085
+ try {
1086
+ writeNestedEvent(config.nestedRoute, {
1087
+ type,
1088
+ ts: Date.now(),
1089
+ parentRunId: config.nestedSelf.parentRunId,
1090
+ parentStepIndex: config.nestedSelf.parentStepIndex,
1091
+ child: nestedSummaryFromAsyncStatus(statusPayload, asyncDir, {
1092
+ id,
1093
+ parentRunId: config.nestedSelf.parentRunId,
1094
+ parentStepIndex: config.nestedSelf.parentStepIndex,
1095
+ depth: config.nestedSelf.depth,
1096
+ path: config.nestedSelf.path,
1097
+ mode: statusPayload.mode,
1098
+ ts: Date.now()
1099
+ })
1100
+ });
1101
+ } catch (error) {
1102
+ console.error("Failed to emit nested async status event:", error);
1103
+ }
1104
+ };
1105
+ const refreshWorkflowGraph = () => {
1106
+ if (!config.workflowGraph)
1107
+ return;
1108
+ const graph = structuredClone(statusPayload.workflowGraph ?? config.workflowGraph);
1109
+ const normalize = (status) => {
1110
+ if (status === "complete" || status === "completed")
1111
+ return "completed";
1112
+ if (status === "running" || status === "failed" || status === "paused" || status === "pending")
1113
+ return status;
1114
+ return "pending";
1115
+ };
1116
+ const updateNode = (node) => {
1117
+ if (node.flatIndex !== undefined) {
1118
+ const step = statusPayload.steps[node.flatIndex];
1119
+ if (step) {
1120
+ node.status = normalize(step.status);
1121
+ node.error = step.error;
1122
+ node.acceptanceStatus = step.acceptance?.status;
1123
+ }
1124
+ if (statusPayload.currentStep === node.flatIndex)
1125
+ graph.currentNodeId = node.id;
1126
+ }
1127
+ for (const child of node.children ?? [])
1128
+ updateNode(child);
1129
+ if (node.children?.length) {
1130
+ if (node.children.every((child) => child.status === "completed"))
1131
+ node.status = "completed";
1132
+ else if (node.children.some((child) => child.status === "running"))
1133
+ node.status = "running";
1134
+ else if (node.children.some((child) => child.status === "failed"))
1135
+ node.status = "failed";
1136
+ else if (node.children.some((child) => child.status === "paused"))
1137
+ node.status = "paused";
1138
+ }
1139
+ if (node.error)
1140
+ node.status = "failed";
1141
+ };
1142
+ for (const node of graph.nodes)
1143
+ updateNode(node);
1144
+ statusPayload.workflowGraph = graph;
1145
+ };
1146
+ const writeStatusPayload = () => {
1147
+ refreshWorkflowGraph();
1148
+ writeAtomicJson(statusPath, statusPayload);
1149
+ emitNestedSelfEvent(statusPayload.state === "running" || statusPayload.state === "queued" ? "subagent.nested.updated" : "subagent.nested.completed");
1150
+ };
1151
+ const registerStepInterrupt = (flatIndex, interrupt) => {
1152
+ if (!interrupt) {
1153
+ activeChildInterrupts.delete(flatIndex);
1154
+ return;
1155
+ }
1156
+ activeChildInterrupts.set(flatIndex, interrupt);
1157
+ if (interrupted)
1158
+ interrupt();
1159
+ };
1160
+ const registerStepTimeout = (flatIndex, interrupt) => {
1161
+ if (!interrupt) {
1162
+ activeChildTimeouts.delete(flatIndex);
1163
+ return;
1164
+ }
1165
+ activeChildTimeouts.set(flatIndex, interrupt);
1166
+ if (timedOut)
1167
+ interrupt();
1168
+ };
1169
+ const registerStepTurnBudgetAbort = (flatIndex, abort) => {
1170
+ if (!abort) {
1171
+ activeChildTurnBudgetAborts.delete(flatIndex);
1172
+ return;
1173
+ }
1174
+ activeChildTurnBudgetAborts.set(flatIndex, abort);
1175
+ };
1176
+ const interruptActiveChildren = () => {
1177
+ for (const interrupt of [...activeChildInterrupts.values()])
1178
+ interrupt();
1179
+ };
1180
+ const timeoutActiveChildren = () => {
1181
+ for (const interrupt of [...activeChildTimeouts.values()])
1182
+ interrupt();
1183
+ };
1184
+ const nestedRuns = function* (children) {
1185
+ for (const child of children ?? []) {
1186
+ yield child;
1187
+ yield* nestedRuns(child.children);
1188
+ yield* nestedRuns(child.steps?.flatMap((step) => step.children ?? []));
1189
+ }
1190
+ };
1191
+ const interruptNestedAsyncDescendants = () => {
1192
+ if (!config.nestedRoute)
1193
+ return;
1194
+ let registry;
1195
+ try {
1196
+ registry = projectNestedEvents(config.nestedRoute);
1197
+ } catch (error) {
1198
+ appendJsonl(eventsPath, JSON.stringify({
1199
+ type: "subagent.nested.interrupt_failed",
1200
+ ts: Date.now(),
1201
+ runId: id,
1202
+ message: error instanceof Error ? error.message : String(error)
1203
+ }));
1204
+ return;
1205
+ }
1206
+ for (const run of nestedRuns(registry.children)) {
1207
+ if (run.state !== "running" && run.state !== "queued")
1208
+ continue;
1209
+ const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
1210
+ if (!nestedAsyncDir)
1211
+ continue;
1212
+ try {
1213
+ deliverInterruptRequest({ asyncDir: nestedAsyncDir, pid: run.pid, source: "ancestor-interrupt" });
1214
+ } catch (error) {
1215
+ appendJsonl(eventsPath, JSON.stringify({
1216
+ type: "subagent.nested.interrupt_failed",
1217
+ ts: Date.now(),
1218
+ runId: id,
1219
+ targetRunId: run.id,
1220
+ message: error instanceof Error ? error.message : String(error)
1221
+ }));
1222
+ }
1223
+ }
1224
+ };
1225
+ const timeoutNestedAsyncDescendants = () => {
1226
+ if (!config.nestedRoute)
1227
+ return;
1228
+ let registry;
1229
+ try {
1230
+ registry = projectNestedEvents(config.nestedRoute);
1231
+ } catch (error) {
1232
+ appendJsonl(eventsPath, JSON.stringify({
1233
+ type: "subagent.nested.timeout_failed",
1234
+ ts: Date.now(),
1235
+ runId: id,
1236
+ message: error instanceof Error ? error.message : String(error)
1237
+ }));
1238
+ return;
1239
+ }
1240
+ for (const run of nestedRuns(registry.children)) {
1241
+ if (run.state !== "running" && run.state !== "queued")
1242
+ continue;
1243
+ const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
1244
+ if (!nestedAsyncDir)
1245
+ continue;
1246
+ try {
1247
+ deliverTimeoutRequest({ asyncDir: nestedAsyncDir, pid: run.pid, source: "ancestor-timeout" });
1248
+ } catch (error) {
1249
+ appendJsonl(eventsPath, JSON.stringify({
1250
+ type: "subagent.nested.timeout_failed",
1251
+ ts: Date.now(),
1252
+ runId: id,
1253
+ targetRunId: run.id,
1254
+ message: error instanceof Error ? error.message : String(error)
1255
+ }));
1256
+ }
1257
+ }
1258
+ };
1259
+ const pausedStepResult = (agent) => ({
1260
+ agent,
1261
+ output: "Paused after interrupt. Waiting for explicit next action.",
1262
+ exitCode: 0,
1263
+ interrupted: true
1264
+ });
1265
+ const timedOutStepResult = (agent) => ({
1266
+ agent,
1267
+ output: timeoutMessage ?? "Subagent timed out.",
1268
+ error: timeoutMessage ?? "Subagent timed out.",
1269
+ exitCode: 1,
1270
+ timedOut: true
1271
+ });
1272
+ const consumePendingAppendRequests = () => {
1273
+ if (statusPayload.mode !== "chain" || statusPayload.state !== "running")
1274
+ return;
1275
+ const requests = consumeChainAppendRequests(asyncDir);
1276
+ if (requests.length === 0) {
1277
+ const pendingAppends = countPendingChainAppendRequests(asyncDir);
1278
+ if ((statusPayload.pendingAppends ?? 0) !== pendingAppends) {
1279
+ statusPayload.pendingAppends = pendingAppends;
1280
+ statusPayload.lastUpdate = Date.now();
1281
+ writeStatusPayload();
1282
+ }
1283
+ return;
1284
+ }
1285
+ const appendedSteps = requests.flatMap((request) => request.steps);
1286
+ steps.push(...appendedSteps);
1287
+ const now = Date.now();
1288
+ const pendingAppends = countPendingChainAppendRequests(asyncDir);
1289
+ const added = appendRunnerStepsToStatus({
1290
+ status: statusPayload,
1291
+ steps: appendedSteps,
1292
+ now,
1293
+ pendingAppends
1294
+ });
1295
+ mutatingFailureStates.push(...Array.from({ length: added.addedFlatSteps }, () => createMutatingFailureState()));
1296
+ pendingToolResults.push(...Array.from({ length: added.addedFlatSteps }, () => {
1297
+ return;
1298
+ }));
1299
+ if (config.childIntercomTargets) {
1300
+ config.childIntercomTargets = statusPayload.steps.map((statusStep, index) => resolveSubagentIntercomTarget(id, statusStep.agent, index));
1301
+ }
1302
+ writeStatusPayload();
1303
+ for (const request of requests) {
1304
+ appendJsonl(eventsPath, JSON.stringify({
1305
+ type: "subagent.chain.append.accepted",
1306
+ ts: now,
1307
+ runId: id,
1308
+ requestId: request.id,
1309
+ stepCount: request.steps.length,
1310
+ pendingAppends
1311
+ }));
1312
+ }
1313
+ };
1314
+ const markDynamicGraphGroup = (stepIndex, status, error, acceptance) => {
1315
+ const groupNode = statusPayload.workflowGraph?.nodes.find((node) => node.id === `step-${stepIndex}`);
1316
+ if (!groupNode)
1317
+ return;
1318
+ groupNode.status = status;
1319
+ groupNode.error = error;
1320
+ groupNode.acceptanceStatus = acceptance?.status ?? groupNode.acceptanceStatus;
1321
+ };
1322
+ const stepOutputActivityAt = (index) => {
1323
+ const step = statusPayload.steps[index];
1324
+ let lastActivityAt = step?.lastActivityAt ?? step?.startedAt ?? overallStartTime;
1325
+ const outputPath = path.join(asyncDir, `output-${index}.log`);
1326
+ try {
1327
+ lastActivityAt = Math.max(lastActivityAt, fs.statSync(outputPath).mtimeMs);
1328
+ } catch (error) {
1329
+ if (error.code !== "ENOENT") {
1330
+ console.error(`Failed to inspect async output file '${outputPath}':`, error);
1331
+ }
1332
+ }
1333
+ return lastActivityAt;
1334
+ };
1335
+ const emittedControlEventKeys = new Set;
1336
+ const activeLongRunningSteps = new Set;
1337
+ const mutatingFailureStates = initialStatusSteps.map(() => createMutatingFailureState());
1338
+ const pendingToolResults = initialStatusSteps.map(() => {
1339
+ return;
1340
+ });
1341
+ const mutatingFailureWindowMs = 300000;
1342
+ const appendControlEvent = (event) => {
1343
+ if (!controlConfig.enabled)
1344
+ return;
1345
+ const childIntercomTarget = config.childIntercomTargets?.[event.index ?? statusPayload.currentStep];
1346
+ const channels = event.type === "active_long_running" ? controlConfig.notifyChannels.filter((channel) => channel !== "intercom") : controlConfig.notifyChannels;
1347
+ if (channels.length === 0 || !claimControlNotification(controlConfig, event, emittedControlEventKeys, childIntercomTarget))
1348
+ return;
1349
+ appendJsonl(eventsPath, JSON.stringify({
1350
+ type: "subagent.control",
1351
+ event,
1352
+ channels,
1353
+ childIntercomTarget,
1354
+ noticeText: formatControlNoticeMessage(event, childIntercomTarget),
1355
+ ...config.controlIntercomTarget && channels.includes("intercom") ? {
1356
+ intercom: {
1357
+ to: config.controlIntercomTarget,
1358
+ message: formatControlIntercomMessage(event, childIntercomTarget)
1359
+ }
1360
+ } : {}
1361
+ }));
1362
+ };
1363
+ const syncTopLevelCurrentTool = () => {
1364
+ const activeStep = statusPayload.steps.filter((step) => step.status === "running" && typeof step.currentTool === "string" && step.currentTool.length > 0).sort((left, right) => (right.currentToolStartedAt ?? 0) - (left.currentToolStartedAt ?? 0))[0];
1365
+ statusPayload.currentTool = activeStep?.currentTool;
1366
+ statusPayload.currentToolStartedAt = activeStep?.currentToolStartedAt;
1367
+ statusPayload.currentPath = activeStep?.currentPath;
1368
+ };
1369
+ const maybeEmitActiveLongRunning = (flatIndex, now) => {
1370
+ if (!controlConfig.enabled || activeLongRunningSteps.has(flatIndex))
1371
+ return false;
1372
+ const step = statusPayload.steps[flatIndex];
1373
+ if (!step || step.status !== "running" || step.activityState === "needs_attention")
1374
+ return false;
1375
+ const reason = nextLongRunningTrigger(controlConfig, {
1376
+ startedAt: step.startedAt ?? overallStartTime,
1377
+ now,
1378
+ turns: step.turnCount ?? 0,
1379
+ tokens: step.tokens?.total ?? 0
1380
+ });
1381
+ if (!reason)
1382
+ return false;
1383
+ activeLongRunningSteps.add(flatIndex);
1384
+ const previous = step.activityState;
1385
+ step.activityState = "active_long_running";
1386
+ statusPayload.activityState = statusPayload.activityState === "needs_attention" ? "needs_attention" : "active_long_running";
1387
+ const event = buildControlEvent({
1388
+ type: "active_long_running",
1389
+ from: previous,
1390
+ to: "active_long_running",
1391
+ runId: id,
1392
+ agent: step.agent,
1393
+ index: flatIndex,
1394
+ ts: now,
1395
+ message: `${step.agent} is still active but long-running`,
1396
+ reason,
1397
+ turns: step.turnCount,
1398
+ tokens: step.tokens?.total,
1399
+ toolCount: step.toolCount,
1400
+ currentTool: step.currentTool,
1401
+ currentToolDurationMs: step.currentToolStartedAt ? Math.max(0, now - step.currentToolStartedAt) : undefined,
1402
+ currentPath: step.currentPath,
1403
+ elapsedMs: now - (step.startedAt ?? overallStartTime)
1404
+ });
1405
+ appendControlEvent(event);
1406
+ return true;
1407
+ };
1408
+ const deliverSteerRequest = (request) => {
1409
+ if (statusPayload.state !== "running")
1410
+ return;
1411
+ const runningIndexes = statusPayload.steps.map((step, index) => ({ step, index })).filter(({ step }) => step.status === "running").map(({ index }) => index);
1412
+ const targets = request.targetIndex !== undefined ? [request.targetIndex] : runningIndexes;
1413
+ const now = Date.now();
1414
+ const accepted = [];
1415
+ const rejected = [];
1416
+ for (const index of targets) {
1417
+ const step = statusPayload.steps[index];
1418
+ if (!step) {
1419
+ rejected.push({ index, reason: "child index out of range" });
1420
+ continue;
1421
+ }
1422
+ if (step.status !== "running") {
1423
+ rejected.push({ index, reason: `child is ${step.status}` });
1424
+ continue;
1425
+ }
1426
+ enqueueStepSteer(asyncDir, index, request);
1427
+ step.steerCount = (step.steerCount ?? 0) + 1;
1428
+ step.lastSteerAt = now;
1429
+ accepted.push(index);
1430
+ }
1431
+ if (accepted.length > 0) {
1432
+ statusPayload.steerCount = (statusPayload.steerCount ?? 0) + accepted.length;
1433
+ statusPayload.lastSteerAt = now;
1434
+ statusPayload.lastUpdate = now;
1435
+ writeStatusPayload();
1436
+ }
1437
+ appendJsonl(eventsPath, JSON.stringify({
1438
+ type: "subagent.steer.requested",
1439
+ ts: now,
1440
+ runId: id,
1441
+ requestId: request.id,
1442
+ message: request.message,
1443
+ ...request.source ? { source: request.source } : {},
1444
+ ...request.targetIndex !== undefined ? { targetIndex: request.targetIndex } : {},
1445
+ acceptedIndexes: accepted,
1446
+ ...rejected.length ? { rejected } : {}
1447
+ }));
1448
+ };
1449
+ const flushPendingStepSteers = (flatIndex) => {
1450
+ const remaining = [];
1451
+ for (const request of pendingStepSteers.splice(0)) {
1452
+ if (request.targetIndex === undefined)
1453
+ deliverSteerRequest({ ...request, targetIndex: flatIndex });
1454
+ else if (request.targetIndex === flatIndex)
1455
+ deliverSteerRequest(request);
1456
+ else
1457
+ remaining.push(request);
1458
+ }
1459
+ pendingStepSteers.push(...remaining);
1460
+ };
1461
+ const updateStepModel = (flatIndex, model, thinking, now = Date.now()) => {
1462
+ const step = statusPayload.steps[flatIndex];
1463
+ if (!step)
1464
+ return;
1465
+ step.model = model;
1466
+ step.thinking = thinking;
1467
+ statusPayload.lastUpdate = now;
1468
+ writeStatusPayload();
1469
+ };
1470
+ const updateStepTurnBudget = (flatIndex, turnCount, now, terminalAssistantStop) => {
1471
+ const budget = config.turnBudget;
1472
+ const step = statusPayload.steps[flatIndex];
1473
+ if (!budget || !step || timedOut || turnBudgetExceeded || step.turnBudgetExceeded)
1474
+ return;
1475
+ if (turnCount < budget.maxTurns) {
1476
+ const state = { ...budget, outcome: "within-budget", turnCount };
1477
+ step.turnBudget = state;
1478
+ statusPayload.turnBudget = state;
1479
+ return;
1480
+ }
1481
+ const state = turnBudgetState(budget, turnCount, false);
1482
+ step.turnBudget = state;
1483
+ statusPayload.turnBudget = state;
1484
+ if (!step.wrapUpRequested) {
1485
+ step.wrapUpRequested = true;
1486
+ statusPayload.wrapUpRequested = true;
1487
+ appendRecentStepOutput(step, [turnBudgetSoftNote(budget, turnCount)]);
1488
+ }
1489
+ if (!shouldAbortForTurnBudget(budget, turnCount, terminalAssistantStop))
1490
+ return;
1491
+ const exceededState = turnBudgetState(budget, turnCount, true);
1492
+ const message = turnBudgetExceededMessage(budget, turnCount);
1493
+ step.turnBudget = exceededState;
1494
+ step.turnBudgetExceeded = true;
1495
+ step.wrapUpRequested = true;
1496
+ step.error = message;
1497
+ turnBudgetExceeded = true;
1498
+ statusPayload.turnBudget = exceededState;
1499
+ statusPayload.turnBudgetExceeded = true;
1500
+ statusPayload.wrapUpRequested = true;
1501
+ statusPayload.error = message;
1502
+ statusPayload.lastUpdate = now;
1503
+ appendJsonl(eventsPath, JSON.stringify({ type: "subagent.step.turn_budget_exceeded", ts: now, runId: id, stepIndex: flatIndex, agent: step.agent, turnCount, maxTurns: budget.maxTurns, graceTurns: budget.graceTurns, message }));
1504
+ activeChildTurnBudgetAborts.get(flatIndex)?.(message, exceededState);
1505
+ };
1506
+ const updateStepFromChildEvent = (flatIndex, event) => {
1507
+ const step = statusPayload.steps[flatIndex];
1508
+ if (!step)
1509
+ return;
1510
+ const now = Date.now();
1511
+ statusPayload.currentStep = flatIndex;
1512
+ if (event.type === "tool_execution_start" && event.toolName) {
1513
+ const mutates = isMutatingTool(event.toolName, event.args);
1514
+ const currentPath = resolveCurrentPath(event.toolName, event.args);
1515
+ step.toolCount = (step.toolCount ?? 0) + 1;
1516
+ const configuredToolBudget = flatSteps[flatIndex]?.toolBudget;
1517
+ if (configuredToolBudget) {
1518
+ step.toolBudget = toolBudgetState(configuredToolBudget, step.toolCount);
1519
+ statusPayload.toolBudget = step.toolBudget;
1520
+ }
1521
+ step.currentTool = event.toolName;
1522
+ step.currentToolArgs = extractToolArgsPreview(event.args ?? {});
1523
+ step.currentToolStartedAt = now;
1524
+ step.currentPath = currentPath;
1525
+ pendingToolResults[flatIndex] = { tool: event.toolName, path: currentPath, mutates, startedAt: now };
1526
+ statusPayload.toolCount = (statusPayload.toolCount ?? 0) + 1;
1527
+ syncTopLevelCurrentTool();
1528
+ } else if (event.type === "tool_execution_end") {
1529
+ if (step.currentTool) {
1530
+ step.recentTools ??= [];
1531
+ step.recentTools.push({ tool: step.currentTool, args: step.currentToolArgs || "", endMs: now });
1532
+ }
1533
+ step.currentTool = undefined;
1534
+ step.currentToolArgs = undefined;
1535
+ step.currentToolStartedAt = undefined;
1536
+ step.currentPath = undefined;
1537
+ syncTopLevelCurrentTool();
1538
+ } else if (event.type === "tool_result_end" && event.message) {
1539
+ const toolSnapshot = pendingToolResults[flatIndex];
1540
+ pendingToolResults[flatIndex] = undefined;
1541
+ const resultText = extractTextFromContent(event.message.content);
1542
+ if (toolSnapshot && resultText.includes("Tool budget hard limit reached")) {
1543
+ const configuredToolBudget = flatSteps[flatIndex]?.toolBudget;
1544
+ if (configuredToolBudget) {
1545
+ step.toolBudget = toolBudgetState(configuredToolBudget, step.toolCount ?? 0, toolSnapshot.tool);
1546
+ step.toolBudgetBlocked = true;
1547
+ statusPayload.toolBudget = step.toolBudget;
1548
+ statusPayload.toolBudgetBlocked = true;
1549
+ }
1550
+ }
1551
+ appendRecentStepOutput(step, resultText.split(`
1552
+ `).slice(-10));
1553
+ if (toolSnapshot?.mutates && didMutatingToolFail(resultText)) {
1554
+ const state = mutatingFailureStates[flatIndex];
1555
+ recordMutatingFailure(state, {
1556
+ tool: toolSnapshot.tool,
1557
+ path: toolSnapshot.path,
1558
+ error: resultText.split(`
1559
+ `).find((line) => line.trim())?.trim().slice(0, 180) ?? "mutating tool failed",
1560
+ ts: now
1561
+ }, mutatingFailureWindowMs);
1562
+ if (controlConfig.enabled && shouldEscalateMutatingFailures(state, controlConfig.failedToolAttemptsBeforeAttention) && step.activityState !== "needs_attention") {
1563
+ const previous = step.activityState;
1564
+ step.activityState = "needs_attention";
1565
+ statusPayload.activityState = "needs_attention";
1566
+ appendControlEvent(buildControlEvent({
1567
+ type: "needs_attention",
1568
+ from: previous,
1569
+ to: "needs_attention",
1570
+ runId: id,
1571
+ agent: step.agent,
1572
+ index: flatIndex,
1573
+ ts: now,
1574
+ message: `${step.agent} needs attention after repeated mutating tool failures`,
1575
+ reason: "tool_failures",
1576
+ turns: step.turnCount,
1577
+ tokens: step.tokens?.total,
1578
+ toolCount: step.toolCount,
1579
+ currentTool: toolSnapshot.tool,
1580
+ currentToolDurationMs: toolSnapshot.startedAt ? Math.max(0, now - toolSnapshot.startedAt) : undefined,
1581
+ currentPath: toolSnapshot.path,
1582
+ recentFailureSummary: summarizeRecentMutatingFailures(state)
1583
+ }));
1584
+ }
1585
+ } else if (toolSnapshot?.mutates) {
1586
+ resetMutatingFailureState(mutatingFailureStates[flatIndex]);
1587
+ }
1588
+ } else if (event.type === "message_end" && event.message?.role === "assistant") {
1589
+ appendRecentStepOutput(step, stripAcceptanceReport(extractTextFromContent(event.message.content)).split(`
1590
+ `).slice(-10));
1591
+ step.turnCount = (step.turnCount ?? 0) + 1;
1592
+ const usage = event.message.usage;
1593
+ if (usage) {
1594
+ const input = usage.input ?? usage.inputTokens ?? 0;
1595
+ const output = usage.output ?? usage.outputTokens ?? 0;
1596
+ const previousInput = step.tokens?.input ?? 0;
1597
+ const previousOutput = step.tokens?.output ?? 0;
1598
+ step.tokens = { input: previousInput + input, output: previousOutput + output, total: previousInput + previousOutput + input + output };
1599
+ const totalInput = statusPayload.totalTokens?.input ?? 0;
1600
+ const totalOutput = statusPayload.totalTokens?.output ?? 0;
1601
+ statusPayload.totalTokens = { input: totalInput + input, output: totalOutput + output, total: totalInput + totalOutput + input + output };
1602
+ }
1603
+ statusPayload.turnCount = Math.max(statusPayload.turnCount ?? 0, step.turnCount);
1604
+ updateStepTurnBudget(flatIndex, step.turnCount, now, isTerminalAssistantStop(event.message));
1605
+ }
1606
+ syncTopLevelCurrentTool();
1607
+ step.lastActivityAt = now;
1608
+ statusPayload.lastActivityAt = now;
1609
+ statusPayload.lastUpdate = now;
1610
+ maybeEmitActiveLongRunning(flatIndex, now);
1611
+ writeStatusPayload();
1612
+ };
1613
+ const updateRunnerActivityState = (now) => {
1614
+ if (!controlConfig.enabled)
1615
+ return false;
1616
+ let changed = false;
1617
+ let runLastActivityAt = statusPayload.lastActivityAt ?? overallStartTime;
1618
+ for (let index = 0;index < statusPayload.steps.length; index++) {
1619
+ const step = statusPayload.steps[index];
1620
+ if (step.status !== "running")
1621
+ continue;
1622
+ const lastActivityAt = stepOutputActivityAt(index);
1623
+ runLastActivityAt = Math.max(runLastActivityAt, lastActivityAt);
1624
+ if (step.lastActivityAt !== lastActivityAt) {
1625
+ step.lastActivityAt = lastActivityAt;
1626
+ changed = true;
1627
+ }
1628
+ const idleState = deriveActivityState({
1629
+ config: controlConfig,
1630
+ startedAt: step.startedAt ?? overallStartTime,
1631
+ lastActivityAt,
1632
+ now
1633
+ });
1634
+ if (idleState === "needs_attention") {
1635
+ const previous = step.activityState;
1636
+ step.activityState = "needs_attention";
1637
+ if (previous !== "needs_attention") {
1638
+ appendControlEvent(buildControlEvent({
1639
+ from: previous,
1640
+ to: "needs_attention",
1641
+ runId: id,
1642
+ agent: step.agent,
1643
+ index,
1644
+ ts: now,
1645
+ lastActivityAt
1646
+ }));
1647
+ changed = true;
1648
+ }
1649
+ } else if (maybeEmitActiveLongRunning(index, now)) {
1650
+ changed = true;
1651
+ }
1652
+ }
1653
+ if (statusPayload.lastActivityAt !== runLastActivityAt) {
1654
+ statusPayload.lastActivityAt = runLastActivityAt;
1655
+ changed = true;
1656
+ }
1657
+ const nextRunState = statusPayload.steps.some((step) => step.activityState === "needs_attention") ? "needs_attention" : statusPayload.steps.some((step) => step.activityState === "active_long_running") ? "active_long_running" : undefined;
1658
+ if (nextRunState !== currentActivityState) {
1659
+ currentActivityState = nextRunState;
1660
+ statusPayload.activityState = nextRunState;
1661
+ changed = true;
1662
+ }
1663
+ statusPayload.lastUpdate = now;
1664
+ if (changed)
1665
+ writeStatusPayload();
1666
+ return changed;
1667
+ };
1668
+ if (controlConfig.enabled) {
1669
+ activityTimer = setInterval(() => {
1670
+ if (statusPayload.state !== "running")
1671
+ return;
1672
+ const now = Date.now();
1673
+ updateRunnerActivityState(now);
1674
+ }, 1000);
1675
+ activityTimer.unref?.();
1676
+ }
1677
+ const interruptRunner = () => {
1678
+ consumeInterruptRequest(asyncDir);
1679
+ if (interrupted || statusPayload.state !== "running")
1680
+ return;
1681
+ interrupted = true;
1682
+ const now = Date.now();
1683
+ statusPayload.state = "paused";
1684
+ currentActivityState = undefined;
1685
+ statusPayload.activityState = undefined;
1686
+ statusPayload.lastUpdate = now;
1687
+ for (const step of statusPayload.steps) {
1688
+ if (step.status === "running") {
1689
+ step.status = "paused";
1690
+ step.activityState = undefined;
1691
+ step.endedAt = now;
1692
+ step.durationMs = step.startedAt ? now - step.startedAt : undefined;
1693
+ step.lastActivityAt = now;
1694
+ }
1695
+ }
1696
+ writeStatusPayload();
1697
+ appendJsonl(eventsPath, JSON.stringify({
1698
+ type: "subagent.run.paused",
1699
+ ts: now,
1700
+ runId: id
1701
+ }));
1702
+ interruptNestedAsyncDescendants();
1703
+ interruptActiveChildren();
1704
+ };
1705
+ const timeoutRunner = () => {
1706
+ if (timedOut || interrupted || statusPayload.state !== "running")
1707
+ return;
1708
+ timedOut = true;
1709
+ const now = Date.now();
1710
+ const message = timeoutMessage ?? "Subagent timed out.";
1711
+ statusPayload.state = "failed";
1712
+ statusPayload.timedOut = true;
1713
+ statusPayload.error = message;
1714
+ currentActivityState = undefined;
1715
+ statusPayload.activityState = undefined;
1716
+ statusPayload.lastUpdate = now;
1717
+ for (const step of statusPayload.steps) {
1718
+ if (step.status !== "running" && step.status !== "pending")
1719
+ continue;
1720
+ step.status = "failed";
1721
+ step.error = message;
1722
+ step.exitCode = 1;
1723
+ step.timedOut = true;
1724
+ step.activityState = undefined;
1725
+ step.endedAt = now;
1726
+ step.durationMs = step.startedAt ? now - step.startedAt : 0;
1727
+ step.lastActivityAt = now;
1728
+ }
1729
+ writeStatusPayload();
1730
+ appendJsonl(eventsPath, JSON.stringify({
1731
+ type: "subagent.run.timed_out",
1732
+ ts: now,
1733
+ runId: id,
1734
+ timeoutMs: config.timeoutMs,
1735
+ deadlineAt: config.deadlineAt,
1736
+ message
1737
+ }));
1738
+ timeoutAbortController.abort();
1739
+ timeoutNestedAsyncDescendants();
1740
+ timeoutActiveChildren();
1741
+ };
1742
+ process.on(ASYNC_INTERRUPT_SIGNAL, interruptRunner);
1743
+ const disposeControlInbox = watchAsyncControlInbox(asyncDir, {
1744
+ onInterrupt: interruptRunner,
1745
+ onTimeout: timeoutRunner,
1746
+ onSteer: (request) => {
1747
+ const targetStep = request.targetIndex !== undefined ? statusPayload.steps[request.targetIndex] : undefined;
1748
+ if (targetStep?.status === "pending")
1749
+ pendingStepSteers.push(request);
1750
+ else if (request.targetIndex !== undefined || statusPayload.steps.some((step) => step.status === "running"))
1751
+ deliverSteerRequest(request);
1752
+ else
1753
+ pendingStepSteers.push(request);
1754
+ }
1755
+ });
1756
+ if (config.deadlineAt !== undefined) {
1757
+ const remainingMs = Math.max(0, config.deadlineAt - Date.now());
1758
+ timeoutTimer = setTimeout(timeoutRunner, remainingMs);
1759
+ timeoutTimer.unref?.();
1760
+ }
1761
+ appendJsonl(eventsPath, JSON.stringify({
1762
+ type: "subagent.run.started",
1763
+ lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
1764
+ ts: overallStartTime,
1765
+ runId: id,
1766
+ mode: statusPayload.mode,
1767
+ cwd,
1768
+ pid: process.pid
1769
+ }));
1770
+ let flatIndex = 0;
1771
+ let stepCursor = 0;
1772
+ while (true) {
1773
+ if (interrupted || timedOut || turnBudgetExceeded)
1774
+ break;
1775
+ consumePendingAppendRequests();
1776
+ if (stepCursor >= steps.length)
1777
+ break;
1778
+ const stepIndex = stepCursor++;
1779
+ const step = steps[stepIndex];
1780
+ if (isDynamicRunnerGroup(step)) {
1781
+ const groupStartFlatIndex = flatIndex;
1782
+ let materialized;
1783
+ try {
1784
+ materialized = materializeDynamicParallelStep(step, outputs, stepIndex, { maxItems: config.dynamicFanoutMaxItems, allowRunnerFields: true });
1785
+ if (materialized.collectedOnEmpty)
1786
+ validateDynamicCollection(step.collect.outputSchema, materialized.collectedOnEmpty);
1787
+ } catch (error) {
1788
+ const now = Date.now();
1789
+ const message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);
1790
+ statusPayload.state = "failed";
1791
+ statusPayload.error = message;
1792
+ statusPayload.currentStep = flatIndex;
1793
+ const placeholder = statusPayload.steps[groupStartFlatIndex];
1794
+ if (placeholder) {
1795
+ placeholder.status = "failed";
1796
+ placeholder.error = message;
1797
+ placeholder.startedAt = now;
1798
+ placeholder.endedAt = now;
1799
+ placeholder.durationMs = 0;
1800
+ placeholder.exitCode = 1;
1801
+ }
1802
+ statusPayload.lastUpdate = now;
1803
+ markDynamicGraphGroup(stepIndex, "failed", message);
1804
+ writeStatusPayload();
1805
+ results.push({ agent: step.parallel.agent, output: message, error: message, success: false, exitCode: 1 });
1806
+ break;
1807
+ }
1808
+ if (materialized.parallel.length === 0) {
1809
+ const now = Date.now();
1810
+ const collection = materialized.collectedOnEmpty ?? [];
1811
+ outputs[step.collect.as] = {
1812
+ text: JSON.stringify(collection),
1813
+ structured: collection,
1814
+ agent: step.parallel.agent,
1815
+ stepIndex
1816
+ };
1817
+ statusPayload.outputs = outputs;
1818
+ const placeholder = statusPayload.steps[groupStartFlatIndex];
1819
+ if (placeholder) {
1820
+ placeholder.status = "complete";
1821
+ placeholder.startedAt = now;
1822
+ placeholder.endedAt = now;
1823
+ placeholder.durationMs = 0;
1824
+ }
1825
+ previousOutput = "Dynamic fanout produced 0 results.";
1826
+ const groupAcceptance = step.effectiveAcceptance?.explicit && !timedOut ? await evaluateAcceptance({
1827
+ acceptance: step.effectiveAcceptance,
1828
+ output: "",
1829
+ report: aggregateAcceptanceReport({
1830
+ results: [],
1831
+ notes: "Dynamic fanout produced 0 results."
1832
+ }),
1833
+ cwd,
1834
+ signal: timeoutAbortController.signal,
1835
+ abortMessage: timeoutMessage ?? "Subagent timed out."
1836
+ }) : undefined;
1837
+ const groupTimedOut = timedOut || timeoutAbortController.signal.aborted;
1838
+ const effectiveGroupAcceptance = groupTimedOut ? undefined : groupAcceptance;
1839
+ if (placeholder && effectiveGroupAcceptance)
1840
+ placeholder.acceptance = effectiveGroupAcceptance;
1841
+ const groupAcceptanceFailure = effectiveGroupAcceptance ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;
1842
+ if (groupTimedOut || groupAcceptanceFailure) {
1843
+ const errorMessage = groupTimedOut ? timeoutMessage ?? "Subagent timed out." : groupAcceptanceFailure;
1844
+ statusPayload.state = "failed";
1845
+ statusPayload.error = errorMessage;
1846
+ if (placeholder) {
1847
+ placeholder.status = "failed";
1848
+ placeholder.error = errorMessage;
1849
+ placeholder.exitCode = 1;
1850
+ placeholder.timedOut = groupTimedOut ? true : undefined;
1851
+ }
1852
+ markDynamicGraphGroup(stepIndex, "failed", errorMessage, effectiveGroupAcceptance);
1853
+ statusPayload.lastUpdate = Date.now();
1854
+ writeStatusPayload();
1855
+ results.push({ agent: step.parallel.agent, output: errorMessage, error: errorMessage, success: false, exitCode: 1, timedOut: groupTimedOut ? true : undefined, acceptance: effectiveGroupAcceptance });
1856
+ break;
1857
+ }
1858
+ flatIndex++;
1859
+ statusPayload.lastUpdate = now;
1860
+ markDynamicGraphGroup(stepIndex, "completed", undefined, effectiveGroupAcceptance);
1861
+ writeStatusPayload();
1862
+ continue;
1863
+ }
1864
+ const dynamicSteps = materialized.parallel.map((task, itemIndex) => {
1865
+ const thinkingOverride = step.thinkingOverrides?.[itemIndex];
1866
+ const model = thinkingOverride ? applyThinkingSuffix(step.parallel.model, thinkingOverride, true) : step.parallel.model;
1867
+ const thinking = thinkingOverride ? resolveEffectiveThinking(model, thinkingOverride) : undefined;
1868
+ return {
1869
+ ...step.parallel,
1870
+ task: task.task ?? step.parallel.task,
1871
+ label: task.label ?? step.parallel.label,
1872
+ ...step.sessionFiles?.[itemIndex] ? { sessionFile: step.sessionFiles[itemIndex] } : {},
1873
+ ...thinkingOverride ? {
1874
+ ...model ? { model } : {},
1875
+ ...thinking ? { thinking } : {},
1876
+ ...step.parallel.modelCandidates ? { modelCandidates: step.parallel.modelCandidates.map((candidate) => applyThinkingSuffix(candidate, thinkingOverride, true)) } : {}
1877
+ } : {},
1878
+ structuredOutput: undefined,
1879
+ structuredOutputSchema: step.parallel.structuredOutputSchema ?? step.parallel.structuredOutput?.schema
1880
+ };
1881
+ });
1882
+ const dynamicFlatStepCount = Math.max(statusPayload.steps.length - 1 + dynamicSteps.length, 1);
1883
+ const dynamicStatusSteps = dynamicSteps.map((task, itemIndex) => {
1884
+ const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: groupStartFlatIndex + itemIndex, flatStepCount: dynamicFlatStepCount });
1885
+ return {
1886
+ agent: task.agent,
1887
+ phase: task.phase ?? step.phase,
1888
+ label: task.label,
1889
+ outputName: undefined,
1890
+ structured: Boolean(task.structuredOutputSchema),
1891
+ status: "pending",
1892
+ ...task.sessionFile ? { sessionFile: task.sessionFile } : {},
1893
+ ...transcriptPath ? { transcriptPath } : {},
1894
+ skills: task.skills,
1895
+ model: task.model,
1896
+ thinking: task.thinking,
1897
+ attemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,
1898
+ recentTools: [],
1899
+ recentOutput: []
1900
+ };
1901
+ });
1902
+ statusPayload.steps.splice(groupStartFlatIndex, 1, ...dynamicStatusSteps);
1903
+ if (config.childIntercomTargets) {
1904
+ config.childIntercomTargets = statusPayload.steps.map((statusStep, index) => resolveSubagentIntercomTarget(id, statusStep.agent, index));
1905
+ }
1906
+ mutatingFailureStates.splice(groupStartFlatIndex, 1, ...dynamicStatusSteps.map(() => createMutatingFailureState()));
1907
+ pendingToolResults.splice(groupStartFlatIndex, 1, ...dynamicStatusSteps.map(() => {
1908
+ return;
1909
+ }));
1910
+ const materializedDelta = dynamicStatusSteps.length - 1;
1911
+ for (const group of statusPayload.parallelGroups) {
1912
+ if (group.stepIndex === stepIndex) {
1913
+ group.start = groupStartFlatIndex;
1914
+ group.count = dynamicStatusSteps.length;
1915
+ } else if (group.start > groupStartFlatIndex) {
1916
+ group.start += materializedDelta;
1917
+ }
1918
+ }
1919
+ if (statusPayload.workflowGraph) {
1920
+ const shiftFlatIndexes = (nodes) => {
1921
+ for (const node of nodes) {
1922
+ if (node.stepIndex !== undefined && node.stepIndex > stepIndex && node.flatIndex !== undefined && node.flatIndex >= groupStartFlatIndex) {
1923
+ node.flatIndex += dynamicStatusSteps.length;
1924
+ }
1925
+ if (node.children)
1926
+ shiftFlatIndexes(node.children);
1927
+ }
1928
+ };
1929
+ shiftFlatIndexes(statusPayload.workflowGraph.nodes);
1930
+ const groupNode = statusPayload.workflowGraph.nodes.find((node) => node.id === `step-${stepIndex}`);
1931
+ if (groupNode) {
1932
+ groupNode.children = materialized.items.map((item, itemIndex) => ({
1933
+ id: `step-${stepIndex}-item-${item.idKey}`,
1934
+ kind: "agent",
1935
+ agent: step.parallel.agent,
1936
+ phase: dynamicSteps[itemIndex]?.phase ?? step.phase,
1937
+ label: dynamicSteps[itemIndex]?.label?.trim() || `${step.parallel.agent} ${item.key}`,
1938
+ status: "pending",
1939
+ flatIndex: groupStartFlatIndex + itemIndex,
1940
+ stepIndex,
1941
+ itemKey: item.key,
1942
+ structured: Boolean(dynamicSteps[itemIndex]?.structuredOutputSchema)
1943
+ }));
1944
+ }
1945
+ }
1946
+ writeStatusPayload();
1947
+ const concurrency = step.concurrency ?? MAX_PARALLEL_CONCURRENCY;
1948
+ const failFast = step.failFast ?? false;
1949
+ let aborted = false;
1950
+ const parallelResults = await mapConcurrent(dynamicSteps, concurrency, async (task, taskIdx) => {
1951
+ const fi = groupStartFlatIndex + taskIdx;
1952
+ if (timedOut)
1953
+ return timedOutStepResult(task.agent);
1954
+ if (interrupted)
1955
+ return pausedStepResult(task.agent);
1956
+ if (aborted && failFast) {
1957
+ const skippedAt = Date.now();
1958
+ statusPayload.steps[fi].status = "failed";
1959
+ statusPayload.steps[fi].error = "Skipped due to fail-fast";
1960
+ statusPayload.steps[fi].startedAt = skippedAt;
1961
+ statusPayload.steps[fi].endedAt = skippedAt;
1962
+ statusPayload.steps[fi].durationMs = 0;
1963
+ statusPayload.steps[fi].exitCode = -1;
1964
+ statusPayload.lastUpdate = skippedAt;
1965
+ writeStatusPayload();
1966
+ return { agent: task.agent, output: "(skipped — fail-fast)", exitCode: -1, skipped: true };
1967
+ }
1968
+ const taskStartTime = Date.now();
1969
+ statusPayload.currentStep = fi;
1970
+ statusPayload.steps[fi].status = "running";
1971
+ statusPayload.steps[fi].error = undefined;
1972
+ statusPayload.steps[fi].activityState = undefined;
1973
+ resetStepLiveDetail(statusPayload.steps[fi]);
1974
+ statusPayload.steps[fi].startedAt = taskStartTime;
1975
+ statusPayload.steps[fi].lastActivityAt = taskStartTime;
1976
+ statusPayload.outputFile = path.join(asyncDir, `output-${fi}.log`);
1977
+ statusPayload.lastActivityAt = taskStartTime;
1978
+ statusPayload.lastUpdate = taskStartTime;
1979
+ writeStatusPayload();
1980
+ appendJsonl(eventsPath, JSON.stringify({ type: "subagent.step.started", ts: taskStartTime, runId: id, stepIndex: fi, agent: task.agent }));
1981
+ flushPendingStepSteers(fi);
1982
+ const singleResult = await runSingleStep(task, {
1983
+ previousOutput,
1984
+ placeholder,
1985
+ cwd,
1986
+ sessionEnabled,
1987
+ outputs,
1988
+ sessionDir: config.sessionDir ? path.join(config.sessionDir, `dynamic-${stepIndex}-${taskIdx}`) : undefined,
1989
+ artifactsDir,
1990
+ artifactConfig,
1991
+ id,
1992
+ flatIndex: fi,
1993
+ flatStepCount: Math.max(statusPayload.steps.length, 1),
1994
+ outputFile: path.join(asyncDir, `output-${fi}.log`),
1995
+ steerInboxDir: stepSteerInboxDir(asyncDir, fi),
1996
+ piPackageRoot: config.piPackageRoot,
1997
+ piArgv1: config.piArgv1,
1998
+ childIntercomTarget: config.childIntercomTargets?.[fi],
1999
+ orchestratorIntercomTarget: config.controlIntercomTarget,
2000
+ nestedRoute: config.nestedRoute,
2001
+ registerInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),
2002
+ registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
2003
+ registerTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(fi, abort),
2004
+ timeoutSignal: timeoutAbortController.signal,
2005
+ timeoutMessage,
2006
+ turnBudget: config.turnBudget,
2007
+ onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking),
2008
+ onChildEvent: (event) => updateStepFromChildEvent(fi, event),
2009
+ skipAcceptance: () => timedOut
2010
+ });
2011
+ const taskEndTime = Date.now();
2012
+ const childInterrupted = singleResult.interrupted === true;
2013
+ statusPayload.steps[fi].status = timedOut ? "failed" : childInterrupted ? "paused" : singleResult.exitCode === 0 ? "complete" : "failed";
2014
+ statusPayload.steps[fi].endedAt = taskEndTime;
2015
+ statusPayload.steps[fi].durationMs = taskEndTime - taskStartTime;
2016
+ statusPayload.steps[fi].exitCode = timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
2017
+ statusPayload.steps[fi].timedOut = timedOut || singleResult.timedOut ? true : undefined;
2018
+ statusPayload.steps[fi].turnBudget = singleResult.turnBudget;
2019
+ statusPayload.steps[fi].turnBudgetExceeded = singleResult.turnBudgetExceeded;
2020
+ statusPayload.steps[fi].wrapUpRequested = singleResult.wrapUpRequested;
2021
+ statusPayload.steps[fi].toolBudget = singleResult.toolBudget;
2022
+ statusPayload.steps[fi].toolBudgetBlocked = singleResult.toolBudgetBlocked;
2023
+ if (singleResult.toolBudget)
2024
+ statusPayload.toolBudget = singleResult.toolBudget;
2025
+ if (singleResult.toolBudgetBlocked)
2026
+ statusPayload.toolBudgetBlocked = true;
2027
+ if (singleResult.turnBudget)
2028
+ statusPayload.turnBudget = singleResult.turnBudget;
2029
+ if (singleResult.turnBudgetExceeded)
2030
+ statusPayload.turnBudgetExceeded = true;
2031
+ if (singleResult.wrapUpRequested)
2032
+ statusPayload.wrapUpRequested = true;
2033
+ statusPayload.steps[fi].model = singleResult.model;
2034
+ statusPayload.steps[fi].thinking = resolveEffectiveThinking(singleResult.model, statusPayload.steps[fi].thinking);
2035
+ statusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;
2036
+ statusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;
2037
+ statusPayload.steps[fi].totalCost = singleResult.totalCost;
2038
+ statusPayload.steps[fi].error = timedOut ? timeoutMessage ?? "Subagent timed out." : singleResult.error;
2039
+ statusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;
2040
+ statusPayload.steps[fi].transcriptError = singleResult.transcriptError;
2041
+ statusPayload.steps[fi].structuredOutput = singleResult.structuredOutput;
2042
+ statusPayload.steps[fi].structuredOutputPath = singleResult.structuredOutputPath;
2043
+ statusPayload.steps[fi].structuredOutputSchemaPath = singleResult.structuredOutputSchemaPath;
2044
+ statusPayload.steps[fi].acceptance = singleResult.acceptance;
2045
+ statusPayload.lastUpdate = taskEndTime;
2046
+ writeStatusPayload();
2047
+ appendJsonl(eventsPath, JSON.stringify({
2048
+ type: timedOut ? "subagent.step.failed" : childInterrupted ? "subagent.step.paused" : singleResult.exitCode === 0 ? "subagent.step.completed" : "subagent.step.failed",
2049
+ ts: taskEndTime,
2050
+ runId: id,
2051
+ stepIndex: fi,
2052
+ agent: task.agent,
2053
+ exitCode: timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode,
2054
+ durationMs: taskEndTime - taskStartTime
2055
+ }));
2056
+ if (singleResult.exitCode !== 0 && failFast)
2057
+ aborted = true;
2058
+ return timedOut ? { ...singleResult, output: timeoutMessage ?? "Subagent timed out.", error: timeoutMessage ?? "Subagent timed out.", exitCode: 1, interrupted: false, timedOut: true, skipped: false } : { ...singleResult, skipped: false };
2059
+ }, globalSemaphore);
2060
+ flatIndex += dynamicSteps.length;
2061
+ for (const pr of parallelResults) {
2062
+ results.push({
2063
+ agent: pr.agent,
2064
+ output: pr.output,
2065
+ error: pr.error,
2066
+ success: pr.interrupted !== true && pr.exitCode === 0,
2067
+ exitCode: pr.interrupted === true ? 0 : pr.exitCode,
2068
+ skipped: pr.skipped,
2069
+ interrupted: pr.interrupted,
2070
+ timedOut: pr.timedOut,
2071
+ turnBudget: pr.turnBudget,
2072
+ turnBudgetExceeded: pr.turnBudgetExceeded,
2073
+ wrapUpRequested: pr.wrapUpRequested,
2074
+ toolBudget: pr.toolBudget,
2075
+ toolBudgetBlocked: pr.toolBudgetBlocked,
2076
+ sessionFile: pr.sessionFile,
2077
+ intercomTarget: pr.intercomTarget,
2078
+ model: pr.model,
2079
+ attemptedModels: pr.attemptedModels,
2080
+ modelAttempts: pr.modelAttempts,
2081
+ totalCost: pr.totalCost,
2082
+ artifactPaths: pr.artifactPaths,
2083
+ transcriptPath: pr.transcriptPath,
2084
+ transcriptError: pr.transcriptError,
2085
+ structuredOutput: pr.structuredOutput,
2086
+ structuredOutputPath: pr.structuredOutputPath,
2087
+ structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
2088
+ acceptance: pr.acceptance
2089
+ });
2090
+ }
2091
+ const collection = collectDynamicResults(step, materialized.items, parallelResults);
2092
+ const failures = parallelResults.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);
2093
+ if (failures.length === 0) {
2094
+ try {
2095
+ validateDynamicCollection(step.collect.outputSchema, collection);
2096
+ outputs[step.collect.as] = {
2097
+ text: JSON.stringify(collection),
2098
+ structured: collection,
2099
+ agent: step.parallel.agent,
2100
+ stepIndex
2101
+ };
2102
+ statusPayload.outputs = outputs;
2103
+ const groupAcceptance = step.effectiveAcceptance && !timedOut ? await evaluateAcceptance({
2104
+ acceptance: step.effectiveAcceptance,
2105
+ output: "",
2106
+ report: aggregateAcceptanceReport({
2107
+ results: parallelResults,
2108
+ notes: `Dynamic fanout collected ${collection.length} result(s) into ${step.collect.as}.`
2109
+ }),
2110
+ cwd,
2111
+ signal: timeoutAbortController.signal,
2112
+ abortMessage: timeoutMessage ?? "Subagent timed out."
2113
+ }) : undefined;
2114
+ const groupTimedOut = timedOut || timeoutAbortController.signal.aborted;
2115
+ const effectiveGroupAcceptance = groupTimedOut ? undefined : groupAcceptance;
2116
+ const groupAcceptanceFailure = effectiveGroupAcceptance ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;
2117
+ const groupError = groupTimedOut ? timeoutMessage ?? "Subagent timed out." : groupAcceptanceFailure;
2118
+ markDynamicGraphGroup(stepIndex, groupError ? "failed" : "completed", groupError, effectiveGroupAcceptance);
2119
+ if (groupError) {
2120
+ results.push({
2121
+ agent: step.parallel.agent,
2122
+ output: groupError,
2123
+ error: groupError,
2124
+ success: false,
2125
+ exitCode: 1,
2126
+ timedOut: groupTimedOut ? true : undefined,
2127
+ structuredOutput: collection,
2128
+ acceptance: effectiveGroupAcceptance
2129
+ });
2130
+ statusPayload.error = groupError;
2131
+ }
2132
+ } catch (error) {
2133
+ const message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);
2134
+ results.push({ agent: step.parallel.agent, output: message, error: message, success: false, exitCode: 1, structuredOutput: collection });
2135
+ statusPayload.error = message;
2136
+ markDynamicGraphGroup(stepIndex, "failed", message);
2137
+ }
2138
+ }
2139
+ previousOutput = aggregateParallelOutputs(parallelResults.map((r, i) => ({
2140
+ agent: r.agent,
2141
+ taskIndex: i,
2142
+ output: r.output,
2143
+ exitCode: r.exitCode,
2144
+ error: r.error
2145
+ })), (i, agent) => `=== Dynamic Item ${i + 1} (${agent}, key ${materialized.items[i]?.key ?? i}) ===`);
2146
+ appendJsonl(eventsPath, JSON.stringify({
2147
+ type: "subagent.dynamic.completed",
2148
+ ts: Date.now(),
2149
+ runId: id,
2150
+ stepIndex,
2151
+ success: failures.length === 0
2152
+ }));
2153
+ if (failures.length > 0)
2154
+ markDynamicGraphGroup(stepIndex, "failed", failures[0]?.error ?? "Dynamic fanout child failed.");
2155
+ statusPayload.lastUpdate = Date.now();
2156
+ writeStatusPayload();
2157
+ if (failures.length > 0 || statusPayload.error)
2158
+ break;
2159
+ continue;
2160
+ }
2161
+ if (isParallelGroup(step)) {
2162
+ const group = step;
2163
+ const concurrency = group.concurrency ?? MAX_PARALLEL_CONCURRENCY;
2164
+ const failFast = group.failFast ?? false;
2165
+ const groupStartFlatIndex = flatIndex;
2166
+ let aborted = false;
2167
+ let worktreeSetup;
2168
+ if (group.worktree) {
2169
+ const worktreeTaskCwdConflict = findWorktreeTaskCwdConflict(group.parallel, cwd);
2170
+ if (worktreeTaskCwdConflict) {
2171
+ const failedAt = Date.now();
2172
+ markParallelGroupSetupFailure({
2173
+ statusPayload,
2174
+ results,
2175
+ group,
2176
+ groupStartFlatIndex,
2177
+ setupError: formatWorktreeTaskCwdConflict(worktreeTaskCwdConflict, cwd),
2178
+ failedAt,
2179
+ statusPath,
2180
+ eventsPath,
2181
+ asyncDir,
2182
+ runId: id,
2183
+ stepIndex
2184
+ });
2185
+ flatIndex += group.parallel.length;
2186
+ break;
2187
+ }
2188
+ try {
2189
+ worktreeSetup = createWorktrees(cwd, `${id}-s${stepIndex}`, group.parallel.length, {
2190
+ agents: group.parallel.map((task) => task.agent),
2191
+ setupHook: config.worktreeSetupHook ? { hookPath: config.worktreeSetupHook, timeoutMs: config.worktreeSetupHookTimeoutMs } : undefined,
2192
+ baseDir: config.worktreeBaseDir
2193
+ });
2194
+ } catch (error) {
2195
+ const setupError = error instanceof Error ? error.message : String(error);
2196
+ const failedAt = Date.now();
2197
+ markParallelGroupSetupFailure({
2198
+ statusPayload,
2199
+ results,
2200
+ group,
2201
+ groupStartFlatIndex,
2202
+ setupError,
2203
+ failedAt,
2204
+ statusPath,
2205
+ eventsPath,
2206
+ asyncDir,
2207
+ runId: id,
2208
+ stepIndex
2209
+ });
2210
+ flatIndex += group.parallel.length;
2211
+ break;
2212
+ }
2213
+ }
2214
+ try {
2215
+ if (group.worktree)
2216
+ ensureParallelProgressFile(cwd, group);
2217
+ const groupStartTime = Date.now();
2218
+ markParallelGroupRunning({
2219
+ statusPayload,
2220
+ group,
2221
+ groupStartFlatIndex,
2222
+ groupStartTime,
2223
+ statusPath,
2224
+ eventsPath,
2225
+ asyncDir,
2226
+ runId: id,
2227
+ stepIndex
2228
+ });
2229
+ const parallelResults = await mapConcurrent(group.parallel, concurrency, async (task, taskIdx) => {
2230
+ const fi = groupStartFlatIndex + taskIdx;
2231
+ if (timedOut)
2232
+ return timedOutStepResult(task.agent);
2233
+ if (interrupted)
2234
+ return pausedStepResult(task.agent);
2235
+ if (aborted && failFast) {
2236
+ const skippedAt = Date.now();
2237
+ statusPayload.steps[fi].status = "failed";
2238
+ statusPayload.steps[fi].error = "Skipped due to fail-fast";
2239
+ statusPayload.steps[fi].startedAt = skippedAt;
2240
+ statusPayload.steps[fi].endedAt = skippedAt;
2241
+ statusPayload.steps[fi].durationMs = 0;
2242
+ statusPayload.steps[fi].exitCode = -1;
2243
+ statusPayload.steps[fi].activityState = undefined;
2244
+ statusPayload.lastUpdate = skippedAt;
2245
+ writeStatusPayload();
2246
+ appendJsonl(eventsPath, JSON.stringify({
2247
+ type: "subagent.step.failed",
2248
+ ts: skippedAt,
2249
+ runId: id,
2250
+ stepIndex: fi,
2251
+ agent: task.agent,
2252
+ exitCode: -1,
2253
+ durationMs: 0
2254
+ }));
2255
+ return { agent: task.agent, output: "(skipped — fail-fast)", exitCode: -1, skipped: true };
2256
+ }
2257
+ const taskStartTime = Date.now();
2258
+ statusPayload.currentStep = fi;
2259
+ statusPayload.steps[fi].status = "running";
2260
+ statusPayload.steps[fi].error = undefined;
2261
+ statusPayload.steps[fi].activityState = undefined;
2262
+ resetStepLiveDetail(statusPayload.steps[fi]);
2263
+ statusPayload.steps[fi].startedAt = taskStartTime;
2264
+ statusPayload.steps[fi].endedAt = undefined;
2265
+ statusPayload.steps[fi].durationMs = undefined;
2266
+ statusPayload.steps[fi].lastActivityAt = taskStartTime;
2267
+ statusPayload.outputFile = path.join(asyncDir, `output-${fi}.log`);
2268
+ statusPayload.lastActivityAt = taskStartTime;
2269
+ statusPayload.lastUpdate = taskStartTime;
2270
+ writeStatusPayload();
2271
+ appendJsonl(eventsPath, JSON.stringify({
2272
+ type: "subagent.step.started",
2273
+ ts: taskStartTime,
2274
+ runId: id,
2275
+ stepIndex: fi,
2276
+ agent: task.agent
2277
+ }));
2278
+ const taskSessionDir = config.sessionDir ? path.join(config.sessionDir, `parallel-${taskIdx}`) : undefined;
2279
+ const { taskForRun, taskCwd } = prepareParallelTaskRun(task, cwd, worktreeSetup, taskIdx);
2280
+ flushPendingStepSteers(fi);
2281
+ const singleResult = await runSingleStep(taskForRun, {
2282
+ previousOutput,
2283
+ placeholder,
2284
+ cwd: taskCwd,
2285
+ sessionEnabled,
2286
+ outputs,
2287
+ sessionDir: taskSessionDir,
2288
+ artifactsDir,
2289
+ artifactConfig,
2290
+ id,
2291
+ flatIndex: fi,
2292
+ flatStepCount: Math.max(statusPayload.steps.length, 1),
2293
+ outputFile: path.join(asyncDir, `output-${fi}.log`),
2294
+ steerInboxDir: stepSteerInboxDir(asyncDir, fi),
2295
+ piPackageRoot: config.piPackageRoot,
2296
+ piArgv1: config.piArgv1,
2297
+ childIntercomTarget: config.childIntercomTargets?.[fi],
2298
+ orchestratorIntercomTarget: config.controlIntercomTarget,
2299
+ nestedRoute: config.nestedRoute,
2300
+ registerInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),
2301
+ registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
2302
+ registerTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(fi, abort),
2303
+ timeoutSignal: timeoutAbortController.signal,
2304
+ timeoutMessage,
2305
+ turnBudget: config.turnBudget,
2306
+ onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking),
2307
+ onChildEvent: (event) => updateStepFromChildEvent(fi, event),
2308
+ skipAcceptance: () => timedOut
2309
+ });
2310
+ if (task.sessionFile) {
2311
+ latestSessionFile = task.sessionFile;
2312
+ }
2313
+ const taskEndTime = Date.now();
2314
+ const taskDuration = taskEndTime - taskStartTime;
2315
+ const childInterrupted = singleResult.interrupted === true;
2316
+ statusPayload.steps[fi].status = timedOut ? "failed" : childInterrupted ? "paused" : singleResult.exitCode === 0 ? "complete" : "failed";
2317
+ statusPayload.steps[fi].endedAt = taskEndTime;
2318
+ statusPayload.steps[fi].durationMs = taskDuration;
2319
+ statusPayload.steps[fi].exitCode = timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
2320
+ statusPayload.steps[fi].timedOut = timedOut || singleResult.timedOut ? true : undefined;
2321
+ statusPayload.steps[fi].turnBudget = singleResult.turnBudget;
2322
+ statusPayload.steps[fi].turnBudgetExceeded = singleResult.turnBudgetExceeded;
2323
+ statusPayload.steps[fi].wrapUpRequested = singleResult.wrapUpRequested;
2324
+ statusPayload.steps[fi].toolBudget = singleResult.toolBudget;
2325
+ statusPayload.steps[fi].toolBudgetBlocked = singleResult.toolBudgetBlocked;
2326
+ if (singleResult.toolBudget)
2327
+ statusPayload.toolBudget = singleResult.toolBudget;
2328
+ if (singleResult.toolBudgetBlocked)
2329
+ statusPayload.toolBudgetBlocked = true;
2330
+ if (singleResult.turnBudget)
2331
+ statusPayload.turnBudget = singleResult.turnBudget;
2332
+ if (singleResult.turnBudgetExceeded)
2333
+ statusPayload.turnBudgetExceeded = true;
2334
+ if (singleResult.wrapUpRequested)
2335
+ statusPayload.wrapUpRequested = true;
2336
+ statusPayload.steps[fi].model = singleResult.model;
2337
+ statusPayload.steps[fi].thinking = resolveEffectiveThinking(singleResult.model, statusPayload.steps[fi].thinking);
2338
+ statusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;
2339
+ statusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;
2340
+ statusPayload.steps[fi].totalCost = singleResult.totalCost;
2341
+ statusPayload.steps[fi].error = timedOut ? timeoutMessage ?? "Subagent timed out." : singleResult.error;
2342
+ statusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;
2343
+ statusPayload.steps[fi].transcriptError = singleResult.transcriptError;
2344
+ statusPayload.steps[fi].structuredOutput = singleResult.structuredOutput;
2345
+ statusPayload.steps[fi].structuredOutputPath = singleResult.structuredOutputPath;
2346
+ statusPayload.steps[fi].structuredOutputSchemaPath = singleResult.structuredOutputSchemaPath;
2347
+ statusPayload.steps[fi].acceptance = singleResult.acceptance;
2348
+ statusPayload.lastUpdate = taskEndTime;
2349
+ writeStatusPayload();
2350
+ appendJsonl(eventsPath, JSON.stringify({
2351
+ type: timedOut ? "subagent.step.failed" : childInterrupted ? "subagent.step.paused" : singleResult.exitCode === 0 ? "subagent.step.completed" : "subagent.step.failed",
2352
+ ts: taskEndTime,
2353
+ runId: id,
2354
+ stepIndex: fi,
2355
+ agent: task.agent,
2356
+ exitCode: timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode,
2357
+ durationMs: taskDuration
2358
+ }));
2359
+ if (singleResult.completionGuardTriggered) {
2360
+ const event = buildControlEvent({
2361
+ from: statusPayload.steps[fi].activityState,
2362
+ to: "needs_attention",
2363
+ runId: id,
2364
+ agent: task.agent,
2365
+ index: fi,
2366
+ ts: taskEndTime,
2367
+ message: `${task.agent} completed without making edits for an implementation task`,
2368
+ reason: "completion_guard"
2369
+ });
2370
+ appendControlEvent(event);
2371
+ }
2372
+ if (singleResult.exitCode !== 0 && failFast)
2373
+ aborted = true;
2374
+ return timedOut ? { ...singleResult, output: timeoutMessage ?? "Subagent timed out.", error: timeoutMessage ?? "Subagent timed out.", exitCode: 1, interrupted: false, timedOut: true, skipped: false } : { ...singleResult, skipped: false };
2375
+ }, globalSemaphore);
2376
+ flatIndex += group.parallel.length;
2377
+ for (let t = 0;t < group.parallel.length; t++) {
2378
+ const fi = groupStartFlatIndex + t;
2379
+ const sessionTokens = config.sessionDir ? parseSessionTokens(path.join(config.sessionDir, `parallel-${t}`)) : null;
2380
+ const taskTokens = sessionTokens ?? tokenUsageFromAttempts(parallelResults[t]?.modelAttempts);
2381
+ if (!taskTokens)
2382
+ continue;
2383
+ statusPayload.steps[fi].tokens = taskTokens;
2384
+ previousCumulativeTokens = {
2385
+ input: previousCumulativeTokens.input + taskTokens.input,
2386
+ output: previousCumulativeTokens.output + taskTokens.output,
2387
+ total: previousCumulativeTokens.total + taskTokens.total
2388
+ };
2389
+ }
2390
+ statusPayload.totalTokens = { ...previousCumulativeTokens };
2391
+ statusPayload.lastUpdate = Date.now();
2392
+ writeStatusPayload();
2393
+ for (const pr of parallelResults) {
2394
+ results.push({
2395
+ agent: pr.agent,
2396
+ output: pr.output,
2397
+ error: pr.error,
2398
+ success: pr.interrupted !== true && pr.exitCode === 0,
2399
+ exitCode: pr.interrupted === true ? 0 : pr.exitCode,
2400
+ skipped: pr.skipped,
2401
+ interrupted: pr.interrupted,
2402
+ timedOut: pr.timedOut,
2403
+ turnBudget: pr.turnBudget,
2404
+ turnBudgetExceeded: pr.turnBudgetExceeded,
2405
+ wrapUpRequested: pr.wrapUpRequested,
2406
+ toolBudget: pr.toolBudget,
2407
+ toolBudgetBlocked: pr.toolBudgetBlocked,
2408
+ sessionFile: pr.sessionFile,
2409
+ intercomTarget: pr.intercomTarget,
2410
+ model: pr.model,
2411
+ attemptedModels: pr.attemptedModels,
2412
+ modelAttempts: pr.modelAttempts,
2413
+ totalCost: pr.totalCost,
2414
+ artifactPaths: pr.artifactPaths,
2415
+ transcriptPath: pr.transcriptPath,
2416
+ transcriptError: pr.transcriptError,
2417
+ structuredOutput: pr.structuredOutput,
2418
+ structuredOutputPath: pr.structuredOutputPath,
2419
+ structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
2420
+ acceptance: pr.acceptance
2421
+ });
2422
+ }
2423
+ for (let t = 0;t < group.parallel.length; t++) {
2424
+ const outputName = group.parallel[t]?.outputName;
2425
+ if (outputName)
2426
+ outputs[outputName] = outputEntryFromAsyncResult({
2427
+ agent: parallelResults[t].agent,
2428
+ output: parallelResults[t].output,
2429
+ structuredOutput: parallelResults[t].structuredOutput
2430
+ }, stepIndex);
2431
+ }
2432
+ statusPayload.outputs = outputs;
2433
+ previousOutput = aggregateParallelOutputs(parallelResults.map((r) => ({
2434
+ agent: r.agent,
2435
+ output: r.output,
2436
+ exitCode: r.exitCode,
2437
+ error: r.error,
2438
+ model: r.model,
2439
+ attemptedModels: r.attemptedModels
2440
+ })));
2441
+ previousOutput = appendParallelWorktreeSummary(previousOutput, worktreeSetup, asyncDir, stepIndex, group);
2442
+ appendJsonl(eventsPath, JSON.stringify({
2443
+ type: "subagent.parallel.completed",
2444
+ ts: Date.now(),
2445
+ runId: id,
2446
+ stepIndex,
2447
+ success: parallelResults.every((r) => r.exitCode === 0 || r.exitCode === -1)
2448
+ }));
2449
+ if (parallelResults.some((r) => r.exitCode !== 0 && r.exitCode !== -1)) {
2450
+ break;
2451
+ }
2452
+ } finally {
2453
+ if (worktreeSetup)
2454
+ cleanupWorktrees(worktreeSetup);
2455
+ }
2456
+ } else {
2457
+ const seqStep = step;
2458
+ const stepStartTime = Date.now();
2459
+ statusPayload.currentStep = flatIndex;
2460
+ statusPayload.steps[flatIndex].status = "running";
2461
+ statusPayload.steps[flatIndex].activityState = undefined;
2462
+ statusPayload.activityState = undefined;
2463
+ resetStepLiveDetail(statusPayload.steps[flatIndex]);
2464
+ statusPayload.steps[flatIndex].skills = seqStep.skills;
2465
+ statusPayload.steps[flatIndex].startedAt = stepStartTime;
2466
+ statusPayload.steps[flatIndex].lastActivityAt = stepStartTime;
2467
+ statusPayload.lastActivityAt = stepStartTime;
2468
+ statusPayload.lastUpdate = stepStartTime;
2469
+ statusPayload.outputFile = path.join(asyncDir, `output-${flatIndex}.log`);
2470
+ writeStatusPayload();
2471
+ appendJsonl(eventsPath, JSON.stringify({
2472
+ type: "subagent.step.started",
2473
+ ts: stepStartTime,
2474
+ runId: id,
2475
+ stepIndex: flatIndex,
2476
+ agent: seqStep.agent
2477
+ }));
2478
+ flushPendingStepSteers(flatIndex);
2479
+ const singleResult = await runSingleStep(seqStep, {
2480
+ previousOutput,
2481
+ placeholder,
2482
+ cwd,
2483
+ sessionEnabled,
2484
+ outputs,
2485
+ sessionDir: config.sessionDir,
2486
+ artifactsDir,
2487
+ artifactConfig,
2488
+ id,
2489
+ flatIndex,
2490
+ flatStepCount: Math.max(statusPayload.steps.length, 1),
2491
+ outputFile: path.join(asyncDir, `output-${flatIndex}.log`),
2492
+ steerInboxDir: stepSteerInboxDir(asyncDir, flatIndex),
2493
+ piPackageRoot: config.piPackageRoot,
2494
+ piArgv1: config.piArgv1,
2495
+ childIntercomTarget: config.childIntercomTargets?.[flatIndex],
2496
+ orchestratorIntercomTarget: config.controlIntercomTarget,
2497
+ nestedRoute: config.nestedRoute,
2498
+ registerInterrupt: (interrupt) => registerStepInterrupt(flatIndex, interrupt),
2499
+ registerTimeout: (interrupt) => registerStepTimeout(flatIndex, interrupt),
2500
+ registerTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(flatIndex, abort),
2501
+ timeoutSignal: timeoutAbortController.signal,
2502
+ timeoutMessage,
2503
+ turnBudget: config.turnBudget,
2504
+ onAttemptStart: (attempt) => updateStepModel(flatIndex, attempt.model, attempt.thinking),
2505
+ onChildEvent: (event) => updateStepFromChildEvent(flatIndex, event),
2506
+ skipAcceptance: () => timedOut
2507
+ });
2508
+ if (seqStep.sessionFile) {
2509
+ latestSessionFile = seqStep.sessionFile;
2510
+ }
2511
+ previousOutput = singleResult.output;
2512
+ results.push({
2513
+ agent: singleResult.agent,
2514
+ output: timedOut ? timeoutMessage ?? "Subagent timed out." : singleResult.output,
2515
+ error: timedOut ? timeoutMessage ?? "Subagent timed out." : singleResult.error,
2516
+ success: !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0,
2517
+ exitCode: timedOut ? 1 : singleResult.interrupted === true ? 0 : singleResult.exitCode,
2518
+ sessionFile: singleResult.sessionFile,
2519
+ intercomTarget: singleResult.intercomTarget,
2520
+ model: singleResult.model,
2521
+ attemptedModels: singleResult.attemptedModels,
2522
+ modelAttempts: singleResult.modelAttempts,
2523
+ totalCost: singleResult.totalCost,
2524
+ artifactPaths: singleResult.artifactPaths,
2525
+ transcriptPath: singleResult.transcriptPath,
2526
+ transcriptError: singleResult.transcriptError,
2527
+ structuredOutput: singleResult.structuredOutput,
2528
+ structuredOutputPath: singleResult.structuredOutputPath,
2529
+ structuredOutputSchemaPath: singleResult.structuredOutputSchemaPath,
2530
+ acceptance: singleResult.acceptance,
2531
+ interrupted: singleResult.interrupted,
2532
+ timedOut: timedOut || singleResult.timedOut ? true : undefined,
2533
+ turnBudget: singleResult.turnBudget,
2534
+ turnBudgetExceeded: singleResult.turnBudgetExceeded,
2535
+ wrapUpRequested: singleResult.wrapUpRequested,
2536
+ toolBudget: singleResult.toolBudget,
2537
+ toolBudgetBlocked: singleResult.toolBudgetBlocked
2538
+ });
2539
+ if (seqStep.outputName) {
2540
+ outputs[seqStep.outputName] = outputEntryFromAsyncResult({
2541
+ agent: singleResult.agent,
2542
+ output: singleResult.output,
2543
+ structuredOutput: singleResult.structuredOutput
2544
+ }, stepIndex);
2545
+ }
2546
+ statusPayload.outputs = outputs;
2547
+ const cumulativeTokens = config.sessionDir ? parseSessionTokens(config.sessionDir) : null;
2548
+ let stepTokens = cumulativeTokens ? {
2549
+ input: cumulativeTokens.input - previousCumulativeTokens.input,
2550
+ output: cumulativeTokens.output - previousCumulativeTokens.output,
2551
+ total: cumulativeTokens.total - previousCumulativeTokens.total
2552
+ } : null;
2553
+ if (cumulativeTokens) {
2554
+ previousCumulativeTokens = cumulativeTokens;
2555
+ } else {
2556
+ stepTokens = tokenUsageFromAttempts(singleResult.modelAttempts);
2557
+ if (stepTokens) {
2558
+ previousCumulativeTokens = {
2559
+ input: previousCumulativeTokens.input + stepTokens.input,
2560
+ output: previousCumulativeTokens.output + stepTokens.output,
2561
+ total: previousCumulativeTokens.total + stepTokens.total
2562
+ };
2563
+ }
2564
+ }
2565
+ const stepEndTime = Date.now();
2566
+ const childInterrupted = singleResult.interrupted === true;
2567
+ statusPayload.steps[flatIndex].status = timedOut ? "failed" : childInterrupted ? "paused" : singleResult.exitCode === 0 ? "complete" : "failed";
2568
+ statusPayload.steps[flatIndex].endedAt = stepEndTime;
2569
+ statusPayload.steps[flatIndex].durationMs = stepEndTime - stepStartTime;
2570
+ statusPayload.steps[flatIndex].exitCode = timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
2571
+ statusPayload.steps[flatIndex].timedOut = timedOut || singleResult.timedOut ? true : undefined;
2572
+ statusPayload.steps[flatIndex].turnBudget = singleResult.turnBudget;
2573
+ statusPayload.steps[flatIndex].turnBudgetExceeded = singleResult.turnBudgetExceeded;
2574
+ statusPayload.steps[flatIndex].wrapUpRequested = singleResult.wrapUpRequested;
2575
+ statusPayload.steps[flatIndex].toolBudget = singleResult.toolBudget;
2576
+ statusPayload.steps[flatIndex].toolBudgetBlocked = singleResult.toolBudgetBlocked;
2577
+ if (singleResult.toolBudget)
2578
+ statusPayload.toolBudget = singleResult.toolBudget;
2579
+ if (singleResult.toolBudgetBlocked)
2580
+ statusPayload.toolBudgetBlocked = true;
2581
+ if (singleResult.turnBudget)
2582
+ statusPayload.turnBudget = singleResult.turnBudget;
2583
+ if (singleResult.turnBudgetExceeded)
2584
+ statusPayload.turnBudgetExceeded = true;
2585
+ if (singleResult.wrapUpRequested)
2586
+ statusPayload.wrapUpRequested = true;
2587
+ statusPayload.steps[flatIndex].model = singleResult.model;
2588
+ statusPayload.steps[flatIndex].thinking = resolveEffectiveThinking(singleResult.model, statusPayload.steps[flatIndex].thinking);
2589
+ statusPayload.steps[flatIndex].attemptedModels = singleResult.attemptedModels;
2590
+ statusPayload.steps[flatIndex].modelAttempts = singleResult.modelAttempts;
2591
+ statusPayload.steps[flatIndex].totalCost = singleResult.totalCost;
2592
+ statusPayload.steps[flatIndex].error = timedOut ? timeoutMessage ?? "Subagent timed out." : singleResult.error;
2593
+ statusPayload.steps[flatIndex].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[flatIndex].transcriptPath;
2594
+ statusPayload.steps[flatIndex].transcriptError = singleResult.transcriptError;
2595
+ statusPayload.steps[flatIndex].structuredOutput = singleResult.structuredOutput;
2596
+ statusPayload.steps[flatIndex].structuredOutputPath = singleResult.structuredOutputPath;
2597
+ statusPayload.steps[flatIndex].structuredOutputSchemaPath = singleResult.structuredOutputSchemaPath;
2598
+ statusPayload.steps[flatIndex].acceptance = singleResult.acceptance;
2599
+ if (stepTokens) {
2600
+ statusPayload.steps[flatIndex].tokens = stepTokens;
2601
+ statusPayload.totalTokens = { ...previousCumulativeTokens };
2602
+ }
2603
+ statusPayload.lastUpdate = stepEndTime;
2604
+ writeStatusPayload();
2605
+ appendJsonl(eventsPath, JSON.stringify({
2606
+ type: timedOut ? "subagent.step.failed" : childInterrupted ? "subagent.step.paused" : singleResult.exitCode === 0 ? "subagent.step.completed" : "subagent.step.failed",
2607
+ ts: stepEndTime,
2608
+ runId: id,
2609
+ stepIndex: flatIndex,
2610
+ agent: seqStep.agent,
2611
+ exitCode: timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode,
2612
+ durationMs: stepEndTime - stepStartTime,
2613
+ tokens: stepTokens
2614
+ }));
2615
+ if (singleResult.completionGuardTriggered) {
2616
+ const event = buildControlEvent({
2617
+ from: statusPayload.steps[flatIndex].activityState,
2618
+ to: "needs_attention",
2619
+ runId: id,
2620
+ agent: seqStep.agent,
2621
+ index: flatIndex,
2622
+ ts: stepEndTime,
2623
+ message: `${seqStep.agent} completed without making edits for an implementation task`,
2624
+ reason: "completion_guard"
2625
+ });
2626
+ appendControlEvent(event);
2627
+ }
2628
+ flatIndex++;
2629
+ if (singleResult.exitCode !== 0) {
2630
+ break;
2631
+ }
2632
+ }
2633
+ }
2634
+ let summary = results.map((r) => {
2635
+ const output = r.output.trim();
2636
+ const detail = output ? r.error ? `${output}
76
2637
 
77
- Error: ${H.error}`:V:H.error??"(no output)";return`${H.agent}:
78
- ${K}`}).join(`
2638
+ Error: ${r.error}` : output : r.error ?? "(no output)";
2639
+ return `${r.agent}:
2640
+ ${detail}`;
2641
+ }).join(`
79
2642
 
80
- `),S1=!1;if(G){let H={...nj,...G},V=h[h.length-1]?.artifactPaths?.outputPath,K=sj(n0,H,V);if(K.truncated)n0=K.text,S1=!0}let oj=$.resultMode??Y.mode,i0=h.reduce((H,V)=>({inputTokens:H.inputTokens+(V.totalCost?.inputTokens??0),outputTokens:H.outputTokens+(V.totalCost?.outputTokens??0),costUsd:H.costUsd+(V.totalCost?.costUsd??0)}),{inputTokens:0,outputTokens:0,costUsd:0}),D1=i0.inputTokens>0||i0.outputTokens>0||i0.costUsd>0?i0:void 0,r0=Y.steps.map((H)=>H.agent),$2=r0.length===1?r0[0]:oj==="parallel"?`parallel:${r0.join("+")}`:`chain:${r0.join("->")}`,H0,s0,b1,M0;if(v$){if(H0=$.sessionDir?m5($.sessionDir)??void 0:void 0,!H0&&o$)H0=o$;if(H0)try{let H=$.sessionDir??r.dirname(H0),V=await l5(H0,H,$.piPackageRoot),K=p5(V);if("error"in K)M0=K.error;else s0=K.shareUrl,b1=K.gistUrl}catch(H){M0=String(H)}else M0="Session file not found."}if(X$)clearInterval(X$),X$=void 0;if(_$)clearTimeout(_$),_$=void 0;e8();let R1=H0??o$,V0=Date.now();if(Y.state=E||t?"failed":s?"paused":h.every((H)=>H.success)?"complete":"failed",Y.activityState=void 0,E)Y.timedOut=!0,Y.error=p??"Subagent timed out.";if(t&&!Y.error){let H=Y.turnBudget;Y.error=H?u0(H,H.turnCount):"Subagent exceeded turn budget."}if(Y.endedAt=V0,Y.lastUpdate=V0,Y.sessionFile=R1,Y.totalCost=D1,Y.shareUrl=s0,Y.gistUrl=b1,Y.shareError=M0,Y.state==="failed"&&!Y.error){let H=Y.steps.find((V)=>V.status==="failed");if(H?.agent)Y.error=H.error?`Step failed: ${H.agent}: ${H.error}`:`Step failed: ${H.agent}`}a(),$$(n,JSON.stringify({type:"subagent.run.completed",lifecycleArtifactVersion:S0,ts:V0,runId:j,status:Y.state,durationMs:V0-S,totalTokens:Y.totalTokens,totalCost:D1})),n5(d$,{id:j,mode:Y.mode,cwd:Q,startedAt:S,endedAt:V0,steps:Y.steps.map((H)=>({agent:H.agent,status:H.status,durationMs:H.durationMs})),summary:n0,truncated:S1,artifactsDir:B,sessionFile:R1,shareUrl:s0,shareError:M0});try{D$(Z,{lifecycleArtifactVersion:S0,id:j,agent:$2,mode:oj,success:!E&&!t&&!s&&h.every((H)=>H.success),state:E||t?"failed":s?"paused":h.every((H)=>H.success)?"complete":"failed",summary:E?p??"Subagent timed out.":t?Y.error??"Subagent exceeded turn budget.":s?"Paused after interrupt. Waiting for explicit next action.":n0,...$.timeoutMs!==void 0?{timeoutMs:$.timeoutMs}:{},...$.deadlineAt!==void 0?{deadlineAt:$.deadlineAt}:{},...Y.turnBudget?{turnBudget:Y.turnBudget}:{},...Y.turnBudgetExceeded?{turnBudgetExceeded:!0}:{},...Y.wrapUpRequested?{wrapUpRequested:!0}:{},...Y.toolBudget?{toolBudget:Y.toolBudget}:{},...Y.toolBudgetBlocked?{toolBudgetBlocked:!0}:{},...E?{timedOut:!0,error:p??"Subagent timed out."}:t?{error:Y.error??"Subagent exceeded turn budget."}:{},results:h.map((H)=>({agent:H.agent,output:H.output,error:H.error,success:H.success,skipped:H.skipped||void 0,interrupted:H.interrupted||void 0,timedOut:H.timedOut||void 0,turnBudget:H.turnBudget,turnBudgetExceeded:H.turnBudgetExceeded||void 0,wrapUpRequested:H.wrapUpRequested||void 0,toolBudget:H.toolBudget,toolBudgetBlocked:H.toolBudgetBlocked||void 0,sessionFile:H.sessionFile,intercomTarget:H.intercomTarget,model:H.model,attemptedModels:H.attemptedModels,modelAttempts:H.modelAttempts,totalCost:H.totalCost,artifactPaths:H.artifactPaths,truncated:H.truncated,transcriptPath:H.transcriptPath,transcriptError:H.transcriptError,structuredOutput:H.structuredOutput,structuredOutputPath:H.structuredOutputPath,structuredOutputSchemaPath:H.structuredOutputSchemaPath,acceptance:H.acceptance})),outputs:y,workflowGraph:Y.workflowGraph,exitCode:E||t?1:s||h.every((H)=>H.success)?0:1,timestamp:V0,durationMs:V0-S,totalTokens:Y.totalTokens,totalCost:D1,truncated:S1,artifactsDir:B,cwd:Q,asyncDir:k,sessionId:$.sessionId,sessionFile:R1,intercomTarget:$.controlIntercomTarget,shareUrl:s0,gistUrl:b1,shareError:M0,...W!==void 0&&{taskIndex:W},...U!==void 0&&{totalTasks:U}})}catch(H){console.error(`Failed to write result file ${Z}:`,H)}}var Pj=process.argv[2];if(Pj)try{let $=e.readFileSync(Pj,"utf-8"),j=JSON.parse($);try{e.unlinkSync(Pj)}catch{}r8(j).catch((J)=>{console.error("Subagent runner error:",J),process.exit(1)})}catch($){console.error("Subagent runner error:",$),process.exit(1)}else{let $="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",(j)=>{$+=j}),process.stdin.on("end",()=>{try{let j=JSON.parse($);r8(j).catch((J)=>{console.error("Subagent runner error:",J),process.exit(1)})}catch(j){console.error("Subagent runner error:",j),process.exit(1)}})}
2643
+ `);
2644
+ let truncated = false;
2645
+ if (maxOutput) {
2646
+ const config = { ...DEFAULT_MAX_OUTPUT, ...maxOutput };
2647
+ const lastArtifactPath = results[results.length - 1]?.artifactPaths?.outputPath;
2648
+ const truncResult = truncateOutput(summary, config, lastArtifactPath);
2649
+ if (truncResult.truncated) {
2650
+ summary = truncResult.text;
2651
+ truncated = true;
2652
+ }
2653
+ }
2654
+ const resultMode = config.resultMode ?? statusPayload.mode;
2655
+ const totalCost = results.reduce((sum, result) => ({
2656
+ inputTokens: sum.inputTokens + (result.totalCost?.inputTokens ?? 0),
2657
+ outputTokens: sum.outputTokens + (result.totalCost?.outputTokens ?? 0),
2658
+ costUsd: sum.costUsd + (result.totalCost?.costUsd ?? 0)
2659
+ }), { inputTokens: 0, outputTokens: 0, costUsd: 0 });
2660
+ const finalTotalCost = totalCost.inputTokens > 0 || totalCost.outputTokens > 0 || totalCost.costUsd > 0 ? totalCost : undefined;
2661
+ const finalFlatAgents = statusPayload.steps.map((step) => step.agent);
2662
+ const agentName = finalFlatAgents.length === 1 ? finalFlatAgents[0] : resultMode === "parallel" ? `parallel:${finalFlatAgents.join("+")}` : `chain:${finalFlatAgents.join("->")}`;
2663
+ let sessionFile;
2664
+ let shareUrl;
2665
+ let gistUrl;
2666
+ let shareError;
2667
+ if (shareEnabled) {
2668
+ sessionFile = config.sessionDir ? findLatestSessionFile(config.sessionDir) ?? undefined : undefined;
2669
+ if (!sessionFile && latestSessionFile) {
2670
+ sessionFile = latestSessionFile;
2671
+ }
2672
+ if (sessionFile) {
2673
+ try {
2674
+ const exportDir = config.sessionDir ?? path.dirname(sessionFile);
2675
+ const htmlPath = await exportSessionHtml(sessionFile, exportDir, config.piPackageRoot);
2676
+ const share = createShareLink(htmlPath);
2677
+ if ("error" in share)
2678
+ shareError = share.error;
2679
+ else {
2680
+ shareUrl = share.shareUrl;
2681
+ gistUrl = share.gistUrl;
2682
+ }
2683
+ } catch (err) {
2684
+ shareError = String(err);
2685
+ }
2686
+ } else {
2687
+ shareError = "Session file not found.";
2688
+ }
2689
+ }
2690
+ if (activityTimer) {
2691
+ clearInterval(activityTimer);
2692
+ activityTimer = undefined;
2693
+ }
2694
+ if (timeoutTimer) {
2695
+ clearTimeout(timeoutTimer);
2696
+ timeoutTimer = undefined;
2697
+ }
2698
+ disposeControlInbox();
2699
+ const effectiveSessionFile = sessionFile ?? latestSessionFile;
2700
+ const runEndedAt = Date.now();
2701
+ statusPayload.state = timedOut || turnBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed";
2702
+ statusPayload.activityState = undefined;
2703
+ if (timedOut) {
2704
+ statusPayload.timedOut = true;
2705
+ statusPayload.error = timeoutMessage ?? "Subagent timed out.";
2706
+ }
2707
+ if (turnBudgetExceeded && !statusPayload.error) {
2708
+ const budget = statusPayload.turnBudget;
2709
+ statusPayload.error = budget ? turnBudgetExceededMessage(budget, budget.turnCount) : "Subagent exceeded turn budget.";
2710
+ }
2711
+ statusPayload.endedAt = runEndedAt;
2712
+ statusPayload.lastUpdate = runEndedAt;
2713
+ statusPayload.sessionFile = effectiveSessionFile;
2714
+ statusPayload.totalCost = finalTotalCost;
2715
+ statusPayload.shareUrl = shareUrl;
2716
+ statusPayload.gistUrl = gistUrl;
2717
+ statusPayload.shareError = shareError;
2718
+ if (statusPayload.state === "failed" && !statusPayload.error) {
2719
+ const failedStep = statusPayload.steps.find((s) => s.status === "failed");
2720
+ if (failedStep?.agent) {
2721
+ statusPayload.error = failedStep.error ? `Step failed: ${failedStep.agent}: ${failedStep.error}` : `Step failed: ${failedStep.agent}`;
2722
+ }
2723
+ }
2724
+ writeStatusPayload();
2725
+ appendJsonl(eventsPath, JSON.stringify({
2726
+ type: "subagent.run.completed",
2727
+ lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
2728
+ ts: runEndedAt,
2729
+ runId: id,
2730
+ status: statusPayload.state,
2731
+ durationMs: runEndedAt - overallStartTime,
2732
+ totalTokens: statusPayload.totalTokens,
2733
+ totalCost: finalTotalCost
2734
+ }));
2735
+ writeRunLog(logPath, {
2736
+ id,
2737
+ mode: statusPayload.mode,
2738
+ cwd,
2739
+ startedAt: overallStartTime,
2740
+ endedAt: runEndedAt,
2741
+ steps: statusPayload.steps.map((step) => ({
2742
+ agent: step.agent,
2743
+ status: step.status,
2744
+ durationMs: step.durationMs
2745
+ })),
2746
+ summary,
2747
+ truncated,
2748
+ artifactsDir,
2749
+ sessionFile: effectiveSessionFile,
2750
+ shareUrl,
2751
+ shareError
2752
+ });
2753
+ try {
2754
+ writeAtomicJson(resultPath, {
2755
+ lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
2756
+ id,
2757
+ agent: agentName,
2758
+ mode: resultMode,
2759
+ success: !timedOut && !turnBudgetExceeded && !interrupted && results.every((r) => r.success),
2760
+ state: timedOut || turnBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed",
2761
+ summary: timedOut ? timeoutMessage ?? "Subagent timed out." : turnBudgetExceeded ? statusPayload.error ?? "Subagent exceeded turn budget." : interrupted ? "Paused after interrupt. Waiting for explicit next action." : summary,
2762
+ ...config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {},
2763
+ ...config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {},
2764
+ ...statusPayload.turnBudget ? { turnBudget: statusPayload.turnBudget } : {},
2765
+ ...statusPayload.turnBudgetExceeded ? { turnBudgetExceeded: true } : {},
2766
+ ...statusPayload.wrapUpRequested ? { wrapUpRequested: true } : {},
2767
+ ...statusPayload.toolBudget ? { toolBudget: statusPayload.toolBudget } : {},
2768
+ ...statusPayload.toolBudgetBlocked ? { toolBudgetBlocked: true } : {},
2769
+ ...timedOut ? { timedOut: true, error: timeoutMessage ?? "Subagent timed out." } : turnBudgetExceeded ? { error: statusPayload.error ?? "Subagent exceeded turn budget." } : {},
2770
+ results: results.map((r) => ({
2771
+ agent: r.agent,
2772
+ output: r.output,
2773
+ error: r.error,
2774
+ success: r.success,
2775
+ skipped: r.skipped || undefined,
2776
+ interrupted: r.interrupted || undefined,
2777
+ timedOut: r.timedOut || undefined,
2778
+ turnBudget: r.turnBudget,
2779
+ turnBudgetExceeded: r.turnBudgetExceeded || undefined,
2780
+ wrapUpRequested: r.wrapUpRequested || undefined,
2781
+ toolBudget: r.toolBudget,
2782
+ toolBudgetBlocked: r.toolBudgetBlocked || undefined,
2783
+ sessionFile: r.sessionFile,
2784
+ intercomTarget: r.intercomTarget,
2785
+ model: r.model,
2786
+ attemptedModels: r.attemptedModels,
2787
+ modelAttempts: r.modelAttempts,
2788
+ totalCost: r.totalCost,
2789
+ artifactPaths: r.artifactPaths,
2790
+ truncated: r.truncated,
2791
+ transcriptPath: r.transcriptPath,
2792
+ transcriptError: r.transcriptError,
2793
+ structuredOutput: r.structuredOutput,
2794
+ structuredOutputPath: r.structuredOutputPath,
2795
+ structuredOutputSchemaPath: r.structuredOutputSchemaPath,
2796
+ acceptance: r.acceptance
2797
+ })),
2798
+ outputs,
2799
+ workflowGraph: statusPayload.workflowGraph,
2800
+ exitCode: timedOut || turnBudgetExceeded ? 1 : interrupted || results.every((r) => r.success) ? 0 : 1,
2801
+ timestamp: runEndedAt,
2802
+ durationMs: runEndedAt - overallStartTime,
2803
+ totalTokens: statusPayload.totalTokens,
2804
+ totalCost: finalTotalCost,
2805
+ truncated,
2806
+ artifactsDir,
2807
+ cwd,
2808
+ asyncDir,
2809
+ sessionId: config.sessionId,
2810
+ sessionFile: effectiveSessionFile,
2811
+ intercomTarget: config.controlIntercomTarget,
2812
+ shareUrl,
2813
+ gistUrl,
2814
+ shareError,
2815
+ ...taskIndex !== undefined && { taskIndex },
2816
+ ...totalTasks !== undefined && { totalTasks }
2817
+ });
2818
+ } catch (err) {
2819
+ console.error(`Failed to write result file ${resultPath}:`, err);
2820
+ }
2821
+ }
2822
+ const configArg = process.argv[2];
2823
+ if (configArg) {
2824
+ try {
2825
+ const configJson = fs.readFileSync(configArg, "utf-8");
2826
+ const config = JSON.parse(configJson);
2827
+ try {
2828
+ fs.unlinkSync(configArg);
2829
+ } catch {}
2830
+ runSubagent(config).catch((runErr) => {
2831
+ console.error("Subagent runner error:", runErr);
2832
+ process.exit(1);
2833
+ });
2834
+ } catch (err) {
2835
+ console.error("Subagent runner error:", err);
2836
+ process.exit(1);
2837
+ }
2838
+ } else {
2839
+ let input = "";
2840
+ process.stdin.setEncoding("utf-8");
2841
+ process.stdin.on("data", (chunk) => {
2842
+ input += chunk;
2843
+ });
2844
+ process.stdin.on("end", () => {
2845
+ try {
2846
+ const config = JSON.parse(input);
2847
+ runSubagent(config).catch((runErr) => {
2848
+ console.error("Subagent runner error:", runErr);
2849
+ process.exit(1);
2850
+ });
2851
+ } catch (err) {
2852
+ console.error("Subagent runner error:", err);
2853
+ process.exit(1);
2854
+ }
2855
+ });
2856
+ }