@duckmind/dm-darwin-x64 0.43.4 → 0.48.5

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 (254) hide show
  1. package/dm +0 -0
  2. package/extensions/.dm-extensions.json +242 -50
  3. package/extensions/dm-9router-ext/package.json +2 -19
  4. package/extensions/dm-9router-ext/src/index.js +5 -0
  5. package/extensions/dm-ask-user/index.js +10 -0
  6. package/extensions/dm-ask-user/package.json +1 -21
  7. package/extensions/dm-cli-anything/package.json +0 -6
  8. package/extensions/dm-context/package.json +2 -12
  9. package/extensions/dm-context/src/context.js +1 -0
  10. package/extensions/dm-context/src/index.js +7 -0
  11. package/extensions/dm-context/src/utils.js +1 -0
  12. package/extensions/dm-cua/package.json +0 -7
  13. package/extensions/dm-fff/package.json +1 -28
  14. package/extensions/dm-fff/src/index.js +15 -0
  15. package/extensions/dm-fff/src/query.js +1 -0
  16. package/extensions/dm-goal/package.json +2 -31
  17. package/extensions/dm-goal/src/goal.js +43 -0
  18. package/extensions/dm-grill-me/index.js +174 -0
  19. package/extensions/dm-grill-me/package.json +1 -26
  20. package/extensions/dm-image2/package.json +0 -7
  21. package/extensions/dm-subagents/package.json +1 -32
  22. package/extensions/dm-subagents/src/agents/agent-management.js +37 -0
  23. package/extensions/dm-subagents/src/agents/agent-memory.js +6 -0
  24. package/extensions/dm-subagents/src/agents/agent-scope.js +1 -0
  25. package/extensions/dm-subagents/src/agents/agent-selection.js +1 -0
  26. package/extensions/dm-subagents/src/agents/agent-serializer.js +7 -0
  27. package/extensions/dm-subagents/src/agents/agents.js +11 -0
  28. package/extensions/dm-subagents/src/agents/chain-serializer.js +12 -0
  29. package/extensions/dm-subagents/src/agents/frontmatter.js +6 -0
  30. package/extensions/dm-subagents/src/agents/identity.js +1 -0
  31. package/extensions/dm-subagents/src/agents/proactive-skills.js +1 -0
  32. package/extensions/dm-subagents/src/agents/skills.js +6 -0
  33. package/extensions/dm-subagents/src/extension/config.js +2 -0
  34. package/extensions/dm-subagents/src/extension/control-notices.js +4 -0
  35. package/extensions/dm-subagents/src/extension/doctor.js +16 -0
  36. package/extensions/dm-subagents/src/extension/fanout-child.js +231 -0
  37. package/extensions/dm-subagents/src/extension/index.js +367 -0
  38. package/extensions/dm-subagents/src/extension/rpc.js +8 -0
  39. package/extensions/dm-subagents/src/extension/schemas.js +1 -0
  40. package/extensions/dm-subagents/src/extension/{tool-description.ts → tool-description.js} +6 -126
  41. package/extensions/dm-subagents/src/intercom/intercom-bridge.js +13 -0
  42. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +5 -0
  43. package/extensions/dm-subagents/src/intercom/result-intercom.js +3 -0
  44. package/extensions/dm-subagents/src/profiles/profiles.js +3 -0
  45. package/extensions/dm-subagents/src/runs/background/async-execution.js +46 -0
  46. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +14 -0
  47. package/extensions/dm-subagents/src/runs/background/async-resume.js +8 -0
  48. package/extensions/dm-subagents/src/runs/background/async-status.js +12 -0
  49. package/extensions/dm-subagents/src/runs/background/chain-append.js +2 -0
  50. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +1 -0
  51. package/extensions/dm-subagents/src/runs/background/completion-batcher.js +1 -0
  52. package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +1 -0
  53. package/extensions/dm-subagents/src/runs/background/control-channel.js +1 -0
  54. package/extensions/dm-subagents/src/runs/background/fleet-view.js +17 -0
  55. package/extensions/dm-subagents/src/runs/background/notify.js +3 -0
  56. package/extensions/dm-subagents/src/runs/background/parallel-groups.js +1 -0
  57. package/extensions/dm-subagents/src/runs/background/result-watcher.js +8 -0
  58. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +4 -0
  59. package/extensions/dm-subagents/src/runs/background/run-status.js +23 -0
  60. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +4 -0
  61. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +11 -0
  62. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +78 -0
  63. package/extensions/dm-subagents/src/runs/background/top-level-async.js +1 -0
  64. package/extensions/dm-subagents/src/runs/background/wait.js +11 -0
  65. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +12 -0
  66. package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +102 -0
  67. package/extensions/dm-subagents/src/runs/foreground/execution.js +51 -0
  68. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +228 -0
  69. package/extensions/dm-subagents/src/runs/shared/acceptance.js +3 -0
  70. package/extensions/dm-subagents/src/runs/shared/chain-outputs.js +1 -0
  71. package/extensions/dm-subagents/src/runs/shared/completion-guard.js +3 -0
  72. package/extensions/dm-subagents/src/runs/shared/dm-args.js +1 -0
  73. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +1 -0
  74. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +1 -0
  75. package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +1 -0
  76. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +1 -0
  77. package/extensions/dm-subagents/src/runs/shared/model-fallback.js +1 -0
  78. package/extensions/dm-subagents/src/runs/shared/model-scope.js +1 -0
  79. package/extensions/dm-subagents/src/runs/shared/nested-events.js +8 -0
  80. package/extensions/dm-subagents/src/runs/shared/nested-path.js +1 -0
  81. package/extensions/dm-subagents/src/runs/shared/nested-render.js +1 -0
  82. package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +5 -0
  83. package/extensions/dm-subagents/src/runs/shared/run-history.js +5 -0
  84. package/extensions/dm-subagents/src/runs/shared/single-output.js +14 -0
  85. package/extensions/dm-subagents/src/runs/shared/structured-output.js +1 -0
  86. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +5 -0
  87. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +22 -0
  88. package/extensions/dm-subagents/src/runs/shared/tool-budget.js +1 -0
  89. package/extensions/dm-subagents/src/runs/shared/turn-budget.js +7 -0
  90. package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +1 -0
  91. package/extensions/dm-subagents/src/runs/shared/worktree.js +3 -0
  92. package/extensions/dm-subagents/src/shared/artifacts.js +2 -0
  93. package/extensions/dm-subagents/src/shared/atomic-json.js +1 -0
  94. package/extensions/dm-subagents/src/shared/child-transcript.js +5 -0
  95. package/extensions/dm-subagents/src/shared/file-coalescer.js +1 -0
  96. package/extensions/dm-subagents/src/shared/fork-context.js +6 -0
  97. package/extensions/dm-subagents/src/shared/formatters.js +9 -0
  98. package/extensions/dm-subagents/src/shared/jsonl-writer.js +2 -0
  99. package/extensions/dm-subagents/src/shared/model-info.js +1 -0
  100. package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +1 -0
  101. package/extensions/dm-subagents/src/shared/session-identity.js +1 -0
  102. package/extensions/dm-subagents/src/shared/session-tokens.js +2 -0
  103. package/extensions/dm-subagents/src/shared/settings.js +23 -0
  104. package/extensions/dm-subagents/src/shared/status-format.js +1 -0
  105. package/extensions/dm-subagents/src/shared/types.js +8 -0
  106. package/extensions/dm-subagents/src/shared/utils.js +2 -0
  107. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +1 -0
  108. package/extensions/dm-subagents/src/slash/prompt-workflows.js +7 -0
  109. package/extensions/dm-subagents/src/slash/slash-bridge.js +1 -0
  110. package/extensions/dm-subagents/src/slash/slash-commands.js +38 -0
  111. package/extensions/dm-subagents/src/slash/slash-live-state.js +6 -0
  112. package/extensions/dm-subagents/src/tui/render-helpers.js +1 -0
  113. package/extensions/dm-subagents/src/tui/render.js +4 -0
  114. package/extensions/dm-tasks/package.json +1 -30
  115. package/extensions/dm-tasks/src/auto-clear.js +1 -0
  116. package/extensions/dm-tasks/src/index.js +212 -0
  117. package/extensions/dm-tasks/src/process-tracker.js +1 -0
  118. package/extensions/dm-tasks/src/task-store.js +1 -0
  119. package/extensions/dm-tasks/src/tasks-config.js +1 -0
  120. package/extensions/dm-tasks/src/types.js +0 -0
  121. package/extensions/dm-tasks/src/ui/settings-menu.js +1 -0
  122. package/extensions/dm-tasks/src/ui/task-widget.js +1 -0
  123. package/extensions/dm-usage/index.js +9 -0
  124. package/extensions/dm-usage/package.json +1 -18
  125. package/extensions/greedysearch-dm/bin/search.mjs +51 -51
  126. package/extensions/greedysearch-dm/index.js +20 -0
  127. package/extensions/greedysearch-dm/package.json +1 -22
  128. package/extensions/greedysearch-dm/src/formatters/results.js +8 -0
  129. package/extensions/greedysearch-dm/src/formatters/sources.js +1 -0
  130. package/extensions/greedysearch-dm/src/formatters/synthesis.js +1 -0
  131. package/extensions/greedysearch-dm/src/search/research.mjs +59 -59
  132. package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +10 -10
  133. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +20 -0
  134. package/extensions/greedysearch-dm/src/tools/shared.js +9 -0
  135. package/extensions/greedysearch-dm/src/types.js +0 -0
  136. package/extensions/greedysearch-dm/src/utils/helpers.js +1 -0
  137. package/package.json +1 -1
  138. package/extensions/dm-9router-ext/src/index.ts +0 -541
  139. package/extensions/dm-ask-user/index.ts +0 -857
  140. package/extensions/dm-context/src/context.ts +0 -158
  141. package/extensions/dm-context/src/index.ts +0 -439
  142. package/extensions/dm-context/src/utils.ts +0 -6
  143. package/extensions/dm-fff/src/index.ts +0 -1023
  144. package/extensions/dm-fff/src/query.ts +0 -87
  145. package/extensions/dm-goal/src/goal.ts +0 -1073
  146. package/extensions/dm-grill-me/index.ts +0 -1085
  147. package/extensions/dm-subagents/src/agents/agent-management.ts +0 -1052
  148. package/extensions/dm-subagents/src/agents/agent-memory.ts +0 -254
  149. package/extensions/dm-subagents/src/agents/agent-scope.ts +0 -6
  150. package/extensions/dm-subagents/src/agents/agent-selection.ts +0 -25
  151. package/extensions/dm-subagents/src/agents/agent-serializer.ts +0 -121
  152. package/extensions/dm-subagents/src/agents/agents.ts +0 -1553
  153. package/extensions/dm-subagents/src/agents/chain-serializer.ts +0 -277
  154. package/extensions/dm-subagents/src/agents/frontmatter.ts +0 -93
  155. package/extensions/dm-subagents/src/agents/identity.ts +0 -30
  156. package/extensions/dm-subagents/src/agents/proactive-skills.ts +0 -191
  157. package/extensions/dm-subagents/src/agents/skills.ts +0 -729
  158. package/extensions/dm-subagents/src/extension/config.ts +0 -39
  159. package/extensions/dm-subagents/src/extension/control-notices.ts +0 -92
  160. package/extensions/dm-subagents/src/extension/doctor.ts +0 -214
  161. package/extensions/dm-subagents/src/extension/fanout-child.ts +0 -172
  162. package/extensions/dm-subagents/src/extension/index.ts +0 -656
  163. package/extensions/dm-subagents/src/extension/rpc.ts +0 -369
  164. package/extensions/dm-subagents/src/extension/schemas.ts +0 -309
  165. package/extensions/dm-subagents/src/intercom/intercom-bridge.ts +0 -180
  166. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.ts +0 -519
  167. package/extensions/dm-subagents/src/intercom/result-intercom.ts +0 -377
  168. package/extensions/dm-subagents/src/profiles/profiles.ts +0 -637
  169. package/extensions/dm-subagents/src/runs/background/async-execution.ts +0 -1065
  170. package/extensions/dm-subagents/src/runs/background/async-job-tracker.ts +0 -441
  171. package/extensions/dm-subagents/src/runs/background/async-resume.ts +0 -391
  172. package/extensions/dm-subagents/src/runs/background/async-status.ts +0 -395
  173. package/extensions/dm-subagents/src/runs/background/chain-append.ts +0 -282
  174. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.ts +0 -191
  175. package/extensions/dm-subagents/src/runs/background/completion-batcher.ts +0 -166
  176. package/extensions/dm-subagents/src/runs/background/completion-dedupe.ts +0 -63
  177. package/extensions/dm-subagents/src/runs/background/control-channel.ts +0 -332
  178. package/extensions/dm-subagents/src/runs/background/fleet-view.ts +0 -515
  179. package/extensions/dm-subagents/src/runs/background/notify.ts +0 -225
  180. package/extensions/dm-subagents/src/runs/background/parallel-groups.ts +0 -45
  181. package/extensions/dm-subagents/src/runs/background/result-watcher.ts +0 -315
  182. package/extensions/dm-subagents/src/runs/background/run-id-resolver.ts +0 -84
  183. package/extensions/dm-subagents/src/runs/background/run-status.ts +0 -434
  184. package/extensions/dm-subagents/src/runs/background/scheduled-runs.ts +0 -514
  185. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.ts +0 -368
  186. package/extensions/dm-subagents/src/runs/background/subagent-runner.ts +0 -3171
  187. package/extensions/dm-subagents/src/runs/background/top-level-async.ts +0 -13
  188. package/extensions/dm-subagents/src/runs/background/wait.ts +0 -353
  189. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.ts +0 -1333
  190. package/extensions/dm-subagents/src/runs/foreground/chain-execution.ts +0 -1313
  191. package/extensions/dm-subagents/src/runs/foreground/execution.ts +0 -1239
  192. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.ts +0 -3613
  193. package/extensions/dm-subagents/src/runs/shared/acceptance.ts +0 -879
  194. package/extensions/dm-subagents/src/runs/shared/chain-outputs.ts +0 -116
  195. package/extensions/dm-subagents/src/runs/shared/completion-guard.ts +0 -147
  196. package/extensions/dm-subagents/src/runs/shared/dm-args.ts +0 -271
  197. package/extensions/dm-subagents/src/runs/shared/dm-spawn.ts +0 -147
  198. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.ts +0 -295
  199. package/extensions/dm-subagents/src/runs/shared/long-running-guard.ts +0 -175
  200. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +0 -365
  201. package/extensions/dm-subagents/src/runs/shared/model-fallback.ts +0 -292
  202. package/extensions/dm-subagents/src/runs/shared/model-scope.ts +0 -128
  203. package/extensions/dm-subagents/src/runs/shared/nested-events.ts +0 -908
  204. package/extensions/dm-subagents/src/runs/shared/nested-path.ts +0 -52
  205. package/extensions/dm-subagents/src/runs/shared/nested-render.ts +0 -115
  206. package/extensions/dm-subagents/src/runs/shared/parallel-utils.ts +0 -198
  207. package/extensions/dm-subagents/src/runs/shared/run-history.ts +0 -60
  208. package/extensions/dm-subagents/src/runs/shared/single-output.ts +0 -180
  209. package/extensions/dm-subagents/src/runs/shared/structured-output.ts +0 -77
  210. package/extensions/dm-subagents/src/runs/shared/subagent-control.ts +0 -223
  211. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.ts +0 -342
  212. package/extensions/dm-subagents/src/runs/shared/tool-budget.ts +0 -74
  213. package/extensions/dm-subagents/src/runs/shared/turn-budget.ts +0 -52
  214. package/extensions/dm-subagents/src/runs/shared/workflow-graph.ts +0 -206
  215. package/extensions/dm-subagents/src/runs/shared/worktree.ts +0 -600
  216. package/extensions/dm-subagents/src/shared/artifacts.ts +0 -113
  217. package/extensions/dm-subagents/src/shared/atomic-json.ts +0 -86
  218. package/extensions/dm-subagents/src/shared/child-transcript.ts +0 -212
  219. package/extensions/dm-subagents/src/shared/file-coalescer.ts +0 -40
  220. package/extensions/dm-subagents/src/shared/fork-context.ts +0 -194
  221. package/extensions/dm-subagents/src/shared/formatters.ts +0 -133
  222. package/extensions/dm-subagents/src/shared/jsonl-writer.ts +0 -81
  223. package/extensions/dm-subagents/src/shared/model-info.ts +0 -78
  224. package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
  225. package/extensions/dm-subagents/src/shared/session-identity.ts +0 -10
  226. package/extensions/dm-subagents/src/shared/session-tokens.ts +0 -44
  227. package/extensions/dm-subagents/src/shared/settings.ts +0 -450
  228. package/extensions/dm-subagents/src/shared/status-format.ts +0 -49
  229. package/extensions/dm-subagents/src/shared/types.ts +0 -1257
  230. package/extensions/dm-subagents/src/shared/utils.ts +0 -554
  231. package/extensions/dm-subagents/src/slash/prompt-template-bridge.ts +0 -420
  232. package/extensions/dm-subagents/src/slash/prompt-workflows.ts +0 -330
  233. package/extensions/dm-subagents/src/slash/slash-bridge.ts +0 -176
  234. package/extensions/dm-subagents/src/slash/slash-commands.ts +0 -1296
  235. package/extensions/dm-subagents/src/slash/slash-live-state.ts +0 -292
  236. package/extensions/dm-subagents/src/tui/render-helpers.ts +0 -80
  237. package/extensions/dm-subagents/src/tui/render.ts +0 -1748
  238. package/extensions/dm-tasks/src/auto-clear.ts +0 -91
  239. package/extensions/dm-tasks/src/index.ts +0 -1145
  240. package/extensions/dm-tasks/src/process-tracker.ts +0 -140
  241. package/extensions/dm-tasks/src/task-store.ts +0 -305
  242. package/extensions/dm-tasks/src/tasks-config.ts +0 -23
  243. package/extensions/dm-tasks/src/types.ts +0 -40
  244. package/extensions/dm-tasks/src/ui/settings-menu.ts +0 -100
  245. package/extensions/dm-tasks/src/ui/task-widget.ts +0 -265
  246. package/extensions/dm-usage/index.ts +0 -1718
  247. package/extensions/greedysearch-dm/index.ts +0 -177
  248. package/extensions/greedysearch-dm/src/formatters/results.ts +0 -163
  249. package/extensions/greedysearch-dm/src/formatters/sources.ts +0 -116
  250. package/extensions/greedysearch-dm/src/formatters/synthesis.ts +0 -87
  251. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.ts +0 -370
  252. package/extensions/greedysearch-dm/src/tools/shared.ts +0 -187
  253. package/extensions/greedysearch-dm/src/types.ts +0 -110
  254. package/extensions/greedysearch-dm/src/utils/helpers.ts +0 -40
@@ -1,277 +0,0 @@
1
- import type { ChainConfig, ChainStepConfig } from "./agents.ts";
2
- import { buildRuntimeName, frontmatterNameForConfig, parsePackageName } from "./identity.ts";
3
- import { parseFrontmatter } from "./frontmatter.ts";
4
- import { ChainOutputValidationError, validateChainOutputBindings } from "../runs/shared/chain-outputs.ts";
5
- import { validateAcceptanceInput } from "../runs/shared/acceptance.ts";
6
- import { validateToolBudgetConfig } from "../runs/shared/tool-budget.ts";
7
- import type { ChainStep } from "../shared/settings.ts";
8
- import type { AgentSource } from "./agents.ts";
9
-
10
- function parseStepBody(agent: string, sectionBody: string): ChainStepConfig {
11
- const lines = sectionBody.split("\n");
12
- const blankIndex = lines.findIndex((line) => line.trim() === "");
13
- const configLines = blankIndex === -1 ? lines : lines.slice(0, blankIndex);
14
- const task = (blankIndex === -1 ? "" : lines.slice(blankIndex + 1).join("\n")).trim();
15
-
16
- const step: ChainStepConfig = { agent, task };
17
- for (const line of configLines) {
18
- const match = line.match(/^([\w-]+):\s*(.*)$/);
19
- if (!match) continue;
20
- const key = match[1].trim().toLowerCase();
21
- const rawValue = match[2].trim();
22
-
23
- if (key === "output") {
24
- if (rawValue === "false") step.output = false;
25
- else if (rawValue) step.output = rawValue;
26
- continue;
27
- }
28
- if (key === "phase") {
29
- if (rawValue) step.phase = rawValue;
30
- continue;
31
- }
32
- if (key === "label") {
33
- if (rawValue) step.label = rawValue;
34
- continue;
35
- }
36
- if (key === "as") {
37
- if (rawValue) step.as = rawValue;
38
- continue;
39
- }
40
- if (key === "outputschema") {
41
- if (rawValue.startsWith("{") || rawValue.startsWith("[")) {
42
- throw new Error("Inline outputSchema values are not supported in .chain.md files; use a schema file path.");
43
- }
44
- if (rawValue) step.outputSchema = rawValue;
45
- continue;
46
- }
47
- if (key === "outputmode") {
48
- if (rawValue === "inline" || rawValue === "file-only") step.outputMode = rawValue;
49
- continue;
50
- }
51
- if (key === "reads") {
52
- if (rawValue === "false") {
53
- step.reads = false;
54
- } else {
55
- const reads = rawValue
56
- .split(",")
57
- .map((v) => v.trim())
58
- .filter(Boolean);
59
- step.reads = reads.length > 0 ? reads : false;
60
- }
61
- continue;
62
- }
63
- if (key === "model") {
64
- if (rawValue) step.model = rawValue;
65
- continue;
66
- }
67
- if (key === "skills") {
68
- if (rawValue === "false") {
69
- step.skills = false;
70
- } else {
71
- const skills = rawValue
72
- .split(",")
73
- .map((v) => v.trim())
74
- .filter(Boolean);
75
- step.skills = skills.length > 0 ? skills : false;
76
- }
77
- continue;
78
- }
79
- if (key === "progress") {
80
- if (rawValue === "true") step.progress = true;
81
- else if (rawValue === "false") step.progress = false;
82
- continue;
83
- }
84
- if (key === "toolbudget") {
85
- let parsed: unknown;
86
- try {
87
- parsed = JSON.parse(rawValue);
88
- } catch (error) {
89
- const message = error instanceof Error ? error.message : String(error);
90
- throw new Error(`Invalid toolBudget in .chain.md step '${agent}': ${message}`);
91
- }
92
- const validation = validateToolBudgetConfig(parsed, `toolBudget for step '${agent}'`);
93
- if (validation.error) throw new Error(validation.error);
94
- step.toolBudget = parsed as ChainStepConfig["toolBudget"];
95
- }
96
- }
97
-
98
- return step;
99
- }
100
-
101
- export function parseChain(content: string, source: AgentSource, filePath: string): ChainConfig {
102
- const { frontmatter, body } = parseFrontmatter(content);
103
- if (!frontmatter.name || !frontmatter.description) {
104
- throw new Error("Chain frontmatter must include name and description");
105
- }
106
-
107
- const matches = [...body.matchAll(/^##\s+(.+)[^\S\n]*$/gm)];
108
- const steps: ChainStepConfig[] = [];
109
-
110
- for (let i = 0; i < matches.length; i++) {
111
- const match = matches[i]!;
112
- const agent = match[1]!.trim();
113
- const lineEndOffset = body[match.index! + match[0].length] === "\n" ? 1 : 0;
114
- const sectionStart = match.index! + match[0].length + lineEndOffset;
115
- const sectionEnd = i + 1 < matches.length ? matches[i + 1]!.index! : body.length;
116
- const sectionBody = body.slice(sectionStart, sectionEnd).trimEnd();
117
- steps.push(parseStepBody(agent, sectionBody));
118
- }
119
-
120
- const localName = frontmatter.name;
121
- const parsedPackage = parsePackageName(frontmatter.package, `Chain '${localName}' package`);
122
- if (parsedPackage.error) throw new Error(parsedPackage.error);
123
- const packageName = parsedPackage.packageName;
124
- const extraFields: Record<string, string> = {};
125
- for (const [key, value] of Object.entries(frontmatter)) {
126
- if (key === "name" || key === "package" || key === "description") continue;
127
- extraFields[key] = value;
128
- }
129
-
130
- return {
131
- name: buildRuntimeName(localName, packageName),
132
- localName,
133
- packageName,
134
- description: frontmatter.description,
135
- source,
136
- filePath,
137
- steps,
138
- extraFields: Object.keys(extraFields).length > 0 ? extraFields : undefined,
139
- };
140
- }
141
-
142
- function validateJsonChainToolBudget(value: unknown, label: string): void {
143
- const validation = validateToolBudgetConfig(value, label);
144
- if (validation.error) throw new Error(validation.error);
145
- }
146
-
147
- export function parseJsonChain(content: string, source: AgentSource, filePath: string): ChainConfig {
148
- let parsed: unknown;
149
- try {
150
- parsed = JSON.parse(content);
151
- } catch (error) {
152
- const message = error instanceof Error ? error.message : String(error);
153
- throw new Error(`Invalid JSON chain '${filePath}': ${message}`);
154
- }
155
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
156
- throw new Error(`JSON chain '${filePath}' must contain an object root.`);
157
- }
158
- const input = parsed as Record<string, unknown>;
159
- if (typeof input.name !== "string" || !input.name.trim()) {
160
- throw new Error(`JSON chain '${filePath}' must include string name.`);
161
- }
162
- if (typeof input.description !== "string" || !input.description.trim()) {
163
- throw new Error(`JSON chain '${filePath}' must include string description.`);
164
- }
165
- if (!Array.isArray(input.chain)) {
166
- throw new Error(`JSON chain '${filePath}' must include array chain.`);
167
- }
168
- for (let i = 0; i < input.chain.length; i++) {
169
- const step = input.chain[i];
170
- if (!step || typeof step !== "object" || Array.isArray(step)) {
171
- throw new Error(`JSON chain '${filePath}' step ${i + 1} must be an object.`);
172
- }
173
- const stepRecord = step as Record<string, unknown>;
174
- if (stepRecord.toolBudget !== undefined) validateJsonChainToolBudget(stepRecord.toolBudget, `step ${i + 1} toolBudget`);
175
- const acceptanceErrors = validateAcceptanceInput(stepRecord.acceptance, `step ${i + 1} acceptance`);
176
- if (acceptanceErrors.length > 0) {
177
- throw new Error(`Invalid JSON chain '${filePath}': ${acceptanceErrors.join(" ")}`);
178
- }
179
- const parallel = stepRecord.parallel;
180
- if (Array.isArray(parallel)) {
181
- for (let taskIndex = 0; taskIndex < parallel.length; taskIndex++) {
182
- const task = parallel[taskIndex];
183
- if (!task || typeof task !== "object" || Array.isArray(task)) continue;
184
- const taskRecord = task as Record<string, unknown>;
185
- if (taskRecord.toolBudget !== undefined) validateJsonChainToolBudget(taskRecord.toolBudget, `step ${i + 1} parallel task ${taskIndex + 1} toolBudget`);
186
- const taskErrors = validateAcceptanceInput(taskRecord.acceptance, `step ${i + 1} parallel task ${taskIndex + 1} acceptance`);
187
- if (taskErrors.length > 0) {
188
- throw new Error(`Invalid JSON chain '${filePath}': ${taskErrors.join(" ")}`);
189
- }
190
- }
191
- } else if (parallel && typeof parallel === "object") {
192
- const parallelRecord = parallel as Record<string, unknown>;
193
- if (parallelRecord.toolBudget !== undefined) validateJsonChainToolBudget(parallelRecord.toolBudget, `step ${i + 1} dynamic template toolBudget`);
194
- const templateErrors = validateAcceptanceInput(parallelRecord.acceptance, `step ${i + 1} dynamic template acceptance`);
195
- if (templateErrors.length > 0) {
196
- throw new Error(`Invalid JSON chain '${filePath}': ${templateErrors.join(" ")}`);
197
- }
198
- }
199
- }
200
- try {
201
- validateChainOutputBindings(input.chain as ChainStep[], { maxItems: Number.MAX_SAFE_INTEGER });
202
- } catch (error) {
203
- if (error instanceof ChainOutputValidationError) throw new Error(`Invalid JSON chain '${filePath}': ${error.message}`);
204
- throw error;
205
- }
206
- const parsedPackage = parsePackageName(typeof input.package === "string" ? input.package : undefined, `Chain '${input.name}' package`);
207
- if (parsedPackage.error) throw new Error(parsedPackage.error);
208
- const extraFields: Record<string, string> = {};
209
- for (const [key, value] of Object.entries(input)) {
210
- if (key === "name" || key === "package" || key === "description" || key === "chain") continue;
211
- if (typeof value === "string") extraFields[key] = value;
212
- }
213
- return {
214
- name: buildRuntimeName(input.name.trim(), parsedPackage.packageName),
215
- localName: input.name.trim(),
216
- packageName: parsedPackage.packageName,
217
- description: input.description.trim(),
218
- source,
219
- filePath,
220
- steps: input.chain as ChainStepConfig[],
221
- extraFields: Object.keys(extraFields).length > 0 ? extraFields : undefined,
222
- };
223
- }
224
-
225
- export function serializeJsonChain(config: ChainConfig): string {
226
- const root: Record<string, unknown> = {
227
- name: frontmatterNameForConfig(config),
228
- description: config.description,
229
- chain: config.steps,
230
- };
231
- if (config.packageName) root.package = config.packageName;
232
- if (config.extraFields) {
233
- for (const [key, value] of Object.entries(config.extraFields)) {
234
- if (key !== "name" && key !== "description" && key !== "package" && key !== "chain") root[key] = value;
235
- }
236
- }
237
- return `${JSON.stringify(root, null, 2)}\n`;
238
- }
239
-
240
- export function serializeChain(config: ChainConfig): string {
241
- const lines: string[] = [];
242
- lines.push("---");
243
- lines.push(`name: ${frontmatterNameForConfig(config)}`);
244
- if (config.packageName) lines.push(`package: ${config.packageName}`);
245
- lines.push(`description: ${config.description}`);
246
- if (config.extraFields) {
247
- for (const [key, value] of Object.entries(config.extraFields)) {
248
- lines.push(`${key}: ${value}`);
249
- }
250
- }
251
- lines.push("---");
252
- lines.push("");
253
-
254
- for (let i = 0; i < config.steps.length; i++) {
255
- const step = config.steps[i]!;
256
- lines.push(`## ${step.agent}`);
257
- if (step.output === false) lines.push("output: false");
258
- else if (step.output) lines.push(`output: ${step.output}`);
259
- if (step.phase) lines.push(`phase: ${step.phase}`);
260
- if (step.label) lines.push(`label: ${step.label}`);
261
- if (step.as) lines.push(`as: ${step.as}`);
262
- if (step.outputSchema) lines.push(`outputSchema: ${step.outputSchema}`);
263
- if (step.outputMode) lines.push(`outputMode: ${step.outputMode}`);
264
- if (step.reads === false) lines.push("reads: false");
265
- else if (Array.isArray(step.reads) && step.reads.length > 0) lines.push(`reads: ${step.reads.join(", ")}`);
266
- if (step.model) lines.push(`model: ${step.model}`);
267
- if (step.skills === false) lines.push("skills: false");
268
- else if (Array.isArray(step.skills) && step.skills.length > 0) lines.push(`skills: ${step.skills.join(", ")}`);
269
- if (step.progress !== undefined) lines.push(`progress: ${step.progress ? "true" : "false"}`);
270
- if (step.toolBudget !== undefined) lines.push(`toolBudget: ${JSON.stringify(step.toolBudget)}`);
271
- lines.push("");
272
- lines.push(step.task ?? "");
273
- if (i < config.steps.length - 1) lines.push("");
274
- }
275
-
276
- return `${lines.join("\n")}\n`;
277
- }
@@ -1,93 +0,0 @@
1
- /**
2
- * Escape regex special characters for use in a RegExp constructor.
3
- */
4
- function escapeRegex(s: string): string {
5
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6
- }
7
-
8
- /**
9
- * Parse YAML frontmatter from agent/chain files.
10
- * Handles both flat (key: value) and nested block (key: \n sub: val) values.
11
- * Block values are stored as single strings with embedded newlines.
12
- * The indentation of the block content is preserved relative to the key.
13
- */
14
- export function parseFrontmatter(content: string): { frontmatter: Record<string, string>; body: string } {
15
- const frontmatter: Record<string, string> = {};
16
- const normalized = content.replace(/\r\n/g, "\n");
17
-
18
- if (!normalized.startsWith("---")) {
19
- return { frontmatter, body: normalized };
20
- }
21
-
22
- const endIndex = normalized.indexOf("\n---", 3);
23
- if (endIndex === -1) {
24
- return { frontmatter, body: normalized };
25
- }
26
-
27
- const frontmatterBlock = normalized.slice(4, endIndex);
28
- const body = normalized.slice(endIndex + 4).trim();
29
-
30
- const lines = frontmatterBlock.split("\n");
31
- let currentKey: string | null = null;
32
- let currentBlockLines: string[] | null = null;
33
- let currentIndent: number | null = null;
34
-
35
- for (const line of lines) {
36
- const indent = line.search(/\S|$/); // position of first non-whitespace char
37
- const trimmed = line.trim();
38
-
39
- if (currentKey !== null && currentBlockLines !== null && indent > (currentIndent ?? 0)) {
40
- // This line is part of the current block value
41
- currentBlockLines.push(line);
42
- continue;
43
- }
44
-
45
- // Flush any pending block value
46
- if (currentKey !== null && currentBlockLines !== null) {
47
- // Strip the common leading whitespace from the block so the
48
- // serializer can add its own indentation level.
49
- const rawBlock = currentBlockLines.join("\n");
50
- const leadingSpaces = rawBlock.match(/^([ \t]+)/m);
51
- const prefix = leadingSpaces?.[1] ?? "";
52
- const stripped = prefix
53
- ? rawBlock.replace(new RegExp(`^${escapeRegex(prefix)}`, "gm"), "").replace(/^\n/, "")
54
- : rawBlock;
55
- frontmatter[currentKey] = stripped;
56
- currentKey = null;
57
- currentBlockLines = null;
58
- currentIndent = null;
59
- }
60
-
61
- const match = line.match(/^([\w-]+):\s*(.*)$/);
62
- if (match) {
63
- let value = match[2].trim();
64
- if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
65
- value = value.slice(1, -1);
66
- }
67
-
68
- if (value === "") {
69
- // Key with empty value — might start a block; defer storing until we see indent
70
- currentKey = match[1];
71
- currentBlockLines = [];
72
- currentIndent = indent;
73
- } else {
74
- // Simple key: value
75
- frontmatter[match[1]] = value;
76
- }
77
- }
78
- // Lines that don't match a key pattern (e.g., comments, empty lines) are ignored
79
- }
80
-
81
- // Flush final block value
82
- if (currentKey !== null && currentBlockLines !== null) {
83
- const rawBlock = currentBlockLines.join("\n");
84
- const leadingSpaces = rawBlock.match(/^([ \t]+)/m);
85
- const prefix = leadingSpaces?.[1] ?? "";
86
- const stripped = prefix
87
- ? rawBlock.replace(new RegExp(`^${escapeRegex(prefix)}`, "gm"), "").replace(/^\n/, "")
88
- : rawBlock;
89
- frontmatter[currentKey] = stripped;
90
- }
91
-
92
- return { frontmatter, body };
93
- }
@@ -1,30 +0,0 @@
1
- import type { AgentConfig, ChainConfig } from "./agents.ts";
2
-
3
- const IDENTIFIER_PATTERN = /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/;
4
-
5
- function normalizePackageName(value: string | undefined): string | undefined {
6
- const trimmed = value?.trim();
7
- if (!trimmed) return undefined;
8
- return trimmed.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9.-]/g, "").replace(/-+/g, "-").replace(/\.+/g, ".").replace(/(?:^[-.]+|[-.]+$)/g, "");
9
- }
10
-
11
- export function parsePackageName(value: unknown, label = "package"): { packageName?: string; error?: string } {
12
- if (value === undefined || value === false || value === "") return { packageName: undefined };
13
- if (typeof value !== "string") return { error: `${label} must be a string or false when provided.` };
14
- const packageName = normalizePackageName(value);
15
- if (!packageName || !IDENTIFIER_PATTERN.test(packageName)) return { error: `${label} is invalid after sanitization.` };
16
- return { packageName };
17
- }
18
-
19
- export function buildRuntimeName(localName: string, packageName?: string): string {
20
- const trimmedPackage = packageName?.trim();
21
- return trimmedPackage ? `${trimmedPackage}.${localName}` : localName;
22
- }
23
-
24
- export function frontmatterNameForConfig(config: Pick<AgentConfig | ChainConfig, "name" | "localName" | "packageName">): string {
25
- if (config.localName) return config.localName;
26
- if (config.packageName && config.name.startsWith(`${config.packageName}.`)) {
27
- return config.name.slice(config.packageName.length + 1);
28
- }
29
- return config.name;
30
- }
@@ -1,191 +0,0 @@
1
- import type { AgentConfig, ChainConfig, ChainStepConfig } from "./agents.ts";
2
- import type { ProactiveSkillSubagentsConfig } from "../shared/types.ts";
3
-
4
- const SUBAGENT_ORCHESTRATION_SKILL = "dm-subagents";
5
- const DEFAULT_MIN_REFERENCES = 2;
6
- const DEFAULT_MAX_RECOMMENDATIONS = 3;
7
- const DEFAULT_PREFERRED_AGENT = "reviewer";
8
- const FALLBACK_AGENT_ORDER = ["reviewer", "context-builder", "delegate"];
9
- const MAX_RECOMMENDATION_CAP = 5;
10
-
11
- export interface ResolvedProactiveSkillSubagentsConfig {
12
- enabled: boolean;
13
- minReferences: number;
14
- maxRecommendations: number;
15
- preferredAgent: string;
16
- }
17
-
18
- export interface ProactiveSkillSubagentRecommendation {
19
- skill: string;
20
- agent: string;
21
- references: number;
22
- sources: string[];
23
- description?: string;
24
- reason: string;
25
- }
26
-
27
- export interface AvailableSkill {
28
- name: string;
29
- description?: string;
30
- }
31
-
32
- function positiveInteger(value: unknown): number | undefined {
33
- if (typeof value !== "number") return undefined;
34
- if (!Number.isInteger(value) || !Number.isFinite(value) || value < 1) return undefined;
35
- return value;
36
- }
37
-
38
- export function resolveProactiveSkillSubagentsConfig(
39
- config?: ProactiveSkillSubagentsConfig | false,
40
- ): ResolvedProactiveSkillSubagentsConfig {
41
- if (config === false) {
42
- return {
43
- enabled: false,
44
- minReferences: DEFAULT_MIN_REFERENCES,
45
- maxRecommendations: DEFAULT_MAX_RECOMMENDATIONS,
46
- preferredAgent: DEFAULT_PREFERRED_AGENT,
47
- };
48
- }
49
-
50
- const maxRecommendations = positiveInteger(config?.maxRecommendations) ?? DEFAULT_MAX_RECOMMENDATIONS;
51
- return {
52
- enabled: config?.enabled ?? true,
53
- minReferences: positiveInteger(config?.minReferences) ?? DEFAULT_MIN_REFERENCES,
54
- maxRecommendations: Math.min(maxRecommendations, MAX_RECOMMENDATION_CAP),
55
- preferredAgent: typeof config?.preferredAgent === "string" && config.preferredAgent.trim()
56
- ? config.preferredAgent.trim()
57
- : DEFAULT_PREFERRED_AGENT,
58
- };
59
- }
60
-
61
- function normalizeSkillNames(value: unknown): string[] {
62
- if (value === false || value === true || value === undefined || value === null) return [];
63
- if (Array.isArray(value)) {
64
- return [...new Set(value.filter((entry): entry is string => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean))];
65
- }
66
- if (typeof value === "string") {
67
- return [...new Set(value.split(",").map((entry) => entry.trim()).filter(Boolean))];
68
- }
69
- return [];
70
- }
71
-
72
- function collectStepSkills(step: ChainStepConfig, out: Set<string>): void {
73
- for (const skill of normalizeSkillNames(step.skills ?? (step as { skill?: unknown }).skill)) {
74
- out.add(skill);
75
- }
76
-
77
- const parallel = step.parallel;
78
- if (!parallel) return;
79
- if (Array.isArray(parallel)) {
80
- for (const child of parallel) {
81
- if (child && typeof child === "object" && !Array.isArray(child)) {
82
- collectStepSkills(child as ChainStepConfig, out);
83
- }
84
- }
85
- return;
86
- }
87
- if (typeof parallel === "object") {
88
- collectStepSkills(parallel as ChainStepConfig, out);
89
- }
90
- }
91
-
92
- function chooseRecommendationAgent(agents: AgentConfig[], preferredAgent: string): string | undefined {
93
- const enabled = agents.filter((agent) => !agent.disabled);
94
- if (enabled.some((agent) => agent.name === preferredAgent)) return preferredAgent;
95
- for (const name of FALLBACK_AGENT_ORDER) {
96
- if (enabled.some((agent) => agent.name === name)) return name;
97
- }
98
- return enabled[0]?.name;
99
- }
100
-
101
- function addSource(counts: Map<string, Set<string>>, skill: string, source: string): void {
102
- if (skill === SUBAGENT_ORCHESTRATION_SKILL) return;
103
- const sources = counts.get(skill) ?? new Set<string>();
104
- sources.add(source);
105
- counts.set(skill, sources);
106
- }
107
-
108
- export function recommendProactiveSkillSubagents(input: {
109
- agents: AgentConfig[];
110
- chains?: ChainConfig[];
111
- availableSkills?: AvailableSkill[];
112
- config?: ProactiveSkillSubagentsConfig | false;
113
- }): ProactiveSkillSubagentRecommendation[] {
114
- const config = resolveProactiveSkillSubagentsConfig(input.config);
115
- if (!config.enabled) return [];
116
-
117
- const agent = chooseRecommendationAgent(input.agents, config.preferredAgent);
118
- if (!agent) return [];
119
-
120
- const availableByName = input.availableSkills
121
- ? new Map(input.availableSkills.map((skill) => [skill.name, skill]))
122
- : undefined;
123
- const counts = new Map<string, Set<string>>();
124
-
125
- for (const candidate of input.agents) {
126
- if (candidate.disabled) continue;
127
- for (const skill of candidate.skills ?? []) {
128
- addSource(counts, skill, `agent:${candidate.name}`);
129
- }
130
- }
131
-
132
- for (const chain of input.chains ?? []) {
133
- const chainSkills = new Set<string>();
134
- for (const step of chain.steps) {
135
- collectStepSkills(step, chainSkills);
136
- }
137
- for (const skill of chainSkills) {
138
- addSource(counts, skill, `chain:${chain.name}`);
139
- }
140
- }
141
-
142
- return [...counts.entries()]
143
- .filter(([skill, sources]) => sources.size >= config.minReferences && (!availableByName || availableByName.has(skill)))
144
- .map(([skill, sources]) => ({
145
- skill,
146
- agent,
147
- references: sources.size,
148
- sources: [...sources].sort((a, b) => a.localeCompare(b)),
149
- description: availableByName?.get(skill)?.description,
150
- reason: `referenced by ${sources.size} configured agents/chains`,
151
- }))
152
- .sort((a, b) => b.references - a.references || a.skill.localeCompare(b.skill))
153
- .slice(0, config.maxRecommendations);
154
- }
155
-
156
- export function formatProactiveSkillSubagentRecommendations(
157
- recommendations: ProactiveSkillSubagentRecommendation[],
158
- ): string[] {
159
- if (recommendations.length === 0) return [];
160
- return [
161
- "Proactive skill subagent suggestions:",
162
- ...recommendations.map((recommendation) => {
163
- const sampleSources = recommendation.sources.slice(0, 3).join(", ");
164
- const extra = recommendation.sources.length > 3 ? `, +${recommendation.sources.length - 3} more` : "";
165
- const description = recommendation.description ? ` - ${recommendation.description}` : "";
166
- return `- ${recommendation.skill} via ${recommendation.agent} (${recommendation.reason}; ${sampleSources}${extra})${description}`;
167
- }),
168
- "Guardrails: use these for broad tasks where a skill-specialist pass is useful; keep fanout small, use fresh context unless private/session context is explicitly needed, and skip when the user asks for a direct answer.",
169
- ];
170
- }
171
-
172
- export function buildProactiveSkillSubagentRecommendationLines(input: {
173
- agents: AgentConfig[];
174
- chains?: ChainConfig[];
175
- config?: ProactiveSkillSubagentsConfig | false;
176
- discoverAvailableSkills: () => AvailableSkill[];
177
- }): string[] {
178
- if (!resolveProactiveSkillSubagentsConfig(input.config).enabled) return [];
179
- let availableSkills: AvailableSkill[];
180
- try {
181
- availableSkills = input.discoverAvailableSkills();
182
- } catch {
183
- availableSkills = [];
184
- }
185
- return formatProactiveSkillSubagentRecommendations(recommendProactiveSkillSubagents({
186
- agents: input.agents,
187
- chains: input.chains,
188
- availableSkills,
189
- config: input.config,
190
- }));
191
- }