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,342 @@
1
+ // apply_patch top-level orchestration: UI-diff side-channel, input salvage,
2
+ // mutation-route planning, V4A conversion wiring, native dispatch, and the
3
+ // executePatchTool entry point + replay capture. Moved verbatim from
4
+ // patch.mjs; control flow and output are unchanged.
5
+
6
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
7
+ import { resolve as pathResolve, isAbsolute, join as pathJoin } from 'node:path';
8
+ import { parsePatch } from 'diff';
9
+ import { getAbortSignalForSession } from '../../session/abort-lookup.mjs';
10
+ import { withBuiltinPathLocks } from '../builtin.mjs';
11
+ import { withAdvisoryLocks } from '../builtin/advisory-lock.mjs';
12
+ import { wrapMutationRouteOutput } from '../mutation-planner.mjs';
13
+ import { getPluginData } from '../../config.mjs';
14
+ import { prepareInput, isV4APatchInput, hasUnifiedBareV4AHunk, canFallbackCountedUnified, parseV4APatch, isCompactedPlaceholderPatch } from './parsing.mjs';
15
+ import { resolveBasePath, resolveV4AEntryPath, mergeDuplicateParsedModifyEntries, renderParsedUnifiedPatch, rewriteHeaderPaths, preValidateNativeBatch } from './paths.mjs';
16
+ import { ensureNativePatchBinaryAvailable } from './native-server.mjs';
17
+ import { assertPathReachable } from '../builtin/fs-reachability.mjs';
18
+ import { dispatchNativePatch } from './dispatch.mjs';
19
+ import {
20
+ planV4ARenameSections,
21
+ applyV4ARenameSections,
22
+ formatV4ARenameSuccessLines,
23
+ convertV4ASectionsToUnifiedPatch,
24
+ convertUnifiedBareV4AToUnifiedPatch,
25
+ convertUnifiedCountedToUnifiedPatchViaV4A,
26
+ } from './v4a-convert.mjs';
27
+
28
+ function isPatchErrorText(text) {
29
+ return /^Error:/i.test(String(text ?? '').trimStart());
30
+ }
31
+
32
+ const APPLY_PATCH_UI_DIFF_MAX_CHARS = 64 * 1024;
33
+ const APPLY_PATCH_UI_DIFF_REGISTRY_MAX = 64;
34
+ const _applyPatchUiDiffByCallId = new Map();
35
+
36
+ function registerApplyPatchUiDiff(callId, diff) {
37
+ if (!callId || typeof diff !== 'string' || !diff.trim()) return;
38
+ let text = diff;
39
+ if (text.length > APPLY_PATCH_UI_DIFF_MAX_CHARS) {
40
+ text = `${text.slice(0, APPLY_PATCH_UI_DIFF_MAX_CHARS)}\n… [diff truncated for display]`;
41
+ }
42
+ if (_applyPatchUiDiffByCallId.size >= APPLY_PATCH_UI_DIFF_REGISTRY_MAX) {
43
+ const oldest = _applyPatchUiDiffByCallId.keys().next().value;
44
+ if (oldest !== undefined) _applyPatchUiDiffByCallId.delete(oldest);
45
+ }
46
+ _applyPatchUiDiffByCallId.set(callId, text);
47
+ }
48
+
49
+ export function takeApplyPatchUiDiff(callId) {
50
+ if (!callId) return null;
51
+ const value = _applyPatchUiDiffByCallId.get(callId) || null;
52
+ if (value != null) _applyPatchUiDiffByCallId.delete(callId);
53
+ return value;
54
+ }
55
+
56
+ function planApplyPatchMutationRoute(args, patchStr, requestedFormat) {
57
+ const v4aInput = isV4APatchInput(patchStr, requestedFormat)
58
+ || (requestedFormat !== 'unified' && hasUnifiedBareV4AHunk(patchStr));
59
+ return {
60
+ sourceTool: 'apply_patch',
61
+ engine: v4aInput ? 'v4a-patch' : 'unified-patch',
62
+ reason: 'direct',
63
+ };
64
+ }
65
+
66
+ function wrapPatchMutationOutput(text, plan, extras = {}) {
67
+ if (isPatchErrorText(text)) return text;
68
+ return wrapMutationRouteOutput(text, plan, extras);
69
+ }
70
+
71
+ const APPLY_PATCH_SCHEMA_KEYS = new Set(['patch', 'format', 'base_path', 'dry_run', 'reject_partial', 'fuzzy']);
72
+ function salvageShatteredV4APatchArgs(args) {
73
+ if (!args || typeof args !== 'object') return args;
74
+ const rawPatch = typeof args.patch === 'string' ? args.patch : '';
75
+ if (!rawPatch.startsWith('*** Begin Patch') || rawPatch.includes('\n') || rawPatch.includes('*** End Patch')) return args;
76
+ const stray = Object.keys(args).filter((k) => !APPLY_PATCH_SCHEMA_KEYS.has(k));
77
+ if (stray.length === 0) return args;
78
+ const lines = [rawPatch];
79
+ for (const key of Object.keys(args)) {
80
+ if (APPLY_PATCH_SCHEMA_KEYS.has(key)) continue;
81
+ lines.push(key);
82
+ lines.push(String(args[key] ?? ''));
83
+ }
84
+ while (lines.length && lines[lines.length - 1] === '') lines.pop();
85
+ const cleaned = {};
86
+ for (const key of Object.keys(args)) if (APPLY_PATCH_SCHEMA_KEYS.has(key)) cleaned[key] = args[key];
87
+ cleaned.patch = lines.join('\n');
88
+ return cleaned;
89
+ }
90
+
91
+ async function apply_patch(args, cwd, options = {}) {
92
+ args = salvageShatteredV4APatchArgs(args);
93
+ const patchStr = (typeof args?.patch === 'string' ? args.patch : '').replace(/^\uFEFF/, '');
94
+ if (!patchStr.trim()) {
95
+ throw new Error('apply_patch: "patch" is required (unified diff or V4A patch string)');
96
+ }
97
+ if (isCompactedPlaceholderPatch(patchStr)) {
98
+ throw new Error('patch body is a compacted-history placeholder ([mixdog compacted …]), not real patch content. Re-read the target file span and write a fresh patch; never resubmit compacted output as new tool input.');
99
+ }
100
+ const requestedFormat = String(args?.format || '').toLowerCase();
101
+ if (requestedFormat && requestedFormat !== 'unified' && requestedFormat !== 'v4a') {
102
+ throw new Error('apply_patch: "format" must be "unified" or "v4a"');
103
+ }
104
+ let mutationPlan = options?.mutationPlan || planApplyPatchMutationRoute(args, patchStr, requestedFormat);
105
+ const readStateScope = options?.readStateScope ?? options?.sessionId ?? null;
106
+ let abortSignal = options?.signal || options?.abortSignal || null;
107
+ if (!abortSignal && options?.sessionId) {
108
+ try { abortSignal = await getAbortSignalForSession(options.sessionId); } catch { abortSignal = null; }
109
+ }
110
+ if (abortSignal?.aborted) {
111
+ throw new Error(abortSignal.reason?.message || abortSignal.reason || 'apply_patch aborted');
112
+ }
113
+ const basePath = resolveBasePath(cwd, args?.base_path);
114
+ try {
115
+ await assertPathReachable(basePath);
116
+ } catch (err) {
117
+ return `Error: ${err?.message || String(err)}`;
118
+ }
119
+ const rejectPartial = args?.reject_partial !== false;
120
+ const dryRun = args?.dry_run === true;
121
+ const fuzzy = args?.fuzzy !== false;
122
+ const fuzz = fuzzy ? 2 : 0;
123
+
124
+ let inputPatchStr = patchStr;
125
+ const rejectedV4AHunks = [];
126
+ const v4aConvertOpts = { rejectPartial, rejectedHunks: rejectedV4AHunks, fuzzy, dryRun, readStateScope };
127
+ let v4aRenamePlan = null;
128
+ if (isV4APatchInput(patchStr, requestedFormat)) {
129
+ try {
130
+ const allSections = parseV4APatch(patchStr);
131
+ v4aRenamePlan = await planV4ARenameSections(allSections, basePath);
132
+ inputPatchStr = await convertV4ASectionsToUnifiedPatch(v4aRenamePlan.remainingSections, basePath, v4aConvertOpts);
133
+ if (v4aRenamePlan.renameSections.length > 0) {
134
+ mutationPlan = v4aRenamePlan.remainingSections.length > 0
135
+ ? { sourceTool: 'apply_patch', engine: 'v4a-patch', reason: 'v4a-mixed' }
136
+ : { sourceTool: 'apply_patch', engine: 'v4a-rename', reason: 'v4a-move' };
137
+ }
138
+ } catch (err) {
139
+ throw new Error(`apply_patch: V4A parse failed — ${err?.message || String(err)}`);
140
+ }
141
+ } else if (requestedFormat !== 'unified' && hasUnifiedBareV4AHunk(patchStr)) {
142
+ try {
143
+ inputPatchStr = await convertUnifiedBareV4AToUnifiedPatch(patchStr, basePath, v4aConvertOpts);
144
+ } catch (err) {
145
+ throw new Error(`apply_patch: bare @@ parse failed — ${err?.message || String(err)}`);
146
+ }
147
+ }
148
+ let normalizedPatchStr = prepareInput(inputPatchStr);
149
+ const v4aRenameOnly = v4aRenamePlan?.renameSections?.length > 0 && v4aRenamePlan.remainingSections.length === 0;
150
+
151
+ let parsed = [];
152
+ if (!v4aRenameOnly) try {
153
+ parsed = parsePatch(normalizedPatchStr);
154
+ } catch (err) {
155
+ if (!canFallbackCountedUnified(patchStr, requestedFormat, err)) {
156
+ throw new Error(`apply_patch: parse failed — ${err?.message || String(err)}; prefer V4A envelope for multi-hunk edits (no @@ line counts)`);
157
+ }
158
+ try {
159
+ inputPatchStr = await convertUnifiedCountedToUnifiedPatchViaV4A(patchStr, basePath, v4aConvertOpts);
160
+ normalizedPatchStr = prepareInput(inputPatchStr);
161
+ parsed = parsePatch(normalizedPatchStr);
162
+ mutationPlan = {
163
+ sourceTool: 'apply_patch',
164
+ engine: 'v4a-patch',
165
+ reason: 'unified-count-fallback',
166
+ };
167
+ } catch (fallbackErr) {
168
+ throw new Error(`apply_patch: parse failed — ${err?.message || String(err)}; V4A fallback failed — ${fallbackErr?.message || String(fallbackErr)}`);
169
+ }
170
+ }
171
+ if (!v4aRenameOnly && (!Array.isArray(parsed) || parsed.length === 0)) {
172
+ return 'Error: patch contained no file sections';
173
+ }
174
+ if (!v4aRenameOnly) {
175
+ const merged = mergeDuplicateParsedModifyEntries(parsed, basePath);
176
+ if (merged.changed) {
177
+ parsed = merged.parsed;
178
+ normalizedPatchStr = renderParsedUnifiedPatch(parsed);
179
+ }
180
+ }
181
+
182
+ if (!v4aRenameOnly) {
183
+ try {
184
+ await ensureNativePatchBinaryAvailable();
185
+ } catch (err) {
186
+ return `Error: ${err?.message || String(err)}`;
187
+ }
188
+ }
189
+ let entries = [];
190
+ let headerRewrites = [];
191
+ if (!v4aRenameOnly) {
192
+ try {
193
+ ({ entries, headerRewrites } = await preValidateNativeBatch(parsed, basePath));
194
+ } catch (err) {
195
+ return `Error: ${err?.message || String(err)}`;
196
+ }
197
+ }
198
+
199
+ const _lockPaths = [
200
+ ...entries.map((entry) => entry.fullPath),
201
+ ...(v4aRenamePlan?.renameSections || []).flatMap((section) => {
202
+ const src = resolveV4AEntryPath(basePath, section.path);
203
+ const dest = resolveV4AEntryPath(basePath, section.movePath);
204
+ return [src, dest];
205
+ }),
206
+ ];
207
+
208
+ return withBuiltinPathLocks(_lockPaths, () =>
209
+ withAdvisoryLocks(_lockPaths, async () => {
210
+ let v4aRenameResults = [];
211
+ if (v4aRenamePlan?.renameSections?.length) {
212
+ v4aRenameResults = await applyV4ARenameSections(v4aRenamePlan.renameSections, basePath, v4aConvertOpts);
213
+ }
214
+ if (v4aRenameOnly) {
215
+ const lines = formatV4ARenameSuccessLines(v4aRenameResults);
216
+ if (lines.length === 0) return 'Error: patch contained no applicable file sections';
217
+ return wrapPatchMutationOutput(`${lines.join('\n')}\n`, mutationPlan, { backend: 'v4a-rename' });
218
+ }
219
+ const nativePatchStr = rewriteHeaderPaths(normalizedPatchStr, headerRewrites);
220
+ const nativeResult = await dispatchNativePatch({
221
+ entries,
222
+ basePath,
223
+ nativePatchStr,
224
+ fuzz,
225
+ rejectPartial,
226
+ dryRun,
227
+ readStateScope,
228
+ signal: abortSignal,
229
+ parsed,
230
+ });
231
+ let combined = nativeResult;
232
+ const renameLines = formatV4ARenameSuccessLines(v4aRenameResults);
233
+ if (renameLines.length > 0 && !isPatchErrorText(nativeResult)) {
234
+ combined = `${renameLines.join('\n')}\n${nativeResult}`;
235
+ }
236
+ if (!isPatchErrorText(combined) && options?.toolCallId) {
237
+ registerApplyPatchUiDiff(options.toolCallId, nativePatchStr);
238
+ }
239
+ if (!isPatchErrorText(combined) && rejectedV4AHunks.length > 0) {
240
+ const tail = [
241
+ '',
242
+ `hunk-level rejected (rejectPartial=false, V4A): ${rejectedV4AHunks.length}`,
243
+ ...rejectedV4AHunks.map((r) => ` REJECT ${r.file || '(unknown)'} — ${String(r.reason || '').split(';')[0].trim()}`),
244
+ ];
245
+ return wrapPatchMutationOutput(`${combined}\n${tail.join('\n')}`, mutationPlan, { backend: 'native-patch' });
246
+ }
247
+ return wrapPatchMutationOutput(combined, mutationPlan, { backend: 'native-patch' });
248
+ }));
249
+ }
250
+
251
+ export async function executePatchTool(name, args, cwd, options = {}) {
252
+ return _executePatchTool(name, args, cwd, options);
253
+ }
254
+
255
+ function patchReplayDir() {
256
+ const base = process.env.MIXDOG_PATCH_REPLAY_DIR
257
+ || pathJoin(getPluginDataDir(), 'history', 'patch-replays');
258
+ return base;
259
+ }
260
+
261
+ function getPluginDataDir() {
262
+ try { return getPluginData(); } catch { /* fall through */ }
263
+ return process.env.MIXDOG_DATA_DIR || pathJoin(process.env.USERPROFILE || process.env.HOME || '.', '.mixdog', 'data');
264
+ }
265
+
266
+ function patchTargetPaths(patchStr, basePath) {
267
+ const out = [];
268
+ const re = /^\*\*\* (?:Update|Add|Delete) File:\s*(.+)$/gm;
269
+ let m;
270
+ while ((m = re.exec(String(patchStr || '')))) {
271
+ const rel = m[1].trim();
272
+ if (rel) out.push(rel);
273
+ }
274
+ const ure = /^\+\+\+ (?:b\/)?(.+)$/gm;
275
+ while ((m = ure.exec(String(patchStr || '')))) {
276
+ const rel = m[1].trim();
277
+ if (rel && rel !== '/dev/null') out.push(rel);
278
+ }
279
+ return [...new Set(out)];
280
+ }
281
+
282
+ function maybeCapturePatchReplay(args, cwd, errorText) {
283
+ if (process.env.MIXDOG_PATCH_REPLAY_CAPTURE !== '1') return;
284
+ try {
285
+ const patchStr = typeof args?.patch === 'string' ? args.patch : '';
286
+ const basePath = pathResolve(String(args?.base_path || cwd || process.cwd()));
287
+ const dir = patchReplayDir();
288
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
289
+ const rels = patchTargetPaths(patchStr, basePath);
290
+ const files = {};
291
+ for (const rel of rels) {
292
+ try {
293
+ const abs = isAbsolute(rel) ? rel : pathResolve(basePath, rel);
294
+ files[rel] = existsSync(abs) ? readFileSync(abs, 'utf8') : null;
295
+ } catch { files[rel] = null; }
296
+ }
297
+ const id = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
298
+ const record = {
299
+ id,
300
+ ts: Date.now(),
301
+ tool: 'apply_patch',
302
+ args: { patch: patchStr, base_path: args?.base_path ?? null, format: args?.format ?? null, dry_run: args?.dry_run ?? null, fuzzy: args?.fuzzy ?? null, reject_partial: args?.reject_partial ?? null },
303
+ cwd: basePath,
304
+ error_first_line: String(errorText || '').split('\n')[0].slice(0, 400),
305
+ targets: rels,
306
+ file_snapshots: files,
307
+ };
308
+ writeFileSync(pathJoin(dir, `${id}.json`), JSON.stringify(record, null, 2), { mode: 0o600 });
309
+ } catch { /* capture is best-effort; never affect the tool result */ }
310
+ }
311
+
312
+ async function _executePatchTool(name, args, cwd, options = {}) {
313
+ const effectiveCwd = cwd || process.cwd();
314
+ switch (name) {
315
+ case 'apply_patch': {
316
+ let result;
317
+ try {
318
+ result = await apply_patch(args || {}, effectiveCwd, options);
319
+ } catch (err) {
320
+ const errText = `Error: ${err?.message || String(err)}`;
321
+ maybeCapturePatchReplay(args, effectiveCwd, errText);
322
+ return errText;
323
+ }
324
+ if (isPatchErrorText(String(result))) maybeCapturePatchReplay(args, effectiveCwd, String(result));
325
+ if (typeof options?.onProgress === 'function') {
326
+ try {
327
+ const _body = String(result);
328
+ if (!/^Error[\s:[]/.test(_body)) {
329
+ if (args?.dry_run === true) options.onProgress('validated');
330
+ else {
331
+ const _m = /^(?:applied|checked)\s+(\d+)\b/m.exec(_body);
332
+ const _n = _m ? Number(_m[1]) : (_body.match(/^\s*OK\s/gm) || []).length;
333
+ options.onProgress(`applied ${_n} files`);
334
+ }
335
+ }
336
+ } catch { /* best-effort */ }
337
+ }
338
+ return result;
339
+ }
340
+ default: throw new Error(`Unknown patch tool: ${name}`);
341
+ }
342
+ }