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,359 @@
1
+ // V4A + unified-as-V4A patch parsers and format-detection helpers. Moved
2
+ // verbatim from patch.mjs; parsing behavior (V4A/unified) is unchanged.
3
+
4
+ import { stripDiffPrefix } from './paths.mjs';
5
+ import {
6
+ DEV_NULL,
7
+ V4A_EOF_MARKER,
8
+ V4A_MOVE_TO_PREFIX,
9
+ UNIFIED_HUNK_HEADER_RE,
10
+ UNIFIED_HUNK_HEADER_CAPTURE_RE,
11
+ } from './constants.mjs';
12
+
13
+ // Strip BOM + normalize CRLF→LF only. Idempotent and structural — no
14
+ // hunk metadata is rewritten.
15
+ export function prepareInput(patchStr) {
16
+ return String(patchStr).replace(/^\uFEFF/, '').replace(/\r\n/g, '\n');
17
+ }
18
+
19
+ export function isApplyPatchEnvelope(patchStr) {
20
+ const text = prepareInput(patchStr).trimStart();
21
+ return text.startsWith('*** Begin Patch')
22
+ || text.startsWith('*** Add File:')
23
+ || text.startsWith('*** Update File:')
24
+ || text.startsWith('*** Delete File:');
25
+ }
26
+
27
+ export function isV4APatchInput(patchStr, format) {
28
+ return String(format || '').toLowerCase() === 'v4a'
29
+ || isApplyPatchEnvelope(patchStr);
30
+ }
31
+
32
+ export function hasUnifiedBareV4AHunk(patchStr) {
33
+ const text = prepareInput(patchStr);
34
+ if (!/^--- /m.test(text) || !/^\+\+\+ /m.test(text)) return false;
35
+ return text.split('\n').some((line) => line.startsWith('@@') && !UNIFIED_HUNK_HEADER_RE.test(line));
36
+ }
37
+
38
+ export function isUnifiedHunkCountError(err) {
39
+ const message = String(err?.message || err || '');
40
+ return /Hunk at line .*more lines than expected|Hunk at line .*less lines than expected|expected \d+ old lines|line count did not match/i.test(message);
41
+ }
42
+
43
+ export function canFallbackCountedUnified(patchStr, requestedFormat, err) {
44
+ if (requestedFormat === 'unified') return false;
45
+ if (isV4APatchInput(patchStr, requestedFormat)) return false;
46
+ const text = prepareInput(patchStr);
47
+ return /^--- /m.test(text)
48
+ && /^\+\+\+ /m.test(text)
49
+ && UNIFIED_HUNK_HEADER_RE.test(text.split('\n').find((line) => line.startsWith('@@')) || '')
50
+ && isUnifiedHunkCountError(err);
51
+ }
52
+
53
+ function stripPatchPathMetadata(rawPath) {
54
+ let text = String(rawPath || '').trim();
55
+ if (!text) return '';
56
+ const tabIdx = text.indexOf('\t');
57
+ if (tabIdx !== -1) text = text.slice(0, tabIdx).trimEnd();
58
+ const quote = text[0];
59
+ if ((quote === '"' || quote === "'") && text.length > 1) {
60
+ const end = text.indexOf(quote, 1);
61
+ if (end > 0) text = text.slice(1, end);
62
+ }
63
+ return text;
64
+ }
65
+
66
+ function stripV4APathHeader(line, prefix) {
67
+ return stripPatchPathMetadata(String(line || '').slice(prefix.length));
68
+ }
69
+
70
+ export function normaliseV4APath(rawPath) {
71
+ const p = stripPatchPathMetadata(rawPath);
72
+ if (!p) return '';
73
+ return p.replace(/^["']|["']$/g, '').replace(/\\/g, '/');
74
+ }
75
+
76
+ function normaliseV4AAnchor(rawAnchor) {
77
+ return String(rawAnchor || '').replace(/\s*@@\s*$/, '').trim();
78
+ }
79
+
80
+ function stripV4AMovePathHeader(line) {
81
+ return normaliseV4APath(String(line || '').slice(V4A_MOVE_TO_PREFIX.length));
82
+ }
83
+
84
+ export function isV4AEndOfFileMarker(rawLine) {
85
+ return String(rawLine || '').trim() === V4A_EOF_MARKER;
86
+ }
87
+
88
+ function v4aEnsureUpdateHunk(current, pendingAnchors) {
89
+ return { anchors: pendingAnchors.slice(), lines: [] };
90
+ }
91
+
92
+ function v4aPushBlankContextLine(currentHunk, pendingAnchors) {
93
+ if (!currentHunk) currentHunk = v4aEnsureUpdateHunk(null, pendingAnchors);
94
+ currentHunk.lines.push(' ');
95
+ return currentHunk;
96
+ }
97
+
98
+ function v4aMarkHunkEndOfFile(currentHunk, finishHunk) {
99
+ if (!currentHunk || currentHunk.lines.length === 0) {
100
+ throw new Error('V4A update hunk does not contain any lines before *** End of File');
101
+ }
102
+ currentHunk.isEndOfFile = true;
103
+ finishHunk();
104
+ }
105
+
106
+ // Split a patch string into lines, dropping the single trailing empty element
107
+ // produced by the patch's terminal newline. Invariant: a well-formed patch
108
+ // ends with "\n", so `"...\n".split("\n")` always yields a spurious final ""
109
+ // that is a line *terminator*, not a content line. Absorbing it as a blank
110
+ // context line corrupts the last hunk (phantom trailing "" in oldLines) and
111
+ // breaks anchoring whenever the matched source region is not followed by a
112
+ // blank line. A genuine trailing blank context line survives as the
113
+ // second-to-last element, so only the terminator artifact is removed.
114
+ function splitPatchLines(patchStr) {
115
+ const lines = prepareInput(patchStr).split('\n');
116
+ if (lines.length > 0 && lines[lines.length - 1] === '') lines.pop();
117
+ return lines;
118
+ }
119
+
120
+ // Guard against the compacted-history placeholder text leaking back in as
121
+ // literal patch input (models sometimes paste tool-output summaries back as
122
+ // new tool args). Exported so callers (e.g. apply_patch entry) can check
123
+ // this before any format detection / V4A-vs-unified dispatch, so ANY
124
+ // compacted body gets the corrective message regardless of format.
125
+ export const COMPACTED_PLACEHOLDER_RE = /^\s*\[mixdog compacted \w+:/;
126
+
127
+ // Mid-body scan uses the FULL placeholder shape ("<N> chars, sha…") rather
128
+ // than the loose prefix above: V4A tolerates unprefixed context lines, so a
129
+ // loose prefix match on any non-diff line could false-positive a legit edit
130
+ // whose content mentions the placeholder text. The full shape only occurs in
131
+ // actual compacted output leaked back as patch input.
132
+ const COMPACTED_PLACEHOLDER_LINE_RE = /^\s*\[mixdog compacted \w+: \d+ chars, sha\d*:/;
133
+
134
+ export function isCompactedPlaceholderPatch(patchStr) {
135
+ const str = String(patchStr ?? '');
136
+ if (COMPACTED_PLACEHOLDER_RE.test(str)) return true;
137
+ // Whole-patch prefix check above only catches the placeholder as the very
138
+ // first line. Models sometimes paste the placeholder mid-body (e.g. after
139
+ // a "*** Begin Patch" header or between hunks) as a standalone raw line.
140
+ // Scan for that shape too, but only on lines that are NOT diff content
141
+ // (unified +/-/space-prefixed lines), so a legit edit to a file whose
142
+ // real content happens to contain this literal text still parses normally.
143
+ for (const line of str.split('\n')) {
144
+ if (line.startsWith('+') || line.startsWith('-') || line.startsWith(' ')) continue;
145
+ if (COMPACTED_PLACEHOLDER_LINE_RE.test(line)) return true;
146
+ }
147
+ return false;
148
+ }
149
+
150
+ export function parseV4APatch(patchStr) {
151
+ const lines = splitPatchLines(patchStr);
152
+ const files = [];
153
+ let current = null;
154
+ let pendingAnchors = [];
155
+ let currentHunk = null;
156
+
157
+ const finishHunk = () => {
158
+ if (!current || !currentHunk) return;
159
+ if (currentHunk.lines.length > 0) current.hunks.push(currentHunk);
160
+ currentHunk = null;
161
+ };
162
+ const finishFile = () => {
163
+ finishHunk();
164
+ current = null;
165
+ pendingAnchors = [];
166
+ };
167
+ const startFile = (kind, path) => {
168
+ finishFile();
169
+ current = { kind, path: normaliseV4APath(path), hunks: [], lines: [], movePath: null };
170
+ files.push(current);
171
+ };
172
+
173
+ for (const rawLine of lines) {
174
+ if (rawLine === '*** Begin Patch' || rawLine === '*** End Patch') continue;
175
+ if (rawLine.startsWith('*** Update File:')) {
176
+ startFile('update', stripV4APathHeader(rawLine, '*** Update File:'));
177
+ continue;
178
+ }
179
+ if (rawLine.startsWith('*** Add File:')) {
180
+ startFile('add', stripV4APathHeader(rawLine, '*** Add File:'));
181
+ continue;
182
+ }
183
+ if (rawLine.startsWith('*** Delete File:')) {
184
+ startFile('delete', stripV4APathHeader(rawLine, '*** Delete File:'));
185
+ continue;
186
+ }
187
+ if (!current) {
188
+ throw new Error(`V4A patch line appears before a file header: ${rawLine}`);
189
+ }
190
+ if (current.kind === 'update' && rawLine.startsWith(V4A_MOVE_TO_PREFIX)) {
191
+ if (current.movePath) {
192
+ throw new Error(`V4A patch lists multiple ${V4A_MOVE_TO_PREFIX} directives for ${current.path}`);
193
+ }
194
+ const dest = stripV4AMovePathHeader(rawLine);
195
+ if (!dest) throw new Error('V4A patch contains an empty move destination path');
196
+ current.movePath = dest;
197
+ continue;
198
+ }
199
+ if (current.kind === 'add') {
200
+ current.lines.push(rawLine.startsWith('+') ? rawLine.slice(1) : rawLine);
201
+ continue;
202
+ }
203
+ if (current.kind === 'delete') {
204
+ continue;
205
+ }
206
+ if (rawLine === '') {
207
+ if (currentHunk) currentHunk = v4aPushBlankContextLine(currentHunk, pendingAnchors);
208
+ continue;
209
+ }
210
+ if (isV4AEndOfFileMarker(rawLine)) {
211
+ v4aMarkHunkEndOfFile(currentHunk, finishHunk);
212
+ currentHunk = null;
213
+ continue;
214
+ }
215
+ if (rawLine.startsWith('@@')) {
216
+ const anchor = normaliseV4AAnchor(rawLine.slice(2));
217
+ if (currentHunk && currentHunk.lines.length > 0) finishHunk();
218
+ pendingAnchors.push(anchor);
219
+ currentHunk = { anchors: pendingAnchors.slice(), lines: [] };
220
+ pendingAnchors = [];
221
+ continue;
222
+ }
223
+ const tag = rawLine[0];
224
+ if (tag !== ' ' && tag !== '-' && tag !== '+') {
225
+ if (!currentHunk) currentHunk = v4aEnsureUpdateHunk(current, pendingAnchors);
226
+ pendingAnchors = [];
227
+ currentHunk.lines.push(` ${rawLine}`);
228
+ continue;
229
+ }
230
+ if (!currentHunk) currentHunk = v4aEnsureUpdateHunk(current, pendingAnchors);
231
+ currentHunk.lines.push(rawLine);
232
+ }
233
+ finishFile();
234
+ const bad = files.find((file) => !file.path);
235
+ if (bad) throw new Error('V4A patch contains an empty file path');
236
+ if (files.length === 0) throw new Error('V4A patch contained no file sections');
237
+ return files;
238
+ }
239
+
240
+ function stripUnifiedV4APathHeader(line, prefix) {
241
+ return stripDiffPrefix(normaliseV4APath(String(line || '').slice(prefix.length)));
242
+ }
243
+
244
+ // Shared parser for unified-input -> V4A sections. The bare and counted
245
+ // fallbacks are byte-identical except for (a) the error label and (b) how an
246
+ // `@@` line yields its anchor: bare rejects counted headers and takes the raw
247
+ // tail; counted requires a counted header and takes its capture group. The
248
+ // difference is injected as `resolveAnchor`; everything else is shared.
249
+ function parseUnifiedAsV4APatch(patchStr, { label, resolveAnchor }) {
250
+ const lines = splitPatchLines(patchStr);
251
+ const files = [];
252
+ let current = null;
253
+ let pendingAnchors = [];
254
+ let currentHunk = null;
255
+
256
+ const finishHunk = () => {
257
+ if (!current || !currentHunk) return;
258
+ if (current.kind === 'update' && currentHunk.lines.length > 0) current.hunks.push(currentHunk);
259
+ currentHunk = null;
260
+ };
261
+ const finishFile = () => {
262
+ finishHunk();
263
+ current = null;
264
+ pendingAnchors = [];
265
+ };
266
+ const startFile = (oldPath, newPath) => {
267
+ finishFile();
268
+ const oldIsNull = DEV_NULL.test(oldPath || '');
269
+ const newIsNull = DEV_NULL.test(newPath || '');
270
+ const kind = oldIsNull ? 'add' : (newIsNull ? 'delete' : 'update');
271
+ const path = kind === 'add' ? newPath : oldPath;
272
+ current = { kind, path: normaliseV4APath(path), hunks: [], lines: [] };
273
+ files.push(current);
274
+ };
275
+
276
+ for (let i = 0; i < lines.length; i++) {
277
+ const rawLine = lines[i];
278
+ if (rawLine.startsWith('diff --git ') || rawLine.startsWith('index ') || rawLine.startsWith('new file mode ') || rawLine.startsWith('deleted file mode ')) {
279
+ continue;
280
+ }
281
+ if (rawLine.startsWith('--- ')) {
282
+ const next = lines[i + 1] || '';
283
+ if (next.startsWith('+++ ')) {
284
+ startFile(stripUnifiedV4APathHeader(rawLine, '--- '), stripUnifiedV4APathHeader(next, '+++ '));
285
+ i++;
286
+ continue;
287
+ }
288
+ // A real unified file header `--- X` is ALWAYS immediately followed by a
289
+ // `+++ Y` line. Without the pair, outside a file this is a malformed
290
+ // patch (keep the diagnostic); INSIDE a file it is a hunk-body deletion
291
+ // line whose content starts with `-- ` (rawLine `--- foo`) — fall through
292
+ // to body handling instead of misreading it as a file header.
293
+ if (!current) throw new Error(`${label} missing +++ header after: ${rawLine}`);
294
+ }
295
+ if (!current) continue;
296
+ if (rawLine === '') {
297
+ if (current.kind !== 'update') continue;
298
+ if (currentHunk) currentHunk = v4aPushBlankContextLine(currentHunk, pendingAnchors);
299
+ continue;
300
+ }
301
+ if (current.kind === 'update' && isV4AEndOfFileMarker(rawLine)) {
302
+ v4aMarkHunkEndOfFile(currentHunk, finishHunk);
303
+ currentHunk = null;
304
+ continue;
305
+ }
306
+ if (rawLine.startsWith('@@')) {
307
+ const anchor = resolveAnchor(rawLine);
308
+ if (currentHunk && currentHunk.lines.length > 0) finishHunk();
309
+ pendingAnchors.push(anchor);
310
+ currentHunk = { anchors: pendingAnchors.slice(), lines: [] };
311
+ pendingAnchors = [];
312
+ continue;
313
+ }
314
+ if (current.kind === 'add') {
315
+ if (rawLine[0] === '+') current.lines.push(rawLine.slice(1));
316
+ continue;
317
+ }
318
+ if (current.kind === 'delete') {
319
+ continue;
320
+ }
321
+ const tag = rawLine[0];
322
+ if (tag !== ' ' && tag !== '-' && tag !== '+') {
323
+ if (!currentHunk) currentHunk = v4aEnsureUpdateHunk(current, pendingAnchors);
324
+ pendingAnchors = [];
325
+ currentHunk.lines.push(` ${rawLine}`);
326
+ continue;
327
+ }
328
+ if (!currentHunk) currentHunk = v4aEnsureUpdateHunk(current, pendingAnchors);
329
+ currentHunk.lines.push(rawLine);
330
+ }
331
+ finishFile();
332
+ const bad = files.find((file) => !file.path);
333
+ if (bad) throw new Error(`${label} contains an empty file path`);
334
+ if (files.length === 0) throw new Error(`${label} contained no file sections`);
335
+ return files;
336
+ }
337
+
338
+ export function parseUnifiedBareV4APatch(patchStr) {
339
+ return parseUnifiedAsV4APatch(patchStr, {
340
+ label: 'unified bare patch',
341
+ resolveAnchor: (rawLine) => {
342
+ if (UNIFIED_HUNK_HEADER_RE.test(rawLine)) {
343
+ throw new Error('unified bare patch cannot mix counted unified hunks with bare @@ anchors');
344
+ }
345
+ return normaliseV4AAnchor(rawLine.slice(2));
346
+ },
347
+ });
348
+ }
349
+
350
+ export function parseUnifiedCountedAsV4APatch(patchStr) {
351
+ return parseUnifiedAsV4APatch(patchStr, {
352
+ label: 'unified fallback',
353
+ resolveAnchor: (rawLine) => {
354
+ const match = UNIFIED_HUNK_HEADER_CAPTURE_RE.exec(rawLine);
355
+ if (!match) throw new Error(`unified fallback requires counted hunk header: ${rawLine}`);
356
+ return normaliseV4AAnchor(match[1] || '');
357
+ },
358
+ });
359
+ }