@duckmind/dm-windows-x64 0.61.4 → 0.61.9

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 (279) hide show
  1. package/dm.exe +0 -0
  2. package/extensions/.dm-extensions.json +211 -67
  3. package/extensions/dm-subagents/agents/claude-code-writer.md +15 -0
  4. package/extensions/dm-subagents/agents/claude-code.md +15 -0
  5. package/extensions/dm-subagents/agents/codex-exec-writer.md +15 -0
  6. package/extensions/dm-subagents/agents/codex-exec.md +15 -0
  7. package/extensions/dm-subagents/agents/cursor-agent-writer.md +14 -0
  8. package/extensions/dm-subagents/agents/cursor-agent.md +14 -0
  9. package/extensions/dm-subagents/agents/delegate.md +3 -2
  10. package/extensions/dm-subagents/agents/oracle.md +10 -5
  11. package/extensions/dm-subagents/agents/researcher.md +2 -2
  12. package/extensions/dm-subagents/agents/reviewer.md +17 -7
  13. package/extensions/dm-subagents/agents/scout.md +5 -5
  14. package/extensions/dm-subagents/agents/worker.md +6 -2
  15. package/extensions/dm-subagents/async-retention-discovery-worker.mjs +167 -0
  16. package/extensions/dm-subagents/index.js +4 -0
  17. package/extensions/dm-subagents/inspector-runner.mjs +10 -0
  18. package/extensions/dm-subagents/install.mjs +3 -2
  19. package/extensions/dm-subagents/package.json +2 -2
  20. package/extensions/dm-subagents/prompts/council.md +60 -0
  21. package/extensions/dm-subagents/prompts/parallel-review.md +5 -1
  22. package/extensions/dm-subagents/prompts/review-loop.md +13 -7
  23. package/extensions/dm-subagents/skills/council-mode/SKILL.md +59 -0
  24. package/extensions/dm-subagents/skills/council-mode/references/pass-contracts.md +150 -0
  25. package/extensions/dm-subagents/skills/dm-subagents/SKILL.md +96 -911
  26. package/extensions/dm-subagents/skills/dm-subagents/references/constraints-and-recipes.md +70 -0
  27. package/extensions/dm-subagents/skills/dm-subagents/references/execution-controls.md +539 -0
  28. package/extensions/dm-subagents/skills/dm-subagents/references/management-authoring-rpc.md +161 -0
  29. package/extensions/dm-subagents/skills/dm-subagents/references/multi-lane-orchestration.md +51 -0
  30. package/extensions/dm-subagents/skills/dm-subagents/references/prompting-and-roles.md +295 -0
  31. package/extensions/dm-subagents/skills/dm-subagents/references/review-and-validation.md +73 -0
  32. package/extensions/dm-subagents/src/agents/agent-management.js +716 -484
  33. package/extensions/dm-subagents/src/agents/agent-refinements.js +563 -0
  34. package/extensions/dm-subagents/src/agents/agent-serializer.js +70 -5
  35. package/extensions/dm-subagents/src/agents/agents.js +1447 -299
  36. package/extensions/dm-subagents/src/agents/builtin-names.js +15 -0
  37. package/extensions/dm-subagents/src/agents/chain-serializer.js +12 -7
  38. package/extensions/dm-subagents/src/agents/frontmatter.js +64 -14
  39. package/extensions/dm-subagents/src/agents/identity.js +1 -1
  40. package/extensions/dm-subagents/src/agents/proactive-skills.js +14 -11
  41. package/extensions/dm-subagents/src/agents/runtime-agent-events.js +49 -0
  42. package/extensions/dm-subagents/src/agents/runtime-agent-registry.js +412 -0
  43. package/extensions/dm-subagents/src/agents/skills.js +52 -35
  44. package/extensions/dm-subagents/src/api/agents.js +6 -0
  45. package/extensions/dm-subagents/src/api/background-work.js +151 -0
  46. package/extensions/dm-subagents/src/api/capability-ceiling.js +12 -0
  47. package/extensions/dm-subagents/src/api/control-channel.js +3 -0
  48. package/extensions/dm-subagents/src/api/delegation.js +5 -0
  49. package/extensions/dm-subagents/src/api/dm-args.js +3 -0
  50. package/extensions/dm-subagents/src/api/external-job-provider.js +137 -0
  51. package/extensions/dm-subagents/src/api/external-runs.js +233 -0
  52. package/extensions/dm-subagents/src/api/intercom-bridge.js +3 -0
  53. package/extensions/dm-subagents/src/api/preflight.js +322 -0
  54. package/extensions/dm-subagents/src/api/project-panes.js +11 -0
  55. package/extensions/dm-subagents/src/api/shared-types.js +4 -0
  56. package/extensions/dm-subagents/src/extension/config.js +175 -0
  57. package/extensions/dm-subagents/src/extension/control-notices.js +4 -43
  58. package/extensions/dm-subagents/src/extension/doctor.js +71 -17
  59. package/extensions/dm-subagents/src/extension/fanout-child.js +49 -32
  60. package/extensions/dm-subagents/src/extension/index.js +711 -265
  61. package/extensions/dm-subagents/src/extension/public-execution.js +114 -0
  62. package/extensions/dm-subagents/src/extension/rpc.js +427 -22
  63. package/extensions/dm-subagents/src/extension/schemas.js +158 -65
  64. package/extensions/dm-subagents/src/extension/steering-notices.js +23 -0
  65. package/extensions/dm-subagents/src/extension/subagent-guide.js +31 -0
  66. package/extensions/dm-subagents/src/extension/tool-description.js +92 -74
  67. package/extensions/dm-subagents/src/extension/tool-result.js +7 -0
  68. package/extensions/dm-subagents/src/inspectors/herdr/actions.js +218 -0
  69. package/extensions/dm-subagents/src/inspectors/herdr/client.js +123 -0
  70. package/extensions/dm-subagents/src/inspectors/herdr/focus.js +47 -0
  71. package/extensions/dm-subagents/src/inspectors/herdr/inspector-runner.js +160 -0
  72. package/extensions/dm-subagents/src/inspectors/herdr/project-panes.js +618 -0
  73. package/extensions/dm-subagents/src/inspectors/herdr/session-roots-codec.js +21 -0
  74. package/extensions/dm-subagents/src/inspectors/herdr/shell-command.js +15 -0
  75. package/extensions/dm-subagents/src/integrations/herdr-status.js +377 -0
  76. package/extensions/dm-subagents/src/intercom/intercom-bridge.js +17 -13
  77. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +371 -79
  78. package/extensions/dm-subagents/src/intercom/result-intercom.js +47 -7
  79. package/extensions/dm-subagents/src/missions/actions.js +394 -0
  80. package/extensions/dm-subagents/src/missions/goal-driver.js +149 -0
  81. package/extensions/dm-subagents/src/missions/lifecycle.js +331 -0
  82. package/extensions/dm-subagents/src/missions/store.js +548 -0
  83. package/extensions/dm-subagents/src/missions/types.js +9 -0
  84. package/extensions/dm-subagents/src/missions/workflow-state.js +245 -0
  85. package/extensions/dm-subagents/src/policy/authority.js +37 -0
  86. package/extensions/dm-subagents/src/profiles/profiles.js +36 -18
  87. package/extensions/dm-subagents/src/runs/background/active-async-capacity.js +427 -0
  88. package/extensions/dm-subagents/src/runs/background/active-run-index.js +122 -0
  89. package/extensions/dm-subagents/src/runs/background/async-execution.js +925 -137
  90. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +515 -148
  91. package/extensions/dm-subagents/src/runs/background/async-resume.js +378 -51
  92. package/extensions/dm-subagents/src/runs/background/async-retention.js +828 -0
  93. package/extensions/dm-subagents/src/runs/background/async-status-snapshot.js +31 -0
  94. package/extensions/dm-subagents/src/runs/background/async-status.js +259 -22
  95. package/extensions/dm-subagents/src/runs/background/auto-drain.js +46 -0
  96. package/extensions/dm-subagents/src/runs/background/chain-append.js +50 -15
  97. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +67 -12
  98. package/extensions/dm-subagents/src/runs/background/completion-batcher.js +5 -1
  99. package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +3 -11
  100. package/extensions/dm-subagents/src/runs/background/completion-replay.js +245 -0
  101. package/extensions/dm-subagents/src/runs/background/control-channel.js +423 -36
  102. package/extensions/dm-subagents/src/runs/background/fleet-view.js +132 -59
  103. package/extensions/dm-subagents/src/runs/background/index-segment.js +38 -0
  104. package/extensions/dm-subagents/src/runs/background/inspect-rpc.js +373 -0
  105. package/extensions/dm-subagents/src/runs/background/notify.js +357 -57
  106. package/extensions/dm-subagents/src/runs/background/owned-process-tree.js +86 -0
  107. package/extensions/dm-subagents/src/runs/background/process-terminal.js +269 -0
  108. package/extensions/dm-subagents/src/runs/background/result-delivery-ownership.js +34 -0
  109. package/extensions/dm-subagents/src/runs/background/result-files.js +469 -0
  110. package/extensions/dm-subagents/src/runs/background/result-watcher.js +540 -75
  111. package/extensions/dm-subagents/src/runs/background/resume-guidance.js +44 -0
  112. package/extensions/dm-subagents/src/runs/background/retained-children.js +119 -0
  113. package/extensions/dm-subagents/src/runs/background/run-id-query.js +5 -0
  114. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +93 -9
  115. package/extensions/dm-subagents/src/runs/background/run-status.js +303 -32
  116. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +784 -376
  117. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +75 -34
  118. package/extensions/dm-subagents/src/runs/background/steering.js +221 -0
  119. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +3106 -844
  120. package/extensions/dm-subagents/src/runs/background/subagent-wait.js +529 -0
  121. package/extensions/dm-subagents/src/runs/background/terminal-run-index.js +106 -0
  122. package/extensions/dm-subagents/src/runs/background/top-level-async.js +1 -1
  123. package/extensions/dm-subagents/src/runs/background/wait-completions.js +155 -0
  124. package/extensions/dm-subagents/src/runs/background/wait-config.js +46 -0
  125. package/extensions/dm-subagents/src/runs/background/wait-subscriptions.js +278 -0
  126. package/extensions/dm-subagents/src/runs/background/wait-tool.js +47 -0
  127. package/extensions/dm-subagents/src/runs/foreground/async-dismiss-action.js +81 -0
  128. package/extensions/dm-subagents/src/runs/foreground/async-steering-action.js +245 -0
  129. package/extensions/dm-subagents/src/runs/foreground/async-stop-action.js +74 -0
  130. package/extensions/dm-subagents/src/runs/foreground/execution.js +1401 -342
  131. package/extensions/dm-subagents/src/runs/foreground/foreground-control.js +133 -0
  132. package/extensions/dm-subagents/src/runs/foreground/foreground-history.js +148 -0
  133. package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +139 -0
  134. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +4278 -1441
  135. package/extensions/dm-subagents/src/runs/foreground/workflow-detach-reconcile.js +278 -0
  136. package/extensions/dm-subagents/src/runs/foreground/workflow-foreground-steering.js +155 -0
  137. package/extensions/dm-subagents/src/runs/shared/abort-recovery.js +97 -0
  138. package/extensions/dm-subagents/src/runs/shared/acceptance.js +597 -148
  139. package/extensions/dm-subagents/src/runs/shared/agent-contract.js +35 -0
  140. package/extensions/dm-subagents/src/runs/shared/async-status-projection.js +472 -0
  141. package/extensions/dm-subagents/src/runs/shared/background-process-options.js +6 -0
  142. package/extensions/dm-subagents/src/runs/shared/capability-ceiling.js +175 -0
  143. package/extensions/dm-subagents/src/runs/shared/child-identity.js +32 -0
  144. package/extensions/dm-subagents/src/runs/shared/child-launch-plan.js +65 -0
  145. package/extensions/dm-subagents/src/runs/shared/child-protocol.js +447 -0
  146. package/extensions/dm-subagents/src/runs/shared/claude-code-adapter.js +120 -0
  147. package/extensions/dm-subagents/src/runs/shared/codex-exec-adapter.js +129 -0
  148. package/extensions/dm-subagents/src/runs/shared/completion-evidence.js +40 -0
  149. package/extensions/dm-subagents/src/runs/shared/completion-guard.js +140 -83
  150. package/extensions/dm-subagents/src/runs/shared/context-mode.js +38 -0
  151. package/extensions/dm-subagents/src/runs/shared/cursor-agent-adapter.js +101 -0
  152. package/extensions/dm-subagents/src/runs/shared/dm-args.js +445 -72
  153. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +27 -16
  154. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +19 -6
  155. package/extensions/dm-subagents/src/runs/shared/extension-bindings.js +81 -0
  156. package/extensions/dm-subagents/src/runs/shared/external-cli-contract.js +134 -0
  157. package/extensions/dm-subagents/src/runs/shared/external-cli-preflight.js +98 -0
  158. package/extensions/dm-subagents/src/runs/shared/external-cli-runner.js +419 -0
  159. package/extensions/dm-subagents/src/runs/shared/external-job-bridge.js +404 -0
  160. package/extensions/dm-subagents/src/runs/shared/external-job-runner.js +334 -0
  161. package/extensions/dm-subagents/src/runs/shared/fast-mode-extension.js +8 -0
  162. package/extensions/dm-subagents/src/runs/shared/host-step-status.js +228 -0
  163. package/extensions/dm-subagents/src/runs/shared/lane-metadata.js +104 -0
  164. package/extensions/dm-subagents/src/runs/shared/launch-cwd.js +17 -0
  165. package/extensions/dm-subagents/src/runs/shared/llm-intent-arbiter.js +190 -0
  166. package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +48 -3
  167. package/extensions/dm-subagents/src/runs/shared/mcp-config-sources.js +387 -0
  168. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +212 -137
  169. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-grant.js +131 -0
  170. package/extensions/dm-subagents/src/runs/shared/model-exclusions.js +207 -0
  171. package/extensions/dm-subagents/src/runs/shared/model-fallback.js +225 -55
  172. package/extensions/dm-subagents/src/runs/shared/model-scope.js +85 -28
  173. package/extensions/dm-subagents/src/runs/shared/mutation-evidence.js +182 -0
  174. package/extensions/dm-subagents/src/runs/shared/nested-events.js +264 -102
  175. package/extensions/dm-subagents/src/runs/shared/nested-render.js +15 -5
  176. package/extensions/dm-subagents/src/runs/shared/orca-progress-tabs.js +505 -0
  177. package/extensions/dm-subagents/src/runs/shared/parallel-handoff.js +653 -0
  178. package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +29 -12
  179. package/extensions/dm-subagents/src/runs/shared/permissions.js +108 -0
  180. package/extensions/dm-subagents/src/runs/shared/process-signal.js +13 -0
  181. package/extensions/dm-subagents/src/runs/shared/run-fanout-budget.js +257 -0
  182. package/extensions/dm-subagents/src/runs/shared/run-history.js +133 -13
  183. package/extensions/dm-subagents/src/runs/shared/runtime-acknowledged-extensions.js +62 -0
  184. package/extensions/dm-subagents/src/runs/shared/session-lease.js +225 -0
  185. package/extensions/dm-subagents/src/runs/shared/single-output.js +129 -27
  186. package/extensions/dm-subagents/src/runs/shared/spawn-budget.js +95 -0
  187. package/extensions/dm-subagents/src/runs/shared/structured-output.js +129 -10
  188. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +66 -11
  189. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +548 -70
  190. package/extensions/dm-subagents/src/runs/shared/subagent-startup-retry.js +50 -0
  191. package/extensions/dm-subagents/src/runs/shared/task-intent.js +130 -0
  192. package/extensions/dm-subagents/src/runs/shared/tool-availability.js +59 -0
  193. package/extensions/dm-subagents/src/runs/shared/tool-budget.js +7 -5
  194. package/extensions/dm-subagents/src/runs/shared/tool-timeout.js +64 -0
  195. package/extensions/dm-subagents/src/runs/shared/usage-budget.js +74 -0
  196. package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +22 -0
  197. package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-plan.js +721 -0
  198. package/extensions/dm-subagents/src/runs/shared/worktree.js +168 -19
  199. package/extensions/dm-subagents/src/shared/accessible-dir.js +35 -0
  200. package/extensions/dm-subagents/src/shared/agent-stream-options.js +3 -0
  201. package/extensions/dm-subagents/src/shared/artifacts.js +170 -11
  202. package/extensions/dm-subagents/src/shared/atomic-json.js +36 -38
  203. package/extensions/dm-subagents/src/shared/capacity-resilient-json.js +77 -0
  204. package/extensions/dm-subagents/src/shared/child-session-name.js +15 -0
  205. package/extensions/dm-subagents/src/shared/child-transcript.js +57 -2
  206. package/extensions/dm-subagents/src/shared/completion-owner.js +7 -0
  207. package/extensions/dm-subagents/src/shared/display-text.js +142 -0
  208. package/extensions/dm-subagents/src/shared/extension-context.js +17 -0
  209. package/extensions/dm-subagents/src/shared/file-coalescer.js +9 -0
  210. package/extensions/dm-subagents/src/shared/file-system-retry.js +56 -0
  211. package/extensions/dm-subagents/src/shared/fork-context.js +96 -33
  212. package/extensions/dm-subagents/src/shared/formatters.js +21 -7
  213. package/extensions/dm-subagents/src/shared/launch-contract.js +94 -0
  214. package/extensions/dm-subagents/src/shared/model-info.js +10 -5
  215. package/extensions/dm-subagents/src/shared/node-executable.js +19 -0
  216. package/extensions/dm-subagents/src/shared/prompt-resources.js +10 -0
  217. package/extensions/dm-subagents/src/shared/pruned-fork.js +427 -0
  218. package/extensions/dm-subagents/src/shared/session-file-trust.js +19 -0
  219. package/extensions/dm-subagents/src/shared/session-tokens.js +14 -3
  220. package/extensions/dm-subagents/src/shared/settings.js +39 -47
  221. package/extensions/dm-subagents/src/shared/shortcuts.js +16 -0
  222. package/extensions/dm-subagents/src/shared/status-format.js +9 -2
  223. package/extensions/dm-subagents/src/shared/thinking-ceiling.js +41 -0
  224. package/extensions/dm-subagents/src/shared/types.js +47 -7
  225. package/extensions/dm-subagents/src/shared/utf8.js +12 -0
  226. package/extensions/dm-subagents/src/shared/utils.js +151 -131
  227. package/extensions/dm-subagents/src/shared/watch-strategy.js +3 -0
  228. package/extensions/dm-subagents/src/shared/workflow-child-permit.js +84 -0
  229. package/extensions/dm-subagents/src/slash/delegation-adapters.js +274 -0
  230. package/extensions/dm-subagents/src/slash/delegation-json.js +113 -0
  231. package/extensions/dm-subagents/src/slash/delegation-request.js +152 -0
  232. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +294 -243
  233. package/extensions/dm-subagents/src/slash/prompt-workflows.js +35 -73
  234. package/extensions/dm-subagents/src/slash/selector.js +101 -0
  235. package/extensions/dm-subagents/src/slash/slash-bridge.js +17 -1
  236. package/extensions/dm-subagents/src/slash/slash-commands.js +722 -732
  237. package/extensions/dm-subagents/src/slash/slash-live-state.js +37 -19
  238. package/extensions/dm-subagents/src/slash/subagents-admin.js +410 -0
  239. package/extensions/dm-subagents/src/tui/fleet-status.js +824 -0
  240. package/extensions/dm-subagents/src/tui/fleet-transcript.js +479 -0
  241. package/extensions/dm-subagents/src/tui/fleet.js +1326 -0
  242. package/extensions/dm-subagents/src/tui/render-helpers.js +22 -0
  243. package/extensions/dm-subagents/src/tui/render.js +1511 -261
  244. package/extensions/dm-subagents/src/watchdog/change-signature.js +220 -0
  245. package/extensions/dm-subagents/src/watchdog/child-status.js +151 -0
  246. package/extensions/dm-subagents/src/watchdog/emission-guard.js +90 -0
  247. package/extensions/dm-subagents/src/watchdog/lsp-diagnostics.js +484 -0
  248. package/extensions/dm-subagents/src/watchdog/model-selection.js +154 -0
  249. package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +138 -0
  250. package/extensions/dm-subagents/src/watchdog/register-child.js +112 -0
  251. package/extensions/dm-subagents/src/watchdog/register-main.js +419 -0
  252. package/extensions/dm-subagents/src/watchdog/render.js +54 -0
  253. package/extensions/dm-subagents/src/watchdog/review.js +251 -0
  254. package/extensions/dm-subagents/src/watchdog/runtime.js +803 -0
  255. package/extensions/dm-subagents/src/watchdog/scope.js +56 -0
  256. package/extensions/dm-subagents/src/watchdog/settings.js +515 -0
  257. package/extensions/dm-subagents/src/watchdog/tool-actions.js +151 -0
  258. package/extensions/dm-subagents/src/watchdog/turn-delta.js +169 -0
  259. package/extensions/dm-subagents/src/watchdog/types.js +29 -0
  260. package/extensions/dm-subagents/src/watchdog/warning-format.js +58 -0
  261. package/extensions/dm-subagents/src/workflows/chat-progress.js +116 -0
  262. package/extensions/dm-subagents/src/workflows/host-command.js +227 -0
  263. package/extensions/dm-subagents/src/workflows/scripted-workflow.js +2011 -0
  264. package/extensions/dm-subagents/src/workflows/workflow-child-summary.js +116 -0
  265. package/extensions/dm-subagents/src/workflows/workflow-preflight.js +243 -0
  266. package/extensions/dm-subagents/src/workflows/workflow-receipt.js +387 -0
  267. package/extensions/dm-subagents/src/workflows/workflow-settlement.js +189 -0
  268. package/package.json +4 -3
  269. package/extensions/dm-fff/package.json +0 -21
  270. package/extensions/dm-fff/src/index.js +0 -691
  271. package/extensions/dm-fff/src/query.js +0 -60
  272. package/extensions/dm-subagents/agents/context-builder.md +0 -46
  273. package/extensions/dm-subagents/agents/planner.md +0 -55
  274. package/extensions/dm-subagents/prompts/parallel-context-build.md +0 -55
  275. package/extensions/dm-subagents/prompts/parallel-handoff-plan.md +0 -61
  276. package/extensions/dm-subagents/src/runs/background/wait.js +0 -206
  277. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +0 -1013
  278. package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +0 -981
  279. package/extensions/dm-subagents/src/runs/shared/turn-budget.js +0 -50
@@ -1,13 +1,36 @@
1
+ import { createHash } from "node:crypto";
1
2
  import * as fs from "node:fs";
2
3
  import * as path from "node:path";
3
4
  import { registerNativeSupervisorClient } from "../../intercom/native-supervisor-channel.js";
4
- import { consumeSteerRequestsFromDir, writeSteerRequestToDir } from "../background/control-channel.js";
5
- import { SUBAGENT_FANOUT_CHILD_ENV, SUBAGENT_STEER_INBOX_ENV } from "./dm-args.js";
6
- import { STRUCTURED_OUTPUT_CAPTURE_ENV, STRUCTURED_OUTPUT_SCHEMA_ENV, validateStructuredOutputValue } from "./structured-output.js";
7
- import { TOOL_BUDGET_ENV, decodeToolBudgetEnv, shouldBlockToolForBudget, toolBudgetBlockedMessage, toolBudgetSoftNudge } from "./tool-budget.js";
5
+ import { shouldUseNativeFsWatch } from "../../shared/watch-strategy.js";
6
+ import { decodePermissionRules, permissionDecision, PERMISSION_AUDIT_PATH_ENV, PERMISSION_POLICY_ENV } from "./permissions.js";
7
+ import { consumeSteerRequestsFromDir, MAX_STEER_QUEUE_SIZE, steerAckPathFromDir, writeSteerAckAt, writeSteerCapabilityAt, writeSteerRequestToDir } from "../background/control-channel.js";
8
+ import { SUBAGENT_CHILD_AGENT_ENV, SUBAGENT_CHILD_INDEX_ENV, SUBAGENT_FANOUT_CHILD_ENV, SUBAGENT_FORK_CACHE_KEY_ENV, SUBAGENT_INHERIT_GLOBAL_CONTEXT_ENV, SUBAGENT_STEER_ACK_DIR_ENV, SUBAGENT_STEER_CAPABILITY_ENV, SUBAGENT_STEER_INBOX_ENV } from "./dm-args.js";
9
+ import { RUNTIME_EXTENSION_ACK_EVENT, RUNTIME_EXTENSION_ACK_PATH_ENV, isRuntimeAcknowledgedExtensionId, writeRuntimeAcknowledgedExtensions } from "./runtime-acknowledged-extensions.js";
10
+ import { createStructuredOutputToolParameters, STRUCTURED_OUTPUT_ACCEPTANCE_CAPTURE_ENV, STRUCTURED_OUTPUT_CAPTURE_ENV, STRUCTURED_OUTPUT_SCHEMA_ENV, validateStructuredOutputValue } from "./structured-output.js";
11
+ import {
12
+ CHILD_TOOL_DIAGNOSTIC_PATH_ENV,
13
+ formatChildToolDiagnostic,
14
+ MCP_DIRECT_CHILD_TOOLS_ENV,
15
+ REQUIRED_CHILD_TOOLS_ENV,
16
+ writeChildToolDiagnostic
17
+ } from "./tool-availability.js";
18
+ import { TOOL_BUDGET_ENV, TOOL_BUDGET_ZERO_AUTH_ENV, decodeToolBudgetEnv, shouldBlockToolForBudget, toolBudgetBlockedMessage, toolBudgetSoftNudge } from "./tool-budget.js";
19
+ import { resolveCurrentSessionId } from "../../shared/session-identity.js";
20
+ import { getAgentDir, resolveWatchPath } from "../../shared/utils.js";
21
+ import { registerChildWatchdog } from "../../watchdog/register-child.js";
22
+ import { CHILD_WATCHDOG_CONFIG_ENV, decodeChildWatchdogConfig } from "../../watchdog/child-status.js";
23
+ import { requestWatchdogPermission } from "../../watchdog/permission-arbiter.js";
24
+ import { SUBAGENT_WATCHDOG_WARNING_TYPE } from "../../watchdog/types.js";
25
+ import { resolveWaitToolConfig } from "../background/wait-config.js";
26
+ import { registerWaitTool } from "../background/wait-tool.js";
27
+ import { drainOutstandingWork } from "../background/auto-drain.js";
8
28
  const SUBAGENT_INHERIT_PROJECT_CONTEXT_ENV = "DM_SUBAGENT_INHERIT_PROJECT_CONTEXT";
9
29
  const SUBAGENT_INHERIT_SKILLS_ENV = "DM_SUBAGENT_INHERIT_SKILLS";
10
30
  export const SUBAGENT_INTERCOM_SESSION_NAME_ENV = "DM_SUBAGENT_INTERCOM_SESSION_NAME";
31
+ export const SUBAGENT_SESSION_NAME_ENV = "DM_SUBAGENT_SESSION_NAME";
32
+ const STEERING_LEGACY_SETTLE_FALLBACK_MS = 1000;
33
+ const STEERING_SAFETY_POLL_INTERVAL_MS = 5000;
11
34
  const STRUCTURED_OUTPUT_INSTRUCTIONS = [
12
35
  "This subagent step has a strict structured output contract.",
13
36
  "Your final action must be to call the `structured_output` tool with JSON matching the provided schema.",
@@ -41,7 +64,12 @@ const PARENT_ONLY_CUSTOM_MESSAGE_TYPES = new Set([
41
64
  "subagent-control-notice"
42
65
  ]);
43
66
  const SUBAGENT_ORCHESTRATION_SKILL_NAME_PATTERN = /<name>\s*dm-subagents\s*<\/name>/;
44
- const PROJECT_CONTEXT_HEADER = `
67
+ const PROJECT_CONTEXT_XML_HEADER = `
68
+
69
+ <project_context>
70
+
71
+ `;
72
+ const PROJECT_CONTEXT_LEGACY_HEADER = `
45
73
 
46
74
  # Project Context
47
75
 
@@ -59,6 +87,66 @@ function readBooleanEnv(name) {
59
87
  return;
60
88
  return value !== "0";
61
89
  }
90
+ function readRequiredChildTools() {
91
+ const encoded = process.env[REQUIRED_CHILD_TOOLS_ENV]?.trim();
92
+ if (!encoded)
93
+ return;
94
+ const required = JSON.parse(encoded);
95
+ if (!Array.isArray(required) || required.some((name) => typeof name !== "string" || !name)) {
96
+ throw new Error(`Invalid ${REQUIRED_CHILD_TOOLS_ENV} payload.`);
97
+ }
98
+ return required;
99
+ }
100
+ function readMcpDirectChildTools() {
101
+ const encoded = process.env[MCP_DIRECT_CHILD_TOOLS_ENV]?.trim();
102
+ if (!encoded)
103
+ return;
104
+ try {
105
+ const tools = JSON.parse(encoded);
106
+ if (!Array.isArray(tools) || tools.some((name) => typeof name !== "string" || !name))
107
+ return;
108
+ return tools;
109
+ } catch {
110
+ return;
111
+ }
112
+ }
113
+ function refreshChildToolDiagnostic(dm) {
114
+ const filePath = process.env[CHILD_TOOL_DIAGNOSTIC_PATH_ENV]?.trim();
115
+ const required = readRequiredChildTools();
116
+ if (!filePath || !required)
117
+ return;
118
+ const available = dm.getAllTools().map((tool) => tool.name);
119
+ return writeChildToolDiagnostic(filePath, required, available, process.env[SUBAGENT_CHILD_AGENT_ENV]?.trim(), readMcpDirectChildTools());
120
+ }
121
+ function registerRuntimeExtensionAcknowledgements(dm) {
122
+ const outputPath = process.env[RUNTIME_EXTENSION_ACK_PATH_ENV]?.trim();
123
+ if (!outputPath)
124
+ return;
125
+ const ids = [];
126
+ let finalized = false;
127
+ const acknowledge = (payload) => {
128
+ if (finalized || !payload || typeof payload !== "object")
129
+ return;
130
+ const id = payload.id;
131
+ if (isRuntimeAcknowledgedExtensionId(id))
132
+ ids.push(id);
133
+ return;
134
+ };
135
+ const finalize = () => {
136
+ if (finalized)
137
+ return;
138
+ finalized = true;
139
+ writeRuntimeAcknowledgedExtensions(outputPath, ids);
140
+ return;
141
+ };
142
+ try {
143
+ const events = dm.events;
144
+ events?.on?.(RUNTIME_EXTENSION_ACK_EVENT, acknowledge);
145
+ const onRuntimeEvent = dm.on;
146
+ onRuntimeEvent("agent_end", finalize);
147
+ onRuntimeEvent("session_shutdown", finalize);
148
+ } catch {}
149
+ }
62
150
  function findSectionEnd(prompt, startIndex, nextHeaders) {
63
151
  let endIndex = prompt.length;
64
152
  for (const header of nextHeaders) {
@@ -70,11 +158,71 @@ function findSectionEnd(prompt, startIndex, nextHeaders) {
70
158
  return endIndex;
71
159
  }
72
160
  export function stripProjectContext(prompt) {
73
- const startIndex = prompt.indexOf(PROJECT_CONTEXT_HEADER);
74
- if (startIndex === -1)
161
+ const xmlStartIndex = prompt.indexOf(PROJECT_CONTEXT_XML_HEADER);
162
+ if (xmlStartIndex !== -1) {
163
+ const closingTag = "</project_context>";
164
+ const closingIndex = prompt.indexOf(closingTag, xmlStartIndex + PROJECT_CONTEXT_XML_HEADER.length);
165
+ if (closingIndex !== -1) {
166
+ return `${prompt.slice(0, xmlStartIndex)}${prompt.slice(closingIndex + closingTag.length)}`;
167
+ }
168
+ }
169
+ const legacyStartIndex = prompt.indexOf(PROJECT_CONTEXT_LEGACY_HEADER);
170
+ if (legacyStartIndex === -1)
75
171
  return prompt;
76
- const endIndex = findSectionEnd(prompt, startIndex + PROJECT_CONTEXT_HEADER.length, [SKILLS_HEADER, DATE_HEADER]);
77
- return `${prompt.slice(0, startIndex)}${prompt.slice(endIndex)}`;
172
+ const endIndex = findSectionEnd(prompt, legacyStartIndex + PROJECT_CONTEXT_LEGACY_HEADER.length, [SKILLS_HEADER, DATE_HEADER]);
173
+ return `${prompt.slice(0, legacyStartIndex)}${prompt.slice(endIndex)}`;
174
+ }
175
+ const GLOBAL_CONTEXT_FILE_NAMES = new Set(["agents.md", "agents.override.md", "claude.md"]);
176
+ function canonicalDirectory(dir) {
177
+ try {
178
+ return fs.realpathSync(dir);
179
+ } catch {
180
+ return path.resolve(dir);
181
+ }
182
+ }
183
+ function expandContextPath(filePath) {
184
+ const home = process.env.HOME ?? process.env.USERPROFILE;
185
+ return filePath === "~" ? home ?? filePath : /^~[\\/]/.test(filePath) ? path.join(home ?? "~", filePath.slice(2)) : filePath;
186
+ }
187
+ function isContextFilePath(filePath) {
188
+ return GLOBAL_CONTEXT_FILE_NAMES.has(path.basename(expandContextPath(filePath)).toLowerCase());
189
+ }
190
+ function isGlobalContextFile(filePath) {
191
+ const expanded = expandContextPath(filePath);
192
+ if (!isContextFilePath(filePath))
193
+ return false;
194
+ return canonicalDirectory(path.dirname(expanded)) === canonicalDirectory(getAgentDir());
195
+ }
196
+ function stripGlobalInstructionsFromXmlContext(context) {
197
+ const block = /<project_instructions\s+path=(["'])(.*?)\1\s*>[\s\S]*?<\/project_instructions>\s*/gi;
198
+ return context.replace(block, (match, _quote, filePath) => isGlobalContextFile(filePath) ? "" : match);
199
+ }
200
+ function stripGlobalInstructionsFromLegacyContext(context) {
201
+ const sections = [...context.matchAll(/^## ([^\r\n]+)(?:\r?\n|$)/gm)].filter((match) => isContextFilePath(match[1].trim()));
202
+ let rewritten = "";
203
+ let cursor = 0;
204
+ for (let index = 0;index < sections.length; index++) {
205
+ const section = sections[index];
206
+ const start = section.index;
207
+ const end = sections[index + 1]?.index ?? context.length;
208
+ rewritten += context.slice(cursor, start);
209
+ if (!isGlobalContextFile(section[1].trim()))
210
+ rewritten += context.slice(start, end);
211
+ cursor = end;
212
+ }
213
+ return `${rewritten}${context.slice(cursor)}`;
214
+ }
215
+ export function stripGlobalContext(prompt) {
216
+ const rewrittenXml = prompt.replace(/<project_context>[\s\S]*?<\/project_context>/gi, (context) => {
217
+ const rewritten = stripGlobalInstructionsFromXmlContext(context);
218
+ return /<project_instructions\b/i.test(rewritten) ? rewritten : "";
219
+ });
220
+ const legacyStartIndex = rewrittenXml.indexOf(PROJECT_CONTEXT_LEGACY_HEADER);
221
+ if (legacyStartIndex === -1)
222
+ return rewrittenXml;
223
+ const legacyEndIndex = findSectionEnd(rewrittenXml, legacyStartIndex + PROJECT_CONTEXT_LEGACY_HEADER.length, [SKILLS_HEADER, DATE_HEADER]);
224
+ const legacyContext = rewrittenXml.slice(legacyStartIndex, legacyEndIndex);
225
+ return `${rewrittenXml.slice(0, legacyStartIndex)}${stripGlobalInstructionsFromLegacyContext(legacyContext)}${rewrittenXml.slice(legacyEndIndex)}`;
78
226
  }
79
227
  export function stripInheritedSkills(prompt) {
80
228
  const startIndex = prompt.indexOf(SKILLS_HEADER);
@@ -100,6 +248,9 @@ export function rewriteSubagentPrompt(prompt, options) {
100
248
  if (!options.inheritProjectContext) {
101
249
  rewritten = stripProjectContext(rewritten);
102
250
  }
251
+ if (!options.inheritGlobalContext) {
252
+ rewritten = stripGlobalContext(rewritten);
253
+ }
103
254
  if (!options.inheritSkills) {
104
255
  rewritten = stripInheritedSkills(rewritten);
105
256
  }
@@ -115,7 +266,11 @@ ${rewritten}`;
115
266
  }
116
267
  function isParentOnlySubagentMessage(message) {
117
268
  const m = message;
118
- return m?.role === "custom" && typeof m.customType === "string" && PARENT_ONLY_CUSTOM_MESSAGE_TYPES.has(m.customType);
269
+ if (m?.role !== "custom" || typeof m.customType !== "string")
270
+ return false;
271
+ if (m.customType === SUBAGENT_WATCHDOG_WARNING_TYPE)
272
+ return true;
273
+ return PARENT_ONLY_CUSTOM_MESSAGE_TYPES.has(m.customType);
119
274
  }
120
275
  function isSubagentToolResultMessage(message) {
121
276
  const m = message;
@@ -125,6 +280,62 @@ function isSubagentToolCallBlock(block) {
125
280
  const b = block;
126
281
  return b?.type === "toolCall" && b.name === "subagent";
127
282
  }
283
+ const PORTABLE_TOOL_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
284
+ const MAX_PORTABLE_TOOL_ID_LENGTH = 64;
285
+ const COMPOSITE_TOOL_ID_APIS = new Set([
286
+ "azure-openai-responses",
287
+ "cursor-native",
288
+ "openai-completions",
289
+ "openai-responses"
290
+ ]);
291
+ const PROMPT_CACHE_KEY_APIS = new Set([
292
+ "azure-openai-responses",
293
+ "openai-codex-responses",
294
+ "openai-completions",
295
+ "openai-responses"
296
+ ]);
297
+ export function rewriteForkCacheProviderRequest(event, ctx) {
298
+ const forkCacheKey = process.env[SUBAGENT_FORK_CACHE_KEY_ENV]?.trim();
299
+ if (!forkCacheKey || !PROMPT_CACHE_KEY_APIS.has(ctx?.model?.api ?? ""))
300
+ return;
301
+ if (!event || typeof event !== "object")
302
+ return;
303
+ const payload = event.payload;
304
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
305
+ return;
306
+ if (typeof payload.prompt_cache_key !== "string")
307
+ return;
308
+ return { ...payload, prompt_cache_key: forkCacheKey };
309
+ }
310
+ function portableToolId(id) {
311
+ if (PORTABLE_TOOL_ID_PATTERN.test(id) && id.length <= MAX_PORTABLE_TOOL_ID_LENGTH)
312
+ return id;
313
+ const encoded = `tool_${Buffer.from(id).toString("base64url") || "empty"}`;
314
+ if (encoded.length <= MAX_PORTABLE_TOOL_ID_LENGTH)
315
+ return encoded;
316
+ return `tool_${createHash("sha256").update(id).digest("base64url")}`;
317
+ }
318
+ function sanitizeToolHistoryMessage(message) {
319
+ const m = message;
320
+ if (m?.role === "toolResult" && typeof m.toolCallId === "string") {
321
+ const toolCallId = portableToolId(m.toolCallId);
322
+ return toolCallId === m.toolCallId ? message : { ...m, toolCallId };
323
+ }
324
+ if (m?.role !== "assistant" || !Array.isArray(m.content))
325
+ return message;
326
+ let changed = false;
327
+ const content = m.content.map((block) => {
328
+ const b = block;
329
+ if (b?.type !== "toolCall" || typeof b.id !== "string")
330
+ return block;
331
+ const id = portableToolId(b.id);
332
+ if (id === b.id)
333
+ return block;
334
+ changed = true;
335
+ return { ...b, id };
336
+ });
337
+ return changed ? { ...m, content } : message;
338
+ }
128
339
  function stripAssistantSubagentToolCallBlocks(message) {
129
340
  const m = message;
130
341
  if (m?.role !== "assistant" || !Array.isArray(m.content))
@@ -136,8 +347,9 @@ function stripAssistantSubagentToolCallBlocks(message) {
136
347
  return;
137
348
  return { ...m, content: filteredContent };
138
349
  }
139
- export function stripParentOnlySubagentMessages(messages) {
350
+ export function stripParentOnlySubagentMessages(messages, options = {}) {
140
351
  const preserveCurrentFanoutToolHistory = process.env[SUBAGENT_FANOUT_CHILD_ENV] === "1";
352
+ const sanitizeToolIds = options.sanitizeToolIds ?? true;
141
353
  let changed = false;
142
354
  const filtered = [];
143
355
  for (const message of messages) {
@@ -150,15 +362,16 @@ export function stripParentOnlySubagentMessages(messages) {
150
362
  changed = true;
151
363
  continue;
152
364
  }
153
- if (stripped !== message)
365
+ const sanitized = sanitizeToolIds ? sanitizeToolHistoryMessage(stripped) : stripped;
366
+ if (stripped !== message || sanitized !== stripped)
154
367
  changed = true;
155
- filtered.push(stripped);
368
+ filtered.push(sanitized);
156
369
  }
157
370
  return changed ? filtered : messages;
158
371
  }
159
372
  export function formatSteerMessage(request) {
160
373
  return [
161
- "Mid-run steering from the parent orchestrator:",
374
+ request.mode === "follow_up" ? "Queued follow-up from the parent orchestrator:" : "Mid-run steering from the parent orchestrator:",
162
375
  "",
163
376
  request.message,
164
377
  "",
@@ -166,13 +379,69 @@ export function formatSteerMessage(request) {
166
379
  ].join(`
167
380
  `);
168
381
  }
169
- function registerToolBudget(pi, budget) {
382
+ export function registerPermissionGate(dm, requestPermission = requestWatchdogPermission) {
383
+ const rules = decodePermissionRules(process.env[PERMISSION_POLICY_ENV]);
384
+ if (!rules)
385
+ return;
386
+ const onRuntimeEvent = dm.on;
387
+ onRuntimeEvent("tool_call", async (event, ctx) => {
388
+ const toolName = typeof event.toolName === "string" ? event.toolName : "tool";
389
+ const decision = permissionDecision(rules, toolName);
390
+ if (decision === "allow")
391
+ return;
392
+ if (decision === "deny")
393
+ return { block: true, reason: `Blocked by dm-subagents permission rule: '${toolName}' is denied.` };
394
+ const rawWatchdogConfig = process.env[CHILD_WATCHDOG_CONFIG_ENV];
395
+ let timeoutMs = 30000;
396
+ try {
397
+ timeoutMs = decodeChildWatchdogConfig(rawWatchdogConfig)?.agentEndTimeoutMs ?? timeoutMs;
398
+ } catch {}
399
+ if (ctx.signal?.aborted)
400
+ return { block: true, reason: "Blocked by dm-subagents permission rule: Watchdog permission decision was cancelled." };
401
+ let timeout;
402
+ let abort;
403
+ let result;
404
+ try {
405
+ result = await Promise.race([
406
+ requestPermission({
407
+ ctx,
408
+ toolName,
409
+ args: event.input ?? {},
410
+ rawWatchdogConfig,
411
+ auditPath: process.env[PERMISSION_AUDIT_PATH_ENV],
412
+ ...ctx.signal ? { signal: ctx.signal } : {}
413
+ }),
414
+ new Promise((resolve) => {
415
+ if (!ctx.signal)
416
+ return;
417
+ abort = () => resolve({ approved: false, reason: "Watchdog permission decision was cancelled.", source: "watchdog" });
418
+ ctx.signal.addEventListener("abort", abort, { once: true });
419
+ }),
420
+ new Promise((_, reject) => {
421
+ timeout = setTimeout(() => reject(new Error(`Watchdog permission decision timed out after ${timeoutMs}ms.`)), timeoutMs);
422
+ })
423
+ ]);
424
+ } catch (error) {
425
+ const reason = error instanceof Error ? error.message : String(error);
426
+ return { block: true, reason: `Blocked by dm-subagents permission rule: Watchdog permission arbiter failed closed: ${reason}` };
427
+ } finally {
428
+ if (timeout)
429
+ clearTimeout(timeout);
430
+ if (abort)
431
+ ctx.signal?.removeEventListener("abort", abort);
432
+ }
433
+ if (result.approved)
434
+ return;
435
+ return { block: true, reason: `Blocked by dm-subagents permission rule: ${result.reason}` };
436
+ });
437
+ }
438
+ function registerToolBudget(dm, budget) {
170
439
  if (!budget)
171
440
  return;
172
441
  let toolCount = 0;
173
442
  let softNudged = false;
174
- const sendUserMessage = pi.sendUserMessage;
175
- const onRuntimeEvent = pi.on;
443
+ const sendUserMessage = dm.sendUserMessage;
444
+ const onRuntimeEvent = dm.on;
176
445
  onRuntimeEvent("tool_call", (event) => {
177
446
  const toolName = typeof event.toolName === "string" ? event.toolName : "tool";
178
447
  toolCount++;
@@ -187,32 +456,78 @@ function registerToolBudget(pi, budget) {
187
456
  return { block: true, reason: toolBudgetBlockedMessage(budget, toolName, toolCount) };
188
457
  });
189
458
  }
190
- function registerSteeringInbox(pi) {
459
+ export function registerSteeringInbox(dm, deps = {}) {
191
460
  const steerInbox = process.env[SUBAGENT_STEER_INBOX_ENV]?.trim();
192
461
  if (!steerInbox)
193
462
  return;
194
- const sendUserMessage = pi.sendUserMessage;
195
- if (typeof sendUserMessage !== "function")
196
- return;
197
- let canSteer = false;
463
+ const capabilityPath = process.env[SUBAGENT_STEER_CAPABILITY_ENV]?.trim();
464
+ const ackDir = process.env[SUBAGENT_STEER_ACK_DIR_ENV]?.trim();
465
+ const sendUserMessage = dm.sendUserMessage;
466
+ const childIndex = Number(process.env[SUBAGENT_CHILD_INDEX_ENV]);
467
+ const pending = new Map;
468
+ const queued = [];
198
469
  let disposed = false;
470
+ let agentRunning = false;
471
+ let inTurn = false;
472
+ let awaitingSettlement = false;
199
473
  let flushing = false;
200
474
  let started = false;
475
+ let canSteer = typeof sendUserMessage === "function";
201
476
  let watcher;
202
477
  let interval;
478
+ let safetyInterval;
479
+ let settleFallback;
480
+ const legacySettleFallbackMs = deps.legacySettleFallbackMs ?? STEERING_LEGACY_SETTLE_FALLBACK_MS;
481
+ const acknowledge = (request, state, message, deliveryStatus) => {
482
+ if (!ackDir || !Number.isInteger(childIndex) || childIndex < 0)
483
+ return;
484
+ writeSteerAckAt(steerAckPathFromDir(ackDir, request.id), {
485
+ requestId: request.id,
486
+ index: childIndex,
487
+ ts: Date.now(),
488
+ state,
489
+ ...deliveryStatus ? { deliveryStatus } : {},
490
+ message
491
+ });
492
+ };
493
+ const publishCapability = () => {
494
+ if (!capabilityPath || !Number.isInteger(childIndex) || childIndex < 0)
495
+ return;
496
+ writeSteerCapabilityAt(capabilityPath, { index: childIndex, pid: process.pid, readyAt: Date.now(), supported: canSteer });
497
+ };
203
498
  const flush = () => {
204
- if (disposed || flushing || !canSteer)
499
+ if (disposed || flushing)
205
500
  return;
206
501
  flushing = true;
207
502
  try {
208
503
  const requests = consumeSteerRequestsFromDir(steerInbox);
209
504
  for (let index = 0;index < requests.length; index++) {
210
505
  const request = requests[index];
506
+ if (!canSteer || typeof sendUserMessage !== "function") {
507
+ acknowledge(request, "failed", "Child DM session does not support sendUserMessage steering.");
508
+ continue;
509
+ }
510
+ const requestedMode = request.mode ?? "steer";
511
+ const autoCanUseIdle = requestedMode === "auto" && !agentRunning && !awaitingSettlement;
512
+ const delivery = requestedMode === "follow_up" || requestedMode === "auto" && (inTurn || awaitingSettlement) ? "followUp" : "steer";
513
+ const pendingFollowUps = [...pending.values()].reduce((count, entries) => count + entries.filter((entry) => entry.deliveryStatus === "queued").length, 0);
514
+ if (delivery === "followUp" && queued.length + pendingFollowUps >= MAX_STEER_QUEUE_SIZE) {
515
+ acknowledge(request, "failed", `Follow-up queue is full (${MAX_STEER_QUEUE_SIZE} messages).`);
516
+ continue;
517
+ }
518
+ const formatted = formatSteerMessage(request);
519
+ const entries = pending.get(formatted) ?? [];
520
+ entries.push({ request, deliveryStatus: delivery === "followUp" ? "queued" : "delivered" });
521
+ pending.set(formatted, entries);
211
522
  try {
212
- sendUserMessage(formatSteerMessage(request), { deliverAs: "steer" });
213
- } catch {
214
- for (const pending of requests.slice(index))
215
- writeSteerRequestToDir(steerInbox, pending);
523
+ sendUserMessage(formatted, autoCanUseIdle ? undefined : { deliverAs: delivery });
524
+ } catch (error) {
525
+ entries.pop();
526
+ if (entries.length === 0)
527
+ pending.delete(formatted);
528
+ acknowledge(request, "failed", error instanceof Error ? error.message : String(error));
529
+ for (const retry of requests.slice(index + 1))
530
+ writeSteerRequestToDir(steerInbox, retry);
216
531
  break;
217
532
  }
218
533
  }
@@ -220,87 +535,238 @@ function registerSteeringInbox(pi) {
220
535
  flushing = false;
221
536
  }
222
537
  };
538
+ const onInput = (event) => {
539
+ if (disposed || !event || typeof event !== "object")
540
+ return;
541
+ const input = event;
542
+ if (input.source !== "extension")
543
+ return;
544
+ const text = typeof input.text === "string" ? input.text : typeof input.content === "string" ? input.content : undefined;
545
+ if (!text)
546
+ return;
547
+ const entries = pending.get(text);
548
+ const entry = entries?.shift();
549
+ if (!entry)
550
+ return;
551
+ if (entries?.length === 0)
552
+ pending.delete(text);
553
+ if (entry.deliveryStatus === "queued") {
554
+ queued.push({ request: entry.request, ready: !inTurn });
555
+ acknowledge(entry.request, "queued", "DM queued the correlated follow-up input.", "queued");
556
+ } else {
557
+ acknowledge(entry.request, "delivered", "DM accepted the correlated steering input.", "delivered");
558
+ }
559
+ return;
560
+ };
223
561
  const start = () => {
224
562
  if (started || disposed)
225
563
  return;
226
564
  try {
227
565
  fs.mkdirSync(steerInbox, { recursive: true });
566
+ publishCapability();
228
567
  } catch {
229
568
  return;
230
569
  }
231
570
  started = true;
232
- try {
233
- watcher = fs.watch(steerInbox, () => flush());
234
- watcher.on("error", () => {});
235
- } catch {
236
- watcher = undefined;
571
+ const startPolling = () => {
572
+ if (interval || disposed)
573
+ return;
574
+ interval = (deps.timers?.setInterval ?? setInterval)(flush, 250);
575
+ interval.unref?.();
576
+ };
577
+ const startSafetyPolling = () => {
578
+ if (safetyInterval || disposed)
579
+ return;
580
+ safetyInterval = (deps.timers?.setInterval ?? setInterval)(flush, deps.safetyPollIntervalMs ?? STEERING_SAFETY_POLL_INTERVAL_MS);
581
+ safetyInterval.unref?.();
582
+ };
583
+ if (!shouldUseNativeFsWatch("child-steering-inbox", deps.platform)) {
584
+ startPolling();
585
+ } else {
586
+ try {
587
+ watcher = (deps.watch ?? fs.watch)(resolveWatchPath(steerInbox, deps.nativeRealpath), () => flush());
588
+ watcher.on("error", startPolling);
589
+ startSafetyPolling();
590
+ } catch {
591
+ watcher = undefined;
592
+ startPolling();
593
+ }
237
594
  }
238
- interval = setInterval(flush, 250);
239
- interval.unref?.();
240
595
  };
241
596
  const activate = () => {
242
597
  start();
243
- canSteer = true;
244
598
  flush();
245
599
  return;
246
600
  };
247
- const onRuntimeEvent = pi.on;
601
+ const clearSettleFallback = () => {
602
+ if (!settleFallback)
603
+ return;
604
+ clearTimeout(settleFallback);
605
+ settleFallback = undefined;
606
+ };
607
+ const markSettled = () => {
608
+ clearSettleFallback();
609
+ agentRunning = false;
610
+ inTurn = false;
611
+ awaitingSettlement = false;
612
+ return activate();
613
+ };
614
+ const armLegacySettleFallback = () => {
615
+ clearSettleFallback();
616
+ settleFallback = setTimeout(() => {
617
+ settleFallback = undefined;
618
+ if (disposed || !awaitingSettlement)
619
+ return;
620
+ agentRunning = false;
621
+ inTurn = false;
622
+ awaitingSettlement = false;
623
+ activate();
624
+ }, legacySettleFallbackMs);
625
+ settleFallback.unref?.();
626
+ };
627
+ const onRuntimeEvent = dm.on;
628
+ onRuntimeEvent("input", onInput);
248
629
  onRuntimeEvent("session_start", () => start());
249
- for (const eventName of ["message_start", "message_update", "message_end", "tool_execution_start", "tool_execution_end", "turn_end"]) {
630
+ onRuntimeEvent("agent_start", () => {
631
+ clearSettleFallback();
632
+ agentRunning = true;
633
+ awaitingSettlement = false;
634
+ return activate();
635
+ });
636
+ onRuntimeEvent("agent_end", (event) => {
637
+ inTurn = false;
638
+ if (event?.willRetry === true) {
639
+ clearSettleFallback();
640
+ agentRunning = true;
641
+ awaitingSettlement = true;
642
+ return activate();
643
+ }
644
+ agentRunning = true;
645
+ awaitingSettlement = true;
646
+ armLegacySettleFallback();
647
+ return activate();
648
+ });
649
+ onRuntimeEvent("agent_settled", markSettled);
650
+ onRuntimeEvent("session_compact", () => {
651
+ const unresolved = [...pending.values()].flat();
652
+ pending.clear();
653
+ for (const entry of unresolved) {
654
+ try {
655
+ writeSteerRequestToDir(steerInbox, { ...entry.request, mode: "follow_up" });
656
+ } catch (error) {
657
+ acknowledge(entry.request, "failed", `Could not retry steering after compaction: ${error instanceof Error ? error.message : String(error)}`);
658
+ }
659
+ }
660
+ return activate();
661
+ });
662
+ onRuntimeEvent("turn_start", () => {
663
+ clearSettleFallback();
664
+ agentRunning = true;
665
+ awaitingSettlement = false;
666
+ inTurn = true;
667
+ const next = queued.findIndex((entry) => entry.ready);
668
+ if (next >= 0) {
669
+ const [entry] = queued.splice(next, 1);
670
+ if (entry)
671
+ acknowledge(entry.request, "delivered", "DM delivered the queued follow-up at a turn boundary.", "delivered");
672
+ }
673
+ return activate();
674
+ });
675
+ onRuntimeEvent("turn_end", () => {
676
+ inTurn = false;
677
+ for (const entry of queued)
678
+ entry.ready = true;
679
+ return activate();
680
+ });
681
+ for (const eventName of ["message_start", "message_update", "message_end", "tool_execution_start", "tool_execution_end"]) {
250
682
  onRuntimeEvent(eventName, activate);
251
683
  }
252
684
  onRuntimeEvent("session_shutdown", () => {
685
+ for (const entry of queued)
686
+ acknowledge(entry.request, "failed", "Run ended before queued follow-up delivery.", "queued");
687
+ for (const entries of pending.values()) {
688
+ for (const entry of entries)
689
+ acknowledge(entry.request, "failed", "Run ended before DM confirmed steering input delivery.");
690
+ }
253
691
  disposed = true;
692
+ clearSettleFallback();
254
693
  try {
255
694
  watcher?.close();
256
695
  } catch {}
257
696
  if (interval)
258
- clearInterval(interval);
697
+ (deps.timers?.clearInterval ?? clearInterval)(interval);
698
+ if (safetyInterval)
699
+ (deps.timers?.clearInterval ?? clearInterval)(safetyInterval);
259
700
  });
260
701
  }
261
- export default function registerSubagentPromptRuntime(pi) {
262
- registerSteeringInbox(pi);
263
- registerToolBudget(pi, decodeToolBudgetEnv(process.env[TOOL_BUDGET_ENV]));
702
+ export default function registerSubagentPromptRuntime(dm) {
703
+ registerRuntimeExtensionAcknowledgements(dm);
704
+ registerSteeringInbox(dm);
705
+ registerPermissionGate(dm);
706
+ registerToolBudget(dm, decodeToolBudgetEnv(process.env[TOOL_BUDGET_ENV], { allowZero: process.env[TOOL_BUDGET_ZERO_AUTH_ENV] === "1" }));
707
+ registerChildWatchdog(dm);
708
+ const waitToolConfig = resolveWaitToolConfig();
709
+ const waitState = {
710
+ baseCwd: "",
711
+ currentSessionId: null,
712
+ asyncJobs: new Map,
713
+ foregroundControls: new Map,
714
+ lastForegroundControlId: null,
715
+ cleanupTimers: new Map,
716
+ lastUiContext: null,
717
+ poller: null,
718
+ completionSeen: new Map,
719
+ watcher: null,
720
+ watcherRestartTimer: null,
721
+ resultFileCoalescer: { schedule: () => false, clear: () => {} }
722
+ };
723
+ if (typeof dm.registerTool === "function")
724
+ registerWaitTool(dm, waitState, waitToolConfig.enabled, undefined, waitToolConfig.defaultTimeoutMs);
264
725
  let nativeSupervisorClientRegistered = false;
265
- let nativeSupervisorFallbackRegistered = false;
266
726
  const registerNativeSupervisorClientOnce = () => {
267
727
  if (nativeSupervisorClientRegistered)
268
728
  return;
269
729
  nativeSupervisorClientRegistered = true;
270
- registerNativeSupervisorClient(pi, { includeIntercomFallback: false });
730
+ registerNativeSupervisorClient(dm);
271
731
  };
272
- const registerNativeSupervisorFallbackOnce = () => {
732
+ const onRuntimeEvent = dm.on;
733
+ onRuntimeEvent("session_start", (_event, ctx) => {
734
+ const sessionManager = ctx?.sessionManager;
735
+ waitState.currentSessionId = sessionManager ? resolveCurrentSessionId(sessionManager) : null;
273
736
  registerNativeSupervisorClientOnce();
274
- if (nativeSupervisorFallbackRegistered)
737
+ });
738
+ onRuntimeEvent("agent_start", () => {
739
+ const diagnostic = refreshChildToolDiagnostic(dm);
740
+ if (diagnostic)
741
+ throw new Error(formatChildToolDiagnostic(diagnostic));
742
+ });
743
+ onRuntimeEvent("agent_end", async (_event, ctx) => {
744
+ if (ctx?.hasUI === true)
275
745
  return;
276
- nativeSupervisorFallbackRegistered = true;
277
- registerNativeSupervisorClient(pi);
278
- };
279
- const onRuntimeEvent = pi.on;
280
- onRuntimeEvent("session_start", registerNativeSupervisorClientOnce);
746
+ await drainOutstandingWork({ state: waitState, events: dm.events });
747
+ });
281
748
  const structuredOutputPath = process.env[STRUCTURED_OUTPUT_CAPTURE_ENV];
749
+ const structuredAcceptanceReportPath = process.env[STRUCTURED_OUTPUT_ACCEPTANCE_CAPTURE_ENV];
282
750
  const structuredSchemaPath = process.env[STRUCTURED_OUTPUT_SCHEMA_ENV];
283
751
  if (structuredOutputPath && structuredSchemaPath) {
284
752
  const schema = JSON.parse(fs.readFileSync(structuredSchemaPath, "utf-8"));
285
- const parameters = {
286
- type: "object",
287
- properties: { value: schema },
288
- required: ["value"],
289
- additionalProperties: false
290
- };
291
- const registerTool = pi.registerTool;
753
+ const parameters = createStructuredOutputToolParameters(schema, { acceptanceReport: Boolean(structuredAcceptanceReportPath) });
754
+ const registerTool = dm.registerTool;
292
755
  registerTool({
293
756
  name: "structured_output",
294
757
  label: "Structured Output",
295
758
  description: "Submit the required final structured output for this subagent step. This terminates the step.",
296
759
  parameters,
297
760
  async execute(_id, params) {
298
- const validation = validateStructuredOutputValue(schema, params.value);
761
+ const validation = await validateStructuredOutputValue(schema, params.value);
299
762
  if (validation.status === "invalid") {
300
763
  throw new Error(`Structured output validation failed: ${validation.message}`);
301
764
  }
302
765
  fs.mkdirSync(path.dirname(structuredOutputPath), { recursive: true });
303
766
  fs.writeFileSync(structuredOutputPath, JSON.stringify(params.value), { mode: 384 });
767
+ if (structuredAcceptanceReportPath && params.acceptanceReport !== undefined) {
768
+ fs.writeFileSync(structuredAcceptanceReportPath, JSON.stringify(params.acceptanceReport), { mode: 384 });
769
+ }
304
770
  return {
305
771
  content: [{ type: "text", text: "Structured output captured." }],
306
772
  details: { path: structuredOutputPath },
@@ -309,28 +775,40 @@ export default function registerSubagentPromptRuntime(pi) {
309
775
  }
310
776
  });
311
777
  }
312
- onRuntimeEvent("context", (event) => {
313
- const messages = stripParentOnlySubagentMessages(event.messages);
778
+ onRuntimeEvent("before_provider_request", (event, ctx) => rewriteForkCacheProviderRequest(event, ctx));
779
+ onRuntimeEvent("context", (event, ctx) => {
780
+ if (!event || typeof event !== "object" || !("messages" in event) || !Array.isArray(event.messages))
781
+ return;
782
+ const messages = stripParentOnlySubagentMessages(event.messages, {
783
+ sanitizeToolIds: !COMPOSITE_TOOL_ID_APIS.has(ctx?.model?.api ?? "")
784
+ });
314
785
  if (messages === event.messages)
315
786
  return;
316
787
  return { messages };
317
788
  });
318
789
  onRuntimeEvent("before_agent_start", async (event) => {
319
- registerNativeSupervisorFallbackOnce();
790
+ if (!event || typeof event !== "object" || !("systemPrompt" in event) || typeof event.systemPrompt !== "string")
791
+ return;
792
+ registerNativeSupervisorClientOnce();
320
793
  const intercomSessionName = process.env[SUBAGENT_INTERCOM_SESSION_NAME_ENV]?.trim();
321
- if (intercomSessionName && typeof pi.setSessionName === "function") {
322
- pi.setSessionName(intercomSessionName);
794
+ const displaySessionName = process.env[SUBAGENT_SESSION_NAME_ENV]?.trim();
795
+ const childSessionName = intercomSessionName || displaySessionName;
796
+ if (childSessionName && typeof dm.setSessionName === "function") {
797
+ dm.setSessionName(childSessionName);
323
798
  }
324
799
  const inheritProjectContext = readBooleanEnv(SUBAGENT_INHERIT_PROJECT_CONTEXT_ENV);
800
+ const inheritGlobalContext = readBooleanEnv(SUBAGENT_INHERIT_GLOBAL_CONTEXT_ENV);
325
801
  const inheritSkills = readBooleanEnv(SUBAGENT_INHERIT_SKILLS_ENV);
326
802
  const fanoutChild = readBooleanEnv(SUBAGENT_FANOUT_CHILD_ENV);
327
- if (inheritProjectContext === undefined && inheritSkills === undefined && fanoutChild === undefined)
328
- return;
329
- const rewritten = rewriteSubagentPrompt(event.systemPrompt, {
330
- inheritProjectContext: inheritProjectContext ?? true,
331
- inheritSkills: inheritSkills ?? true,
332
- fanoutChild: fanoutChild === true
333
- });
803
+ let rewritten = event.systemPrompt;
804
+ if (inheritProjectContext !== undefined || inheritGlobalContext !== undefined || inheritSkills !== undefined || fanoutChild !== undefined) {
805
+ rewritten = rewriteSubagentPrompt(event.systemPrompt, {
806
+ inheritProjectContext: inheritProjectContext ?? true,
807
+ inheritGlobalContext: inheritGlobalContext ?? true,
808
+ inheritSkills: inheritSkills ?? true,
809
+ fanoutChild: fanoutChild === true
810
+ });
811
+ }
334
812
  if (rewritten === event.systemPrompt)
335
813
  return;
336
814
  return { systemPrompt: rewritten };