@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,191 +0,0 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import type { AcceptanceLedger, AsyncStatus, CostSummary, ModelAttempt } from "../../shared/types.ts";
4
- import { readStatus } from "../../shared/utils.ts";
5
-
6
- export interface ImportedAsyncRoot {
7
- runId: string;
8
- asyncDir: string;
9
- resultPath: string;
10
- index: number;
11
- }
12
-
13
- export interface ImportedAsyncRootResult {
14
- agent: string;
15
- output: string;
16
- success: boolean;
17
- exitCode: number;
18
- error?: string;
19
- sessionFile?: string;
20
- intercomTarget?: string;
21
- model?: string;
22
- attemptedModels?: string[];
23
- modelAttempts?: ModelAttempt[];
24
- totalCost?: CostSummary;
25
- structuredOutput?: unknown;
26
- structuredOutputPath?: string;
27
- structuredOutputSchemaPath?: string;
28
- acceptance?: AcceptanceLedger;
29
- timedOut?: boolean;
30
- }
31
-
32
- interface AsyncResultFile {
33
- state?: string;
34
- success?: boolean;
35
- summary?: string;
36
- error?: string;
37
- timedOut?: boolean;
38
- results?: Array<{
39
- agent?: string;
40
- output?: string;
41
- error?: string;
42
- success?: boolean;
43
- timedOut?: boolean;
44
- sessionFile?: string;
45
- intercomTarget?: string;
46
- model?: string;
47
- attemptedModels?: string[];
48
- modelAttempts?: ModelAttempt[];
49
- totalCost?: CostSummary;
50
- structuredOutput?: unknown;
51
- structuredOutputPath?: string;
52
- structuredOutputSchemaPath?: string;
53
- acceptance?: AcceptanceLedger;
54
- }>;
55
- }
56
-
57
- const TERMINAL_STATES = new Set(["complete", "failed", "paused"]);
58
- const TERMINAL_STEP_STATUSES = new Set(["complete", "completed", "failed", "paused"]);
59
-
60
- function readResultFile(resultPath: string): AsyncResultFile | undefined {
61
- try {
62
- return JSON.parse(fs.readFileSync(resultPath, "utf-8")) as AsyncResultFile;
63
- } catch (error) {
64
- if (typeof error === "object" && error !== null && "code" in error && (error as NodeJS.ErrnoException).code === "ENOENT") {
65
- return undefined;
66
- }
67
- throw error;
68
- }
69
- }
70
-
71
- function selectedStatusStep(status: AsyncStatus | null, index: number): NonNullable<AsyncStatus["steps"]>[number] | undefined {
72
- return status?.steps?.[index];
73
- }
74
-
75
- function isTerminalStatus(status: AsyncStatus | null, index: number): boolean {
76
- if (!status) return false;
77
- const step = selectedStatusStep(status, index);
78
- if (step && TERMINAL_STEP_STATUSES.has(step.status)) return true;
79
- return TERMINAL_STATES.has(status.state);
80
- }
81
-
82
- function resultState(result: AsyncResultFile | undefined, child: NonNullable<AsyncResultFile["results"]>[number] | undefined): "complete" | "failed" | "paused" | undefined {
83
- if (!result) return undefined;
84
- if (child?.success === true) return "complete";
85
- if (child?.success === false) return result.state === "paused" ? "paused" : "failed";
86
- if (result.state === "complete" || result.state === "failed" || result.state === "paused") return result.state;
87
- if (result.success === true) return "complete";
88
- if (result.success === false) return "failed";
89
- return undefined;
90
- }
91
-
92
- function outputFromTerminalStatus(root: ImportedAsyncRoot, status: AsyncStatus, step: NonNullable<AsyncStatus["steps"]>[number] | undefined): ImportedAsyncRootResult {
93
- const agent = step?.agent ?? status.steps?.[root.index]?.agent ?? "subagent";
94
- const timedOut = step?.timedOut === true || status.timedOut === true;
95
- const message = step?.error ?? status.error ?? `Attached async root ${root.runId} ended without a result file at ${root.resultPath}.`;
96
- return {
97
- agent,
98
- output: message,
99
- success: false,
100
- exitCode: 1,
101
- error: message,
102
- ...(timedOut ? { timedOut: true } : {}),
103
- ...(step?.sessionFile ?? status.sessionFile ? { sessionFile: step?.sessionFile ?? status.sessionFile } : {}),
104
- ...(step?.model ? { model: step.model } : {}),
105
- ...(step?.attemptedModels ? { attemptedModels: step.attemptedModels } : {}),
106
- ...(step?.modelAttempts ? { modelAttempts: step.modelAttempts } : {}),
107
- ...(step?.totalCost ? { totalCost: step.totalCost } : {}),
108
- ...(step?.structuredOutput !== undefined ? { structuredOutput: step.structuredOutput } : {}),
109
- ...(step?.structuredOutputPath ? { structuredOutputPath: step.structuredOutputPath } : {}),
110
- ...(step?.structuredOutputSchemaPath ? { structuredOutputSchemaPath: step.structuredOutputSchemaPath } : {}),
111
- ...(step?.acceptance ? { acceptance: step.acceptance } : {}),
112
- };
113
- }
114
-
115
- function outputFromTimeout(root: ImportedAsyncRoot, status: AsyncStatus | null, message: string): ImportedAsyncRootResult {
116
- const step = selectedStatusStep(status, root.index);
117
- return {
118
- agent: step?.agent ?? status?.steps?.[root.index]?.agent ?? "subagent",
119
- output: message,
120
- success: false,
121
- exitCode: 1,
122
- error: message,
123
- timedOut: true,
124
- ...(step?.sessionFile ?? status?.sessionFile ? { sessionFile: step?.sessionFile ?? status?.sessionFile } : {}),
125
- ...(step?.model ? { model: step.model } : {}),
126
- ...(step?.attemptedModels ? { attemptedModels: step.attemptedModels } : {}),
127
- ...(step?.modelAttempts ? { modelAttempts: step.modelAttempts } : {}),
128
- ...(step?.totalCost ? { totalCost: step.totalCost } : {}),
129
- };
130
- }
131
-
132
- function buildImportedResult(root: ImportedAsyncRoot, status: AsyncStatus | null, result: AsyncResultFile): ImportedAsyncRootResult {
133
- const child = result.results?.[root.index];
134
- const step = selectedStatusStep(status, root.index);
135
- const state = resultState(result, child);
136
- const agent = child?.agent ?? step?.agent ?? status?.steps?.[root.index]?.agent ?? "subagent";
137
- const output = child?.output ?? result.summary ?? "";
138
- const timedOut = child?.timedOut === true || step?.timedOut === true || result.timedOut === true || status?.timedOut === true;
139
- const success = state === "complete" && !timedOut;
140
- const error = child?.error ?? (success ? undefined : result.error ?? result.summary ?? status?.error ?? `Attached async root ${root.runId} did not complete successfully.`);
141
- return {
142
- agent,
143
- output: success ? output : (output || error || ""),
144
- success,
145
- exitCode: success ? 0 : 1,
146
- ...(error ? { error } : {}),
147
- ...(timedOut ? { timedOut: true } : {}),
148
- ...(child?.sessionFile ?? step?.sessionFile ?? status?.sessionFile ? { sessionFile: child?.sessionFile ?? step?.sessionFile ?? status?.sessionFile } : {}),
149
- ...(child?.intercomTarget ? { intercomTarget: child.intercomTarget } : {}),
150
- ...(child?.model ?? step?.model ? { model: child?.model ?? step?.model } : {}),
151
- ...(child?.attemptedModels ?? step?.attemptedModels ? { attemptedModels: child?.attemptedModels ?? step?.attemptedModels } : {}),
152
- ...(child?.modelAttempts ?? step?.modelAttempts ? { modelAttempts: child?.modelAttempts ?? step?.modelAttempts } : {}),
153
- ...(child?.totalCost ?? step?.totalCost ? { totalCost: child?.totalCost ?? step?.totalCost } : {}),
154
- ...(child?.structuredOutput !== undefined ? { structuredOutput: child.structuredOutput } : step?.structuredOutput !== undefined ? { structuredOutput: step.structuredOutput } : {}),
155
- ...(child?.structuredOutputPath ?? step?.structuredOutputPath ? { structuredOutputPath: child?.structuredOutputPath ?? step?.structuredOutputPath } : {}),
156
- ...(child?.structuredOutputSchemaPath ?? step?.structuredOutputSchemaPath ? { structuredOutputSchemaPath: child?.structuredOutputSchemaPath ?? step?.structuredOutputSchemaPath } : {}),
157
- ...(child?.acceptance ?? step?.acceptance ? { acceptance: child?.acceptance ?? step?.acceptance } : {}),
158
- };
159
- }
160
-
161
- export async function waitForImportedAsyncRoot(
162
- root: ImportedAsyncRoot,
163
- options: { pollIntervalMs?: number; terminalResultGraceMs?: number; now?: () => number; shouldAbort?: () => boolean; timeoutMessage?: string } = {},
164
- ): Promise<ImportedAsyncRootResult> {
165
- const pollIntervalMs = options.pollIntervalMs ?? 500;
166
- const terminalResultGraceMs = options.terminalResultGraceMs ?? 1_000;
167
- const now = options.now ?? Date.now;
168
- let terminalSince: number | undefined;
169
- for (;;) {
170
- const status = readStatus(root.asyncDir);
171
- if (options.shouldAbort?.()) return outputFromTimeout(root, status, options.timeoutMessage ?? "Subagent timed out.");
172
- const result = readResultFile(root.resultPath);
173
- if (result) return buildImportedResult(root, status, result);
174
- if (isTerminalStatus(status, root.index)) {
175
- terminalSince ??= now();
176
- if (now() - terminalSince >= terminalResultGraceMs) {
177
- return outputFromTerminalStatus(root, status!, selectedStatusStep(status, root.index));
178
- }
179
- } else {
180
- terminalSince = undefined;
181
- }
182
- if (!status && !fs.existsSync(root.asyncDir)) {
183
- throw new Error(`Attached async root '${root.runId}' directory does not exist: ${root.asyncDir}`);
184
- }
185
- await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
186
- }
187
- }
188
-
189
- export function resolveAsyncRootResultPath(resultsDir: string, runId: string): string {
190
- return path.join(resultsDir, `${runId}.json`);
191
- }
@@ -1,166 +0,0 @@
1
- /**
2
- * Smart completion batching with straggler handling.
3
- *
4
- * Holds successful async-completion notifications briefly so sibling jobs that
5
- * finish within a short window arrive as a single grouped message. A hard
6
- * max-wait cap (measured from the first item in a group) prevents holding
7
- * notifications indefinitely. After a group is emitted, late-finishing
8
- * siblings that arrive within the straggler window join a shorter "straggler"
9
- * group with reduced debounce and max-wait timers.
10
- *
11
- * Failure and attention signals bypass this batcher entirely. Callers must
12
- * flush() held items and emit those signals immediately so failures and
13
- * needs-attention notices are never delayed.
14
- */
15
-
16
- import type { CompletionBatchConfig } from "../../shared/types.ts";
17
-
18
- export type { CompletionBatchConfig };
19
-
20
- export interface ResolvedCompletionBatchConfig {
21
- enabled: boolean;
22
- debounceMs: number;
23
- maxWaitMs: number;
24
- stragglerDebounceMs: number;
25
- stragglerMaxWaitMs: number;
26
- stragglerWindowMs: number;
27
- }
28
-
29
- export const DEFAULT_COMPLETION_BATCH_CONFIG: ResolvedCompletionBatchConfig = {
30
- enabled: true,
31
- debounceMs: 150,
32
- maxWaitMs: 1000,
33
- stragglerDebounceMs: 75,
34
- stragglerMaxWaitMs: 400,
35
- stragglerWindowMs: 2000,
36
- };
37
-
38
- function parsePositiveInt(value: unknown): number | undefined {
39
- if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value < 1) return undefined;
40
- return value;
41
- }
42
-
43
- export function resolveCompletionBatchConfig(
44
- globalConfig?: CompletionBatchConfig,
45
- override?: CompletionBatchConfig,
46
- ): ResolvedCompletionBatchConfig {
47
- const enabled = typeof override?.enabled === "boolean"
48
- ? override.enabled
49
- : typeof globalConfig?.enabled === "boolean"
50
- ? globalConfig.enabled
51
- : DEFAULT_COMPLETION_BATCH_CONFIG.enabled;
52
- return {
53
- enabled,
54
- debounceMs: parsePositiveInt(override?.debounceMs) ?? parsePositiveInt(globalConfig?.debounceMs) ?? DEFAULT_COMPLETION_BATCH_CONFIG.debounceMs,
55
- maxWaitMs: parsePositiveInt(override?.maxWaitMs) ?? parsePositiveInt(globalConfig?.maxWaitMs) ?? DEFAULT_COMPLETION_BATCH_CONFIG.maxWaitMs,
56
- stragglerDebounceMs: parsePositiveInt(override?.stragglerDebounceMs) ?? parsePositiveInt(globalConfig?.stragglerDebounceMs) ?? DEFAULT_COMPLETION_BATCH_CONFIG.stragglerDebounceMs,
57
- stragglerMaxWaitMs: parsePositiveInt(override?.stragglerMaxWaitMs) ?? parsePositiveInt(globalConfig?.stragglerMaxWaitMs) ?? DEFAULT_COMPLETION_BATCH_CONFIG.stragglerMaxWaitMs,
58
- stragglerWindowMs: parsePositiveInt(override?.stragglerWindowMs) ?? parsePositiveInt(globalConfig?.stragglerWindowMs) ?? DEFAULT_COMPLETION_BATCH_CONFIG.stragglerWindowMs,
59
- };
60
- }
61
-
62
- type TimerHandle = unknown;
63
-
64
- interface TimerApi {
65
- setTimeout(handler: () => void, delayMs: number): TimerHandle;
66
- clearTimeout(handle: TimerHandle): void;
67
- }
68
-
69
- const defaultTimers: TimerApi = {
70
- setTimeout: (handler, delayMs) => setTimeout(handler, delayMs),
71
- clearTimeout: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),
72
- };
73
-
74
- function unrefHandle(handle: TimerHandle): void {
75
- if (handle && typeof handle === "object" && "unref" in handle && typeof (handle as { unref: unknown }).unref === "function") {
76
- (handle as { unref: () => void }).unref();
77
- }
78
- }
79
-
80
- export interface CompletionBatcherOptions<T> {
81
- config: ResolvedCompletionBatchConfig;
82
- emit: (items: T[]) => void;
83
- timers?: TimerApi;
84
- now?: () => number;
85
- }
86
-
87
- export interface CompletionBatcher<T> {
88
- /** Add a batchable item. Emits immediately when batching is disabled. */
89
- push(item: T): void;
90
- /** Emit any held items immediately as a single group. */
91
- flush(): void;
92
- /** Clear timers without emitting. */
93
- dispose(): void;
94
- }
95
-
96
- /**
97
- * Create a completion batcher. The batcher is single-use per registration: it
98
- * holds at most one open group. `flush` forces emission; `dispose` tears down
99
- * timers for reload/shutdown without emitting.
100
- */
101
- export function createCompletionBatcher<T>(options: CompletionBatcherOptions<T>): CompletionBatcher<T> {
102
- const timers = options.timers ?? defaultTimers;
103
- const now = options.now ?? Date.now;
104
- const config = options.config;
105
-
106
- if (!config.enabled) {
107
- return {
108
- push(item: T) {
109
- options.emit([item]);
110
- },
111
- flush() {},
112
- dispose() {},
113
- };
114
- }
115
-
116
- let pending: T[] = [];
117
- let debounceTimer: TimerHandle | null = null;
118
- let maxWaitTimer: TimerHandle | null = null;
119
- let straggler = false;
120
- let lastEmitAt: number | null = null;
121
-
122
- const clearTimers = () => {
123
- if (debounceTimer) {
124
- timers.clearTimeout(debounceTimer);
125
- debounceTimer = null;
126
- }
127
- if (maxWaitTimer) {
128
- timers.clearTimeout(maxWaitTimer);
129
- maxWaitTimer = null;
130
- }
131
- };
132
-
133
- const emitGroup = () => {
134
- clearTimers();
135
- if (pending.length === 0) return;
136
- const items = pending;
137
- pending = [];
138
- lastEmitAt = now();
139
- options.emit(items);
140
- };
141
-
142
- return {
143
- push(item: T) {
144
- if (pending.length === 0) {
145
- straggler = lastEmitAt !== null && (now() - lastEmitAt) < config.stragglerWindowMs;
146
- }
147
- pending.push(item);
148
-
149
- if (debounceTimer) timers.clearTimeout(debounceTimer);
150
- const debounceDelay = straggler ? config.stragglerDebounceMs : config.debounceMs;
151
- debounceTimer = timers.setTimeout(emitGroup, debounceDelay);
152
- unrefHandle(debounceTimer);
153
-
154
- if (!maxWaitTimer) {
155
- const maxWaitDelay = straggler ? config.stragglerMaxWaitMs : config.maxWaitMs;
156
- maxWaitTimer = timers.setTimeout(emitGroup, maxWaitDelay);
157
- unrefHandle(maxWaitTimer);
158
- }
159
- },
160
- flush: emitGroup,
161
- dispose() {
162
- clearTimers();
163
- pending = [];
164
- },
165
- };
166
- }
@@ -1,63 +0,0 @@
1
- interface CompletionDataLike {
2
- id?: unknown;
3
- agent?: unknown;
4
- timestamp?: unknown;
5
- sessionId?: unknown;
6
- taskIndex?: unknown;
7
- totalTasks?: unknown;
8
- success?: unknown;
9
- }
10
-
11
- function asNonEmptyString(value: unknown): string | undefined {
12
- if (typeof value !== "string") return undefined;
13
- const trimmed = value.trim();
14
- return trimmed.length > 0 ? trimmed : undefined;
15
- }
16
-
17
- function asFiniteNumber(value: unknown): number | undefined {
18
- if (typeof value !== "number") return undefined;
19
- return Number.isFinite(value) ? value : undefined;
20
- }
21
-
22
- export function buildCompletionKey(data: CompletionDataLike, fallback: string): string {
23
- const id = asNonEmptyString(data.id);
24
- if (id) return `id:${id}`;
25
- const sessionId = asNonEmptyString(data.sessionId) ?? "no-session";
26
- const agent = asNonEmptyString(data.agent) ?? "unknown";
27
- const timestamp = asFiniteNumber(data.timestamp);
28
- const taskIndex = asFiniteNumber(data.taskIndex);
29
- const totalTasks = asFiniteNumber(data.totalTasks);
30
- const success = typeof data.success === "boolean" ? (data.success ? "1" : "0") : "?";
31
- return [
32
- "meta",
33
- sessionId,
34
- agent,
35
- timestamp !== undefined ? String(timestamp) : "no-ts",
36
- taskIndex !== undefined ? String(taskIndex) : "-",
37
- totalTasks !== undefined ? String(totalTasks) : "-",
38
- success,
39
- fallback,
40
- ].join(":");
41
- }
42
-
43
- function pruneSeenMap(seen: Map<string, number>, now: number, ttlMs: number): void {
44
- for (const [key, ts] of seen.entries()) {
45
- if (now - ts > ttlMs) seen.delete(key);
46
- }
47
- }
48
-
49
- export function markSeenWithTtl(seen: Map<string, number>, key: string, now: number, ttlMs: number): boolean {
50
- pruneSeenMap(seen, now, ttlMs);
51
- if (seen.has(key)) return true;
52
- seen.set(key, now);
53
- return false;
54
- }
55
-
56
- export function getGlobalSeenMap(storeKey: string): Map<string, number> {
57
- const globalStore = globalThis as Record<string, unknown>;
58
- const existing = globalStore[storeKey];
59
- if (existing instanceof Map) return existing as Map<string, number>;
60
- const map = new Map<string, number>();
61
- globalStore[storeKey] = map;
62
- return map;
63
- }