@oh-my-pi/pi-tui 18.2.4 → 18.2.6

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 (748) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +43 -0
  3. package/dist/types/app-keybindings.d.ts +395 -0
  4. package/dist/types/apps/autoresearch-dashboard.d.ts +43 -0
  5. package/dist/types/apps/autoresearch-data.d.ts +15 -0
  6. package/dist/types/apps/cleanse-board.d.ts +66 -0
  7. package/dist/types/apps/cleanse-picker.d.ts +23 -0
  8. package/dist/types/apps/debug/log-formatting.d.ts +6 -0
  9. package/dist/types/apps/debug/log-viewer.d.ts +81 -0
  10. package/dist/types/apps/debug/protocol-probe.d.ts +42 -0
  11. package/dist/types/apps/debug/raw-sse-buffer.d.ts +58 -0
  12. package/dist/types/apps/debug/raw-sse.d.ts +26 -0
  13. package/dist/types/apps/debug/terminal-info.d.ts +34 -0
  14. package/dist/types/apps/debug/viewer-frame.d.ts +52 -0
  15. package/dist/types/apps/git/avatar.d.ts +9 -0
  16. package/dist/types/apps/git/colors.d.ts +49 -0
  17. package/dist/types/apps/git/diff-pane.d.ts +188 -0
  18. package/dist/types/apps/git/git-tui.d.ts +66 -0
  19. package/dist/types/apps/git/sidebar.d.ts +149 -0
  20. package/dist/types/apps/git/state.d.ts +117 -0
  21. package/dist/types/apps/if-bench-board.d.ts +75 -0
  22. package/dist/types/apps/live-visualizer.d.ts +33 -0
  23. package/dist/types/apps/ps-data.d.ts +51 -0
  24. package/dist/types/apps/ps-top.d.ts +33 -0
  25. package/dist/types/apps/session-picker.d.ts +26 -0
  26. package/dist/types/apps/setup-model-picker.d.ts +13 -0
  27. package/dist/types/apps/standalone-picker.d.ts +42 -0
  28. package/dist/types/autocomplete.d.ts +4 -0
  29. package/dist/types/chat/advisor-message.d.ts +11 -0
  30. package/dist/types/chat/assistant-message.d.ts +106 -0
  31. package/dist/types/chat/background-tan-message.d.ts +9 -0
  32. package/dist/types/chat/bash-execution.d.ts +47 -0
  33. package/dist/types/chat/cache-invalidation-marker.d.ts +50 -0
  34. package/dist/types/chat/chat-transcript-builder.d.ts +50 -0
  35. package/dist/types/chat/collab-prompt-message.d.ts +10 -0
  36. package/dist/types/chat/compaction-summary-message.d.ts +54 -0
  37. package/dist/types/chat/custom-message.d.ts +10 -0
  38. package/dist/types/chat/display-preferences.d.ts +13 -0
  39. package/dist/types/chat/eval-execution.d.ts +29 -0
  40. package/dist/types/chat/execution-shared.d.ts +51 -0
  41. package/dist/types/chat/extension-types.d.ts +28 -0
  42. package/dist/types/chat/hook-message.d.ts +10 -0
  43. package/dist/types/chat/image-loading.d.ts +46 -0
  44. package/dist/types/chat/late-diagnostics-message.d.ts +21 -0
  45. package/dist/types/chat/messages.d.ts +189 -0
  46. package/dist/types/chat/reaction.d.ts +30 -0
  47. package/dist/types/chat/read-target.d.ts +4 -0
  48. package/dist/types/chat/read-tool-group.d.ts +67 -0
  49. package/dist/types/chat/served-model-marker.d.ts +47 -0
  50. package/dist/types/chat/skill-message.d.ts +33 -0
  51. package/dist/types/chat/skill-title-input.d.ts +14 -0
  52. package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +12 -0
  53. package/dist/types/chat/thinking-display.d.ts +12 -0
  54. package/dist/types/chat/todo-reminder.d.ts +13 -0
  55. package/dist/types/chat/tool-execution.d.ts +138 -0
  56. package/dist/types/chat/transcript-browser.d.ts +93 -0
  57. package/dist/types/chat/transcript-entry.d.ts +45 -0
  58. package/dist/types/chat/transcript-outline.d.ts +86 -0
  59. package/dist/types/chat/transcript-render-helpers.d.ts +92 -0
  60. package/dist/types/chat/ttsr-notification.d.ts +23 -0
  61. package/dist/types/chat/user-message.d.ts +52 -0
  62. package/dist/types/chrome/chat-block.d.ts +64 -0
  63. package/dist/types/chrome/collab-qrcode.d.ts +28 -0
  64. package/dist/types/chrome/context-thresholds.d.ts +10 -0
  65. package/dist/types/chrome/countdown-timer.d.ts +14 -0
  66. package/dist/types/chrome/diff.d.ts +14 -0
  67. package/dist/types/chrome/dynamic-border.d.ts +16 -0
  68. package/dist/types/chrome/error-block.d.ts +17 -0
  69. package/dist/types/chrome/form-theme.d.ts +3 -0
  70. package/dist/types/chrome/format.d.ts +12 -0
  71. package/dist/types/chrome/index.d.ts +20 -0
  72. package/dist/types/chrome/keybinding-hints.d.ts +40 -0
  73. package/dist/types/chrome/live-board.d.ts +23 -0
  74. package/dist/types/chrome/local-date.d.ts +4 -0
  75. package/dist/types/chrome/message-divider.d.ts +22 -0
  76. package/dist/types/chrome/message-frame.d.ts +52 -0
  77. package/dist/types/chrome/message-notice.d.ts +35 -0
  78. package/dist/types/chrome/overlay-box.d.ts +74 -0
  79. package/dist/types/chrome/qrcode.d.ts +48 -0
  80. package/dist/types/chrome/segment-track.d.ts +27 -0
  81. package/dist/types/chrome/select-list-mouse-routing.d.ts +4 -0
  82. package/dist/types/chrome/selector-helpers.d.ts +52 -0
  83. package/dist/types/chrome/shared.d.ts +5 -0
  84. package/dist/types/chrome/streaming-panel.d.ts +19 -0
  85. package/dist/types/chrome/tool-activity.d.ts +17 -0
  86. package/dist/types/chrome/transcript-container.d.ts +129 -0
  87. package/dist/types/chrome/transcript-status.d.ts +12 -0
  88. package/dist/types/chrome/visual-truncate.d.ts +19 -0
  89. package/dist/types/components/disclosure.d.ts +42 -0
  90. package/dist/types/components/form.d.ts +130 -0
  91. package/dist/types/components/key-value-list.d.ts +24 -0
  92. package/dist/types/components/layout/geometry.d.ts +73 -0
  93. package/dist/types/components/layout/row.d.ts +55 -0
  94. package/dist/types/components/layout/split-pane.d.ts +80 -0
  95. package/dist/types/components/layout/stack.d.ts +50 -0
  96. package/dist/types/components/menu-selection.d.ts +71 -0
  97. package/dist/types/components/metric.d.ts +44 -0
  98. package/dist/types/components/progress-bar.d.ts +36 -0
  99. package/dist/types/components/scroll-view.d.ts +53 -19
  100. package/dist/types/components/scroll-viewport.d.ts +46 -0
  101. package/dist/types/components/section.d.ts +19 -0
  102. package/dist/types/components/select-list.d.ts +46 -2
  103. package/dist/types/components/settings-list.d.ts +20 -0
  104. package/dist/types/components/table.d.ts +32 -0
  105. package/dist/types/components/tree-view.d.ts +130 -0
  106. package/dist/types/components/wizard-step.d.ts +60 -0
  107. package/dist/types/hotkeys-markdown.d.ts +7 -0
  108. package/dist/types/index.d.ts +17 -0
  109. package/dist/types/keybinding-matchers.d.ts +35 -0
  110. package/dist/types/keys.d.ts +2 -2
  111. package/dist/types/lang-from-path.d.ts +9 -0
  112. package/dist/types/overlays/advisor-config.d.ts +114 -0
  113. package/dist/types/overlays/agent-activity.d.ts +41 -0
  114. package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
  115. package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
  116. package/dist/types/overlays/agent-hub-types.d.ts +99 -0
  117. package/dist/types/overlays/agent-hub.d.ts +126 -0
  118. package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
  119. package/dist/types/overlays/agents-hub.d.ts +72 -0
  120. package/dist/types/overlays/ask-dialog.d.ts +88 -0
  121. package/dist/types/overlays/bordered-loader.d.ts +11 -0
  122. package/dist/types/overlays/btw-history-panel.d.ts +29 -0
  123. package/dist/types/overlays/btw-history.d.ts +17 -0
  124. package/dist/types/overlays/btw-panel.d.ts +26 -0
  125. package/dist/types/overlays/cleanse-panel.d.ts +36 -0
  126. package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
  127. package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
  128. package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
  129. package/dist/types/overlays/copy-selector.d.ts +48 -0
  130. package/dist/types/overlays/copy-targets.d.ts +63 -0
  131. package/dist/types/overlays/error-banner.d.ts +13 -0
  132. package/dist/types/overlays/extensions/display-text.d.ts +10 -0
  133. package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
  134. package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
  135. package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
  136. package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
  137. package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
  138. package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
  139. package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
  140. package/dist/types/overlays/extensions/types.d.ts +165 -0
  141. package/dist/types/overlays/history-search.d.ts +16 -0
  142. package/dist/types/overlays/hook-editor.d.ts +44 -0
  143. package/dist/types/overlays/hook-input.d.ts +20 -0
  144. package/dist/types/overlays/hook-selector.d.ts +71 -0
  145. package/dist/types/overlays/hub-frame.d.ts +77 -0
  146. package/dist/types/overlays/login-dialog.d.ts +43 -0
  147. package/dist/types/overlays/logout-account-selector.d.ts +15 -0
  148. package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
  149. package/dist/types/overlays/model-browser.d.ts +213 -0
  150. package/dist/types/overlays/model-hub.d.ts +72 -0
  151. package/dist/types/overlays/model-picker.d.ts +74 -0
  152. package/dist/types/overlays/model-selector.d.ts +52 -0
  153. package/dist/types/overlays/move-overlay.d.ts +39 -0
  154. package/dist/types/overlays/oauth-selector.d.ts +41 -0
  155. package/dist/types/overlays/omfg-panel.d.ts +20 -0
  156. package/dist/types/overlays/pause-screen.d.ts +43 -0
  157. package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
  158. package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
  159. package/dist/types/overlays/plan-toc.d.ts +41 -0
  160. package/dist/types/overlays/plugin-selector.d.ts +28 -0
  161. package/dist/types/overlays/plugin-settings.d.ts +180 -0
  162. package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
  163. package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
  164. package/dist/types/overlays/rewind-selector.d.ts +61 -0
  165. package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
  166. package/dist/types/overlays/session-account-selector.d.ts +24 -0
  167. package/dist/types/overlays/session-info-overlay.d.ts +17 -0
  168. package/dist/types/overlays/session-observer-registry.d.ts +77 -0
  169. package/dist/types/overlays/session-selector.d.ts +131 -0
  170. package/dist/types/overlays/settings-defs.d.ts +119 -0
  171. package/dist/types/overlays/settings-selector.d.ts +73 -0
  172. package/dist/types/overlays/show-images-selector.d.ts +11 -0
  173. package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
  174. package/dist/types/overlays/theme-selector.d.ts +12 -0
  175. package/dist/types/overlays/thinking-selector.d.ts +12 -0
  176. package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
  177. package/dist/types/overlays/tree-selector.d.ts +92 -0
  178. package/dist/types/overlays/usage-dashboard.d.ts +94 -0
  179. package/dist/types/overlays/usage-display.d.ts +5 -0
  180. package/dist/types/overlays/usage-row.d.ts +17 -0
  181. package/dist/types/prompt/attachment-chips.d.ts +19 -0
  182. package/dist/types/prompt/composer-attachments.d.ts +71 -0
  183. package/dist/types/prompt/composer-cache.d.ts +37 -0
  184. package/dist/types/prompt/composer.d.ts +159 -0
  185. package/dist/types/prompt/custom-editor.d.ts +261 -0
  186. package/dist/types/prompt/editor-top-gap.d.ts +18 -0
  187. package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
  188. package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
  189. package/dist/types/prompt/gradient-highlight.d.ts +32 -0
  190. package/dist/types/prompt/image-format.d.ts +4 -0
  191. package/dist/types/prompt/image-references.d.ts +26 -0
  192. package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
  193. package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
  194. package/dist/types/prompt/macos-spelling.d.ts +44 -0
  195. package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
  196. package/dist/types/prompt/magic-keywords.d.ts +26 -0
  197. package/dist/types/prompt/markdown-prose.d.ts +15 -0
  198. package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
  199. package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
  200. package/dist/types/prompt/orchestrate.d.ts +13 -0
  201. package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
  202. package/dist/types/prompt/queue-input.d.ts +8 -0
  203. package/dist/types/prompt/skill-tokens.d.ts +13 -0
  204. package/dist/types/prompt/tools-markdown.d.ts +12 -0
  205. package/dist/types/prompt/ultrathink.d.ts +13 -0
  206. package/dist/types/prompt/usage-amounts.d.ts +26 -0
  207. package/dist/types/prompt/video.d.ts +18 -0
  208. package/dist/types/prompt/welcome.d.ts +83 -0
  209. package/dist/types/prompt/workflow.d.ts +13 -0
  210. package/dist/types/render/code-cell.d.ts +51 -0
  211. package/dist/types/render/file-list.d.ts +22 -0
  212. package/dist/types/render/hyperlink.d.ts +80 -0
  213. package/dist/types/render/index.d.ts +16 -0
  214. package/dist/types/render/output-block.d.ts +54 -0
  215. package/dist/types/render/output-pane.d.ts +80 -0
  216. package/dist/types/render/render-utils.d.ts +312 -0
  217. package/dist/types/render/sixel.d.ts +21 -0
  218. package/dist/types/render/status-line.d.ts +23 -0
  219. package/dist/types/render/tool-card.d.ts +71 -0
  220. package/dist/types/render/tree-list.d.ts +29 -0
  221. package/dist/types/render/types.d.ts +17 -0
  222. package/dist/types/render/utils.d.ts +43 -0
  223. package/dist/types/render/width-aware-text.d.ts +23 -0
  224. package/dist/types/setup/lazy.d.ts +3 -0
  225. package/dist/types/setup/scenes/composer.d.ts +3 -0
  226. package/dist/types/setup/scenes/glyph.d.ts +3 -0
  227. package/dist/types/setup/scenes/model.d.ts +3 -0
  228. package/dist/types/setup/scenes/outro.d.ts +2 -0
  229. package/dist/types/setup/scenes/providers.d.ts +3 -0
  230. package/dist/types/setup/scenes/sign-in.d.ts +21 -0
  231. package/dist/types/setup/scenes/splash.d.ts +11 -0
  232. package/dist/types/setup/scenes/theme.d.ts +3 -0
  233. package/dist/types/setup/scenes/types.d.ts +110 -0
  234. package/dist/types/setup/scenes/web-search.d.ts +22 -0
  235. package/dist/types/setup/setup-version.d.ts +11 -0
  236. package/dist/types/setup/startup-splash.d.ts +9 -0
  237. package/dist/types/setup/wizard-overlay.d.ts +16 -0
  238. package/dist/types/setup/wizard.d.ts +25 -0
  239. package/dist/types/status-line/component.d.ts +182 -0
  240. package/dist/types/status-line/context-usage.d.ts +156 -0
  241. package/dist/types/status-line/footer.d.ts +30 -0
  242. package/dist/types/status-line/git-utils.d.ts +22 -0
  243. package/dist/types/status-line/host.d.ts +129 -0
  244. package/dist/types/status-line/index.d.ts +6 -0
  245. package/dist/types/status-line/loop.d.ts +18 -0
  246. package/dist/types/status-line/metrics.d.ts +21 -0
  247. package/dist/types/status-line/presets.d.ts +3 -0
  248. package/dist/types/status-line/schema.d.ts +15 -0
  249. package/dist/types/status-line/segments.d.ts +5 -0
  250. package/dist/types/status-line/separators.d.ts +3 -0
  251. package/dist/types/status-line/types.d.ts +236 -0
  252. package/dist/types/stdin-buffer.d.ts +4 -0
  253. package/dist/types/theme/color.d.ts +24 -0
  254. package/dist/types/theme/defaults/index.d.ts +9489 -0
  255. package/dist/types/theme/index.d.ts +4 -0
  256. package/dist/types/theme/loader.d.ts +23 -0
  257. package/dist/types/theme/mermaid-cache.d.ts +26 -0
  258. package/dist/types/theme/schema-validation.d.ts +3 -0
  259. package/dist/types/theme/schema.d.ts +25 -0
  260. package/dist/types/theme/session-color.d.ts +43 -0
  261. package/dist/types/theme/shimmer.d.ts +44 -0
  262. package/dist/types/theme/symbols.d.ts +34 -0
  263. package/dist/types/theme/theme-class.d.ts +299 -0
  264. package/dist/types/theme/theme.d.ts +111 -0
  265. package/dist/types/theme/tui-adapters.d.ts +30 -0
  266. package/dist/types/thinking.d.ts +165 -0
  267. package/dist/types/tools/agent-tree.d.ts +36 -0
  268. package/dist/types/tools/ask.d.ts +67 -0
  269. package/dist/types/tools/ast-edit.d.ts +53 -0
  270. package/dist/types/tools/ast-grep.d.ts +52 -0
  271. package/dist/types/tools/autoresearch.d.ts +156 -0
  272. package/dist/types/tools/bash-interactive.d.ts +28 -0
  273. package/dist/types/tools/bash.d.ts +103 -0
  274. package/dist/types/tools/conflict-detect.d.ts +43 -0
  275. package/dist/types/tools/debug.d.ts +60 -0
  276. package/dist/types/tools/default-renderer.d.ts +24 -0
  277. package/dist/types/tools/edit.d.ts +158 -0
  278. package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
  279. package/dist/types/tools/eval-format/index.d.ts +5 -0
  280. package/dist/types/tools/eval-format/javascript.d.ts +2 -0
  281. package/dist/types/tools/eval-format/python.d.ts +2 -0
  282. package/dist/types/tools/eval.d.ts +94 -0
  283. package/dist/types/tools/fetch.d.ts +42 -0
  284. package/dist/types/tools/gh-format.d.ts +8 -0
  285. package/dist/types/tools/github.d.ts +144 -0
  286. package/dist/types/tools/glob.d.ts +44 -0
  287. package/dist/types/tools/goal.d.ts +42 -0
  288. package/dist/types/tools/grep.d.ts +64 -0
  289. package/dist/types/tools/grouped-file-output.d.ts +71 -0
  290. package/dist/types/tools/hashline-format.d.ts +28 -0
  291. package/dist/types/tools/hub.d.ts +340 -0
  292. package/dist/types/tools/index.d.ts +4 -0
  293. package/dist/types/tools/json-tree.d.ts +59 -0
  294. package/dist/types/tools/line-ranges.d.ts +29 -0
  295. package/dist/types/tools/list-limit.d.ts +15 -0
  296. package/dist/types/tools/lsp.d.ts +72 -0
  297. package/dist/types/tools/match-line-format.d.ts +11 -0
  298. package/dist/types/tools/mcp.d.ts +81 -0
  299. package/dist/types/tools/memory.d.ts +67 -0
  300. package/dist/types/tools/output-meta.d.ts +151 -0
  301. package/dist/types/tools/read.d.ts +139 -0
  302. package/dist/types/tools/renderer.d.ts +98 -0
  303. package/dist/types/tools/report-tool-issue.d.ts +8 -0
  304. package/dist/types/tools/resolve.d.ts +47 -0
  305. package/dist/types/tools/streaming-output.d.ts +282 -0
  306. package/dist/types/tools/subprocess.d.ts +24 -0
  307. package/dist/types/tools/task-repair-args.d.ts +53 -0
  308. package/dist/types/tools/task-yield-assembly.d.ts +20 -0
  309. package/dist/types/tools/task.d.ts +425 -0
  310. package/dist/types/tools/terminal-output.d.ts +8 -0
  311. package/dist/types/tools/think.d.ts +13 -0
  312. package/dist/types/tools/todo.d.ts +118 -0
  313. package/dist/types/tools/tool-errors.d.ts +7 -0
  314. package/dist/types/tools/vibe.d.ts +120 -0
  315. package/dist/types/tools/web-search.d.ts +195 -0
  316. package/dist/types/tools/write.d.ts +76 -0
  317. package/dist/types/tools/xd-url.d.ts +13 -0
  318. package/dist/types/tools/xdev.d.ts +52 -0
  319. package/dist/types/tui.d.ts +18 -0
  320. package/dist/types/utils.d.ts +2 -0
  321. package/package.json +37 -3
  322. package/src/app-keybindings.ts +760 -0
  323. package/src/apps/autoresearch-dashboard.ts +500 -0
  324. package/src/apps/autoresearch-data.ts +64 -0
  325. package/src/apps/cleanse-board.ts +341 -0
  326. package/src/apps/cleanse-picker.ts +57 -0
  327. package/src/apps/debug/log-formatting.ts +53 -0
  328. package/src/apps/debug/log-viewer.ts +868 -0
  329. package/src/apps/debug/protocol-probe.ts +267 -0
  330. package/src/apps/debug/raw-sse-buffer.ts +449 -0
  331. package/src/apps/debug/raw-sse.ts +282 -0
  332. package/src/apps/debug/terminal-info.ts +115 -0
  333. package/src/apps/debug/viewer-frame.ts +174 -0
  334. package/src/apps/git/avatar.ts +52 -0
  335. package/src/apps/git/colors.ts +109 -0
  336. package/src/apps/git/diff-pane.ts +1512 -0
  337. package/src/apps/git/git-tui.ts +889 -0
  338. package/src/apps/git/sidebar.ts +1204 -0
  339. package/src/apps/git/state.ts +113 -0
  340. package/src/apps/if-bench-board.ts +324 -0
  341. package/src/apps/live-visualizer.ts +238 -0
  342. package/src/apps/ps-data.ts +116 -0
  343. package/src/apps/ps-top.ts +422 -0
  344. package/src/apps/session-picker.ts +95 -0
  345. package/src/apps/setup-model-picker.ts +21 -0
  346. package/src/apps/standalone-picker.ts +111 -0
  347. package/src/autocomplete.ts +9 -13
  348. package/src/chat/advisor-message.ts +175 -0
  349. package/src/chat/assistant-message.ts +1214 -0
  350. package/src/chat/background-tan-message.ts +35 -0
  351. package/src/chat/bash-execution.ts +394 -0
  352. package/src/chat/cache-invalidation-marker.ts +94 -0
  353. package/src/chat/chat-transcript-builder.ts +593 -0
  354. package/src/chat/collab-prompt-message.ts +34 -0
  355. package/src/chat/compaction-summary-message.ts +261 -0
  356. package/src/chat/custom-message.ts +23 -0
  357. package/src/chat/display-preferences.ts +24 -0
  358. package/src/chat/eval-execution.ts +172 -0
  359. package/src/chat/execution-shared.ts +113 -0
  360. package/src/chat/extension-types.ts +46 -0
  361. package/src/chat/hook-message.ts +20 -0
  362. package/src/chat/image-loading.ts +122 -0
  363. package/src/chat/late-diagnostics-message.ts +92 -0
  364. package/src/chat/messages.ts +305 -0
  365. package/src/chat/reaction.ts +65 -0
  366. package/src/chat/read-target.ts +7 -0
  367. package/src/chat/read-tool-group.ts +873 -0
  368. package/src/chat/served-model-marker.ts +91 -0
  369. package/src/chat/skill-message.ts +220 -0
  370. package/src/chat/skill-title-input.ts +41 -0
  371. package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
  372. package/src/chat/thinking-display.ts +312 -0
  373. package/src/chat/todo-reminder.ts +33 -0
  374. package/src/chat/tool-execution.ts +1395 -0
  375. package/src/chat/transcript-browser.ts +268 -0
  376. package/src/chat/transcript-entry.ts +96 -0
  377. package/src/chat/transcript-outline.ts +260 -0
  378. package/src/chat/transcript-render-helpers.ts +315 -0
  379. package/src/chat/ttsr-notification.ts +123 -0
  380. package/src/chat/user-message.ts +287 -0
  381. package/src/chrome/chat-block.ts +110 -0
  382. package/src/chrome/collab-qrcode.ts +74 -0
  383. package/src/chrome/context-thresholds.ts +85 -0
  384. package/src/chrome/countdown-timer.ts +74 -0
  385. package/src/chrome/diff.ts +266 -0
  386. package/src/chrome/dynamic-border.ts +36 -0
  387. package/src/chrome/error-block.ts +63 -0
  388. package/src/chrome/form-theme.ts +10 -0
  389. package/src/chrome/format.ts +66 -0
  390. package/src/chrome/index.ts +21 -0
  391. package/src/chrome/keybinding-hints.ts +55 -0
  392. package/src/chrome/live-board.ts +123 -0
  393. package/src/chrome/local-date.ts +20 -0
  394. package/src/chrome/message-divider.ts +51 -0
  395. package/src/chrome/message-frame.ts +164 -0
  396. package/src/chrome/message-notice.ts +103 -0
  397. package/src/chrome/overlay-box.ts +301 -0
  398. package/src/chrome/qrcode.ts +539 -0
  399. package/src/chrome/segment-track.ts +86 -0
  400. package/src/chrome/select-list-mouse-routing.ts +11 -0
  401. package/src/chrome/selector-helpers.ts +119 -0
  402. package/src/chrome/shared.ts +27 -0
  403. package/src/chrome/streaming-panel.ts +72 -0
  404. package/src/chrome/tool-activity.ts +44 -0
  405. package/src/chrome/transcript-container.ts +902 -0
  406. package/src/chrome/transcript-status.ts +27 -0
  407. package/src/chrome/visual-truncate.ts +70 -0
  408. package/src/components/disclosure.ts +235 -0
  409. package/src/components/editor.ts +10 -12
  410. package/src/components/form.ts +566 -0
  411. package/src/components/input.ts +6 -27
  412. package/src/components/key-value-list.ts +88 -0
  413. package/src/components/layout/geometry.ts +202 -0
  414. package/src/components/layout/row.ts +283 -0
  415. package/src/components/layout/split-pane.ts +349 -0
  416. package/src/components/layout/stack.ts +261 -0
  417. package/src/components/markdown.ts +16 -12
  418. package/src/components/menu-selection.ts +248 -0
  419. package/src/components/metric.ts +132 -0
  420. package/src/components/progress-bar.ts +140 -0
  421. package/src/components/scroll-view.ts +372 -70
  422. package/src/components/scroll-viewport.ts +154 -0
  423. package/src/components/section.ts +77 -0
  424. package/src/components/select-list.ts +238 -159
  425. package/src/components/settings-list.ts +103 -80
  426. package/src/components/table.ts +127 -0
  427. package/src/components/tree-view.ts +481 -0
  428. package/src/components/wizard-step.ts +229 -0
  429. package/src/deccara.ts +1 -3
  430. package/src/hotkeys-markdown.ts +100 -0
  431. package/src/index.ts +18 -0
  432. package/src/keybinding-matchers.ts +99 -0
  433. package/src/keys.ts +2 -2
  434. package/src/lang-from-path.ts +252 -0
  435. package/src/overlays/advisor-config.ts +761 -0
  436. package/src/overlays/agent-activity.ts +113 -0
  437. package/src/overlays/agent-hub-projection.ts +250 -0
  438. package/src/overlays/agent-hub-renderer.ts +281 -0
  439. package/src/overlays/agent-hub-types.ts +74 -0
  440. package/src/overlays/agent-hub.ts +1562 -0
  441. package/src/overlays/agent-transcript-viewer.ts +669 -0
  442. package/src/overlays/agents-hub.ts +1203 -0
  443. package/src/overlays/ask-dialog.ts +1202 -0
  444. package/src/overlays/bordered-loader.ts +41 -0
  445. package/src/overlays/btw-history-panel.ts +591 -0
  446. package/src/overlays/btw-history.ts +33 -0
  447. package/src/overlays/btw-panel.ts +167 -0
  448. package/src/overlays/cleanse-panel.ts +167 -0
  449. package/src/overlays/codex-reset-fireworks.ts +375 -0
  450. package/src/overlays/composer-shape-preview.ts +137 -0
  451. package/src/overlays/composer-shape-registry.ts +82 -0
  452. package/src/overlays/copy-selector.ts +618 -0
  453. package/src/overlays/copy-targets.ts +210 -0
  454. package/src/overlays/error-banner.ts +39 -0
  455. package/src/overlays/extensions/display-text.ts +39 -0
  456. package/src/overlays/extensions/extension-dashboard.ts +645 -0
  457. package/src/overlays/extensions/extension-list.ts +667 -0
  458. package/src/overlays/extensions/inspector-model.ts +484 -0
  459. package/src/overlays/extensions/inspector-panel.ts +669 -0
  460. package/src/overlays/extensions/live-tool-session.ts +67 -0
  461. package/src/overlays/extensions/mcp-runtime.ts +289 -0
  462. package/src/overlays/extensions/state-manager.ts +337 -0
  463. package/src/overlays/extensions/types.ts +208 -0
  464. package/src/overlays/history-search.ts +268 -0
  465. package/src/overlays/hook-editor.ts +272 -0
  466. package/src/overlays/hook-input.ts +84 -0
  467. package/src/overlays/hook-selector.ts +635 -0
  468. package/src/overlays/hub-frame.ts +262 -0
  469. package/src/overlays/login-dialog.ts +231 -0
  470. package/src/overlays/logout-account-selector.ts +115 -0
  471. package/src/overlays/mcp-add-wizard.ts +1436 -0
  472. package/src/overlays/model-browser.ts +1176 -0
  473. package/src/overlays/model-hub.ts +2279 -0
  474. package/src/overlays/model-picker.ts +285 -0
  475. package/src/overlays/model-selector.ts +107 -0
  476. package/src/overlays/move-overlay.ts +197 -0
  477. package/src/overlays/oauth-selector.ts +446 -0
  478. package/src/overlays/omfg-panel.ts +136 -0
  479. package/src/overlays/pause-screen.ts +198 -0
  480. package/src/overlays/plan-review-overlay.ts +1227 -0
  481. package/src/overlays/plan-save-overlay.ts +74 -0
  482. package/src/overlays/plan-toc.ts +139 -0
  483. package/src/overlays/plugin-selector.ts +97 -0
  484. package/src/overlays/plugin-settings.ts +839 -0
  485. package/src/overlays/queue-mode-selector.ts +55 -0
  486. package/src/overlays/reset-usage-selector.ts +170 -0
  487. package/src/overlays/rewind-selector.ts +499 -0
  488. package/src/overlays/running-subagent-badge.ts +19 -0
  489. package/src/overlays/session-account-selector.ts +68 -0
  490. package/src/overlays/session-info-overlay.ts +96 -0
  491. package/src/overlays/session-observer-registry.ts +289 -0
  492. package/src/overlays/session-selector.ts +1137 -0
  493. package/src/overlays/settings-defs.ts +315 -0
  494. package/src/overlays/settings-selector.ts +1415 -0
  495. package/src/overlays/show-images-selector.ts +44 -0
  496. package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
  497. package/src/overlays/snapcompact-shape-preview.ts +192 -0
  498. package/src/overlays/theme-selector.ts +62 -0
  499. package/src/overlays/thinking-selector.ts +51 -0
  500. package/src/overlays/tiny-title-download-progress.ts +102 -0
  501. package/src/overlays/tree-selector.ts +1121 -0
  502. package/src/overlays/usage-dashboard.ts +629 -0
  503. package/src/overlays/usage-display.ts +45 -0
  504. package/src/overlays/usage-row.ts +118 -0
  505. package/src/prompt/attachment-chips.ts +201 -0
  506. package/src/prompt/composer-attachments.ts +280 -0
  507. package/src/prompt/composer-cache.ts +304 -0
  508. package/src/prompt/composer.ts +934 -0
  509. package/src/prompt/custom-editor.ts +1392 -0
  510. package/src/prompt/data/emojis.json +1 -0
  511. package/src/prompt/editor-top-gap.ts +28 -0
  512. package/src/prompt/emoji-autocomplete.ts +285 -0
  513. package/src/prompt/github-ref-autocomplete.ts +75 -0
  514. package/src/prompt/gradient-highlight.ts +101 -0
  515. package/src/prompt/image-format.ts +28 -0
  516. package/src/prompt/image-references.ts +102 -0
  517. package/src/prompt/interactive-context-helpers.ts +126 -0
  518. package/src/prompt/internal-url-autocomplete.ts +155 -0
  519. package/src/prompt/macos-spelling.ts +456 -0
  520. package/src/prompt/magic-keyword-boundary.ts +23 -0
  521. package/src/prompt/magic-keywords.ts +42 -0
  522. package/src/prompt/markdown-prose.ts +245 -0
  523. package/src/prompt/model-mention-autocomplete.ts +94 -0
  524. package/src/prompt/model-mention-syntax.ts +41 -0
  525. package/src/prompt/orchestrate.ts +26 -0
  526. package/src/prompt/prompt-action-autocomplete.ts +337 -0
  527. package/src/prompt/queue-input.ts +132 -0
  528. package/src/prompt/skill-tokens.ts +36 -0
  529. package/src/prompt/tips.txt +27 -0
  530. package/src/prompt/tools-markdown.ts +29 -0
  531. package/src/prompt/ultrathink.ts +26 -0
  532. package/src/prompt/usage-amounts.ts +99 -0
  533. package/src/prompt/video.ts +47 -0
  534. package/src/prompt/welcome.ts +605 -0
  535. package/src/prompt/workflow.ts +26 -0
  536. package/src/render/code-cell.ts +244 -0
  537. package/src/render/file-list.ts +58 -0
  538. package/src/render/hyperlink.ts +192 -0
  539. package/src/render/index.ts +17 -0
  540. package/src/render/output-block.ts +267 -0
  541. package/src/render/output-pane.ts +299 -0
  542. package/src/render/render-utils.ts +1182 -0
  543. package/src/render/sixel.ts +69 -0
  544. package/src/render/status-line.ts +55 -0
  545. package/src/render/tool-card.ts +272 -0
  546. package/src/render/tree-list.ts +188 -0
  547. package/src/render/types.ts +19 -0
  548. package/src/render/utils.ts +109 -0
  549. package/src/render/width-aware-text.ts +60 -0
  550. package/src/setup/lazy.ts +17 -0
  551. package/src/setup/scenes/composer.ts +127 -0
  552. package/src/setup/scenes/glyph.ts +120 -0
  553. package/src/setup/scenes/model.ts +138 -0
  554. package/src/setup/scenes/outro.ts +24 -0
  555. package/src/setup/scenes/providers.ts +107 -0
  556. package/src/setup/scenes/sign-in.ts +373 -0
  557. package/src/setup/scenes/splash.ts +192 -0
  558. package/src/setup/scenes/theme.ts +343 -0
  559. package/src/setup/scenes/types.ts +111 -0
  560. package/src/setup/scenes/web-search.ts +165 -0
  561. package/src/setup/setup-version.ts +11 -0
  562. package/src/setup/startup-splash.ts +107 -0
  563. package/src/setup/wizard-overlay.ts +319 -0
  564. package/src/setup/wizard.ts +101 -0
  565. package/src/status-line/component.ts +3003 -0
  566. package/src/status-line/context-usage.ts +688 -0
  567. package/src/status-line/footer.ts +323 -0
  568. package/src/status-line/git-utils.ts +42 -0
  569. package/src/status-line/host.ts +97 -0
  570. package/src/status-line/index.ts +6 -0
  571. package/src/status-line/loop.ts +28 -0
  572. package/src/status-line/metrics.ts +94 -0
  573. package/src/status-line/presets.ts +107 -0
  574. package/src/status-line/schema.ts +57 -0
  575. package/src/status-line/segments.ts +934 -0
  576. package/src/status-line/separators.ts +55 -0
  577. package/src/status-line/types.ts +227 -0
  578. package/src/stdin-buffer.ts +4 -2
  579. package/src/theme/color.ts +95 -0
  580. package/src/theme/dark.json +95 -0
  581. package/src/theme/defaults/alabaster.json +93 -0
  582. package/src/theme/defaults/amethyst.json +96 -0
  583. package/src/theme/defaults/anthracite.json +93 -0
  584. package/src/theme/defaults/basalt.json +91 -0
  585. package/src/theme/defaults/birch.json +95 -0
  586. package/src/theme/defaults/dark-abyss.json +91 -0
  587. package/src/theme/defaults/dark-arctic.json +104 -0
  588. package/src/theme/defaults/dark-aurora.json +95 -0
  589. package/src/theme/defaults/dark-catppuccin.json +107 -0
  590. package/src/theme/defaults/dark-cavern.json +91 -0
  591. package/src/theme/defaults/dark-celestial.json +106 -0
  592. package/src/theme/defaults/dark-copper.json +95 -0
  593. package/src/theme/defaults/dark-cosmos.json +90 -0
  594. package/src/theme/defaults/dark-cyberpunk.json +102 -0
  595. package/src/theme/defaults/dark-dracula.json +98 -0
  596. package/src/theme/defaults/dark-eclipse.json +91 -0
  597. package/src/theme/defaults/dark-ember.json +95 -0
  598. package/src/theme/defaults/dark-equinox.json +90 -0
  599. package/src/theme/defaults/dark-forest.json +96 -0
  600. package/src/theme/defaults/dark-github.json +105 -0
  601. package/src/theme/defaults/dark-gruvbox.json +112 -0
  602. package/src/theme/defaults/dark-lavender.json +95 -0
  603. package/src/theme/defaults/dark-lunar.json +89 -0
  604. package/src/theme/defaults/dark-midnight.json +95 -0
  605. package/src/theme/defaults/dark-monochrome.json +94 -0
  606. package/src/theme/defaults/dark-monokai.json +98 -0
  607. package/src/theme/defaults/dark-nebula.json +90 -0
  608. package/src/theme/defaults/dark-nord.json +98 -0
  609. package/src/theme/defaults/dark-ocean.json +101 -0
  610. package/src/theme/defaults/dark-one.json +100 -0
  611. package/src/theme/defaults/dark-poimandres.json +115 -0
  612. package/src/theme/defaults/dark-rainforest.json +91 -0
  613. package/src/theme/defaults/dark-reef.json +91 -0
  614. package/src/theme/defaults/dark-retro.json +92 -0
  615. package/src/theme/defaults/dark-rose-pine.json +96 -0
  616. package/src/theme/defaults/dark-sakura.json +95 -0
  617. package/src/theme/defaults/dark-slate.json +95 -0
  618. package/src/theme/defaults/dark-solarized.json +97 -0
  619. package/src/theme/defaults/dark-solstice.json +90 -0
  620. package/src/theme/defaults/dark-starfall.json +91 -0
  621. package/src/theme/defaults/dark-sunset.json +99 -0
  622. package/src/theme/defaults/dark-swamp.json +90 -0
  623. package/src/theme/defaults/dark-synthwave.json +103 -0
  624. package/src/theme/defaults/dark-taiga.json +91 -0
  625. package/src/theme/defaults/dark-terminal.json +95 -0
  626. package/src/theme/defaults/dark-tokyo-night.json +101 -0
  627. package/src/theme/defaults/dark-tundra.json +91 -0
  628. package/src/theme/defaults/dark-twilight.json +91 -0
  629. package/src/theme/defaults/dark-volcanic.json +91 -0
  630. package/src/theme/defaults/graphite.json +92 -0
  631. package/src/theme/defaults/index.ts +201 -0
  632. package/src/theme/defaults/light-arctic.json +107 -0
  633. package/src/theme/defaults/light-aurora-day.json +91 -0
  634. package/src/theme/defaults/light-canyon.json +91 -0
  635. package/src/theme/defaults/light-catppuccin.json +106 -0
  636. package/src/theme/defaults/light-cirrus.json +90 -0
  637. package/src/theme/defaults/light-coral.json +95 -0
  638. package/src/theme/defaults/light-cyberpunk.json +96 -0
  639. package/src/theme/defaults/light-dawn.json +90 -0
  640. package/src/theme/defaults/light-dunes.json +91 -0
  641. package/src/theme/defaults/light-eucalyptus.json +95 -0
  642. package/src/theme/defaults/light-forest.json +100 -0
  643. package/src/theme/defaults/light-frost.json +95 -0
  644. package/src/theme/defaults/light-github.json +115 -0
  645. package/src/theme/defaults/light-glacier.json +91 -0
  646. package/src/theme/defaults/light-gruvbox.json +108 -0
  647. package/src/theme/defaults/light-haze.json +90 -0
  648. package/src/theme/defaults/light-honeycomb.json +95 -0
  649. package/src/theme/defaults/light-lagoon.json +91 -0
  650. package/src/theme/defaults/light-lavender.json +95 -0
  651. package/src/theme/defaults/light-meadow.json +91 -0
  652. package/src/theme/defaults/light-mint.json +95 -0
  653. package/src/theme/defaults/light-monochrome.json +101 -0
  654. package/src/theme/defaults/light-ocean.json +99 -0
  655. package/src/theme/defaults/light-one.json +99 -0
  656. package/src/theme/defaults/light-opal.json +91 -0
  657. package/src/theme/defaults/light-orchard.json +91 -0
  658. package/src/theme/defaults/light-paper.json +95 -0
  659. package/src/theme/defaults/light-poimandres.json +115 -0
  660. package/src/theme/defaults/light-prism.json +90 -0
  661. package/src/theme/defaults/light-retro.json +98 -0
  662. package/src/theme/defaults/light-sand.json +95 -0
  663. package/src/theme/defaults/light-savanna.json +91 -0
  664. package/src/theme/defaults/light-solarized.json +102 -0
  665. package/src/theme/defaults/light-soleil.json +90 -0
  666. package/src/theme/defaults/light-sunset.json +99 -0
  667. package/src/theme/defaults/light-synthwave.json +98 -0
  668. package/src/theme/defaults/light-tokyo-night.json +111 -0
  669. package/src/theme/defaults/light-wetland.json +91 -0
  670. package/src/theme/defaults/light-zenith.json +89 -0
  671. package/src/theme/defaults/limestone.json +94 -0
  672. package/src/theme/defaults/mahogany.json +97 -0
  673. package/src/theme/defaults/marble.json +93 -0
  674. package/src/theme/defaults/obsidian.json +91 -0
  675. package/src/theme/defaults/onyx.json +91 -0
  676. package/src/theme/defaults/pearl.json +93 -0
  677. package/src/theme/defaults/porcelain.json +91 -0
  678. package/src/theme/defaults/quartz.json +96 -0
  679. package/src/theme/defaults/sandstone.json +95 -0
  680. package/src/theme/defaults/titanium.json +90 -0
  681. package/src/theme/index.ts +5 -0
  682. package/src/theme/light.json +93 -0
  683. package/src/theme/loader.ts +200 -0
  684. package/src/theme/mermaid-cache.ts +92 -0
  685. package/src/theme/schema-validation.ts +119 -0
  686. package/src/theme/schema.ts +168 -0
  687. package/src/theme/session-color.ts +253 -0
  688. package/src/theme/shimmer.ts +307 -0
  689. package/src/theme/symbols.ts +1433 -0
  690. package/src/theme/theme-class.ts +787 -0
  691. package/src/theme/theme-schema.json +463 -0
  692. package/src/theme/theme.ts +810 -0
  693. package/src/theme/tui-adapters.ts +339 -0
  694. package/src/thinking.ts +380 -0
  695. package/src/tools/agent-tree.ts +128 -0
  696. package/src/tools/ask.ts +482 -0
  697. package/src/tools/ast-edit.ts +210 -0
  698. package/src/tools/ast-grep.ts +171 -0
  699. package/src/tools/autoresearch.ts +287 -0
  700. package/src/tools/bash-interactive.ts +295 -0
  701. package/src/tools/bash.ts +468 -0
  702. package/src/tools/conflict-detect.ts +77 -0
  703. package/src/tools/debug.ts +167 -0
  704. package/src/tools/default-renderer.ts +172 -0
  705. package/src/tools/edit.ts +1258 -0
  706. package/src/tools/eval-format/code-mode-declarations.ts +61 -0
  707. package/src/tools/eval-format/index.ts +16 -0
  708. package/src/tools/eval-format/javascript.ts +952 -0
  709. package/src/tools/eval-format/python.ts +544 -0
  710. package/src/tools/eval.ts +835 -0
  711. package/src/tools/fetch.ts +226 -0
  712. package/src/tools/gh-format.ts +18 -0
  713. package/src/tools/github.ts +686 -0
  714. package/src/tools/glob.ts +213 -0
  715. package/src/tools/goal.ts +153 -0
  716. package/src/tools/grep.ts +385 -0
  717. package/src/tools/grouped-file-output.ts +211 -0
  718. package/src/tools/hashline-format.ts +59 -0
  719. package/src/tools/hub.ts +1488 -0
  720. package/src/tools/index.ts +71 -0
  721. package/src/tools/json-tree.ts +388 -0
  722. package/src/tools/line-ranges.ts +98 -0
  723. package/src/tools/list-limit.ts +43 -0
  724. package/src/tools/lsp.ts +702 -0
  725. package/src/tools/match-line-format.ts +20 -0
  726. package/src/tools/mcp.ts +309 -0
  727. package/src/tools/memory.ts +220 -0
  728. package/src/tools/output-meta.ts +367 -0
  729. package/src/tools/read.ts +628 -0
  730. package/src/tools/renderer.ts +107 -0
  731. package/src/tools/report-tool-issue.ts +13 -0
  732. package/src/tools/resolve.ts +139 -0
  733. package/src/tools/streaming-output.ts +1576 -0
  734. package/src/tools/subprocess.ts +39 -0
  735. package/src/tools/task-repair-args.ts +118 -0
  736. package/src/tools/task-yield-assembly.ts +147 -0
  737. package/src/tools/task.ts +2110 -0
  738. package/src/tools/terminal-output.ts +153 -0
  739. package/src/tools/think.ts +28 -0
  740. package/src/tools/todo.ts +580 -0
  741. package/src/tools/tool-errors.ts +15 -0
  742. package/src/tools/vibe.ts +420 -0
  743. package/src/tools/web-search.ts +409 -0
  744. package/src/tools/write.ts +511 -0
  745. package/src/tools/xd-url.ts +28 -0
  746. package/src/tools/xdev.ts +201 -0
  747. package/src/tui.ts +57 -4
  748. package/src/utils.ts +8 -0
@@ -0,0 +1,113 @@
1
+ import type { DiffStreamProgress, DiffStreamResult } from "@oh-my-pi/pi-natives";
2
+
3
+ /** Context lines retained around each exact streamed hunk. */
4
+ export const DIFF_CONTEXT_LINES = 3;
5
+
6
+ /** Change classification shown beside a file path. */
7
+ export type ChangeKind = "modified" | "added" | "deleted" | "renamed" | "untracked" | "conflicted";
8
+ /** Repository area represented by a file list. */
9
+ export type ChangeArea = "unstaged" | "staged" | "commit";
10
+
11
+ /** One changed path shown in the sidebar file lists. */
12
+ export interface ChangedFile {
13
+ readonly path: string;
14
+ /** Pre-rename path for renames/copies. */
15
+ readonly origPath?: string;
16
+ readonly kind: ChangeKind;
17
+ readonly area: ChangeArea;
18
+ readonly additions?: number;
19
+ readonly deletions?: number;
20
+ }
21
+
22
+ /** HEAD commit metadata for the clean-tree sidebar view. */
23
+ export interface HeadCommit {
24
+ readonly sha: string;
25
+ readonly shortSha: string;
26
+ readonly subject: string;
27
+ readonly body: string;
28
+ readonly authorName: string;
29
+ readonly authorEmail: string;
30
+ readonly authorDate: string;
31
+ readonly parents: readonly string[];
32
+ /** Changed paths once their numstats have loaded. */
33
+ readonly files: readonly ChangedFile[];
34
+ /** Whether {@link files} contains the complete commit file list. */
35
+ readonly filesLoaded: boolean;
36
+ }
37
+
38
+ /** A terminal-ready image decoded from one Git file side. */
39
+ export interface ReviewImage {
40
+ readonly data: string;
41
+ readonly mimeType: "image/png";
42
+ readonly sourceMimeType: string;
43
+ readonly widthPx: number;
44
+ readonly heightPx: number;
45
+ readonly byteLength: number;
46
+ /** Stable content identity for terminal graphics placement. */
47
+ readonly key: string;
48
+ /** Git LFS object id when the preview came from local LFS storage. */
49
+ readonly lfsOid?: string;
50
+ }
51
+
52
+ /** One side of a media or binary Git change. */
53
+ export type FileAssetSide =
54
+ | { readonly kind: "empty" }
55
+ | { readonly kind: "text"; readonly byteLength: number; readonly lfsOid?: string }
56
+ | { readonly kind: "image"; readonly image: ReviewImage }
57
+ | { readonly kind: "binary"; readonly byteLength?: number; readonly lfsOid?: string }
58
+ | { readonly kind: "tooLarge"; readonly byteLength?: number; readonly lfsOid?: string }
59
+ | { readonly kind: "lfsMissing"; readonly oid: string; readonly byteLength: number };
60
+
61
+ /** Diffable UTF-8 content for both sides of a file. */
62
+ export interface TextFileContents {
63
+ readonly kind: "text";
64
+ readonly oldText: string;
65
+ readonly newText: string;
66
+ readonly streamResult: DiffStreamResult;
67
+ }
68
+
69
+ /** Non-text sides rendered as previews or explicit placeholders. */
70
+ export interface AssetFileContents {
71
+ readonly kind: "asset";
72
+ readonly old: FileAssetSide;
73
+ readonly new: FileAssetSide;
74
+ }
75
+
76
+ /** Loaded file content selected for text diffing or asset preview. */
77
+ export type FileContents = TextFileContents | AssetFileContents;
78
+
79
+ /** Newly completed lines and state emitted while a file pair streams. */
80
+ export interface FileStreamUpdate {
81
+ readonly oldLineOffset: number;
82
+ readonly oldLines: readonly string[];
83
+ readonly newLineOffset: number;
84
+ readonly newLines: readonly string[];
85
+ readonly progress: DiffStreamProgress;
86
+ }
87
+
88
+ /** Repository values read by the sidebar. */
89
+ export interface GitViewState {
90
+ readonly cwd: string;
91
+ readonly branch: string | null;
92
+ readonly clean: boolean;
93
+ readonly unstaged: readonly ChangedFile[];
94
+ readonly staged: readonly ChangedFile[];
95
+ readonly headCommit: HeadCommit | null;
96
+ }
97
+
98
+ /** Repository operations supplied by the command host. */
99
+ export interface GitTuiModel extends GitViewState {
100
+ refresh(): Promise<boolean>;
101
+ loadChangeStats(): Promise<boolean>;
102
+ loadHeadFiles(): Promise<boolean>;
103
+ streamContents(
104
+ file: ChangedFile,
105
+ onProgress: (update: FileStreamUpdate) => void,
106
+ signal?: AbortSignal,
107
+ ): Promise<FileContents>;
108
+ stage(files?: readonly ChangedFile[]): Promise<void>;
109
+ unstage(files?: readonly ChangedFile[]): Promise<void>;
110
+ discard(files: readonly ChangedFile[]): Promise<void>;
111
+ commit(message: string, options?: { amend?: boolean }): Promise<void>;
112
+ applyPatch(patchText: string, options?: { cached?: boolean; reverse?: boolean }): Promise<void>;
113
+ }
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Live board and scoreboard for `omp if-bench`.
3
+ *
4
+ * Interactive terminals get one repainted row per model — a turn ladder that
5
+ * fills as turns pass, the in-flight turn as a spinner cell, and the live
6
+ * position of the cat directive — plus a permanent verdict line per model as it
7
+ * settles. Non-TTY output falls back to one plain line per turn so scripted
8
+ * callers keep a parseable trace.
9
+ */
10
+
11
+ import { replaceTabs, truncateToWidth } from "../utils";
12
+ import { renderTableRow, type TableColumn } from "../components/table";
13
+ import { formatDuration, formatNumber } from "@oh-my-pi/pi-utils";
14
+ import { fgOrPlain, theme } from "../theme/theme";
15
+ import { createLiveBoard, type LiveBoardOutput } from "../chrome/live-board";
16
+
17
+ /** Failure category displayed in benchmark verdicts. */
18
+ export type IfBenchFailure = "result" | "cat" | "result+cat" | "format" | "provider";
19
+
20
+ /** Scored turn fields consumed by the live board and failure details. */
21
+ export interface IfBenchTurnRecord {
22
+ turn: number;
23
+ cumulativeActions: number;
24
+ placement: string;
25
+ durationMs: number;
26
+ passed: boolean;
27
+ failure?: IfBenchFailure;
28
+ expected: string;
29
+ response: string;
30
+ }
31
+
32
+ /** Per-model scoreboard and verdict fields. */
33
+ export interface IfBenchModelReport {
34
+ label: string;
35
+ turns: readonly IfBenchTurnRecord[];
36
+ turnsPassed: number;
37
+ actionsPassed: number;
38
+ failure?: { turn: number; kind: IfBenchFailure };
39
+ durationMs: number;
40
+ outputTokens: number;
41
+ cost: number;
42
+ }
43
+
44
+ /** Benchmark results consumed by the ranked scoreboard. */
45
+ export interface IfBenchSummary {
46
+ maxTurns: number;
47
+ models: readonly IfBenchModelReport[];
48
+ }
49
+
50
+ /** Optional live-progress callbacks accepted by a benchmark runner. */
51
+ export interface IfBenchObserver<
52
+ Turn extends IfBenchTurnRecord = IfBenchTurnRecord,
53
+ Report extends IfBenchModelReport = IfBenchModelReport,
54
+ > {
55
+ modelStarted?(label: string): void;
56
+ turnStarted?(label: string, turn: number, actions: number): void;
57
+ turnFinished?(label: string, record: Turn): void;
58
+ modelFinished?(report: Report): void;
59
+ }
60
+
61
+ const LADDER_WIDTH = 28;
62
+ const LABEL_WIDTH = 34;
63
+ const DETAIL_WIDTH = 120;
64
+
65
+ /** Human-readable verdict for each scored failure mode. */
66
+ const FAILURE_TEXT: Record<IfBenchFailure, string> = {
67
+ result: "wrong array",
68
+ cat: "no cat sound",
69
+ "result+cat": "wrong array + no cat sound",
70
+ format: "no <result> block",
71
+ provider: "provider error",
72
+ };
73
+
74
+ /** Rendering surface for one `omp if-bench` run. */
75
+ export interface IfBenchBoard extends IfBenchObserver {
76
+ readonly interactive: boolean;
77
+ /** Print a permanent line above the live rows (plain write when non-TTY). */
78
+ log(text: string): void;
79
+ /** Clear the live area and restore the cursor. Idempotent. */
80
+ close(): void;
81
+ }
82
+
83
+ interface RowState {
84
+ startedAt: number;
85
+ turn: number;
86
+ actions: number;
87
+ passed: number;
88
+ failed: boolean;
89
+ placement: string;
90
+ lastDurationMs: number;
91
+ }
92
+
93
+ /** Static run parameters shown in the board header. */
94
+ export interface IfBenchBoardMeta {
95
+ maxTurns: number;
96
+ arrayLength: number;
97
+ nyaMax: number;
98
+ }
99
+
100
+ /**
101
+ * Create the if-bench board bound to `output`.
102
+ *
103
+ * `errors` receives non-TTY failure lines so a piped stdout stays a clean
104
+ * turn-by-turn trace.
105
+ */
106
+ export function createIfBenchBoard(
107
+ meta: IfBenchBoardMeta,
108
+ output: LiveBoardOutput = process.stdout,
109
+ errors: LiveBoardOutput = process.stderr,
110
+ ): IfBenchBoard {
111
+ const rows = new Map<string, RowState>();
112
+ const startedAt = Date.now();
113
+ const board = createLiveBoard(spinner => renderLive(meta, rows, spinner, startedAt), output);
114
+
115
+ return {
116
+ interactive: board.interactive,
117
+ log: board.log,
118
+ modelStarted(label) {
119
+ rows.set(label, {
120
+ startedAt: Date.now(),
121
+ turn: 0,
122
+ actions: 0,
123
+ passed: 0,
124
+ failed: false,
125
+ placement: "",
126
+ lastDurationMs: 0,
127
+ });
128
+ board.repaint();
129
+ },
130
+ turnStarted(label, turn) {
131
+ const row = rows.get(label);
132
+ if (!row) return;
133
+ row.turn = turn;
134
+ board.repaint();
135
+ },
136
+ turnFinished(label, record) {
137
+ const row = rows.get(label);
138
+ if (row) {
139
+ row.actions = record.cumulativeActions;
140
+ row.placement = record.placement;
141
+ row.lastDurationMs = record.durationMs;
142
+ if (record.passed) row.passed = record.turn;
143
+ else row.failed = true;
144
+ board.repaint();
145
+ }
146
+ if (!board.interactive) {
147
+ const sink = record.passed ? output : errors;
148
+ sink.write(`${formatTurnLine(label, record)}\n`);
149
+ }
150
+ },
151
+ modelFinished(report) {
152
+ rows.delete(report.label);
153
+ board.log(formatVerdict(report, meta));
154
+ if (report.failure) {
155
+ for (const line of failureDetail(report)) board.log(line);
156
+ }
157
+ },
158
+ close: board.close,
159
+ };
160
+ }
161
+
162
+ function renderLive(
163
+ meta: IfBenchBoardMeta,
164
+ rows: ReadonlyMap<string, RowState>,
165
+ spinner: string,
166
+ startedAt: number,
167
+ ): string[] {
168
+ if (rows.size === 0) return [];
169
+ const deepest = Math.max(0, ...[...rows.values()].map(row => row.actions));
170
+ const header =
171
+ `${fgOrPlain("accent", spinner)} ${theme ? theme.bold("if-bench") : "if-bench"} ${fgOrPlain("dim", "·")} ` +
172
+ `${rows.size} live ${fgOrPlain("dim", "·")} ${deepest} actions ${fgOrPlain("dim", "·")} ` +
173
+ `${fgOrPlain("dim", `L=${meta.arrayLength} nya{1,${meta.nyaMax}}`)} ${fgOrPlain("dim", "·")} ` +
174
+ `${formatDuration(Date.now() - startedAt)}`;
175
+ const lines = [header];
176
+ for (const [label, row] of rows) {
177
+ const meterCells = ladder(row, meta.maxTurns, spinner);
178
+ const parts = [
179
+ `turn ${Math.max(row.turn, 1)}/${meta.maxTurns}`,
180
+ `${row.actions} acts`,
181
+ formatDuration(Date.now() - row.startedAt),
182
+ ];
183
+ if (row.placement) parts.push(fgOrPlain("dim", `cat@${row.placement}`));
184
+ lines.push(
185
+ renderTableRow(
186
+ [
187
+ { text: spinner, style: text => fgOrPlain("warning", text) },
188
+ { text: label },
189
+ { text: meterCells },
190
+ { text: parts.join(fgOrPlain("dim", " · ")) },
191
+ ],
192
+ LIVE_ROW_COLUMNS[Math.min(meta.maxTurns, LADDER_WIDTH)]!,
193
+ undefined,
194
+ { indent: " ", gap: " " },
195
+ ),
196
+ );
197
+ }
198
+ return lines;
199
+ }
200
+
201
+ const LIVE_ROW_COLUMNS: readonly (readonly TableColumn[])[] = Array.from(
202
+ { length: LADDER_WIDTH + 1 },
203
+ (_, meterWidth): readonly TableColumn[] => [
204
+ { width: 1, align: "left", overflow: "truncate" },
205
+ { width: LABEL_WIDTH, align: "left", overflow: "truncate" },
206
+ { width: meterWidth, align: "left", overflow: "truncate" },
207
+ { width: DETAIL_WIDTH, align: "left", overflow: "allow" },
208
+ ],
209
+ );
210
+
211
+ /**
212
+ * Turn meter: filled cells for passed turns, a spinner cell for the in-flight
213
+ * turn, dim cells for the remaining budget. Scales to {@link LADDER_WIDTH} when
214
+ * the turn budget is larger so the row never wraps.
215
+ */
216
+ function ladder(row: RowState, maxTurns: number, spinner: string): string {
217
+ const width = Math.min(maxTurns, LADDER_WIDTH);
218
+ const scale = width / maxTurns;
219
+ const filled = Math.min(width, Math.round(row.passed * scale));
220
+ const active = row.failed || filled >= width ? 0 : Math.max(0, Math.min(width - filled, Math.round(scale)) || 1);
221
+ const rest = Math.max(0, width - filled - active);
222
+ return (
223
+ fgOrPlain("success", "█".repeat(filled)) +
224
+ (row.failed ? fgOrPlain("error", "▚") : fgOrPlain("warning", spinner.repeat(active))) +
225
+ fgOrPlain("dim", "░".repeat(rest))
226
+ );
227
+ }
228
+
229
+ function formatTurnLine(label: string, record: IfBenchTurnRecord): string {
230
+ const head = `[turn ${record.turn}] ${label} ${record.cumulativeActions} acts cat@${record.placement}`;
231
+ if (record.passed) return `${head} PASS ${formatDuration(Math.round(record.durationMs))}`;
232
+ return `${head} FAIL ${record.failure ?? "format"}`;
233
+ }
234
+
235
+ function formatVerdict(report: IfBenchModelReport, meta: IfBenchBoardMeta): string {
236
+ const stats = [
237
+ `${report.turnsPassed}/${meta.maxTurns} turns`,
238
+ `${report.actionsPassed} actions`,
239
+ `${formatDuration(Math.round(meanTurnMs(report)))}/turn`,
240
+ ];
241
+ if (report.outputTokens > 0) stats.push(`${formatNumber(report.outputTokens)} tok`);
242
+ if (report.cost > 0) stats.push(formatCost(report.cost));
243
+ const body = `${theme ? theme.bold(report.label) : report.label} ${stats.join(fgOrPlain("dim", " · "))}`;
244
+ if (!report.failure) return `${fgOrPlain("success", "✓")} ${body}`;
245
+ return `${fgOrPlain("error", "✗")} ${body} ${fgOrPlain("dim", "·")} ${fgOrPlain("error", `broke on turn ${report.failure.turn}: ${FAILURE_TEXT[report.failure.kind]}`)}`;
246
+ }
247
+
248
+ /** Expected/actual pair for the turn that ended a run, clipped for the terminal. */
249
+ function failureDetail(report: IfBenchModelReport): string[] {
250
+ const failed = report.turns[report.turns.length - 1];
251
+ if (!failed) return [];
252
+ const oneLine = (text: string): string =>
253
+ truncateToWidth(replaceTabs(text).replace(/\s+/g, " ").trim(), DETAIL_WIDTH);
254
+ if (failed.failure === "provider")
255
+ return [` ${fgOrPlain("dim", "provider")} ${fgOrPlain("error", oneLine(failed.response))}`];
256
+ return [
257
+ ` ${fgOrPlain("dim", "expected")} <${failed.expected}>`,
258
+ ` ${fgOrPlain("dim", "actual ")} ${oneLine(failed.response)}`,
259
+ ];
260
+ }
261
+
262
+ function meanTurnMs(report: IfBenchModelReport): number {
263
+ if (report.turns.length === 0) return 0;
264
+ return report.durationMs / report.turns.length;
265
+ }
266
+
267
+ function formatCost(cost: number): string {
268
+ return `$${cost >= 0.095 ? cost.toFixed(2) : cost.toFixed(3)}`;
269
+ }
270
+
271
+ interface ScoreboardColumn {
272
+ header: string;
273
+ value(report: IfBenchModelReport): string;
274
+ align?: "right";
275
+ }
276
+
277
+ /**
278
+ * Ranked comparison table: depth first (turns, then actions), latency only as a
279
+ * tie-break, because surviving one more turn always beats answering faster.
280
+ */
281
+ export function formatIfBenchScoreboard(summary: IfBenchSummary): string {
282
+ const ranked = [...summary.models].sort(
283
+ (a, b) => b.turnsPassed - a.turnsPassed || b.actionsPassed - a.actionsPassed || meanTurnMs(a) - meanTurnMs(b),
284
+ );
285
+ const columns: ScoreboardColumn[] = [
286
+ { header: "model", value: report => report.label },
287
+ { header: "turns", value: report => `${report.turnsPassed}/${summary.maxTurns}`, align: "right" },
288
+ { header: "actions", value: report => String(report.actionsPassed), align: "right" },
289
+ {
290
+ header: "broke on",
291
+ value: report =>
292
+ report.failure ? `turn ${report.failure.turn} · ${FAILURE_TEXT[report.failure.kind]}` : "survived",
293
+ },
294
+ { header: "per turn", value: report => formatDuration(Math.round(meanTurnMs(report))), align: "right" },
295
+ {
296
+ header: "tokens",
297
+ value: report => (report.outputTokens > 0 ? formatNumber(report.outputTokens) : "-"),
298
+ align: "right",
299
+ },
300
+ { header: "cost", value: report => (report.cost > 0 ? formatCost(report.cost) : "-"), align: "right" },
301
+ ];
302
+ const cells = ranked.map(report => columns.map(column => column.value(report)));
303
+ const widths = columns.map((column, index) =>
304
+ Math.max(column.header.length, ...cells.map(row => row[index]!.length)),
305
+ );
306
+ const tableColumns: TableColumn[] = columns.map((column, index): TableColumn => ({
307
+ width: widths[index]!,
308
+ align: column.align === "right" ? "right" : "left",
309
+ overflow: "truncate",
310
+ }));
311
+ const layout = (row: string[]): string =>
312
+ renderTableRow(
313
+ row.map(cell => ({ text: cell })),
314
+ tableColumns,
315
+ undefined,
316
+ { gap: " " },
317
+ ).trimEnd();
318
+ const lines = [fgOrPlain("dim", layout(columns.map(column => column.header)))];
319
+ for (const [index, row] of cells.entries()) {
320
+ const line = layout(row);
321
+ lines.push(index === 0 && ranked[0]!.turnsPassed > 0 ? fgOrPlain("success", line) : line);
322
+ }
323
+ return `${lines.join("\n")}\n`;
324
+ }
@@ -0,0 +1,238 @@
1
+ import type { Component } from "../tui";
2
+ import { OverlayPanel, PanelRows } from "../chrome/overlay-box";
3
+ import { type KeyId, matchesKey } from "../keys";
4
+ import { sliceWithWidth, truncateToWidth, visibleWidth } from "../utils";
5
+ import { sanitizeDisplaySingleLine } from "../overlays/extensions/display-text";
6
+ import { type ThemeColor, theme } from "../theme/theme";
7
+
8
+ /** Distinct states of a realtime call connection. */
9
+ export type LivePhase = "connecting" | "listening" | "working" | "speaking" | "muted" | "error";
10
+
11
+ const PHASE_ICONS: Record<LivePhase, string> = {
12
+ connecting: "○",
13
+ listening: "●",
14
+ working: "○",
15
+ speaking: "»",
16
+ muted: "×",
17
+ error: "!",
18
+ };
19
+ const PHASE_COLORS: Record<LivePhase, ThemeColor> = {
20
+ connecting: "dim",
21
+ listening: "success",
22
+ working: "warning",
23
+ speaking: "accent",
24
+ muted: "dim",
25
+ error: "error",
26
+ };
27
+ const SPECTRUM_BLOCKS = [" ", "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"] as const;
28
+
29
+ /** Configuration callbacks for user interactions in the visualizer. */
30
+ export interface LiveVisualizerOptions {
31
+ onStop(): void;
32
+ onToggleMute(): void;
33
+ /** Configured `app.live.toggle` chords that also end the call (Ctrl+L by default). */
34
+ stopKeys?: readonly KeyId[];
35
+ }
36
+
37
+ function truncateFromStart(text: string, width: number): string {
38
+ if (width <= 0) return "";
39
+ const textWidth = visibleWidth(text);
40
+ if (textWidth <= width) return text;
41
+ if (width === 1) return "…";
42
+ return `…${sliceWithWidth(text, textWidth - width + 1, width - 1, true).text}`;
43
+ }
44
+
45
+ /** A compact, fixed-height terminal component for displaying a realtime call. */
46
+ export class LiveVisualizer implements Component {
47
+ readonly wantsKeyRelease = false;
48
+
49
+ readonly #options: LiveVisualizerOptions;
50
+ readonly #body = new PanelRows();
51
+ readonly #panel = new OverlayPanel();
52
+
53
+ #phase: LivePhase = "connecting";
54
+ #inputLevel = 0;
55
+ #displayLevel = 0;
56
+ #frame = 0;
57
+ #userTranscript = "";
58
+
59
+ #cache:
60
+ | {
61
+ width: number;
62
+ phase: LivePhase;
63
+ displayLevel: number;
64
+ frame: number;
65
+ userTranscript: string;
66
+ lines: readonly string[];
67
+ }
68
+ | undefined;
69
+
70
+ constructor(options: LiveVisualizerOptions) {
71
+ this.#options = options;
72
+ this.#body.setHeight(3);
73
+ this.#panel.addChild(this.#body);
74
+ }
75
+
76
+ /** Updates the current call phase. */
77
+ setPhase(phase: LivePhase): void {
78
+ if (this.#phase !== phase) {
79
+ this.#phase = phase;
80
+ this.invalidate();
81
+ }
82
+ }
83
+
84
+ /** Updates the microphone volume level (0..1). */
85
+ setInputLevel(level: number): void {
86
+ const next = Number.isFinite(level) ? Math.min(1, Math.max(0, level)) : 0;
87
+ if (this.#inputLevel === next) return;
88
+ this.#inputLevel = next;
89
+ if (next > this.#displayLevel) this.#displayLevel = next;
90
+ this.invalidate();
91
+ }
92
+
93
+ /** Advances the spectrum animation and its peak decay. */
94
+ setFrame(frame: number): void {
95
+ const nextLevel = Math.max(this.#inputLevel, this.#displayLevel * 0.84);
96
+ if (this.#frame !== frame || this.#displayLevel !== nextLevel) {
97
+ this.#frame = frame;
98
+ this.#displayLevel = nextLevel;
99
+ this.invalidate();
100
+ }
101
+ }
102
+
103
+ /** Updates the user's streaming voice transcript. */
104
+ setTranscript(text: string): void {
105
+ const normalized = sanitizeDisplaySingleLine(text).replace(/\s+/g, " ").trim();
106
+ if (this.#userTranscript === normalized) return;
107
+ this.#userTranscript = normalized;
108
+ this.invalidate();
109
+ }
110
+
111
+ /** Clears the user's voice transcript row. */
112
+ clearTranscript(): void {
113
+ if (!this.#userTranscript) return;
114
+ this.#userTranscript = "";
115
+ this.invalidate();
116
+ }
117
+
118
+ /** Processes user keypresses. */
119
+ handleInput(data: string): void {
120
+ if (
121
+ matchesKey(data, "escape") ||
122
+ matchesKey(data, "ctrl+c") ||
123
+ this.#options.stopKeys?.some(key => matchesKey(data, key))
124
+ ) {
125
+ this.#options.onStop();
126
+ } else if (matchesKey(data, "space")) {
127
+ this.#options.onToggleMute();
128
+ }
129
+ }
130
+
131
+ /** Clears the render cache. */
132
+ invalidate(): void {
133
+ this.#cache = undefined;
134
+ this.#panel.invalidate();
135
+ }
136
+
137
+ /** Renders the microphone spectrum into a compact fixed-height panel. */
138
+ render(width: number): readonly string[] {
139
+ if (
140
+ this.#cache &&
141
+ this.#cache.width === width &&
142
+ this.#cache.phase === this.#phase &&
143
+ this.#cache.displayLevel === this.#displayLevel &&
144
+ this.#cache.frame === this.#frame &&
145
+ this.#cache.userTranscript === this.#userTranscript
146
+ ) {
147
+ return this.#cache.lines;
148
+ }
149
+
150
+ const lines = this.#renderLines(width);
151
+ this.#cache = {
152
+ width,
153
+ phase: this.#phase,
154
+ displayLevel: this.#displayLevel,
155
+ frame: this.#frame,
156
+ userTranscript: this.#userTranscript,
157
+ lines,
158
+ };
159
+ return lines;
160
+ }
161
+
162
+ #renderLines(maxWidth: number): readonly string[] {
163
+ const width = Math.max(2, maxWidth);
164
+ const spectrumColor: ThemeColor = this.#phase === "muted" ? "dim" : this.#phase === "error" ? "error" : "success";
165
+ if (width < 4) {
166
+ const innerWidth = width - 2;
167
+ const border = (content: string): string =>
168
+ theme.fg("border", "│") + content + (width > 1 ? theme.fg("border", "│") : "");
169
+ const top = theme.fg("border", `┌${"─".repeat(innerWidth)}${width > 1 ? "┐" : ""}`);
170
+ const spectrum = this.#generateSpectrum(innerWidth, 2);
171
+ return [
172
+ top,
173
+ ...spectrum.map(row => border(theme.fg(spectrumColor, row))),
174
+ border(this.#renderTranscript(this.#userTranscript, innerWidth)),
175
+ this.#renderFooter(width, innerWidth),
176
+ ];
177
+ }
178
+
179
+ const contentWidth = width - 4;
180
+ const spectrum = this.#generateSpectrum(contentWidth, 2);
181
+ this.#body.setLines([
182
+ ...spectrum.map(row => theme.fg(spectrumColor, row)),
183
+ this.#renderTranscript(this.#userTranscript, contentWidth),
184
+ ]);
185
+ const lines = [...this.#panel.render(width)];
186
+ lines[lines.length - 1] = this.#renderFooter(width, width - 2);
187
+ return lines;
188
+ }
189
+
190
+ #renderTranscript(transcript: string, width: number): string {
191
+ const content = truncateFromStart(transcript, width);
192
+ const padding = " ".repeat(Math.max(0, width - visibleWidth(content)));
193
+ return theme.fg("accent", content) + padding;
194
+ }
195
+
196
+ #renderFooter(width: number, innerWidth: number): string {
197
+ const frames = theme.spinnerFrames;
198
+ const icon = this.#phase === "working" ? frames[this.#frame % frames.length] : PHASE_ICONS[this.#phase];
199
+ const status = `${icon} ${this.#phase}`;
200
+ const fullLabel = ` ${status} · space mute · esc end `;
201
+ const shortLabel = ` ${status} `;
202
+ const label =
203
+ innerWidth >= visibleWidth(fullLabel) + 1
204
+ ? fullLabel
205
+ : innerWidth >= visibleWidth(shortLabel) + 1
206
+ ? shortLabel
207
+ : "";
208
+ const box = width >= 4 ? theme.boxRound : undefined;
209
+ const bottomLeft = box?.bottomLeft ?? "└";
210
+ const horizontal = box?.horizontal ?? "─";
211
+ const bottomRight = box?.bottomRight ?? "┘";
212
+ if (!label) {
213
+ return theme.fg("border", `${bottomLeft}${horizontal.repeat(innerWidth)}${width > 1 ? bottomRight : ""}`);
214
+ }
215
+ const remaining = Math.max(0, innerWidth - visibleWidth(label) - 1);
216
+ return (
217
+ theme.fg("border", `${bottomLeft}${horizontal}`) +
218
+ theme.fg(PHASE_COLORS[this.#phase], truncateToWidth(label, innerWidth - 1)) +
219
+ theme.fg("border", `${horizontal.repeat(remaining)}${width > 1 ? bottomRight : ""}`)
220
+ );
221
+ }
222
+
223
+ #generateSpectrum(width: number, rows: number): string[] {
224
+ const output = Array.from({ length: rows }, () => "");
225
+ const energy = this.#phase === "muted" ? 0 : Math.min(1, Math.sqrt(this.#displayLevel * 5));
226
+ const maxHeight = rows * (SPECTRUM_BLOCKS.length - 1);
227
+ for (let column = 0; column < width; column += 1) {
228
+ const carrier = 0.5 + 0.5 * Math.sin(this.#frame * 0.43 + column * 0.71);
229
+ const shimmer = 0.5 + 0.5 * Math.sin(this.#frame * 0.19 - column * 1.17);
230
+ const height = Math.round(energy * (0.3 + carrier * 0.5 + shimmer * 0.2) * maxHeight);
231
+ for (let row = 0; row < rows; row += 1) {
232
+ const units = Math.max(0, Math.min(SPECTRUM_BLOCKS.length - 1, height - (rows - row - 1) * 8));
233
+ output[row] += SPECTRUM_BLOCKS[units];
234
+ }
235
+ }
236
+ return output;
237
+ }
238
+ }