@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,10 +1,20 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
+ import { previewDisplayText, sanitizeDisplayText, truncateDisplayText } from "./display-text.js";
4
5
  import { formatToolCall } from "./formatters.js";
6
+ import { validateAsyncStatusLaneMetadata } from "../runs/shared/lane-metadata.js";
5
7
  const DEFAULT_CONFIG_DIR_NAME = ".dm";
6
- const PI_CODING_AGENT_PACKAGE_NAME = "@duckmind/dm-coding-agent";
7
- export const PI_CODING_AGENT_PACKAGE_ROOT_ENV = "DM_SUBAGENTS_PI_CODING_AGENT_PACKAGE_ROOT";
8
+ const DM_CODING_AGENT_PACKAGE_NAME = "@duckmind/dm-coding-agent";
9
+ export const DM_CODING_AGENT_PACKAGE_ROOT_ENV = "DM_SUBAGENTS_DM_CODING_AGENT_PACKAGE_ROOT";
10
+ export const PROMPT_REDACTED = "[prompt redacted]";
11
+ export function resolveWatchPath(watchPath, nativeRealpath = fs.realpathSync.native) {
12
+ try {
13
+ return nativeRealpath(watchPath);
14
+ } catch {
15
+ return watchPath;
16
+ }
17
+ }
8
18
  function validConfigDirName(value) {
9
19
  return typeof value === "string" && value.trim() ? value : undefined;
10
20
  }
@@ -13,14 +23,14 @@ function readConfigDirNameFromPackageRoot(packageRoot) {
13
23
  return;
14
24
  try {
15
25
  const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf-8"));
16
- if (pkg.name !== PI_CODING_AGENT_PACKAGE_NAME)
26
+ if (pkg.name !== DM_CODING_AGENT_PACKAGE_NAME)
17
27
  return;
18
28
  return validConfigDirName(pkg.piConfig?.configDir);
19
29
  } catch {
20
30
  return;
21
31
  }
22
32
  }
23
- function resolveConfigDirNameFromPackageJson(entryPoint = process.argv[1], packageRoot = process.env[PI_CODING_AGENT_PACKAGE_ROOT_ENV]) {
33
+ function resolveConfigDirNameFromPackageJson(entryPoint = process.argv[1], packageRoot = process.env[DM_CODING_AGENT_PACKAGE_ROOT_ENV]) {
24
34
  const packageRootValue = readConfigDirNameFromPackageRoot(packageRoot);
25
35
  if (packageRootValue)
26
36
  return packageRootValue;
@@ -41,21 +51,45 @@ export function resolveConfigDirName(codingAgentModule, entryPoint, packageRoot)
41
51
  const moduleValue = codingAgentModule && typeof codingAgentModule === "object" ? validConfigDirName(codingAgentModule.CONFIG_DIR_NAME) : undefined;
42
52
  return moduleValue ?? resolveConfigDirNameFromPackageJson(entryPoint, packageRoot) ?? DEFAULT_CONFIG_DIR_NAME;
43
53
  }
54
+ let cachedConfigDirName;
44
55
  export function getConfigDirName() {
45
- return resolveConfigDirName();
56
+ const entryPoint = process.argv[1];
57
+ const packageRoot = process.env[DM_CODING_AGENT_PACKAGE_ROOT_ENV];
58
+ if (cachedConfigDirName && cachedConfigDirName.entryPoint === entryPoint && cachedConfigDirName.packageRoot === packageRoot) {
59
+ return cachedConfigDirName.value;
60
+ }
61
+ const value = resolveConfigDirName(undefined, entryPoint, packageRoot);
62
+ cachedConfigDirName = { entryPoint, packageRoot, value };
63
+ return value;
46
64
  }
47
65
  export function getProjectConfigDir(projectRoot) {
48
66
  return path.join(projectRoot, getConfigDirName());
49
67
  }
50
68
  export function getAgentDir() {
51
69
  const configured = process.env.DM_CODING_AGENT_DIR;
70
+ const home = process.env.HOME || process.env.USERPROFILE || os.homedir();
52
71
  if (configured === "~")
53
- return os.homedir();
54
- if (configured?.startsWith("~/"))
55
- return path.join(os.homedir(), configured.slice(2));
56
- return configured || path.join(os.homedir(), getConfigDirName(), "agent");
72
+ return home;
73
+ if (configured?.startsWith("~/") || configured?.startsWith("~\\"))
74
+ return path.join(home, configured.slice(2));
75
+ return configured || path.join(home, getConfigDirName(), "agent");
57
76
  }
58
77
  const statusCache = new Map;
78
+ const MAX_STATUS_CACHE_ENTRIES = 512;
79
+ export function pruneStatusCacheForAsyncRoot(asyncDirRoot, runIds) {
80
+ const root = path.resolve(asyncDirRoot);
81
+ const currentStatusPaths = new Set(Array.from(runIds, (runId) => path.resolve(root, runId, "status.json")));
82
+ let removed = 0;
83
+ for (const statusPath of statusCache.keys()) {
84
+ const resolved = path.resolve(statusPath);
85
+ const relative = path.relative(root, resolved);
86
+ if (relative && !relative.startsWith("..") && !path.isAbsolute(relative) && !currentStatusPaths.has(resolved)) {
87
+ statusCache.delete(statusPath);
88
+ removed++;
89
+ }
90
+ }
91
+ return removed;
92
+ }
59
93
  function getErrorMessage(error) {
60
94
  return error instanceof Error ? error.message : String(error);
61
95
  }
@@ -73,22 +107,28 @@ export function readStatus(asyncDir) {
73
107
  try {
74
108
  stat = fs.statSync(statusPath);
75
109
  } catch (error) {
76
- if (isNotFoundError(error))
110
+ if (isNotFoundError(error)) {
111
+ statusCache.delete(statusPath);
77
112
  return null;
113
+ }
78
114
  throw new Error(`Failed to inspect async status file '${statusPath}': ${getErrorMessage(error)}`, {
79
115
  cause: error instanceof Error ? error : undefined
80
116
  });
81
117
  }
82
118
  const cached = statusCache.get(statusPath);
83
- if (cached && cached.mtime === stat.mtimeMs) {
119
+ if (cached && cached.mtime === stat.mtimeMs && cached.ctime === stat.ctimeMs && cached.size === stat.size && cached.ino === stat.ino) {
120
+ statusCache.delete(statusPath);
121
+ statusCache.set(statusPath, cached);
84
122
  return cached.status;
85
123
  }
86
124
  let content;
87
125
  try {
88
126
  content = fs.readFileSync(statusPath, "utf-8");
89
127
  } catch (error) {
90
- if (isNotFoundError(error))
128
+ if (isNotFoundError(error)) {
129
+ statusCache.delete(statusPath);
91
130
  return null;
131
+ }
92
132
  throw new Error(`Failed to read async status file '${statusPath}': ${getErrorMessage(error)}`, {
93
133
  cause: error instanceof Error ? error : undefined
94
134
  });
@@ -101,52 +141,27 @@ export function readStatus(asyncDir) {
101
141
  cause: error instanceof Error ? error : undefined
102
142
  });
103
143
  }
104
- statusCache.set(statusPath, { mtime: stat.mtimeMs, status });
105
- if (statusCache.size > 50) {
106
- const firstKey = statusCache.keys().next().value;
107
- if (firstKey)
108
- statusCache.delete(firstKey);
109
- }
110
- return status;
111
- }
112
- const outputTailCache = new Map;
113
- function getOutputTail(outputFile, maxLines = 3) {
114
- if (!outputFile)
115
- return [];
116
- let fd = null;
117
144
  try {
118
- const stat = fs.statSync(outputFile);
119
- if (stat.size === 0)
120
- return [];
121
- const cached = outputTailCache.get(outputFile);
122
- if (cached && cached.mtime === stat.mtimeMs && cached.size === stat.size) {
123
- return cached.lines;
124
- }
125
- const tailBytes = 4096;
126
- const start = Math.max(0, stat.size - tailBytes);
127
- fd = fs.openSync(outputFile, "r");
128
- const buffer = Buffer.alloc(Math.min(tailBytes, stat.size));
129
- fs.readSync(fd, buffer, 0, buffer.length, start);
130
- const content = buffer.toString("utf-8");
131
- const allLines = content.split(`
132
- `).filter((l) => l.trim());
133
- const lines = allLines.slice(-maxLines).map((l) => l.slice(0, 120) + (l.length > 120 ? "..." : ""));
134
- outputTailCache.set(outputFile, { mtime: stat.mtimeMs, size: stat.size, lines });
135
- if (outputTailCache.size > 20) {
136
- const firstKey = outputTailCache.keys().next().value;
137
- if (firstKey)
138
- outputTailCache.delete(firstKey);
139
- }
140
- return lines;
141
- } catch {
142
- return [];
143
- } finally {
144
- if (fd !== null) {
145
- try {
146
- fs.closeSync(fd);
147
- } catch {}
148
- }
145
+ validateAsyncStatusLaneMetadata(status, `Invalid async status '${statusPath}'`);
146
+ } catch (error) {
147
+ throw new Error(`Failed to validate async status file '${statusPath}': ${getErrorMessage(error)}`, {
148
+ cause: error instanceof Error ? error : undefined
149
+ });
150
+ }
151
+ statusCache.set(statusPath, {
152
+ mtime: stat.mtimeMs,
153
+ ctime: stat.ctimeMs,
154
+ size: stat.size,
155
+ ino: stat.ino,
156
+ status
157
+ });
158
+ while (statusCache.size > MAX_STATUS_CACHE_ENTRIES) {
159
+ const oldest = statusCache.keys().next().value;
160
+ if (oldest === undefined)
161
+ break;
162
+ statusCache.delete(oldest);
149
163
  }
164
+ return status;
150
165
  }
151
166
  export function getLastActivity(outputFile) {
152
167
  if (!outputFile)
@@ -173,38 +188,35 @@ export function findLatestSessionFile(sessionDir) {
173
188
  mtime: fs.statSync(filePath).mtimeMs
174
189
  };
175
190
  }).sort((a, b) => b.mtime - a.mtime);
176
- return files.length > 0 ? files[0].path : null;
177
- }
178
- function writePrompt(agent, prompt) {
179
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), "dm-subagent-"));
180
- const p = path.join(dir, `${agent.replace(/[^\w.-]/g, "_")}.md`);
181
- fs.writeFileSync(p, prompt, { mode: 384 });
182
- return { dir, path: p };
191
+ const latest = files[0];
192
+ return latest ? latest.path : null;
183
193
  }
184
194
  export function getFinalOutput(messages) {
185
195
  const validTextParts = [];
186
196
  for (let i = messages.length - 1;i >= 0; i--) {
187
197
  const msg = messages[i];
188
- if (msg.role !== "assistant")
198
+ if (!msg || msg.role !== "assistant")
189
199
  continue;
190
200
  const hasAssistantError = "errorMessage" in msg && typeof msg.errorMessage === "string" && msg.errorMessage.length > 0 || "stopReason" in msg && msg.stopReason === "error";
191
201
  if (hasAssistantError)
192
202
  continue;
203
+ const messageText = msg.content.filter((part) => part.type === "text" && part.text.trim().length > 0).map((part) => part.type === "text" ? part.text : "").join(`
204
+ `);
193
205
  for (let j = msg.content.length - 1;j >= 0; j--) {
194
206
  const part = msg.content[j];
195
- if (part.type !== "text" || part.text.trim().length === 0)
207
+ if (!part || part.type !== "text" || part.text.trim().length === 0)
196
208
  continue;
197
209
  validTextParts.push(part.text);
198
- if (/```acceptance-report\s*\n[\s\S]*?```/i.test(part.text))
199
- return part.text;
210
+ if (/```acceptance[-_]report\s*\n[\s\S]*?```/i.test(part.text))
211
+ return messageText;
200
212
  for (const match of part.text.matchAll(/```(?:json|jsonc|json5)\s*\n([\s\S]*?)```/gi)) {
201
213
  const body = match[1] ?? "";
202
- if (/"criteriaSatisfied"/.test(body) && /"(?:changedFiles|testsAddedOrUpdated|commandsRun|validationOutput|residualRisks|noStagedFiles|diffSummary|reviewFindings|manualNotes)"/.test(body)) {
203
- return part.text;
214
+ if (/"(?:criteriaSatisfied|criteria_satisfied)"/.test(body) && /"(?:changedFiles|changed_files|testsAddedOrUpdated|tests_added_or_updated|commandsRun|commands_run|validationOutput|validation_output|residualRisks|residual_risks|noStagedFiles|no_staged_files|diffSummary|diff_summary|reviewFindings|review_findings|manualNotes|manual_notes)"/.test(body)) {
215
+ return messageText;
204
216
  }
205
217
  }
206
218
  if (/ACCEPTANCE_REPORT\s*:/i.test(part.text))
207
- return part.text;
219
+ return messageText;
208
220
  }
209
221
  }
210
222
  return validTextParts[0] ?? "";
@@ -234,9 +246,10 @@ function compactCompletedProgress(progress) {
234
246
  return {
235
247
  index: progress.index,
236
248
  agent: progress.agent,
249
+ ...progress.sessionName ? { sessionName: progress.sessionName } : {},
237
250
  status: progress.status,
238
251
  activityState: progress.activityState,
239
- task: progress.task,
252
+ task: "[prompt redacted]",
240
253
  skills: progress.skills,
241
254
  toolCount: progress.toolCount,
242
255
  tokens: progress.tokens,
@@ -278,6 +291,16 @@ export function sumResultsUsage(results) {
278
291
  }
279
292
  return usage;
280
293
  }
294
+ export function toAgentToolUsage(usage) {
295
+ return {
296
+ input: usage.input,
297
+ output: usage.output,
298
+ cacheRead: usage.cacheRead,
299
+ cacheWrite: usage.cacheWrite,
300
+ totalTokens: usage.input + usage.output + usage.cacheRead + usage.cacheWrite,
301
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: usage.cost }
302
+ };
303
+ }
281
304
  function addNestedCost(total, children) {
282
305
  for (const child of children ?? []) {
283
306
  if (child.totalCost) {
@@ -307,6 +330,7 @@ export function compactForegroundResult(result) {
307
330
  const toolCalls = result.toolCalls?.length ? result.toolCalls : extractToolCallSummaries(result.messages);
308
331
  return {
309
332
  ...result,
333
+ task: "[prompt redacted]",
310
334
  messages: undefined,
311
335
  progress: undefined,
312
336
  toolCalls: toolCalls.length ? toolCalls : undefined
@@ -319,11 +343,38 @@ export function compactForegroundDetails(details) {
319
343
  progress: details.progress ? details.progress.map(compactCompletedProgress) : undefined
320
344
  };
321
345
  }
346
+ export const MAX_STREAMED_RECENT_TOOLS = 32;
347
+ export const MAX_STREAMED_TOOL_CALLS = 64;
348
+ export const MAX_STREAMED_OUTPUT_LINE_CHARS = 2000;
349
+ export function boundStreamedRecentTools(recentTools) {
350
+ return recentTools.slice(-MAX_STREAMED_RECENT_TOOLS).map((tool) => ({ ...tool }));
351
+ }
352
+ export function boundStreamedRecentOutput(recentOutput) {
353
+ return recentOutput.map((line) => line.length > MAX_STREAMED_OUTPUT_LINE_CHARS ? `${line.slice(0, MAX_STREAMED_OUTPUT_LINE_CHARS)}… [truncated]` : line);
354
+ }
355
+ export function boundStreamedToolCalls(result) {
356
+ const summaries = result.toolCalls?.length ? result.toolCalls : extractToolCallSummaries(result.messages);
357
+ if (!summaries.length)
358
+ return;
359
+ return summaries.slice(-MAX_STREAMED_TOOL_CALLS).map((summary) => ({ ...summary }));
360
+ }
361
+ export function hasEmptyTerminalAssistantResponse(messages) {
362
+ const lastAssistant = messages.findLast((message) => message.role === "assistant");
363
+ return lastAssistant?.role === "assistant" && Array.isArray(lastAssistant.content) && lastAssistant.content.length === 0 && lastAssistant.usage.output === 0;
364
+ }
365
+ export function formatEmptyTerminalAssistantResponseError(messages) {
366
+ const lastAssistant = messages.findLast((message) => message.role === "assistant");
367
+ const errorMessage = lastAssistant && "errorMessage" in lastAssistant && typeof lastAssistant.errorMessage === "string" && lastAssistant.errorMessage.trim() ? lastAssistant.errorMessage.trim() : undefined;
368
+ if (errorMessage)
369
+ return errorMessage;
370
+ const stopReason = lastAssistant && "stopReason" in lastAssistant && typeof lastAssistant.stopReason === "string" && lastAssistant.stopReason.trim() ? lastAssistant.stopReason.trim() : undefined;
371
+ return stopReason && stopReason !== "stop" ? `Subagent produced no output after terminal assistant stopReason "${stopReason}".` : "Subagent produced no output (possible model cold-start or empty response).";
372
+ }
322
373
  export function detectSubagentError(messages) {
323
374
  let lastAssistantTextIndex = -1;
324
375
  for (let i = messages.length - 1;i >= 0; i--) {
325
376
  const msg = messages[i];
326
- if (msg.role === "assistant") {
377
+ if (msg?.role === "assistant") {
327
378
  const hasText = Array.isArray(msg.content) && msg.content.some((c) => c.type === "text" && ("text" in c) && typeof c.text === "string" && c.text.trim().length > 0);
328
379
  if (hasText) {
329
380
  lastAssistantTextIndex = i;
@@ -334,57 +385,29 @@ export function detectSubagentError(messages) {
334
385
  const scanStart = lastAssistantTextIndex >= 0 ? lastAssistantTextIndex + 1 : 0;
335
386
  for (let i = messages.length - 1;i >= scanStart; i--) {
336
387
  const msg = messages[i];
337
- if (msg.role !== "toolResult")
388
+ if (!msg || msg.role !== "toolResult")
338
389
  continue;
339
390
  const toolName = "toolName" in msg && typeof msg.toolName === "string" ? msg.toolName : undefined;
340
391
  const isError = "isError" in msg && msg.isError === true;
341
- if (isError) {
342
- const text = msg.content.find((c) => c.type === "text");
343
- const details = text && "text" in text ? text.text : undefined;
344
- const exitMatch = details?.match(/exit(?:ed)?\s*(?:with\s*)?(?:code|status)?\s*[:\s]?\s*(\d+)/i);
345
- return {
346
- hasError: true,
347
- exitCode: exitMatch ? parseInt(exitMatch[1], 10) : 1,
348
- errorType: toolName || "tool",
349
- details: details?.slice(0, 200)
350
- };
351
- }
352
- if (toolName !== "bash")
392
+ if (!isError)
353
393
  continue;
354
394
  const text = msg.content.find((c) => c.type === "text");
355
- if (!text || !("text" in text))
356
- continue;
357
- const output = text.text;
358
- const exitMatch = output.match(/exit(?:ed)?\s*(?:with\s*)?(?:code|status)?\s*[:\s]?\s*(\d+)/i);
359
- if (exitMatch) {
360
- const code = parseInt(exitMatch[1], 10);
361
- if (code !== 0) {
362
- return { hasError: true, exitCode: code, errorType: "bash", details: output.slice(0, 200) };
363
- }
364
- }
365
- const fatalPatterns = [
366
- /command not found/i,
367
- /permission denied/i,
368
- /no such file or directory/i,
369
- /segmentation fault/i,
370
- /killed|terminated/i,
371
- /out of memory/i,
372
- /connection refused/i,
373
- /timeout/i
374
- ];
375
- for (const pattern of fatalPatterns) {
376
- if (pattern.test(output)) {
377
- return { hasError: true, exitCode: 1, errorType: "bash", details: output.slice(0, 200) };
378
- }
379
- }
395
+ const details = text && "text" in text ? text.text : undefined;
396
+ const exitMatch = details?.match(/exit(?:ed)?\s*(?:with\s*)?(?:code|status)?\s*[:\s]?\s*(\d+)/i);
397
+ const exitCodeText = exitMatch?.[1];
398
+ return {
399
+ hasError: true,
400
+ exitCode: exitCodeText ? parseInt(exitCodeText, 10) : 1,
401
+ errorType: toolName || "tool",
402
+ details: details?.slice(0, 200)
403
+ };
380
404
  }
381
405
  return { hasError: false };
382
406
  }
383
407
  export function extractToolArgsPreview(args) {
384
- const truncatePreview = (value, maxLength) => value.length > maxLength ? `${value.slice(0, maxLength - 3)}...` : value;
385
408
  const stringifyPreviewValue = (value) => {
386
409
  if (typeof value === "string" && value.trim().length > 0)
387
- return value;
410
+ return sanitizeDisplayText(value);
388
411
  if (typeof value === "number" || typeof value === "boolean")
389
412
  return String(value);
390
413
  return;
@@ -398,40 +421,37 @@ export function extractToolArgsPreview(args) {
398
421
  const suffix = value.length > 1 ? ` (+${value.length - 1} more)` : "";
399
422
  return `${first}${suffix}`;
400
423
  };
401
- if (args.tool && typeof args.tool === "string") {
402
- const server = args.server && typeof args.server === "string" ? `${args.server}/` : "";
403
- const toolArgs = args.args && typeof args.args === "string" ? ` ${args.args.slice(0, 40)}` : "";
404
- return `${server}${args.tool}${toolArgs}`;
424
+ if (typeof args.tool === "string") {
425
+ const server = typeof args.server === "string" ? `${sanitizeDisplayText(args.server)}/` : "";
426
+ const toolArgs = typeof args.args === "string" ? ` ${truncateDisplayText(sanitizeDisplayText(args.args), 40)}` : "";
427
+ return sanitizeDisplayText(`${server}${args.tool}${toolArgs}`);
405
428
  }
406
429
  const queriesPreview = previewArray(args.queries);
407
430
  if (queriesPreview)
408
- return truncatePreview(queriesPreview, 60);
431
+ return previewDisplayText(queriesPreview, 60);
409
432
  if (typeof args.query === "string" && args.query.trim().length > 0)
410
- return truncatePreview(args.query, 60);
433
+ return previewDisplayText(args.query, 60);
411
434
  if (typeof args.workflow === "string" && args.workflow.trim().length > 0)
412
- return `workflow=${truncatePreview(args.workflow, 48)}`;
435
+ return `workflow=${previewDisplayText(args.workflow, 48)}`;
413
436
  if (typeof args.url === "string" && args.url.trim().length > 0)
414
- return truncatePreview(args.url, 60);
437
+ return previewDisplayText(args.url, 60);
415
438
  const urlsPreview = previewArray(args.urls);
416
439
  if (urlsPreview)
417
- return truncatePreview(urlsPreview, 60);
440
+ return previewDisplayText(urlsPreview, 60);
418
441
  if (typeof args.prompt === "string" && args.prompt.trim().length > 0)
419
- return truncatePreview(args.prompt, 60);
442
+ return previewDisplayText(args.prompt, 60);
420
443
  const previewKeys = ["command", "path", "file_path", "pattern", "query", "url", "task", "describe", "search"];
421
444
  for (const key of previewKeys) {
422
- if (args[key] && typeof args[key] === "string") {
423
- const value = args[key];
424
- return truncatePreview(value, 60);
425
- }
445
+ if (typeof args[key] === "string")
446
+ return previewDisplayText(args[key], 60);
426
447
  }
427
448
  for (const [key, value] of Object.entries(args)) {
449
+ const displayKey = sanitizeDisplayText(key);
428
450
  const arrayPreview = previewArray(value);
429
451
  if (arrayPreview)
430
- return `${key}=${truncatePreview(arrayPreview, 50)}`;
431
- if (typeof value === "string" && value.length > 0) {
432
- const preview = truncatePreview(value, 50);
433
- return `${key}=${preview}`;
434
- }
452
+ return `${displayKey}=${previewDisplayText(arrayPreview, 50)}`;
453
+ if (typeof value === "string" && value.length > 0)
454
+ return `${displayKey}=${previewDisplayText(value, 50)}`;
435
455
  }
436
456
  return "";
437
457
  }
@@ -0,0 +1,3 @@
1
+ export function shouldUseNativeFsWatch(_purpose, platform = process.platform) {
2
+ return platform !== "darwin";
3
+ }
@@ -0,0 +1,84 @@
1
+ import { stableJsonDigest } from "./launch-contract.js";
2
+ const records = new WeakMap;
3
+ function projectionDigest(input) {
4
+ return stableJsonDigest({
5
+ version: 1,
6
+ childKey: input.childKey,
7
+ agent: input.agent,
8
+ launchContractDigest: input.launchContractDigest,
9
+ context: input.context,
10
+ runner: input.runner
11
+ });
12
+ }
13
+ function required(value, label) {
14
+ if (!value.trim() || value !== value.trim())
15
+ throw new Error(`${label} must be a non-empty trimmed string.`);
16
+ return value;
17
+ }
18
+ export function createWorkflowChildPermit(input) {
19
+ const permit = Object.freeze(Object.create(null));
20
+ const record = {
21
+ issuerPackage: required(input.issuerPackage, "issuerPackage"),
22
+ workflowRunId: required(input.workflowRunId, "workflowRunId"),
23
+ childKey: required(input.childKey, "childKey"),
24
+ agent: required(input.agent, "agent"),
25
+ expectedProjectionDigest: projectionDigest({
26
+ childKey: input.childKey,
27
+ agent: input.agent,
28
+ launchContractDigest: required(input.launchContractDigest, "launchContractDigest"),
29
+ context: input.context,
30
+ runner: "dm"
31
+ }),
32
+ state: "available"
33
+ };
34
+ records.set(permit, record);
35
+ return permit;
36
+ }
37
+ export function validateWorkflowChildPermitRoot(permit, workflowRunId) {
38
+ const record = records.get(permit);
39
+ if (!record)
40
+ return "Workflow child permit is invalid.";
41
+ if (record.state !== "available")
42
+ return "Workflow child permit is already consumed.";
43
+ if (record.workflowRunId !== workflowRunId)
44
+ return "Workflow child permit does not match this workflow root.";
45
+ return;
46
+ }
47
+ export function claimWorkflowChildPermit(permit, workflowRunId, childKey) {
48
+ const record = records.get(permit);
49
+ if (!record)
50
+ return "Workflow child permit is invalid.";
51
+ if (record.state !== "available")
52
+ return "Workflow child permit is already consumed.";
53
+ if (record.workflowRunId !== workflowRunId)
54
+ return "Workflow child permit does not match this workflow root.";
55
+ record.state = record.childKey === childKey ? "claimed" : "consumed";
56
+ if (record.childKey !== childKey)
57
+ return "Workflow child permit child key mismatch.";
58
+ return;
59
+ }
60
+ export function consumeWorkflowChildPermit(permit, launch) {
61
+ const record = records.get(permit);
62
+ if (!record)
63
+ return "Workflow child permit is invalid.";
64
+ if (record.state === "available")
65
+ return "Workflow child permit launch was not claimed.";
66
+ if (record.state === "consumed")
67
+ return "Workflow child permit is already consumed.";
68
+ if (record.workflowRunId !== launch.workflowRunId)
69
+ return "Workflow child permit does not match this workflow root.";
70
+ record.state = "consumed";
71
+ if (record.childKey !== launch.childKey)
72
+ return "Workflow child permit child key mismatch.";
73
+ if (record.agent !== launch.agent)
74
+ return "Workflow child permit agent mismatch.";
75
+ if (launch.runner !== "dm")
76
+ return "Workflow child permit supports native DM children only.";
77
+ if (record.expectedProjectionDigest !== projectionDigest(launch))
78
+ return "Workflow child permit does not match the final launch projection.";
79
+ return;
80
+ }
81
+ export function workflowChildPermitConsumed(permit) {
82
+ const state = records.get(permit)?.state;
83
+ return state === "claimed" || state === "consumed";
84
+ }