mixdog 0.9.3 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. package/README.md +112 -38
  2. package/package.json +10 -3
  3. package/scripts/bench/lead-review-tasks-r3.json +20 -0
  4. package/scripts/bench/lead-review-tasks.json +20 -0
  5. package/scripts/bench/r4-mixed-tasks.json +20 -0
  6. package/scripts/bench/r5-orchestrated-task.json +7 -0
  7. package/scripts/bench/review-tasks.json +20 -0
  8. package/scripts/bench/round-codex.json +114 -0
  9. package/scripts/bench/round-mixdog-lead-r3.json +269 -0
  10. package/scripts/bench/round-mixdog-lead.json +269 -0
  11. package/scripts/bench/round-mixdog.json +126 -0
  12. package/scripts/bench/round-r10-bigsample.json +679 -0
  13. package/scripts/bench/round-r11-codexalign.json +257 -0
  14. package/scripts/bench/round-r13-clientmeta.json +464 -0
  15. package/scripts/bench/round-r14-betafeatures.json +466 -0
  16. package/scripts/bench/round-r15-fulldefault.json +462 -0
  17. package/scripts/bench/round-r16-sessionid.json +466 -0
  18. package/scripts/bench/round-r17-wirebytes.json +456 -0
  19. package/scripts/bench/round-r18-prewarm.json +468 -0
  20. package/scripts/bench/round-r19-clean.json +472 -0
  21. package/scripts/bench/round-r20-prewarm-clean.json +475 -0
  22. package/scripts/bench/round-r21-delta-retry.json +473 -0
  23. package/scripts/bench/round-r22-full-probe.json +693 -0
  24. package/scripts/bench/round-r23-itemprobe.json +701 -0
  25. package/scripts/bench/round-r24-shapefix.json +677 -0
  26. package/scripts/bench/round-r25-serial.json +464 -0
  27. package/scripts/bench/round-r26-parallel3.json +671 -0
  28. package/scripts/bench/round-r27-parallel10.json +894 -0
  29. package/scripts/bench/round-r28-parallel10-stagger.json +882 -0
  30. package/scripts/bench/round-r29-parallel10-stagger166.json +886 -0
  31. package/scripts/bench/round-r30-instid.json +253 -0
  32. package/scripts/bench/round-r31-upgradeprobe.json +256 -0
  33. package/scripts/bench/round-r32-vs-codex-lead.json +254 -0
  34. package/scripts/bench/round-r33-vs-codex-codex.json +115 -0
  35. package/scripts/bench/round-r34-orchestrated.json +120 -0
  36. package/scripts/bench/round-r35-orchestrated-codex.json +61 -0
  37. package/scripts/bench/round-r36-orchestrated-capped.json +128 -0
  38. package/scripts/bench/round-r4-codex.json +114 -0
  39. package/scripts/bench/round-r4-mixed.json +225 -0
  40. package/scripts/bench/round-r5-gpt-lead.json +259 -0
  41. package/scripts/bench/round-r6-codex.json +114 -0
  42. package/scripts/bench/round-r6-solo.json +257 -0
  43. package/scripts/bench/round-r7-full.json +254 -0
  44. package/scripts/bench/round-r8-fulldefault.json +255 -0
  45. package/scripts/bench-run.mjs +251 -32
  46. package/scripts/freevar-smoke.mjs +95 -0
  47. package/scripts/internal-comms-bench.mjs +3 -4
  48. package/scripts/internal-comms-smoke.mjs +10 -9
  49. package/scripts/model-catalog-audit.mjs +209 -0
  50. package/scripts/model-list-sanitize-test.mjs +37 -0
  51. package/scripts/mouse-probe.mjs +45 -0
  52. package/scripts/output-style-bench.mjs +13 -6
  53. package/scripts/output-style-smoke.mjs +4 -4
  54. package/scripts/provider-toolcall-test.mjs +7 -3
  55. package/scripts/recall-bench.mjs +76 -13
  56. package/scripts/recall-quality-cases.json +12 -0
  57. package/scripts/recall-usecase-cases.json +18 -0
  58. package/scripts/session-bench.mjs +152 -6
  59. package/scripts/tool-smoke.mjs +25 -65
  60. package/scripts/tui-render-smoke.mjs +90 -0
  61. package/scripts/webhook-smoke.mjs +208 -0
  62. package/src/agents/debugger/AGENT.md +4 -1
  63. package/src/agents/heavy-worker/AGENT.md +9 -8
  64. package/src/agents/maintainer/AGENT.md +4 -0
  65. package/src/agents/reviewer/AGENT.md +2 -1
  66. package/src/agents/scheduler-task/AGENT.md +2 -3
  67. package/src/agents/webhook-handler/AGENT.md +2 -3
  68. package/src/agents/worker/AGENT.md +10 -7
  69. package/src/app.mjs +12 -1
  70. package/src/headless-role.mjs +7 -1
  71. package/src/lib/rules-builder.cjs +4 -0
  72. package/src/mixdog-session-runtime.mjs +647 -2056
  73. package/src/output-styles/default.md +30 -9
  74. package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
  75. package/src/output-styles/minimal.md +8 -6
  76. package/src/output-styles/simple.md +21 -7
  77. package/src/rules/agent/00-common.md +6 -3
  78. package/src/rules/agent/30-explorer.md +16 -5
  79. package/src/rules/lead/01-general.md +5 -5
  80. package/src/rules/lead/lead-brief.md +15 -0
  81. package/src/rules/lead/lead-tool.md +6 -15
  82. package/src/rules/shared/01-tool.md +17 -21
  83. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +8 -3
  84. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
  85. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
  86. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
  87. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
  88. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
  89. package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
  90. package/src/runtime/agent/orchestrator/config.mjs +69 -2
  91. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +62 -20
  92. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
  93. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
  94. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +81 -1281
  95. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
  96. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -3
  97. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
  98. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
  99. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
  101. package/src/runtime/agent/orchestrator/providers/gemini.mjs +43 -1013
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +17 -3
  103. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +105 -11
  104. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +356 -0
  105. package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
  107. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
  108. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +40 -1143
  110. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +740 -0
  111. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +349 -2131
  113. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +143 -1002
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +229 -0
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +465 -0
  117. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
  118. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
  119. package/src/runtime/agent/orchestrator/providers/provider-catalog-cache.mjs +80 -0
  120. package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
  121. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
  122. package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
  123. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
  124. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
  125. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
  126. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
  127. package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
  128. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +14 -2
  129. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
  130. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -3
  131. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +275 -0
  132. package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
  133. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
  134. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
  135. package/src/runtime/agent/orchestrator/session/loop.mjs +278 -402
  136. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
  137. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +7 -4
  138. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +12 -0
  139. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
  140. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
  141. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
  142. package/src/runtime/agent/orchestrator/session/manager.mjs +166 -1087
  143. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
  144. package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
  145. package/src/runtime/agent/orchestrator/stall-policy.mjs +20 -1
  146. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
  147. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
  148. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +35 -44
  149. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
  150. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
  151. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
  152. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
  153. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -92
  154. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
  155. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
  156. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +28 -265
  157. package/src/runtime/agent/orchestrator/tools/builtin.mjs +0 -6
  158. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +57 -3
  159. package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
  160. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +10 -122
  161. package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
  162. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
  163. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
  164. package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
  165. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
  166. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
  167. package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
  168. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
  169. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
  170. package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
  171. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
  172. package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
  173. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +0 -21
  174. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +9 -72
  175. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
  176. package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
  177. package/src/runtime/channels/backends/discord-access.mjs +32 -0
  178. package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
  179. package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
  180. package/src/runtime/channels/backends/discord.mjs +27 -318
  181. package/src/runtime/channels/backends/telegram.mjs +8 -12
  182. package/src/runtime/channels/index.mjs +247 -701
  183. package/src/runtime/channels/lib/backend-dispatch.mjs +46 -0
  184. package/src/runtime/channels/lib/config.mjs +37 -149
  185. package/src/runtime/channels/lib/event-pipeline.mjs +22 -5
  186. package/src/runtime/channels/lib/event-queue.mjs +78 -13
  187. package/src/runtime/channels/lib/inbound-routing.mjs +74 -0
  188. package/src/runtime/channels/lib/interaction-workflows.mjs +5 -113
  189. package/src/runtime/channels/lib/output-forwarder.mjs +1 -1
  190. package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
  191. package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
  192. package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
  193. package/src/runtime/channels/lib/scheduler.mjs +27 -113
  194. package/src/runtime/channels/lib/session-discovery.mjs +56 -4
  195. package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
  196. package/src/runtime/channels/lib/tool-format.mjs +1 -1
  197. package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
  198. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
  199. package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
  200. package/src/runtime/channels/lib/webhook/deliveries.mjs +313 -0
  201. package/src/runtime/channels/lib/webhook/log.mjs +42 -0
  202. package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
  203. package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
  204. package/src/runtime/channels/lib/webhook.mjs +43 -616
  205. package/src/runtime/channels/tool-defs.mjs +11 -130
  206. package/src/runtime/memory/index.mjs +210 -1948
  207. package/src/runtime/memory/lib/core-memory-store.mjs +5 -1
  208. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
  209. package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
  210. package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
  211. package/src/runtime/memory/lib/ko-morph.mjs +195 -0
  212. package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
  213. package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
  214. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
  215. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
  216. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
  217. package/src/runtime/memory/lib/memory-cycle2.mjs +24 -842
  218. package/src/runtime/memory/lib/memory-embed.mjs +149 -0
  219. package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
  220. package/src/runtime/memory/lib/memory-recall-store.mjs +69 -12
  221. package/src/runtime/memory/lib/memory-text-utils.mjs +46 -0
  222. package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
  223. package/src/runtime/memory/lib/query-handlers.mjs +802 -0
  224. package/src/runtime/memory/lib/recall-format.mjs +55 -0
  225. package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
  226. package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
  227. package/src/runtime/memory/tool-defs.mjs +5 -13
  228. package/src/runtime/search/lib/http-fetch.mjs +274 -0
  229. package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
  230. package/src/runtime/search/lib/web-tools.mjs +24 -602
  231. package/src/runtime/shared/atomic-file.mjs +26 -1
  232. package/src/runtime/shared/config.mjs +14 -4
  233. package/src/runtime/shared/launcher-control.mjs +2 -2
  234. package/src/runtime/shared/markdown-frontmatter.mjs +19 -0
  235. package/src/runtime/shared/schedules-store.mjs +13 -3
  236. package/src/runtime/shared/tool-execution-contract.mjs +2 -2
  237. package/src/runtime/shared/tool-primitives.mjs +308 -0
  238. package/src/runtime/shared/tool-result-summary.mjs +515 -0
  239. package/src/runtime/shared/tool-surface.mjs +80 -898
  240. package/src/runtime/shared/transcript-writer.mjs +23 -0
  241. package/src/runtime/shared/update-checker.mjs +7 -4
  242. package/src/session-runtime/config-helpers.mjs +119 -2
  243. package/src/session-runtime/config-lifecycle.mjs +232 -0
  244. package/src/session-runtime/cwd-plugins.mjs +226 -0
  245. package/src/session-runtime/mcp-glue.mjs +177 -0
  246. package/src/session-runtime/model-recency.mjs +111 -0
  247. package/src/session-runtime/native-search.mjs +247 -0
  248. package/src/session-runtime/output-styles.mjs +11 -9
  249. package/src/session-runtime/prewarm.mjs +142 -0
  250. package/src/session-runtime/provider-models.mjs +278 -0
  251. package/src/session-runtime/provider-usage.mjs +120 -0
  252. package/src/session-runtime/quick-model-rows.mjs +205 -0
  253. package/src/session-runtime/quick-search-models.mjs +47 -0
  254. package/src/session-runtime/session-hooks.mjs +93 -0
  255. package/src/session-runtime/settings-api.mjs +352 -0
  256. package/src/session-runtime/tool-catalog.mjs +29 -29
  257. package/src/session-runtime/tool-defs.mjs +84 -0
  258. package/src/session-runtime/warmup-schedulers.mjs +201 -0
  259. package/src/session-runtime/workflow.mjs +1 -1
  260. package/src/standalone/agent-tool/helpers.mjs +237 -0
  261. package/src/standalone/agent-tool/notify.mjs +107 -0
  262. package/src/standalone/agent-tool/provider-init.mjs +143 -0
  263. package/src/standalone/agent-tool/render.mjs +152 -0
  264. package/src/standalone/agent-tool/tool-def.mjs +55 -0
  265. package/src/standalone/agent-tool.mjs +138 -669
  266. package/src/standalone/channel-admin.mjs +102 -90
  267. package/src/standalone/channel-worker.mjs +4 -7
  268. package/src/standalone/explore-tool.mjs +64 -14
  269. package/src/standalone/hook-bus/config.mjs +207 -0
  270. package/src/standalone/hook-bus/constants.mjs +90 -0
  271. package/src/standalone/hook-bus/handlers.mjs +481 -0
  272. package/src/standalone/hook-bus/payload.mjs +31 -0
  273. package/src/standalone/hook-bus/rules.mjs +77 -0
  274. package/src/standalone/hook-bus.mjs +77 -870
  275. package/src/standalone/memory-runtime-proxy.mjs +7 -0
  276. package/src/standalone/opencode-go-login.mjs +5 -1
  277. package/src/standalone/provider-admin.mjs +1 -16
  278. package/src/standalone/usage-dashboard.mjs +3 -1
  279. package/src/tui/App.jsx +1059 -8110
  280. package/src/tui/app/app-format.mjs +213 -0
  281. package/src/tui/app/channel-pickers.mjs +508 -0
  282. package/src/tui/app/clipboard.mjs +67 -0
  283. package/src/tui/app/core-memory-picker.mjs +210 -0
  284. package/src/tui/app/extension-pickers.mjs +506 -0
  285. package/src/tui/app/input-parsers.mjs +193 -0
  286. package/src/tui/app/maintenance-pickers.mjs +356 -0
  287. package/src/tui/app/model-options.mjs +334 -0
  288. package/src/tui/app/model-picker.mjs +365 -0
  289. package/src/tui/app/onboarding-steps.mjs +400 -0
  290. package/src/tui/app/project-picker.mjs +247 -0
  291. package/src/tui/app/provider-setup-picker.mjs +580 -0
  292. package/src/tui/app/resume-picker.mjs +55 -0
  293. package/src/tui/app/route-pickers.mjs +419 -0
  294. package/src/tui/app/settings-picker.mjs +489 -0
  295. package/src/tui/app/slash-commands.mjs +101 -0
  296. package/src/tui/app/slash-dispatch.mjs +427 -0
  297. package/src/tui/app/text-layout.mjs +46 -0
  298. package/src/tui/app/theme-effort-pickers.mjs +154 -0
  299. package/src/tui/app/transcript-window.mjs +677 -0
  300. package/src/tui/app/use-mouse-input.mjs +460 -0
  301. package/src/tui/app/use-prompt-handlers.mjs +310 -0
  302. package/src/tui/app/use-transcript-scroll.mjs +512 -0
  303. package/src/tui/app/use-transcript-window.mjs +607 -0
  304. package/src/tui/components/ConfirmBar.jsx +10 -7
  305. package/src/tui/components/Picker.jsx +64 -15
  306. package/src/tui/components/PromptInput.jsx +33 -102
  307. package/src/tui/components/SlashCommandPalette.jsx +8 -1
  308. package/src/tui/components/StatusLine.jsx +69 -15
  309. package/src/tui/components/TextEntryPanel.jsx +11 -0
  310. package/src/tui/components/ToolExecution.jsx +52 -594
  311. package/src/tui/components/TranscriptItem.jsx +105 -0
  312. package/src/tui/components/UsagePanel.jsx +18 -4
  313. package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
  314. package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
  315. package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
  316. package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
  317. package/src/tui/components/tool-execution/text-format.mjs +161 -0
  318. package/src/tui/display-width.mjs +20 -3
  319. package/src/tui/dist/index.mjs +13553 -12384
  320. package/src/tui/engine/agent-job-feed.mjs +133 -0
  321. package/src/tui/engine/notification-plan.mjs +76 -0
  322. package/src/tui/engine/render-timing.mjs +17 -0
  323. package/src/tui/engine/tool-approval.mjs +94 -0
  324. package/src/tui/engine/tool-card-results.mjs +234 -0
  325. package/src/tui/engine/tool-result-status.mjs +135 -0
  326. package/src/tui/engine.mjs +170 -574
  327. package/src/tui/figures.mjs +5 -0
  328. package/src/tui/index.jsx +65 -1
  329. package/src/tui/input-editing.mjs +2 -2
  330. package/src/tui/markdown/format-token.mjs +4 -1
  331. package/src/tui/statusline-ansi-bridge.mjs +11 -3
  332. package/src/tui/theme.mjs +6 -0
  333. package/src/ui/statusline-agents.mjs +213 -0
  334. package/src/ui/statusline-format.mjs +146 -0
  335. package/src/ui/statusline-segments.mjs +148 -0
  336. package/src/ui/statusline.mjs +77 -501
  337. package/src/ui/tool-card.mjs +0 -1
  338. package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
  339. package/src/workflows/default/WORKFLOW.md +16 -18
  340. package/src/workflows/sequential/WORKFLOW.md +16 -18
  341. package/vendor/ink/build/display-width.js +19 -3
  342. package/vendor/ink/build/ink.js +112 -7
  343. package/vendor/ink/build/log-update.js +17 -3
  344. package/vendor/ink/build/wrap-text.js +125 -0
  345. package/scripts/_test-folder-dialog.mjs +0 -30
  346. package/scripts/fix-brief-fn.mjs +0 -35
  347. package/scripts/fix-format-tool-surface.mjs +0 -24
  348. package/scripts/fix-tool-exec-visible.mjs +0 -42
  349. package/scripts/patch-agent-brief.mjs +0 -48
  350. package/scripts/patch-app.mjs +0 -21
  351. package/scripts/patch-app2.mjs +0 -18
  352. package/scripts/patch-dist-brief.mjs +0 -96
  353. package/scripts/patch-tool-exec.mjs +0 -70
  354. package/src/examples/schedules/SCHEDULE.example.md +0 -32
  355. package/src/examples/webhooks/WEBHOOK.example.md +0 -40
  356. package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
  357. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
  358. package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
  359. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.test.mjs +0 -162
  360. package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
  361. package/src/runtime/channels/lib/holidays.mjs +0 -138
  362. package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
  363. package/src/runtime/shared/task-notification-envelope.test.mjs +0 -107
  364. package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
  365. package/src/standalone/agent-task-status.test.mjs +0 -76
  366. package/src/tui/components/tool-output-format.test.mjs +0 -399
  367. package/src/tui/display-width.test.mjs +0 -35
  368. package/src/tui/engine-runtime-notification.test.mjs +0 -115
  369. package/src/tui/engine-tool-result-text.test.mjs +0 -75
  370. package/src/tui/input-editing.selection.test.mjs +0 -75
  371. package/src/tui/markdown/format-token.test.mjs +0 -354
  372. package/src/tui/markdown/render-ansi.test.mjs +0 -108
  373. package/src/tui/markdown/stream-fence.test.mjs +0 -26
  374. package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
  375. package/src/tui/paste-fix.test.mjs +0 -119
  376. package/src/tui/prompt-history-store.test.mjs +0 -52
  377. package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
  378. package/src/tui/transcript-tool-failures.test.mjs +0 -111
  379. package/src/ui/markdown.test.mjs +0 -70
  380. package/src/ui/statusline-context-label.test.mjs +0 -15
  381. package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
  382. package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
@@ -0,0 +1,340 @@
1
+ // Path resolution / entry classification helpers for apply_patch. Moved
2
+ // verbatim from patch.mjs; path/diff semantics unchanged.
3
+
4
+ import { existsSync, realpathSync } from 'node:fs';
5
+ import { resolve as pathResolve, relative as pathRelative, isAbsolute, dirname as pathDirname } from 'node:path';
6
+ import {
7
+ normalizeInputPath,
8
+ normalizeOutputPath,
9
+ resolveAgainstCwd,
10
+ } from '../builtin.mjs';
11
+ import { assertPathReachable, assertPathsReachable } from '../builtin/fs-reachability.mjs';
12
+ import { nativePatchEnabled, nativePatchBinPath } from './native-server.mjs';
13
+ import { DEV_NULL } from './constants.mjs';
14
+
15
+ // Strip the leading `a/` or `b/` prefix that `diff -u` / git emit by
16
+ // default, plus timestamp suffixes (`\t2024-...`) that some tools append
17
+ // to header lines. parsePatch already splits the name from the header
18
+ // so timestamps land in `oldHeader` / `newHeader`, but be defensive.
19
+ export function stripDiffPrefix(name) {
20
+ if (!name) return name;
21
+ if (isAbsolute(name) || /^[A-Za-z]:[\\/]/.test(name)) return name;
22
+ const m = /^[ab]\/(.+)$/.exec(name);
23
+ return m ? m[1] : name;
24
+ }
25
+
26
+ export function resolveEntryPath(basePath, rawName) {
27
+ const stripped = stripDiffPrefix(rawName);
28
+ const norm = normalizeInputPath(stripped);
29
+ return isAbsolute(norm) ? pathResolve(norm) : resolveAgainstCwd(norm, basePath);
30
+ }
31
+
32
+ // V4A section paths are real repository paths and never carry the unified
33
+ // diff `a/`·`b/` prefix, so resolution must NOT apply stripDiffPrefix — a
34
+ // legitimate top-level `a/` or `b/` directory would otherwise be silently
35
+ // rewritten to its child, reading/writing the wrong file.
36
+ export function resolveV4AEntryPath(basePath, rawName) {
37
+ const norm = normalizeInputPath(rawName);
38
+ return isAbsolute(norm) ? pathResolve(norm) : resolveAgainstCwd(norm, basePath);
39
+ }
40
+
41
+ export function resolveBasePath(cwd, basePath) {
42
+ if (!basePath) return cwd;
43
+ const norm = normalizeInputPath(basePath);
44
+ return isAbsolute(norm) ? pathResolve(norm) : resolveAgainstCwd(norm, cwd);
45
+ }
46
+
47
+ // Categorise the per-file entry. A unified diff can describe:
48
+ // - modify : both files named, oldFileName exists on disk
49
+ // - create : oldFileName === /dev/null (or file doesn't exist + hunks start at 0)
50
+ // - delete : newFileName === /dev/null
51
+ export function classifyEntry(entry) {
52
+ const oldIsNull = DEV_NULL.test(entry.oldFileName || '');
53
+ const newIsNull = DEV_NULL.test(entry.newFileName || '');
54
+ if (oldIsNull && !newIsNull) return 'create';
55
+ if (!oldIsNull && newIsNull) return 'delete';
56
+ return 'modify';
57
+ }
58
+
59
+ function parsedEntryTargetKey(entry, basePath) {
60
+ if (classifyEntry(entry) !== 'modify') return '';
61
+ const headerName = entry.oldFileName || entry.newFileName;
62
+ if (!headerName || DEV_NULL.test(headerName)) return '';
63
+ const fullPath = resolveEntryPath(basePath, headerName);
64
+ return process.platform === 'win32' ? fullPath.toLowerCase() : fullPath;
65
+ }
66
+
67
+ export function mergeDuplicateParsedModifyEntries(parsed, basePath) {
68
+ const out = [];
69
+ const byTarget = new Map();
70
+ let changed = false;
71
+ for (const entry of parsed || []) {
72
+ const key = parsedEntryTargetKey(entry, basePath);
73
+ if (!key) {
74
+ out.push(entry);
75
+ continue;
76
+ }
77
+ const existing = byTarget.get(key);
78
+ if (!existing) {
79
+ byTarget.set(key, entry);
80
+ out.push(entry);
81
+ continue;
82
+ }
83
+ existing.hunks.push(...(entry.hunks || []));
84
+ changed = true;
85
+ }
86
+ return { parsed: out, changed };
87
+ }
88
+
89
+ function unifiedRange(start, lines) {
90
+ const s = Math.max(0, Number(start) || 0);
91
+ const n = Math.max(0, Number(lines) || 0);
92
+ return `${s},${n}`;
93
+ }
94
+
95
+ export function renderParsedUnifiedPatch(parsed) {
96
+ const out = [];
97
+ for (const entry of parsed || []) {
98
+ out.push(`--- ${entry.oldFileName || '/dev/null'}`);
99
+ out.push(`+++ ${entry.newFileName || '/dev/null'}`);
100
+ for (const hunk of entry.hunks || []) {
101
+ const section = hunk.section ? ` ${hunk.section}` : '';
102
+ out.push(`@@ -${unifiedRange(hunk.oldStart, hunk.oldLines)} +${unifiedRange(hunk.newStart, hunk.newLines)} @@${section}`);
103
+ for (const line of hunk.lines || []) out.push(line);
104
+ }
105
+ }
106
+ return `${out.join('\n')}\n`;
107
+ }
108
+
109
+ // Count how many source lines a hunk consumes vs produces so we can
110
+ // surface a concise `lines_changed` figure without re-diffing.
111
+ export function countHunkChanges(hunks) {
112
+ let added = 0;
113
+ let removed = 0;
114
+ for (const h of hunks || []) {
115
+ for (const line of h.lines || []) {
116
+ if (line.startsWith('+')) added++;
117
+ else if (line.startsWith('-')) removed++;
118
+ }
119
+ }
120
+ return { added, removed };
121
+ }
122
+
123
+ // Header-shape pre-validator (lexical only): a missing header, a
124
+ // `..` segment, or an absolute path that does not resolve inside the
125
+ // basePath returns false. Caller wraps the negative result into a clean
126
+ // throw so unsupported headers surface as a clean error instead of
127
+ // silently degrading to a JS fallback.
128
+ function nativeHeaderSupported(entry, basePath) {
129
+ const kind = classifyEntry(entry);
130
+ const headerName = kind === 'create' ? entry.newFileName : entry.oldFileName;
131
+ if (!headerName || DEV_NULL.test(headerName)) return false;
132
+ // Reject any `..` segment on EITHER oldFileName or newFileName (every
133
+ // non-/dev/null header) — a modify whose newFileName traverses out of
134
+ // base must still be refused even when the resolved path lands inside.
135
+ for (const which of ['oldFileName', 'newFileName']) {
136
+ const raw = entry[which];
137
+ if (!raw || DEV_NULL.test(raw)) continue;
138
+ const segs = normalizeInputPath(stripDiffPrefix(raw)).split(/[\\/]+/);
139
+ if (segs.some((part) => part === '..')) return false;
140
+ }
141
+ const stripped = stripDiffPrefix(headerName);
142
+ const norm = normalizeInputPath(stripped);
143
+ if (isAbsolute(norm) || /^[A-Za-z]:[\\/]/.test(norm)) {
144
+ if (!basePath) return false;
145
+ const absHeader = pathResolve(norm);
146
+ const absBase = pathResolve(basePath);
147
+ const rel = pathRelative(absBase, absHeader);
148
+ if (!rel || rel.startsWith('..') || isAbsolute(rel)) return false;
149
+ if (rel.split(/[\\/]+/).some((part) => part === '..')) return false;
150
+ return true;
151
+ }
152
+ return true;
153
+ }
154
+
155
+ // Resolve `absPath` via fs.realpathSync, walking up to the nearest existing
156
+ // ancestor when the leaf does not yet exist (e.g. a create-mode target).
157
+ // Returns the resolved real path, or the lexically-resolved path if no
158
+ // ancestor can be realpath'd.
159
+ export function realpathNearestExistingAncestor(absPath) {
160
+ let cur = pathResolve(absPath);
161
+ while (true) {
162
+ try {
163
+ return realpathSync(cur);
164
+ } catch {
165
+ const parent = pathDirname(cur);
166
+ if (!parent || parent === cur) return cur;
167
+ cur = parent;
168
+ }
169
+ }
170
+ }
171
+
172
+ // Pre-validator (throws): walks every parsed entry and enforces
173
+ // - native engine is enabled
174
+ // - native binary exists on disk
175
+ // - each header is shape-supported (no `..`, no out-of-base absolute)
176
+ // - realpath of each non-/dev/null header stays inside the real basePath
177
+ // (catches symlink/junction escapes that lexical checks miss)
178
+ // - no duplicate target paths in the patch (case-insensitive on win32)
179
+ // Returns the list of normalized entry rows the dispatcher uses to format
180
+ // output, plus the header-rewrite map for absolute-path normalization.
181
+ export async function preValidateNativeBatch(parsed, basePath) {
182
+ if (!nativePatchEnabled()) {
183
+ throw new Error('apply_patch: native engine disabled via MIXDOG_PATCH_NATIVE; set it to "auto" or "1" to apply patches.');
184
+ }
185
+ const binPath = nativePatchBinPath();
186
+ if (!existsSync(binPath)) {
187
+ throw new Error(`apply_patch: native patch binary not found at ${binPath}; build native/mixdog-patch or fetch the prebuilt before invoking apply_patch.`);
188
+ }
189
+ if (!Array.isArray(parsed) || parsed.length === 0) {
190
+ throw new Error('apply_patch: patch contained no file sections');
191
+ }
192
+ await assertPathReachable(basePath);
193
+ const reachabilityPaths = [];
194
+ for (const entry of parsed) {
195
+ for (const which of ['oldFileName', 'newFileName']) {
196
+ const checkName = entry[which];
197
+ if (!checkName || DEV_NULL.test(checkName)) continue;
198
+ reachabilityPaths.push(resolveEntryPath(basePath, checkName));
199
+ }
200
+ }
201
+ await assertPathsReachable(reachabilityPaths);
202
+ let realBase;
203
+ try {
204
+ realBase = realpathSync(pathResolve(basePath));
205
+ } catch (err) {
206
+ throw new Error(`apply_patch: base_path unreadable (${err?.code || err?.message || String(err)}): ${basePath}`);
207
+ }
208
+ const entries = [];
209
+ const seenPaths = new Set();
210
+ const headerRewrites = [];
211
+ for (const entry of parsed) {
212
+ const kind = classifyEntry(entry);
213
+ const headerName = kind === 'create' ? entry.newFileName : entry.oldFileName;
214
+ if (!nativeHeaderSupported(entry, basePath)) {
215
+ // Two distinct failure modes share nativeHeaderSupported()===false:
216
+ // (a) no usable target path could be parsed from the section header
217
+ // (oldFileName/newFileName empty or /dev/null) — a SHAPE problem,
218
+ // (b) a parsed path that escapes base_path (`..` segment / out-of-base
219
+ // absolute) — a SECURITY refusal.
220
+ // Collapsing both into the "path escapes base_path or contains `..`"
221
+ // message mislabels (a) as (b): the model sees a nonsensical reason for a
222
+ // patch that uses no `..`, cannot self-correct, and re-submits the same
223
+ // patch until the iteration cap. Emit a shape-specific, actionable hint
224
+ // for (a) so the loop breaks on the first failure.
225
+ const hasUsableHeader = headerName && !DEV_NULL.test(headerName);
226
+ if (!hasUsableHeader) {
227
+ throw new Error(
228
+ 'apply_patch: a file section header could not be parsed (no target path). '
229
+ + 'Each section must start with a valid header: `*** Update File: <path>` / '
230
+ + '`*** Add File: <path>` / `*** Delete File: <path>` (V4A), or a '
231
+ + '`--- a/<path>` + `+++ b/<path>` pair (unified). Wrap multi-hunk V4A '
232
+ + 'edits in a `*** Begin Patch` / `*** End Patch` envelope and pass format:"v4a".',
233
+ );
234
+ }
235
+ const display = normalizeOutputPath(stripDiffPrefix(headerName));
236
+ throw new Error(`apply_patch: header ${display} is unsupported (path escapes base_path or contains \`..\`).`);
237
+ }
238
+ if (kind !== 'delete' && !(entry.hunks?.length > 0)) {
239
+ const display = headerName ? normalizeOutputPath(stripDiffPrefix(headerName)) : '(unknown)';
240
+ throw new Error(`apply_patch: entry ${display} has no hunks — patch header malformed (use \`@@ -A,B +C,D @@\` per hunk).`);
241
+ }
242
+ // Realpath each non-/dev/null header; nearest-existing-ancestor handles
243
+ // create-mode leaves that do not yet exist. A symlink/junction whose
244
+ // target escapes basePath fails here even when the lexical check above
245
+ // looked safe.
246
+ for (const which of ['oldFileName', 'newFileName']) {
247
+ const checkName = entry[which];
248
+ if (!checkName || DEV_NULL.test(checkName)) continue;
249
+ const checkFull = resolveEntryPath(basePath, checkName);
250
+ const checkReal = realpathNearestExistingAncestor(checkFull);
251
+ const checkRel = pathRelative(realBase, checkReal);
252
+ if (checkRel.split(/[\\/]+/).some((part) => part === '..') || isAbsolute(checkRel)) {
253
+ const display = normalizeOutputPath(stripDiffPrefix(checkName));
254
+ throw new Error(`apply_patch: ${display} resolves outside base_path via symlink/junction; refusing to apply.`);
255
+ }
256
+ }
257
+ const fullPath = resolveEntryPath(basePath, headerName);
258
+ const pathKey = process.platform === 'win32' ? fullPath.toLowerCase() : fullPath;
259
+ if (seenPaths.has(pathKey)) {
260
+ const display = normalizeOutputPath(stripDiffPrefix(headerName));
261
+ throw new Error(`apply_patch: duplicate target ${display} — patch lists the same path twice.`);
262
+ }
263
+ seenPaths.add(pathKey);
264
+ const displayPath = normalizeOutputPath(stripDiffPrefix(headerName));
265
+ const { added, removed } = countHunkChanges(entry.hunks);
266
+ entries.push({
267
+ kind,
268
+ fullPath,
269
+ displayPath,
270
+ added,
271
+ removed,
272
+ hunks: entry.hunks?.length || 0,
273
+ linesChanged: added + removed,
274
+ });
275
+ // Absolute-form headers must be rewritten to repo-relative before the
276
+ // native server, which joins headers to basePath, sees them.
277
+ for (const which of ['oldFileName', 'newFileName']) {
278
+ const raw = entry[which];
279
+ if (!raw || DEV_NULL.test(raw)) continue;
280
+ const stripped = stripDiffPrefix(raw);
281
+ const norm = normalizeInputPath(stripped);
282
+ if (!isAbsolute(norm) && !/^[A-Za-z]:[\\/]/.test(norm)) continue;
283
+ const rel = pathRelative(pathResolve(basePath), pathResolve(norm)).replace(/\\/g, '/');
284
+ if (!rel || rel.startsWith('..') || isAbsolute(rel)) {
285
+ const display = normalizeOutputPath(stripDiffPrefix(raw));
286
+ throw new Error(`apply_patch: absolute header ${display} does not resolve inside base_path.`);
287
+ }
288
+ headerRewrites.push({ from: raw, to: rel });
289
+ }
290
+ }
291
+ return { entries, headerRewrites };
292
+ }
293
+
294
+ // Rewrite ONLY the file-section header lines (`--- old`/`+++ new`) that
295
+ // precede each hunk so the native server, which joins headers to
296
+ // basePath, never sees an absolute header. A hunk DELETION line is `-`
297
+ // + content, so a deleted line whose body text is `-- C:/...` renders as
298
+ // `--- C:/...`; track hunk-body state by consuming each `@@ -a,b +c,d @@`
299
+ // header's declared line counts so only lines outside any hunk body are
300
+ // eligible for rewrite.
301
+ export function rewriteHeaderPaths(patchStr, headerRewrites) {
302
+ if (!headerRewrites || headerRewrites.length === 0) return patchStr;
303
+ const lines = patchStr.split('\n');
304
+ let i = 0;
305
+ while (i < lines.length) {
306
+ const line = lines[i];
307
+ if (line.startsWith('@@ ')) {
308
+ const m = /^@@ -\d+(?:,(\d+))? \+\d+(?:,(\d+))? @@/.exec(line);
309
+ let oldRem = m && m[1] !== undefined ? Number(m[1]) : 1;
310
+ let newRem = m && m[2] !== undefined ? Number(m[2]) : 1;
311
+ i++;
312
+ while (i < lines.length && (oldRem > 0 || newRem > 0)) {
313
+ const body = lines[i];
314
+ const c = body.charAt(0);
315
+ if (c === ' ') { oldRem--; newRem--; }
316
+ else if (c === '-') { oldRem--; }
317
+ else if (c === '+') { newRem--; }
318
+ else if (c === '\\') { /* "" marker */ }
319
+ else break;
320
+ i++;
321
+ }
322
+ continue;
323
+ }
324
+ if (line.startsWith('--- ') || line.startsWith('+++ ')) {
325
+ const prefix = line.slice(0, 4);
326
+ const rest = line.slice(4);
327
+ const tabIdx = rest.indexOf('\t');
328
+ const pathPart = tabIdx === -1 ? rest : rest.slice(0, tabIdx);
329
+ const suffix = tabIdx === -1 ? '' : rest.slice(tabIdx);
330
+ for (const { from, to } of headerRewrites) {
331
+ if (pathPart === from) {
332
+ lines[i] = `${prefix}${to}${suffix}`;
333
+ break;
334
+ }
335
+ }
336
+ }
337
+ i++;
338
+ }
339
+ return lines.join('\n');
340
+ }