@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,158 +0,0 @@
1
- import {
2
- type ExtensionAPI,
3
- type SessionManager,
4
- DynamicBorder,
5
- } from "@duckmind/dm-coding-agent";
6
- import { Container, Text, Spacer } from "@duckmind/dm-tui";
7
- import { formatTokens } from "./utils.js";
8
-
9
- export default function (pi: ExtensionAPI) {
10
- pi.registerCommand("context", {
11
- description: "Show context usage visualization",
12
- handler: async (args, ctx) => {
13
- const usage = await ctx.getContextUsage();
14
- if (!usage) {
15
- ctx.ui.notify("Context usage info not available.", "warning");
16
- return;
17
- }
18
-
19
- const sm = ctx.sessionManager as SessionManager;
20
- const branch = sm.getBranch();
21
- const systemPrompt = ctx.getSystemPrompt();
22
- const tools = pi.getActiveTools();
23
- const allTools = pi.getAllTools();
24
- const activeToolDefs = allTools.filter(t => tools.includes(t.name));
25
-
26
- const estimateTokens = (text: string) => Math.ceil(text.length / 4);
27
-
28
- let msgTokensRaw = 0;
29
- let toolUseTokensRaw = 0;
30
- let toolResultTokensRaw = 0;
31
-
32
- for (const entry of branch) {
33
- if (entry.type === "message") {
34
- const m = entry.message;
35
- if (m.role === "user") {
36
- if (typeof m.content === "string") msgTokensRaw += estimateTokens(m.content);
37
- else if (Array.isArray(m.content)) {
38
- for (const p of m.content) if (p.type === "text") msgTokensRaw += estimateTokens(p.text);
39
- }
40
- } else if (m.role === "assistant") {
41
- if (typeof m.content === "string") msgTokensRaw += estimateTokens(m.content);
42
- else if (Array.isArray(m.content)) {
43
- for (const p of m.content) {
44
- if (p.type === "text") msgTokensRaw += estimateTokens(p.text);
45
- if (p.type === "toolCall") toolUseTokensRaw += estimateTokens(JSON.stringify(p));
46
- }
47
- }
48
- } else if (m.role === "toolResult") {
49
- if (Array.isArray(m.content)) {
50
- for (const p of m.content) if (p.type === "text") toolResultTokensRaw += estimateTokens(p.text);
51
- }
52
- } else if (m.role === "bashExecution") {
53
- toolUseTokensRaw += estimateTokens(m.command || "");
54
- }
55
- } else if (entry.type === "branch_summary" || entry.type === "compaction") {
56
- msgTokensRaw += estimateTokens(entry.summary || "");
57
- }
58
- }
59
-
60
- const systemTokensRaw = estimateTokens(systemPrompt);
61
- const toolDefTokensRaw = estimateTokens(JSON.stringify(activeToolDefs));
62
- const totalActual = usage.tokens;
63
- const limit = usage.contextWindow;
64
-
65
- if (totalActual == null || limit == null || usage.percent == null) {
66
- ctx.ui.notify("Context usage info not available.", "warning");
67
- return;
68
- }
69
-
70
- const totalRaw = systemTokensRaw + toolDefTokensRaw + msgTokensRaw + toolUseTokensRaw + toolResultTokensRaw;
71
- const ratio = totalRaw > 0 ? (totalActual / totalRaw) : 1;
72
-
73
- const systemTokens = Math.round(systemTokensRaw * ratio);
74
- const toolDefTokens = Math.round(toolDefTokensRaw * ratio);
75
- const msgTokens = Math.round(msgTokensRaw * ratio);
76
- const toolUseTokens = Math.round(toolUseTokensRaw * ratio);
77
- const toolResultTokens = Math.round(toolResultTokensRaw * ratio);
78
-
79
- await ctx.ui.custom((tui, theme, kb, done) => {
80
- const container = new Container();
81
- container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
82
- container.addChild(new Text(theme.fg("accent", theme.bold(" Context Usage")), 1, 0));
83
- container.addChild(new Spacer(1));
84
-
85
- // Grouped by function and color
86
- const categories = [
87
- { label: "System Prompt", value: systemTokens, color: "muted" },
88
- { label: "System Tools", value: toolDefTokens, color: "dim" },
89
- { label: "Tool Call", value: toolUseTokens + toolResultTokens, color: "success" },
90
- { label: "Messages", value: msgTokens, color: "accent" },
91
- ];
92
-
93
- const otherTokens = Math.max(0, totalActual - (systemTokens + toolDefTokens + msgTokens + toolUseTokens + toolResultTokens));
94
- if (otherTokens > 10) categories.push({ label: "Other", value: otherTokens, color: "dim" });
95
-
96
- categories.push({ label: "Available", value: Math.max(0, limit - totalActual), color: "borderMuted" });
97
-
98
- const gridWidth = 10;
99
- const gridHeight = 5;
100
- const totalBlocks = gridWidth * gridHeight;
101
-
102
- const blocks: { color: string, filled: boolean }[] = [];
103
- categories.forEach((cat) => {
104
- if (cat.label === "Available") return;
105
- let count = Math.round((cat.value / limit) * totalBlocks);
106
- if (count === 0 && cat.value > 0) count = 1;
107
- for (let i = 0; i < count && blocks.length < totalBlocks; i++) {
108
- blocks.push({ color: cat.color, filled: true });
109
- }
110
- });
111
-
112
- while (blocks.length < totalBlocks) {
113
- blocks.push({ color: "borderMuted", filled: false });
114
- }
115
-
116
- const gridLines: string[] = [];
117
- for (let r = 0; r < gridHeight; r++) {
118
- let rowStr = "";
119
- for (let c = 0; c < gridWidth; c++) {
120
- const b = blocks[r * gridWidth + c];
121
- rowStr += theme.fg(b.color as any, b.filled ? "■ " : "□ ");
122
- }
123
- gridLines.push(rowStr.trimEnd());
124
- }
125
-
126
- const totalUsageTitle = `${theme.fg("text", theme.bold("Total Usage".padEnd(16)))} ${theme.fg("text", theme.bold(formatTokens(totalActual).padStart(7)))} ${theme.fg("text", theme.bold(`(${usage.percent.toFixed(1).padStart(5)}%)`))}`;
127
-
128
- const catDetailLines = categories.map(cat => {
129
- const labelStr = cat.label.padEnd(14);
130
- const valStr = formatTokens(cat.value).padStart(7);
131
- const rowPercent = ((cat.value / limit) * 100).toFixed(1).padStart(5);
132
- const icon = cat.label === "Available" ? "□" : "■";
133
- return `${theme.fg(cat.color as any, icon)} ${theme.fg("text", labelStr)} ${theme.fg("accent", valStr)} (${rowPercent}%)`;
134
- });
135
-
136
- const allDetailLines = [totalUsageTitle, "", ...catDetailLines];
137
-
138
- const leftSideWidth = 20;
139
- const maxH = Math.max(gridLines.length, allDetailLines.length);
140
- for (let i = 0; i < maxH; i++) {
141
- const left = (gridLines[i] || "").padEnd(leftSideWidth);
142
- const right = allDetailLines[i] || "";
143
- container.addChild(new Text(` ${left} ${right}`, 1, 0));
144
- }
145
-
146
- container.addChild(new Spacer(1));
147
- container.addChild(new Text(theme.fg("dim", " Press any key to close"), 1, 0));
148
- container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
149
-
150
- return {
151
- render: (w) => container.render(w),
152
- invalidate: () => container.invalidate(),
153
- handleInput: (data) => done(undefined),
154
- };
155
- }, { overlay: true });
156
- }
157
- });
158
- }
@@ -1,439 +0,0 @@
1
- import {
2
- type ExtensionAPI,
3
- type SessionManager,
4
- type SessionEntry,
5
- } from "@duckmind/dm-coding-agent";
6
- import type {
7
- TextContent,
8
- ImageContent,
9
- ToolCall,
10
- } from "@duckmind/dm-ai";
11
- import { Type, type Static } from "@sinclair/typebox";
12
- import { ExtensionCommandContext } from "@duckmind/dm-coding-agent";
13
- import { formatTokens } from "./utils.js";
14
-
15
- // Define missing types locally as they are not exported from the main entry point
16
- interface SessionTreeNode {
17
- entry: SessionEntry;
18
- children: SessionTreeNode[];
19
- label?: string;
20
- }
21
-
22
- const InternalTools = ["context_tag", "context_log", "context_checkout"];
23
- let CommandCtx: ExtensionCommandContext | null = null;
24
- let CheckoutParams: any = null;
25
-
26
- const isInternal = (name: string) => InternalTools.includes(name);
27
-
28
- const resolveTargetId = (sm: SessionManager, target: string): string => {
29
- if (target.toLowerCase() === "root") {
30
- const tree = sm.getTree();
31
- return tree.length > 0 ? tree[0].entry.id : target;
32
- }
33
-
34
- // If it already looks like an ID, keep it.
35
- if (/^[0-9a-f]{8,}$/i.test(target)) return target;
36
-
37
- // Iterative DFS to avoid call stack overflows on deep histories.
38
- const stack: SessionTreeNode[] = [...(sm.getTree() as unknown as SessionTreeNode[])];
39
- while (stack.length > 0) {
40
- const n = stack.pop()!;
41
- if (sm.getLabel(n.entry.id) === target) return n.entry.id;
42
- if (n.children?.length) stack.push(...n.children);
43
- }
44
-
45
- // Fallback: let SessionManager deal with invalid targets downstream.
46
- return target;
47
- };
48
-
49
- const ContextLogParams = Type.Object({
50
- limit: Type.Optional(Type.Number({ description: "History limit for visible entries (default: 50)." })),
51
- verbose: Type.Optional(Type.Boolean({ description: "If true, show ALL messages. If false (default), collapses intermediate AI steps and only shows 'milestones': User messages, Tags, Branch Points, and Summaries." })),
52
- });
53
-
54
- const ContextCheckoutParams = Type.Object({
55
- target: Type.String({ description: "Where to jump/squash to. Can be a tag name (e.g., 'task-start'), a commit ID, or 'root'. This is the base for your new branch." }),
56
- message: Type.String({ description: "The 'Carryover Message' for the new branch. A summary of your *current* progress/lessons that you want to bring with you to the new state. This ensures you don't lose key information when switching contexts. Good summary message: '[Status] + [Reason] + [Important Changes] + [Carryover Data]'" }),
57
- backupTag: Type.Optional(Type.String({ description: "Optional tag name to apply to the CURRENT state before checking out. Use this to create an automatic backup of the history you are about to leave/squash." })),
58
- });
59
-
60
- const ContextTagParams = Type.Object({
61
- name: Type.String({ description: "The tag/milestone name. Use meaningful names." }),
62
- target: Type.Optional(Type.String({ description: "The commit ID to tag. Defaults to HEAD (current state)." })),
63
- });
64
-
65
- export default function (pi: ExtensionAPI) {
66
- pi.registerCommand("acm", {
67
- description: "Enable agentic context management for the current session",
68
- handler: async (args, ctx) => {
69
- CommandCtx = ctx;
70
- ctx.ui.notify("Agentic Context Management enabled.", "info");
71
- pi.sendMessage({
72
- customType: "dm-context",
73
- content: "use context-management skill",
74
- display: false,
75
- }, {
76
- deliverAs: "followUp"
77
- });
78
- if (args) {
79
- pi.sendUserMessage(args)
80
- }
81
- }
82
- });
83
-
84
- // Helper: Check if a tag name already exists in the tree
85
- const findTagInTree = (sm: SessionManager, nodes: SessionTreeNode[], tagName: string): string | null => {
86
- for (const n of nodes) {
87
- if (sm.getLabel(n.entry.id) === tagName) return n.entry.id;
88
- const r = findTagInTree(sm, n.children, tagName);
89
- if (r) return r;
90
- }
91
- return null;
92
- };
93
-
94
- pi.registerTool({
95
- name: "context_tag",
96
- label: "Context Tag",
97
- description: "Creates a 'Save Point' (Bookmark) in the history. Use this before trying risky changes or when a feature is stable. 'Untagged progress is risky'.",
98
- parameters: ContextTagParams,
99
- async execute(_id, params: Static<typeof ContextTagParams>, _signal, _onUpdate, ctx) {
100
- const sm = ctx.sessionManager as SessionManager;
101
-
102
- // Deduplication check: ensure tag name is unique
103
- const existingTagId = findTagInTree(sm, sm.getTree(), params.name);
104
- if (existingTagId) {
105
- return {
106
- content: [{
107
- type: "text",
108
- text: `Error: Tag '${params.name}' already exists at ${existingTagId}. Tag names must be unique. Use a different name or delete the existing tag first.`
109
- }],
110
- details: {}
111
- };
112
- }
113
-
114
- let id = params.target ? resolveTargetId(sm, params.target) : undefined;
115
-
116
- if (!id) {
117
- // Auto-resolve: Find the last "interesting" node to tag.
118
- // We skip ToolResults (which look ugly tagged) and internal-only Assistant messages (which look empty).
119
- const branch = sm.getBranch();
120
- for (let i = branch.length - 1; i >= 0; i--) {
121
- const entry = branch[i];
122
-
123
- // 1. Check ToolResults
124
- if (entry.type === 'message' && entry.message.role === 'toolResult') {
125
- const tr = entry.message as any;
126
- if (isInternal(tr.toolName)) continue;
127
-
128
- // Public tool result is a valid target
129
- id = entry.id;
130
- break;
131
- }
132
-
133
- // 2. Check Assistant messages for visibility
134
- if (entry.type === 'message' && entry.message.role === 'assistant') {
135
- const m = entry.message;
136
- const hasInternalTool = m.content.some(c => c.type === 'toolCall' && isInternal(c.name));
137
-
138
- if (!hasInternalTool) {
139
- id = entry.id;
140
- break;
141
- }
142
- }
143
-
144
- id = entry.id;
145
- break;
146
- }
147
- // Fallback to leaf if search failed
148
- if (!id) id = sm.getLeafId() ?? "";
149
- }
150
-
151
- pi.setLabel(id, params.name);
152
- return { content: [{ type: "text", text: `Created tag '${params.name}' at ${id}` }], details: {} };
153
- },
154
- });
155
-
156
- pi.registerTool({
157
- name: "context_log",
158
- label: "Context Log",
159
- description: "Show the entire history structure (status, message, tags, milestones). Analogous to 'git log --graph --oneline --decorate'",
160
- parameters: ContextLogParams,
161
- async execute(_id, params: Static<typeof ContextLogParams>, _signal, _onUpdate, ctx) {
162
- const sm = ctx.sessionManager as SessionManager;
163
- const branch = sm.getBranch();
164
- const currentLeafId = sm.getLeafId();
165
- const verbose = params.verbose ?? false;
166
- const limit = params.limit ?? 50;
167
-
168
- const backboneIds = new Set(branch.map((e) => e.id));
169
- const sequence: SessionEntry[] = [];
170
-
171
- branch.forEach((entry) => {
172
- sequence.push(entry);
173
-
174
- // Preserve side-summary logic: Show branch summaries/compactions that are off-path
175
- const children = sm.getChildren(entry.id);
176
- children.forEach((child) => {
177
- if ((child.type === "branch_summary" || child.type === "compaction") && !backboneIds.has(child.id)) {
178
- sequence.push(child);
179
- }
180
- });
181
- });
182
-
183
- const getMsgContent = (entry: SessionEntry): string => {
184
- if (entry.type === "branch_summary" || entry.type === "compaction") {
185
- const e = entry;
186
- return e.summary || "[No summary provided]";
187
- }
188
- if (entry.type === "label") {
189
- return `tag: ${entry.label}`;
190
- }
191
-
192
- if (entry.type === "message") {
193
- const msg = entry.message;
194
-
195
- if (msg.role === "toolResult") {
196
- const tr = msg;
197
- if (!verbose && isInternal(tr.toolName)) return "";
198
-
199
- const extractText = (content: (TextContent | ImageContent)[]): string => {
200
- return content
201
- .map((p) => (p.type === "text" ? p.text : ""))
202
- .join(" ")
203
- .trim();
204
- };
205
-
206
- let resText = extractText(tr.content);
207
- const details = tr.details as Record<string, unknown> | undefined;
208
- if ((tr.toolName === "read" || tr.toolName === "edit") && details && "path" in details && typeof details.path === "string") {
209
- resText = `${details.path}: ${resText}`;
210
- }
211
- return `(${tr.toolName}) ${resText}`;
212
- }
213
-
214
- if (msg.role === "bashExecution") {
215
- return `[Bash] ${msg.command}`;
216
- }
217
-
218
- if (msg.role === "user" || msg.role === "assistant") {
219
- let text = "";
220
- if (typeof msg.content === "string") {
221
- text = msg.content;
222
- } else if (Array.isArray(msg.content)) {
223
- text = msg.content
224
- .map((p: any) => {
225
- if (typeof p === "object" && p !== null && "text" in p) return (p as TextContent).text;
226
- return "";
227
- })
228
- .join(" ")
229
- .trim();
230
- }
231
-
232
- let toolCallsText = "";
233
- if (msg.role === "assistant") {
234
- const toolCalls = msg.content.filter((c): c is ToolCall => c.type === "toolCall");
235
-
236
- toolCallsText = toolCalls
237
- .filter((tc) => verbose || !isInternal(tc.name))
238
- .map((tc) => `call: ${tc.name}(${JSON.stringify(tc.arguments)})`)
239
- .join("; ");
240
- }
241
-
242
- return [text, toolCallsText].filter(Boolean).join(" ");
243
- }
244
- }
245
- return "";
246
- };
247
-
248
- const isInteresting = (entry: SessionEntry): boolean => {
249
- // 1. HEAD and Root
250
- if (entry.id === currentLeafId) return true;
251
- if (branch.length > 0 && entry.id === branch[0].id) return true;
252
-
253
- // 2. Explicit Tags (Labels) - Only show the TAGGED node, not the label node itself
254
- if (sm.getLabel(entry.id)) return true;
255
- if (entry.type === 'label') return false; // Hide label nodes, they are redundant
256
-
257
- // 3. Structural Milestones (Summaries)
258
- if (entry.type === 'branch_summary' || entry.type === 'compaction') return true;
259
-
260
- // 4. Branch Points (Forks)
261
- if (sm.getChildren(entry.id).length > 1) return true;
262
-
263
- // 5. Natural Milestones (User Messages) - This is the key auto-tagging mechanism
264
- if (entry.type === 'message' && entry.message.role === 'user') return true;
265
-
266
- return false;
267
- };
268
-
269
- const visibleSequenceIds = new Set<string>();
270
- sequence.forEach(e => {
271
- if (verbose || isInteresting(e)) {
272
- visibleSequenceIds.add(e.id);
273
- }
274
- });
275
-
276
- let visibleEntries = sequence.filter(e => visibleSequenceIds.has(e.id));
277
- if (visibleEntries.length > limit) {
278
- const allowedIds = new Set(visibleEntries.slice(-limit).map(e => e.id));
279
- visibleSequenceIds.clear();
280
- allowedIds.forEach(id => visibleSequenceIds.add(id));
281
- }
282
-
283
- const lines: string[] = [];
284
- let hiddenCount = 0;
285
-
286
- sequence.forEach((entry) => {
287
- if (!visibleSequenceIds.has(entry.id)) {
288
- hiddenCount++;
289
- return;
290
- }
291
-
292
- if (hiddenCount > 0) {
293
- lines.push(` : ... (${hiddenCount} hidden messages) ...`);
294
- hiddenCount = 0;
295
- }
296
-
297
- const isHead = entry.id === currentLeafId;
298
- const label = sm.getLabel(entry.id);
299
- const content = getMsgContent(entry).replace(/\s+/g, " ");
300
-
301
- let role = entry.type.toUpperCase();
302
- if (entry.type === "message") {
303
- const m = entry.message;
304
- role =
305
- m.role === "assistant"
306
- ? "AI"
307
- : m.role === "user"
308
- ? "USER"
309
- : m.role === "bashExecution"
310
- ? "BASH"
311
- : "TOOL";
312
- } else if (entry.type === "branch_summary" || entry.type === "compaction") {
313
- role = "SUMMARY";
314
- }
315
-
316
- // hide custom messages
317
- if (role === "CUSTOM_MESSAGE") {
318
- return
319
- }
320
-
321
- const id = entry.id;
322
- const isRoot = branch.length > 0 && entry.id === branch[0].id;
323
- const meta = [isRoot ? "ROOT" : null, isHead ? "HEAD" : null, label ? `tag: ${label}` : null].filter(Boolean).join(", ");
324
-
325
- const body = content.length > 100 ? content.slice(0, 100) + "..." : content;
326
-
327
- const marker = isHead ? "*" : (role === "USER" ? "•" : "|");
328
-
329
- lines.push(`${marker} ${id}${meta ? ` (${meta})` : ""} [${role}] ${body}`);
330
- });
331
-
332
- if (hiddenCount > 0) {
333
- lines.push(` : ... (${hiddenCount} hidden messages) ...`);
334
- }
335
-
336
- // --- Context Dashboard (HUD) ---
337
- const usage = await ctx.getContextUsage();
338
- let usageStr = "Unknown";
339
- if (usage) {
340
- usageStr = `${usage.percent.toFixed(1)}% (${formatTokens(usage.tokens)}/${formatTokens(usage.contextWindow)})`;
341
- }
342
-
343
- // Find the distance to the nearest tag
344
- let stepsSinceTag = 0;
345
- let nearestTagName = "None";
346
- for (let i = branch.length - 1; i >= 0; i--) {
347
- const id = branch[i].id;
348
- const label = sm.getLabel(id);
349
- if (label) {
350
- nearestTagName = label;
351
- break;
352
- }
353
- stepsSinceTag++;
354
- }
355
-
356
- const hud = [
357
- `[Context Dashboard]`,
358
- `• Context Usage: ${usageStr}`,
359
- `• Segment Size: ${stepsSinceTag} steps since last tag '${nearestTagName}'`,
360
- `---------------------------------------------------`
361
- ].join("\n");
362
-
363
- return { content: [{ type: "text", text: hud + "\n" + (lines.join("\n") || "(Root Path Only)") }], details: {} };
364
- },
365
- });
366
-
367
- pi.registerTool({
368
- name: "context_checkout",
369
- label: "Context Checkout",
370
- description: "Navigate to ANY point in the conversation history. This checkout only resets *conversation history*, NOT disk files. ALWAYS provide a detailed 'message' to bridge context.",
371
- parameters: ContextCheckoutParams,
372
- async execute(_id, params: Static<typeof ContextCheckoutParams>, _signal, _onUpdate, ctx) {
373
- if (!CommandCtx) {
374
- ctx.ui.setEditorText(`/acm ${ctx.ui.getEditorText() || "continue"}`)
375
- return {
376
- content: [{
377
- type: "text",
378
- text: "Agentic context management is not enabled. Ask the user to run `/acm` in DM to enable it, then retry."
379
- }],
380
- details: {}
381
- };
382
- }
383
- const sm = ctx.sessionManager as SessionManager;
384
-
385
- const tid = resolveTargetId(sm, params.target);
386
-
387
- const currentLeaf = sm.getLeafId();
388
- if (currentLeaf === tid) {
389
- return { content: [{ type: "text", text: `Already at target ${tid}` }], details: {} };
390
- }
391
- if (params.backupTag && currentLeaf) {
392
- pi.setLabel(currentLeaf, params.backupTag);
393
- }
394
- const currentLabel = currentLeaf ? sm.getLabel(currentLeaf) : undefined;
395
- const origin = currentLabel ? `tag: ${currentLabel}` : (currentLeaf || "unknown");
396
-
397
- const enrichedMessage = `(summary from ${origin})\n${params.message}`;
398
-
399
- const nid = await sm.branchWithSummary(tid, enrichedMessage);
400
- CheckoutParams = params;
401
- CheckoutParams.nid = nid;
402
- CheckoutParams.tid = tid;
403
- CheckoutParams.enrichedMessage = enrichedMessage;
404
-
405
- return { content: [{ type: "text", text: "checkout start" }], details: {} };
406
- },
407
- });
408
-
409
- pi.on("turn_end", async (event, ctx) => {
410
- if (!CheckoutParams) {
411
- return
412
- }
413
- ctx.abort()
414
- });
415
-
416
- pi.on("agent_end", async (_event, ctx) => {
417
- if (!CheckoutParams) {
418
- return
419
- }
420
- if (!CommandCtx) {
421
- return
422
- }
423
-
424
- await CommandCtx.navigateTree(CheckoutParams.nid, {
425
- summarize: false,
426
- });
427
-
428
- ctx.ui.notify(`Checked out ${CheckoutParams.target}${CheckoutParams.target === CheckoutParams.tid ? "" : `(${CheckoutParams.tid})`}\nBackup tag created: ${CheckoutParams.backupTag || "none"}\nmessage: ${CheckoutParams.enrichedMessage}`, "info");
429
- CheckoutParams = null;
430
-
431
- pi.sendMessage({
432
- customType: "dm-context",
433
- content: "context_checkout complete. A summary of your previous branch was injected above. Read it to understand your new state. Execute the 'Next Step' from the summary",
434
- display: false,
435
- }, {
436
- triggerTurn: true,
437
- });
438
- });
439
- }
@@ -1,6 +0,0 @@
1
- export const formatTokens = (n: number | null | undefined) => {
2
- if (n == null) return "N/A";
3
- if (n >= 1_000_000) return (n / 1_000_000).toFixed(1) + "M";
4
- if (n >= 1_000) return Math.round(n / 1_000) + "k";
5
- return n.toString();
6
- };