@duckmind/dm-windows-x64 0.60.4 → 0.60.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/dm.exe +0 -0
  2. package/extensions/.dm-extensions.json +70 -123
  3. package/extensions/dm-9router-ext/src/index.js +410 -5
  4. package/extensions/dm-caveman/extensions/caveman.js +283 -12
  5. package/extensions/dm-cliproxy/index.js +182 -2
  6. package/extensions/dm-cliproxy/scripts/check-config-migration.js +66 -8
  7. package/extensions/dm-cliproxy/src/apply.js +228 -1
  8. package/extensions/dm-cliproxy/src/cache.js +42 -1
  9. package/extensions/dm-cliproxy/src/commands.js +50 -2
  10. package/extensions/dm-cliproxy/src/compat.js +81 -1
  11. package/extensions/dm-cliproxy/src/config.js +192 -2
  12. package/extensions/dm-cliproxy/src/conflicts.js +46 -1
  13. package/extensions/dm-cliproxy/src/fetch-models.js +190 -1
  14. package/extensions/dm-cliproxy/src/fetch-usage.js +41 -1
  15. package/extensions/dm-cliproxy/src/log.js +23 -1
  16. package/extensions/dm-cliproxy/src/status-quota.js +77 -1
  17. package/extensions/dm-cliproxy/src/ui-frame.js +50 -1
  18. package/extensions/dm-cliproxy/src/ui-hub/hub.js +199 -2
  19. package/extensions/dm-cliproxy/src/ui-hub/index.js +26 -2
  20. package/extensions/dm-cliproxy/src/ui-hub/shell.js +46 -1
  21. package/extensions/dm-cliproxy/src/ui-hub/view-diagnostics.js +69 -1
  22. package/extensions/dm-cliproxy/src/ui-hub/view-models.js +379 -1
  23. package/extensions/dm-cliproxy/src/ui-hub/view-usage.js +106 -1
  24. package/extensions/dm-cliproxy/src/ui-picker/catalog.js +41 -1
  25. package/extensions/dm-cliproxy/src/ui-picker/mutate.js +115 -1
  26. package/extensions/dm-cliproxy/src/ui-picker/prompt-confirm.js +35 -1
  27. package/extensions/dm-cliproxy/src/ui-picker/prompt-name.js +62 -1
  28. package/extensions/dm-cliproxy/src/ui-picker/providers.js +45 -1
  29. package/extensions/dm-cliproxy/src/ui-picker/render-text.js +34 -1
  30. package/extensions/dm-cliproxy/src/ui-picker/rows.js +57 -1
  31. package/extensions/dm-cliproxy/src/ui-setup.js +260 -2
  32. package/extensions/dm-cliproxy/src/ui-usage.js +151 -1
  33. package/extensions/dm-cliproxy/src/usage-shared-cache.js +97 -1
  34. package/extensions/dm-context/src/context.js +144 -1
  35. package/extensions/dm-context/src/index.js +339 -7
  36. package/extensions/dm-context/src/utils.js +9 -1
  37. package/extensions/dm-cua/bin/browser-cua.mjs +73 -8
  38. package/extensions/dm-cua/index.js +75 -6
  39. package/extensions/dm-cua/src/browser-cua-lib.mjs +490 -6
  40. package/extensions/dm-cua/src/browser-install.mjs +331 -2
  41. package/extensions/dm-fff/src/index.js +688 -12
  42. package/extensions/dm-fff/src/query.js +60 -1
  43. package/extensions/dm-goal/src/goal.js +894 -23
  44. package/extensions/dm-image2/index.js +103 -9
  45. package/extensions/dm-image2/src/image-lib.mjs +1275 -8
  46. package/extensions/dm-subagents/install.mjs +62 -8
  47. package/extensions/dm-subagents/src/agents/agent-management.js +1190 -36
  48. package/extensions/dm-subagents/src/agents/agent-memory.js +216 -6
  49. package/extensions/dm-subagents/src/agents/agent-scope.js +5 -1
  50. package/extensions/dm-subagents/src/agents/agent-selection.js +20 -1
  51. package/extensions/dm-subagents/src/agents/agent-serializer.js +120 -5
  52. package/extensions/dm-subagents/src/agents/agents.js +1139 -11
  53. package/extensions/dm-subagents/src/agents/chain-serializer.js +299 -11
  54. package/extensions/dm-subagents/src/agents/frontmatter.js +65 -6
  55. package/extensions/dm-subagents/src/agents/identity.js +29 -1
  56. package/extensions/dm-subagents/src/agents/proactive-skills.js +141 -1
  57. package/extensions/dm-subagents/src/agents/skills.js +614 -6
  58. package/extensions/dm-subagents/src/extension/config.js +35 -2
  59. package/extensions/dm-subagents/src/extension/control-notices.js +69 -4
  60. package/extensions/dm-subagents/src/extension/doctor.js +172 -15
  61. package/extensions/dm-subagents/src/extension/fanout-child.js +158 -231
  62. package/extensions/dm-subagents/src/extension/index.js +521 -359
  63. package/extensions/dm-subagents/src/extension/rpc.js +266 -7
  64. package/extensions/dm-subagents/src/extension/schemas.js +275 -1
  65. package/extensions/dm-subagents/src/extension/tool-description.js +111 -6
  66. package/extensions/dm-subagents/src/intercom/intercom-bridge.js +126 -4
  67. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +452 -5
  68. package/extensions/dm-subagents/src/intercom/result-intercom.js +319 -3
  69. package/extensions/dm-subagents/src/profiles/profiles.js +458 -3
  70. package/extensions/dm-subagents/src/runs/background/async-execution.js +834 -40
  71. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +435 -14
  72. package/extensions/dm-subagents/src/runs/background/async-resume.js +334 -8
  73. package/extensions/dm-subagents/src/runs/background/async-status.js +313 -12
  74. package/extensions/dm-subagents/src/runs/background/chain-append.js +245 -2
  75. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +136 -1
  76. package/extensions/dm-subagents/src/runs/background/completion-batcher.js +94 -1
  77. package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +54 -1
  78. package/extensions/dm-subagents/src/runs/background/control-channel.js +190 -1
  79. package/extensions/dm-subagents/src/runs/background/fleet-view.js +483 -17
  80. package/extensions/dm-subagents/src/runs/background/notify.js +129 -3
  81. package/extensions/dm-subagents/src/runs/background/parallel-groups.js +34 -1
  82. package/extensions/dm-subagents/src/runs/background/result-watcher.js +236 -6
  83. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +76 -4
  84. package/extensions/dm-subagents/src/runs/background/run-status.js +427 -23
  85. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +487 -4
  86. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +306 -9
  87. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +2849 -73
  88. package/extensions/dm-subagents/src/runs/background/top-level-async.js +5 -1
  89. package/extensions/dm-subagents/src/runs/background/wait.js +206 -11
  90. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +1013 -12
  91. package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +980 -101
  92. package/extensions/dm-subagents/src/runs/foreground/execution.js +1165 -45
  93. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +3157 -222
  94. package/extensions/dm-subagents/src/runs/shared/acceptance.js +835 -3
  95. package/extensions/dm-subagents/src/runs/shared/chain-outputs.js +104 -1
  96. package/extensions/dm-subagents/src/runs/shared/completion-guard.js +116 -3
  97. package/extensions/dm-subagents/src/runs/shared/dm-args.js +208 -1
  98. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +90 -1
  99. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +282 -1
  100. package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +148 -1
  101. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +305 -1
  102. package/extensions/dm-subagents/src/runs/shared/model-fallback.js +194 -1
  103. package/extensions/dm-subagents/src/runs/shared/model-scope.js +65 -1
  104. package/extensions/dm-subagents/src/runs/shared/nested-events.js +851 -8
  105. package/extensions/dm-subagents/src/runs/shared/nested-path.js +41 -1
  106. package/extensions/dm-subagents/src/runs/shared/nested-render.js +105 -1
  107. package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +81 -4
  108. package/extensions/dm-subagents/src/runs/shared/run-history.js +51 -4
  109. package/extensions/dm-subagents/src/runs/shared/single-output.js +149 -8
  110. package/extensions/dm-subagents/src/runs/shared/structured-output.js +58 -1
  111. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +166 -5
  112. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +329 -13
  113. package/extensions/dm-subagents/src/runs/shared/tool-budget.js +73 -1
  114. package/extensions/dm-subagents/src/runs/shared/turn-budget.js +47 -4
  115. package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +196 -1
  116. package/extensions/dm-subagents/src/runs/shared/worktree.js +435 -3
  117. package/extensions/dm-subagents/src/shared/artifacts.js +92 -2
  118. package/extensions/dm-subagents/src/shared/atomic-json.js +55 -1
  119. package/extensions/dm-subagents/src/shared/child-transcript.js +167 -5
  120. package/extensions/dm-subagents/src/shared/file-coalescer.js +25 -1
  121. package/extensions/dm-subagents/src/shared/fork-context.js +147 -4
  122. package/extensions/dm-subagents/src/shared/formatters.js +98 -7
  123. package/extensions/dm-subagents/src/shared/jsonl-writer.js +56 -2
  124. package/extensions/dm-subagents/src/shared/model-info.js +62 -1
  125. package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +68 -1
  126. package/extensions/dm-subagents/src/shared/session-identity.js +6 -1
  127. package/extensions/dm-subagents/src/shared/session-tokens.js +39 -2
  128. package/extensions/dm-subagents/src/shared/settings.js +198 -11
  129. package/extensions/dm-subagents/src/shared/status-format.js +53 -1
  130. package/extensions/dm-subagents/src/shared/types.js +184 -6
  131. package/extensions/dm-subagents/src/shared/utils.js +462 -2
  132. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +288 -1
  133. package/extensions/dm-subagents/src/slash/prompt-workflows.js +297 -7
  134. package/extensions/dm-subagents/src/slash/slash-bridge.js +118 -1
  135. package/extensions/dm-subagents/src/slash/slash-commands.js +1287 -31
  136. package/extensions/dm-subagents/src/slash/slash-live-state.js +240 -4
  137. package/extensions/dm-subagents/src/tui/render-helpers.js +64 -1
  138. package/extensions/dm-subagents/src/tui/render.js +1542 -4
  139. package/extensions/dm-usage/index.js +1294 -9
  140. package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +40 -9
  141. package/extensions/greedysearch-dm/bin/cdp-headless.mjs +5 -2
  142. package/extensions/greedysearch-dm/bin/cdp-visible.mjs +5 -2
  143. package/extensions/greedysearch-dm/bin/cdp.mjs +896 -30
  144. package/extensions/greedysearch-dm/bin/gschrome.mjs +30 -2
  145. package/extensions/greedysearch-dm/bin/kill-visible.mjs +7 -2
  146. package/extensions/greedysearch-dm/bin/launch-visible.mjs +13 -2
  147. package/extensions/greedysearch-dm/bin/launch.mjs +282 -10
  148. package/extensions/greedysearch-dm/bin/mcp.mjs +386 -361
  149. package/extensions/greedysearch-dm/bin/search.mjs +620 -540
  150. package/extensions/greedysearch-dm/bin/visible.mjs +22 -2
  151. package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +329 -579
  152. package/extensions/greedysearch-dm/extractors/chatgpt.mjs +301 -583
  153. package/extensions/greedysearch-dm/extractors/common.mjs +408 -32
  154. package/extensions/greedysearch-dm/extractors/consensus.mjs +376 -365
  155. package/extensions/greedysearch-dm/extractors/consent.mjs +303 -14
  156. package/extensions/greedysearch-dm/extractors/gemini.mjs +228 -592
  157. package/extensions/greedysearch-dm/extractors/google-ai.mjs +78 -499
  158. package/extensions/greedysearch-dm/extractors/logically.mjs +270 -347
  159. package/extensions/greedysearch-dm/extractors/perplexity.mjs +243 -581
  160. package/extensions/greedysearch-dm/extractors/selectors.mjs +32 -1
  161. package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +130 -317
  162. package/extensions/greedysearch-dm/index.js +123 -23
  163. package/extensions/greedysearch-dm/src/fetcher.mjs +576 -2
  164. package/extensions/greedysearch-dm/src/formatters/results.js +95 -10
  165. package/extensions/greedysearch-dm/src/formatters/sources.js +57 -1
  166. package/extensions/greedysearch-dm/src/formatters/synthesis.js +49 -1
  167. package/extensions/greedysearch-dm/src/github.mjs +222 -7
  168. package/extensions/greedysearch-dm/src/reddit.mjs +145 -14
  169. package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +340 -9
  170. package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +112 -4
  171. package/extensions/greedysearch-dm/src/search/chrome.mjs +486 -285
  172. package/extensions/greedysearch-dm/src/search/constants.mjs +109 -8
  173. package/extensions/greedysearch-dm/src/search/defaults.mjs +10 -1
  174. package/extensions/greedysearch-dm/src/search/engines.mjs +79 -9
  175. package/extensions/greedysearch-dm/src/search/fetch-source.mjs +441 -349
  176. package/extensions/greedysearch-dm/src/search/file-sources.mjs +29 -7
  177. package/extensions/greedysearch-dm/src/search/minimize.mjs +86 -1
  178. package/extensions/greedysearch-dm/src/search/output.mjs +51 -5
  179. package/extensions/greedysearch-dm/src/search/paths.mjs +48 -1
  180. package/extensions/greedysearch-dm/src/search/pdf.mjs +63 -2
  181. package/extensions/greedysearch-dm/src/search/port-pid.mjs +69 -1
  182. package/extensions/greedysearch-dm/src/search/progress.mjs +109 -2
  183. package/extensions/greedysearch-dm/src/search/query.mjs +21 -1
  184. package/extensions/greedysearch-dm/src/search/recovery.mjs +49 -1
  185. package/extensions/greedysearch-dm/src/search/research.mjs +2227 -458
  186. package/extensions/greedysearch-dm/src/search/scale-aware.mjs +61 -11
  187. package/extensions/greedysearch-dm/src/search/simple-research.mjs +396 -805
  188. package/extensions/greedysearch-dm/src/search/sources.mjs +412 -1
  189. package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +127 -12
  190. package/extensions/greedysearch-dm/src/search/synthesis.mjs +202 -12
  191. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +209 -23
  192. package/extensions/greedysearch-dm/src/tools/shared.js +226 -10
  193. package/extensions/greedysearch-dm/src/utils/content.mjs +35 -4
  194. package/extensions/greedysearch-dm/src/utils/helpers.js +22 -1
  195. package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +10 -1
  196. package/extensions/greedysearch-dm/src/utils/system-cmds.mjs +61 -1
  197. package/package.json +1 -1
@@ -1 +1,190 @@
1
- import{randomUUID as I}from"node:crypto";import*as J from"node:fs";import*as H from"node:path";import*as w from"node:fs";import*as B from"node:path";var S=[10,25,50,100,200,500,1000,2000,4000],x=new Set(["EACCES","EBUSY","EPERM"]),k=typeof SharedArrayBuffer<"u"?new SharedArrayBuffer(4):void 0,_=k?new Int32Array(k):void 0;function v(K){if(K<=0)return;if(_)try{Atomics.wait(_,0,0,K);return}catch{}let Z=Date.now()+K;while(Date.now()<Z);}function R(K){let Z=K?.code;return typeof Z==="string"&&x.has(Z)}function g(K,Z,$,C,j){for(let X=0;;X++)try{K.renameSync(Z,$);return}catch(Q){let G=C[X];if(G===void 0||!R(Q))throw Q;j(G)}}function q(K={}){let Z=K.fs??w,$=K.now??Date.now,C=K.pid??process.pid,j=K.random??Math.random,Q=K.retryRenameErrors??process.platform==="win32"?K.retryDelaysMs??S:[],G=K.wait??v;return(Y,W)=>{Z.mkdirSync(B.dirname(Y),{recursive:!0});let L=B.join(B.dirname(Y),`.${B.basename(Y)}.${C}.${$()}.${j().toString(36).slice(2)}.tmp`);try{Z.writeFileSync(L,JSON.stringify(W,null,2),"utf-8"),g(Z,L,Y,Q,G)}finally{Z.rmSync(L,{force:!0})}}}var F=q();import*as O from"node:os";import*as V from"node:path";function N(K){return K.trim().replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}function P(K){let Z=K?.env??process.env,$=K&&Object.hasOwn(K,"getuid")?K.getuid:process.getuid?.bind(process);if(typeof $==="function")return`uid-${$()}`;for(let Q of["USERNAME","USER","LOGNAME"]){let G=Z[Q];if(G)return`user-${N(G)}`}let C=K&&Object.hasOwn(K,"userInfo")?K.userInfo:O.userInfo;try{let Q=C?.().username;if(Q)return`user-${N(Q)}`}catch{}let j=Z.USERPROFILE??Z.HOME;if(j)return`home-${N(j)}`;let X=K&&Object.hasOwn(K,"homedir")?K.homedir:O.homedir;try{let Q=X?.();if(Q)return`home-${N(Q)}`}catch{}return"shared"}var U=V.join(O.tmpdir(),`dm-subagents-${P()}`),i=V.join(U,"async-subagent-results"),s=V.join(U,"async-subagent-runs"),a=V.join(U,"chain-runs"),t=V.join(U,"artifacts");var A=250;var D=process.platform==="win32"?"SIGBREAK":"SIGUSR2",h="steer-requests",f="steer-targets";function z(K){return H.join(K,"control")}function T(K){return H.join(z(K),"interrupt.json")}function M(K){return H.join(z(K),"timeout.json")}function b(K){return H.join(z(K),h)}function m(K,Z){return H.join(z(K),f,String(Z))}function y(K){return`${String(K.ts).padStart(13,"0")}-${Buffer.from(K.id).toString("base64url")}.json`}function E(K,Z){let $=H.join(K,y(Z));return F($,Z),$}function c(K,Z={},$={}){let C=T(K),j={...Z,ts:Z.ts??$.now?.()??Date.now(),type:"interrupt"};return F(C,j),C}function d(K,Z={},$={}){let C=M(K),j={...Z,ts:Z.ts??$.now?.()??Date.now(),type:"timeout"};return F(C,j),C}function jK(K,Z,$={}){let C=Z.message.trim();if(!C)throw Error("steer message must not be empty.");if(Z.targetIndex!==void 0&&(!Number.isInteger(Z.targetIndex)||Z.targetIndex<0))throw Error("steer targetIndex must be a non-negative integer.");let j={type:"steer",id:Z.id??$.randomId?.()??I(),ts:Z.ts??$.now?.()??Date.now(),message:C,...Z.targetIndex!==void 0?{targetIndex:Z.targetIndex}:{},...Z.source?{source:Z.source}:{}};return E(b(K),j)}function CK(K,Z,$){if(!Number.isInteger(Z)||Z<0)throw Error("steer child index must be a non-negative integer.");return E(m(K,Z),{...$,targetIndex:Z,type:"steer"})}function l(K){if(!K||typeof K!=="object"||Array.isArray(K))return;let Z=K;if(Z.type!=="steer")return;if(typeof Z.id!=="string"||!Z.id.trim())return;if(typeof Z.ts!=="number"||!Number.isFinite(Z.ts))return;if(typeof Z.message!=="string"||!Z.message.trim())return;if(Z.targetIndex!==void 0&&(!Number.isInteger(Z.targetIndex)||Z.targetIndex<0))return;return{type:"steer",id:Z.id.trim(),ts:Z.ts,message:Z.message.trim(),...Z.targetIndex!==void 0?{targetIndex:Z.targetIndex}:{},...typeof Z.source==="string"&&Z.source.trim()?{source:Z.source}:{}}}function u(K,Z=J){if(!Z.existsSync(K))return[];let $=[];for(let C of Z.readdirSync(K).filter((j)=>j.endsWith(".json")).sort()){let j=H.join(K,C),X;try{X=l(JSON.parse(Z.readFileSync(j,"utf-8")))}catch{X=void 0}try{Z.rmSync(j,{recursive:!0})}catch{continue}if(X)$.push(X)}return $.sort((C,j)=>C.ts-j.ts||C.id.localeCompare(j.id))}function o(K,Z=J){return u(b(K),Z)}function n(K,Z=J){let $=T(K);if(!Z.existsSync($))return!1;try{Z.rmSync($,{force:!0,recursive:!0})}catch{}return!0}function p(K,Z=J){let $=M(K);if(!Z.existsSync($))return!1;try{Z.rmSync($,{force:!0,recursive:!0})}catch{}return!0}function QK(K){let Z=c(K.asyncDir,K.source?{source:K.source}:{},{now:K.now});if(typeof K.pid==="number"&&K.pid>0)try{(K.kill??process.kill)(K.pid,K.signal??D)}catch($){if($?.code==="ENOSYS")return;try{J.rmSync(Z,{force:!0})}catch{}throw $}}function XK(K){d(K.asyncDir,K.source?{source:K.source}:{},{now:K.now})}function GK(K,Z){let $=Z.fs??J,C=Z.timers??{setInterval,clearInterval},j=z(K);try{$.mkdirSync(j,{recursive:!0})}catch{}let X=!1,Q=()=>{if(X)return;try{if(p(K,$))Z.onTimeout?.();if(n(K,$))Z.onInterrupt();for(let W of o(K,$))Z.onSteer?.(W)}catch{}};Q();let G;try{G=$.watch(j,()=>Q()),G.on?.("error",()=>{})}catch{G=void 0}let Y=C.setInterval(Q,Z.pollIntervalMs??A);return Y.unref?.(),()=>{if(X)return;X=!0;try{G?.close()}catch{}C.clearInterval(Y)}}export{E as writeSteerRequestToDir,GK as watchAsyncControlInbox,M as timeoutRequestPath,m as stepSteerInboxDir,b as steerRequestsDir,d as requestAsyncTimeout,jK as requestAsyncSteer,c as requestAsyncInterrupt,T as interruptRequestPath,CK as enqueueStepSteer,XK as deliverTimeoutRequest,QK as deliverInterruptRequest,z as controlInboxDir,p as consumeTimeoutRequest,u as consumeSteerRequestsFromDir,o as consumeSteerRequests,n as consumeInterruptRequest,D as INTERRUPT_SIGNAL};
1
+ import { randomUUID } from "node:crypto";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { writeAtomicJson } from "../../shared/atomic-json.js";
5
+ import { POLL_INTERVAL_MS } from "../../shared/types.js";
6
+ export const INTERRUPT_SIGNAL = process.platform === "win32" ? "SIGBREAK" : "SIGUSR2";
7
+ const STEER_REQUESTS_DIR = "steer-requests";
8
+ const STEER_TARGETS_DIR = "steer-targets";
9
+ export function controlInboxDir(asyncDir) {
10
+ return path.join(asyncDir, "control");
11
+ }
12
+ export function interruptRequestPath(asyncDir) {
13
+ return path.join(controlInboxDir(asyncDir), "interrupt.json");
14
+ }
15
+ export function timeoutRequestPath(asyncDir) {
16
+ return path.join(controlInboxDir(asyncDir), "timeout.json");
17
+ }
18
+ export function steerRequestsDir(asyncDir) {
19
+ return path.join(controlInboxDir(asyncDir), STEER_REQUESTS_DIR);
20
+ }
21
+ export function stepSteerInboxDir(asyncDir, index) {
22
+ return path.join(controlInboxDir(asyncDir), STEER_TARGETS_DIR, String(index));
23
+ }
24
+ function steerRequestFileName(request) {
25
+ return `${String(request.ts).padStart(13, "0")}-${Buffer.from(request.id).toString("base64url")}.json`;
26
+ }
27
+ export function writeSteerRequestToDir(dir, request) {
28
+ const requestPath = path.join(dir, steerRequestFileName(request));
29
+ writeAtomicJson(requestPath, request);
30
+ return requestPath;
31
+ }
32
+ export function requestAsyncInterrupt(asyncDir, payload = {}, deps = {}) {
33
+ const requestPath = interruptRequestPath(asyncDir);
34
+ const request = { ...payload, ts: payload.ts ?? deps.now?.() ?? Date.now(), type: "interrupt" };
35
+ writeAtomicJson(requestPath, request);
36
+ return requestPath;
37
+ }
38
+ export function requestAsyncTimeout(asyncDir, payload = {}, deps = {}) {
39
+ const requestPath = timeoutRequestPath(asyncDir);
40
+ const request = { ...payload, ts: payload.ts ?? deps.now?.() ?? Date.now(), type: "timeout" };
41
+ writeAtomicJson(requestPath, request);
42
+ return requestPath;
43
+ }
44
+ export function requestAsyncSteer(asyncDir, payload, deps = {}) {
45
+ const message = payload.message.trim();
46
+ if (!message)
47
+ throw new Error("steer message must not be empty.");
48
+ if (payload.targetIndex !== undefined && (!Number.isInteger(payload.targetIndex) || payload.targetIndex < 0)) {
49
+ throw new Error("steer targetIndex must be a non-negative integer.");
50
+ }
51
+ const request = {
52
+ type: "steer",
53
+ id: payload.id ?? deps.randomId?.() ?? randomUUID(),
54
+ ts: payload.ts ?? deps.now?.() ?? Date.now(),
55
+ message,
56
+ ...payload.targetIndex !== undefined ? { targetIndex: payload.targetIndex } : {},
57
+ ...payload.source ? { source: payload.source } : {}
58
+ };
59
+ return writeSteerRequestToDir(steerRequestsDir(asyncDir), request);
60
+ }
61
+ export function enqueueStepSteer(asyncDir, index, request) {
62
+ if (!Number.isInteger(index) || index < 0)
63
+ throw new Error("steer child index must be a non-negative integer.");
64
+ return writeSteerRequestToDir(stepSteerInboxDir(asyncDir, index), { ...request, targetIndex: index, type: "steer" });
65
+ }
66
+ function parseSteerRequest(raw) {
67
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
68
+ return;
69
+ const input = raw;
70
+ if (input.type !== "steer")
71
+ return;
72
+ if (typeof input.id !== "string" || !input.id.trim())
73
+ return;
74
+ if (typeof input.ts !== "number" || !Number.isFinite(input.ts))
75
+ return;
76
+ if (typeof input.message !== "string" || !input.message.trim())
77
+ return;
78
+ if (input.targetIndex !== undefined && (!Number.isInteger(input.targetIndex) || input.targetIndex < 0))
79
+ return;
80
+ return {
81
+ type: "steer",
82
+ id: input.id.trim(),
83
+ ts: input.ts,
84
+ message: input.message.trim(),
85
+ ...input.targetIndex !== undefined ? { targetIndex: input.targetIndex } : {},
86
+ ...typeof input.source === "string" && input.source.trim() ? { source: input.source } : {}
87
+ };
88
+ }
89
+ export function consumeSteerRequestsFromDir(dir, fsImpl = fs) {
90
+ if (!fsImpl.existsSync(dir))
91
+ return [];
92
+ const requests = [];
93
+ for (const entry of fsImpl.readdirSync(dir).filter((name) => name.endsWith(".json")).sort()) {
94
+ const requestPath = path.join(dir, entry);
95
+ let parsed;
96
+ try {
97
+ parsed = parseSteerRequest(JSON.parse(fsImpl.readFileSync(requestPath, "utf-8")));
98
+ } catch {
99
+ parsed = undefined;
100
+ }
101
+ try {
102
+ fsImpl.rmSync(requestPath, { recursive: true });
103
+ } catch {
104
+ continue;
105
+ }
106
+ if (parsed)
107
+ requests.push(parsed);
108
+ }
109
+ return requests.sort((left, right) => left.ts - right.ts || left.id.localeCompare(right.id));
110
+ }
111
+ export function consumeSteerRequests(asyncDir, fsImpl = fs) {
112
+ return consumeSteerRequestsFromDir(steerRequestsDir(asyncDir), fsImpl);
113
+ }
114
+ export function consumeInterruptRequest(asyncDir, fsImpl = fs) {
115
+ const requestPath = interruptRequestPath(asyncDir);
116
+ if (!fsImpl.existsSync(requestPath))
117
+ return false;
118
+ try {
119
+ fsImpl.rmSync(requestPath, { force: true, recursive: true });
120
+ } catch {}
121
+ return true;
122
+ }
123
+ export function consumeTimeoutRequest(asyncDir, fsImpl = fs) {
124
+ const requestPath = timeoutRequestPath(asyncDir);
125
+ if (!fsImpl.existsSync(requestPath))
126
+ return false;
127
+ try {
128
+ fsImpl.rmSync(requestPath, { force: true, recursive: true });
129
+ } catch {}
130
+ return true;
131
+ }
132
+ export function deliverInterruptRequest(input) {
133
+ const requestPath = requestAsyncInterrupt(input.asyncDir, input.source ? { source: input.source } : {}, { now: input.now });
134
+ if (typeof input.pid === "number" && input.pid > 0) {
135
+ try {
136
+ (input.kill ?? process.kill)(input.pid, input.signal ?? INTERRUPT_SIGNAL);
137
+ } catch (error) {
138
+ if (error?.code === "ENOSYS") {
139
+ return;
140
+ }
141
+ try {
142
+ fs.rmSync(requestPath, { force: true });
143
+ } catch {}
144
+ throw error;
145
+ }
146
+ }
147
+ }
148
+ export function deliverTimeoutRequest(input) {
149
+ requestAsyncTimeout(input.asyncDir, input.source ? { source: input.source } : {}, { now: input.now });
150
+ }
151
+ export function watchAsyncControlInbox(asyncDir, opts) {
152
+ const fsImpl = opts.fs ?? fs;
153
+ const timers = opts.timers ?? { setInterval, clearInterval };
154
+ const dir = controlInboxDir(asyncDir);
155
+ try {
156
+ fsImpl.mkdirSync(dir, { recursive: true });
157
+ } catch {}
158
+ let disposed = false;
159
+ const check = () => {
160
+ if (disposed)
161
+ return;
162
+ try {
163
+ if (consumeTimeoutRequest(asyncDir, fsImpl))
164
+ opts.onTimeout?.();
165
+ if (consumeInterruptRequest(asyncDir, fsImpl))
166
+ opts.onInterrupt();
167
+ for (const request of consumeSteerRequests(asyncDir, fsImpl))
168
+ opts.onSteer?.(request);
169
+ } catch {}
170
+ };
171
+ check();
172
+ let watcher;
173
+ try {
174
+ watcher = fsImpl.watch(dir, () => check());
175
+ watcher.on?.("error", () => {});
176
+ } catch {
177
+ watcher = undefined;
178
+ }
179
+ const interval = timers.setInterval(check, opts.pollIntervalMs ?? POLL_INTERVAL_MS);
180
+ interval.unref?.();
181
+ return () => {
182
+ if (disposed)
183
+ return;
184
+ disposed = true;
185
+ try {
186
+ watcher?.close();
187
+ } catch {}
188
+ timers.clearInterval(interval);
189
+ };
190
+ }