@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,288 @@
1
- var N="prompt-template:subagent:request",S="prompt-template:subagent:started",h="prompt-template:subagent:response",C="prompt-template:subagent:update",D="prompt-template:subagent:cancel";function b(n){if(!Array.isArray(n))return[];let e=[];for(let t of n){if(!t||typeof t!=="object")return[];let s=t;if(typeof s.agent!=="string"||!s.agent.trim())return[];if(typeof s.task!=="string"||!s.task.trim())return[];let i=typeof s.model==="string"&&s.model.trim().length>0?s.model:void 0,o=typeof s.cwd==="string"&&s.cwd.trim().length>0?s.cwd:void 0;e.push({agent:s.agent,task:s.task,...i?{model:i}:{},...o?{cwd:o}:{}})}return e}function O(n){if(!n||typeof n!=="object")return;let e=n;if(typeof e.requestId!=="string"||!e.requestId)return;if(typeof e.model!=="string"||!e.model)return;if(typeof e.cwd!=="string"||!e.cwd)return;if(e.context!=="fresh"&&e.context!=="fork")return;let t=b(e.tasks),s=e.worktree===!0?!0:void 0,i=typeof e.agent==="string"&&e.agent.length>0&&typeof e.task==="string"&&e.task.length>0;if(!i&&t.length===0)return;let o=t[0];return{requestId:e.requestId,agent:i?e.agent:o.agent,task:i?e.task:o.task,...t.length>0?{tasks:t}:{},context:e.context,model:e.model,cwd:e.cwd,...s?{worktree:s}:{}}}function R(n){if(!Array.isArray(n))return;for(let e of n){if(!e||typeof e!=="object")continue;if(e.type!=="text")continue;let t=e.text;if(typeof t==="string"&&t.trim())return t.trim()}return}function E(n){if(!n||n.length===0)return;let e=n.filter((t)=>typeof t==="string"&&t.trim()&&t.trim()!=="(running...)");if(e.length===0)return;return e}function P(n){if(!n||n.length===0)return;let e=n.flatMap((t)=>{if(typeof t.tool!=="string"||t.tool.trim().length===0)return[];return[{tool:t.tool,args:typeof t.args==="string"?t.args:String(t.args??"")}]});return e.length>0?e:void 0}function x(n,e){let t=n.details?.results;if(!t||t.length===0)return;if(typeof e.index==="number"&&e.index>=0){let i=t[e.index];if(typeof i?.model==="string")return i.model}if(e.agent){let i=t.find((o)=>o.agent===e.agent&&typeof o.model==="string");if(i?.model)return i.model}return t.find((i)=>typeof i.model==="string")?.model}function M(n){let e=typeof n.expandedText==="string"&&n.expandedText.trim().length>0?n.expandedText.trim():typeof n.text==="string"?n.text.trim():"";if(!e)return;if(e.startsWith("$ "))return"bash";return e.match(/^[A-Za-z_][\w.-]*/)?.[0]}function A(n,e){if(Array.isArray(n.messages)&&n.messages.length>0)return n.messages;let t=(n.toolCalls??[]).flatMap((o)=>{let r=M(o);return r?[{type:"toolCall",name:r,arguments:{summary:o.expandedText??o.text??""}}]:[]}),s=typeof n.finalOutput==="string"&&n.finalOutput.trim().length>0?n.finalOutput.trim():e,i=[...t,...s?[{type:"text",text:s}]:[]];if(i.length===0)return[];return[{role:"assistant",content:i}]}function w(n,e){let t=e.details?.progress?.[0],s=e.details?.progress?.map((r)=>{let a=r.recentOutput?.[r.recentOutput.length-1],d=typeof a==="string"&&a.trim()&&a!=="(running...)"?a:void 0;return{index:r.index,agent:r.agent??"delegate",status:r.status,currentTool:r.currentTool,currentToolArgs:r.currentToolArgs,recentOutput:d,recentOutputLines:E(r.recentOutput),recentTools:P(r.recentTools),model:x(e,r),toolCount:r.toolCount,durationMs:r.durationMs,tokens:r.tokens}});if(!t&&(!s||s.length===0))return;let i=t?.recentOutput?.[t.recentOutput.length-1],o=typeof i==="string"&&i.trim()&&i!=="(running...)"?i:void 0;return{requestId:n,currentTool:t?.currentTool,currentToolArgs:t?.currentToolArgs,recentOutput:o,recentOutputLines:E(t?.recentOutput),recentTools:P(t?.recentTools),model:t?x(e,t):void 0,toolCount:t?.toolCount,durationMs:t?.durationMs,tokens:t?.tokens,taskProgress:s}}function y(n){let e=new Map,t=new Set,s=[],i=(o,r)=>{let a=n.events.on(o,r);if(typeof a==="function")s.push(a)};return i("prompt-template:subagent:cancel",(o)=>{if(!o||typeof o!=="object")return;let r=o.requestId;if(typeof r!=="string")return;let a=e.get(r);if(a){a.abort();return}t.add(r)}),i("prompt-template:subagent:request",async(o)=>{let r=O(o);if(!r)return;let a=n.getContext();if(!a){let u={...r,messages:[],isError:!0,errorText:"No active extension context for delegated subagent execution."};n.events.emit("prompt-template:subagent:response",u);return}let d=new AbortController;if(e.set(r.requestId,d),t.delete(r.requestId)){d.abort();let u={...r,messages:[],isError:!0,errorText:"Delegated prompt cancelled."};n.events.emit("prompt-template:subagent:response",u),e.delete(r.requestId);return}n.events.emit("prompt-template:subagent:started",{requestId:r.requestId});try{let u=await n.execute(r.requestId,r,d.signal,a,(p)=>{let c=w(r.requestId,p);if(!c)return;n.events.emit("prompt-template:subagent:update",c)}),l=R(u.content),k=A(u.details?.results?.[0]??{},l),T=r.tasks?r.tasks.map((p,c)=>{let g=u.details?.results?.[c];if(!g)return{agent:p.agent,messages:[],isError:!0,errorText:"Missing result for delegated parallel task."};let f=typeof g.exitCode==="number"?g.exitCode:void 0,m=g.error;return{agent:g.agent??p.agent,messages:A(g),isError:f!==void 0&&f!==0||!!m,errorText:m||void 0}}):void 0,_={...r,messages:k,...T?{parallelResults:T}:{},...l?{contentText:l}:{},isError:u.isError===!0,errorText:u.isError?l:void 0};n.events.emit("prompt-template:subagent:response",_)}catch(u){let l={...r,messages:[],isError:!0,errorText:u instanceof Error?u.message:String(u)};n.events.emit("prompt-template:subagent:response",l)}finally{e.delete(r.requestId)}}),{cancelAll:()=>{for(let o of e.values())o.abort();e.clear(),t.clear()},dispose:()=>{for(let o of s)o();s.length=0,t.clear()}}}export{y as registerPromptTemplateDelegationBridge,C as PROMPT_TEMPLATE_SUBAGENT_UPDATE_EVENT,S as PROMPT_TEMPLATE_SUBAGENT_STARTED_EVENT,h as PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT,N as PROMPT_TEMPLATE_SUBAGENT_REQUEST_EVENT,D as PROMPT_TEMPLATE_SUBAGENT_CANCEL_EVENT};
1
+ export const PROMPT_TEMPLATE_SUBAGENT_REQUEST_EVENT = "prompt-template:subagent:request";
2
+ export const PROMPT_TEMPLATE_SUBAGENT_STARTED_EVENT = "prompt-template:subagent:started";
3
+ export const PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT = "prompt-template:subagent:response";
4
+ export const PROMPT_TEMPLATE_SUBAGENT_UPDATE_EVENT = "prompt-template:subagent:update";
5
+ export const PROMPT_TEMPLATE_SUBAGENT_CANCEL_EVENT = "prompt-template:subagent:cancel";
6
+ function parseDelegationTasks(tasks) {
7
+ if (!Array.isArray(tasks))
8
+ return [];
9
+ const parsed = [];
10
+ for (const item of tasks) {
11
+ if (!item || typeof item !== "object")
12
+ return [];
13
+ const value = item;
14
+ if (typeof value.agent !== "string" || !value.agent.trim())
15
+ return [];
16
+ if (typeof value.task !== "string" || !value.task.trim())
17
+ return [];
18
+ const model = typeof value.model === "string" && value.model.trim().length > 0 ? value.model : undefined;
19
+ const cwd = typeof value.cwd === "string" && value.cwd.trim().length > 0 ? value.cwd : undefined;
20
+ parsed.push({
21
+ agent: value.agent,
22
+ task: value.task,
23
+ ...model ? { model } : {},
24
+ ...cwd ? { cwd } : {}
25
+ });
26
+ }
27
+ return parsed;
28
+ }
29
+ function parsePromptTemplateRequest(data) {
30
+ if (!data || typeof data !== "object")
31
+ return;
32
+ const value = data;
33
+ if (typeof value.requestId !== "string" || !value.requestId)
34
+ return;
35
+ if (typeof value.model !== "string" || !value.model)
36
+ return;
37
+ if (typeof value.cwd !== "string" || !value.cwd)
38
+ return;
39
+ if (value.context !== "fresh" && value.context !== "fork")
40
+ return;
41
+ const tasks = parseDelegationTasks(value.tasks);
42
+ const worktree = value.worktree === true ? true : undefined;
43
+ const hasSingle = typeof value.agent === "string" && value.agent.length > 0 && typeof value.task === "string" && value.task.length > 0;
44
+ if (!hasSingle && tasks.length === 0)
45
+ return;
46
+ const fallbackTask = tasks[0];
47
+ return {
48
+ requestId: value.requestId,
49
+ agent: hasSingle ? value.agent : fallbackTask.agent,
50
+ task: hasSingle ? value.task : fallbackTask.task,
51
+ ...tasks.length > 0 ? { tasks } : {},
52
+ context: value.context,
53
+ model: value.model,
54
+ cwd: value.cwd,
55
+ ...worktree ? { worktree } : {}
56
+ };
57
+ }
58
+ function firstTextContent(content) {
59
+ if (!Array.isArray(content))
60
+ return;
61
+ for (const part of content) {
62
+ if (!part || typeof part !== "object")
63
+ continue;
64
+ if (part.type !== "text")
65
+ continue;
66
+ const text = part.text;
67
+ if (typeof text === "string" && text.trim())
68
+ return text.trim();
69
+ }
70
+ return;
71
+ }
72
+ function filterRecentOutput(lines) {
73
+ if (!lines || lines.length === 0)
74
+ return;
75
+ const filtered = lines.filter((line) => typeof line === "string" && line.trim() && line.trim() !== "(running...)");
76
+ if (filtered.length === 0)
77
+ return;
78
+ return filtered;
79
+ }
80
+ function sanitizeRecentTools(tools) {
81
+ if (!tools || tools.length === 0)
82
+ return;
83
+ const sanitized = tools.flatMap((entry) => {
84
+ if (typeof entry.tool !== "string" || entry.tool.trim().length === 0)
85
+ return [];
86
+ return [{
87
+ tool: entry.tool,
88
+ args: typeof entry.args === "string" ? entry.args : String(entry.args ?? "")
89
+ }];
90
+ });
91
+ return sanitized.length > 0 ? sanitized : undefined;
92
+ }
93
+ function resolveProgressModel(update, entry) {
94
+ const results = update.details?.results;
95
+ if (!results || results.length === 0)
96
+ return;
97
+ if (typeof entry.index === "number" && entry.index >= 0) {
98
+ const byIndex = results[entry.index];
99
+ if (typeof byIndex?.model === "string")
100
+ return byIndex.model;
101
+ }
102
+ if (entry.agent) {
103
+ const byAgent = results.find((result) => result.agent === entry.agent && typeof result.model === "string");
104
+ if (byAgent?.model)
105
+ return byAgent.model;
106
+ }
107
+ const firstWithModel = results.find((result) => typeof result.model === "string");
108
+ return firstWithModel?.model;
109
+ }
110
+ function toolCallNameFromSummary(summary) {
111
+ const text = typeof summary.expandedText === "string" && summary.expandedText.trim().length > 0 ? summary.expandedText.trim() : typeof summary.text === "string" ? summary.text.trim() : "";
112
+ if (!text)
113
+ return;
114
+ if (text.startsWith("$ "))
115
+ return "bash";
116
+ return text.match(/^[A-Za-z_][\w.-]*/)?.[0];
117
+ }
118
+ function buildDelegationMessages(result, fallbackText) {
119
+ if (Array.isArray(result.messages) && result.messages.length > 0)
120
+ return result.messages;
121
+ const toolCallParts = (result.toolCalls ?? []).flatMap((summary) => {
122
+ const name = toolCallNameFromSummary(summary);
123
+ return name ? [{ type: "toolCall", name, arguments: { summary: summary.expandedText ?? summary.text ?? "" } }] : [];
124
+ });
125
+ const text = typeof result.finalOutput === "string" && result.finalOutput.trim().length > 0 ? result.finalOutput.trim() : fallbackText;
126
+ const content = [
127
+ ...toolCallParts,
128
+ ...text ? [{ type: "text", text }] : []
129
+ ];
130
+ if (content.length === 0)
131
+ return [];
132
+ return [{ role: "assistant", content }];
133
+ }
134
+ function toDelegationUpdate(requestId, update) {
135
+ const progress = update.details?.progress?.[0];
136
+ const taskProgress = update.details?.progress?.map((entry) => {
137
+ const lastOutput = entry.recentOutput?.[entry.recentOutput.length - 1];
138
+ const safeLastOutput = typeof lastOutput === "string" && lastOutput.trim() && lastOutput !== "(running...)" ? lastOutput : undefined;
139
+ return {
140
+ index: entry.index,
141
+ agent: entry.agent ?? "delegate",
142
+ status: entry.status,
143
+ currentTool: entry.currentTool,
144
+ currentToolArgs: entry.currentToolArgs,
145
+ recentOutput: safeLastOutput,
146
+ recentOutputLines: filterRecentOutput(entry.recentOutput),
147
+ recentTools: sanitizeRecentTools(entry.recentTools),
148
+ model: resolveProgressModel(update, entry),
149
+ toolCount: entry.toolCount,
150
+ durationMs: entry.durationMs,
151
+ tokens: entry.tokens
152
+ };
153
+ });
154
+ if (!progress && (!taskProgress || taskProgress.length === 0))
155
+ return;
156
+ const lastOutput = progress?.recentOutput?.[progress.recentOutput.length - 1];
157
+ const safeLastOutput = typeof lastOutput === "string" && lastOutput.trim() && lastOutput !== "(running...)" ? lastOutput : undefined;
158
+ return {
159
+ requestId,
160
+ currentTool: progress?.currentTool,
161
+ currentToolArgs: progress?.currentToolArgs,
162
+ recentOutput: safeLastOutput,
163
+ recentOutputLines: filterRecentOutput(progress?.recentOutput),
164
+ recentTools: sanitizeRecentTools(progress?.recentTools),
165
+ model: progress ? resolveProgressModel(update, progress) : undefined,
166
+ toolCount: progress?.toolCount,
167
+ durationMs: progress?.durationMs,
168
+ tokens: progress?.tokens,
169
+ taskProgress
170
+ };
171
+ }
172
+ export function registerPromptTemplateDelegationBridge(options) {
173
+ const controllers = new Map;
174
+ const pendingCancels = new Set;
175
+ const subscriptions = [];
176
+ const subscribe = (event, handler) => {
177
+ const unsubscribe = options.events.on(event, handler);
178
+ if (typeof unsubscribe === "function")
179
+ subscriptions.push(unsubscribe);
180
+ };
181
+ subscribe(PROMPT_TEMPLATE_SUBAGENT_CANCEL_EVENT, (data) => {
182
+ if (!data || typeof data !== "object")
183
+ return;
184
+ const requestId = data.requestId;
185
+ if (typeof requestId !== "string")
186
+ return;
187
+ const controller = controllers.get(requestId);
188
+ if (controller) {
189
+ controller.abort();
190
+ return;
191
+ }
192
+ pendingCancels.add(requestId);
193
+ });
194
+ subscribe(PROMPT_TEMPLATE_SUBAGENT_REQUEST_EVENT, async (data) => {
195
+ const request = parsePromptTemplateRequest(data);
196
+ if (!request)
197
+ return;
198
+ const ctx = options.getContext();
199
+ if (!ctx) {
200
+ const response = {
201
+ ...request,
202
+ messages: [],
203
+ isError: true,
204
+ errorText: "No active extension context for delegated subagent execution."
205
+ };
206
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
207
+ return;
208
+ }
209
+ const controller = new AbortController;
210
+ controllers.set(request.requestId, controller);
211
+ if (pendingCancels.delete(request.requestId)) {
212
+ controller.abort();
213
+ const response = {
214
+ ...request,
215
+ messages: [],
216
+ isError: true,
217
+ errorText: "Delegated prompt cancelled."
218
+ };
219
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
220
+ controllers.delete(request.requestId);
221
+ return;
222
+ }
223
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_STARTED_EVENT, { requestId: request.requestId });
224
+ try {
225
+ const result = await options.execute(request.requestId, request, controller.signal, ctx, (update) => {
226
+ const payload = toDelegationUpdate(request.requestId, update);
227
+ if (!payload)
228
+ return;
229
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_UPDATE_EVENT, payload);
230
+ });
231
+ const contentText = firstTextContent(result.content);
232
+ const messages = buildDelegationMessages(result.details?.results?.[0] ?? {}, contentText);
233
+ const parallelResults = request.tasks ? request.tasks.map((task, index) => {
234
+ const step = result.details?.results?.[index];
235
+ if (!step) {
236
+ return {
237
+ agent: task.agent,
238
+ messages: [],
239
+ isError: true,
240
+ errorText: "Missing result for delegated parallel task."
241
+ };
242
+ }
243
+ const exitCode = typeof step.exitCode === "number" ? step.exitCode : undefined;
244
+ const errorText = step.error;
245
+ return {
246
+ agent: step.agent ?? task.agent,
247
+ messages: buildDelegationMessages(step),
248
+ isError: exitCode !== undefined && exitCode !== 0 || !!errorText,
249
+ errorText: errorText || undefined
250
+ };
251
+ }) : undefined;
252
+ const response = {
253
+ ...request,
254
+ messages,
255
+ ...parallelResults ? { parallelResults } : {},
256
+ ...contentText ? { contentText } : {},
257
+ isError: result.isError === true,
258
+ errorText: result.isError ? contentText : undefined
259
+ };
260
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
261
+ } catch (error) {
262
+ const response = {
263
+ ...request,
264
+ messages: [],
265
+ isError: true,
266
+ errorText: error instanceof Error ? error.message : String(error)
267
+ };
268
+ options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
269
+ } finally {
270
+ controllers.delete(request.requestId);
271
+ }
272
+ });
273
+ return {
274
+ cancelAll: () => {
275
+ for (const controller of controllers.values()) {
276
+ controller.abort();
277
+ }
278
+ controllers.clear();
279
+ pendingCancels.clear();
280
+ },
281
+ dispose: () => {
282
+ for (const unsubscribe of subscriptions)
283
+ unsubscribe();
284
+ subscriptions.length = 0;
285
+ pendingCancels.clear();
286
+ }
287
+ };
288
+ }
@@ -1,7 +1,297 @@
1
- import*as N from"node:fs";import*as K from"node:path";import{fileURLToPath as t}from"node:url";function f(W){return W.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function S(W){let Q={},$=W.replace(/\r\n/g,`
2
- `);if(!$.startsWith("---"))return{frontmatter:Q,body:$};let Y=$.indexOf(`
3
- ---`,3);if(Y===-1)return{frontmatter:Q,body:$};let Z=$.slice(4,Y),J=$.slice(Y+4).trim(),X=Z.split(`
4
- `),U=null,q=null,V=null;for(let j of X){let H=j.search(/\S|$/),_=j.trim();if(U!==null&&q!==null&&H>(V??0)){q.push(j);continue}if(U!==null&&q!==null){let G=q.join(`
5
- `),b=G.match(/^([ \t]+)/m)?.[1]??"",g=b?G.replace(new RegExp(`^${f(b)}`,"gm"),"").replace(/^\n/,""):G;Q[U]=g,U=null,q=null,V=null}let A=j.match(/^([\w-]+):\s*(.*)$/);if(A){let G=A[2].trim();if(G.startsWith('"')&&G.endsWith('"')||G.startsWith("'")&&G.endsWith("'"))G=G.slice(1,-1);if(G==="")U=A[1],q=[],V=H;else Q[A[1]]=G}}if(U!==null&&q!==null){let j=q.join(`
6
- `),_=j.match(/^([ \t]+)/m)?.[1]??"",A=_?j.replace(new RegExp(`^${f(_)}`,"gm"),"").replace(/^\n/,""):j;Q[U]=A}return{frontmatter:Q,body:J}}import*as B from"node:fs";import*as T from"node:os";import*as E from"node:path";import*as M from"node:os";import*as F from"node:path";function z(W){return W.trim().replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}function u(W){let Q=W?.env??process.env,$=W&&Object.hasOwn(W,"getuid")?W.getuid:process.getuid?.bind(process);if(typeof $==="function")return`uid-${$()}`;for(let X of["USERNAME","USER","LOGNAME"]){let U=Q[X];if(U)return`user-${z(U)}`}let Y=W&&Object.hasOwn(W,"userInfo")?W.userInfo:M.userInfo;try{let X=Y?.().username;if(X)return`user-${z(X)}`}catch{}let Z=Q.USERPROFILE??Q.HOME;if(Z)return`home-${z(Z)}`;let J=W&&Object.hasOwn(W,"homedir")?W.homedir:M.homedir;try{let X=J?.();if(X)return`home-${z(X)}`}catch{}return"shared"}var O=F.join(M.tmpdir(),`dm-subagents-${u()}`),GW=F.join(O,"async-subagent-results"),BW=F.join(O,"async-subagent-runs"),p=F.join(O,"chain-runs"),EW=F.join(O,"artifacts");var d=".dm",o="@duckmind/dm-coding-agent",r="DM_SUBAGENTS_PI_CODING_AGENT_PACKAGE_ROOT";function D(W){return typeof W==="string"&&W.trim()?W:void 0}function y(W){if(!W)return;try{let Q=JSON.parse(B.readFileSync(E.join(W,"package.json"),"utf-8"));if(Q.name!==o)return;return D(Q.piConfig?.configDir)}catch{return}}function l(W=process.argv[1],Q=process.env[r]){let $=y(Q);if($)return $;if(!W)return;try{let Y=E.dirname(B.realpathSync(W));while(Y!==E.dirname(Y)){let Z=y(Y);if(Z)return Z;Y=E.dirname(Y)}}catch{}return}function i(W,Q,$){return(W&&typeof W==="object"?D(W.CONFIG_DIR_NAME):void 0)??l(Q,$)??d}function x(){return i()}function w(W){return E.join(W,x())}function C(){let W=process.env.DM_CODING_AGENT_DIR;if(W==="~")return T.homedir();if(W?.startsWith("~/"))return E.join(T.homedir(),W.slice(2));return W||E.join(T.homedir(),x(),"agent")}var a=new Set(["chain-prompts","prompt-workflow","run","chain","parallel","run-chain","subagents-doctor","subagents-models"]);function s(){return K.resolve(K.dirname(t(import.meta.url)),"..","..","prompts")}function e(W){return[s(),K.join(C(),"prompts"),K.join(w(W),"prompts")]}function WW(W){let Q=[];for(let $ of e(W)){let Y;try{Y=N.readdirSync($,{withFileTypes:!0})}catch{continue}for(let Z of Y)if(Z.isFile()&&Z.name.endsWith(".md"))Q.push(K.join($,Z.name))}return Q}function $W(W){return W.split(/\r?\n/).map((Q)=>Q.trim()).find(Boolean)??"Prompt workflow"}function L(W,Q){let $=W[Q]?.trim();return $?$:void 0}function R(W,Q){let $=W[Q]?.trim().toLowerCase();if($==="true"||$==="yes"||$==="1")return!0;if($==="false"||$==="no"||$==="0")return!1;return}function QW(W){if(!W)return;if(W==="false")return!1;let Q=W.split(",").map(($)=>$.trim()).filter(Boolean);return Q.length>1?Q:Q[0]}function YW(W){let Q=L(W,"subagent");if(!Q||Q==="true")return"delegate";return Q}function ZW(W){let Q=N.readFileSync(W,"utf-8"),{frontmatter:$,body:Y}=S(Q),Z=K.basename(W,".md");if(!Z||a.has(Z))return;let J=L($,"model"),X=QW(L($,"skill")),U=L($,"cwd"),q=L($,"chain");return{name:Z,description:L($,"description")??$W(Y),body:Y,filePath:W,agent:YW($),...R($,"inheritContext")===!0||R($,"fork")===!0?{context:"fork"}:{},...R($,"fresh")===!0?{context:"fresh"}:{},...J?{model:J}:{},...X!==void 0?{skill:X}:{},...U?{cwd:U}:{},...R($,"worktree")===!0?{worktree:!0}:{},...q?{chain:q}:{}}}function P(W){let Q=new Map;for(let $ of WW(W)){let Y=ZW($);if(Y)Q.set(Y.name,Y)}return[...Q.values()].sort(($,Y)=>$.name.localeCompare(Y.name))}function v(W){let Q=[],$="",Y,Z=!1;for(let J of W){if(Z){$+=J,Z=!1;continue}if(J==="\\"){Z=!0;continue}if(Y){if(J===Y)Y=void 0;else $+=J;continue}if(J==="'"||J==='"'){Y=J;continue}if(/\s/.test(J)){if($)Q.push($),$="";continue}$+=J}if($)Q.push($);return Q}function qW(W,Q){let $=Q.join(" ");return W.replace(/\$ARGUMENTS/g,$).replace(/\$@/g,$).replace(/\$\{(\d+):-([^}]*)\}/g,(Y,Z,J)=>Q[Number(Z)-1]||J).replace(/\$(\d+)/g,(Y,Z)=>Q[Number(Z)-1]??"")}function m(W){let Q=[],$,Y=!1,Z=!1,J=!1,X=!1;for(let U=0;U<W.length;U++){let q=W[U];if(q==="--fork"){Y=!0;continue}if(q==="--fresh"){Z=!0;continue}if(q==="--worktree"){J=!0;continue}if(q==="--bg"||q==="--async"){X=!0;continue}if(q==="--subagent"){$=W[++U];continue}let V=q.match(/^--subagent(?:=|:)(.+)$/);if(V){$=V[1];continue}Q.push(q)}return{args:Q,agentOverride:$,fork:Y,fresh:Z,worktree:J,bg:X}}function JW(W){let Q=W.indexOf(" -- ");if(Q===-1)return{declaration:W.trim(),argsText:""};return{declaration:W.slice(0,Q).trim(),argsText:W.slice(Q+4).trim()}}function k(W){return W.split(" -> ").map((Q)=>Q.trim()).filter(Boolean)}function n(W,Q,$){let Y=qW(W.body,Q).trim(),Z=$.fork?"fork":$.fresh?"fresh":W.context;return{agent:$.agentOverride??W.agent,task:Y,clarify:!1,agentScope:"both",...Z?{context:Z}:{},...W.model?{model:W.model}:{},...W.skill!==void 0?{skill:W.skill}:{},...W.cwd?{cwd:W.cwd}:{},...$.worktree||W.worktree?{worktree:!0}:{},...$.bg?{async:!0}:{}}}function h(W,Q,$){let Y=n(W,Q,$);return{agent:Y.agent??"delegate",task:Y.task,...Y.model?{model:Y.model}:{},...Y.skill!==void 0?{skill:Y.skill}:{},...Y.cwd?{cwd:Y.cwd}:{}}}function I(W,Q){return W.find(($)=>$.name===Q)}function c(W){if(W.length===0)return"No prompt workflows found in package, user, or project prompts.";return["Prompt workflows:",...W.map((Q)=>`- ${Q.name}: ${Q.description} (${Q.filePath})`)].join(`
7
- `)}function kW(W){let{pi:Q,run:$}=W;Q.registerCommand("prompt-workflow",{description:"Run a prompt template through native dm-subagents: /prompt-workflow <name> [args]",handler:async(Y,Z)=>{let J=v(Y),X=J.shift(),U=P(Z.cwd);if(!X||X==="list"){Q.sendMessage({content:c(U),display:!0});return}let q=I(U,X);if(!q){Z.ui.notify(`Unknown prompt workflow: ${X}`,"error");return}let V=m(J);try{if(q.chain){let H=k(q.chain).map((_)=>{let A=I(U,_);if(!A)throw Error(`Unknown prompt workflow in chain '${q.name}': ${_}`);return h(A,V.args,V)});await $({chain:H,task:V.args.join(" "),clarify:!1,agentScope:"both",...V.bg?{async:!0}:{}},Z);return}await $(n(q,V.args,V),Z)}catch(j){Z.ui.notify(j instanceof Error?j.message:String(j),"error")}}}),Q.registerCommand("chain-prompts",{description:"Run prompt templates as a native subagent chain: /chain-prompts analyze -> fix -- args",handler:async(Y,Z)=>{let{declaration:J,argsText:X}=JW(Y),U=P(Z.cwd);if(!J||J==="list"){Q.sendMessage({content:c(U),display:!0});return}let q=m(v(X)),V=k(J);if(V.length===0){Z.ui.notify("Usage: /chain-prompts prompt-a -> prompt-b -- args","error");return}try{let j=V.map((H)=>{let _=I(U,H);if(!_)throw Error(`Unknown prompt workflow: ${H}`);return h(_,q.args,q)});await $({chain:j,task:q.args.join(" "),clarify:!1,agentScope:"both",...q.bg?{async:!0}:{}},Z)}catch(j){Z.ui.notify(j instanceof Error?j.message:String(j),"error")}}})}export{kW as registerPromptWorkflowCommands,P as discoverPromptWorkflows};
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { parseFrontmatter } from "../agents/frontmatter.js";
5
+ import { getAgentDir, getProjectConfigDir } from "../shared/utils.js";
6
+ const RESERVED_COMMAND_NAMES = new Set([
7
+ "chain-prompts",
8
+ "prompt-workflow",
9
+ "run",
10
+ "chain",
11
+ "parallel",
12
+ "run-chain",
13
+ "subagents-doctor",
14
+ "subagents-models"
15
+ ]);
16
+ function packagePromptsDir() {
17
+ return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "prompts");
18
+ }
19
+ function promptDirs(cwd) {
20
+ return [
21
+ packagePromptsDir(),
22
+ path.join(getAgentDir(), "prompts"),
23
+ path.join(getProjectConfigDir(cwd), "prompts")
24
+ ];
25
+ }
26
+ function readPromptFiles(cwd) {
27
+ const files = [];
28
+ for (const dir of promptDirs(cwd)) {
29
+ let entries;
30
+ try {
31
+ entries = fs.readdirSync(dir, { withFileTypes: true });
32
+ } catch {
33
+ continue;
34
+ }
35
+ for (const entry of entries) {
36
+ if (entry.isFile() && entry.name.endsWith(".md"))
37
+ files.push(path.join(dir, entry.name));
38
+ }
39
+ }
40
+ return files;
41
+ }
42
+ function firstNonEmptyLine(value) {
43
+ return value.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? "Prompt workflow";
44
+ }
45
+ function stringField(frontmatter, key) {
46
+ const value = frontmatter[key]?.trim();
47
+ return value ? value : undefined;
48
+ }
49
+ function booleanField(frontmatter, key) {
50
+ const value = frontmatter[key]?.trim().toLowerCase();
51
+ if (value === "true" || value === "yes" || value === "1")
52
+ return true;
53
+ if (value === "false" || value === "no" || value === "0")
54
+ return false;
55
+ return;
56
+ }
57
+ function parseSkill(value) {
58
+ if (!value)
59
+ return;
60
+ if (value === "false")
61
+ return false;
62
+ const parts = value.split(",").map((part) => part.trim()).filter(Boolean);
63
+ return parts.length > 1 ? parts : parts[0];
64
+ }
65
+ function parseAgent(frontmatter) {
66
+ const subagent = stringField(frontmatter, "subagent");
67
+ if (!subagent || subagent === "true")
68
+ return "delegate";
69
+ return subagent;
70
+ }
71
+ function loadPromptWorkflow(filePath) {
72
+ const content = fs.readFileSync(filePath, "utf-8");
73
+ const { frontmatter, body } = parseFrontmatter(content);
74
+ const name = path.basename(filePath, ".md");
75
+ if (!name || RESERVED_COMMAND_NAMES.has(name))
76
+ return;
77
+ const model = stringField(frontmatter, "model");
78
+ const skill = parseSkill(stringField(frontmatter, "skill"));
79
+ const cwd = stringField(frontmatter, "cwd");
80
+ const chain = stringField(frontmatter, "chain");
81
+ return {
82
+ name,
83
+ description: stringField(frontmatter, "description") ?? firstNonEmptyLine(body),
84
+ body,
85
+ filePath,
86
+ agent: parseAgent(frontmatter),
87
+ ...booleanField(frontmatter, "inheritContext") === true || booleanField(frontmatter, "fork") === true ? { context: "fork" } : {},
88
+ ...booleanField(frontmatter, "fresh") === true ? { context: "fresh" } : {},
89
+ ...model ? { model } : {},
90
+ ...skill !== undefined ? { skill } : {},
91
+ ...cwd ? { cwd } : {},
92
+ ...booleanField(frontmatter, "worktree") === true ? { worktree: true } : {},
93
+ ...chain ? { chain } : {}
94
+ };
95
+ }
96
+ export function discoverPromptWorkflows(cwd) {
97
+ const workflows = new Map;
98
+ for (const file of readPromptFiles(cwd)) {
99
+ const workflow = loadPromptWorkflow(file);
100
+ if (workflow)
101
+ workflows.set(workflow.name, workflow);
102
+ }
103
+ return [...workflows.values()].sort((a, b) => a.name.localeCompare(b.name));
104
+ }
105
+ function shellWords(input) {
106
+ const words = [];
107
+ let current = "";
108
+ let quote;
109
+ let escaped = false;
110
+ for (const ch of input) {
111
+ if (escaped) {
112
+ current += ch;
113
+ escaped = false;
114
+ continue;
115
+ }
116
+ if (ch === "\\") {
117
+ escaped = true;
118
+ continue;
119
+ }
120
+ if (quote) {
121
+ if (ch === quote)
122
+ quote = undefined;
123
+ else
124
+ current += ch;
125
+ continue;
126
+ }
127
+ if (ch === "'" || ch === '"') {
128
+ quote = ch;
129
+ continue;
130
+ }
131
+ if (/\s/.test(ch)) {
132
+ if (current) {
133
+ words.push(current);
134
+ current = "";
135
+ }
136
+ continue;
137
+ }
138
+ current += ch;
139
+ }
140
+ if (current)
141
+ words.push(current);
142
+ return words;
143
+ }
144
+ function substituteArgs(template, args) {
145
+ const all = args.join(" ");
146
+ return template.replace(/\$ARGUMENTS/g, all).replace(/\$@/g, all).replace(/\$\{(\d+):-([^}]*)\}/g, (_match, index, fallback) => args[Number(index) - 1] || fallback).replace(/\$(\d+)/g, (_match, index) => args[Number(index) - 1] ?? "");
147
+ }
148
+ function parseRuntimeOptions(words) {
149
+ const args = [];
150
+ let agentOverride;
151
+ let fork = false;
152
+ let fresh = false;
153
+ let worktree = false;
154
+ let bg = false;
155
+ for (let i = 0;i < words.length; i++) {
156
+ const word = words[i];
157
+ if (word === "--fork") {
158
+ fork = true;
159
+ continue;
160
+ }
161
+ if (word === "--fresh") {
162
+ fresh = true;
163
+ continue;
164
+ }
165
+ if (word === "--worktree") {
166
+ worktree = true;
167
+ continue;
168
+ }
169
+ if (word === "--bg" || word === "--async") {
170
+ bg = true;
171
+ continue;
172
+ }
173
+ if (word === "--subagent") {
174
+ agentOverride = words[++i];
175
+ continue;
176
+ }
177
+ const eq = word.match(/^--subagent(?:=|:)(.+)$/);
178
+ if (eq) {
179
+ agentOverride = eq[1];
180
+ continue;
181
+ }
182
+ args.push(word);
183
+ }
184
+ return { args, agentOverride, fork, fresh, worktree, bg };
185
+ }
186
+ function splitChainDeclaration(input) {
187
+ const delimiter = input.indexOf(" -- ");
188
+ if (delimiter === -1)
189
+ return { declaration: input.trim(), argsText: "" };
190
+ return { declaration: input.slice(0, delimiter).trim(), argsText: input.slice(delimiter + 4).trim() };
191
+ }
192
+ function splitPromptChain(input) {
193
+ return input.split(" -> ").map((part) => part.trim()).filter(Boolean);
194
+ }
195
+ function workflowParams(workflow, args, runtime) {
196
+ const task = substituteArgs(workflow.body, args).trim();
197
+ const context = runtime.fork ? "fork" : runtime.fresh ? "fresh" : workflow.context;
198
+ return {
199
+ agent: runtime.agentOverride ?? workflow.agent,
200
+ task,
201
+ clarify: false,
202
+ agentScope: "both",
203
+ ...context ? { context } : {},
204
+ ...workflow.model ? { model: workflow.model } : {},
205
+ ...workflow.skill !== undefined ? { skill: workflow.skill } : {},
206
+ ...workflow.cwd ? { cwd: workflow.cwd } : {},
207
+ ...runtime.worktree || workflow.worktree ? { worktree: true } : {},
208
+ ...runtime.bg ? { async: true } : {}
209
+ };
210
+ }
211
+ function workflowChainStep(workflow, args, runtime) {
212
+ const params = workflowParams(workflow, args, runtime);
213
+ return {
214
+ agent: params.agent ?? "delegate",
215
+ task: params.task,
216
+ ...params.model ? { model: params.model } : {},
217
+ ...params.skill !== undefined ? { skill: params.skill } : {},
218
+ ...params.cwd ? { cwd: params.cwd } : {}
219
+ };
220
+ }
221
+ function findWorkflow(workflows, name) {
222
+ return workflows.find((workflow) => workflow.name === name);
223
+ }
224
+ function formatWorkflowList(workflows) {
225
+ if (workflows.length === 0)
226
+ return "No prompt workflows found in package, user, or project prompts.";
227
+ return [
228
+ "Prompt workflows:",
229
+ ...workflows.map((workflow) => `- ${workflow.name}: ${workflow.description} (${workflow.filePath})`)
230
+ ].join(`
231
+ `);
232
+ }
233
+ export function registerPromptWorkflowCommands(input) {
234
+ const { pi, run } = input;
235
+ pi.registerCommand("prompt-workflow", {
236
+ description: "Run a prompt template through native dm-subagents: /prompt-workflow <name> [args]",
237
+ handler: async (rawArgs, ctx) => {
238
+ const words = shellWords(rawArgs);
239
+ const name = words.shift();
240
+ const workflows = discoverPromptWorkflows(ctx.cwd);
241
+ if (!name || name === "list") {
242
+ pi.sendMessage({ content: formatWorkflowList(workflows), display: true });
243
+ return;
244
+ }
245
+ const workflow = findWorkflow(workflows, name);
246
+ if (!workflow) {
247
+ ctx.ui.notify(`Unknown prompt workflow: ${name}`, "error");
248
+ return;
249
+ }
250
+ const runtime = parseRuntimeOptions(words);
251
+ try {
252
+ if (workflow.chain) {
253
+ const chainNames = splitPromptChain(workflow.chain);
254
+ const chain = chainNames.map((stepName) => {
255
+ const step = findWorkflow(workflows, stepName);
256
+ if (!step)
257
+ throw new Error(`Unknown prompt workflow in chain '${workflow.name}': ${stepName}`);
258
+ return workflowChainStep(step, runtime.args, runtime);
259
+ });
260
+ await run({ chain, task: runtime.args.join(" "), clarify: false, agentScope: "both", ...runtime.bg ? { async: true } : {} }, ctx);
261
+ return;
262
+ }
263
+ await run(workflowParams(workflow, runtime.args, runtime), ctx);
264
+ } catch (error) {
265
+ ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
266
+ }
267
+ }
268
+ });
269
+ pi.registerCommand("chain-prompts", {
270
+ description: "Run prompt templates as a native subagent chain: /chain-prompts analyze -> fix -- args",
271
+ handler: async (rawArgs, ctx) => {
272
+ const { declaration, argsText } = splitChainDeclaration(rawArgs);
273
+ const workflows = discoverPromptWorkflows(ctx.cwd);
274
+ if (!declaration || declaration === "list") {
275
+ pi.sendMessage({ content: formatWorkflowList(workflows), display: true });
276
+ return;
277
+ }
278
+ const runtime = parseRuntimeOptions(shellWords(argsText));
279
+ const names = splitPromptChain(declaration);
280
+ if (names.length === 0) {
281
+ ctx.ui.notify("Usage: /chain-prompts prompt-a -> prompt-b -- args", "error");
282
+ return;
283
+ }
284
+ try {
285
+ const chain = names.map((name) => {
286
+ const workflow = findWorkflow(workflows, name);
287
+ if (!workflow)
288
+ throw new Error(`Unknown prompt workflow: ${name}`);
289
+ return workflowChainStep(workflow, runtime.args, runtime);
290
+ });
291
+ await run({ chain, task: runtime.args.join(" "), clarify: false, agentScope: "both", ...runtime.bg ? { async: true } : {} }, ctx);
292
+ } catch (error) {
293
+ ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
294
+ }
295
+ }
296
+ });
297
+ }