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,326 @@
1
+ // Text/token/message helpers and secret redaction for compaction. Extracted
2
+ // verbatim from compact.mjs (behavior-preserving).
3
+ import { createHash } from 'node:crypto';
4
+ import { estimateMessagesTokens } from '../context-utils.mjs';
5
+
6
+ const TOOL_ARG_STRING_MAX_CHARS = 360;
7
+ const TOOL_ARG_ARRAY_MAX_ITEMS = 8;
8
+ const TOOL_ARG_MAX_DEPTH = 4;
9
+ export const TOOL_CALL_ARGS_MAX_CHARS = 260;
10
+ export const TOOL_CALL_FACT_ARGS_MAX_CHARS = 140;
11
+ export const TOOL_CALLS_MAX = 4;
12
+ const SENSITIVE_TOOL_ARG_KEY_RE = /(?:^|[_-])(?:api[_-]?key|authorization|auth|cookie|credential|passwd|password|refresh[_-]?token|secret|token)(?:$|[_-])/i;
13
+ // Word alternation for raw-string (non-JSON) secret redaction. Mirrors the
14
+ // keys in SENSITIVE_TOOL_ARG_KEY_RE and the session-ingest redactor so a raw
15
+ // tool-call argument string like `authorization: Bearer abc.def` or
16
+ // `password="abc def"` never reaches preserved facts or the compaction prompt.
17
+ const SENSITIVE_TOOL_ARG_KEY_WORD = '(?:api[_-]?key|authorization|auth|cookie|credential|passwd|password|refresh[_-]?token|secret|token)';
18
+ // Full key matcher: the sensitive WORD may carry a prefix and/or suffix segment
19
+ // joined by `_`/`-` so prefixed variants like `access_token`, `access-token`,
20
+ // `x-api-key`, and `bearer_token` are matched as whole keys (not just the bare
21
+ // word at key start). Prefix/suffix are bounded by a `_`/`-` separator so the
22
+ // word stays at an identifier boundary.
23
+ const SENSITIVE_TOOL_ARG_KEY_FULL = `(?:[A-Za-z0-9_-]*[_-])?${SENSITIVE_TOOL_ARG_KEY_WORD}(?:[_-][A-Za-z0-9_-]*)?`;
24
+ // camelCase variants (case-SENSITIVE, deliberately not /i): a capitalized
25
+ // sensitive word CLOSING the key — `accessToken`, `authToken`, `bearerToken`,
26
+ // `sessionSecret`, `myPassword`. Bounded so plural/compound counters
27
+ // (`tokens`, `maxOutputTokens`, `budgetTokens`) do NOT match.
28
+ const SENSITIVE_TOOL_ARG_KEY_CAMEL_WORD = '(?:Api[_-]?Key|Authorization|Auth|Cookie|Credential|Passwd|Password|Refresh[_-]?Token|Secret|Token)';
29
+ const SENSITIVE_TOOL_ARG_KEY_CAMEL_RE = new RegExp(`[a-z0-9]${SENSITIVE_TOOL_ARG_KEY_CAMEL_WORD}s?$`);
30
+ function isSensitiveToolArgKey(key) {
31
+ const k = String(key || '');
32
+ return SENSITIVE_TOOL_ARG_KEY_RE.test(k) || SENSITIVE_TOOL_ARG_KEY_CAMEL_RE.test(k);
33
+ }
34
+ const SENSITIVE_RAW_KEY_RES = [
35
+ new RegExp(`((?:^|[\\s,{(?&])["']?${SENSITIVE_TOOL_ARG_KEY_FULL}["']?\\s*[:=]\\s*)`, 'gi'),
36
+ // Case-sensitive camelCase raw keys (`accessToken=...`, `myAuthToken: ...`).
37
+ new RegExp(`((?:^|[\\s,{(?&])["']?[A-Za-z0-9_-]*[a-z0-9]${SENSITIVE_TOOL_ARG_KEY_CAMEL_WORD}["']?\\s*[:=]\\s*)`, 'g'),
38
+ ];
39
+
40
+ // Redact `key: value` / `key=value` secret pairs inside a raw (non-JSON)
41
+ // string. Consumes the WHOLE value after the key — spaces, `Bearer `/`Basic `
42
+ // scheme words, quoted values with internal spaces, and `;`-separated cookie
43
+ // pairs — so no secret fragment survives. Kept local to compact-core to avoid a
44
+ // cross-module dependency on the memory lib; logic matches session-ingest's
45
+ // redactRawArgString.
46
+ export function redactRawSecretString(text) {
47
+ let value = String(text ?? '');
48
+ if (!value) return value;
49
+ for (const keyRe of SENSITIVE_RAW_KEY_RES) {
50
+ keyRe.lastIndex = 0;
51
+ let out = '';
52
+ let last = 0;
53
+ let match;
54
+ while ((match = keyRe.exec(value)) !== null) {
55
+ const prefixEnd = match.index + match[0].length;
56
+ out += value.slice(last, prefixEnd);
57
+ let i = prefixEnd;
58
+ const quote = value[i] === '"' || value[i] === "'" ? value[i] : '';
59
+ if (quote) {
60
+ i += 1;
61
+ while (i < value.length && value[i] !== quote) i += 1;
62
+ if (i < value.length) i += 1; // include closing quote
63
+ } else {
64
+ // Header-style `key: value` may carry scheme words and spaces
65
+ // (`authorization: Bearer abc.def`) — consume the whole value so
66
+ // no fragment survives. KV-style `key=value` stops at whitespace
67
+ // so space-separated trailing keys (`token=abc fileName=x`) are
68
+ // preserved.
69
+ const headerStyle = /:\s*$/.test(match[0]);
70
+ const stopRe = headerStyle ? /[,)}\n]/ : /[,)}\s]/;
71
+ while (i < value.length && !stopRe.test(value[i])) i += 1;
72
+ }
73
+ out += '[redacted]';
74
+ last = i;
75
+ keyRe.lastIndex = i;
76
+ }
77
+ out += value.slice(last);
78
+ value = out;
79
+ }
80
+ return value;
81
+ }
82
+
83
+ export function sha16(value) {
84
+ const text = typeof value === 'string' ? value : JSON.stringify(value ?? null);
85
+ return createHash('sha256').update(text).digest('hex').slice(0, 16);
86
+ }
87
+
88
+ export function roleCounts(messages) {
89
+ const counts = new Map();
90
+ for (const m of messages) counts.set(m?.role || 'unknown', (counts.get(m?.role || 'unknown') || 0) + 1);
91
+ return [...counts.entries()].map(([role, count]) => `${role}:${count}`).join(', ');
92
+ }
93
+
94
+ export function extractText(m) {
95
+ if (!m || typeof m !== 'object') return '';
96
+ if (typeof m.content === 'string') return m.content;
97
+ if (Array.isArray(m.content)) {
98
+ return m.content
99
+ .map((item) => {
100
+ if (!item || typeof item !== 'object') return '';
101
+ if (typeof item.text === 'string') return item.text;
102
+ if (typeof item.content === 'string') return item.content;
103
+ return '';
104
+ })
105
+ .filter(Boolean)
106
+ .join('\n');
107
+ }
108
+ try { return JSON.stringify(m.content ?? ''); } catch { return ''; }
109
+ }
110
+
111
+ export function truncateMiddle(text, maxChars) {
112
+ const value = String(text ?? '').replace(/\r\n/g, '\n');
113
+ if (maxChars <= 0 || value.length === 0) return '';
114
+ if (value.length <= maxChars) return value;
115
+ if (maxChars <= 8) return value.slice(0, maxChars);
116
+ const head = Math.ceil((maxChars - 5) / 2);
117
+ const tail = Math.floor((maxChars - 5) / 2);
118
+ return `${value.slice(0, head)} … ${value.slice(value.length - tail)}`;
119
+ }
120
+
121
+ function normalizeToolArgValue(value, key = '', depth = 0) {
122
+ if (isSensitiveToolArgKey(key)) return '[redacted]';
123
+ if (typeof value === 'bigint') return String(value);
124
+ // Defense-in-depth: a non-sensitive KEY can still carry a secret embedded
125
+ // in its string VALUE (e.g. a freeform `headers` string). Redact raw
126
+ // key:value secret pairs before truncating.
127
+ if (typeof value === 'string') return truncateMiddle(redactRawSecretString(value), TOOL_ARG_STRING_MAX_CHARS);
128
+ if (!value || typeof value !== 'object') return value ?? null;
129
+ if (depth >= TOOL_ARG_MAX_DEPTH) return Array.isArray(value) ? `[array:${value.length}]` : '[object]';
130
+ if (Array.isArray(value)) {
131
+ const out = value.slice(0, TOOL_ARG_ARRAY_MAX_ITEMS)
132
+ .map((item, index) => normalizeToolArgValue(item, String(index), depth + 1));
133
+ if (value.length > TOOL_ARG_ARRAY_MAX_ITEMS) out.push(`+${value.length - TOOL_ARG_ARRAY_MAX_ITEMS} more`);
134
+ return out;
135
+ }
136
+ const out = {};
137
+ for (const k of Object.keys(value).sort()) {
138
+ out[k] = normalizeToolArgValue(value[k], k, depth + 1);
139
+ }
140
+ return out;
141
+ }
142
+
143
+ function stableToolArgJson(value) {
144
+ if (value == null) return '';
145
+ if (typeof value === 'string') {
146
+ const text = value.trim();
147
+ if (!text) return '';
148
+ if (/^[\[{]/.test(text)) {
149
+ try { return JSON.stringify(normalizeToolArgValue(JSON.parse(text))); } catch { /* keep raw */ }
150
+ }
151
+ // Non-JSON raw string: redact secret key:value pairs before truncating
152
+ // so toolCallSummary / preserved facts / compaction prompt metadata
153
+ // never leak `authorization: Bearer ...`, passwords, cookies, tokens.
154
+ return truncateMiddle(redactRawSecretString(text), TOOL_ARG_STRING_MAX_CHARS);
155
+ }
156
+ try {
157
+ return JSON.stringify(normalizeToolArgValue(value));
158
+ } catch {
159
+ return truncateMiddle(redactRawSecretString(String(value || '')), TOOL_ARG_STRING_MAX_CHARS);
160
+ }
161
+ }
162
+
163
+ function toolCallArgsText(tc, maxChars = TOOL_CALL_ARGS_MAX_CHARS) {
164
+ if (!(maxChars > 0)) return '';
165
+ const raw = tc?.arguments ?? tc?.function?.arguments;
166
+ const text = stableToolArgJson(raw);
167
+ return text ? truncateMiddle(text, maxChars) : '';
168
+ }
169
+
170
+ export function summarizeToolCall(tc, maxArgChars = TOOL_CALL_ARGS_MAX_CHARS) {
171
+ const name = tc?.name || tc?.function?.name || tc?.id || '?';
172
+ const args = toolCallArgsText(tc, maxArgChars);
173
+ return args ? `${name}(${args})` : name;
174
+ }
175
+
176
+ export function toolCallArgBudget(perMessageChars) {
177
+ const chars = Number(perMessageChars);
178
+ if (!Number.isFinite(chars) || chars <= 0) return 0;
179
+ return Math.min(TOOL_CALL_ARGS_MAX_CHARS, Math.max(32, Math.floor(chars * 0.5)));
180
+ }
181
+
182
+ export function toolCallSummary(m, maxArgChars = TOOL_CALL_ARGS_MAX_CHARS) {
183
+ if (!Array.isArray(m?.toolCalls) || m.toolCalls.length === 0) return '';
184
+ const calls = m.toolCalls
185
+ .slice(0, TOOL_CALLS_MAX)
186
+ .map(tc => summarizeToolCall(tc, maxArgChars));
187
+ if (m.toolCalls.length > TOOL_CALLS_MAX) calls.push(`+${m.toolCalls.length - TOOL_CALLS_MAX} more`);
188
+ return ` tool_calls=${calls.join(';')}`;
189
+ }
190
+
191
+ export function toolResultId(m) {
192
+ return m?.role === 'tool' && m.toolCallId ? ` tool_result=${m.toolCallId}` : '';
193
+ }
194
+
195
+ export function safeEstimateMessagesTokens(messages) {
196
+ try { return estimateMessagesTokens(messages); }
197
+ catch { return null; }
198
+ }
199
+
200
+ export function textByteLength(text) {
201
+ try { return Buffer.byteLength(String(text || ''), 'utf8'); }
202
+ catch { return String(text || '').length; }
203
+ }
204
+
205
+ export function messageContentHasMarker(m, marker) {
206
+ if (!m || !marker) return false;
207
+ if (typeof m.content === 'string') return m.content.includes(marker);
208
+ if (Array.isArray(m.content)) {
209
+ return m.content.some((part) => {
210
+ if (!part || typeof part !== 'object') return false;
211
+ return String(part.text || part.content || '').includes(marker);
212
+ });
213
+ }
214
+ return false;
215
+ }
216
+
217
+ // --- Verbatim redaction for messages kept through compaction ---------------
218
+
219
+ // Redaction-ONLY recursive walk for tool-call argument VALUES kept verbatim
220
+ // through compaction. Unlike normalizeToolArgValue (which is for prompt-side
221
+ // summaries and truncates/summarizes/key-sorts), this preserves shape exactly:
222
+ // - sensitive KEY -> '[redacted]'
223
+ // - string value -> redactRawSecretString(value) (no truncation/middle-cut)
224
+ // - array -> same length, items walked in order (no slicing/caps)
225
+ // - object -> same keys in INSERTION order (no sorting/depth caps)
226
+ // - other primitive (number/boolean/bigint/null) -> returned unchanged
227
+ // Returns { value, changed } so callers can preserve byte-exact input when the
228
+ // walk altered nothing. Only sensitive-key values and embedded raw secret pairs
229
+ // inside strings are altered; everything else is structure identical.
230
+ function redactToolArgValueOnly(value, key = '') {
231
+ if (isSensitiveToolArgKey(key)) {
232
+ return { value: '[redacted]', changed: value !== '[redacted]' };
233
+ }
234
+ if (value == null) return { value, changed: false };
235
+ if (typeof value === 'string') {
236
+ const redacted = redactRawSecretString(value);
237
+ return { value: redacted, changed: redacted !== value };
238
+ }
239
+ if (Array.isArray(value)) {
240
+ let changed = false;
241
+ const out = value.map((item) => {
242
+ const r = redactToolArgValueOnly(item, '');
243
+ if (r.changed) changed = true;
244
+ return r.value;
245
+ });
246
+ return { value: changed ? out : value, changed };
247
+ }
248
+ if (typeof value === 'object') {
249
+ let changed = false;
250
+ const out = {};
251
+ for (const k of Object.keys(value)) {
252
+ const r = redactToolArgValueOnly(value[k], k);
253
+ if (r.changed) changed = true;
254
+ out[k] = r.value;
255
+ }
256
+ return { value: changed ? out : value, changed };
257
+ }
258
+ return { value, changed: false };
259
+ }
260
+
261
+ // Redact sensitive values inside a single tool-call arguments payload while
262
+ // preserving its original shape (string stays a string, object stays an
263
+ // object) so the provider-valid tool_call structure is not broken. Used to
264
+ // scrub messages that survive compaction VERBATIM (preserved tail / mandatory
265
+ // context), where prompt-side redaction does not apply. Redaction-only — no
266
+ // truncation, summarization, key sorting, or depth/array caps.
267
+ function redactToolCallArgumentsValue(rawArgs) {
268
+ if (rawArgs == null) return rawArgs;
269
+ if (typeof rawArgs === 'string') {
270
+ const trimmed = rawArgs.trim();
271
+ if (/^[\[{]/.test(trimmed)) {
272
+ try {
273
+ // Parse, redaction-only walk; only reserialize when the walk
274
+ // actually changed a sensitive value. When nothing changed,
275
+ // return the ORIGINAL string byte-exact (no JSON re-formatting).
276
+ const { value, changed } = redactToolArgValueOnly(JSON.parse(trimmed));
277
+ return changed ? JSON.stringify(value) : rawArgs;
278
+ } catch { /* fall through to raw redaction */ }
279
+ }
280
+ return redactRawSecretString(rawArgs);
281
+ }
282
+ if (typeof rawArgs === 'object') {
283
+ try {
284
+ const { value, changed } = redactToolArgValueOnly(rawArgs);
285
+ return changed ? value : rawArgs;
286
+ } catch { return rawArgs; }
287
+ }
288
+ return rawArgs;
289
+ }
290
+
291
+ // Return a copy of a message with sensitive tool-call argument values redacted,
292
+ // keeping role / content / toolCallId / tool names+ids and non-sensitive args
293
+ // intact. Non-tool-bearing messages are returned unchanged (same reference).
294
+ function redactMessageToolCallSecrets(m) {
295
+ if (!m || typeof m !== 'object' || !Array.isArray(m.toolCalls) || m.toolCalls.length === 0) {
296
+ return m;
297
+ }
298
+ let changed = false;
299
+ const toolCalls = m.toolCalls.map((tc) => {
300
+ if (!tc || typeof tc !== 'object') return tc;
301
+ const out = { ...tc };
302
+ if ('arguments' in tc && tc.arguments != null) {
303
+ const redacted = redactToolCallArgumentsValue(tc.arguments);
304
+ if (redacted !== tc.arguments) { out.arguments = redacted; changed = true; }
305
+ }
306
+ if (tc.function && typeof tc.function === 'object' && tc.function.arguments != null) {
307
+ const redacted = redactToolCallArgumentsValue(tc.function.arguments);
308
+ if (redacted !== tc.function.arguments) {
309
+ out.function = { ...tc.function, arguments: redacted };
310
+ changed = true;
311
+ }
312
+ }
313
+ return out;
314
+ });
315
+ if (!changed) return m;
316
+ return { ...m, toolCalls };
317
+ }
318
+
319
+ // Scrub an array of messages that are kept verbatim through compaction so a
320
+ // recent assistant tool call carrying a secret (e.g. `authorization: Bearer
321
+ // ...`) cannot survive into the returned compacted transcript. Only assistant
322
+ // toolCalls argument VALUES are touched; structure/order/pairing is preserved.
323
+ export function redactToolCallSecretsInMessages(messages) {
324
+ if (!Array.isArray(messages)) return messages;
325
+ return messages.map((m) => redactMessageToolCallSecrets(m));
326
+ }