mixdog 0.9.3 → 0.9.4

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 (329) hide show
  1. package/package.json +7 -3
  2. package/scripts/bench/lead-review-tasks-r3.json +20 -0
  3. package/scripts/bench/lead-review-tasks.json +20 -0
  4. package/scripts/bench/r4-mixed-tasks.json +20 -0
  5. package/scripts/bench/review-tasks.json +20 -0
  6. package/scripts/bench/round-codex.json +114 -0
  7. package/scripts/bench/round-mixdog-lead-r3.json +269 -0
  8. package/scripts/bench/round-mixdog-lead.json +269 -0
  9. package/scripts/bench/round-mixdog.json +126 -0
  10. package/scripts/bench/round-r10-bigsample.json +679 -0
  11. package/scripts/bench/round-r11-codexalign.json +257 -0
  12. package/scripts/bench/round-r4-codex.json +114 -0
  13. package/scripts/bench/round-r4-mixed.json +225 -0
  14. package/scripts/bench/round-r5-gpt-lead.json +259 -0
  15. package/scripts/bench/round-r6-codex.json +114 -0
  16. package/scripts/bench/round-r6-solo.json +257 -0
  17. package/scripts/bench/round-r7-full.json +254 -0
  18. package/scripts/bench/round-r8-fulldefault.json +255 -0
  19. package/scripts/bench-run.mjs +215 -29
  20. package/scripts/freevar-smoke.mjs +95 -0
  21. package/scripts/internal-comms-bench.mjs +1 -0
  22. package/scripts/internal-comms-smoke.mjs +10 -9
  23. package/scripts/mouse-probe.mjs +45 -0
  24. package/scripts/output-style-bench.mjs +13 -6
  25. package/scripts/output-style-smoke.mjs +4 -4
  26. package/scripts/provider-toolcall-test.mjs +7 -3
  27. package/scripts/recall-usecase-cases.json +18 -0
  28. package/scripts/recall-usecase-probe.json +6 -0
  29. package/scripts/session-bench.mjs +152 -6
  30. package/scripts/tool-smoke.mjs +23 -63
  31. package/scripts/tui-render-smoke.mjs +90 -0
  32. package/scripts/webhook-smoke.mjs +208 -0
  33. package/src/agents/debugger/AGENT.md +4 -1
  34. package/src/agents/heavy-worker/AGENT.md +6 -5
  35. package/src/agents/maintainer/AGENT.md +4 -0
  36. package/src/agents/reviewer/AGENT.md +2 -1
  37. package/src/agents/worker/AGENT.md +8 -4
  38. package/src/lib/rules-builder.cjs +4 -0
  39. package/src/mixdog-session-runtime.mjs +632 -2042
  40. package/src/output-styles/default.md +34 -9
  41. package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
  42. package/src/output-styles/minimal.md +4 -1
  43. package/src/output-styles/simple.md +22 -7
  44. package/src/rules/agent/00-common.md +2 -0
  45. package/src/rules/lead/lead-brief.md +12 -0
  46. package/src/rules/lead/lead-tool.md +0 -11
  47. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
  48. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
  49. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
  50. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
  51. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
  52. package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
  53. package/src/runtime/agent/orchestrator/config.mjs +69 -2
  54. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +62 -20
  55. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
  56. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
  57. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +81 -1281
  58. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
  59. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -3
  60. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
  61. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
  62. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
  63. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
  64. package/src/runtime/agent/orchestrator/providers/gemini.mjs +43 -1013
  65. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +17 -3
  66. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +86 -11
  67. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +348 -0
  68. package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
  69. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
  70. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
  71. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
  72. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +40 -1143
  73. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +732 -0
  74. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
  75. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +297 -2123
  76. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +130 -1002
  77. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +227 -0
  78. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
  79. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +436 -0
  80. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
  81. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
  82. package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
  83. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
  84. package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
  85. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
  86. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
  87. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
  88. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
  89. package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
  90. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +14 -2
  91. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
  92. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -3
  93. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +182 -0
  94. package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
  95. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
  96. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
  97. package/src/runtime/agent/orchestrator/session/loop.mjs +251 -397
  98. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
  99. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +7 -4
  100. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +12 -0
  101. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
  102. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
  103. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
  104. package/src/runtime/agent/orchestrator/session/manager.mjs +166 -1087
  105. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
  106. package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
  107. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
  108. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
  109. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +32 -41
  110. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
  111. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
  112. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
  113. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
  114. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -92
  115. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
  116. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
  117. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +28 -265
  118. package/src/runtime/agent/orchestrator/tools/builtin.mjs +0 -6
  119. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +57 -3
  120. package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
  121. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +10 -122
  122. package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
  123. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
  124. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
  125. package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
  126. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
  127. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
  128. package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
  129. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
  130. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
  131. package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
  132. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
  133. package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
  134. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +0 -21
  135. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +9 -72
  136. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
  137. package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
  138. package/src/runtime/channels/backends/discord-access.mjs +32 -0
  139. package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
  140. package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
  141. package/src/runtime/channels/backends/discord.mjs +12 -292
  142. package/src/runtime/channels/index.mjs +229 -663
  143. package/src/runtime/channels/lib/backend-dispatch.mjs +44 -0
  144. package/src/runtime/channels/lib/event-pipeline.mjs +18 -1
  145. package/src/runtime/channels/lib/event-queue.mjs +63 -4
  146. package/src/runtime/channels/lib/inbound-routing.mjs +111 -0
  147. package/src/runtime/channels/lib/output-forwarder.mjs +1 -1
  148. package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
  149. package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
  150. package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
  151. package/src/runtime/channels/lib/session-discovery.mjs +56 -4
  152. package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
  153. package/src/runtime/channels/lib/tool-format.mjs +1 -1
  154. package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
  155. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
  156. package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
  157. package/src/runtime/channels/lib/webhook/deliveries.mjs +312 -0
  158. package/src/runtime/channels/lib/webhook/log.mjs +42 -0
  159. package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
  160. package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
  161. package/src/runtime/channels/lib/webhook.mjs +36 -570
  162. package/src/runtime/channels/tool-defs.mjs +11 -130
  163. package/src/runtime/memory/index.mjs +201 -1948
  164. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
  165. package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
  166. package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
  167. package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
  168. package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
  169. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
  170. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
  171. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
  172. package/src/runtime/memory/lib/memory-cycle2.mjs +24 -842
  173. package/src/runtime/memory/lib/memory-embed.mjs +149 -0
  174. package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
  175. package/src/runtime/memory/lib/memory-recall-store.mjs +22 -2
  176. package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
  177. package/src/runtime/memory/lib/query-handlers.mjs +780 -0
  178. package/src/runtime/memory/lib/recall-format.mjs +55 -0
  179. package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
  180. package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
  181. package/src/runtime/memory/tool-defs.mjs +5 -13
  182. package/src/runtime/search/lib/http-fetch.mjs +274 -0
  183. package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
  184. package/src/runtime/search/lib/web-tools.mjs +24 -602
  185. package/src/runtime/shared/atomic-file.mjs +26 -1
  186. package/src/runtime/shared/launcher-control.mjs +2 -2
  187. package/src/runtime/shared/tool-primitives.mjs +308 -0
  188. package/src/runtime/shared/tool-result-summary.mjs +515 -0
  189. package/src/runtime/shared/tool-surface.mjs +80 -898
  190. package/src/runtime/shared/transcript-writer.mjs +23 -0
  191. package/src/runtime/shared/update-checker.mjs +7 -4
  192. package/src/session-runtime/config-helpers.mjs +84 -2
  193. package/src/session-runtime/config-lifecycle.mjs +232 -0
  194. package/src/session-runtime/cwd-plugins.mjs +226 -0
  195. package/src/session-runtime/mcp-glue.mjs +177 -0
  196. package/src/session-runtime/model-recency.mjs +111 -0
  197. package/src/session-runtime/native-search.mjs +247 -0
  198. package/src/session-runtime/output-styles.mjs +11 -9
  199. package/src/session-runtime/prewarm.mjs +142 -0
  200. package/src/session-runtime/provider-models.mjs +278 -0
  201. package/src/session-runtime/provider-usage.mjs +120 -0
  202. package/src/session-runtime/quick-model-rows.mjs +170 -0
  203. package/src/session-runtime/quick-search-models.mjs +46 -0
  204. package/src/session-runtime/session-hooks.mjs +93 -0
  205. package/src/session-runtime/settings-api.mjs +319 -0
  206. package/src/session-runtime/tool-catalog.mjs +29 -29
  207. package/src/session-runtime/tool-defs.mjs +84 -0
  208. package/src/session-runtime/warmup-schedulers.mjs +201 -0
  209. package/src/standalone/agent-tool/helpers.mjs +237 -0
  210. package/src/standalone/agent-tool/notify.mjs +107 -0
  211. package/src/standalone/agent-tool/provider-init.mjs +143 -0
  212. package/src/standalone/agent-tool/render.mjs +152 -0
  213. package/src/standalone/agent-tool/tool-def.mjs +55 -0
  214. package/src/standalone/agent-tool.mjs +110 -671
  215. package/src/standalone/channel-worker.mjs +4 -7
  216. package/src/standalone/explore-tool.mjs +30 -9
  217. package/src/standalone/hook-bus/config.mjs +207 -0
  218. package/src/standalone/hook-bus/constants.mjs +90 -0
  219. package/src/standalone/hook-bus/handlers.mjs +481 -0
  220. package/src/standalone/hook-bus/payload.mjs +31 -0
  221. package/src/standalone/hook-bus/rules.mjs +77 -0
  222. package/src/standalone/hook-bus.mjs +77 -870
  223. package/src/standalone/memory-runtime-proxy.mjs +7 -0
  224. package/src/standalone/opencode-go-login.mjs +5 -1
  225. package/src/standalone/provider-admin.mjs +1 -16
  226. package/src/standalone/usage-dashboard.mjs +3 -1
  227. package/src/tui/App.jsx +945 -8094
  228. package/src/tui/app/app-format.mjs +206 -0
  229. package/src/tui/app/channel-pickers.mjs +510 -0
  230. package/src/tui/app/clipboard.mjs +67 -0
  231. package/src/tui/app/core-memory-picker.mjs +210 -0
  232. package/src/tui/app/extension-pickers.mjs +506 -0
  233. package/src/tui/app/input-parsers.mjs +193 -0
  234. package/src/tui/app/maintenance-pickers.mjs +324 -0
  235. package/src/tui/app/model-options.mjs +330 -0
  236. package/src/tui/app/model-picker.mjs +365 -0
  237. package/src/tui/app/onboarding-steps.mjs +400 -0
  238. package/src/tui/app/project-picker.mjs +247 -0
  239. package/src/tui/app/provider-setup-picker.mjs +580 -0
  240. package/src/tui/app/resume-picker.mjs +55 -0
  241. package/src/tui/app/route-pickers.mjs +419 -0
  242. package/src/tui/app/settings-picker.mjs +490 -0
  243. package/src/tui/app/slash-commands.mjs +101 -0
  244. package/src/tui/app/slash-dispatch.mjs +427 -0
  245. package/src/tui/app/text-layout.mjs +46 -0
  246. package/src/tui/app/theme-effort-pickers.mjs +154 -0
  247. package/src/tui/app/transcript-window.mjs +671 -0
  248. package/src/tui/app/use-mouse-input.mjs +460 -0
  249. package/src/tui/app/use-prompt-handlers.mjs +310 -0
  250. package/src/tui/app/use-transcript-scroll.mjs +510 -0
  251. package/src/tui/app/use-transcript-window.mjs +589 -0
  252. package/src/tui/components/ConfirmBar.jsx +1 -1
  253. package/src/tui/components/Picker.jsx +32 -4
  254. package/src/tui/components/PromptInput.jsx +23 -101
  255. package/src/tui/components/SlashCommandPalette.jsx +8 -1
  256. package/src/tui/components/StatusLine.jsx +63 -12
  257. package/src/tui/components/TextEntryPanel.jsx +11 -0
  258. package/src/tui/components/ToolExecution.jsx +52 -594
  259. package/src/tui/components/TranscriptItem.jsx +105 -0
  260. package/src/tui/components/UsagePanel.jsx +18 -4
  261. package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
  262. package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
  263. package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
  264. package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
  265. package/src/tui/components/tool-execution/text-format.mjs +161 -0
  266. package/src/tui/display-width.mjs +20 -3
  267. package/src/tui/dist/index.mjs +19652 -18630
  268. package/src/tui/engine/agent-job-feed.mjs +133 -0
  269. package/src/tui/engine/notification-plan.mjs +76 -0
  270. package/src/tui/engine/render-timing.mjs +17 -0
  271. package/src/tui/engine/tool-approval.mjs +94 -0
  272. package/src/tui/engine/tool-card-results.mjs +234 -0
  273. package/src/tui/engine/tool-result-status.mjs +135 -0
  274. package/src/tui/engine.mjs +122 -562
  275. package/src/tui/figures.mjs +5 -0
  276. package/src/tui/index.jsx +105 -0
  277. package/src/tui/input-editing.mjs +2 -2
  278. package/src/tui/markdown/format-token.mjs +4 -1
  279. package/src/tui/statusline-ansi-bridge.mjs +11 -3
  280. package/src/tui/theme.mjs +6 -0
  281. package/src/ui/statusline-agents.mjs +213 -0
  282. package/src/ui/statusline-format.mjs +146 -0
  283. package/src/ui/statusline-segments.mjs +148 -0
  284. package/src/ui/statusline.mjs +67 -501
  285. package/src/ui/tool-card.mjs +0 -1
  286. package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
  287. package/src/workflows/default/WORKFLOW.md +1 -1
  288. package/src/workflows/sequential/WORKFLOW.md +1 -1
  289. package/vendor/ink/build/display-width.js +19 -3
  290. package/vendor/ink/build/ink.js +103 -6
  291. package/vendor/ink/build/log-update.js +17 -3
  292. package/vendor/ink/build/wrap-text.js +125 -0
  293. package/scripts/_test-folder-dialog.mjs +0 -30
  294. package/scripts/fix-brief-fn.mjs +0 -35
  295. package/scripts/fix-format-tool-surface.mjs +0 -24
  296. package/scripts/fix-tool-exec-visible.mjs +0 -42
  297. package/scripts/patch-agent-brief.mjs +0 -48
  298. package/scripts/patch-app.mjs +0 -21
  299. package/scripts/patch-app2.mjs +0 -18
  300. package/scripts/patch-dist-brief.mjs +0 -96
  301. package/scripts/patch-tool-exec.mjs +0 -70
  302. package/src/examples/schedules/SCHEDULE.example.md +0 -32
  303. package/src/examples/webhooks/WEBHOOK.example.md +0 -40
  304. package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
  305. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
  306. package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
  307. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.test.mjs +0 -162
  308. package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
  309. package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
  310. package/src/runtime/shared/task-notification-envelope.test.mjs +0 -107
  311. package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
  312. package/src/standalone/agent-task-status.test.mjs +0 -76
  313. package/src/tui/components/tool-output-format.test.mjs +0 -399
  314. package/src/tui/display-width.test.mjs +0 -35
  315. package/src/tui/engine-runtime-notification.test.mjs +0 -115
  316. package/src/tui/engine-tool-result-text.test.mjs +0 -75
  317. package/src/tui/input-editing.selection.test.mjs +0 -75
  318. package/src/tui/markdown/format-token.test.mjs +0 -354
  319. package/src/tui/markdown/render-ansi.test.mjs +0 -108
  320. package/src/tui/markdown/stream-fence.test.mjs +0 -26
  321. package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
  322. package/src/tui/paste-fix.test.mjs +0 -119
  323. package/src/tui/prompt-history-store.test.mjs +0 -52
  324. package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
  325. package/src/tui/transcript-tool-failures.test.mjs +0 -111
  326. package/src/ui/markdown.test.mjs +0 -70
  327. package/src/ui/statusline-context-label.test.mjs +0 -15
  328. package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
  329. package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
@@ -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
+ };