@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
@@ -0,0 +1,404 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import * as fs from "node:fs";
3
+ import * as os from "node:os";
4
+ import * as path from "node:path";
5
+ import { writeAtomicJson } from "../../shared/atomic-json.js";
6
+ import {
7
+ ExternalJobProviderError,
8
+ getExternalJobProvider,
9
+ validateExternalJobHandle,
10
+ validateExternalJobResult
11
+ } from "../../api/external-job-provider.js";
12
+ export const EXTERNAL_JOB_BRIDGE_REQUEST_DIR = "external-job-requests";
13
+ const EXTERNAL_JOB_BRIDGE_RESPONSE_DIR = "external-job-responses";
14
+ const DEFAULT_OPERATION_TIMEOUT_MS = 120000;
15
+ const POLL_INTERVAL_MS = 50;
16
+ const MAX_REQUESTS_PER_SWEEP = 100;
17
+ const inFlight = new Set;
18
+ function requestDir(asyncDir) {
19
+ return path.join(asyncDir, EXTERNAL_JOB_BRIDGE_REQUEST_DIR);
20
+ }
21
+ function responseDir(asyncDir) {
22
+ return path.join(asyncDir, EXTERNAL_JOB_BRIDGE_RESPONSE_DIR);
23
+ }
24
+ function requestPath(asyncDir, id) {
25
+ return path.join(requestDir(asyncDir), `${id}.json`);
26
+ }
27
+ function isDispatchOperation(operation) {
28
+ return operation === "start" || operation === "follow-up";
29
+ }
30
+ function dispatchClaimDir(asyncDir, id) {
31
+ return path.join(requestDir(asyncDir), `${id}.claim`);
32
+ }
33
+ function dispatchClaimTempDir(asyncDir, id) {
34
+ return path.join(requestDir(asyncDir), `${id}.claim.tmp-${randomUUID()}`);
35
+ }
36
+ function dispatchClaimCompletedPath(claimDir) {
37
+ return path.join(claimDir, "completed.json");
38
+ }
39
+ function dispatchClaimHandlePath(claimDir) {
40
+ return path.join(claimDir, "handle.json");
41
+ }
42
+ function completedDispatchClaimExists(asyncDir, id) {
43
+ return fs.existsSync(dispatchClaimCompletedPath(dispatchClaimDir(asyncDir, id)));
44
+ }
45
+ function cancelDispatchRequest(asyncDir, request) {
46
+ const claimDir = dispatchClaimDir(asyncDir, request.id);
47
+ const tempClaimDir = dispatchClaimTempDir(asyncDir, request.id);
48
+ try {
49
+ fs.mkdirSync(tempClaimDir);
50
+ writeAtomicJson(dispatchClaimCompletedPath(tempClaimDir), { completedAt: Date.now() });
51
+ fs.renameSync(tempClaimDir, claimDir);
52
+ } catch (error) {
53
+ fs.rmSync(tempClaimDir, { recursive: true, force: true });
54
+ if (isClaimConflictError(error))
55
+ return false;
56
+ throw error;
57
+ }
58
+ fs.rmSync(requestPath(asyncDir, request.id), { force: true });
59
+ return true;
60
+ }
61
+ function responsePath(asyncDir, id) {
62
+ return path.join(responseDir(asyncDir), `${id}.json`);
63
+ }
64
+ function sleep(ms) {
65
+ return new Promise((resolve) => setTimeout(resolve, ms));
66
+ }
67
+ function readJson(filePath) {
68
+ return JSON.parse(fs.readFileSync(filePath, "utf-8"));
69
+ }
70
+ function processStartIdentity(pid) {
71
+ if (process.platform === "linux") {
72
+ try {
73
+ const stat = fs.readFileSync(`/proc/${pid}/stat`, "utf-8");
74
+ const commandEnd = stat.lastIndexOf(")");
75
+ if (commandEnd === -1)
76
+ return;
77
+ const fields = stat.slice(commandEnd + 1).trim().split(/\s+/);
78
+ const startTicks = fields[19];
79
+ return startTicks ? `linux:${startTicks}` : undefined;
80
+ } catch {
81
+ return;
82
+ }
83
+ }
84
+ return;
85
+ }
86
+ function processIsAlive(pid) {
87
+ try {
88
+ process.kill(pid, 0);
89
+ return true;
90
+ } catch (error) {
91
+ const code = error.code;
92
+ if (code === "ESRCH")
93
+ return false;
94
+ if (code === "EPERM")
95
+ return true;
96
+ return;
97
+ }
98
+ }
99
+ function currentClaimOwner() {
100
+ const startIdentity = processStartIdentity(process.pid);
101
+ return {
102
+ version: 1,
103
+ pid: process.pid,
104
+ hostname: os.hostname(),
105
+ claimedAt: Date.now(),
106
+ ...startIdentity ? { processStartIdentity: startIdentity } : {}
107
+ };
108
+ }
109
+ function isClaimConflictError(error) {
110
+ if (typeof error !== "object" || error === null || !("code" in error))
111
+ return false;
112
+ const code = error.code;
113
+ return code === "EEXIST" || code === "ENOTEMPTY" || code === "EPERM";
114
+ }
115
+ function isNotFoundError(error) {
116
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
117
+ }
118
+ function bridgeError(error) {
119
+ if (error instanceof ExternalJobProviderError) {
120
+ return { code: error.code, message: error.message, ...error.blockingJobId ? { blockingJobId: error.blockingJobId } : {} };
121
+ }
122
+ if (error && typeof error === "object") {
123
+ const record = error;
124
+ const code = typeof record.code === "string" && record.code.trim() ? record.code : "provider-error";
125
+ const blockingJobId = typeof record.blockingJobId === "string" && record.blockingJobId.trim() ? record.blockingJobId : undefined;
126
+ return {
127
+ code,
128
+ message: error instanceof Error ? error.message : String(error),
129
+ ...blockingJobId ? { blockingJobId } : {}
130
+ };
131
+ }
132
+ return { code: "provider-error", message: String(error) };
133
+ }
134
+ function assertRequest(value, filePath) {
135
+ if (!value || typeof value !== "object" || Array.isArray(value))
136
+ throw new Error(`External-job bridge request '${filePath}' must be an object.`);
137
+ const request = value;
138
+ if (typeof request.id !== "string" || !request.id)
139
+ throw new Error(`External-job bridge request '${filePath}' has invalid id.`);
140
+ if (request.operation !== "start" && request.operation !== "follow-up" && request.operation !== "status" && request.operation !== "result" && request.operation !== "reattach")
141
+ throw new Error(`External-job bridge request '${filePath}' has invalid operation.`);
142
+ if (typeof request.provider !== "string" || !request.provider.trim())
143
+ throw new Error(`External-job bridge request '${filePath}' has invalid provider.`);
144
+ if (typeof request.createdAt !== "number")
145
+ throw new Error(`External-job bridge request '${filePath}' has invalid createdAt.`);
146
+ if (request.claimedAt !== undefined && typeof request.claimedAt !== "number")
147
+ throw new Error(`External-job bridge request '${filePath}' has invalid claimedAt.`);
148
+ if (request.operation === "start") {
149
+ if (!request.start || typeof request.start !== "object" || Array.isArray(request.start))
150
+ throw new Error(`External-job bridge start request '${filePath}' is missing start input.`);
151
+ } else if (request.operation === "follow-up") {
152
+ if (!request.followUp || typeof request.followUp !== "object" || Array.isArray(request.followUp))
153
+ throw new Error(`External-job bridge follow-up request '${filePath}' is missing follow-up input.`);
154
+ } else if (typeof request.providerJobId !== "string" || !request.providerJobId.trim()) {
155
+ throw new Error(`External-job bridge ${request.operation} request '${filePath}' is missing providerJobId.`);
156
+ }
157
+ return request;
158
+ }
159
+ async function executeBridgeRequest(request, claimDir) {
160
+ const provider = getExternalJobProvider(request.provider);
161
+ if (!provider) {
162
+ return {
163
+ id: request.id,
164
+ ok: false,
165
+ operation: request.operation,
166
+ provider: request.provider,
167
+ code: "provider-unavailable",
168
+ message: `External-job provider '${request.provider}' is not registered. Load the Surf DM extension and its external-job provider bridge before starting this agent.`,
169
+ completedAt: Date.now()
170
+ };
171
+ }
172
+ try {
173
+ let raw;
174
+ if (request.operation === "start") {
175
+ raw = await provider.start(request.start);
176
+ } else if (request.operation === "follow-up") {
177
+ if (typeof provider.followUp !== "function") {
178
+ throw new ExternalJobProviderError(`External-job provider '${request.provider}' does not support follow-up. Update or reload the provider package, then retry action='resume'.`, { code: "follow-up-unsupported" });
179
+ }
180
+ raw = await provider.followUp(request.followUp);
181
+ } else {
182
+ raw = request.operation === "status" ? await provider.status(request.providerJobId) : request.operation === "reattach" ? await provider.reattach(request.providerJobId) : await provider.result(request.providerJobId);
183
+ }
184
+ const result = request.operation === "result" ? validateExternalJobResult(provider.name, raw, "External-job bridge result") : validateExternalJobHandle(provider.name, raw, "External-job bridge handle");
185
+ if (isDispatchOperation(request.operation) && claimDir)
186
+ writeAtomicJson(dispatchClaimHandlePath(claimDir), result);
187
+ return { id: request.id, ok: true, operation: request.operation, provider: request.provider, result, completedAt: Date.now() };
188
+ } catch (error) {
189
+ const details = bridgeError(error);
190
+ return {
191
+ id: request.id,
192
+ ok: false,
193
+ operation: request.operation,
194
+ provider: request.provider,
195
+ ...details,
196
+ completedAt: Date.now()
197
+ };
198
+ }
199
+ }
200
+ function claimDispatchRequest(asyncDir, filePath, request) {
201
+ const owner = currentClaimOwner();
202
+ const claimed = { ...request, claimedAt: owner.claimedAt };
203
+ const claimDir = dispatchClaimDir(asyncDir, request.id);
204
+ const tempClaimDir = dispatchClaimTempDir(asyncDir, request.id);
205
+ try {
206
+ fs.mkdirSync(tempClaimDir);
207
+ writeAtomicJson(path.join(tempClaimDir, "owner.json"), owner);
208
+ writeAtomicJson(path.join(tempClaimDir, "request.json"), claimed);
209
+ fs.renameSync(tempClaimDir, claimDir);
210
+ } catch (error) {
211
+ fs.rmSync(tempClaimDir, { recursive: true, force: true });
212
+ if (isClaimConflictError(error))
213
+ return;
214
+ throw error;
215
+ }
216
+ fs.rmSync(filePath, { force: true });
217
+ return { request: claimed, filePath: claimDir };
218
+ }
219
+ function parseClaimOwner(value) {
220
+ if (!value || typeof value !== "object" || Array.isArray(value))
221
+ return;
222
+ const owner = value;
223
+ if (owner.version !== 1 || typeof owner.pid !== "number" || !Number.isInteger(owner.pid) || owner.pid <= 0 || typeof owner.hostname !== "string" || typeof owner.claimedAt !== "number")
224
+ return;
225
+ if (owner.processStartIdentity !== undefined && typeof owner.processStartIdentity !== "string")
226
+ return;
227
+ return owner;
228
+ }
229
+ function claimOwnerIsDead(owner) {
230
+ if (!owner || owner.hostname !== os.hostname())
231
+ return false;
232
+ const alive = processIsAlive(owner.pid);
233
+ if (alive === false)
234
+ return true;
235
+ if (alive !== true || !owner.processStartIdentity)
236
+ return false;
237
+ const currentIdentity = processStartIdentity(owner.pid);
238
+ return currentIdentity !== undefined && currentIdentity !== owner.processStartIdentity;
239
+ }
240
+ function readClaimOwner(claimDir) {
241
+ try {
242
+ return parseClaimOwner(readJson(path.join(claimDir, "owner.json")));
243
+ } catch {
244
+ return;
245
+ }
246
+ }
247
+ function readClaimHandle(provider, claimDir) {
248
+ try {
249
+ return validateExternalJobHandle(provider, readJson(dispatchClaimHandlePath(claimDir)), "External-job bridge recovered dispatch handle");
250
+ } catch {
251
+ return;
252
+ }
253
+ }
254
+ export function serviceExternalJobBridgeRequests(asyncDir) {
255
+ let files;
256
+ try {
257
+ files = fs.readdirSync(requestDir(asyncDir), { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json") && !completedDispatchClaimExists(asyncDir, entry.name.replace(/\.json$/, "")) || entry.isDirectory() && entry.name.endsWith(".claim") && !fs.existsSync(dispatchClaimCompletedPath(path.join(requestDir(asyncDir), entry.name)))).map((entry) => entry.name).slice(0, MAX_REQUESTS_PER_SWEEP);
258
+ } catch (error) {
259
+ if (error.code === "ENOENT")
260
+ return;
261
+ throw error;
262
+ }
263
+ fs.mkdirSync(responseDir(asyncDir), { recursive: true });
264
+ for (const file of files) {
265
+ serviceExternalJobBridgeRequestFile(asyncDir, file);
266
+ }
267
+ }
268
+ export function serviceExternalJobBridgeRequestFile(asyncDir, file) {
269
+ fs.mkdirSync(responseDir(asyncDir), { recursive: true });
270
+ if (file.endsWith(".claim")) {
271
+ serviceExternalJobDispatchClaim(asyncDir, file);
272
+ return;
273
+ }
274
+ const filePath = path.join(requestDir(asyncDir), file);
275
+ let request;
276
+ try {
277
+ request = assertRequest(readJson(filePath), filePath);
278
+ } catch (error) {
279
+ if (isNotFoundError(error))
280
+ return;
281
+ const id = file.replace(/\.json$/, "");
282
+ writeAtomicJson(responsePath(asyncDir, id), {
283
+ id,
284
+ ok: false,
285
+ operation: "status",
286
+ provider: "unknown",
287
+ code: "malformed-request",
288
+ message: error instanceof Error ? error.message : String(error),
289
+ completedAt: Date.now()
290
+ });
291
+ fs.rmSync(filePath, { force: true });
292
+ return;
293
+ }
294
+ if (isDispatchOperation(request.operation) && completedDispatchClaimExists(asyncDir, request.id)) {
295
+ fs.rmSync(filePath, { force: true });
296
+ return;
297
+ }
298
+ if (inFlight.has(request.id) || fs.existsSync(responsePath(asyncDir, request.id)))
299
+ return;
300
+ if (isDispatchOperation(request.operation) && request.claimedAt !== undefined)
301
+ return;
302
+ const claimed = isDispatchOperation(request.operation) ? claimDispatchRequest(asyncDir, filePath, request) : { request, filePath };
303
+ if (!claimed)
304
+ return;
305
+ const claimedRequest = claimed.request;
306
+ inFlight.add(claimedRequest.id);
307
+ executeBridgeRequest(claimedRequest, isDispatchOperation(claimedRequest.operation) ? claimed.filePath : undefined).then((response) => {
308
+ writeAtomicJson(responsePath(asyncDir, claimedRequest.id), response);
309
+ if (isDispatchOperation(claimedRequest.operation)) {
310
+ writeAtomicJson(dispatchClaimCompletedPath(claimed.filePath), { completedAt: Date.now() });
311
+ } else {
312
+ fs.rmSync(claimed.filePath, { recursive: true, force: true });
313
+ }
314
+ }).catch((error) => {
315
+ writeAtomicJson(responsePath(asyncDir, claimedRequest.id), {
316
+ id: claimedRequest.id,
317
+ ok: false,
318
+ operation: claimedRequest.operation,
319
+ provider: claimedRequest.provider,
320
+ code: "bridge-error",
321
+ message: error instanceof Error ? error.message : String(error),
322
+ completedAt: Date.now()
323
+ });
324
+ if (isDispatchOperation(claimedRequest.operation))
325
+ writeAtomicJson(dispatchClaimCompletedPath(claimed.filePath), { completedAt: Date.now() });
326
+ }).finally(() => {
327
+ inFlight.delete(claimedRequest.id);
328
+ });
329
+ }
330
+ function serviceExternalJobDispatchClaim(asyncDir, file) {
331
+ const claimDir = path.join(requestDir(asyncDir), file);
332
+ if (fs.existsSync(dispatchClaimCompletedPath(claimDir)))
333
+ return;
334
+ const owner = readClaimOwner(claimDir);
335
+ if (!owner && fs.existsSync(requestPath(asyncDir, file.replace(/\.claim$/, ""))) && !fs.existsSync(responsePath(asyncDir, file.replace(/\.claim$/, "")))) {
336
+ fs.rmSync(claimDir, { recursive: true, force: true });
337
+ return;
338
+ }
339
+ if (!claimOwnerIsDead(owner))
340
+ return;
341
+ let request;
342
+ try {
343
+ request = assertRequest(readJson(path.join(claimDir, "request.json")), path.join(claimDir, "request.json"));
344
+ } catch {
345
+ return;
346
+ }
347
+ if (!isDispatchOperation(request.operation) || fs.existsSync(responsePath(asyncDir, request.id)))
348
+ return;
349
+ const handle = readClaimHandle(request.provider, claimDir);
350
+ if (handle) {
351
+ writeAtomicJson(responsePath(asyncDir, request.id), {
352
+ id: request.id,
353
+ ok: true,
354
+ operation: request.operation,
355
+ provider: request.provider,
356
+ result: handle,
357
+ completedAt: Date.now()
358
+ });
359
+ writeAtomicJson(dispatchClaimCompletedPath(claimDir), { completedAt: Date.now() });
360
+ fs.rmSync(requestPath(asyncDir, request.id), { force: true });
361
+ return;
362
+ }
363
+ writeAtomicJson(responsePath(asyncDir, request.id), {
364
+ id: request.id,
365
+ ok: false,
366
+ operation: request.operation,
367
+ provider: request.provider,
368
+ code: `${request.operation}-dispatch-abandoned`,
369
+ message: `External-job ${request.operation} for provider '${request.provider}' was claimed by a host process that is no longer alive before a provider job id was committed. Refusing to redispatch the prompt automatically.`,
370
+ completedAt: Date.now()
371
+ });
372
+ fs.rmSync(claimDir, { recursive: true, force: true });
373
+ fs.rmSync(requestPath(asyncDir, request.id), { force: true });
374
+ }
375
+ export async function requestExternalJobOperation(asyncDir, request, timeoutMs = DEFAULT_OPERATION_TIMEOUT_MS, cancel) {
376
+ const id = randomUUID();
377
+ fs.mkdirSync(requestDir(asyncDir), { recursive: true });
378
+ fs.mkdirSync(responseDir(asyncDir), { recursive: true });
379
+ const bridgeRequest = { ...request, id, createdAt: Date.now() };
380
+ writeAtomicJson(requestPath(asyncDir, id), bridgeRequest);
381
+ const deadline = isDispatchOperation(request.operation) ? undefined : Date.now() + timeoutMs;
382
+ const outPath = responsePath(asyncDir, id);
383
+ while (!fs.existsSync(outPath)) {
384
+ const canceled = cancel?.();
385
+ if (canceled) {
386
+ if (isDispatchOperation(request.operation) && !cancelDispatchRequest(asyncDir, bridgeRequest)) {
387
+ await sleep(POLL_INTERVAL_MS);
388
+ continue;
389
+ }
390
+ if (!isDispatchOperation(request.operation))
391
+ fs.rmSync(requestPath(asyncDir, id), { force: true });
392
+ throw canceled;
393
+ }
394
+ if (deadline !== undefined && Date.now() >= deadline) {
395
+ throw new ExternalJobProviderError(`External-job provider bridge did not respond to ${request.operation} for provider '${request.provider}' within ${timeoutMs}ms.`, { code: "bridge-timeout" });
396
+ }
397
+ await sleep(POLL_INTERVAL_MS);
398
+ }
399
+ const response = readJson(outPath);
400
+ fs.rmSync(outPath, { force: true });
401
+ if (!response.ok)
402
+ throw new ExternalJobProviderError(response.message, { code: response.code, ...response.blockingJobId ? { blockingJobId: response.blockingJobId } : {} });
403
+ return response.result;
404
+ }