@duckmind/dm-darwin-x64 0.43.2 → 0.43.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 (256) hide show
  1. package/dm +0 -0
  2. package/extensions/.dm-extensions.json +242 -49
  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 +135 -135
  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/engines.mjs +9 -9
  132. package/extensions/greedysearch-dm/src/search/paths.mjs +1 -0
  133. package/extensions/greedysearch-dm/src/search/research.mjs +100 -100
  134. package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +10 -10
  135. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +20 -0
  136. package/extensions/greedysearch-dm/src/tools/shared.js +9 -0
  137. package/extensions/greedysearch-dm/src/types.js +0 -0
  138. package/extensions/greedysearch-dm/src/utils/helpers.js +1 -0
  139. package/package.json +1 -1
  140. package/extensions/dm-9router-ext/src/index.ts +0 -541
  141. package/extensions/dm-ask-user/index.ts +0 -857
  142. package/extensions/dm-context/src/context.ts +0 -158
  143. package/extensions/dm-context/src/index.ts +0 -439
  144. package/extensions/dm-context/src/utils.ts +0 -6
  145. package/extensions/dm-fff/src/index.ts +0 -1023
  146. package/extensions/dm-fff/src/query.ts +0 -87
  147. package/extensions/dm-goal/src/goal.ts +0 -1073
  148. package/extensions/dm-grill-me/index.ts +0 -1085
  149. package/extensions/dm-subagents/src/agents/agent-management.ts +0 -1052
  150. package/extensions/dm-subagents/src/agents/agent-memory.ts +0 -254
  151. package/extensions/dm-subagents/src/agents/agent-scope.ts +0 -6
  152. package/extensions/dm-subagents/src/agents/agent-selection.ts +0 -25
  153. package/extensions/dm-subagents/src/agents/agent-serializer.ts +0 -121
  154. package/extensions/dm-subagents/src/agents/agents.ts +0 -1553
  155. package/extensions/dm-subagents/src/agents/chain-serializer.ts +0 -277
  156. package/extensions/dm-subagents/src/agents/frontmatter.ts +0 -93
  157. package/extensions/dm-subagents/src/agents/identity.ts +0 -30
  158. package/extensions/dm-subagents/src/agents/proactive-skills.ts +0 -191
  159. package/extensions/dm-subagents/src/agents/skills.ts +0 -729
  160. package/extensions/dm-subagents/src/extension/config.ts +0 -39
  161. package/extensions/dm-subagents/src/extension/control-notices.ts +0 -92
  162. package/extensions/dm-subagents/src/extension/doctor.ts +0 -214
  163. package/extensions/dm-subagents/src/extension/fanout-child.ts +0 -172
  164. package/extensions/dm-subagents/src/extension/index.ts +0 -656
  165. package/extensions/dm-subagents/src/extension/rpc.ts +0 -369
  166. package/extensions/dm-subagents/src/extension/schemas.ts +0 -309
  167. package/extensions/dm-subagents/src/intercom/intercom-bridge.ts +0 -180
  168. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.ts +0 -519
  169. package/extensions/dm-subagents/src/intercom/result-intercom.ts +0 -377
  170. package/extensions/dm-subagents/src/profiles/profiles.ts +0 -637
  171. package/extensions/dm-subagents/src/runs/background/async-execution.ts +0 -1065
  172. package/extensions/dm-subagents/src/runs/background/async-job-tracker.ts +0 -441
  173. package/extensions/dm-subagents/src/runs/background/async-resume.ts +0 -391
  174. package/extensions/dm-subagents/src/runs/background/async-status.ts +0 -395
  175. package/extensions/dm-subagents/src/runs/background/chain-append.ts +0 -282
  176. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.ts +0 -191
  177. package/extensions/dm-subagents/src/runs/background/completion-batcher.ts +0 -166
  178. package/extensions/dm-subagents/src/runs/background/completion-dedupe.ts +0 -63
  179. package/extensions/dm-subagents/src/runs/background/control-channel.ts +0 -332
  180. package/extensions/dm-subagents/src/runs/background/fleet-view.ts +0 -515
  181. package/extensions/dm-subagents/src/runs/background/notify.ts +0 -225
  182. package/extensions/dm-subagents/src/runs/background/parallel-groups.ts +0 -45
  183. package/extensions/dm-subagents/src/runs/background/result-watcher.ts +0 -315
  184. package/extensions/dm-subagents/src/runs/background/run-id-resolver.ts +0 -84
  185. package/extensions/dm-subagents/src/runs/background/run-status.ts +0 -434
  186. package/extensions/dm-subagents/src/runs/background/scheduled-runs.ts +0 -514
  187. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.ts +0 -368
  188. package/extensions/dm-subagents/src/runs/background/subagent-runner.ts +0 -3171
  189. package/extensions/dm-subagents/src/runs/background/top-level-async.ts +0 -13
  190. package/extensions/dm-subagents/src/runs/background/wait.ts +0 -353
  191. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.ts +0 -1333
  192. package/extensions/dm-subagents/src/runs/foreground/chain-execution.ts +0 -1313
  193. package/extensions/dm-subagents/src/runs/foreground/execution.ts +0 -1239
  194. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.ts +0 -3613
  195. package/extensions/dm-subagents/src/runs/shared/acceptance.ts +0 -879
  196. package/extensions/dm-subagents/src/runs/shared/chain-outputs.ts +0 -116
  197. package/extensions/dm-subagents/src/runs/shared/completion-guard.ts +0 -147
  198. package/extensions/dm-subagents/src/runs/shared/dm-args.ts +0 -271
  199. package/extensions/dm-subagents/src/runs/shared/dm-spawn.ts +0 -147
  200. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.ts +0 -295
  201. package/extensions/dm-subagents/src/runs/shared/long-running-guard.ts +0 -175
  202. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +0 -365
  203. package/extensions/dm-subagents/src/runs/shared/model-fallback.ts +0 -292
  204. package/extensions/dm-subagents/src/runs/shared/model-scope.ts +0 -128
  205. package/extensions/dm-subagents/src/runs/shared/nested-events.ts +0 -908
  206. package/extensions/dm-subagents/src/runs/shared/nested-path.ts +0 -52
  207. package/extensions/dm-subagents/src/runs/shared/nested-render.ts +0 -115
  208. package/extensions/dm-subagents/src/runs/shared/parallel-utils.ts +0 -198
  209. package/extensions/dm-subagents/src/runs/shared/run-history.ts +0 -60
  210. package/extensions/dm-subagents/src/runs/shared/single-output.ts +0 -180
  211. package/extensions/dm-subagents/src/runs/shared/structured-output.ts +0 -77
  212. package/extensions/dm-subagents/src/runs/shared/subagent-control.ts +0 -223
  213. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.ts +0 -342
  214. package/extensions/dm-subagents/src/runs/shared/tool-budget.ts +0 -74
  215. package/extensions/dm-subagents/src/runs/shared/turn-budget.ts +0 -52
  216. package/extensions/dm-subagents/src/runs/shared/workflow-graph.ts +0 -206
  217. package/extensions/dm-subagents/src/runs/shared/worktree.ts +0 -600
  218. package/extensions/dm-subagents/src/shared/artifacts.ts +0 -113
  219. package/extensions/dm-subagents/src/shared/atomic-json.ts +0 -86
  220. package/extensions/dm-subagents/src/shared/child-transcript.ts +0 -212
  221. package/extensions/dm-subagents/src/shared/file-coalescer.ts +0 -40
  222. package/extensions/dm-subagents/src/shared/fork-context.ts +0 -194
  223. package/extensions/dm-subagents/src/shared/formatters.ts +0 -133
  224. package/extensions/dm-subagents/src/shared/jsonl-writer.ts +0 -81
  225. package/extensions/dm-subagents/src/shared/model-info.ts +0 -78
  226. package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
  227. package/extensions/dm-subagents/src/shared/session-identity.ts +0 -10
  228. package/extensions/dm-subagents/src/shared/session-tokens.ts +0 -44
  229. package/extensions/dm-subagents/src/shared/settings.ts +0 -450
  230. package/extensions/dm-subagents/src/shared/status-format.ts +0 -49
  231. package/extensions/dm-subagents/src/shared/types.ts +0 -1257
  232. package/extensions/dm-subagents/src/shared/utils.ts +0 -554
  233. package/extensions/dm-subagents/src/slash/prompt-template-bridge.ts +0 -420
  234. package/extensions/dm-subagents/src/slash/prompt-workflows.ts +0 -330
  235. package/extensions/dm-subagents/src/slash/slash-bridge.ts +0 -176
  236. package/extensions/dm-subagents/src/slash/slash-commands.ts +0 -1296
  237. package/extensions/dm-subagents/src/slash/slash-live-state.ts +0 -292
  238. package/extensions/dm-subagents/src/tui/render-helpers.ts +0 -80
  239. package/extensions/dm-subagents/src/tui/render.ts +0 -1748
  240. package/extensions/dm-tasks/src/auto-clear.ts +0 -91
  241. package/extensions/dm-tasks/src/index.ts +0 -1145
  242. package/extensions/dm-tasks/src/process-tracker.ts +0 -140
  243. package/extensions/dm-tasks/src/task-store.ts +0 -305
  244. package/extensions/dm-tasks/src/tasks-config.ts +0 -23
  245. package/extensions/dm-tasks/src/types.ts +0 -40
  246. package/extensions/dm-tasks/src/ui/settings-menu.ts +0 -100
  247. package/extensions/dm-tasks/src/ui/task-widget.ts +0 -265
  248. package/extensions/dm-usage/index.ts +0 -1718
  249. package/extensions/greedysearch-dm/index.ts +0 -177
  250. package/extensions/greedysearch-dm/src/formatters/results.ts +0 -163
  251. package/extensions/greedysearch-dm/src/formatters/sources.ts +0 -116
  252. package/extensions/greedysearch-dm/src/formatters/synthesis.ts +0 -87
  253. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.ts +0 -370
  254. package/extensions/greedysearch-dm/src/tools/shared.ts +0 -187
  255. package/extensions/greedysearch-dm/src/types.ts +0 -110
  256. 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
- }