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,310 @@
1
+ /**
2
+ * use-prompt-handlers.mjs — the PROMPT HANDLER cluster extracted from App.jsx
3
+ * (pass-7 split).
4
+ *
5
+ * Exports usePromptHandlers(), which owns the five useCallback handlers wired to
6
+ * PromptInput: handleVoiceToggle / handlePromptPaste / handlePromptHistoryNavigate
7
+ * / handlePromptEscape / handlePromptInterrupt. Every ref, setter, store value and
8
+ * derived value the handlers close over is threaded in explicitly so the deps
9
+ * arrays stay byte-identical to the original inline hooks. Import-level helpers
10
+ * (voice recorder + paste attachments) are imported directly here.
11
+ */
12
+ import { useCallback } from 'react';
13
+ import {
14
+ readClipboardImageAttachment,
15
+ readImageAttachmentFromPath,
16
+ splitPastedImagePathCandidates,
17
+ } from '../paste-attachments.mjs';
18
+ import {
19
+ shouldFoldPastedText,
20
+ } from '../paste-attachments.mjs';
21
+ import {
22
+ isVoiceEnabled,
23
+ getRecorderState,
24
+ startRecording,
25
+ stopRecording,
26
+ cancelRecording,
27
+ } from '../lib/voice-recorder.mjs';
28
+ import { promptHistoryKey } from '../prompt-history-store.mjs';
29
+
30
+ export function usePromptHandlers({
31
+ store,
32
+ state,
33
+ // refs
34
+ promptValueRef,
35
+ pastedImagesRef,
36
+ nextPastedImageIdRef,
37
+ pastedTextsRef,
38
+ nextPastedTextIdRef,
39
+ promptHistoryNavRef,
40
+ promptHistoryDraftChangeRef,
41
+ // setters
42
+ setPastedImages,
43
+ setPastedTexts,
44
+ setPromptDraftOverride,
45
+ setVoiceRecPhase,
46
+ setContextPanel,
47
+ // derived / helper values + callbacks
48
+ setVoiceStatusHint,
49
+ syncPromptLayoutRows,
50
+ showPromptHint,
51
+ clearPromptHint,
52
+ recentPromptHistory,
53
+ resetPromptHistoryNav,
54
+ restoreQueuedToPrompt,
55
+ usagePanel,
56
+ closeUsagePanel,
57
+ contextPanel,
58
+ // paste-attachment helpers (owned by App, threaded in explicitly)
59
+ installPastedImages,
60
+ clearPastedImagesSnapshot,
61
+ registerPastedImage,
62
+ installPastedTexts,
63
+ clearPastedTextsSnapshot,
64
+ registerPastedText,
65
+ }) {
66
+ // Ctrl+Space handler wired to PromptInput's onVoiceToggle. Dispatches on the
67
+ // recorder's CURRENT state (idle/recording/transcribing) — see
68
+ // src/tui/lib/voice-recorder.mjs for the state machine itself.
69
+ const handleVoiceToggle = useCallback(async () => {
70
+ if (!isVoiceEnabled()) {
71
+ store.pushNotice('Voice is off — run /voice to turn it on', 'warn');
72
+ return;
73
+ }
74
+ const recState = getRecorderState();
75
+ if (recState === 'transcribing') {
76
+ store.pushNotice('Voice: already transcribing…', 'info');
77
+ return;
78
+ }
79
+ if (recState === 'recording') {
80
+ setVoiceStatusHint('… transcribing', 'info');
81
+ setVoiceRecPhase('transcribing');
82
+ let result;
83
+ try {
84
+ result = await stopRecording();
85
+ } catch (e) {
86
+ result = { ok: false, reason: e?.message || String(e) };
87
+ }
88
+ setVoiceStatusHint('', 'info');
89
+ setVoiceRecPhase('idle');
90
+ if (!result) return; // race: recorder was no longer RECORDING
91
+ if (!result.ok) {
92
+ store.pushNotice(`Voice: ${result.reason || 'transcription failed'}`, 'error');
93
+ return;
94
+ }
95
+ const text = String(result.text || '').trim();
96
+ if (!text) {
97
+ store.pushNotice('Voice: no speech detected', 'warn');
98
+ return;
99
+ }
100
+ // End-of-draft insertion via promptDraftOverride (approved design —
101
+ // no cursor-position insert; see gamerscroll skill's out-of-scope note
102
+ // on PromptInput's imperative surface).
103
+ // Med-4: promptValueRef.current is read HERE — after `await
104
+ // stopRecording()` has already resolved — not captured earlier before
105
+ // the await. PromptInput keeps valueRef.current live on every
106
+ // keystroke (commitDraft), so this always reflects whatever the user
107
+ // typed during the recording+transcribe window; nothing typed in that
108
+ // gap is overwritten.
109
+ const current = promptValueRef.current || '';
110
+ const next = current ? `${current}${/\s$/.test(current) ? '' : ' '}${text}` : text;
111
+ syncPromptLayoutRows(next);
112
+ setPromptDraftOverride({ id: Date.now(), value: next });
113
+ return;
114
+ }
115
+ // idle -> recording
116
+ let result;
117
+ try {
118
+ result = await startRecording();
119
+ } catch (e) {
120
+ result = { ok: false, reason: e?.message || String(e) };
121
+ }
122
+ if (!result?.ok) {
123
+ store.pushNotice(`Voice: ${result?.reason || 'failed to start recording'}`, 'error');
124
+ return;
125
+ }
126
+ setVoiceStatusHint('● REC', 'error');
127
+ setVoiceRecPhase('recording');
128
+ }, [store, setVoiceStatusHint, syncPromptLayoutRows]);
129
+
130
+ const handlePromptPaste = useCallback((text, meta = {}) => {
131
+ const source = String(meta?.source || 'paste');
132
+ const value = String(text ?? '');
133
+ if (source === 'clipboard-image-shortcut' && !value) {
134
+ return readClipboardImageAttachment()
135
+ .then((image) => {
136
+ if (!image) {
137
+ showPromptHint('no image found on clipboard', 'plain');
138
+ return false;
139
+ }
140
+ const ref = registerPastedImage(image);
141
+ showPromptHint(`attached ${image.filename || 'clipboard image'}`, 'plain');
142
+ return ref;
143
+ })
144
+ .catch((e) => {
145
+ showPromptHint(`image paste failed: ${e?.message || e}`, 'warn');
146
+ return false;
147
+ });
148
+ }
149
+
150
+ const chunks = splitPastedImagePathCandidates(value);
151
+ const hasImagePath = chunks.some((chunk) => chunk.imagePath);
152
+ // No image paths in the paste: fold the whole text into a token when it is
153
+ // large, otherwise let PromptInput insert it raw (return undefined).
154
+ if (!hasImagePath) {
155
+ if (shouldFoldPastedText(value)) return registerPastedText(value);
156
+ return undefined;
157
+ }
158
+ // Mixed paste: resolve each image chunk to an image ref, then fold each
159
+ // CONTIGUOUS run of non-image text into its own token (only if over
160
+ // threshold) so content order around image refs is preserved. '\n'
161
+ // separator chunks are plain text and stay inside their surrounding run.
162
+ return Promise.all(chunks.map(async (chunk) => {
163
+ if (!chunk.imagePath) return chunk.text;
164
+ try {
165
+ const image = await readImageAttachmentFromPath(chunk.text, state.cwd || process.cwd());
166
+ if (!image) return chunk.text;
167
+ const ref = registerPastedImage(image);
168
+ showPromptHint(`attached ${image.filename || 'image'}`, 'plain');
169
+ return ref;
170
+ } catch (e) {
171
+ showPromptHint(`image attach failed: ${e?.message || e}`, 'warn');
172
+ return chunk.text;
173
+ }
174
+ })).then((parts) => {
175
+ let out = '';
176
+ let run = '';
177
+ const flushRun = () => {
178
+ if (!run) return;
179
+ out += shouldFoldPastedText(run) ? registerPastedText(run) : run;
180
+ run = '';
181
+ };
182
+ for (let i = 0; i < chunks.length; i += 1) {
183
+ if (chunks[i].imagePath) {
184
+ flushRun();
185
+ out += parts[i];
186
+ } else {
187
+ run += parts[i];
188
+ }
189
+ }
190
+ flushRun();
191
+ return out;
192
+ });
193
+ }, [registerPastedImage, registerPastedText, showPromptHint, state.cwd]);
194
+
195
+ const handlePromptHistoryNavigate = useCallback((direction, currentText = '', meta = {}) => {
196
+ const currentValue = String(currentText || '');
197
+ const currentKey = promptHistoryKey(currentValue);
198
+ const nav = promptHistoryNavRef.current || { active: false, index: -1, seed: '', lastValue: '' };
199
+
200
+ if (meta.emptyDraft && direction === 'down') {
201
+ resetPromptHistoryNav();
202
+ clearPromptHint();
203
+ return undefined;
204
+ }
205
+
206
+ if (recentPromptHistory.length === 0) {
207
+ resetPromptHistoryNav();
208
+ clearPromptHint();
209
+ return undefined;
210
+ }
211
+
212
+ if (direction === 'down' && !nav.active) {
213
+ clearPromptHint();
214
+ return undefined;
215
+ }
216
+
217
+ const active = nav.active && (currentValue === nav.lastValue || currentValue === nav.seed);
218
+ const seed = active ? nav.seed : currentValue;
219
+ const step = direction === 'down' ? -1 : 1;
220
+ let nextIndex = (active ? nav.index : -1) + step;
221
+
222
+ if (nextIndex < 0) {
223
+ resetPromptHistoryNav();
224
+ clearPromptHint();
225
+ promptHistoryDraftChangeRef.current = true;
226
+ return seed;
227
+ }
228
+
229
+ while (nextIndex >= 0 && nextIndex < recentPromptHistory.length && promptHistoryKey(recentPromptHistory[nextIndex]) === currentKey) {
230
+ nextIndex += step;
231
+ }
232
+
233
+ if (nextIndex < 0) {
234
+ resetPromptHistoryNav();
235
+ clearPromptHint();
236
+ promptHistoryDraftChangeRef.current = true;
237
+ return seed;
238
+ }
239
+
240
+ if (nextIndex >= recentPromptHistory.length) {
241
+ clearPromptHint();
242
+ return undefined;
243
+ }
244
+
245
+ const nextValue = recentPromptHistory[nextIndex];
246
+ promptHistoryNavRef.current = { active: true, index: nextIndex, seed, lastValue: nextValue };
247
+ clearPromptHint();
248
+ promptHistoryDraftChangeRef.current = true;
249
+ return nextValue;
250
+ }, [recentPromptHistory, resetPromptHistoryNav, clearPromptHint]);
251
+
252
+ // ESC / Up handling (prompt input):
253
+ // - prompt-local overlays such as the slash palette close first.
254
+ // - queued editable messages pop back into the prompt before clear/interrupt.
255
+ // - non-empty prompt text is cleared by PromptInput and must never interrupt
256
+ // the active turn on the same Esc press.
257
+ // - empty prompt + active turn interrupts the active turn.
258
+ const handlePromptEscape = useCallback((text = '', meta = {}) => {
259
+ // Recording takes priority over every other Esc branch (usage/context
260
+ // panels, slash-clear, queue-restore, turn-interrupt): a live mic capture
261
+ // must never silently keep running because Esc was consumed by something
262
+ // else first. Only consumes Esc while actually RECORDING — transcribing
263
+ // (already stopped, awaiting the HTTP round-trip) and idle fall through
264
+ // to the existing branches unchanged.
265
+ if (getRecorderState() === 'recording') {
266
+ cancelRecording();
267
+ setVoiceStatusHint('', 'info');
268
+ setVoiceRecPhase('idle');
269
+ store.pushNotice('Voice: recording cancelled', 'plain');
270
+ return true;
271
+ }
272
+ if (usagePanel) { closeUsagePanel(); return true; }
273
+ if (contextPanel) { setContextPanel(null); return true; }
274
+
275
+ if (meta.phase === 'clear') {
276
+ clearPastedImagesSnapshot();
277
+ clearPromptHint();
278
+ return false;
279
+ }
280
+ if (meta.phase === 'empty') {
281
+ return restoreQueuedToPrompt({ restoreDraft: true, showHint: false, currentText: text });
282
+ }
283
+ // Idle + empty + nothing to restore: nothing (double-press from empty
284
+ // opens message selector, but we don't have that feature yet).
285
+ return false;
286
+ }, [contextPanel, usagePanel, closeUsagePanel, restoreQueuedToPrompt, clearPromptHint, clearPastedImagesSnapshot, setVoiceStatusHint, store]);
287
+
288
+ const handlePromptInterrupt = useCallback((currentText = '') => {
289
+ const result = store.abort?.();
290
+ if (result?.aborted === false) return undefined;
291
+ if (result?.pastedImages) installPastedImages(result.pastedImages, { merge: true });
292
+ if (result?.discardPastedImages) clearPastedImagesSnapshot(result.discardPastedImages);
293
+ if (result?.pastedTexts) installPastedTexts(result.pastedTexts, { merge: true });
294
+ if (result?.discardPastedTexts) clearPastedTextsSnapshot(result.discardPastedTexts);
295
+ const restoreText = String(result?.restoreText || '').trim();
296
+ if (!restoreText) return undefined;
297
+ const existingText = String(currentText || '').trim();
298
+ const nextText = [restoreText, existingText].filter(Boolean).join('\n');
299
+ clearPromptHint();
300
+ return nextText;
301
+ }, [store, clearPromptHint, installPastedImages, clearPastedImagesSnapshot]);
302
+
303
+ return {
304
+ handleVoiceToggle,
305
+ handlePromptPaste,
306
+ handlePromptHistoryNavigate,
307
+ handlePromptEscape,
308
+ handlePromptInterrupt,
309
+ };
310
+ }