mixdog 0.9.2 → 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 (417) hide show
  1. package/package.json +8 -3
  2. package/scripts/anthropic-maxtokens-test.mjs +119 -0
  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/review-tasks.json +20 -0
  7. package/scripts/bench/round-codex.json +114 -0
  8. package/scripts/bench/round-mixdog-lead-r3.json +269 -0
  9. package/scripts/bench/round-mixdog-lead.json +269 -0
  10. package/scripts/bench/round-mixdog.json +126 -0
  11. package/scripts/bench/round-r10-bigsample.json +679 -0
  12. package/scripts/bench/round-r11-codexalign.json +257 -0
  13. package/scripts/bench/round-r4-codex.json +114 -0
  14. package/scripts/bench/round-r4-mixed.json +225 -0
  15. package/scripts/bench/round-r5-gpt-lead.json +259 -0
  16. package/scripts/bench/round-r6-codex.json +114 -0
  17. package/scripts/bench/round-r6-solo.json +257 -0
  18. package/scripts/bench/round-r7-full.json +254 -0
  19. package/scripts/bench/round-r8-fulldefault.json +255 -0
  20. package/scripts/bench-run.mjs +215 -29
  21. package/scripts/build-tui.mjs +13 -1
  22. package/scripts/explore-bench.mjs +124 -0
  23. package/scripts/freevar-smoke.mjs +95 -0
  24. package/scripts/hook-bus-test.mjs +191 -0
  25. package/scripts/internal-comms-bench.mjs +1 -0
  26. package/scripts/internal-comms-smoke.mjs +10 -9
  27. package/scripts/mouse-probe.mjs +45 -0
  28. package/scripts/output-style-bench.mjs +13 -6
  29. package/scripts/output-style-smoke.mjs +4 -4
  30. package/scripts/path-suffix-test.mjs +57 -0
  31. package/scripts/provider-toolcall-test.mjs +7 -3
  32. package/scripts/recall-bench.mjs +207 -0
  33. package/scripts/recall-usecase-cases.json +18 -0
  34. package/scripts/recall-usecase-probe.json +6 -0
  35. package/scripts/session-bench.mjs +152 -6
  36. package/scripts/tool-smoke.mjs +30 -67
  37. package/scripts/tui-render-smoke.mjs +90 -0
  38. package/scripts/webhook-smoke.mjs +208 -0
  39. package/src/agents/debugger/AGENT.md +5 -2
  40. package/src/agents/heavy-worker/AGENT.md +21 -11
  41. package/src/agents/maintainer/AGENT.md +4 -0
  42. package/src/agents/reviewer/AGENT.md +3 -2
  43. package/src/agents/worker/AGENT.md +21 -11
  44. package/src/lib/rules-builder.cjs +4 -0
  45. package/src/mixdog-session-runtime.mjs +933 -3731
  46. package/src/output-styles/default.md +34 -9
  47. package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
  48. package/src/output-styles/minimal.md +4 -1
  49. package/src/output-styles/simple.md +22 -7
  50. package/src/repl.mjs +5 -5
  51. package/src/rules/agent/00-common.md +2 -0
  52. package/src/rules/agent/30-explorer.md +8 -11
  53. package/src/rules/lead/lead-brief.md +12 -0
  54. package/src/rules/lead/lead-tool.md +2 -9
  55. package/src/rules/shared/01-tool.md +11 -5
  56. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
  57. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
  58. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
  59. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
  60. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
  61. package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
  62. package/src/runtime/agent/orchestrator/config.mjs +69 -2
  63. package/src/runtime/agent/orchestrator/context/collect.mjs +51 -0
  64. package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
  65. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +63 -21
  66. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
  67. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
  69. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +97 -1343
  70. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
  71. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +78 -10
  72. package/src/runtime/agent/orchestrator/providers/api-usage.mjs +1 -13
  73. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
  74. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
  75. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
  76. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
  77. package/src/runtime/agent/orchestrator/providers/gemini.mjs +44 -1014
  78. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +18 -4
  79. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
  80. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +86 -11
  81. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +348 -0
  82. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
  83. package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
  84. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +19 -12
  85. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
  86. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
  88. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +41 -1142
  89. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +732 -0
  90. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
  91. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +303 -2119
  92. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +140 -995
  93. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +227 -0
  94. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
  95. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +436 -0
  96. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
  97. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
  98. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +38 -12
  99. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +7 -8
  100. package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
  101. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
  102. package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
  103. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
  104. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
  105. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
  106. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
  107. package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
  108. package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
  109. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +274 -0
  110. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
  111. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
  112. package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
  113. package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
  114. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +47 -0
  115. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +182 -0
  116. package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
  117. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
  118. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
  119. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
  120. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
  121. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
  122. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
  123. package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
  124. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
  125. package/src/runtime/agent/orchestrator/session/loop.mjs +409 -1304
  126. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
  127. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +230 -0
  128. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
  129. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +149 -0
  130. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
  131. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
  132. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
  133. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
  134. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
  135. package/src/runtime/agent/orchestrator/session/manager.mjs +226 -2114
  136. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
  137. package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
  138. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -3
  139. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
  140. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
  141. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +33 -42
  142. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
  143. package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
  144. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
  145. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
  146. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +1 -1
  147. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
  148. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
  149. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
  150. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
  151. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -87
  152. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
  153. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
  154. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +78 -304
  155. package/src/runtime/agent/orchestrator/tools/builtin.mjs +11 -6
  156. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
  157. package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
  158. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
  159. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +551 -0
  160. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
  161. package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
  162. package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
  163. package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
  164. package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
  165. package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
  166. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1080 -0
  167. package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
  168. package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
  169. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
  170. package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
  171. package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
  172. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
  173. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +36 -4277
  174. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
  175. package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
  176. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
  177. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
  178. package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
  179. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
  180. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
  181. package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
  182. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
  183. package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
  184. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -23
  185. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +10 -74
  186. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
  187. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
  188. package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
  189. package/src/runtime/channels/backends/discord-access.mjs +32 -0
  190. package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
  191. package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
  192. package/src/runtime/channels/backends/discord.mjs +12 -292
  193. package/src/runtime/channels/index.mjs +241 -894
  194. package/src/runtime/channels/lib/backend-dispatch.mjs +44 -0
  195. package/src/runtime/channels/lib/boot-profile.mjs +23 -0
  196. package/src/runtime/channels/lib/crash-log.mjs +106 -0
  197. package/src/runtime/channels/lib/event-pipeline.mjs +18 -1
  198. package/src/runtime/channels/lib/event-queue.mjs +63 -4
  199. package/src/runtime/channels/lib/inbound-routing.mjs +111 -0
  200. package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
  201. package/src/runtime/channels/lib/output-forwarder.mjs +9 -1
  202. package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
  203. package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
  204. package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
  205. package/src/runtime/channels/lib/session-discovery.mjs +56 -4
  206. package/src/runtime/channels/lib/telegram-format.mjs +19 -22
  207. package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
  208. package/src/runtime/channels/lib/tool-format.mjs +1 -1
  209. package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
  210. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
  211. package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
  212. package/src/runtime/channels/lib/webhook/deliveries.mjs +312 -0
  213. package/src/runtime/channels/lib/webhook/log.mjs +42 -0
  214. package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
  215. package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
  216. package/src/runtime/channels/lib/webhook.mjs +36 -570
  217. package/src/runtime/channels/lib/whisper-language.mjs +42 -0
  218. package/src/runtime/channels/tool-defs.mjs +11 -130
  219. package/src/runtime/memory/index.mjs +258 -2050
  220. package/src/runtime/memory/lib/core-memory-store.mjs +351 -1
  221. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
  222. package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
  223. package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
  224. package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
  225. package/src/runtime/memory/lib/http-wire.mjs +57 -0
  226. package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
  227. package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
  228. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
  229. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
  230. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
  231. package/src/runtime/memory/lib/memory-cycle2.mjs +72 -837
  232. package/src/runtime/memory/lib/memory-embed.mjs +149 -0
  233. package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
  234. package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
  235. package/src/runtime/memory/lib/memory-recall-store.mjs +22 -2
  236. package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
  237. package/src/runtime/memory/lib/memory.mjs +20 -0
  238. package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
  239. package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
  240. package/src/runtime/memory/lib/query-handlers.mjs +780 -0
  241. package/src/runtime/memory/lib/recall-format.mjs +238 -0
  242. package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
  243. package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
  244. package/src/runtime/memory/tool-defs.mjs +6 -14
  245. package/src/runtime/search/lib/http-fetch.mjs +274 -0
  246. package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
  247. package/src/runtime/search/lib/web-tools.mjs +24 -602
  248. package/src/runtime/shared/abort-controller.mjs +1 -1
  249. package/src/runtime/shared/atomic-file.mjs +26 -1
  250. package/src/runtime/shared/background-tasks.mjs +2 -3
  251. package/src/runtime/shared/buffered-appender.mjs +149 -0
  252. package/src/runtime/shared/launcher-control.mjs +2 -2
  253. package/src/runtime/shared/task-notification-envelope.mjs +98 -0
  254. package/src/runtime/shared/tool-execution-contract.mjs +2 -2
  255. package/src/runtime/shared/tool-primitives.mjs +308 -0
  256. package/src/runtime/shared/tool-result-summary.mjs +515 -0
  257. package/src/runtime/shared/tool-surface.mjs +80 -898
  258. package/src/runtime/shared/transcript-writer.mjs +52 -2
  259. package/src/runtime/shared/update-checker.mjs +7 -4
  260. package/src/session-runtime/config-helpers.mjs +291 -0
  261. package/src/session-runtime/config-lifecycle.mjs +232 -0
  262. package/src/session-runtime/cwd-plugins.mjs +226 -0
  263. package/src/session-runtime/effort.mjs +128 -0
  264. package/src/session-runtime/fs-utils.mjs +10 -0
  265. package/src/session-runtime/mcp-glue.mjs +177 -0
  266. package/src/session-runtime/model-capabilities.mjs +130 -0
  267. package/src/session-runtime/model-recency.mjs +111 -0
  268. package/src/session-runtime/native-search.mjs +247 -0
  269. package/src/session-runtime/output-styles.mjs +126 -0
  270. package/src/session-runtime/plugin-mcp.mjs +114 -0
  271. package/src/session-runtime/prewarm.mjs +142 -0
  272. package/src/session-runtime/provider-models.mjs +278 -0
  273. package/src/session-runtime/provider-usage.mjs +120 -0
  274. package/src/session-runtime/quick-model-rows.mjs +170 -0
  275. package/src/session-runtime/quick-search-models.mjs +46 -0
  276. package/src/session-runtime/session-hooks.mjs +93 -0
  277. package/src/session-runtime/session-text.mjs +100 -0
  278. package/src/session-runtime/settings-api.mjs +319 -0
  279. package/src/session-runtime/statusline-route.mjs +35 -0
  280. package/src/session-runtime/tool-catalog.mjs +720 -0
  281. package/src/session-runtime/tool-defs.mjs +84 -0
  282. package/src/session-runtime/warmup-schedulers.mjs +201 -0
  283. package/src/session-runtime/workflow.mjs +358 -0
  284. package/src/standalone/agent-tool/helpers.mjs +237 -0
  285. package/src/standalone/agent-tool/notify.mjs +107 -0
  286. package/src/standalone/agent-tool/provider-init.mjs +143 -0
  287. package/src/standalone/agent-tool/render.mjs +152 -0
  288. package/src/standalone/agent-tool/tool-def.mjs +55 -0
  289. package/src/standalone/agent-tool.mjs +155 -677
  290. package/src/standalone/channel-worker.mjs +7 -9
  291. package/src/standalone/explore-tool.mjs +40 -12
  292. package/src/standalone/hook-bus/config.mjs +207 -0
  293. package/src/standalone/hook-bus/constants.mjs +90 -0
  294. package/src/standalone/hook-bus/handlers.mjs +481 -0
  295. package/src/standalone/hook-bus/payload.mjs +31 -0
  296. package/src/standalone/hook-bus/rules.mjs +77 -0
  297. package/src/standalone/hook-bus.mjs +110 -746
  298. package/src/standalone/memory-runtime-proxy.mjs +7 -0
  299. package/src/standalone/opencode-go-login.mjs +125 -0
  300. package/src/standalone/provider-admin.mjs +15 -19
  301. package/src/standalone/usage-dashboard.mjs +3 -1
  302. package/src/tui/App.jsx +1163 -7571
  303. package/src/tui/app/app-format.mjs +206 -0
  304. package/src/tui/app/channel-pickers.mjs +510 -0
  305. package/src/tui/app/clipboard.mjs +67 -0
  306. package/src/tui/app/core-memory-picker.mjs +210 -0
  307. package/src/tui/app/extension-pickers.mjs +506 -0
  308. package/src/tui/app/input-parsers.mjs +193 -0
  309. package/src/tui/app/maintenance-pickers.mjs +324 -0
  310. package/src/tui/app/model-options.mjs +330 -0
  311. package/src/tui/app/model-picker.mjs +365 -0
  312. package/src/tui/app/onboarding-steps.mjs +400 -0
  313. package/src/tui/app/project-picker.mjs +247 -0
  314. package/src/tui/app/provider-setup-picker.mjs +580 -0
  315. package/src/tui/app/resume-picker.mjs +55 -0
  316. package/src/tui/app/route-pickers.mjs +419 -0
  317. package/src/tui/app/settings-picker.mjs +490 -0
  318. package/src/tui/app/slash-commands.mjs +101 -0
  319. package/src/tui/app/slash-dispatch.mjs +427 -0
  320. package/src/tui/app/text-layout.mjs +46 -0
  321. package/src/tui/app/theme-effort-pickers.mjs +154 -0
  322. package/src/tui/app/transcript-window.mjs +671 -0
  323. package/src/tui/app/use-mouse-input.mjs +460 -0
  324. package/src/tui/app/use-prompt-handlers.mjs +310 -0
  325. package/src/tui/app/use-transcript-scroll.mjs +510 -0
  326. package/src/tui/app/use-transcript-window.mjs +589 -0
  327. package/src/tui/components/ConfirmBar.jsx +1 -1
  328. package/src/tui/components/Picker.jsx +32 -4
  329. package/src/tui/components/PromptInput.jsx +259 -80
  330. package/src/tui/components/SlashCommandPalette.jsx +8 -1
  331. package/src/tui/components/StatusLine.jsx +63 -12
  332. package/src/tui/components/TextEntryPanel.jsx +11 -0
  333. package/src/tui/components/ToolExecution.jsx +56 -588
  334. package/src/tui/components/TranscriptItem.jsx +105 -0
  335. package/src/tui/components/UsagePanel.jsx +18 -4
  336. package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
  337. package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
  338. package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
  339. package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
  340. package/src/tui/components/tool-execution/text-format.mjs +161 -0
  341. package/src/tui/components/tool-output-format.mjs +2 -2
  342. package/src/tui/display-width.mjs +20 -3
  343. package/src/tui/dist/index.mjs +18034 -17188
  344. package/src/tui/engine/agent-envelope.mjs +296 -0
  345. package/src/tui/engine/agent-job-feed.mjs +133 -0
  346. package/src/tui/engine/boot-profile.mjs +21 -0
  347. package/src/tui/engine/labels.mjs +67 -0
  348. package/src/tui/engine/notice-text.mjs +112 -0
  349. package/src/tui/engine/notification-plan.mjs +76 -0
  350. package/src/tui/engine/queue-helpers.mjs +161 -0
  351. package/src/tui/engine/render-timing.mjs +17 -0
  352. package/src/tui/engine/session-stats.mjs +46 -0
  353. package/src/tui/engine/tool-approval.mjs +94 -0
  354. package/src/tui/engine/tool-call-fields.mjs +23 -0
  355. package/src/tui/engine/tool-card-results.mjs +234 -0
  356. package/src/tui/engine/tool-result-status.mjs +135 -0
  357. package/src/tui/engine/tool-result-text.mjs +126 -0
  358. package/src/tui/engine.mjs +405 -1385
  359. package/src/tui/figures.mjs +5 -0
  360. package/src/tui/index.jsx +105 -0
  361. package/src/tui/input-editing.mjs +60 -10
  362. package/src/tui/keyboard-protocol.mjs +2 -2
  363. package/src/tui/lib/voice-recorder.mjs +35 -19
  364. package/src/tui/markdown/format-token.mjs +11 -9
  365. package/src/tui/paste-attachments.mjs +38 -0
  366. package/src/tui/statusline-ansi-bridge.mjs +11 -3
  367. package/src/tui/theme.mjs +6 -0
  368. package/src/tui/themes/base.mjs +2 -2
  369. package/src/tui/themes/kanagawa.mjs +4 -4
  370. package/src/tui/themes/teal.mjs +4 -5
  371. package/src/tui/themes/utils.mjs +1 -1
  372. package/src/ui/statusline-agents.mjs +213 -0
  373. package/src/ui/statusline-format.mjs +146 -0
  374. package/src/ui/statusline-segments.mjs +148 -0
  375. package/src/ui/statusline.mjs +77 -462
  376. package/src/ui/tool-card.mjs +0 -1
  377. package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
  378. package/src/workflows/default/WORKFLOW.md +16 -9
  379. package/src/workflows/sequential/WORKFLOW.md +16 -11
  380. package/src/workflows/solo/WORKFLOW.md +5 -1
  381. package/vendor/ink/build/display-width.js +19 -3
  382. package/vendor/ink/build/ink.js +103 -6
  383. package/vendor/ink/build/log-update.js +17 -3
  384. package/vendor/ink/build/wrap-text.js +125 -0
  385. package/scripts/_test-folder-dialog.mjs +0 -30
  386. package/scripts/fix-brief-fn.mjs +0 -35
  387. package/scripts/fix-format-tool-surface.mjs +0 -24
  388. package/scripts/fix-tool-exec-visible.mjs +0 -42
  389. package/scripts/patch-agent-brief.mjs +0 -48
  390. package/scripts/patch-app.mjs +0 -21
  391. package/scripts/patch-app2.mjs +0 -18
  392. package/scripts/patch-dist-brief.mjs +0 -96
  393. package/scripts/patch-tool-exec.mjs +0 -70
  394. package/src/examples/schedules/SCHEDULE.example.md +0 -32
  395. package/src/examples/webhooks/WEBHOOK.example.md +0 -40
  396. package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
  397. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
  398. package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
  399. package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
  400. package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
  401. package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
  402. package/src/standalone/agent-task-status.test.mjs +0 -76
  403. package/src/tui/components/tool-output-format.test.mjs +0 -399
  404. package/src/tui/display-width.test.mjs +0 -35
  405. package/src/tui/engine-runtime-notification.test.mjs +0 -115
  406. package/src/tui/engine-tool-result-text.test.mjs +0 -75
  407. package/src/tui/markdown/format-token.test.mjs +0 -354
  408. package/src/tui/markdown/render-ansi.test.mjs +0 -108
  409. package/src/tui/markdown/stream-fence.test.mjs +0 -26
  410. package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
  411. package/src/tui/prompt-history-store.test.mjs +0 -52
  412. package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
  413. package/src/tui/transcript-tool-failures.test.mjs +0 -111
  414. package/src/ui/markdown.test.mjs +0 -70
  415. package/src/ui/statusline-context-label.test.mjs +0 -15
  416. package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
  417. package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
@@ -0,0 +1,105 @@
1
+ /**
2
+ * TranscriptItem.jsx — per-item transcript renderer (Item) + the hook-denial
3
+ * tool card. Extracted verbatim from App.jsx.
4
+ */
5
+ import React from 'react';
6
+ import { Box, Text } from 'ink';
7
+ import stringWidth from 'string-width';
8
+ import stripAnsi from 'strip-ansi';
9
+ import { theme, TURN_MARKER, RESULT_GUTTER } from '../theme.mjs';
10
+ import { AssistantMessage, UserMessage, NoticeMessage } from './Message.jsx';
11
+ import { ToolExecution } from './ToolExecution.jsx';
12
+ import { StatusDone, TurnDone } from './TurnDone.jsx';
13
+ import { ItemRightHintOverprint } from './ItemRightHintOverprint.jsx';
14
+ import { formatToolSurface } from '../../runtime/shared/tool-surface.mjs';
15
+ import {
16
+ formatHookDenialDetail,
17
+ isHookApprovalDenialToolItem,
18
+ shouldSuppressFullyFailedToolItem,
19
+ toolItemResultText,
20
+ } from '../transcript-tool-failures.mjs';
21
+
22
+ export function ToolHookDenialCard({ item, columns = 80 }) {
23
+ const { label, summary } = formatToolSurface(item.name, item.args);
24
+ const detail = formatHookDenialDetail(toolItemResultText(item));
25
+ const safeLabel = stripAnsi(String(label || '')).replace(/[\u0000-\u001F\u007F]/g, ' ').replace(/\s+/g, ' ').trim();
26
+ const safeSummary = stripAnsi(String(summary || '')).replace(/[\u0000-\u001F\u007F]/g, ' ').replace(/\s+/g, ' ').trim();
27
+ const safeDetail = stripAnsi(String(detail || '')).replace(/[\u0000-\u001F\u007F]/g, ' ').replace(/\s+/g, ' ').trim();
28
+ const summaryText = safeSummary ? ` (${safeSummary})` : '';
29
+ const rowWidth = Math.max(1, Number(columns || 80));
30
+ const detailWidth = Math.max(1, rowWidth - stringWidth(RESULT_GUTTER));
31
+ return (
32
+ <Box flexDirection="column" marginTop={1} width={rowWidth} overflow="hidden">
33
+ <Box flexDirection="row" width={rowWidth} overflow="hidden">
34
+ <Box flexShrink={0} minWidth={2}>
35
+ <Text color={theme.error}>{TURN_MARKER}</Text>
36
+ </Box>
37
+ <Box flexGrow={1} flexShrink={1} overflow="hidden" minWidth={0}>
38
+ <Text wrap="truncate">
39
+ <Text bold color={theme.text}>{safeLabel}</Text>
40
+ {summaryText ? <Text color={theme.text}>{summaryText}</Text> : null}
41
+ <Text color={theme.error}> · Denied</Text>
42
+ </Text>
43
+ </Box>
44
+ </Box>
45
+ {safeDetail ? (
46
+ <Box flexDirection="row" width={rowWidth} overflow="hidden">
47
+ <Box flexShrink={0} width={stringWidth(RESULT_GUTTER)}>
48
+ <Text color={theme.subtle}>{RESULT_GUTTER}</Text>
49
+ </Box>
50
+ <Box flexShrink={0} width={detailWidth} overflow="hidden">
51
+ <Text color={theme.error} wrap="truncate">{safeDetail}</Text>
52
+ </Box>
53
+ </Box>
54
+ ) : null}
55
+ </Box>
56
+ );
57
+ }
58
+
59
+ // `themeEpoch` is read but not used in the body: it is a memo-busting prop. The
60
+ // active theme mutates `theme` in-place, so a switch must force every mounted
61
+ // transcript row (which reads theme.* directly) to re-render. Threading the
62
+ // epoch through Item → AssistantMessage/UserMessage/ToolExecution breaks
63
+ // React.memo's shallow equality on a theme change without a broad refactor.
64
+ export const Item = React.memo(function Item({ item, prevKind, columns, toolOutputExpanded, rightMessage = '', rightTone = 'info', rightMessageWidth = 24, themeEpoch = 0 }) {
65
+ const hintOnTurnDoneRow = item.kind === 'turndone' || item.kind === 'statusdone';
66
+ let node = null;
67
+ switch (item.kind) {
68
+ case 'user':
69
+ node = <UserMessage text={item.text} attached={prevKind === 'user'} columns={columns} themeEpoch={themeEpoch} />;
70
+ break;
71
+ case 'assistant':
72
+ node = <AssistantMessage text={item.text} streaming={item.streaming} columns={columns} themeEpoch={themeEpoch} assistantId={item.id} />;
73
+ break;
74
+ case 'tool': {
75
+ if (shouldSuppressFullyFailedToolItem(item)) return null;
76
+ if (isHookApprovalDenialToolItem(item)) {
77
+ node = <ToolHookDenialCard item={item} columns={columns} />;
78
+ break;
79
+ }
80
+ node = <ToolExecution name={item.name} args={item.args} result={item.result} rawResult={item.rawResult} isError={item.isError} errorCount={item.errorCount} expanded={toolOutputExpanded || item.expanded} columns={columns} attached={false} count={item.count} completedCount={item.completedCount} startedAt={item.startedAt} completedAt={item.completedAt} aggregate={item.aggregate} categories={item.categories} headerFinalized={item.headerFinalized} deferredDisplayReady={item.deferredDisplayReady} themeEpoch={themeEpoch} />;
81
+ break;
82
+ }
83
+ case 'notice':
84
+ node = <NoticeMessage text={item.text} tone={item.tone} columns={columns} />;
85
+ break;
86
+ case 'turndone':
87
+ node = <TurnDone elapsedMs={item.elapsedMs} status={item.status} outputTokens={item.outputTokens} thinkingElapsedMs={item.thinkingElapsedMs} verb={item.verb} rightMessage={rightMessage} rightTone={rightTone} rightMessageWidth={rightMessageWidth} />;
88
+ break;
89
+ case 'statusdone':
90
+ node = <StatusDone label={item.label} detail={item.detail} rightMessage={rightMessage} rightTone={rightTone} rightMessageWidth={rightMessageWidth} />;
91
+ break;
92
+ default:
93
+ return null;
94
+ }
95
+ if (!node || hintOnTurnDoneRow || !rightMessage) return node;
96
+ return (
97
+ <ItemRightHintOverprint
98
+ rightMessage={rightMessage}
99
+ rightTone={rightTone}
100
+ rightMessageWidth={rightMessageWidth}
101
+ >
102
+ {node}
103
+ </ItemRightHintOverprint>
104
+ );
105
+ });
@@ -108,6 +108,12 @@ function windowValue(w) {
108
108
  const limitCredits = Number(w?.limitCredits);
109
109
  const usedPct = Number(w?.usedPct);
110
110
  const prefix = estimated ? 'est ' : '';
111
+ // Percent first: windows that carry usedPct (OAuth quotas, OpenCode Go
112
+ // console) all render as "5H 17%" so provider rows stay uniform; dollar
113
+ // remaining is the fallback for billing-style windows without a percent.
114
+ if (hasFiniteNumber(w?.usedPct)) {
115
+ return { text: `${prefix}${Math.round(usedPct)}%`, color: estimated ? theme.warning : pctColor(usedPct) };
116
+ }
111
117
  if (hasFiniteNumber(w?.remainingUsd)) {
112
118
  return { text: `${prefix}${money(remainingUsd)}`, color: estimated ? theme.warning : remainingUsdColor(remainingUsd) };
113
119
  }
@@ -123,9 +129,6 @@ function windowValue(w) {
123
129
  if (hasFiniteNumber(w?.usedCredits) && hasFiniteNumber(w?.limitCredits)) {
124
130
  return { text: `${prefix}${compactNumber(usedCredits)}/${compactNumber(limitCredits)}`, color: estimated ? theme.warning : creditsColor(w) };
125
131
  }
126
- if (hasFiniteNumber(w?.usedPct)) {
127
- return { text: `${prefix}${Math.round(usedPct)}%`, color: estimated ? theme.warning : pctColor(usedPct) };
128
- }
129
132
  return { text: '', color: theme.subtle };
130
133
  }
131
134
 
@@ -171,7 +174,15 @@ function rowStatusParts(row, columns = 80, statusWidth = 0) {
171
174
  const showCredit = hasCredit && (columns >= 80 || windows.length === 0);
172
175
  if (windows.length || showCredit) {
173
176
  const maxWindows = windows.length ? maxStatusWindows(columns, statusWidth, showCredit) : 0;
174
- const visibleWindows = windows.slice(0, maxWindows);
177
+ let visibleWindows = windows.slice(0, maxWindows);
178
+ if (windows.length > maxWindows && maxWindows > 0) {
179
+ // Don't let an actively-used window (e.g. monthly at 17%) get cut in
180
+ // favor of idle 0% windows; keep the top-usage windows in list order.
181
+ const ranked = [...windows]
182
+ .sort((a, b) => (Number(b?.usedPct) || 0) - (Number(a?.usedPct) || 0))
183
+ .slice(0, maxWindows);
184
+ visibleWindows = windows.filter((w) => ranked.includes(w));
185
+ }
175
186
  for (const window of visibleWindows) {
176
187
  pushStatusSeparator(parts);
177
188
  parts.push(...windowSegmentParts(window));
@@ -186,6 +197,9 @@ function rowStatusParts(row, columns = 80, statusWidth = 0) {
186
197
  case 'checking':
187
198
  return [{ text: 'checking...', color: theme.inactive }];
188
199
  case 'hidden':
200
+ // Provider balance can't be accurately refreshed (no/failed balance
201
+ // API): show an explicit "-" placeholder instead of a blank cell.
202
+ return [{ text: row?.primary || '-', color: theme.inactive }];
189
203
  case 'missing':
190
204
  case 'local':
191
205
  case 'error':
@@ -0,0 +1,72 @@
1
+ /**
2
+ * components/prompt-input/edit-helpers.mjs — pure prompt-editor helpers (no
3
+ * React): hint styling, insert/draft-compare, pasted-text normalization, and
4
+ * modified-Enter (kitty / modifyOtherKeys) sequence recognition. Extracted
5
+ * verbatim from PromptInput.jsx — behavior unchanged.
6
+ */
7
+ import { theme } from '../../theme.mjs';
8
+ import { replaceSelection } from '../../input-editing.mjs';
9
+
10
+ export function hintStyle(tone) {
11
+ if (tone === 'error') return { textColor: theme.error };
12
+ if (tone === 'warn' || tone === 'cancel') return { textColor: theme.warning };
13
+ if (tone === 'plain') return { textColor: theme.subtle };
14
+ return { textColor: theme.inactive };
15
+ }
16
+
17
+ export function insertText(draft, input) {
18
+ if (!input) return draft;
19
+ return replaceSelection(draft, input);
20
+ }
21
+
22
+ export function normalizePastedText(text) {
23
+ return String(text ?? '').replace(/\r\n?/g, '\n');
24
+ }
25
+
26
+ export function singleTrailingLineBreakPrefix(text) {
27
+ const normalized = normalizePastedText(text);
28
+ if (!normalized.endsWith('\n')) return null;
29
+ const prefix = normalized.slice(0, -1);
30
+ return prefix.includes('\n') ? null : prefix;
31
+ }
32
+
33
+ export function draftStateEqual(a, b) {
34
+ return (
35
+ a.value === b.value
36
+ && a.cursor === b.cursor
37
+ && a.selectionAnchor === b.selectionAnchor
38
+ );
39
+ }
40
+
41
+ // Recognize a MODIFIED Enter delivered via the kitty keyboard protocol
42
+ // (\x1b[13;<mod>u) or modifyOtherKeys (\x1b[27;<mod>;13~). The xterm modifier
43
+ // param is (1 + bitmask) where the bitmask bits are shift=1, alt=2, ctrl=4. We
44
+ // treat Ctrl+Enter AND Shift+Enter (the two common "insert newline" chords) as a
45
+ // newline, so we match when the shift OR ctrl bit is set. Ctrl+J is handled
46
+ // separately as the protocol-independent fallback.
47
+ const MODIFIED_ENTER_SHIFT_OR_CTRL = 1 | 4;
48
+
49
+ export function isModifiedEnterSequence(input) {
50
+ const text = String(input ?? '');
51
+ const body = text.startsWith('\x1b[') ? text.slice(2) : text.startsWith('[') ? text.slice(1) : '';
52
+ if (!body) return false;
53
+ const kitty = /^13;(\d+)(?::\d+)?(?:;[\d:]+)?u$/.exec(body);
54
+ if (kitty) return ((Number(kitty[1]) - 1) & MODIFIED_ENTER_SHIFT_OR_CTRL) !== 0;
55
+ const modifyOtherKeys = /^27;(\d+);13~$/.exec(body);
56
+ return Boolean(modifyOtherKeys && (((Number(modifyOtherKeys[1]) - 1) & MODIFIED_ENTER_SHIFT_OR_CTRL) !== 0));
57
+ }
58
+
59
+ // Recognize ANY modified Enter (any modifier bitmask, e.g. Alt+Enter \x1b[13;3u
60
+ // / \x1b[27;3;13~). Used to CONSUME modified-Enter sequences we don't map to a
61
+ // newline (Alt-only, etc.) so they aren't typed into the prompt as raw CSI text
62
+ // under modifyOtherKeys. Plain Enter (mod param = 1, bitmask 0) is intentionally
63
+ // NOT matched, so it still submits.
64
+ export function isAnyModifiedEnterSequence(input) {
65
+ const text = String(input ?? '');
66
+ const body = text.startsWith('\x1b[') ? text.slice(2) : text.startsWith('[') ? text.slice(1) : '';
67
+ if (!body) return false;
68
+ const kitty = /^13;(\d+)(?::\d+)?(?:;[\d:]+)?u$/.exec(body);
69
+ if (kitty) return (Number(kitty[1]) - 1) !== 0;
70
+ const modifyOtherKeys = /^27;(\d+);13~$/.exec(body);
71
+ return Boolean(modifyOtherKeys && ((Number(modifyOtherKeys[1]) - 1) !== 0));
72
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * components/prompt-input/voice-indicator.mjs — voice-indicator glyph frames,
3
+ * timing constants, and frame-selection helper for the prompt box right edge.
4
+ * Pure (no React). Extracted verbatim from PromptInput.jsx — behavior unchanged.
5
+ */
6
+
7
+ // Monotone voice indicator glyphs — right end of the prompt box. All frames
8
+ // are 1-cell-wide (no emoji, no string-width special-casing needed). Modes:
9
+ // 'off' — voice disabled and no install in flight: renders nothing,
10
+ // zero reserved columns.
11
+ // 'installing' — voice-runtime download in progress (progressHint active):
12
+ // braille spinner only.
13
+ // 'idle' — voice enabled, recorder idle: a STATIC ○ glyph. No
14
+ // animation — an animated idle reads as "something is
15
+ // running" when nothing is, and the old pulse frames
16
+ // (◎ ◍ ◉ ◍) rendered as tofu/odd-width glyphs in common
17
+ // Windows Terminal fonts (◍ U+25CD especially).
18
+ // 'recording' — steady ● + a braille spinner riding next to it (2 cells).
19
+ // 'transcribing' — braille spinner only (recording just stopped, awaiting
20
+ // the whisper-server round-trip).
21
+ // A single ~120ms interval drives the braille cycle, and it only exists
22
+ // while an ANIMATED mode is active (installing/recording/transcribing) —
23
+ // 'idle' and 'off' need no timer at all.
24
+ export const VOICE_BRAILLE_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧'];
25
+ export const VOICE_IDLE_GLYPH = '○';
26
+ export const VOICE_TICK_MS = 120;
27
+
28
+ // Resolve the indicator glyph text for a given mode + animation tick. Returns
29
+ // '' (rendered as null / zero reserved columns) when the indicator is hidden.
30
+ export function voiceIndicatorTextFor(mode, tick) {
31
+ const voiceBrailleFrame = VOICE_BRAILLE_FRAMES[tick % VOICE_BRAILLE_FRAMES.length];
32
+ return mode === 'installing' || mode === 'transcribing'
33
+ ? voiceBrailleFrame
34
+ : mode === 'recording'
35
+ ? `●${voiceBrailleFrame}`
36
+ : mode === 'idle'
37
+ ? VOICE_IDLE_GLYPH
38
+ : '';
39
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * components/tool-execution/ResultBody.jsx — the multi-line result body under
3
+ * the ⎿ gutter (COLLAPSED fitted summary or EXPANDED raw). Extracted verbatim
4
+ * from ToolExecution.jsx — behavior unchanged.
5
+ */
6
+ import React from 'react';
7
+ import { Box, Text } from 'ink';
8
+ import { theme, RESULT_GUTTER, RESULT_GUTTER_CONT } from '../../theme.mjs';
9
+ import { formatExpandedResult, wrapExpandedResultLines } from '../tool-output-format.mjs';
10
+ import { deltaTextParts, fitResultLine } from './text-format.mjs';
11
+
12
+ export function renderDeltaText(text) {
13
+ return deltaTextParts(text).map((part, index) => (
14
+ part.color ? <Text key={index} color={part.color}>{part.text}</Text> : part.text
15
+ ));
16
+ }
17
+
18
+ // Shared multi-line result body: `└` on the first row, `│` continuation rail on
19
+ // every following row, body text in one flex column so wrapping stays aligned
20
+ // under the head gutter.
21
+ //
22
+ // Two render paths:
23
+ // - COLLAPSED (raw=false): a single fitted summary line, diff(+/-) colored via
24
+ // renderDeltaText.
25
+ // - EXPANDED (raw=true): formatExpandedResult then wrapExpandedResultLines so
26
+ // each physical row fits the body width before render (rail rows stay 1:1;
27
+ // ink does not re-wrap). Physical row mount cap: MIXDOG_TUI_TOOL_OUTPUT_MAX_RENDER_LINES
28
+ // (default 600; 0 disables). Shell/script bodies keep the newest tail when capped.
29
+ export function ResultBody({ lines, rawText, pathArg = '', isShell = false, columns, color, raw }) {
30
+ const renderLines = raw
31
+ ? wrapExpandedResultLines(
32
+ formatExpandedResult(rawText, { pathArg, isShell }),
33
+ columns,
34
+ { isShell },
35
+ )
36
+ : (lines || []);
37
+ if (!renderLines || renderLines.length === 0) return null;
38
+ return (
39
+ <Box flexDirection="row">
40
+ <Box flexShrink={0} flexDirection="column">
41
+ {renderLines.map((_, i) => (
42
+ <Text key={i} color={theme.subtle}>{i === 0 ? RESULT_GUTTER : RESULT_GUTTER_CONT}</Text>
43
+ ))}
44
+ </Box>
45
+ <Box flexDirection="column" flexShrink={1} flexGrow={1}>
46
+ {renderLines.map((line, i) => (
47
+ <Text key={i} color={raw ? undefined : color} wrap="truncate">
48
+ {raw
49
+ ? (line || ' ')
50
+ : renderDeltaText(fitResultLine(line || ' ', columns))}
51
+ </Text>
52
+ ))}
53
+ </Box>
54
+ </Box>
55
+ );
56
+ }