mixdog 0.9.3 → 0.9.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 (382) hide show
  1. package/README.md +112 -38
  2. package/package.json +10 -3
  3. package/scripts/bench/lead-review-tasks-r3.json +20 -0
  4. package/scripts/bench/lead-review-tasks.json +20 -0
  5. package/scripts/bench/r4-mixed-tasks.json +20 -0
  6. package/scripts/bench/r5-orchestrated-task.json +7 -0
  7. package/scripts/bench/review-tasks.json +20 -0
  8. package/scripts/bench/round-codex.json +114 -0
  9. package/scripts/bench/round-mixdog-lead-r3.json +269 -0
  10. package/scripts/bench/round-mixdog-lead.json +269 -0
  11. package/scripts/bench/round-mixdog.json +126 -0
  12. package/scripts/bench/round-r10-bigsample.json +679 -0
  13. package/scripts/bench/round-r11-codexalign.json +257 -0
  14. package/scripts/bench/round-r13-clientmeta.json +464 -0
  15. package/scripts/bench/round-r14-betafeatures.json +466 -0
  16. package/scripts/bench/round-r15-fulldefault.json +462 -0
  17. package/scripts/bench/round-r16-sessionid.json +466 -0
  18. package/scripts/bench/round-r17-wirebytes.json +456 -0
  19. package/scripts/bench/round-r18-prewarm.json +468 -0
  20. package/scripts/bench/round-r19-clean.json +472 -0
  21. package/scripts/bench/round-r20-prewarm-clean.json +475 -0
  22. package/scripts/bench/round-r21-delta-retry.json +473 -0
  23. package/scripts/bench/round-r22-full-probe.json +693 -0
  24. package/scripts/bench/round-r23-itemprobe.json +701 -0
  25. package/scripts/bench/round-r24-shapefix.json +677 -0
  26. package/scripts/bench/round-r25-serial.json +464 -0
  27. package/scripts/bench/round-r26-parallel3.json +671 -0
  28. package/scripts/bench/round-r27-parallel10.json +894 -0
  29. package/scripts/bench/round-r28-parallel10-stagger.json +882 -0
  30. package/scripts/bench/round-r29-parallel10-stagger166.json +886 -0
  31. package/scripts/bench/round-r30-instid.json +253 -0
  32. package/scripts/bench/round-r31-upgradeprobe.json +256 -0
  33. package/scripts/bench/round-r32-vs-codex-lead.json +254 -0
  34. package/scripts/bench/round-r33-vs-codex-codex.json +115 -0
  35. package/scripts/bench/round-r34-orchestrated.json +120 -0
  36. package/scripts/bench/round-r35-orchestrated-codex.json +61 -0
  37. package/scripts/bench/round-r36-orchestrated-capped.json +128 -0
  38. package/scripts/bench/round-r4-codex.json +114 -0
  39. package/scripts/bench/round-r4-mixed.json +225 -0
  40. package/scripts/bench/round-r5-gpt-lead.json +259 -0
  41. package/scripts/bench/round-r6-codex.json +114 -0
  42. package/scripts/bench/round-r6-solo.json +257 -0
  43. package/scripts/bench/round-r7-full.json +254 -0
  44. package/scripts/bench/round-r8-fulldefault.json +255 -0
  45. package/scripts/bench-run.mjs +251 -32
  46. package/scripts/freevar-smoke.mjs +95 -0
  47. package/scripts/internal-comms-bench.mjs +3 -4
  48. package/scripts/internal-comms-smoke.mjs +10 -9
  49. package/scripts/model-catalog-audit.mjs +209 -0
  50. package/scripts/model-list-sanitize-test.mjs +37 -0
  51. package/scripts/mouse-probe.mjs +45 -0
  52. package/scripts/output-style-bench.mjs +13 -6
  53. package/scripts/output-style-smoke.mjs +4 -4
  54. package/scripts/provider-toolcall-test.mjs +7 -3
  55. package/scripts/recall-bench.mjs +76 -13
  56. package/scripts/recall-quality-cases.json +12 -0
  57. package/scripts/recall-usecase-cases.json +18 -0
  58. package/scripts/session-bench.mjs +152 -6
  59. package/scripts/tool-smoke.mjs +25 -65
  60. package/scripts/tui-render-smoke.mjs +90 -0
  61. package/scripts/webhook-smoke.mjs +208 -0
  62. package/src/agents/debugger/AGENT.md +4 -1
  63. package/src/agents/heavy-worker/AGENT.md +9 -8
  64. package/src/agents/maintainer/AGENT.md +4 -0
  65. package/src/agents/reviewer/AGENT.md +2 -1
  66. package/src/agents/scheduler-task/AGENT.md +2 -3
  67. package/src/agents/webhook-handler/AGENT.md +2 -3
  68. package/src/agents/worker/AGENT.md +10 -7
  69. package/src/app.mjs +12 -1
  70. package/src/headless-role.mjs +7 -1
  71. package/src/lib/rules-builder.cjs +4 -0
  72. package/src/mixdog-session-runtime.mjs +647 -2056
  73. package/src/output-styles/default.md +30 -9
  74. package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
  75. package/src/output-styles/minimal.md +8 -6
  76. package/src/output-styles/simple.md +21 -7
  77. package/src/rules/agent/00-common.md +6 -3
  78. package/src/rules/agent/30-explorer.md +16 -5
  79. package/src/rules/lead/01-general.md +5 -5
  80. package/src/rules/lead/lead-brief.md +15 -0
  81. package/src/rules/lead/lead-tool.md +6 -15
  82. package/src/rules/shared/01-tool.md +17 -21
  83. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +8 -3
  84. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
  85. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
  86. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
  87. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
  88. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
  89. package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
  90. package/src/runtime/agent/orchestrator/config.mjs +69 -2
  91. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +62 -20
  92. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
  93. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
  94. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +81 -1281
  95. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
  96. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -3
  97. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
  98. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
  99. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
  101. package/src/runtime/agent/orchestrator/providers/gemini.mjs +43 -1013
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +17 -3
  103. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +105 -11
  104. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +356 -0
  105. package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
  107. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
  108. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +40 -1143
  110. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +740 -0
  111. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +349 -2131
  113. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +143 -1002
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +229 -0
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +465 -0
  117. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
  118. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
  119. package/src/runtime/agent/orchestrator/providers/provider-catalog-cache.mjs +80 -0
  120. package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
  121. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
  122. package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
  123. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
  124. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
  125. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
  126. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
  127. package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
  128. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +14 -2
  129. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
  130. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -3
  131. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +275 -0
  132. package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
  133. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
  134. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
  135. package/src/runtime/agent/orchestrator/session/loop.mjs +278 -402
  136. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
  137. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +7 -4
  138. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +12 -0
  139. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
  140. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
  141. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
  142. package/src/runtime/agent/orchestrator/session/manager.mjs +166 -1087
  143. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
  144. package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
  145. package/src/runtime/agent/orchestrator/stall-policy.mjs +20 -1
  146. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
  147. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
  148. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +35 -44
  149. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
  150. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
  151. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
  152. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
  153. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -92
  154. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
  155. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
  156. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +28 -265
  157. package/src/runtime/agent/orchestrator/tools/builtin.mjs +0 -6
  158. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +57 -3
  159. package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
  160. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +10 -122
  161. package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
  162. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
  163. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
  164. package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
  165. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
  166. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
  167. package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
  168. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
  169. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
  170. package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
  171. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
  172. package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
  173. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +0 -21
  174. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +9 -72
  175. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
  176. package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
  177. package/src/runtime/channels/backends/discord-access.mjs +32 -0
  178. package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
  179. package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
  180. package/src/runtime/channels/backends/discord.mjs +27 -318
  181. package/src/runtime/channels/backends/telegram.mjs +8 -12
  182. package/src/runtime/channels/index.mjs +247 -701
  183. package/src/runtime/channels/lib/backend-dispatch.mjs +46 -0
  184. package/src/runtime/channels/lib/config.mjs +37 -149
  185. package/src/runtime/channels/lib/event-pipeline.mjs +22 -5
  186. package/src/runtime/channels/lib/event-queue.mjs +78 -13
  187. package/src/runtime/channels/lib/inbound-routing.mjs +74 -0
  188. package/src/runtime/channels/lib/interaction-workflows.mjs +5 -113
  189. package/src/runtime/channels/lib/output-forwarder.mjs +1 -1
  190. package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
  191. package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
  192. package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
  193. package/src/runtime/channels/lib/scheduler.mjs +27 -113
  194. package/src/runtime/channels/lib/session-discovery.mjs +56 -4
  195. package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
  196. package/src/runtime/channels/lib/tool-format.mjs +1 -1
  197. package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
  198. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
  199. package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
  200. package/src/runtime/channels/lib/webhook/deliveries.mjs +313 -0
  201. package/src/runtime/channels/lib/webhook/log.mjs +42 -0
  202. package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
  203. package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
  204. package/src/runtime/channels/lib/webhook.mjs +43 -616
  205. package/src/runtime/channels/tool-defs.mjs +11 -130
  206. package/src/runtime/memory/index.mjs +210 -1948
  207. package/src/runtime/memory/lib/core-memory-store.mjs +5 -1
  208. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
  209. package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
  210. package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
  211. package/src/runtime/memory/lib/ko-morph.mjs +195 -0
  212. package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
  213. package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
  214. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
  215. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
  216. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
  217. package/src/runtime/memory/lib/memory-cycle2.mjs +24 -842
  218. package/src/runtime/memory/lib/memory-embed.mjs +149 -0
  219. package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
  220. package/src/runtime/memory/lib/memory-recall-store.mjs +69 -12
  221. package/src/runtime/memory/lib/memory-text-utils.mjs +46 -0
  222. package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
  223. package/src/runtime/memory/lib/query-handlers.mjs +802 -0
  224. package/src/runtime/memory/lib/recall-format.mjs +55 -0
  225. package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
  226. package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
  227. package/src/runtime/memory/tool-defs.mjs +5 -13
  228. package/src/runtime/search/lib/http-fetch.mjs +274 -0
  229. package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
  230. package/src/runtime/search/lib/web-tools.mjs +24 -602
  231. package/src/runtime/shared/atomic-file.mjs +26 -1
  232. package/src/runtime/shared/config.mjs +14 -4
  233. package/src/runtime/shared/launcher-control.mjs +2 -2
  234. package/src/runtime/shared/markdown-frontmatter.mjs +19 -0
  235. package/src/runtime/shared/schedules-store.mjs +13 -3
  236. package/src/runtime/shared/tool-execution-contract.mjs +2 -2
  237. package/src/runtime/shared/tool-primitives.mjs +308 -0
  238. package/src/runtime/shared/tool-result-summary.mjs +515 -0
  239. package/src/runtime/shared/tool-surface.mjs +80 -898
  240. package/src/runtime/shared/transcript-writer.mjs +23 -0
  241. package/src/runtime/shared/update-checker.mjs +7 -4
  242. package/src/session-runtime/config-helpers.mjs +119 -2
  243. package/src/session-runtime/config-lifecycle.mjs +232 -0
  244. package/src/session-runtime/cwd-plugins.mjs +226 -0
  245. package/src/session-runtime/mcp-glue.mjs +177 -0
  246. package/src/session-runtime/model-recency.mjs +111 -0
  247. package/src/session-runtime/native-search.mjs +247 -0
  248. package/src/session-runtime/output-styles.mjs +11 -9
  249. package/src/session-runtime/prewarm.mjs +142 -0
  250. package/src/session-runtime/provider-models.mjs +278 -0
  251. package/src/session-runtime/provider-usage.mjs +120 -0
  252. package/src/session-runtime/quick-model-rows.mjs +205 -0
  253. package/src/session-runtime/quick-search-models.mjs +47 -0
  254. package/src/session-runtime/session-hooks.mjs +93 -0
  255. package/src/session-runtime/settings-api.mjs +352 -0
  256. package/src/session-runtime/tool-catalog.mjs +29 -29
  257. package/src/session-runtime/tool-defs.mjs +84 -0
  258. package/src/session-runtime/warmup-schedulers.mjs +201 -0
  259. package/src/session-runtime/workflow.mjs +1 -1
  260. package/src/standalone/agent-tool/helpers.mjs +237 -0
  261. package/src/standalone/agent-tool/notify.mjs +107 -0
  262. package/src/standalone/agent-tool/provider-init.mjs +143 -0
  263. package/src/standalone/agent-tool/render.mjs +152 -0
  264. package/src/standalone/agent-tool/tool-def.mjs +55 -0
  265. package/src/standalone/agent-tool.mjs +138 -669
  266. package/src/standalone/channel-admin.mjs +102 -90
  267. package/src/standalone/channel-worker.mjs +4 -7
  268. package/src/standalone/explore-tool.mjs +64 -14
  269. package/src/standalone/hook-bus/config.mjs +207 -0
  270. package/src/standalone/hook-bus/constants.mjs +90 -0
  271. package/src/standalone/hook-bus/handlers.mjs +481 -0
  272. package/src/standalone/hook-bus/payload.mjs +31 -0
  273. package/src/standalone/hook-bus/rules.mjs +77 -0
  274. package/src/standalone/hook-bus.mjs +77 -870
  275. package/src/standalone/memory-runtime-proxy.mjs +7 -0
  276. package/src/standalone/opencode-go-login.mjs +5 -1
  277. package/src/standalone/provider-admin.mjs +1 -16
  278. package/src/standalone/usage-dashboard.mjs +3 -1
  279. package/src/tui/App.jsx +1059 -8110
  280. package/src/tui/app/app-format.mjs +213 -0
  281. package/src/tui/app/channel-pickers.mjs +508 -0
  282. package/src/tui/app/clipboard.mjs +67 -0
  283. package/src/tui/app/core-memory-picker.mjs +210 -0
  284. package/src/tui/app/extension-pickers.mjs +506 -0
  285. package/src/tui/app/input-parsers.mjs +193 -0
  286. package/src/tui/app/maintenance-pickers.mjs +356 -0
  287. package/src/tui/app/model-options.mjs +334 -0
  288. package/src/tui/app/model-picker.mjs +365 -0
  289. package/src/tui/app/onboarding-steps.mjs +400 -0
  290. package/src/tui/app/project-picker.mjs +247 -0
  291. package/src/tui/app/provider-setup-picker.mjs +580 -0
  292. package/src/tui/app/resume-picker.mjs +55 -0
  293. package/src/tui/app/route-pickers.mjs +419 -0
  294. package/src/tui/app/settings-picker.mjs +489 -0
  295. package/src/tui/app/slash-commands.mjs +101 -0
  296. package/src/tui/app/slash-dispatch.mjs +427 -0
  297. package/src/tui/app/text-layout.mjs +46 -0
  298. package/src/tui/app/theme-effort-pickers.mjs +154 -0
  299. package/src/tui/app/transcript-window.mjs +677 -0
  300. package/src/tui/app/use-mouse-input.mjs +460 -0
  301. package/src/tui/app/use-prompt-handlers.mjs +310 -0
  302. package/src/tui/app/use-transcript-scroll.mjs +512 -0
  303. package/src/tui/app/use-transcript-window.mjs +607 -0
  304. package/src/tui/components/ConfirmBar.jsx +10 -7
  305. package/src/tui/components/Picker.jsx +64 -15
  306. package/src/tui/components/PromptInput.jsx +33 -102
  307. package/src/tui/components/SlashCommandPalette.jsx +8 -1
  308. package/src/tui/components/StatusLine.jsx +69 -15
  309. package/src/tui/components/TextEntryPanel.jsx +11 -0
  310. package/src/tui/components/ToolExecution.jsx +52 -594
  311. package/src/tui/components/TranscriptItem.jsx +105 -0
  312. package/src/tui/components/UsagePanel.jsx +18 -4
  313. package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
  314. package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
  315. package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
  316. package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
  317. package/src/tui/components/tool-execution/text-format.mjs +161 -0
  318. package/src/tui/display-width.mjs +20 -3
  319. package/src/tui/dist/index.mjs +13553 -12384
  320. package/src/tui/engine/agent-job-feed.mjs +133 -0
  321. package/src/tui/engine/notification-plan.mjs +76 -0
  322. package/src/tui/engine/render-timing.mjs +17 -0
  323. package/src/tui/engine/tool-approval.mjs +94 -0
  324. package/src/tui/engine/tool-card-results.mjs +234 -0
  325. package/src/tui/engine/tool-result-status.mjs +135 -0
  326. package/src/tui/engine.mjs +170 -574
  327. package/src/tui/figures.mjs +5 -0
  328. package/src/tui/index.jsx +65 -1
  329. package/src/tui/input-editing.mjs +2 -2
  330. package/src/tui/markdown/format-token.mjs +4 -1
  331. package/src/tui/statusline-ansi-bridge.mjs +11 -3
  332. package/src/tui/theme.mjs +6 -0
  333. package/src/ui/statusline-agents.mjs +213 -0
  334. package/src/ui/statusline-format.mjs +146 -0
  335. package/src/ui/statusline-segments.mjs +148 -0
  336. package/src/ui/statusline.mjs +77 -501
  337. package/src/ui/tool-card.mjs +0 -1
  338. package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
  339. package/src/workflows/default/WORKFLOW.md +16 -18
  340. package/src/workflows/sequential/WORKFLOW.md +16 -18
  341. package/vendor/ink/build/display-width.js +19 -3
  342. package/vendor/ink/build/ink.js +112 -7
  343. package/vendor/ink/build/log-update.js +17 -3
  344. package/vendor/ink/build/wrap-text.js +125 -0
  345. package/scripts/_test-folder-dialog.mjs +0 -30
  346. package/scripts/fix-brief-fn.mjs +0 -35
  347. package/scripts/fix-format-tool-surface.mjs +0 -24
  348. package/scripts/fix-tool-exec-visible.mjs +0 -42
  349. package/scripts/patch-agent-brief.mjs +0 -48
  350. package/scripts/patch-app.mjs +0 -21
  351. package/scripts/patch-app2.mjs +0 -18
  352. package/scripts/patch-dist-brief.mjs +0 -96
  353. package/scripts/patch-tool-exec.mjs +0 -70
  354. package/src/examples/schedules/SCHEDULE.example.md +0 -32
  355. package/src/examples/webhooks/WEBHOOK.example.md +0 -40
  356. package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
  357. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
  358. package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
  359. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.test.mjs +0 -162
  360. package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
  361. package/src/runtime/channels/lib/holidays.mjs +0 -138
  362. package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
  363. package/src/runtime/shared/task-notification-envelope.test.mjs +0 -107
  364. package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
  365. package/src/standalone/agent-task-status.test.mjs +0 -76
  366. package/src/tui/components/tool-output-format.test.mjs +0 -399
  367. package/src/tui/display-width.test.mjs +0 -35
  368. package/src/tui/engine-runtime-notification.test.mjs +0 -115
  369. package/src/tui/engine-tool-result-text.test.mjs +0 -75
  370. package/src/tui/input-editing.selection.test.mjs +0 -75
  371. package/src/tui/markdown/format-token.test.mjs +0 -354
  372. package/src/tui/markdown/render-ansi.test.mjs +0 -108
  373. package/src/tui/markdown/stream-fence.test.mjs +0 -26
  374. package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
  375. package/src/tui/paste-fix.test.mjs +0 -119
  376. package/src/tui/prompt-history-store.test.mjs +0 -52
  377. package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
  378. package/src/tui/transcript-tool-failures.test.mjs +0 -111
  379. package/src/ui/markdown.test.mjs +0 -70
  380. package/src/ui/statusline-context-label.test.mjs +0 -15
  381. package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
  382. package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
@@ -24,28 +24,21 @@ import { loadConfig } from '../config.mjs';
24
24
  import { AGENT_OWNER } from '../agent-owner.mjs';
25
25
 
26
26
  import {
27
- COMPACT_TYPE_RECALL_FASTTRACK,
28
27
  COMPACT_TYPE_SEMANTIC,
29
28
  normalizeCompactType,
30
29
  } from '../session/compact.mjs';
31
30
 
32
- function memoryModuleEnabled(config) {
33
- const entry = config?.modules?.memory;
34
- if (entry && typeof entry === 'object' && entry.enabled === false) return false;
35
- return true;
36
- }
37
-
38
31
  function normalizeAgentCompactionConfig(value = {}, { memoryEnabled = true } = {}) {
39
32
  const raw = value && typeof value === 'object' ? value : {};
40
33
  let compactType = normalizeCompactType(
41
34
  raw.compactType ?? raw.compact_type ?? raw.type,
42
35
  COMPACT_TYPE_SEMANTIC,
43
36
  );
44
- // recall-fasttrack depends on memory ingest/recall; fall back to semantic when
45
- // the memory module is disabled (same rule as Lead session runtime).
46
- if (compactType === COMPACT_TYPE_RECALL_FASTTRACK && memoryEnabled === false) {
47
- compactType = COMPACT_TYPE_SEMANTIC;
48
- }
37
+ // Memory is now always-on, so recall-fasttrack no longer downgrades to
38
+ // semantic. `memoryEnabled` is retained as a param for API compatibility
39
+ // but is intentionally ignored (fasttrack drains run on-demand regardless
40
+ // of the recap/background-cycle toggle) — mirrors config-helpers.mjs.
41
+ void memoryEnabled;
49
42
  return {
50
43
  ...raw,
51
44
  auto: raw.auto !== false && raw.enabled !== false,
@@ -109,9 +102,7 @@ export function prepareAgentSession({
109
102
  try {
110
103
  const cfg = loadConfig({ secrets: false });
111
104
  if (cfg?.compaction && typeof cfg.compaction === 'object') {
112
- compaction = normalizeAgentCompactionConfig(cfg.compaction, {
113
- memoryEnabled: memoryModuleEnabled(cfg),
114
- });
105
+ compaction = normalizeAgentCompactionConfig(cfg.compaction);
115
106
  }
116
107
  } catch { /* config is best-effort for agent compaction policy */ }
117
108
  const sessionOpts = {
@@ -0,0 +1,362 @@
1
+ import { createHash } from 'crypto';
2
+ import { countJsonNextCalls } from './tools/next-call-utils.mjs';
3
+ import {
4
+ appendAgentTrace,
5
+ normalizeSessionId,
6
+ warnAgentOnce,
7
+ _resolveToolFailurePath,
8
+ _appendToolFailureRow,
9
+ } from './agent-trace-io.mjs';
10
+
11
+ const MIXDOG_SLOW_TOOL_TRACE_MS = (() => {
12
+ const v = parseInt(process.env.MIXDOG_SLOW_TOOL_TRACE_MS, 10);
13
+ return Number.isFinite(v) && v > 0 ? v : 3000;
14
+ })();
15
+ const MIXDOG_SLOW_TOOL_TRACE_NAMES_RAW = String(process.env.MIXDOG_SLOW_TOOL_TRACE_NAMES || 'recall,grep,code_graph');
16
+ const MIXDOG_SLOW_TOOL_TRACE_ALL = MIXDOG_SLOW_TOOL_TRACE_NAMES_RAW.trim() === '*';
17
+ const MIXDOG_SLOW_TOOL_TRACE_NAMES = new Set(
18
+ MIXDOG_SLOW_TOOL_TRACE_NAMES_RAW
19
+ .split(',')
20
+ .map((name) => name.trim())
21
+ .filter(Boolean)
22
+ );
23
+
24
+ function traceAgentLoop({ sessionId, iteration, sendMs, messageCount, bodyBytesEst }) {
25
+ if (process.env.MIXDOG_AGENT_TRACE_VERBOSE !== '1') return;
26
+ appendAgentTrace({
27
+ sessionId,
28
+ iteration,
29
+ kind: 'loop',
30
+ send_ms: sendMs,
31
+ message_count: messageCount,
32
+ body_bytes_est: bodyBytesEst,
33
+ });
34
+ }
35
+
36
+ function traceAgentCompact({
37
+ sessionId,
38
+ iteration,
39
+ stage,
40
+ trigger,
41
+ compact_type,
42
+ prune_count,
43
+ compact_changed,
44
+ input_prefix_hash,
45
+ before_count,
46
+ after_count,
47
+ before_bytes,
48
+ after_bytes,
49
+ context_window,
50
+ budget_tokens,
51
+ boundary_tokens,
52
+ target_budget_tokens,
53
+ reserve_tokens,
54
+ pressure_tokens,
55
+ trigger_tokens,
56
+ message_tokens_est,
57
+ duration_ms,
58
+ provider,
59
+ model,
60
+ error,
61
+ error_code,
62
+ details,
63
+ }) {
64
+ appendAgentTrace({
65
+ sessionId,
66
+ iteration,
67
+ kind: 'compact_meta',
68
+ stage: stage || null,
69
+ trigger: trigger || null,
70
+ compact_type: compact_type || null,
71
+ prune_count: prune_count ?? 0,
72
+ compact_changed: !!compact_changed,
73
+ input_prefix_hash: input_prefix_hash || null,
74
+ before_count: before_count ?? null,
75
+ after_count: after_count ?? null,
76
+ before_bytes: before_bytes ?? null,
77
+ after_bytes: after_bytes ?? null,
78
+ context_window: context_window ?? null,
79
+ budget_tokens: budget_tokens ?? null,
80
+ boundary_tokens: boundary_tokens ?? null,
81
+ target_budget_tokens: target_budget_tokens ?? null,
82
+ reserve_tokens: reserve_tokens ?? null,
83
+ pressure_tokens: pressure_tokens ?? null,
84
+ trigger_tokens: trigger_tokens ?? null,
85
+ message_tokens_est: message_tokens_est ?? null,
86
+ duration_ms: duration_ms ?? null,
87
+ provider: provider || null,
88
+ model: model || null,
89
+ error: error || null,
90
+ error_code: error_code || null,
91
+ details: details && typeof details === 'object' ? details : null,
92
+ });
93
+ }
94
+
95
+ const TOOL_ARG_KEYS = {
96
+ read: ['path', 'offset', 'limit', 'line', 'context', 'symbol'],
97
+ grep: ['pattern', 'path', 'glob', 'output_mode', 'head_limit', 'offset'],
98
+ glob: ['pattern', 'path', 'head_limit', 'offset', 'sort'],
99
+ find: ['query', 'path', 'head_limit'],
100
+ list: ['path', 'head_limit', 'offset'],
101
+ recall: ['query', 'limit', 'session_id', 'cwd'],
102
+ search: ['query', 'limit', 'cwd'],
103
+ explore: ['query', 'queries', 'limit', 'cwd'],
104
+ code_graph: ['mode', 'file', 'symbol', 'symbols', 'body', 'language', 'limit', 'depth', 'page', 'cwd'],
105
+ shell: ['command', 'cwd', 'timeout', 'mode', 'run_in_background', 'persistent', 'session_id'],
106
+ task: ['task_id', 'action', 'timeout_ms', 'poll_ms'],
107
+ edit: ['path', 'replace_all', 'edits'],
108
+ edit_many: ['edits'],
109
+ write: ['path'],
110
+ apply_patch: ['base_path', 'dry_run'],
111
+ };
112
+
113
+ const REDACT_KEY_RE = /token|secret|password|passwd|credential|authorization|api[_-]?key/i;
114
+ const BODY_KEY_RE = /content|old_string|new_string|patch|rewrite/i;
115
+ // Redact shell `command` values that look like they carry secrets. Covers
116
+ // assignment forms, Authorization headers, --password / -p flags, and
117
+ function _redactShellCommand(cmd) {
118
+ if (typeof cmd !== 'string') return cmd;
119
+ let out = cmd;
120
+ // Assignment RHS: PASSWORD=, SECRET=, TOKEN=, API_KEY=/APIKEY=.
121
+ out = out.replace(/((?:PASSWORD|SECRET|TOKEN|API_KEY|APIKEY)\s*=\s*)\S+/gi, '$1[redacted]');
122
+ // Authorization: Bearer <token>.
123
+ out = out.replace(/(Authorization:\s*Bearer\s+)\S+/gi, '$1[redacted]');
124
+ // Long flags: --password <v> / --password=<v> (also --token, --secret, --api-key).
125
+ out = out.replace(/(--(?:password|token|secret|api[-_]?key)(?:\s+|=))\S+/gi, '$1[redacted]');
126
+ // Short -p <v> flag (mysql/psql/curl style).
127
+ out = out.replace(/((?:^|\s)-p(?:\s+|=))\S+/g, '$1[redacted]');
128
+ // URL userinfo: scheme://user:secret@host -> scheme://user:[redacted]@host.
129
+ out = out.replace(/(:\/\/[^:\/\s@]+:)[^@\s]+(@)/g, '$1[redacted]$2');
130
+ // URL query params carrying tokens/keys.
131
+ out = out.replace(/([?&](?:token|api[-_]?key|access[-_]?token|auth|password|secret)=)[^&\s#]+/gi, '$1[redacted]');
132
+ return out;
133
+ }
134
+
135
+ function compactTraceArgValue(value, key = '', depth = 0) {
136
+ if (REDACT_KEY_RE.test(key)) return '[redacted]';
137
+ if (value === null || value === undefined) return value;
138
+ if (typeof value === 'string') {
139
+ // Redact shell commands that embed secrets before length-truncating.
140
+ if (key === 'command') {
141
+ value = _redactShellCommand(value);
142
+ }
143
+ const limit = BODY_KEY_RE.test(key) ? 60 : 180;
144
+ return value.length > limit ? `${value.slice(0, limit)}...` : value;
145
+ }
146
+ if (typeof value === 'number' || typeof value === 'boolean') return value;
147
+ if (Array.isArray(value)) {
148
+ if (depth >= 2) return `[${value.length} items]`;
149
+ return value.slice(0, 6).map((v) => compactTraceArgValue(v, key, depth + 1));
150
+ }
151
+ if (typeof value === 'object') {
152
+ if (depth >= 2) return '{...}';
153
+ const out = {};
154
+ for (const [k, v] of Object.entries(value).slice(0, 12)) {
155
+ out[k] = compactTraceArgValue(v, k, depth + 1);
156
+ }
157
+ return out;
158
+ }
159
+ return String(value);
160
+ }
161
+
162
+ function summarizeToolArgs(toolName, args) {
163
+ if (!args || typeof args !== 'object') return null;
164
+ const keys = TOOL_ARG_KEYS[String(toolName || '')] || Object.keys(args).slice(0, 8);
165
+ const out = {};
166
+ for (const key of keys) {
167
+ if (Object.prototype.hasOwnProperty.call(args, key)) out[key] = compactTraceArgValue(args[key], key);
168
+ }
169
+ for (const countKey of ['edits', 'writes']) {
170
+ if (Array.isArray(args[countKey])) out[`${countKey}_count`] = args[countKey].length;
171
+ }
172
+ if (toolName === 'read' && Array.isArray(args.path)) {
173
+ out.path_count = args.path.length;
174
+ }
175
+ return Object.keys(out).length ? out : null;
176
+ }
177
+
178
+ function stableTraceStringify(value) {
179
+ if (value === null || value === undefined) return JSON.stringify(value);
180
+ if (typeof value !== 'object') return JSON.stringify(value);
181
+ if (Array.isArray(value)) return '[' + value.map(stableTraceStringify).join(',') + ']';
182
+ const keys = Object.keys(value).sort();
183
+ return '{' + keys.map((k) => `${JSON.stringify(k)}:${stableTraceStringify(value[k])}`).join(',') + '}';
184
+ }
185
+
186
+ function hashTraceValue(value) {
187
+ try {
188
+ return createHash('sha256').update(stableTraceStringify(value)).digest('hex').slice(0, 16);
189
+ } catch {
190
+ return null;
191
+ }
192
+ }
193
+
194
+ function _firstNonEmptyLine(text) {
195
+ return String(text ?? '').split(/\r?\n/).find((line) => line.trim())?.trim() || '';
196
+ }
197
+
198
+ function _redactLogText(text) {
199
+ if (typeof text !== 'string') return '';
200
+ let out = text;
201
+ out = out.replace(/(Authorization:\s*Bearer\s+)\S+/gi, '$1[redacted]');
202
+ out = out.replace(/([?&](?:token|api[-_]?key|access[-_]?token|auth|password|secret)=)[^&\s#]+/gi, '$1[redacted]');
203
+ out = out.replace(/((?:PASSWORD|SECRET|TOKEN|API_KEY|APIKEY)\s*=\s*)\S+/gi, '$1[redacted]');
204
+ return out;
205
+ }
206
+
207
+ function classifyToolFailure(resultText, toolName) {
208
+ const text = String(resultText ?? '').toLowerCase();
209
+ if (/requires either|invalid arguments|unknown parameter|must be|schema|expected|required|old_string is .*>=/.test(text)) return 'schema/args';
210
+ if (/enoent|cannot find|not found at this path|path does not exist|no such file|file not found in graph|unreadable/.test(text)) return 'path/cwd';
211
+ if (/timed out|timeout|interrupted|aborted/.test(text)) return 'timeout/abort';
212
+ if (/hunk rejected|patch failed|context mismatch|expected first old\/context|context not found/.test(text)) return 'patch/context';
213
+ if (/not in allow-list|permission|denied|forbidden|not allowed/.test(text)) return 'permission';
214
+ if (/unknown tool|tool.*not.*available|missing.*tool/.test(text)) return 'tool-surface';
215
+ if (String(toolName || '') === 'shell' || /^\s*\[exit code:\s*\d+\]/i.test(String(resultText ?? ''))) return 'command-exit';
216
+ return 'runtime/failure';
217
+ }
218
+
219
+ function traceAgentToolFailure({ sessionId, iteration, toolName, toolKind, toolMs, toolArgs, agent, model, cwd, resultText, resultKind = 'error' }) {
220
+ if (process.env.MIXDOG_AGENT_TRACE_DISABLE === '1') return;
221
+ if (!_resolveToolFailurePath()) return;
222
+ try {
223
+ const cleanText = _redactLogText(String(resultText ?? ''));
224
+ const row = {
225
+ ts: Date.now(),
226
+ session_id: normalizeSessionId(sessionId),
227
+ iteration: iteration ?? null,
228
+ tool_name: toolName || null,
229
+ tool_kind: toolKind || null,
230
+ result_kind: resultKind || 'error',
231
+ category: classifyToolFailure(cleanText, toolName),
232
+ agent: agent || null,
233
+ model: model || null,
234
+ cwd: cwd || null,
235
+ tool_ms: Number.isFinite(Number(toolMs)) ? Number(toolMs) : null,
236
+ tool_args: summarizeToolArgs(toolName, toolArgs),
237
+ error_first_line: _firstNonEmptyLine(cleanText).slice(0, 300),
238
+ error_preview: cleanText.slice(0, 1200),
239
+ result_bytes_est: Buffer.byteLength(cleanText, 'utf8'),
240
+ result_lines_est: cleanText.length > 0 ? cleanText.split('\n').length : 0,
241
+ };
242
+ _appendToolFailureRow(row);
243
+ } catch (err) {
244
+ warnAgentOnce('tool-failure-log:append', `[tool-failure-log] append failed (${err?.message})`);
245
+ }
246
+ }
247
+
248
+ function traceAgentTool({ sessionId, iteration, toolName, toolKind, toolMs, toolArgs, agent, resultKind, model, resultText, cwd }) {
249
+ const nextCallCount = countJsonNextCalls(resultText);
250
+ const resultBytesEst = typeof resultText === 'string' ? Buffer.byteLength(resultText, 'utf8') : 0;
251
+ const resultLinesEst = typeof resultText === 'string' && resultText.length > 0 ? resultText.split('\n').length : 0;
252
+ const numericToolMs = Number(toolMs);
253
+ const summarizedArgs = summarizeToolArgs(toolName, toolArgs);
254
+ // Hash the FULL args, not the summary: summaries drop payload fields
255
+ // (e.g. apply_patch keeps only base_path), which made every patch in a
256
+ // session collide to one hash and broke duplicate/retry detection.
257
+ const toolArgsHash = toolArgs && typeof toolArgs === 'object'
258
+ ? hashTraceValue(toolArgs)
259
+ : (summarizedArgs ? hashTraceValue(summarizedArgs) : null);
260
+ // Keep a short redacted error preview on the tool row itself so trace
261
+ // analysis can see WHY a call failed without joining the failure log.
262
+ const errorFirstLine = resultKind === 'error'
263
+ ? _firstNonEmptyLine(_redactLogText(String(resultText ?? ''))).slice(0, 200) || null
264
+ : null;
265
+ // Flat shape — fields named exactly as the agent_calls PG columns so
266
+ // insertAgentCalls can pick them up by direct property access without
267
+ // a payload-unwrap step. result_kind has no column and rides as plain
268
+ // sibling metadata for downstream consumers.
269
+ appendAgentTrace({
270
+ sessionId,
271
+ iteration,
272
+ kind: 'tool',
273
+ agent: agent || null,
274
+ model: model || null,
275
+ tool_name: toolName,
276
+ tool_kind: toolKind,
277
+ tool_ms: toolMs,
278
+ tool_args: summarizedArgs,
279
+ tool_args_hash: toolArgsHash,
280
+ tool_args_summary: summarizedArgs,
281
+ result_kind: resultKind || null,
282
+ result_error_first_line: errorFirstLine,
283
+ result_has_next_call: nextCallCount > 0,
284
+ result_next_call_count: nextCallCount,
285
+ result_bytes_est: resultBytesEst,
286
+ result_lines_est: resultLinesEst,
287
+ });
288
+ if (
289
+ Number.isFinite(numericToolMs)
290
+ && numericToolMs >= MIXDOG_SLOW_TOOL_TRACE_MS
291
+ && (MIXDOG_SLOW_TOOL_TRACE_ALL || MIXDOG_SLOW_TOOL_TRACE_NAMES.size === 0 || MIXDOG_SLOW_TOOL_TRACE_NAMES.has(String(toolName || '')))
292
+ ) {
293
+ appendAgentTrace({
294
+ sessionId,
295
+ iteration,
296
+ kind: 'tool_slow',
297
+ agent: agent || null,
298
+ model: model || null,
299
+ tool_name: toolName,
300
+ tool_kind: toolKind,
301
+ tool_ms: numericToolMs,
302
+ payload: {
303
+ threshold_ms: MIXDOG_SLOW_TOOL_TRACE_MS,
304
+ result_kind: resultKind || null,
305
+ tool_args: summarizedArgs,
306
+ tool_args_hash: toolArgsHash,
307
+ tool_args_summary: summarizedArgs,
308
+ result_has_next_call: nextCallCount > 0,
309
+ result_next_call_count: nextCallCount,
310
+ result_bytes_est: resultBytesEst,
311
+ result_lines_est: resultLinesEst,
312
+ cwd: cwd || null,
313
+ },
314
+ });
315
+ }
316
+ if (resultKind === 'error') {
317
+ traceAgentToolFailure({ sessionId, iteration, toolName, toolKind, toolMs, toolArgs, agent, model, cwd, resultText, resultKind });
318
+ }
319
+ }
320
+
321
+ // Compression layer trace (result-compression.mjs). One row per tool call
322
+ // where compression actually changed the byte count, so `gain` analytics
323
+ // can sum savings_pct over a window (mirrors RTK's `rtk gain` model
324
+ // without an external binary). No-op rows are dropped at the call site.
325
+ export function traceAgentCompress({ sessionId, toolName, before, after }) {
326
+ // bytes_before/after/savings_pct moved into payload because the
327
+ // trace_events table only carries known top-level columns (id, ts,
328
+ // session_id, kind, tool_name, payload, ...) — fields outside that
329
+ // set are silently dropped at insert time. payload is jsonb so any
330
+ // shape survives. Aggregation: SELECT (payload->>'bytes_before')::int.
331
+ appendAgentTrace({
332
+ sessionId,
333
+ kind: 'compress',
334
+ tool_name: toolName,
335
+ payload: {
336
+ bytes_before: before,
337
+ bytes_after: after,
338
+ savings_pct: before > 0 ? Math.round((1 - after / before) * 100) : 0,
339
+ },
340
+ });
341
+ }
342
+
343
+ // Per-turn batch shape — one row per assistant turn with the number of
344
+ // tool calls observed. Lets a consumer compute Lead-side multi-tool
345
+ // adoption ratio (calls > 1 / total turns) directly from trace rows
346
+ // instead of re-parsing every assistant message body.
347
+ export function traceAgentBatch({ sessionId, toolCallCount }) {
348
+ appendAgentTrace({
349
+ sessionId,
350
+ kind: 'batch',
351
+ tool_call_count: toolCallCount,
352
+ });
353
+ }
354
+
355
+ export {
356
+ traceAgentLoop,
357
+ traceAgentCompact,
358
+ traceAgentTool,
359
+ traceAgentToolFailure,
360
+ summarizeToolArgs,
361
+ classifyToolFailure,
362
+ };