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