@oh-my-pi/pi-tui 18.2.3 → 18.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (750) hide show
  1. package/CHANGELOG.md +29 -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/image.d.ts +18 -16
  92. package/dist/types/components/key-value-list.d.ts +24 -0
  93. package/dist/types/components/layout/geometry.d.ts +73 -0
  94. package/dist/types/components/layout/row.d.ts +55 -0
  95. package/dist/types/components/layout/split-pane.d.ts +80 -0
  96. package/dist/types/components/layout/stack.d.ts +50 -0
  97. package/dist/types/components/menu-selection.d.ts +71 -0
  98. package/dist/types/components/metric.d.ts +44 -0
  99. package/dist/types/components/progress-bar.d.ts +36 -0
  100. package/dist/types/components/scroll-view.d.ts +53 -19
  101. package/dist/types/components/scroll-viewport.d.ts +46 -0
  102. package/dist/types/components/section.d.ts +19 -0
  103. package/dist/types/components/select-list.d.ts +46 -2
  104. package/dist/types/components/settings-list.d.ts +20 -0
  105. package/dist/types/components/table.d.ts +32 -0
  106. package/dist/types/components/tree-view.d.ts +130 -0
  107. package/dist/types/components/wizard-step.d.ts +60 -0
  108. package/dist/types/hotkeys-markdown.d.ts +7 -0
  109. package/dist/types/index.d.ts +17 -0
  110. package/dist/types/keybinding-matchers.d.ts +35 -0
  111. package/dist/types/keys.d.ts +2 -2
  112. package/dist/types/lang-from-path.d.ts +9 -0
  113. package/dist/types/overlays/advisor-config.d.ts +114 -0
  114. package/dist/types/overlays/agent-activity.d.ts +41 -0
  115. package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
  116. package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
  117. package/dist/types/overlays/agent-hub-types.d.ts +99 -0
  118. package/dist/types/overlays/agent-hub.d.ts +126 -0
  119. package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
  120. package/dist/types/overlays/agents-hub.d.ts +72 -0
  121. package/dist/types/overlays/ask-dialog.d.ts +88 -0
  122. package/dist/types/overlays/bordered-loader.d.ts +11 -0
  123. package/dist/types/overlays/btw-history-panel.d.ts +29 -0
  124. package/dist/types/overlays/btw-history.d.ts +17 -0
  125. package/dist/types/overlays/btw-panel.d.ts +26 -0
  126. package/dist/types/overlays/cleanse-panel.d.ts +36 -0
  127. package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
  128. package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
  129. package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
  130. package/dist/types/overlays/copy-selector.d.ts +48 -0
  131. package/dist/types/overlays/copy-targets.d.ts +63 -0
  132. package/dist/types/overlays/error-banner.d.ts +13 -0
  133. package/dist/types/overlays/extensions/display-text.d.ts +10 -0
  134. package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
  135. package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
  136. package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
  137. package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
  138. package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
  139. package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
  140. package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
  141. package/dist/types/overlays/extensions/types.d.ts +165 -0
  142. package/dist/types/overlays/history-search.d.ts +16 -0
  143. package/dist/types/overlays/hook-editor.d.ts +44 -0
  144. package/dist/types/overlays/hook-input.d.ts +20 -0
  145. package/dist/types/overlays/hook-selector.d.ts +71 -0
  146. package/dist/types/overlays/hub-frame.d.ts +77 -0
  147. package/dist/types/overlays/login-dialog.d.ts +43 -0
  148. package/dist/types/overlays/logout-account-selector.d.ts +15 -0
  149. package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
  150. package/dist/types/overlays/model-browser.d.ts +213 -0
  151. package/dist/types/overlays/model-hub.d.ts +72 -0
  152. package/dist/types/overlays/model-picker.d.ts +74 -0
  153. package/dist/types/overlays/model-selector.d.ts +52 -0
  154. package/dist/types/overlays/move-overlay.d.ts +39 -0
  155. package/dist/types/overlays/oauth-selector.d.ts +41 -0
  156. package/dist/types/overlays/omfg-panel.d.ts +20 -0
  157. package/dist/types/overlays/pause-screen.d.ts +43 -0
  158. package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
  159. package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
  160. package/dist/types/overlays/plan-toc.d.ts +41 -0
  161. package/dist/types/overlays/plugin-selector.d.ts +28 -0
  162. package/dist/types/overlays/plugin-settings.d.ts +180 -0
  163. package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
  164. package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
  165. package/dist/types/overlays/rewind-selector.d.ts +61 -0
  166. package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
  167. package/dist/types/overlays/session-account-selector.d.ts +24 -0
  168. package/dist/types/overlays/session-info-overlay.d.ts +17 -0
  169. package/dist/types/overlays/session-observer-registry.d.ts +77 -0
  170. package/dist/types/overlays/session-selector.d.ts +131 -0
  171. package/dist/types/overlays/settings-defs.d.ts +119 -0
  172. package/dist/types/overlays/settings-selector.d.ts +73 -0
  173. package/dist/types/overlays/show-images-selector.d.ts +11 -0
  174. package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
  175. package/dist/types/overlays/theme-selector.d.ts +12 -0
  176. package/dist/types/overlays/thinking-selector.d.ts +12 -0
  177. package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
  178. package/dist/types/overlays/tree-selector.d.ts +92 -0
  179. package/dist/types/overlays/usage-dashboard.d.ts +94 -0
  180. package/dist/types/overlays/usage-display.d.ts +5 -0
  181. package/dist/types/overlays/usage-row.d.ts +17 -0
  182. package/dist/types/prompt/attachment-chips.d.ts +19 -0
  183. package/dist/types/prompt/composer-attachments.d.ts +71 -0
  184. package/dist/types/prompt/composer-cache.d.ts +37 -0
  185. package/dist/types/prompt/composer.d.ts +159 -0
  186. package/dist/types/prompt/custom-editor.d.ts +261 -0
  187. package/dist/types/prompt/editor-top-gap.d.ts +18 -0
  188. package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
  189. package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
  190. package/dist/types/prompt/gradient-highlight.d.ts +32 -0
  191. package/dist/types/prompt/image-format.d.ts +4 -0
  192. package/dist/types/prompt/image-references.d.ts +26 -0
  193. package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
  194. package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
  195. package/dist/types/prompt/macos-spelling.d.ts +44 -0
  196. package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
  197. package/dist/types/prompt/magic-keywords.d.ts +26 -0
  198. package/dist/types/prompt/markdown-prose.d.ts +15 -0
  199. package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
  200. package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
  201. package/dist/types/prompt/orchestrate.d.ts +13 -0
  202. package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
  203. package/dist/types/prompt/queue-input.d.ts +8 -0
  204. package/dist/types/prompt/skill-tokens.d.ts +13 -0
  205. package/dist/types/prompt/tools-markdown.d.ts +12 -0
  206. package/dist/types/prompt/ultrathink.d.ts +13 -0
  207. package/dist/types/prompt/usage-amounts.d.ts +26 -0
  208. package/dist/types/prompt/video.d.ts +18 -0
  209. package/dist/types/prompt/welcome.d.ts +83 -0
  210. package/dist/types/prompt/workflow.d.ts +13 -0
  211. package/dist/types/render/code-cell.d.ts +51 -0
  212. package/dist/types/render/file-list.d.ts +22 -0
  213. package/dist/types/render/hyperlink.d.ts +80 -0
  214. package/dist/types/render/index.d.ts +16 -0
  215. package/dist/types/render/output-block.d.ts +54 -0
  216. package/dist/types/render/output-pane.d.ts +80 -0
  217. package/dist/types/render/render-utils.d.ts +312 -0
  218. package/dist/types/render/sixel.d.ts +21 -0
  219. package/dist/types/render/status-line.d.ts +23 -0
  220. package/dist/types/render/tool-card.d.ts +71 -0
  221. package/dist/types/render/tree-list.d.ts +29 -0
  222. package/dist/types/render/types.d.ts +17 -0
  223. package/dist/types/render/utils.d.ts +43 -0
  224. package/dist/types/render/width-aware-text.d.ts +23 -0
  225. package/dist/types/setup/lazy.d.ts +3 -0
  226. package/dist/types/setup/scenes/composer.d.ts +3 -0
  227. package/dist/types/setup/scenes/glyph.d.ts +3 -0
  228. package/dist/types/setup/scenes/model.d.ts +3 -0
  229. package/dist/types/setup/scenes/outro.d.ts +2 -0
  230. package/dist/types/setup/scenes/providers.d.ts +3 -0
  231. package/dist/types/setup/scenes/sign-in.d.ts +21 -0
  232. package/dist/types/setup/scenes/splash.d.ts +11 -0
  233. package/dist/types/setup/scenes/theme.d.ts +3 -0
  234. package/dist/types/setup/scenes/types.d.ts +110 -0
  235. package/dist/types/setup/scenes/web-search.d.ts +22 -0
  236. package/dist/types/setup/setup-version.d.ts +11 -0
  237. package/dist/types/setup/startup-splash.d.ts +9 -0
  238. package/dist/types/setup/wizard-overlay.d.ts +16 -0
  239. package/dist/types/setup/wizard.d.ts +25 -0
  240. package/dist/types/status-line/component.d.ts +182 -0
  241. package/dist/types/status-line/context-usage.d.ts +156 -0
  242. package/dist/types/status-line/footer.d.ts +30 -0
  243. package/dist/types/status-line/git-utils.d.ts +22 -0
  244. package/dist/types/status-line/host.d.ts +129 -0
  245. package/dist/types/status-line/index.d.ts +6 -0
  246. package/dist/types/status-line/loop.d.ts +18 -0
  247. package/dist/types/status-line/metrics.d.ts +21 -0
  248. package/dist/types/status-line/presets.d.ts +3 -0
  249. package/dist/types/status-line/schema.d.ts +15 -0
  250. package/dist/types/status-line/segments.d.ts +5 -0
  251. package/dist/types/status-line/separators.d.ts +3 -0
  252. package/dist/types/status-line/types.d.ts +236 -0
  253. package/dist/types/stdin-buffer.d.ts +4 -0
  254. package/dist/types/theme/color.d.ts +24 -0
  255. package/dist/types/theme/defaults/index.d.ts +9489 -0
  256. package/dist/types/theme/index.d.ts +4 -0
  257. package/dist/types/theme/loader.d.ts +23 -0
  258. package/dist/types/theme/mermaid-cache.d.ts +26 -0
  259. package/dist/types/theme/schema-validation.d.ts +3 -0
  260. package/dist/types/theme/schema.d.ts +25 -0
  261. package/dist/types/theme/session-color.d.ts +43 -0
  262. package/dist/types/theme/shimmer.d.ts +44 -0
  263. package/dist/types/theme/symbols.d.ts +34 -0
  264. package/dist/types/theme/theme-class.d.ts +299 -0
  265. package/dist/types/theme/theme.d.ts +111 -0
  266. package/dist/types/theme/tui-adapters.d.ts +30 -0
  267. package/dist/types/thinking.d.ts +165 -0
  268. package/dist/types/tools/agent-tree.d.ts +36 -0
  269. package/dist/types/tools/ask.d.ts +67 -0
  270. package/dist/types/tools/ast-edit.d.ts +53 -0
  271. package/dist/types/tools/ast-grep.d.ts +52 -0
  272. package/dist/types/tools/autoresearch.d.ts +156 -0
  273. package/dist/types/tools/bash-interactive.d.ts +28 -0
  274. package/dist/types/tools/bash.d.ts +103 -0
  275. package/dist/types/tools/conflict-detect.d.ts +43 -0
  276. package/dist/types/tools/debug.d.ts +60 -0
  277. package/dist/types/tools/default-renderer.d.ts +24 -0
  278. package/dist/types/tools/edit.d.ts +158 -0
  279. package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
  280. package/dist/types/tools/eval-format/index.d.ts +5 -0
  281. package/dist/types/tools/eval-format/javascript.d.ts +2 -0
  282. package/dist/types/tools/eval-format/python.d.ts +2 -0
  283. package/dist/types/tools/eval.d.ts +94 -0
  284. package/dist/types/tools/fetch.d.ts +42 -0
  285. package/dist/types/tools/gh-format.d.ts +8 -0
  286. package/dist/types/tools/github.d.ts +144 -0
  287. package/dist/types/tools/glob.d.ts +44 -0
  288. package/dist/types/tools/goal.d.ts +42 -0
  289. package/dist/types/tools/grep.d.ts +64 -0
  290. package/dist/types/tools/grouped-file-output.d.ts +71 -0
  291. package/dist/types/tools/hashline-format.d.ts +28 -0
  292. package/dist/types/tools/hub.d.ts +340 -0
  293. package/dist/types/tools/index.d.ts +4 -0
  294. package/dist/types/tools/json-tree.d.ts +59 -0
  295. package/dist/types/tools/line-ranges.d.ts +29 -0
  296. package/dist/types/tools/list-limit.d.ts +15 -0
  297. package/dist/types/tools/lsp.d.ts +72 -0
  298. package/dist/types/tools/match-line-format.d.ts +11 -0
  299. package/dist/types/tools/mcp.d.ts +81 -0
  300. package/dist/types/tools/memory.d.ts +67 -0
  301. package/dist/types/tools/output-meta.d.ts +151 -0
  302. package/dist/types/tools/read.d.ts +139 -0
  303. package/dist/types/tools/renderer.d.ts +98 -0
  304. package/dist/types/tools/report-tool-issue.d.ts +8 -0
  305. package/dist/types/tools/resolve.d.ts +47 -0
  306. package/dist/types/tools/streaming-output.d.ts +282 -0
  307. package/dist/types/tools/subprocess.d.ts +24 -0
  308. package/dist/types/tools/task-repair-args.d.ts +53 -0
  309. package/dist/types/tools/task-yield-assembly.d.ts +20 -0
  310. package/dist/types/tools/task.d.ts +425 -0
  311. package/dist/types/tools/terminal-output.d.ts +8 -0
  312. package/dist/types/tools/think.d.ts +13 -0
  313. package/dist/types/tools/todo.d.ts +118 -0
  314. package/dist/types/tools/tool-errors.d.ts +7 -0
  315. package/dist/types/tools/vibe.d.ts +120 -0
  316. package/dist/types/tools/web-search.d.ts +195 -0
  317. package/dist/types/tools/write.d.ts +76 -0
  318. package/dist/types/tools/xd-url.d.ts +13 -0
  319. package/dist/types/tools/xdev.d.ts +52 -0
  320. package/dist/types/tui.d.ts +18 -0
  321. package/dist/types/utils.d.ts +2 -0
  322. package/package.json +37 -3
  323. package/src/app-keybindings.ts +760 -0
  324. package/src/apps/autoresearch-dashboard.ts +500 -0
  325. package/src/apps/autoresearch-data.ts +64 -0
  326. package/src/apps/cleanse-board.ts +341 -0
  327. package/src/apps/cleanse-picker.ts +57 -0
  328. package/src/apps/debug/log-formatting.ts +53 -0
  329. package/src/apps/debug/log-viewer.ts +868 -0
  330. package/src/apps/debug/protocol-probe.ts +267 -0
  331. package/src/apps/debug/raw-sse-buffer.ts +449 -0
  332. package/src/apps/debug/raw-sse.ts +282 -0
  333. package/src/apps/debug/terminal-info.ts +115 -0
  334. package/src/apps/debug/viewer-frame.ts +174 -0
  335. package/src/apps/git/avatar.ts +52 -0
  336. package/src/apps/git/colors.ts +109 -0
  337. package/src/apps/git/diff-pane.ts +1512 -0
  338. package/src/apps/git/git-tui.ts +889 -0
  339. package/src/apps/git/sidebar.ts +1204 -0
  340. package/src/apps/git/state.ts +113 -0
  341. package/src/apps/if-bench-board.ts +324 -0
  342. package/src/apps/live-visualizer.ts +238 -0
  343. package/src/apps/ps-data.ts +116 -0
  344. package/src/apps/ps-top.ts +422 -0
  345. package/src/apps/session-picker.ts +95 -0
  346. package/src/apps/setup-model-picker.ts +21 -0
  347. package/src/apps/standalone-picker.ts +111 -0
  348. package/src/autocomplete.ts +9 -13
  349. package/src/chat/advisor-message.ts +175 -0
  350. package/src/chat/assistant-message.ts +1214 -0
  351. package/src/chat/background-tan-message.ts +35 -0
  352. package/src/chat/bash-execution.ts +394 -0
  353. package/src/chat/cache-invalidation-marker.ts +94 -0
  354. package/src/chat/chat-transcript-builder.ts +593 -0
  355. package/src/chat/collab-prompt-message.ts +34 -0
  356. package/src/chat/compaction-summary-message.ts +261 -0
  357. package/src/chat/custom-message.ts +23 -0
  358. package/src/chat/display-preferences.ts +24 -0
  359. package/src/chat/eval-execution.ts +172 -0
  360. package/src/chat/execution-shared.ts +113 -0
  361. package/src/chat/extension-types.ts +46 -0
  362. package/src/chat/hook-message.ts +20 -0
  363. package/src/chat/image-loading.ts +122 -0
  364. package/src/chat/late-diagnostics-message.ts +92 -0
  365. package/src/chat/messages.ts +305 -0
  366. package/src/chat/reaction.ts +65 -0
  367. package/src/chat/read-target.ts +7 -0
  368. package/src/chat/read-tool-group.ts +873 -0
  369. package/src/chat/served-model-marker.ts +91 -0
  370. package/src/chat/skill-message.ts +220 -0
  371. package/src/chat/skill-title-input.ts +41 -0
  372. package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
  373. package/src/chat/thinking-display.ts +312 -0
  374. package/src/chat/todo-reminder.ts +33 -0
  375. package/src/chat/tool-execution.ts +1395 -0
  376. package/src/chat/transcript-browser.ts +268 -0
  377. package/src/chat/transcript-entry.ts +96 -0
  378. package/src/chat/transcript-outline.ts +260 -0
  379. package/src/chat/transcript-render-helpers.ts +315 -0
  380. package/src/chat/ttsr-notification.ts +123 -0
  381. package/src/chat/user-message.ts +287 -0
  382. package/src/chrome/chat-block.ts +110 -0
  383. package/src/chrome/collab-qrcode.ts +74 -0
  384. package/src/chrome/context-thresholds.ts +85 -0
  385. package/src/chrome/countdown-timer.ts +74 -0
  386. package/src/chrome/diff.ts +266 -0
  387. package/src/chrome/dynamic-border.ts +36 -0
  388. package/src/chrome/error-block.ts +63 -0
  389. package/src/chrome/form-theme.ts +10 -0
  390. package/src/chrome/format.ts +66 -0
  391. package/src/chrome/index.ts +21 -0
  392. package/src/chrome/keybinding-hints.ts +55 -0
  393. package/src/chrome/live-board.ts +123 -0
  394. package/src/chrome/local-date.ts +20 -0
  395. package/src/chrome/message-divider.ts +51 -0
  396. package/src/chrome/message-frame.ts +164 -0
  397. package/src/chrome/message-notice.ts +103 -0
  398. package/src/chrome/overlay-box.ts +301 -0
  399. package/src/chrome/qrcode.ts +539 -0
  400. package/src/chrome/segment-track.ts +86 -0
  401. package/src/chrome/select-list-mouse-routing.ts +11 -0
  402. package/src/chrome/selector-helpers.ts +119 -0
  403. package/src/chrome/shared.ts +27 -0
  404. package/src/chrome/streaming-panel.ts +72 -0
  405. package/src/chrome/tool-activity.ts +44 -0
  406. package/src/chrome/transcript-container.ts +902 -0
  407. package/src/chrome/transcript-status.ts +27 -0
  408. package/src/chrome/visual-truncate.ts +70 -0
  409. package/src/components/disclosure.ts +235 -0
  410. package/src/components/editor.ts +10 -12
  411. package/src/components/form.ts +566 -0
  412. package/src/components/image.ts +80 -53
  413. package/src/components/input.ts +6 -27
  414. package/src/components/key-value-list.ts +88 -0
  415. package/src/components/layout/geometry.ts +202 -0
  416. package/src/components/layout/row.ts +283 -0
  417. package/src/components/layout/split-pane.ts +349 -0
  418. package/src/components/layout/stack.ts +261 -0
  419. package/src/components/markdown.ts +16 -12
  420. package/src/components/menu-selection.ts +248 -0
  421. package/src/components/metric.ts +132 -0
  422. package/src/components/progress-bar.ts +140 -0
  423. package/src/components/scroll-view.ts +372 -70
  424. package/src/components/scroll-viewport.ts +154 -0
  425. package/src/components/section.ts +77 -0
  426. package/src/components/select-list.ts +238 -159
  427. package/src/components/settings-list.ts +103 -80
  428. package/src/components/table.ts +127 -0
  429. package/src/components/tree-view.ts +481 -0
  430. package/src/components/wizard-step.ts +229 -0
  431. package/src/deccara.ts +1 -3
  432. package/src/hotkeys-markdown.ts +100 -0
  433. package/src/index.ts +18 -0
  434. package/src/keybinding-matchers.ts +99 -0
  435. package/src/keys.ts +2 -2
  436. package/src/lang-from-path.ts +252 -0
  437. package/src/overlays/advisor-config.ts +761 -0
  438. package/src/overlays/agent-activity.ts +113 -0
  439. package/src/overlays/agent-hub-projection.ts +250 -0
  440. package/src/overlays/agent-hub-renderer.ts +281 -0
  441. package/src/overlays/agent-hub-types.ts +74 -0
  442. package/src/overlays/agent-hub.ts +1562 -0
  443. package/src/overlays/agent-transcript-viewer.ts +669 -0
  444. package/src/overlays/agents-hub.ts +1203 -0
  445. package/src/overlays/ask-dialog.ts +1202 -0
  446. package/src/overlays/bordered-loader.ts +41 -0
  447. package/src/overlays/btw-history-panel.ts +591 -0
  448. package/src/overlays/btw-history.ts +33 -0
  449. package/src/overlays/btw-panel.ts +167 -0
  450. package/src/overlays/cleanse-panel.ts +167 -0
  451. package/src/overlays/codex-reset-fireworks.ts +375 -0
  452. package/src/overlays/composer-shape-preview.ts +137 -0
  453. package/src/overlays/composer-shape-registry.ts +82 -0
  454. package/src/overlays/copy-selector.ts +618 -0
  455. package/src/overlays/copy-targets.ts +210 -0
  456. package/src/overlays/error-banner.ts +39 -0
  457. package/src/overlays/extensions/display-text.ts +39 -0
  458. package/src/overlays/extensions/extension-dashboard.ts +645 -0
  459. package/src/overlays/extensions/extension-list.ts +667 -0
  460. package/src/overlays/extensions/inspector-model.ts +484 -0
  461. package/src/overlays/extensions/inspector-panel.ts +669 -0
  462. package/src/overlays/extensions/live-tool-session.ts +67 -0
  463. package/src/overlays/extensions/mcp-runtime.ts +289 -0
  464. package/src/overlays/extensions/state-manager.ts +337 -0
  465. package/src/overlays/extensions/types.ts +208 -0
  466. package/src/overlays/history-search.ts +268 -0
  467. package/src/overlays/hook-editor.ts +272 -0
  468. package/src/overlays/hook-input.ts +84 -0
  469. package/src/overlays/hook-selector.ts +635 -0
  470. package/src/overlays/hub-frame.ts +262 -0
  471. package/src/overlays/login-dialog.ts +231 -0
  472. package/src/overlays/logout-account-selector.ts +115 -0
  473. package/src/overlays/mcp-add-wizard.ts +1436 -0
  474. package/src/overlays/model-browser.ts +1176 -0
  475. package/src/overlays/model-hub.ts +2279 -0
  476. package/src/overlays/model-picker.ts +285 -0
  477. package/src/overlays/model-selector.ts +107 -0
  478. package/src/overlays/move-overlay.ts +197 -0
  479. package/src/overlays/oauth-selector.ts +446 -0
  480. package/src/overlays/omfg-panel.ts +136 -0
  481. package/src/overlays/pause-screen.ts +198 -0
  482. package/src/overlays/plan-review-overlay.ts +1227 -0
  483. package/src/overlays/plan-save-overlay.ts +74 -0
  484. package/src/overlays/plan-toc.ts +139 -0
  485. package/src/overlays/plugin-selector.ts +97 -0
  486. package/src/overlays/plugin-settings.ts +839 -0
  487. package/src/overlays/queue-mode-selector.ts +55 -0
  488. package/src/overlays/reset-usage-selector.ts +170 -0
  489. package/src/overlays/rewind-selector.ts +499 -0
  490. package/src/overlays/running-subagent-badge.ts +19 -0
  491. package/src/overlays/session-account-selector.ts +68 -0
  492. package/src/overlays/session-info-overlay.ts +96 -0
  493. package/src/overlays/session-observer-registry.ts +289 -0
  494. package/src/overlays/session-selector.ts +1137 -0
  495. package/src/overlays/settings-defs.ts +315 -0
  496. package/src/overlays/settings-selector.ts +1415 -0
  497. package/src/overlays/show-images-selector.ts +44 -0
  498. package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
  499. package/src/overlays/snapcompact-shape-preview.ts +192 -0
  500. package/src/overlays/theme-selector.ts +62 -0
  501. package/src/overlays/thinking-selector.ts +51 -0
  502. package/src/overlays/tiny-title-download-progress.ts +102 -0
  503. package/src/overlays/tree-selector.ts +1121 -0
  504. package/src/overlays/usage-dashboard.ts +629 -0
  505. package/src/overlays/usage-display.ts +45 -0
  506. package/src/overlays/usage-row.ts +118 -0
  507. package/src/prompt/attachment-chips.ts +201 -0
  508. package/src/prompt/composer-attachments.ts +280 -0
  509. package/src/prompt/composer-cache.ts +304 -0
  510. package/src/prompt/composer.ts +934 -0
  511. package/src/prompt/custom-editor.ts +1392 -0
  512. package/src/prompt/data/emojis.json +1 -0
  513. package/src/prompt/editor-top-gap.ts +28 -0
  514. package/src/prompt/emoji-autocomplete.ts +285 -0
  515. package/src/prompt/github-ref-autocomplete.ts +75 -0
  516. package/src/prompt/gradient-highlight.ts +101 -0
  517. package/src/prompt/image-format.ts +28 -0
  518. package/src/prompt/image-references.ts +102 -0
  519. package/src/prompt/interactive-context-helpers.ts +126 -0
  520. package/src/prompt/internal-url-autocomplete.ts +155 -0
  521. package/src/prompt/macos-spelling.ts +456 -0
  522. package/src/prompt/magic-keyword-boundary.ts +23 -0
  523. package/src/prompt/magic-keywords.ts +42 -0
  524. package/src/prompt/markdown-prose.ts +245 -0
  525. package/src/prompt/model-mention-autocomplete.ts +94 -0
  526. package/src/prompt/model-mention-syntax.ts +41 -0
  527. package/src/prompt/orchestrate.ts +26 -0
  528. package/src/prompt/prompt-action-autocomplete.ts +337 -0
  529. package/src/prompt/queue-input.ts +132 -0
  530. package/src/prompt/skill-tokens.ts +36 -0
  531. package/src/prompt/tips.txt +27 -0
  532. package/src/prompt/tools-markdown.ts +29 -0
  533. package/src/prompt/ultrathink.ts +26 -0
  534. package/src/prompt/usage-amounts.ts +99 -0
  535. package/src/prompt/video.ts +47 -0
  536. package/src/prompt/welcome.ts +605 -0
  537. package/src/prompt/workflow.ts +26 -0
  538. package/src/render/code-cell.ts +244 -0
  539. package/src/render/file-list.ts +58 -0
  540. package/src/render/hyperlink.ts +192 -0
  541. package/src/render/index.ts +17 -0
  542. package/src/render/output-block.ts +267 -0
  543. package/src/render/output-pane.ts +299 -0
  544. package/src/render/render-utils.ts +1182 -0
  545. package/src/render/sixel.ts +69 -0
  546. package/src/render/status-line.ts +55 -0
  547. package/src/render/tool-card.ts +272 -0
  548. package/src/render/tree-list.ts +188 -0
  549. package/src/render/types.ts +19 -0
  550. package/src/render/utils.ts +109 -0
  551. package/src/render/width-aware-text.ts +60 -0
  552. package/src/setup/lazy.ts +17 -0
  553. package/src/setup/scenes/composer.ts +127 -0
  554. package/src/setup/scenes/glyph.ts +120 -0
  555. package/src/setup/scenes/model.ts +138 -0
  556. package/src/setup/scenes/outro.ts +24 -0
  557. package/src/setup/scenes/providers.ts +107 -0
  558. package/src/setup/scenes/sign-in.ts +373 -0
  559. package/src/setup/scenes/splash.ts +192 -0
  560. package/src/setup/scenes/theme.ts +343 -0
  561. package/src/setup/scenes/types.ts +111 -0
  562. package/src/setup/scenes/web-search.ts +165 -0
  563. package/src/setup/setup-version.ts +11 -0
  564. package/src/setup/startup-splash.ts +107 -0
  565. package/src/setup/wizard-overlay.ts +319 -0
  566. package/src/setup/wizard.ts +101 -0
  567. package/src/status-line/component.ts +3003 -0
  568. package/src/status-line/context-usage.ts +688 -0
  569. package/src/status-line/footer.ts +323 -0
  570. package/src/status-line/git-utils.ts +42 -0
  571. package/src/status-line/host.ts +97 -0
  572. package/src/status-line/index.ts +6 -0
  573. package/src/status-line/loop.ts +28 -0
  574. package/src/status-line/metrics.ts +94 -0
  575. package/src/status-line/presets.ts +107 -0
  576. package/src/status-line/schema.ts +57 -0
  577. package/src/status-line/segments.ts +934 -0
  578. package/src/status-line/separators.ts +55 -0
  579. package/src/status-line/types.ts +227 -0
  580. package/src/stdin-buffer.ts +4 -2
  581. package/src/theme/color.ts +95 -0
  582. package/src/theme/dark.json +95 -0
  583. package/src/theme/defaults/alabaster.json +93 -0
  584. package/src/theme/defaults/amethyst.json +96 -0
  585. package/src/theme/defaults/anthracite.json +93 -0
  586. package/src/theme/defaults/basalt.json +91 -0
  587. package/src/theme/defaults/birch.json +95 -0
  588. package/src/theme/defaults/dark-abyss.json +91 -0
  589. package/src/theme/defaults/dark-arctic.json +104 -0
  590. package/src/theme/defaults/dark-aurora.json +95 -0
  591. package/src/theme/defaults/dark-catppuccin.json +107 -0
  592. package/src/theme/defaults/dark-cavern.json +91 -0
  593. package/src/theme/defaults/dark-celestial.json +106 -0
  594. package/src/theme/defaults/dark-copper.json +95 -0
  595. package/src/theme/defaults/dark-cosmos.json +90 -0
  596. package/src/theme/defaults/dark-cyberpunk.json +102 -0
  597. package/src/theme/defaults/dark-dracula.json +98 -0
  598. package/src/theme/defaults/dark-eclipse.json +91 -0
  599. package/src/theme/defaults/dark-ember.json +95 -0
  600. package/src/theme/defaults/dark-equinox.json +90 -0
  601. package/src/theme/defaults/dark-forest.json +96 -0
  602. package/src/theme/defaults/dark-github.json +105 -0
  603. package/src/theme/defaults/dark-gruvbox.json +112 -0
  604. package/src/theme/defaults/dark-lavender.json +95 -0
  605. package/src/theme/defaults/dark-lunar.json +89 -0
  606. package/src/theme/defaults/dark-midnight.json +95 -0
  607. package/src/theme/defaults/dark-monochrome.json +94 -0
  608. package/src/theme/defaults/dark-monokai.json +98 -0
  609. package/src/theme/defaults/dark-nebula.json +90 -0
  610. package/src/theme/defaults/dark-nord.json +98 -0
  611. package/src/theme/defaults/dark-ocean.json +101 -0
  612. package/src/theme/defaults/dark-one.json +100 -0
  613. package/src/theme/defaults/dark-poimandres.json +115 -0
  614. package/src/theme/defaults/dark-rainforest.json +91 -0
  615. package/src/theme/defaults/dark-reef.json +91 -0
  616. package/src/theme/defaults/dark-retro.json +92 -0
  617. package/src/theme/defaults/dark-rose-pine.json +96 -0
  618. package/src/theme/defaults/dark-sakura.json +95 -0
  619. package/src/theme/defaults/dark-slate.json +95 -0
  620. package/src/theme/defaults/dark-solarized.json +97 -0
  621. package/src/theme/defaults/dark-solstice.json +90 -0
  622. package/src/theme/defaults/dark-starfall.json +91 -0
  623. package/src/theme/defaults/dark-sunset.json +99 -0
  624. package/src/theme/defaults/dark-swamp.json +90 -0
  625. package/src/theme/defaults/dark-synthwave.json +103 -0
  626. package/src/theme/defaults/dark-taiga.json +91 -0
  627. package/src/theme/defaults/dark-terminal.json +95 -0
  628. package/src/theme/defaults/dark-tokyo-night.json +101 -0
  629. package/src/theme/defaults/dark-tundra.json +91 -0
  630. package/src/theme/defaults/dark-twilight.json +91 -0
  631. package/src/theme/defaults/dark-volcanic.json +91 -0
  632. package/src/theme/defaults/graphite.json +92 -0
  633. package/src/theme/defaults/index.ts +201 -0
  634. package/src/theme/defaults/light-arctic.json +107 -0
  635. package/src/theme/defaults/light-aurora-day.json +91 -0
  636. package/src/theme/defaults/light-canyon.json +91 -0
  637. package/src/theme/defaults/light-catppuccin.json +106 -0
  638. package/src/theme/defaults/light-cirrus.json +90 -0
  639. package/src/theme/defaults/light-coral.json +95 -0
  640. package/src/theme/defaults/light-cyberpunk.json +96 -0
  641. package/src/theme/defaults/light-dawn.json +90 -0
  642. package/src/theme/defaults/light-dunes.json +91 -0
  643. package/src/theme/defaults/light-eucalyptus.json +95 -0
  644. package/src/theme/defaults/light-forest.json +100 -0
  645. package/src/theme/defaults/light-frost.json +95 -0
  646. package/src/theme/defaults/light-github.json +115 -0
  647. package/src/theme/defaults/light-glacier.json +91 -0
  648. package/src/theme/defaults/light-gruvbox.json +108 -0
  649. package/src/theme/defaults/light-haze.json +90 -0
  650. package/src/theme/defaults/light-honeycomb.json +95 -0
  651. package/src/theme/defaults/light-lagoon.json +91 -0
  652. package/src/theme/defaults/light-lavender.json +95 -0
  653. package/src/theme/defaults/light-meadow.json +91 -0
  654. package/src/theme/defaults/light-mint.json +95 -0
  655. package/src/theme/defaults/light-monochrome.json +101 -0
  656. package/src/theme/defaults/light-ocean.json +99 -0
  657. package/src/theme/defaults/light-one.json +99 -0
  658. package/src/theme/defaults/light-opal.json +91 -0
  659. package/src/theme/defaults/light-orchard.json +91 -0
  660. package/src/theme/defaults/light-paper.json +95 -0
  661. package/src/theme/defaults/light-poimandres.json +115 -0
  662. package/src/theme/defaults/light-prism.json +90 -0
  663. package/src/theme/defaults/light-retro.json +98 -0
  664. package/src/theme/defaults/light-sand.json +95 -0
  665. package/src/theme/defaults/light-savanna.json +91 -0
  666. package/src/theme/defaults/light-solarized.json +102 -0
  667. package/src/theme/defaults/light-soleil.json +90 -0
  668. package/src/theme/defaults/light-sunset.json +99 -0
  669. package/src/theme/defaults/light-synthwave.json +98 -0
  670. package/src/theme/defaults/light-tokyo-night.json +111 -0
  671. package/src/theme/defaults/light-wetland.json +91 -0
  672. package/src/theme/defaults/light-zenith.json +89 -0
  673. package/src/theme/defaults/limestone.json +94 -0
  674. package/src/theme/defaults/mahogany.json +97 -0
  675. package/src/theme/defaults/marble.json +93 -0
  676. package/src/theme/defaults/obsidian.json +91 -0
  677. package/src/theme/defaults/onyx.json +91 -0
  678. package/src/theme/defaults/pearl.json +93 -0
  679. package/src/theme/defaults/porcelain.json +91 -0
  680. package/src/theme/defaults/quartz.json +96 -0
  681. package/src/theme/defaults/sandstone.json +95 -0
  682. package/src/theme/defaults/titanium.json +90 -0
  683. package/src/theme/index.ts +5 -0
  684. package/src/theme/light.json +93 -0
  685. package/src/theme/loader.ts +200 -0
  686. package/src/theme/mermaid-cache.ts +92 -0
  687. package/src/theme/schema-validation.ts +119 -0
  688. package/src/theme/schema.ts +168 -0
  689. package/src/theme/session-color.ts +253 -0
  690. package/src/theme/shimmer.ts +307 -0
  691. package/src/theme/symbols.ts +1433 -0
  692. package/src/theme/theme-class.ts +787 -0
  693. package/src/theme/theme-schema.json +463 -0
  694. package/src/theme/theme.ts +810 -0
  695. package/src/theme/tui-adapters.ts +339 -0
  696. package/src/thinking.ts +380 -0
  697. package/src/tools/agent-tree.ts +128 -0
  698. package/src/tools/ask.ts +482 -0
  699. package/src/tools/ast-edit.ts +210 -0
  700. package/src/tools/ast-grep.ts +171 -0
  701. package/src/tools/autoresearch.ts +287 -0
  702. package/src/tools/bash-interactive.ts +295 -0
  703. package/src/tools/bash.ts +468 -0
  704. package/src/tools/conflict-detect.ts +77 -0
  705. package/src/tools/debug.ts +167 -0
  706. package/src/tools/default-renderer.ts +172 -0
  707. package/src/tools/edit.ts +1258 -0
  708. package/src/tools/eval-format/code-mode-declarations.ts +61 -0
  709. package/src/tools/eval-format/index.ts +16 -0
  710. package/src/tools/eval-format/javascript.ts +952 -0
  711. package/src/tools/eval-format/python.ts +544 -0
  712. package/src/tools/eval.ts +835 -0
  713. package/src/tools/fetch.ts +226 -0
  714. package/src/tools/gh-format.ts +18 -0
  715. package/src/tools/github.ts +686 -0
  716. package/src/tools/glob.ts +213 -0
  717. package/src/tools/goal.ts +153 -0
  718. package/src/tools/grep.ts +385 -0
  719. package/src/tools/grouped-file-output.ts +211 -0
  720. package/src/tools/hashline-format.ts +59 -0
  721. package/src/tools/hub.ts +1488 -0
  722. package/src/tools/index.ts +71 -0
  723. package/src/tools/json-tree.ts +388 -0
  724. package/src/tools/line-ranges.ts +98 -0
  725. package/src/tools/list-limit.ts +43 -0
  726. package/src/tools/lsp.ts +702 -0
  727. package/src/tools/match-line-format.ts +20 -0
  728. package/src/tools/mcp.ts +309 -0
  729. package/src/tools/memory.ts +220 -0
  730. package/src/tools/output-meta.ts +367 -0
  731. package/src/tools/read.ts +628 -0
  732. package/src/tools/renderer.ts +107 -0
  733. package/src/tools/report-tool-issue.ts +13 -0
  734. package/src/tools/resolve.ts +139 -0
  735. package/src/tools/streaming-output.ts +1576 -0
  736. package/src/tools/subprocess.ts +39 -0
  737. package/src/tools/task-repair-args.ts +118 -0
  738. package/src/tools/task-yield-assembly.ts +147 -0
  739. package/src/tools/task.ts +2110 -0
  740. package/src/tools/terminal-output.ts +153 -0
  741. package/src/tools/think.ts +28 -0
  742. package/src/tools/todo.ts +580 -0
  743. package/src/tools/tool-errors.ts +15 -0
  744. package/src/tools/vibe.ts +420 -0
  745. package/src/tools/web-search.ts +409 -0
  746. package/src/tools/write.ts +511 -0
  747. package/src/tools/xd-url.ts +28 -0
  748. package/src/tools/xdev.ts +201 -0
  749. package/src/tui.ts +70 -8
  750. package/src/utils.ts +8 -0
@@ -0,0 +1,261 @@
1
+ import type { MouseRoutable, SgrMouseEvent } from "../../mouse";
2
+ import type { Component } from "../../tui";
3
+ import { padding } from "../../utils";
4
+ import {
5
+ allocateLayoutSpace,
6
+ equalLayoutInsets,
7
+ fitLayoutLine,
8
+ isLayoutMouseRoutable,
9
+ layoutAlignmentOffset,
10
+ type LayoutAlignment,
11
+ type LayoutContent,
12
+ layoutInsets,
13
+ type LayoutInsets,
14
+ type LayoutRect,
15
+ layoutSize,
16
+ optionalLayoutSize,
17
+ renderLayoutContent,
18
+ uniqueLayoutComponents,
19
+ } from "./geometry";
20
+
21
+ /** One child and its vertical row-budget constraints. */
22
+ export interface StackChild {
23
+ content: LayoutContent;
24
+ height?: number;
25
+ grow?: number;
26
+ minHeight?: number;
27
+ maxHeight?: number;
28
+ padding?: LayoutInsets;
29
+ align?: LayoutAlignment;
30
+ }
31
+
32
+ /** Construction options for {@link Stack}. */
33
+ export interface StackOptions {
34
+ children: readonly StackChild[];
35
+ height?: number;
36
+ align?: LayoutAlignment;
37
+ }
38
+
39
+ /** A stack hit translated into the child's local coordinates. */
40
+ export interface StackHit {
41
+ index: number;
42
+ content: LayoutContent;
43
+ line: number;
44
+ col: number;
45
+ rect: LayoutRect;
46
+ }
47
+
48
+ interface StackMemo {
49
+ width: number;
50
+ height: number | undefined;
51
+ heights: readonly number[];
52
+ lines: readonly (readonly string[])[];
53
+ result: readonly string[];
54
+ }
55
+
56
+ function sameChild(left: StackChild, right: StackChild): boolean {
57
+ return (
58
+ left.content === right.content &&
59
+ left.height === right.height &&
60
+ left.grow === right.grow &&
61
+ left.minHeight === right.minHeight &&
62
+ left.maxHeight === right.maxHeight &&
63
+ left.align === right.align &&
64
+ equalLayoutInsets(left.padding, right.padding)
65
+ );
66
+ }
67
+
68
+ /**
69
+ * Vertical component layout with fixed and growing regions, exact height
70
+ * budgets, ANSI-aware clipping, padding, and local mouse translation.
71
+ */
72
+ export class Stack implements Component, MouseRoutable {
73
+ #children: StackChild[];
74
+ #height: number | undefined;
75
+ #align: LayoutAlignment;
76
+ #frames: LayoutRect[] = [];
77
+ #memo: StackMemo | undefined;
78
+ #ignoreTight = false;
79
+
80
+ constructor(options: StackOptions) {
81
+ this.#children = options.children.map(child => ({ ...child, padding: { ...child.padding } }));
82
+ this.#height = optionalLayoutSize(options.height);
83
+ this.#align = options.align ?? "start";
84
+ }
85
+
86
+ /** Concrete component children exposed to the debug tree. */
87
+ get debugChildren(): readonly Component[] {
88
+ return uniqueLayoutComponents(this.#children.map(child => child.content));
89
+ }
90
+
91
+ /** Last-rendered content rectangle for `index`, excluding its padding. */
92
+ childRect(index: number): LayoutRect | undefined {
93
+ return this.#frames[index];
94
+ }
95
+
96
+ /** Replace the stack's children without recreating the layout component. */
97
+ setChildren(children: readonly StackChild[]): void {
98
+ if (
99
+ children.length === this.#children.length &&
100
+ children.every((child, index) => sameChild(child, this.#children[index]!))
101
+ ) {
102
+ return;
103
+ }
104
+ this.#children = children.map(child => ({ ...child, padding: { ...child.padding } }));
105
+ if (this.#ignoreTight) {
106
+ for (const child of uniqueLayoutComponents(this.#children.map(item => item.content))) {
107
+ child.setIgnoreTight?.(true);
108
+ }
109
+ }
110
+ this.#memo = undefined;
111
+ }
112
+
113
+ /** Set the exact total row budget, or clear it to use natural height. */
114
+ setHeight(height: number | undefined): void {
115
+ const next = optionalLayoutSize(height);
116
+ if (next === this.#height) return;
117
+ this.#height = next;
118
+ this.#memo = undefined;
119
+ }
120
+
121
+ setIgnoreTight(ignore: boolean): this {
122
+ if (ignore === this.#ignoreTight) return this;
123
+ this.#ignoreTight = ignore;
124
+ for (const child of uniqueLayoutComponents(this.#children.map(item => item.content))) {
125
+ child.setIgnoreTight?.(ignore);
126
+ }
127
+ this.#memo = undefined;
128
+ return this;
129
+ }
130
+
131
+ invalidate(): void {
132
+ this.#memo = undefined;
133
+ for (const child of uniqueLayoutComponents(this.#children.map(item => item.content))) {
134
+ child.invalidate?.();
135
+ }
136
+ }
137
+
138
+ dispose(): void {
139
+ for (const child of uniqueLayoutComponents(this.#children.map(item => item.content))) {
140
+ child.dispose?.();
141
+ }
142
+ }
143
+
144
+ /** Translate a stack-local point into a child's local coordinates. */
145
+ locate(line: number, col: number): StackHit | undefined {
146
+ for (let index = 0; index < this.#frames.length; index++) {
147
+ const rect = this.#frames[index];
148
+ if (!rect) continue;
149
+ if (line < rect.row || line >= rect.row + rect.height || col < rect.col || col >= rect.col + rect.width)
150
+ continue;
151
+ return {
152
+ index,
153
+ content: this.#children[index]!.content,
154
+ line: line - rect.row,
155
+ col: col - rect.col,
156
+ rect,
157
+ };
158
+ }
159
+ return undefined;
160
+ }
161
+
162
+ routeMouse(event: SgrMouseEvent, line: number, col: number): void {
163
+ const hit = this.locate(line, col);
164
+ if (hit && isLayoutMouseRoutable(hit.content)) hit.content.routeMouse(event, hit.line, hit.col);
165
+ }
166
+
167
+ render(width: number): readonly string[] {
168
+ width = layoutSize(width);
169
+ const insets = this.#children.map(child => layoutInsets(child.padding));
170
+ let heights = this.#children.map(child => {
171
+ if (child.height !== undefined) return layoutSize(child.height);
172
+ return this.#height !== undefined && layoutSize(child.grow) > 0 ? layoutSize(child.minHeight) : -1;
173
+ });
174
+ const childLines: (readonly string[])[] = Array.from({ length: this.#children.length }, () => []);
175
+ const rendered = this.#children.map(() => false);
176
+
177
+ for (let index = 0; index < this.#children.length; index++) {
178
+ if ((heights[index] ?? -1) >= 0) continue;
179
+ const inset = insets[index]!;
180
+ const contentWidth = Math.max(0, width - inset.left - inset.right);
181
+ const lines =
182
+ contentWidth > 0 ? renderLayoutContent(this.#children[index]!.content, contentWidth, undefined) : [];
183
+ childLines[index] = lines;
184
+ rendered[index] = true;
185
+ heights[index] = lines.length + inset.top + inset.bottom;
186
+ }
187
+
188
+ const naturalTotal = heights.reduce((sum, height) => sum + Math.max(0, height), 0);
189
+ heights = allocateLayoutSpace(
190
+ this.#children.map((child, index) => ({
191
+ fixed:
192
+ child.height !== undefined || this.#height === undefined || layoutSize(child.grow) === 0
193
+ ? heights[index]
194
+ : undefined,
195
+ grow: child.grow,
196
+ min: child.minHeight,
197
+ max: child.maxHeight,
198
+ })),
199
+ this.#height ?? naturalTotal,
200
+ );
201
+
202
+ for (let index = 0; index < this.#children.length; index++) {
203
+ if (rendered[index] || (heights[index] ?? 0) <= 0) continue;
204
+ const inset = insets[index]!;
205
+ const contentWidth = Math.max(0, width - inset.left - inset.right);
206
+ const contentHeight = Math.max(0, (heights[index] ?? 0) - inset.top - inset.bottom);
207
+ childLines[index] =
208
+ contentWidth > 0 ? renderLayoutContent(this.#children[index]!.content, contentWidth, contentHeight) : [];
209
+ rendered[index] = true;
210
+ }
211
+
212
+ let row = 0;
213
+ this.#frames = this.#children.map((_child, index) => {
214
+ const inset = insets[index]!;
215
+ const allocated = heights[index] ?? 0;
216
+ const rect: LayoutRect = {
217
+ row: row + inset.top,
218
+ col: inset.left,
219
+ width: Math.max(0, width - inset.left - inset.right),
220
+ height: Math.max(0, allocated - inset.top - inset.bottom),
221
+ };
222
+ row += allocated;
223
+ return rect;
224
+ });
225
+
226
+ const memo = this.#memo;
227
+ if (
228
+ memo &&
229
+ memo.width === width &&
230
+ memo.height === this.#height &&
231
+ memo.heights.length === heights.length &&
232
+ memo.heights.every((value, index) => value === heights[index]) &&
233
+ memo.lines.length === childLines.length &&
234
+ memo.lines.every((lines, index) => lines === childLines[index])
235
+ ) {
236
+ return memo.result;
237
+ }
238
+
239
+ const result: string[] = [];
240
+ for (let index = 0; index < this.#children.length; index++) {
241
+ const child = this.#children[index]!;
242
+ const inset = insets[index]!;
243
+ const allocated = heights[index] ?? 0;
244
+ const viewportHeight = Math.max(0, allocated - inset.top - inset.bottom);
245
+ const lines = childLines[index]!;
246
+ const visibleHeight = Math.min(viewportHeight, lines.length);
247
+ const offset = layoutAlignmentOffset(viewportHeight - visibleHeight, child.align ?? this.#align);
248
+ for (let line = 0; line < allocated; line++) {
249
+ const childLine = line - inset.top - offset;
250
+ const content = childLine >= 0 && childLine < visibleHeight ? (lines[childLine] ?? "") : "";
251
+ const innerWidth = Math.max(0, width - inset.left - inset.right);
252
+ result.push(
253
+ fitLayoutLine(padding(inset.left) + fitLayoutLine(content, innerWidth) + padding(inset.right), width),
254
+ );
255
+ }
256
+ }
257
+ while (this.#height !== undefined && result.length < this.#height) result.push(padding(width));
258
+ this.#memo = { width, height: this.#height, heights, lines: childLines, result };
259
+ return result;
260
+ }
261
+ }
@@ -2061,17 +2061,8 @@ export class Markdown implements Component {
2061
2061
  return EMPTY_RENDER_LINES;
2062
2062
  }
2063
2063
 
2064
- // Replace tabs with spaces, then repair orphan fences in final mode.
2065
- const tabbed = replaceTabs(this.#text);
2066
- const normalizedText = this.transientRenderCache ? tabbed : repairOrphanClosingFence(tabbed);
2067
- if (!this.transientRenderCache && normalizedText.length < tabbed.length) {
2068
- // repairOrphanClosingFence deleted bytes this frame (orphan fence
2069
- // removed): the guard-scan memo's checked region is no longer
2070
- // byte-identical, and a cached false verdict may have been based
2071
- // on the very CR/ref-def line that was deleted. Invalidate so the
2072
- // next #lexTokens re-derives on the repaired buffer.
2073
- this.#lastScanValid = false;
2074
- }
2064
+ // Fast-path inputs only: signature first, so the append-only branch below
2065
+ // can return without scanning the whole document for tabs.
2075
2066
  const signature = this.#renderSignature(width, paddingX);
2076
2067
  // B+ fast path: an append-only, same-line delta re-renders ONLY the
2077
2068
  // last content row (the paragraph's trailing wrapped row) with the
@@ -2197,7 +2188,20 @@ export class Markdown implements Component {
2197
2188
  // Hazard → disarm until the next real render re-captures.
2198
2189
  this.#fastTail = undefined;
2199
2190
  }
2200
- // Replace tabs with 3 spaces for consistent rendering
2191
+ // Normalize only after the append-only branch: the fast path above
2192
+ // returns without ever reading these, so streaming frames skip the
2193
+ // whole-document tab scan/copy (the delta-only replaceTabs inside the
2194
+ // branch is the only tab work a streamed frame pays).
2195
+ const tabbed = this.#text.includes("\t") ? replaceTabs(this.#text) : this.#text;
2196
+ const normalizedText = this.transientRenderCache ? tabbed : repairOrphanClosingFence(tabbed);
2197
+ if (!this.transientRenderCache && normalizedText.length < tabbed.length) {
2198
+ // repairOrphanClosingFence deleted bytes this frame (orphan fence
2199
+ // removed): the guard-scan memo's checked region is no longer
2200
+ // byte-identical, and a cached false verdict may have been based
2201
+ // on the very CR/ref-def line that was deleted. Invalidate so the
2202
+ // next #lexTokens re-derives on the repaired buffer.
2203
+ this.#lastScanValid = false;
2204
+ }
2201
2205
 
2202
2206
  // L2: module-level LRU — survives component disposal/recreation across
2203
2207
  // session-tree navigations. Key encodes every dimension that affects the
@@ -0,0 +1,248 @@
1
+ import { fuzzyFilter } from "../fuzzy";
2
+
3
+ /** Describes how a menu identifies, searches, disables, and confirms its items. */
4
+ export interface MenuSelectionAdapter<T> {
5
+ /** Stable identity used to retain selection while data or filtering changes. */
6
+ getKey: (item: T) => string;
7
+ /** Searchable text used by the default fuzzy filter. */
8
+ getSearchText: (item: T) => string;
9
+ /** Disabled items remain visible but are skipped by navigation and cannot activate. */
10
+ isDisabled?: (item: T) => boolean;
11
+ /** Items returning true require two activation requests without an intervening state change. */
12
+ requiresConfirmation?: (item: T) => boolean;
13
+ /** Optional domain-specific filtering/ranking. */
14
+ filter?: (items: readonly T[], query: string) => readonly T[];
15
+ }
16
+
17
+ /** Result of requesting activation of the current menu item. */
18
+ export type MenuActivation<T> =
19
+ | { kind: "empty" }
20
+ | { kind: "disabled"; item: T }
21
+ | { kind: "pending"; item: T }
22
+ | { kind: "confirmed"; item: T };
23
+
24
+ /** A viewport over variable-height items. */
25
+ export interface MenuWindow {
26
+ startIndex: number;
27
+ endIndex: number;
28
+ /** Number of visual rows before startIndex, for scrollbar positioning. */
29
+ rowOffset: number;
30
+ /** Total visual rows across every item. */
31
+ totalRows: number;
32
+ }
33
+
34
+ /**
35
+ * Pick a selection-centered, contiguous window whose visual rows fit `rowBudget`.
36
+ * A selected item taller than the budget is retained and clipped by the renderer.
37
+ */
38
+ export function getMenuWindow(rowCounts: readonly number[], selectedIndex: number, rowBudget: number): MenuWindow {
39
+ let totalRows = 0;
40
+ for (const count of rowCounts) totalRows += Math.max(0, count);
41
+ if (rowCounts.length === 0) return { startIndex: 0, endIndex: 0, rowOffset: 0, totalRows };
42
+
43
+ const budget = Math.max(1, Math.trunc(rowBudget));
44
+ const selected = Math.max(0, Math.min(Math.trunc(selectedIndex), rowCounts.length - 1));
45
+ const selectedRows = Math.max(0, rowCounts[selected] ?? 0);
46
+ const targetRowsBeforeSelection = Math.floor(Math.max(0, budget - Math.min(selectedRows, budget)) / 2);
47
+ let startIndex = selected;
48
+ let rowsBeforeSelection = 0;
49
+ while (startIndex > 0) {
50
+ const cost = Math.max(0, rowCounts[startIndex - 1] ?? 0);
51
+ if (rowsBeforeSelection + cost > targetRowsBeforeSelection) break;
52
+ startIndex--;
53
+ rowsBeforeSelection += cost;
54
+ }
55
+
56
+ let endIndex = selected + 1;
57
+ let used = rowsBeforeSelection + selectedRows;
58
+ while (endIndex < rowCounts.length) {
59
+ const cost = Math.max(0, rowCounts[endIndex] ?? 0);
60
+ if (used + cost > budget) break;
61
+ used += cost;
62
+ endIndex++;
63
+ }
64
+ while (startIndex > 0) {
65
+ const cost = Math.max(0, rowCounts[startIndex - 1] ?? 0);
66
+ if (used + cost > budget) break;
67
+ startIndex--;
68
+ used += cost;
69
+ }
70
+
71
+ let rowOffset = 0;
72
+ for (let index = 0; index < startIndex; index++) rowOffset += Math.max(0, rowCounts[index] ?? 0);
73
+ return { startIndex, endIndex, rowOffset, totalRows };
74
+ }
75
+
76
+ /**
77
+ * Controlled menu data, filtering, selection, disabled-row navigation, and
78
+ * confirmation state. Renderers remain domain-owned and consume `visibleItems`.
79
+ */
80
+ export class MenuSelection<T> {
81
+ #items: readonly T[];
82
+ #visibleItems: readonly T[];
83
+ #query = "";
84
+ #selectedIndex = -1;
85
+ #pendingKey: string | undefined;
86
+
87
+ constructor(
88
+ items: readonly T[],
89
+ readonly adapter: MenuSelectionAdapter<T>,
90
+ initialKey?: string,
91
+ ) {
92
+ this.#items = items;
93
+ this.#visibleItems = items;
94
+ this.#selectedIndex = this.#findInitialIndex(initialKey);
95
+ }
96
+
97
+ get items(): readonly T[] {
98
+ return this.#items;
99
+ }
100
+
101
+ get visibleItems(): readonly T[] {
102
+ return this.#visibleItems;
103
+ }
104
+
105
+ get query(): string {
106
+ return this.#query;
107
+ }
108
+
109
+ get selectedIndex(): number {
110
+ return this.#selectedIndex;
111
+ }
112
+
113
+ get selectedItem(): T | undefined {
114
+ return this.#visibleItems[this.#selectedIndex];
115
+ }
116
+
117
+ get selectedKey(): string | undefined {
118
+ const item = this.selectedItem;
119
+ return item === undefined ? undefined : this.adapter.getKey(item);
120
+ }
121
+
122
+ get pendingKey(): string | undefined {
123
+ return this.#pendingKey;
124
+ }
125
+
126
+ isDisabled(item: T): boolean {
127
+ return this.adapter.isDisabled?.(item) ?? false;
128
+ }
129
+
130
+ isPending(item: T): boolean {
131
+ return this.#pendingKey === this.adapter.getKey(item);
132
+ }
133
+
134
+ /** Replace controlled data, retaining the selected key when it remains visible. */
135
+ setItems(items: readonly T[], selectedKey = this.selectedKey): boolean {
136
+ const previousKey = this.selectedKey;
137
+ this.#items = items;
138
+ this.#applyFilter(selectedKey);
139
+ this.#pendingKey = undefined;
140
+ return previousKey !== this.selectedKey;
141
+ }
142
+
143
+ /** Set the query and retain the selected key when it survives filtering. */
144
+ setQuery(query: string, retainSelection = true): boolean {
145
+ if (query === this.#query) return false;
146
+ const previousKey = this.selectedKey;
147
+ this.#query = query;
148
+ this.#pendingKey = undefined;
149
+ this.#applyFilter(retainSelection ? previousKey : undefined);
150
+ return previousKey !== this.selectedKey;
151
+ }
152
+
153
+ /** Select a visible row, coercing disabled rows to the nearest enabled row. */
154
+ setSelectedIndex(index: number, direction: -1 | 1 = 1): boolean {
155
+ const next = this.#coerceIndex(index, direction);
156
+ if (next === this.#selectedIndex) return false;
157
+ this.#selectedIndex = next;
158
+ this.#pendingKey = undefined;
159
+ return true;
160
+ }
161
+
162
+ setSelectedKey(key: string): boolean {
163
+ const index = this.#visibleItems.findIndex(item => this.adapter.getKey(item) === key);
164
+ return index >= 0 ? this.setSelectedIndex(index) : false;
165
+ }
166
+
167
+ /** Move by item count, optionally wrapping at list edges. */
168
+ move(delta: number, wrap = false): boolean {
169
+ const total = this.#visibleItems.length;
170
+ if (total === 0 || delta === 0) return false;
171
+ const direction: -1 | 1 = delta < 0 ? -1 : 1;
172
+ let remaining = Math.max(1, Math.abs(Math.trunc(delta)));
173
+ let index = this.#selectedIndex;
174
+ for (let attempts = 0; attempts < total && remaining > 0; attempts++) {
175
+ let next = index + direction;
176
+ if (next < 0 || next >= total) {
177
+ if (!wrap) break;
178
+ next = direction > 0 ? 0 : total - 1;
179
+ }
180
+ if (next === index) break;
181
+ index = next;
182
+ const item = this.#visibleItems[index];
183
+ if (item !== undefined && !this.isDisabled(item)) remaining--;
184
+ }
185
+ return index !== this.#selectedIndex && this.setSelectedIndex(index, direction);
186
+ }
187
+
188
+ moveToBoundary(boundary: "first" | "last"): boolean {
189
+ return this.setSelectedIndex(
190
+ boundary === "first" ? 0 : this.#visibleItems.length - 1,
191
+ boundary === "first" ? 1 : -1,
192
+ );
193
+ }
194
+
195
+ /** Clear a pending confirmation. Returns true only when one was cleared. */
196
+ cancelConfirmation(): boolean {
197
+ if (this.#pendingKey === undefined) return false;
198
+ this.#pendingKey = undefined;
199
+ return true;
200
+ }
201
+
202
+ requestActivation(index = this.#selectedIndex): MenuActivation<T> {
203
+ const item = this.#visibleItems[index];
204
+ if (item === undefined) return { kind: "empty" };
205
+ if (this.isDisabled(item)) return { kind: "disabled", item };
206
+ const key = this.adapter.getKey(item);
207
+ if (this.adapter.requiresConfirmation?.(item) === true && this.#pendingKey !== key) {
208
+ this.#pendingKey = key;
209
+ return { kind: "pending", item };
210
+ }
211
+ this.#pendingKey = undefined;
212
+ return { kind: "confirmed", item };
213
+ }
214
+
215
+ #applyFilter(preferredKey: string | undefined): void {
216
+ const query = this.#query.trim();
217
+ this.#visibleItems = query
218
+ ? (this.adapter.filter?.(this.#items, query) ??
219
+ fuzzyFilter([...this.#items], query, item => this.adapter.getSearchText(item)))
220
+ : this.#items;
221
+ this.#selectedIndex = this.#findInitialIndex(preferredKey);
222
+ }
223
+
224
+ #findInitialIndex(preferredKey: string | undefined): number {
225
+ if (this.#visibleItems.length === 0) return -1;
226
+ if (preferredKey !== undefined) {
227
+ const preferred = this.#visibleItems.findIndex(item => this.adapter.getKey(item) === preferredKey);
228
+ if (preferred >= 0 && !this.isDisabled(this.#visibleItems[preferred]!)) return preferred;
229
+ }
230
+ return this.#coerceIndex(0, 1);
231
+ }
232
+
233
+ #coerceIndex(index: number, direction: -1 | 1): number {
234
+ if (this.#visibleItems.length === 0) return -1;
235
+ const clamped = Math.max(0, Math.min(Math.trunc(index), this.#visibleItems.length - 1));
236
+ const candidate = this.#visibleItems[clamped];
237
+ if (candidate !== undefined && !this.isDisabled(candidate)) return clamped;
238
+ for (let next = clamped + direction; next >= 0 && next < this.#visibleItems.length; next += direction) {
239
+ const item = this.#visibleItems[next];
240
+ if (item !== undefined && !this.isDisabled(item)) return next;
241
+ }
242
+ for (let next = clamped - direction; next >= 0 && next < this.#visibleItems.length; next -= direction) {
243
+ const item = this.#visibleItems[next];
244
+ if (item !== undefined && !this.isDisabled(item)) return next;
245
+ }
246
+ return clamped;
247
+ }
248
+ }
@@ -0,0 +1,132 @@
1
+ import type { Component } from "../tui";
2
+ import { Ellipsis, getWidthConfigEpoch, truncateToWidth, visibleWidth } from "../utils";
3
+ import { Text } from "./text";
4
+
5
+ /** One preformatted metric. Domain-specific number, cost, and quota policy stays with the caller. */
6
+ export interface MetricSpec {
7
+ /** Undefined omits the metric; an empty string and zero-like strings remain observable values. */
8
+ readonly value: string | undefined;
9
+ /** Optional icon or label placed before the value. */
10
+ readonly leading?: string;
11
+ /** Separator between `leading` and `value`. */
12
+ readonly separator?: string;
13
+ /** Higher-priority metrics survive first when a row uses `drop` overflow. */
14
+ readonly priority?: number;
15
+ /** Render-time styling for the complete metric. */
16
+ readonly style?: (text: string) => string;
17
+ }
18
+
19
+ /** Width behavior for an inline metric row. */
20
+ export type MetricOverflow = "allow" | "drop" | "truncate" | "wrap";
21
+
22
+ /** Presentation options shared by {@link formatMetricRow} and {@link MetricRow}. */
23
+ export interface MetricRowOptions {
24
+ readonly separator?: string;
25
+ readonly overflow?: MetricOverflow;
26
+ readonly maxWidth?: number;
27
+ readonly paddingX?: number;
28
+ readonly paddingY?: number;
29
+ readonly style?: (text: string) => string;
30
+ }
31
+
32
+ /** Format one metric without imposing domain-specific value policy. */
33
+ export function formatMetric(metric: MetricSpec): string | undefined {
34
+ if (metric.value === undefined) return undefined;
35
+ const text =
36
+ metric.leading !== undefined ? `${metric.leading}${metric.separator ?? " "}${metric.value}` : metric.value;
37
+ return metric.style ? metric.style(text) : text;
38
+ }
39
+
40
+ /**
41
+ * Join metrics in declaration order. `drop` removes the lowest-priority metric
42
+ * first (rightmost on ties); `truncate` clips the complete row. `wrap` is
43
+ * applied by {@link MetricRow}, where the component owns the available width.
44
+ */
45
+ export function formatMetricRow(metrics: readonly MetricSpec[], options: MetricRowOptions = {}): string {
46
+ const separator = options.separator ?? " ";
47
+ const entries = metrics.flatMap((metric, index) => {
48
+ const text = formatMetric(metric);
49
+ return text === undefined ? [] : [{ text, index, priority: metric.priority ?? 0 }];
50
+ });
51
+ if (entries.length === 0) return "";
52
+
53
+ const maxWidth = options.maxWidth;
54
+ const overflow = options.overflow ?? "allow";
55
+ const join = (): string => entries.map(entry => entry.text).join(separator);
56
+ if (maxWidth === undefined || overflow === "allow" || overflow === "wrap") return join();
57
+
58
+ if (overflow === "truncate") {
59
+ return truncateToWidth(join(), Math.max(0, maxWidth));
60
+ }
61
+
62
+ while (entries.length > 1 && visibleWidth(join()) > maxWidth) {
63
+ let dropIndex = 0;
64
+ for (let i = 1; i < entries.length; i += 1) {
65
+ const candidate = entries[i]!;
66
+ const current = entries[dropIndex]!;
67
+ if (
68
+ candidate.priority < current.priority ||
69
+ (candidate.priority === current.priority && candidate.index > current.index)
70
+ ) {
71
+ dropIndex = i;
72
+ }
73
+ }
74
+ entries.splice(dropIndex, 1);
75
+ }
76
+ return join();
77
+ }
78
+
79
+ /**
80
+ * Component form of an inline metric row. It delegates ANSI-aware wrapping,
81
+ * padding, theme invalidation, and stable unchanged-render arrays to {@link Text}.
82
+ */
83
+ export class MetricRow implements Component {
84
+ #metrics: readonly MetricSpec[];
85
+ readonly #options: MetricRowOptions;
86
+ readonly #text: Text;
87
+ #cache: { width: number; epoch: number; source: readonly string[]; lines: readonly string[] } | undefined;
88
+
89
+ constructor(metrics: readonly MetricSpec[], options: MetricRowOptions = {}) {
90
+ this.#metrics = metrics;
91
+ this.#options = options;
92
+ this.#text = new Text("", options.paddingX ?? 0, options.paddingY ?? 0).setStyleFn(options.style);
93
+ }
94
+
95
+ setMetrics(metrics: readonly MetricSpec[]): boolean {
96
+ if (this.#metrics === metrics) return false;
97
+ this.#metrics = metrics;
98
+ this.#cache = undefined;
99
+ return true;
100
+ }
101
+
102
+ invalidate(): void {
103
+ this.#text.invalidate();
104
+ this.#cache = undefined;
105
+ }
106
+
107
+ render(width: number): readonly string[] {
108
+ const renderWidth = Number.isFinite(width) ? Math.max(0, Math.trunc(width)) : 0;
109
+ const paddingX =
110
+ this.#options.paddingX !== undefined && Number.isFinite(this.#options.paddingX)
111
+ ? Math.max(0, Math.trunc(this.#options.paddingX))
112
+ : 0;
113
+ const maxWidth = Math.max(0, renderWidth - paddingX * 2);
114
+ this.#text.setText(
115
+ formatMetricRow(this.#metrics, {
116
+ ...this.#options,
117
+ maxWidth,
118
+ overflow: this.#options.overflow === "wrap" ? "allow" : this.#options.overflow,
119
+ }),
120
+ );
121
+ const source = this.#text.render(renderWidth);
122
+ const epoch = getWidthConfigEpoch();
123
+ if (this.#cache?.width === renderWidth && this.#cache.epoch === epoch && this.#cache.source === source) {
124
+ return this.#cache.lines;
125
+ }
126
+ const lines = source.every(line => visibleWidth(line) <= renderWidth)
127
+ ? source
128
+ : source.map(line => truncateToWidth(line, renderWidth, Ellipsis.Omit));
129
+ this.#cache = { width: renderWidth, epoch, source, lines };
130
+ return lines;
131
+ }
132
+ }