@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,5 +1,452 @@
1
- import{randomUUID as Qj}from"node:crypto";import*as W from"node:fs";import*as U from"node:path";import{Type as Y}from"typebox";import*as K from"node:path";import{fileURLToPath as c}from"node:url";import*as V from"node:os";import*as T from"node:path";import*as L from"node:os";import*as C from"node:path";function z(j){return j.trim().replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}function l(j){let $=j?.env??process.env,f=j&&Object.hasOwn(j,"getuid")?j.getuid:process.getuid?.bind(process);if(typeof f==="function")return`uid-${f()}`;for(let Q of["USERNAME","USER","LOGNAME"]){let O=$[Q];if(O)return`user-${z(O)}`}let J=j&&Object.hasOwn(j,"userInfo")?j.userInfo:L.userInfo;try{let Q=J?.().username;if(Q)return`user-${z(Q)}`}catch{}let B=$.USERPROFILE??$.HOME;if(B)return`home-${z(B)}`;let Z=j&&Object.hasOwn(j,"homedir")?j.homedir:L.homedir;try{let Q=Z?.();if(Q)return`home-${z(Q)}`}catch{}return"shared"}var A=C.join(L.tmpdir(),`dm-subagents-${l()}`),cj=C.join(A,"async-subagent-results"),qj=C.join(A,"async-subagent-runs"),s=C.join(A,"chain-runs"),Ij=C.join(A,"artifacts");var w=250;var f$=T.join(V.homedir(),".config","mcp","mcp.json"),J$={cursor:[T.join(V.homedir(),".cursor","mcp.json")],"claude-code":[T.join(V.homedir(),".claude","mcp.json"),T.join(V.homedir(),".claude.json"),T.join(V.homedir(),".claude","claude_desktop_config.json")],"claude-desktop":[T.join(V.homedir(),"Library","Application Support","Claude","claude_desktop_config.json")],codex:[T.join(V.homedir(),".codex","config.json")],windsurf:[T.join(V.homedir(),".windsurf","mcp.json")],vscode:[".vscode/mcp.json"]};import{Compile as Q$}from"typebox/compile";function q(j,$){let f=c(j),J=K.extname(f),B=[".js",".mjs",".cjs",".ts",".mts",".cts"].includes(J)?J:".ts";return K.join(K.dirname(f),`${$}${B}`)}function I(j){return K.basename(c(j)).startsWith("dm-args.")}function i(j=import.meta.url){let $=I(j)?"subagent-prompt-runtime":K.join("..","runs","shared","subagent-prompt-runtime");return q(j,$)}function a(j=import.meta.url){let $=I(j)?K.join("..","..","extension","fanout-child"):"fanout-child";return q(j,$)}var z$=i(),b$=a();var x="DM_SUBAGENT_ORCHESTRATOR_TARGET",D="DM_SUBAGENT_ORCHESTRATOR_SESSION_ID",v="DM_SUBAGENT_SUPERVISOR_CHANNEL_DIR",P="DM_SUBAGENT_RUN_ID",k="DM_SUBAGENT_CHILD_AGENT",o="DM_SUBAGENT_CHILD_INDEX";import*as e from"node:fs";import*as _ from"node:path";var jj=[10,25,50,100,200,500,1000,2000,4000],$j=new Set(["EACCES","EBUSY","EPERM"]),h=typeof SharedArrayBuffer<"u"?new SharedArrayBuffer(4):void 0,g=h?new Int32Array(h):void 0;function fj(j){if(j<=0)return;if(g)try{Atomics.wait(g,0,0,j);return}catch{}let $=Date.now()+j;while(Date.now()<$);}function Jj(j){let $=j?.code;return typeof $==="string"&&$j.has($)}function Bj(j,$,f,J,B){for(let Z=0;;Z++)try{j.renameSync($,f);return}catch(Q){let O=J[Z];if(O===void 0||!Jj(Q))throw Q;B(O)}}function Zj(j={}){let $=j.fs??e,f=j.now??Date.now,J=j.pid??process.pid,B=j.random??Math.random,Q=j.retryRenameErrors??process.platform==="win32"?j.retryDelaysMs??jj:[],O=j.wait??fj;return(G,H)=>{$.mkdirSync(_.dirname(G),{recursive:!0});let X=_.join(_.dirname(G),`.${_.basename(G)}.${J}.${f()}.${B().toString(36).slice(2)}.tmp`);try{$.writeFileSync(X,JSON.stringify(H,null,2),"utf-8"),Bj($,X,G,Q,O)}finally{$.rmSync(X,{force:!0})}}}var R=Zj();var b=U.join(A,"supervisor-channels"),y="requests",n="replies",E="subagent_supervisor",Xj=65536,Oj=600000,Yj=Math.min(w,500),Wj=Y.Object({reason:Y.String({enum:["need_decision","interview_request","progress_update"]}),message:Y.Optional(Y.String()),interview:Y.Optional(Y.Unsafe({type:"object",additionalProperties:!0}))},{additionalProperties:!1}),d=Y.Object({action:Y.String({enum:["list","send","ask","reply","pending","status"]}),to:Y.Optional(Y.String()),message:Y.Optional(Y.String()),replyTo:Y.Optional(Y.String())},{additionalProperties:!1});function F(j){return j.trim().replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}function c$(j,$,f){return U.join(b,`${F(j)}-${F($)}-${f}`)}function Tj(j){W.mkdirSync(U.join(j,y),{recursive:!0,mode:448}),W.mkdirSync(U.join(j,n),{recursive:!0,mode:448})}function Kj(j,$){return U.join(j,y,`${F($)}.json`)}function u(j,$){return U.join(j,n,`${F($)}.json`)}function M(j){let $=process.env[j]?.trim();return $?$:void 0}function r(){let j=M(v),$=M(P),f=M(k),J=M(o),B=M(D);if(!j||!$||!f||!B||J===void 0||!/^\d+$/.test(J))return;return{channelDir:j,runId:$,agent:f,childIndex:Number(J),orchestratorTarget:M(x),orchestratorSessionId:B,childTarget:M("DM_SUBAGENT_INTERCOM_SESSION_NAME")}}function Uj(j){if(j==="interview_request")return"Subagent requests a structured supervisor interview.";if(j==="progress_update")return"Subagent progress update.";return"Subagent needs a supervisor decision."}function Gj(j){let $=[Uj(j.reason),`Run: ${j.runId}`,`Agent: ${j.agent}`,`Child index: ${j.childIndex}`];if(j.childTarget)$.push(`Child intercom target: ${j.childTarget}`);if($.push(""),j.message?.trim())$.push(j.message.trim());if(j.reason==="interview_request"){if($.push("","Structured response requested. Reply with JSON, optionally fenced in ```json, matching the requested interview shape."),j.interview!==void 0)$.push(JSON.stringify(j.interview,null,"\t"))}return $.join(`
2
- `).trimEnd()}function Hj(j){let $=j.trim(),f=$.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i)?.[1]?.trim();try{return{value:JSON.parse(f??$)}}catch(J){return{error:J instanceof Error?`${J.name}: ${J.message}`:String(J)}}}function Vj(){let j=Number(process.env.PI_INTERCOM_ASK_TIMEOUT_MS);return Number.isFinite(j)&&j>0?j:Oj}function Aj(j,$){return new Promise((f,J)=>{if($?.aborted){J(Error("Supervisor request cancelled."));return}let B,Z=()=>{if(B)clearTimeout(B);$?.removeEventListener("abort",Q)},Q=()=>{Z(),J(Error("Supervisor request cancelled."))};B=setTimeout(()=>{Z(),f()},j),$?.addEventListener("abort",Q,{once:!0})})}async function _j(j,$,f){let J=u(j,$),B=Date.now()+Vj();while(Date.now()<=B){if(f?.aborted)throw Error("Supervisor request cancelled.");if(W.existsSync(J)){let Z=JSON.parse(W.readFileSync(J,"utf-8"));if(Z.type==="subagent.supervisor.reply"&&Z.requestId===$&&typeof Z.message==="string")return Z}await Aj(250,f)}throw Error("Timed out waiting for supervisor reply.")}async function N(j,$){let f=r();if(!f)throw Error("Native supervisor channel is not available for this subagent.");if(j.reason!=="progress_update"&&!j.message?.trim()&&j.reason!=="interview_request")throw Error("message is required for supervisor decisions.");Tj(f.channelDir);let J=Qj(),B=j.reason!=="progress_update",Z=Gj({...f,reason:j.reason,message:j.message,interview:j.interview}),Q={type:"subagent.supervisor.request",id:J,createdAt:Date.now(),reason:j.reason,message:Z,expectsReply:B,...f.orchestratorTarget?{orchestratorTarget:f.orchestratorTarget}:{},...f.orchestratorSessionId?{orchestratorSessionId:f.orchestratorSessionId}:{},runId:f.runId,agent:f.agent,childIndex:f.childIndex,...f.childTarget?{childTarget:f.childTarget}:{},...j.interview!==void 0?{interview:j.interview}:{}},O=JSON.stringify(Q,null,"\t");if(Buffer.byteLength(O,"utf-8")>Xj)throw Error("Supervisor request is too large.");if(R(Kj(f.channelDir,J),Q),!B)return{content:[{type:"text",text:"Supervisor progress update queued."}],details:{delivered:!0,requestId:J,reason:j.reason}};let G=await _j(f.channelDir,J,$),H={requestId:J,reason:j.reason};if(j.reason==="interview_request"){let X=Hj(G.message);if(X.error)H.structuredReplyParseError=X.error;else H.structuredReply=X.value}return{content:[{type:"text",text:`**Reply from supervisor:**
3
- ${G.message}`}],details:H}}function S(j,$){try{return j.getAllTools?.().some((f)=>f.name===$)===!0}catch{return!1}}function q$(j,$={}){if(!r())return;let f=$.includeIntercomFallback!==!1;if(!S(j,"contact_supervisor")){let J={name:"contact_supervisor",label:"Contact Supervisor",description:"Contact the parent/supervisor session for a blocking decision, structured interview, or progress update.",parameters:Wj,execute(B,Z,Q){return N(Z,Q)}};j.registerTool(J)}if(f&&!S(j,"intercom")){let J={name:"intercom",label:"Intercom",description:"Native supervisor-channel intercom fallback for subagents. Prefer contact_supervisor when available.",parameters:d,async execute(B,Z,Q){let O=Z.action;if(O==="status")return{content:[{type:"text",text:"Native supervisor channel is active."}],details:{active:!0}};if(O==="list")return{content:[{type:"text",text:"Supervisor session available through contact_supervisor."}],details:{sessions:[]}};if(O==="send")return N({reason:"progress_update",message:Z.message??""},Q);if(O==="ask")return N({reason:"need_decision",message:Z.message??""},Q);throw Error("Native child intercom supports status, list, send, and ask. Use parent intercom reply from the supervisor session.")}};j.registerTool(J)}}function Mj(j,$){try{let f=JSON.parse(W.readFileSync(j,"utf-8"));if(f.type!=="subagent.supervisor.request")return;if(typeof f.id!=="string"||!f.id)return;if(f.reason!=="need_decision"&&f.reason!=="interview_request"&&f.reason!=="progress_update")return;if(typeof f.message!=="string"||!f.message)return;if(typeof f.runId!=="string"||typeof f.agent!=="string"||typeof f.childIndex!=="number")return;return{...f,channelDir:$,requestFile:j}}catch{return}}function Lj(){let j;try{j=W.readdirSync(b,{withFileTypes:!0})}catch(f){if(f.code==="ENOENT")return[];throw f}let $=[];for(let f of j){if(!f.isDirectory())continue;let J=U.join(b,f.name),B=U.join(J,y),Z;try{Z=W.readdirSync(B,{withFileTypes:!0})}catch{continue}for(let Q of Z)if(Q.isFile()&&Q.name.endsWith(".json"))$.push({channelDir:J,file:U.join(B,Q.name)})}return $}function Cj(j,$){try{let f=$.sessionManager.getSessionId();if(f)return f}catch{}return j.currentSessionId??void 0}function zj(j,$,f){let J=Cj($,f);return Boolean(J&&j.orchestratorSessionId===J)}function bj(j){let $=j.expectsReply?` Reply: ${E}({ action: "reply", replyTo: "${j.id}", message: "..." })`:"";return`- ${j.id}: ${j.agent} [${j.runId}#${j.childIndex}] ${j.reason}.${$}`}function Ej(j){let $=[j.message];if(j.expectsReply)$.push("",`Reply with: ${E}({ action: "reply", replyTo: "${j.id}", message: "..." })`);return $.join(`
4
- `)}function Fj(j,$){if(!$.trim())throw Error("message is required for supervisor replies.");let f={type:"subagent.supervisor.reply",requestId:j.id,createdAt:Date.now(),message:$.trim()};R(u(j.channelDir,j.id),f);try{W.rmSync(j.requestFile,{force:!0})}catch{}}function Sj(j,$){if($.replyTo){let J=j.get($.replyTo);if(!J)throw Error(`No pending supervisor request found for replyTo '${$.replyTo}'.`);return J}let f=[...j.values()].filter((J)=>J.expectsReply);if($.to){let J=$.to.toLowerCase(),B=f.filter((Z)=>Z.id.toLowerCase().startsWith(J)||Z.agent.toLowerCase()===J||Z.childTarget?.toLowerCase()===J);if(B.length===1)return B[0];if(B.length>1)throw Error(`Multiple pending supervisor requests match '${$.to}'. Use replyTo.`)}if(f.length===1)return f[0];if(f.length===0)throw Error("No pending supervisor requests need a reply.");throw Error("Multiple pending supervisor requests need replies. Use replyTo.")}function Rj(j){return[...j.values()].map(($)=>({id:$.id,runId:$.runId,agent:$.agent,childIndex:$.childIndex,reason:$.reason,expectsReply:$.expectsReply}))}function m(j,$="intercom"){return{name:$,label:$==="intercom"?"Intercom":"Subagent Supervisor",description:$==="intercom"?"Native dm-subagents supervisor channel. Use reply/pending/status to answer child subagent requests.":"Native dm-subagents supervisor channel. Use reply/pending/status to answer child subagent requests without overriding the optional intercom compatibility extension.",parameters:d,async execute(f,J){let B=J;if(B.action==="status")return{content:[{type:"text",text:`Native supervisor channel active. Pending replies: ${j.size}.`}],details:{active:!0,pending:j.size,root:b}};if(B.action==="pending"||B.action==="list"){let Z=[...j.values()].filter((Q)=>Q.expectsReply).map(bj);return{content:[{type:"text",text:Z.length?Z.join(`
5
- `):"No pending supervisor requests."}],details:{pending:Rj(j)}}}if(B.action==="reply"){let Z=Sj(j,B);return Fj(Z,B.message??""),j.delete(Z.id),{content:[{type:"text",text:`Replied to supervisor request ${Z.id}.`}],details:{replyTo:Z.id,runId:Z.runId,agent:Z.agent}}}if(B.action==="send"||B.action==="ask")throw Error("Native dm-subagents intercom currently handles supervisor replies. Child agents initiate asks with contact_supervisor.");throw Error(`Unsupported intercom action: ${B.action}`)}}}function I$(j,$){let f=new Map,J=new Set,B,Z=()=>{if(!S(j,E))j.registerTool(m(f,E));if(!S(j,"intercom"))j.registerTool(m(f))},Q=()=>{let O=$.lastUiContext;if(!O)return;for(let{channelDir:G,file:H}of Lj()){if(J.has(H))continue;let X=Mj(H,G);if(!X||!zj(X,$,O))continue;if(J.add(H),X.expectsReply)f.set(X.id,X);else try{W.rmSync(X.requestFile,{force:!0})}catch{}j.sendMessage({customType:"subagent_supervisor_request",content:Ej(X),display:!0,details:{id:X.id,reason:X.reason,expectsReply:X.expectsReply,runId:X.runId,agent:X.agent,childIndex:X.childIndex}})}};return{start:()=>{if(B)return;Z(),Q(),B=setInterval(Q,Yj),B.unref?.()},dispose:()=>{if(B)clearInterval(B);B=void 0,f.clear(),J.clear()},pending:f}}export{c$ as resolveSupervisorChannelDir,q$ as registerNativeSupervisorClient,Tj as ensureSupervisorChannelDir,I$ as createNativeSupervisorChannel,E as NATIVE_SUPERVISOR_TOOL_NAME};
1
+ import { randomUUID } from "node:crypto";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { Type } from "typebox";
5
+ import {
6
+ SUBAGENT_CHILD_AGENT_ENV,
7
+ SUBAGENT_CHILD_INDEX_ENV,
8
+ SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV,
9
+ SUBAGENT_ORCHESTRATOR_TARGET_ENV,
10
+ SUBAGENT_RUN_ID_ENV,
11
+ SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV
12
+ } from "../runs/shared/dm-args.js";
13
+ import { POLL_INTERVAL_MS, TEMP_ROOT_DIR } from "../shared/types.js";
14
+ import { writeAtomicJson } from "../shared/atomic-json.js";
15
+ const SUPERVISOR_CHANNEL_ROOT = path.join(TEMP_ROOT_DIR, "supervisor-channels");
16
+ const REQUESTS_DIR = "requests";
17
+ const REPLIES_DIR = "replies";
18
+ export const NATIVE_SUPERVISOR_TOOL_NAME = "subagent_supervisor";
19
+ const MAX_MESSAGE_BYTES = 64 * 1024;
20
+ const DEFAULT_ASK_TIMEOUT_MS = 10 * 60 * 1000;
21
+ const CHANNEL_POLL_MS = Math.min(POLL_INTERVAL_MS, 500);
22
+ const ContactSupervisorParamsSchema = Type.Object({
23
+ reason: Type.String({ enum: ["need_decision", "interview_request", "progress_update"] }),
24
+ message: Type.Optional(Type.String()),
25
+ interview: Type.Optional(Type.Unsafe({ type: "object", additionalProperties: true }))
26
+ }, { additionalProperties: false });
27
+ const IntercomParamsSchema = Type.Object({
28
+ action: Type.String({ enum: ["list", "send", "ask", "reply", "pending", "status"] }),
29
+ to: Type.Optional(Type.String()),
30
+ message: Type.Optional(Type.String()),
31
+ replyTo: Type.Optional(Type.String())
32
+ }, { additionalProperties: false });
33
+ function safeSegment(value) {
34
+ return value.trim().replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "unknown";
35
+ }
36
+ export function resolveSupervisorChannelDir(runId, agent, childIndex) {
37
+ return path.join(SUPERVISOR_CHANNEL_ROOT, `${safeSegment(runId)}-${safeSegment(agent)}-${childIndex}`);
38
+ }
39
+ export function ensureSupervisorChannelDir(channelDir) {
40
+ fs.mkdirSync(path.join(channelDir, REQUESTS_DIR), { recursive: true, mode: 448 });
41
+ fs.mkdirSync(path.join(channelDir, REPLIES_DIR), { recursive: true, mode: 448 });
42
+ }
43
+ function requestPath(channelDir, requestId) {
44
+ return path.join(channelDir, REQUESTS_DIR, `${safeSegment(requestId)}.json`);
45
+ }
46
+ function replyPath(channelDir, requestId) {
47
+ return path.join(channelDir, REPLIES_DIR, `${safeSegment(requestId)}.json`);
48
+ }
49
+ function readTextEnv(name) {
50
+ const value = process.env[name]?.trim();
51
+ return value ? value : undefined;
52
+ }
53
+ function readChildMetadata() {
54
+ const channelDir = readTextEnv(SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV);
55
+ const runId = readTextEnv(SUBAGENT_RUN_ID_ENV);
56
+ const agent = readTextEnv(SUBAGENT_CHILD_AGENT_ENV);
57
+ const rawIndex = readTextEnv(SUBAGENT_CHILD_INDEX_ENV);
58
+ const orchestratorSessionId = readTextEnv(SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV);
59
+ if (!channelDir || !runId || !agent || !orchestratorSessionId || rawIndex === undefined || !/^\d+$/.test(rawIndex))
60
+ return;
61
+ return {
62
+ channelDir,
63
+ runId,
64
+ agent,
65
+ childIndex: Number(rawIndex),
66
+ orchestratorTarget: readTextEnv(SUBAGENT_ORCHESTRATOR_TARGET_ENV),
67
+ orchestratorSessionId,
68
+ childTarget: readTextEnv("DM_SUBAGENT_INTERCOM_SESSION_NAME")
69
+ };
70
+ }
71
+ function reasonHeading(reason) {
72
+ if (reason === "interview_request")
73
+ return "Subagent requests a structured supervisor interview.";
74
+ if (reason === "progress_update")
75
+ return "Subagent progress update.";
76
+ return "Subagent needs a supervisor decision.";
77
+ }
78
+ function formatChildMessage(input) {
79
+ const lines = [
80
+ reasonHeading(input.reason),
81
+ `Run: ${input.runId}`,
82
+ `Agent: ${input.agent}`,
83
+ `Child index: ${input.childIndex}`
84
+ ];
85
+ if (input.childTarget)
86
+ lines.push(`Child intercom target: ${input.childTarget}`);
87
+ lines.push("");
88
+ if (input.message?.trim())
89
+ lines.push(input.message.trim());
90
+ if (input.reason === "interview_request") {
91
+ lines.push("", "Structured response requested. Reply with JSON, optionally fenced in ```json, matching the requested interview shape.");
92
+ if (input.interview !== undefined)
93
+ lines.push(JSON.stringify(input.interview, null, "\t"));
94
+ }
95
+ return lines.join(`
96
+ `).trimEnd();
97
+ }
98
+ function parseStructuredReply(message) {
99
+ const trimmed = message.trim();
100
+ const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i)?.[1]?.trim();
101
+ try {
102
+ return { value: JSON.parse(fenced ?? trimmed) };
103
+ } catch (error) {
104
+ return { error: error instanceof Error ? `${error.name}: ${error.message}` : String(error) };
105
+ }
106
+ }
107
+ function askTimeoutMs() {
108
+ const parsed = Number(process.env.PI_INTERCOM_ASK_TIMEOUT_MS);
109
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_ASK_TIMEOUT_MS;
110
+ }
111
+ function delay(ms, signal) {
112
+ return new Promise((resolve, reject) => {
113
+ if (signal?.aborted) {
114
+ reject(new Error("Supervisor request cancelled."));
115
+ return;
116
+ }
117
+ let timer;
118
+ const cleanup = () => {
119
+ if (timer)
120
+ clearTimeout(timer);
121
+ signal?.removeEventListener("abort", onAbort);
122
+ };
123
+ const onAbort = () => {
124
+ cleanup();
125
+ reject(new Error("Supervisor request cancelled."));
126
+ };
127
+ timer = setTimeout(() => {
128
+ cleanup();
129
+ resolve();
130
+ }, ms);
131
+ signal?.addEventListener("abort", onAbort, { once: true });
132
+ });
133
+ }
134
+ async function waitForReply(channelDir, requestId, signal) {
135
+ const file = replyPath(channelDir, requestId);
136
+ const deadline = Date.now() + askTimeoutMs();
137
+ while (Date.now() <= deadline) {
138
+ if (signal?.aborted)
139
+ throw new Error("Supervisor request cancelled.");
140
+ if (fs.existsSync(file)) {
141
+ const parsed = JSON.parse(fs.readFileSync(file, "utf-8"));
142
+ if (parsed.type === "subagent.supervisor.reply" && parsed.requestId === requestId && typeof parsed.message === "string") {
143
+ return parsed;
144
+ }
145
+ }
146
+ await delay(250, signal);
147
+ }
148
+ throw new Error("Timed out waiting for supervisor reply.");
149
+ }
150
+ async function sendSupervisorRequest(params, signal) {
151
+ const metadata = readChildMetadata();
152
+ if (!metadata)
153
+ throw new Error("Native supervisor channel is not available for this subagent.");
154
+ if (params.reason !== "progress_update" && !params.message?.trim() && params.reason !== "interview_request") {
155
+ throw new Error("message is required for supervisor decisions.");
156
+ }
157
+ ensureSupervisorChannelDir(metadata.channelDir);
158
+ const requestId = randomUUID();
159
+ const expectsReply = params.reason !== "progress_update";
160
+ const message = formatChildMessage({ ...metadata, reason: params.reason, message: params.message, interview: params.interview });
161
+ const request = {
162
+ type: "subagent.supervisor.request",
163
+ id: requestId,
164
+ createdAt: Date.now(),
165
+ reason: params.reason,
166
+ message,
167
+ expectsReply,
168
+ ...metadata.orchestratorTarget ? { orchestratorTarget: metadata.orchestratorTarget } : {},
169
+ ...metadata.orchestratorSessionId ? { orchestratorSessionId: metadata.orchestratorSessionId } : {},
170
+ runId: metadata.runId,
171
+ agent: metadata.agent,
172
+ childIndex: metadata.childIndex,
173
+ ...metadata.childTarget ? { childTarget: metadata.childTarget } : {},
174
+ ...params.interview !== undefined ? { interview: params.interview } : {}
175
+ };
176
+ const serialized = JSON.stringify(request, null, "\t");
177
+ if (Buffer.byteLength(serialized, "utf-8") > MAX_MESSAGE_BYTES)
178
+ throw new Error("Supervisor request is too large.");
179
+ writeAtomicJson(requestPath(metadata.channelDir, requestId), request);
180
+ if (!expectsReply) {
181
+ return {
182
+ content: [{ type: "text", text: "Supervisor progress update queued." }],
183
+ details: { delivered: true, requestId, reason: params.reason }
184
+ };
185
+ }
186
+ const reply = await waitForReply(metadata.channelDir, requestId, signal);
187
+ const details = { requestId, reason: params.reason };
188
+ if (params.reason === "interview_request") {
189
+ const structured = parseStructuredReply(reply.message);
190
+ if (structured.error)
191
+ details.structuredReplyParseError = structured.error;
192
+ else
193
+ details.structuredReply = structured.value;
194
+ }
195
+ return {
196
+ content: [{ type: "text", text: `**Reply from supervisor:**
197
+ ${reply.message}` }],
198
+ details
199
+ };
200
+ }
201
+ function hasTool(pi, name) {
202
+ try {
203
+ return pi.getAllTools?.().some((tool) => tool.name === name) === true;
204
+ } catch {
205
+ return false;
206
+ }
207
+ }
208
+ export function registerNativeSupervisorClient(pi, options = {}) {
209
+ if (!readChildMetadata())
210
+ return;
211
+ const includeIntercomFallback = options.includeIntercomFallback !== false;
212
+ if (!hasTool(pi, "contact_supervisor")) {
213
+ const tool = {
214
+ name: "contact_supervisor",
215
+ label: "Contact Supervisor",
216
+ description: "Contact the parent/supervisor session for a blocking decision, structured interview, or progress update.",
217
+ parameters: ContactSupervisorParamsSchema,
218
+ execute(_id, params, signal) {
219
+ return sendSupervisorRequest(params, signal);
220
+ }
221
+ };
222
+ pi.registerTool(tool);
223
+ }
224
+ if (includeIntercomFallback && !hasTool(pi, "intercom")) {
225
+ const tool = {
226
+ name: "intercom",
227
+ label: "Intercom",
228
+ description: "Native supervisor-channel intercom fallback for subagents. Prefer contact_supervisor when available.",
229
+ parameters: IntercomParamsSchema,
230
+ async execute(_id, params, signal) {
231
+ const action = params.action;
232
+ if (action === "status")
233
+ return { content: [{ type: "text", text: "Native supervisor channel is active." }], details: { active: true } };
234
+ if (action === "list")
235
+ return { content: [{ type: "text", text: "Supervisor session available through contact_supervisor." }], details: { sessions: [] } };
236
+ if (action === "send")
237
+ return sendSupervisorRequest({ reason: "progress_update", message: params.message ?? "" }, signal);
238
+ if (action === "ask")
239
+ return sendSupervisorRequest({ reason: "need_decision", message: params.message ?? "" }, signal);
240
+ throw new Error("Native child intercom supports status, list, send, and ask. Use parent intercom reply from the supervisor session.");
241
+ }
242
+ };
243
+ pi.registerTool(tool);
244
+ }
245
+ }
246
+ function parseRequestFile(file, channelDir) {
247
+ try {
248
+ const parsed = JSON.parse(fs.readFileSync(file, "utf-8"));
249
+ if (parsed.type !== "subagent.supervisor.request")
250
+ return;
251
+ if (typeof parsed.id !== "string" || !parsed.id)
252
+ return;
253
+ if (parsed.reason !== "need_decision" && parsed.reason !== "interview_request" && parsed.reason !== "progress_update")
254
+ return;
255
+ if (typeof parsed.message !== "string" || !parsed.message)
256
+ return;
257
+ if (typeof parsed.runId !== "string" || typeof parsed.agent !== "string" || typeof parsed.childIndex !== "number")
258
+ return;
259
+ return { ...parsed, channelDir, requestFile: file };
260
+ } catch {
261
+ return;
262
+ }
263
+ }
264
+ function listRequestFiles() {
265
+ let channelEntries;
266
+ try {
267
+ channelEntries = fs.readdirSync(SUPERVISOR_CHANNEL_ROOT, { withFileTypes: true });
268
+ } catch (error) {
269
+ if (error.code === "ENOENT")
270
+ return [];
271
+ throw error;
272
+ }
273
+ const files = [];
274
+ for (const entry of channelEntries) {
275
+ if (!entry.isDirectory())
276
+ continue;
277
+ const channelDir = path.join(SUPERVISOR_CHANNEL_ROOT, entry.name);
278
+ const requestsDir = path.join(channelDir, REQUESTS_DIR);
279
+ let requestEntries;
280
+ try {
281
+ requestEntries = fs.readdirSync(requestsDir, { withFileTypes: true });
282
+ } catch {
283
+ continue;
284
+ }
285
+ for (const requestEntry of requestEntries) {
286
+ if (requestEntry.isFile() && requestEntry.name.endsWith(".json"))
287
+ files.push({ channelDir, file: path.join(requestsDir, requestEntry.name) });
288
+ }
289
+ }
290
+ return files;
291
+ }
292
+ function currentContextSessionId(state, ctx) {
293
+ try {
294
+ const sessionId = ctx.sessionManager.getSessionId();
295
+ if (sessionId)
296
+ return sessionId;
297
+ } catch {}
298
+ return state.currentSessionId ?? undefined;
299
+ }
300
+ function requestMatchesContext(request, state, ctx) {
301
+ const currentSessionId = currentContextSessionId(state, ctx);
302
+ return Boolean(currentSessionId && request.orchestratorSessionId === currentSessionId);
303
+ }
304
+ function formatPendingLine(request) {
305
+ const replyHint = request.expectsReply ? ` Reply: ${NATIVE_SUPERVISOR_TOOL_NAME}({ action: "reply", replyTo: "${request.id}", message: "..." })` : "";
306
+ return `- ${request.id}: ${request.agent} [${request.runId}#${request.childIndex}] ${request.reason}.${replyHint}`;
307
+ }
308
+ function requestVisibleText(request) {
309
+ const lines = [request.message];
310
+ if (request.expectsReply) {
311
+ lines.push("", `Reply with: ${NATIVE_SUPERVISOR_TOOL_NAME}({ action: "reply", replyTo: "${request.id}", message: "..." })`);
312
+ }
313
+ return lines.join(`
314
+ `);
315
+ }
316
+ function writeReply(request, message) {
317
+ if (!message.trim())
318
+ throw new Error("message is required for supervisor replies.");
319
+ const reply = {
320
+ type: "subagent.supervisor.reply",
321
+ requestId: request.id,
322
+ createdAt: Date.now(),
323
+ message: message.trim()
324
+ };
325
+ writeAtomicJson(replyPath(request.channelDir, request.id), reply);
326
+ try {
327
+ fs.rmSync(request.requestFile, { force: true });
328
+ } catch {}
329
+ }
330
+ function resolvePendingRequest(pending, params) {
331
+ if (params.replyTo) {
332
+ const request = pending.get(params.replyTo);
333
+ if (!request)
334
+ throw new Error(`No pending supervisor request found for replyTo '${params.replyTo}'.`);
335
+ return request;
336
+ }
337
+ const requests = [...pending.values()].filter((request) => request.expectsReply);
338
+ if (params.to) {
339
+ const normalizedTo = params.to.toLowerCase();
340
+ const matches = requests.filter((request) => request.id.toLowerCase().startsWith(normalizedTo) || request.agent.toLowerCase() === normalizedTo || request.childTarget?.toLowerCase() === normalizedTo);
341
+ if (matches.length === 1)
342
+ return matches[0];
343
+ if (matches.length > 1)
344
+ throw new Error(`Multiple pending supervisor requests match '${params.to}'. Use replyTo.`);
345
+ }
346
+ if (requests.length === 1)
347
+ return requests[0];
348
+ if (requests.length === 0)
349
+ throw new Error("No pending supervisor requests need a reply.");
350
+ throw new Error("Multiple pending supervisor requests need replies. Use replyTo.");
351
+ }
352
+ function publicPendingRequests(pending) {
353
+ return [...pending.values()].map((request) => ({
354
+ id: request.id,
355
+ runId: request.runId,
356
+ agent: request.agent,
357
+ childIndex: request.childIndex,
358
+ reason: request.reason,
359
+ expectsReply: request.expectsReply
360
+ }));
361
+ }
362
+ function buildParentIntercomTool(pending, name = "intercom") {
363
+ return {
364
+ name,
365
+ label: name === "intercom" ? "Intercom" : "Subagent Supervisor",
366
+ description: name === "intercom" ? "Native dm-subagents supervisor channel. Use reply/pending/status to answer child subagent requests." : "Native dm-subagents supervisor channel. Use reply/pending/status to answer child subagent requests without overriding the optional intercom compatibility extension.",
367
+ parameters: IntercomParamsSchema,
368
+ async execute(_id, params) {
369
+ const input = params;
370
+ if (input.action === "status") {
371
+ return { content: [{ type: "text", text: `Native supervisor channel active. Pending replies: ${pending.size}.` }], details: { active: true, pending: pending.size, root: SUPERVISOR_CHANNEL_ROOT } };
372
+ }
373
+ if (input.action === "pending" || input.action === "list") {
374
+ const lines = [...pending.values()].filter((request) => request.expectsReply).map(formatPendingLine);
375
+ return { content: [{ type: "text", text: lines.length ? lines.join(`
376
+ `) : "No pending supervisor requests." }], details: { pending: publicPendingRequests(pending) } };
377
+ }
378
+ if (input.action === "reply") {
379
+ const request = resolvePendingRequest(pending, input);
380
+ writeReply(request, input.message ?? "");
381
+ pending.delete(request.id);
382
+ return { content: [{ type: "text", text: `Replied to supervisor request ${request.id}.` }], details: { replyTo: request.id, runId: request.runId, agent: request.agent } };
383
+ }
384
+ if (input.action === "send" || input.action === "ask") {
385
+ throw new Error("Native dm-subagents intercom currently handles supervisor replies. Child agents initiate asks with contact_supervisor.");
386
+ }
387
+ throw new Error(`Unsupported intercom action: ${input.action}`);
388
+ }
389
+ };
390
+ }
391
+ export function createNativeSupervisorChannel(pi, state) {
392
+ const pending = new Map;
393
+ const seenFiles = new Set;
394
+ let poller;
395
+ const registerParentTools = () => {
396
+ if (!hasTool(pi, NATIVE_SUPERVISOR_TOOL_NAME))
397
+ pi.registerTool(buildParentIntercomTool(pending, NATIVE_SUPERVISOR_TOOL_NAME));
398
+ if (!hasTool(pi, "intercom"))
399
+ pi.registerTool(buildParentIntercomTool(pending));
400
+ };
401
+ const poll = () => {
402
+ const ctx = state.lastUiContext;
403
+ if (!ctx)
404
+ return;
405
+ for (const { channelDir, file } of listRequestFiles()) {
406
+ if (seenFiles.has(file))
407
+ continue;
408
+ const request = parseRequestFile(file, channelDir);
409
+ if (!request || !requestMatchesContext(request, state, ctx))
410
+ continue;
411
+ seenFiles.add(file);
412
+ if (request.expectsReply)
413
+ pending.set(request.id, request);
414
+ else {
415
+ try {
416
+ fs.rmSync(request.requestFile, { force: true });
417
+ } catch {}
418
+ }
419
+ pi.sendMessage({
420
+ customType: "subagent_supervisor_request",
421
+ content: requestVisibleText(request),
422
+ display: true,
423
+ details: {
424
+ id: request.id,
425
+ reason: request.reason,
426
+ expectsReply: request.expectsReply,
427
+ runId: request.runId,
428
+ agent: request.agent,
429
+ childIndex: request.childIndex
430
+ }
431
+ });
432
+ }
433
+ };
434
+ return {
435
+ start: () => {
436
+ if (poller)
437
+ return;
438
+ registerParentTools();
439
+ poll();
440
+ poller = setInterval(poll, CHANNEL_POLL_MS);
441
+ poller.unref?.();
442
+ },
443
+ dispose: () => {
444
+ if (poller)
445
+ clearInterval(poller);
446
+ poller = undefined;
447
+ pending.clear();
448
+ seenFiles.clear();
449
+ },
450
+ pending
451
+ };
452
+ }