@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,287 @@
1
+ import { applyBackgroundToLine, padding, visibleWidth } from "../utils";
2
+ import { type Component, Container } from "../tui";
3
+ import { Disclosure } from "../components/disclosure";
4
+ import { Markdown } from "../components/markdown";
5
+ import { formatBytes } from "@oh-my-pi/pi-utils";
6
+ import { ensureThemeSync, getMarkdownTheme, theme } from "../theme";
7
+ import {
8
+ attachmentSgr,
9
+ collapseImageMarkers,
10
+ COMPOSER_TOKEN_REGEX,
11
+ composerTokenRegex,
12
+ modelChipStyle,
13
+ modelMentionChipLabel,
14
+ renderPlaceholders,
15
+ skillChipStyle,
16
+ } from "../prompt/composer-attachments";
17
+ import { MODEL_MENTION_TAG_RE } from "../prompt/model-mention-syntax";
18
+ import { fileHyperlink } from "../render";
19
+ import { imageReferenceHyperlink } from "../prompt/image-references";
20
+ import { highlightMagicKeywords } from "../prompt/magic-keywords";
21
+ import type { ReactionTarget } from "./reaction";
22
+
23
+ // OSC 133 shell integration: marks prompt zones for terminal multiplexers.
24
+ //
25
+ // The zone must be *closed* within the same render. `133;B` sets a sticky
26
+ // cursor semantic of `.input` in Ghostty (and Ghostty-derived terminals such
27
+ // as cmux) that only a command-start marker clears; leaving it latched makes
28
+ // `cursorIsAtPrompt()` permanently true and tags every subsequently painted
29
+ // cell as `.input`. Combined with `cursor-click-to-move = true` (Ghostty's
30
+ // default) that turns every left-click inside the pane into a burst of
31
+ // synthesized arrow keys on omp's pty, slamming the editor caret to column 0
32
+ // (#8030, #6115).
33
+ //
34
+ // `133;C` is therefore emitted immediately followed by `133;D;0` at the end of
35
+ // the bubble. That clears the input state without reintroducing the grouping
36
+ // problem the marker was originally omitted to avoid: the command zone opens
37
+ // and finishes inside this component, so later assistant/tool output can never
38
+ // be grouped under the first submitted prompt.
39
+ const OSC133_ZONE_START = "\x1b]133;A\x07";
40
+ const OSC133_ZONE_END = "\x1b]133;B\x07";
41
+ const OSC133_COMMAND_START = "\x1b]133;C\x07";
42
+ const OSC133_COMMAND_DONE = "\x1b]133;D;0\x07";
43
+ const OSC133_ZONE_CLOSE = OSC133_ZONE_END + OSC133_COMMAND_START + OSC133_COMMAND_DONE;
44
+
45
+ /** How a user bubble styles its prose and chips (see {@link userBubbleColor}). */
46
+ export interface UserBubbleOptions {
47
+ /** Materialized `file://` targets per attached image, indexed by chip number. */
48
+ imageLinks?: readonly (string | undefined)[];
49
+ /** Agent-attributed input: dim, flat prose. */
50
+ synthetic?: boolean;
51
+ /** SKILL.md path for a skill chip by name; `undefined` leaves the chip unlinked. */
52
+ skillPath?: (name: string) => string | undefined;
53
+ }
54
+
55
+ /**
56
+ * Foreground styling for prose inside a user bubble: the bubble text color with the
57
+ * magic-keyword glow, attachment chips in their composer identity color, and skill
58
+ * chips as soft pills (linked to their SKILL.md) — each token restoring the bubble's
59
+ * own foreground after it. Shared by {@link UserMessageComponent} and the skill
60
+ * callout so both read as one turn.
61
+ */
62
+ export function userBubbleColor(
63
+ options: UserBubbleOptions = {},
64
+ tokenRegex: RegExp = COMPOSER_TOKEN_REGEX,
65
+ ): (value: string) => string {
66
+ const { imageLinks, synthetic = false, skillPath } = options;
67
+ // The Markdown component routes code spans and fenced blocks through its own code styling
68
+ // (never `color`), so those are already excluded; `highlightMagicKeywords` additionally
69
+ // restores the bubble's own foreground after each painted keyword so the gradient never
70
+ // bleeds into the rest of the line.
71
+ const keywordReset = theme.getFgOnBgAnsi("userMessageText", "userMessageBg");
72
+ const bubbleReset = `${keywordReset}${theme.getBgAnsi("userMessageBg")}`;
73
+ const renderText = synthetic
74
+ ? (text: string) => theme.fg("dim", text)
75
+ : (text: string) => theme.fgOnBg("userMessageText", "userMessageBg", highlightMagicKeywords(text, keywordReset));
76
+ return (value: string) =>
77
+ renderPlaceholders(
78
+ value,
79
+ {
80
+ renderText,
81
+ renderSkill: (label, name) => {
82
+ const styled = skillChipStyle(label, bubbleReset);
83
+ const path = skillPath?.(name);
84
+ return path ? fileHyperlink(path, styled, { line: 1 }) : styled;
85
+ },
86
+ renderMention: label => modelChipStyle(label, bubbleReset),
87
+ renderReference: (label, kind, index, form) => {
88
+ // Chip tokens keep their composer identity color; the bubble's own
89
+ // foreground resumes after the token (same pattern as keywords).
90
+ const styled =
91
+ form === "chip"
92
+ ? `${attachmentSgr(kind, index)}\x1b[1m${label}\x1b[22m${keywordReset}`
93
+ : theme.fg("accent", `\x1b[1m${label}\x1b[22m`);
94
+ return kind === "image" || kind === "video"
95
+ ? imageReferenceHyperlink(label, index, imageLinks, () => styled)
96
+ : styled;
97
+ },
98
+ },
99
+ tokenRegex,
100
+ );
101
+ }
102
+
103
+ /**
104
+ * Component that renders a user message. Accepts an agent reaction badge
105
+ * (see {@link ReactionTarget}) drawn right-aligned in the bubble's top padding row.
106
+ */
107
+ export class UserMessageComponent extends Container implements ReactionTarget {
108
+ // Memoized OSC 133 zone wrapping keyed on the underlying container render
109
+ // (same source ref ⇒ identical rows ⇒ reuse the wrapped copy). Keeps this
110
+ // component reference-stable for the transcript's incremental assembly and
111
+ // never mutates the container's cached array.
112
+ #zoneSource: readonly string[] | undefined;
113
+ #zoneLines: string[] | undefined;
114
+ readonly #bgColor: (value: string) => string;
115
+ #reaction: string | undefined;
116
+
117
+ constructor(text: string, options: UserBubbleOptions = {}) {
118
+ super();
119
+ ensureThemeSync();
120
+ // Display-only collapse: the stored/wire text carries bracketed `[Image #N, WxH]` markers,
121
+ // but the transcript shows the same compact `<icon> #N` chip the composer used. Runs before
122
+ // Markdown layout so wrapping and bubble padding are computed on the visible text.
123
+ text = collapseImageMarkers(text, Number.POSITIVE_INFINITY, () => {});
124
+ const mentionLabels: string[] = [];
125
+ MODEL_MENTION_TAG_RE.lastIndex = 0;
126
+ text = text.replace(MODEL_MENTION_TAG_RE, (_tag, _agent: string, name: string) => {
127
+ const label = modelMentionChipLabel(name);
128
+ mentionLabels.push(label);
129
+ return label;
130
+ });
131
+ const bgColor = (value: string) => theme.bg("userMessageBg", value);
132
+ this.#bgColor = bgColor;
133
+ const md = new Markdown(text, 1, 1, getMarkdownTheme(), {
134
+ bgColor,
135
+ color: userBubbleColor(options, composerTokenRegex(mentionLabels)),
136
+ });
137
+ md.setIgnoreTight(true);
138
+ this.addChild(md);
139
+ }
140
+
141
+ setReaction(emoji: string): void {
142
+ if (this.#reaction === emoji) return;
143
+ this.#reaction = emoji;
144
+ this.#zoneLines = undefined;
145
+ }
146
+
147
+ /** The top padding row with the reaction badge right-aligned inside the horizontal padding. */
148
+ #reactionRow(width: number): string {
149
+ const emoji = this.#reaction!;
150
+ return applyBackgroundToLine(padding(width - 1 - visibleWidth(emoji)) + emoji, width, this.#bgColor);
151
+ }
152
+
153
+ override render(width: number): readonly string[] {
154
+ const lines = super.render(width);
155
+ if (lines.length === 0) {
156
+ return lines;
157
+ }
158
+ if (this.#zoneSource === lines && this.#zoneLines !== undefined) {
159
+ return this.#zoneLines;
160
+ }
161
+ const wrapped = lines.slice();
162
+ if (this.#reaction !== undefined) wrapped[0] = this.#reactionRow(width);
163
+ wrapped[0] = OSC133_ZONE_START + wrapped[0];
164
+ wrapped[wrapped.length - 1] = wrapped[wrapped.length - 1] + OSC133_ZONE_CLOSE;
165
+ this.#zoneSource = lines;
166
+ this.#zoneLines = wrapped;
167
+ return wrapped;
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Always-visible dim summary row for a collapsed synthetic input. Kept as a
173
+ * small domain renderer so the width-truncated label never pays Markdown
174
+ * layout; the heavy body lives in the {@link Disclosure} detail slot.
175
+ */
176
+ class SyntheticSummary implements Component {
177
+ readonly #summary: string;
178
+ #cache: { width: number; lines: readonly string[] } | undefined;
179
+
180
+ constructor(summary: string) {
181
+ this.#summary = summary;
182
+ }
183
+
184
+ invalidate(): void {
185
+ this.#cache = undefined;
186
+ }
187
+
188
+ render(width: number): readonly string[] {
189
+ width = Math.max(1, width);
190
+ if (this.#cache?.width === width) return this.#cache.lines;
191
+ const hint = `${theme.sep.dot.trim()} ctrl+o`;
192
+ const lines = [` ${theme.fg("dim", truncateSummary(`${this.#summary} ${hint}`, Math.max(10, width - 1)))}`];
193
+ this.#cache = { width, lines };
194
+ return lines;
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Collapsed placeholder for a synthetic (agent-attributed) user input in the
200
+ * file/remote-backed transcript viewer — chiefly the advisor's `Session update`
201
+ * replay dumps, which can each be hundreds of KiB of Markdown and, on cold open,
202
+ * blocked the TUI for tens of seconds while every historical body was laid out
203
+ * before the viewport clip (issue #6308).
204
+ *
205
+ * Collapsed by default: renders one dim summary row (label · size · line count ·
206
+ * expand hint) and builds NO Markdown. The heavy {@link UserMessageComponent} is
207
+ * constructed lazily only when expanded via `ctrl+o`, so blocks above the
208
+ * viewport never pay layout cost until the reader asks to see them. The raw
209
+ * observability data stays intact in `__advisor.jsonl`.
210
+ */
211
+ export class CollapsedSyntheticMessageComponent implements Component {
212
+ #disclosure: Disclosure;
213
+
214
+ readonly #text: string;
215
+ readonly #imageLinks?: readonly (string | undefined)[];
216
+
217
+ constructor(text: string, imageLinks?: readonly (string | undefined)[]) {
218
+ this.#text = text;
219
+ this.#imageLinks = imageLinks;
220
+
221
+ // The heavy UserMessageComponent is constructed lazily only on the
222
+ // first expanded render and retained across collapse/re-expand cycles.
223
+ this.#disclosure = new Disclosure({
224
+ summary: new SyntheticSummary(summarizeSyntheticInput(text)),
225
+ body: () => new UserMessageComponent(this.#text, { synthetic: true, imageLinks: this.#imageLinks }),
226
+ });
227
+ }
228
+
229
+ /** ctrl+o toggle: reveal/hide the full Markdown body. */
230
+ setExpanded(expanded: boolean): void {
231
+ this.#disclosure.setExpanded(expanded);
232
+ }
233
+
234
+ setIgnoreTight(ignore: boolean): this {
235
+ this.#disclosure.setIgnoreTight(ignore);
236
+ return this;
237
+ }
238
+
239
+ invalidate(): void {
240
+ this.#disclosure.invalidate();
241
+ }
242
+
243
+ dispose(): void {
244
+ this.#disclosure.dispose();
245
+ }
246
+
247
+ render(width: number): readonly string[] {
248
+ return this.#disclosure.render(width);
249
+ }
250
+ }
251
+
252
+ /** Truncate a plain summary label to `maxWidth` display columns, appending `…`. */
253
+ function truncateSummary(text: string, maxWidth: number): string {
254
+ if (Bun.stringWidth(text, { countAnsiEscapeCodes: false }) <= maxWidth) return text;
255
+ let out = "";
256
+ let w = 0;
257
+ for (const ch of text) {
258
+ const cw = Bun.stringWidth(ch, { countAnsiEscapeCodes: false });
259
+ if (w + cw > maxWidth - 1) break;
260
+ out += ch;
261
+ w += cw;
262
+ }
263
+ return `${out}…`;
264
+ }
265
+
266
+ /**
267
+ * One-line summary for a collapsed synthetic input: `<label> · <size> · <n>
268
+ * lines`. The label is the first Markdown heading's text (e.g. `Session
269
+ * update`), falling back to `Synthetic input` when the body opens with none.
270
+ */
271
+ function summarizeSyntheticInput(text: string): string {
272
+ const size = formatBytes(Buffer.byteLength(text, "utf-8"));
273
+ const lineCount = text === "" ? 0 : text.split("\n").length;
274
+ const dot = theme.sep.dot.trim();
275
+ return `${syntheticInputLabel(text)} ${dot} ${size} ${dot} ${lineCount} line${lineCount === 1 ? "" : "s"}`;
276
+ }
277
+
278
+ /** First Markdown heading text in `text`, else `Synthetic input`. */
279
+ function syntheticInputLabel(text: string): string {
280
+ for (const raw of text.split("\n")) {
281
+ const line = raw.trim();
282
+ if (!line) continue;
283
+ const heading = /^#{1,6}\s+(.*)$/.exec(line);
284
+ return heading ? heading[1]!.trim() || "Synthetic input" : "Synthetic input";
285
+ }
286
+ return "Synthetic input";
287
+ }
@@ -0,0 +1,110 @@
1
+ import { Container } from "../tui";
2
+ /**
3
+ * Capabilities a mounted {@link ChatBlock} may use against its host transcript.
4
+ * Kept minimal so blocks never reach into the full TUI/InteractiveMode surface.
5
+ */
6
+ export interface ChatBlockHost {
7
+ /** Schedule a repaint of the transcript. */
8
+ requestRender(): void;
9
+ }
10
+
11
+ /**
12
+ * Lifecycle-aware transcript block — the "return a block, let the host mount it"
13
+ * primitive, modelled on React/Svelte component lifecycles.
14
+ *
15
+ * Producers build and return a `ChatBlock` instead of poking `chatContainer` and
16
+ * `ui.requestRender()` directly. The host (`ctx.present`) appends it and calls
17
+ * {@link mount}, which runs {@link onMount}; effects started there register
18
+ * teardown via {@link onCleanup}. The block repaints through {@link requestRender}
19
+ * — never touching the TUI — and tears down exactly once on {@link finish}
20
+ * (self-complete: stop the animation, keep the final frame in the transcript) or
21
+ * {@link dispose} (host discards it, e.g. a transcript reset).
22
+ *
23
+ * While mounted and unfinished a block reports `isTranscriptBlockFinalized() ===
24
+ * false` so {@link "../components/transcript-container".TranscriptContainer}
25
+ * keeps it in the live, repaintable region on ED3-risk terminals; after
26
+ * `finish()`/`dispose()` it reports `true` and freezes at its final content.
27
+ */
28
+ export abstract class ChatBlock extends Container {
29
+ #host: ChatBlockHost | undefined;
30
+ #cleanups: Array<() => void> = [];
31
+ #active = false;
32
+ #disposed = false;
33
+
34
+ /**
35
+ * Run setup after the block is in the transcript: start timers/subscriptions
36
+ * and register their teardown with {@link onCleanup}. Default: no-op (a block
37
+ * whose content is fixed at construction needs no mount work).
38
+ */
39
+ protected onMount(): void {}
40
+
41
+ /**
42
+ * Register a teardown to run on {@link finish}/{@link dispose}, à la a
43
+ * `useEffect` cleanup. If the block is already disposed the cleanup runs
44
+ * immediately so callers never leak.
45
+ */
46
+ protected onCleanup(cleanup: () => void): void {
47
+ if (this.#disposed) {
48
+ cleanup();
49
+ return;
50
+ }
51
+ this.#cleanups.push(cleanup);
52
+ }
53
+
54
+ /** Ask the host to repaint. No-op before mount or after dispose. */
55
+ protected requestRender(): void {
56
+ this.#host?.requestRender();
57
+ }
58
+
59
+ /** True between {@link mount} and {@link finish}/{@link dispose}. */
60
+ protected get active(): boolean {
61
+ return this.#active;
62
+ }
63
+
64
+ /**
65
+ * Host-only: attach the host and run {@link onMount}. Idempotent — a second
66
+ * call (e.g. a transcript rebuild that re-presents the same instance) is a
67
+ * no-op.
68
+ */
69
+ mount(host: ChatBlockHost): void {
70
+ if (this.#host || this.#disposed) return;
71
+ this.#host = host;
72
+ this.#active = true;
73
+ this.onMount();
74
+ }
75
+
76
+ /**
77
+ * Self-complete: stop ongoing effects and freeze the block at its current
78
+ * content, leaving it rendered in the transcript. Use when the operation the
79
+ * block represents finishes (connection resolved, download done).
80
+ */
81
+ finish(): void {
82
+ if (!this.#active) return;
83
+ this.#active = false;
84
+ this.#runCleanups();
85
+ this.requestRender();
86
+ }
87
+
88
+ /**
89
+ * Host-only teardown: release everything and propagate to children. Called
90
+ * when the host permanently discards the block (transcript reset). Idempotent.
91
+ */
92
+ override dispose(): void {
93
+ if (this.#disposed) return;
94
+ this.#disposed = true;
95
+ this.#active = false;
96
+ this.#runCleanups();
97
+ super.dispose();
98
+ this.#host = undefined;
99
+ }
100
+
101
+ /** Live blocks stay repaintable; finished/disposed ones may freeze. */
102
+ isTranscriptBlockFinalized(): boolean {
103
+ return !this.#active;
104
+ }
105
+
106
+ #runCleanups(): void {
107
+ const cleanups = this.#cleanups.splice(0);
108
+ for (const cleanup of cleanups) cleanup();
109
+ }
110
+ }
@@ -0,0 +1,74 @@
1
+ import type { Component } from "../tui";
2
+ import { Ellipsis, truncateToWidth, visibleWidth } from "../utils";
3
+ import type { AnimationFrame, TranscriptPresentationTarget } from "./transcript-container";
4
+ import { fgOrPlain } from "../theme/theme";
5
+ import { urlHyperlinkAlways } from "../render/index";
6
+ import { QrCode, renderQrHalfBlocks } from "./qrcode";
7
+
8
+ /** Scheme-less display form of a collab browser deep link, OSC-8 linked. */
9
+ export function collabBrowserLink(webLink: string, label?: string): string {
10
+ const schemeLess = webLink.replace(/^https?:\/\//, "");
11
+ const display = fgOrPlain("accent", `\x1b[4m${label ?? schemeLess}\x1b[24m`);
12
+ const linked = urlHyperlinkAlways(webLink, display);
13
+ // Without OSC-8 support, keep the literal URL at the visible prefix.
14
+ return label !== undefined && linked === display ? fgOrPlain("accent", `\x1b[4m${schemeLess}\x1b[24m`) : linked;
15
+ }
16
+
17
+ /**
18
+ * One-shot transcript block that prints a collab browser-join URL as a
19
+ * scannable QR code. The symbol is encoded once at construction (byte mode,
20
+ * EC level M) and rendered as ANSI half-blocks; on terminals too narrow for
21
+ * the symbol it degrades to a one-line hint that includes the URL.
22
+ *
23
+ * The transcript viewport can also clip a live block to a single row under
24
+ * pressure (many short settled blocks — typical when thinking is a one-line
25
+ * summary rather than a tall trace). The QR's first/last rows are a white
26
+ * quiet zone, so a 1-row clip looks like an empty white line. When the
27
+ * allocated height cannot fit the full symbol, degrade to the same hint.
28
+ * The sibling `/collab` status heading can also collapse to its first row
29
+ * under that pressure, so the hint must carry the URL itself — "use the
30
+ * URL above" is not reachable.
31
+ */
32
+ export class CollabQrCodeComponent implements Component, TranscriptPresentationTarget {
33
+ readonly #lines: readonly string[];
34
+ readonly #minWidth: number;
35
+ #allocatedRows = Number.POSITIVE_INFINITY;
36
+
37
+ constructor(readonly url: string) {
38
+ const rows = renderQrHalfBlocks(QrCode.encodeText(url, "M"));
39
+ this.#lines = rows.map(row => ` ${row}`);
40
+ this.#minWidth = rows.reduce((max, row) => Math.max(max, visibleWidth(row)), 0) + 1;
41
+ }
42
+
43
+ setTranscriptAllocation(rows: number, _frame?: AnimationFrame): void {
44
+ this.#allocatedRows = Number.isFinite(rows) ? Math.max(0, Math.trunc(rows)) : Number.POSITIVE_INFINITY;
45
+ }
46
+
47
+ render(width: number): readonly string[] {
48
+ if (width < this.#minWidth) {
49
+ return [this.#hiddenHint(`terminal width ${width}; need ${this.#minWidth}`, width)];
50
+ }
51
+ if (this.#allocatedRows < this.#lines.length) {
52
+ return [this.#hiddenHint(`viewport height ${this.#allocatedRows}; need ${this.#lines.length}`, width)];
53
+ }
54
+ return this.#lines;
55
+ }
56
+
57
+ /** Survives emergency 1-row transcript pressure when this block is otherwise hidden. */
58
+ renderTranscriptBlockEmergencyRow(width: number): string {
59
+ return this.#hiddenHint(
60
+ Number.isFinite(this.#allocatedRows)
61
+ ? `viewport height ${this.#allocatedRows}; need ${this.#lines.length}`
62
+ : "transcript pressure",
63
+ width,
64
+ );
65
+ }
66
+
67
+ #hiddenHint(reason: string, width: number): string {
68
+ return truncateToWidth(
69
+ `${collabBrowserLink(this.url, "Join")} ${fgOrPlain("warning", `QR code hidden: ${reason}.`)}`,
70
+ width,
71
+ Ellipsis.Omit,
72
+ );
73
+ }
74
+ }
@@ -0,0 +1,85 @@
1
+ import { formatNumber } from "@oh-my-pi/pi-utils";
2
+ import type { ThemeColor } from "../theme/index";
3
+ export type ContextUsageLevel = "normal" | "warning" | "purple" | "error";
4
+
5
+ const CONTEXT_WARNING_PERCENT_THRESHOLD = 50;
6
+ const CONTEXT_WARNING_TOKEN_THRESHOLD = 150_000;
7
+ const CONTEXT_PURPLE_PERCENT_THRESHOLD = 70;
8
+ const CONTEXT_PURPLE_TOKEN_THRESHOLD = 270_000;
9
+ const CONTEXT_ERROR_PERCENT_THRESHOLD = 90;
10
+ const CONTEXT_ERROR_TOKEN_THRESHOLD = 500_000;
11
+
12
+ function reachesThreshold(
13
+ contextPercent: number,
14
+ contextWindow: number,
15
+ percentThreshold: number,
16
+ tokenThreshold: number,
17
+ ): boolean {
18
+ if (!Number.isFinite(contextPercent) || contextPercent <= 0) {
19
+ return false;
20
+ }
21
+
22
+ if (!Number.isFinite(contextWindow) || contextWindow <= 0) {
23
+ return contextPercent >= percentThreshold;
24
+ }
25
+
26
+ const tokenPercentThreshold = (tokenThreshold / contextWindow) * 100;
27
+ return contextPercent >= Math.min(percentThreshold, tokenPercentThreshold);
28
+ }
29
+
30
+ export function getContextUsageLevel(contextPercent: number, contextWindow: number): ContextUsageLevel {
31
+ if (
32
+ reachesThreshold(contextPercent, contextWindow, CONTEXT_ERROR_PERCENT_THRESHOLD, CONTEXT_ERROR_TOKEN_THRESHOLD)
33
+ ) {
34
+ return "error";
35
+ }
36
+
37
+ if (
38
+ reachesThreshold(contextPercent, contextWindow, CONTEXT_PURPLE_PERCENT_THRESHOLD, CONTEXT_PURPLE_TOKEN_THRESHOLD)
39
+ ) {
40
+ return "purple";
41
+ }
42
+
43
+ if (
44
+ reachesThreshold(
45
+ contextPercent,
46
+ contextWindow,
47
+ CONTEXT_WARNING_PERCENT_THRESHOLD,
48
+ CONTEXT_WARNING_TOKEN_THRESHOLD,
49
+ )
50
+ ) {
51
+ return "warning";
52
+ }
53
+
54
+ return "normal";
55
+ }
56
+
57
+ /**
58
+ * Format context usage as `<percent>%/<window>` when the model window is known.
59
+ * Unknown windows render as `<tokens>/?`, because `0.0%/0` suggests a real
60
+ * empty context instead of missing provider metadata.
61
+ */
62
+ export function formatContextUsage(
63
+ contextPercent: number | null | undefined,
64
+ contextWindow: number,
65
+ usedTokens?: number,
66
+ ): string {
67
+ if (!Number.isFinite(contextWindow) || contextWindow <= 0) {
68
+ return `${formatNumber(usedTokens ?? 0)}/?`;
69
+ }
70
+ const pct = contextPercent === null || contextPercent === undefined ? "?" : `${contextPercent.toFixed(1)}%`;
71
+ return `${pct}/${formatNumber(contextWindow)}`;
72
+ }
73
+
74
+ export function getContextUsageThemeColor(level: ContextUsageLevel): ThemeColor {
75
+ switch (level) {
76
+ case "error":
77
+ return "error";
78
+ case "purple":
79
+ return "thinkingHigh";
80
+ case "warning":
81
+ return "warning";
82
+ case "normal":
83
+ return "statusLineContext";
84
+ }
85
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Reusable countdown timer for dialog components.
3
+ */
4
+ import type { TUI } from "../tui";
5
+ export class CountdownTimer {
6
+ #intervalId: NodeJS.Timeout | undefined;
7
+ #expireTimeoutId: NodeJS.Timeout | undefined;
8
+ #remainingSeconds: number;
9
+ #deadlineMs = 0;
10
+ readonly #initialMs: number;
11
+
12
+ constructor(
13
+ timeoutMs: number,
14
+ private tui: TUI | undefined,
15
+ private onTick: (seconds: number) => void,
16
+ private onExpire: () => void,
17
+ ) {
18
+ this.#initialMs = timeoutMs;
19
+ this.#remainingSeconds = Math.ceil(timeoutMs / 1000);
20
+ this.#start();
21
+ }
22
+
23
+ #calculateRemainingSeconds(now = Date.now()): number {
24
+ const remainingMs = Math.max(0, this.#deadlineMs - now);
25
+ return Math.ceil(remainingMs / 1000);
26
+ }
27
+
28
+ #start(): void {
29
+ const now = Date.now();
30
+ this.#deadlineMs = now + this.#initialMs;
31
+ this.#remainingSeconds = this.#calculateRemainingSeconds(now);
32
+ this.onTick(this.#remainingSeconds);
33
+ this.tui?.requestRender();
34
+
35
+ this.#expireTimeoutId = setTimeout(() => {
36
+ this.dispose();
37
+ this.onExpire();
38
+ }, this.#initialMs);
39
+
40
+ this.#startInterval();
41
+ }
42
+
43
+ #startInterval(): void {
44
+ if (this.#intervalId) {
45
+ clearInterval(this.#intervalId);
46
+ this.#intervalId = undefined;
47
+ }
48
+ this.#intervalId = setInterval(() => {
49
+ const remainingSeconds = this.#calculateRemainingSeconds();
50
+ if (remainingSeconds !== this.#remainingSeconds) {
51
+ this.#remainingSeconds = remainingSeconds;
52
+ this.onTick(this.#remainingSeconds);
53
+ }
54
+ this.tui?.requestRender();
55
+ }, 1000);
56
+ }
57
+
58
+ /** Reset the countdown to its initial value */
59
+ reset(): void {
60
+ this.dispose();
61
+ this.#start();
62
+ }
63
+
64
+ dispose(): void {
65
+ if (this.#intervalId) {
66
+ clearInterval(this.#intervalId);
67
+ this.#intervalId = undefined;
68
+ }
69
+ if (this.#expireTimeoutId) {
70
+ clearTimeout(this.#expireTimeoutId);
71
+ this.#expireTimeoutId = undefined;
72
+ }
73
+ }
74
+ }