@oh-my-pi/pi-tui 18.4.2 → 18.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/types/apps/cleanse-board.d.ts +17 -0
  3. package/dist/types/apps/git/help.d.ts +16 -0
  4. package/dist/types/apps/git/sidebar.d.ts +18 -0
  5. package/dist/types/apps/live-visualizer.d.ts +10 -0
  6. package/dist/types/apps/ps-top.d.ts +15 -0
  7. package/dist/types/apps/standalone-picker.d.ts +3 -0
  8. package/dist/types/autocomplete.d.ts +8 -0
  9. package/dist/types/chat/advisor-message.d.ts +12 -2
  10. package/dist/types/chat/assistant-message.d.ts +20 -0
  11. package/dist/types/chat/bash-execution.d.ts +9 -0
  12. package/dist/types/chat/chat-transcript-builder.d.ts +6 -1
  13. package/dist/types/chat/collab-prompt-message.d.ts +4 -0
  14. package/dist/types/chat/compaction-summary-message.d.ts +15 -0
  15. package/dist/types/chat/eval-execution.d.ts +8 -0
  16. package/dist/types/chat/execution-shared.d.ts +58 -0
  17. package/dist/types/chat/late-diagnostics-message.d.ts +15 -1
  18. package/dist/types/chat/read-tool-group.d.ts +15 -0
  19. package/dist/types/chat/skill-message.d.ts +9 -0
  20. package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +3 -0
  21. package/dist/types/chat/thinking-display.d.ts +2 -0
  22. package/dist/types/chat/todo-reminder.d.ts +4 -1
  23. package/dist/types/chat/tool-execution.d.ts +25 -1
  24. package/dist/types/chat/transcript-actions.d.ts +37 -0
  25. package/dist/types/chat/transcript-entry.d.ts +3 -1
  26. package/dist/types/chat/user-message.d.ts +25 -0
  27. package/dist/types/chrome/collab-qrcode.d.ts +7 -0
  28. package/dist/types/chrome/context-thresholds.d.ts +11 -0
  29. package/dist/types/chrome/countdown-timer.d.ts +9 -3
  30. package/dist/types/chrome/diff.d.ts +12 -0
  31. package/dist/types/chrome/dynamic-border.d.ts +3 -0
  32. package/dist/types/chrome/format.d.ts +6 -0
  33. package/dist/types/chrome/message-divider.d.ts +13 -0
  34. package/dist/types/chrome/message-frame.d.ts +10 -0
  35. package/dist/types/chrome/message-notice.d.ts +23 -0
  36. package/dist/types/chrome/overlay-box.d.ts +11 -2
  37. package/dist/types/chrome/qrcode.d.ts +7 -0
  38. package/dist/types/chrome/segment-track.d.ts +7 -0
  39. package/dist/types/chrome/selector-helpers.d.ts +0 -6
  40. package/dist/types/chrome/status-notice.d.ts +14 -0
  41. package/dist/types/chrome/streaming-panel.d.ts +3 -0
  42. package/dist/types/chrome/tool-activity.d.ts +3 -0
  43. package/dist/types/chrome/transcript-container.d.ts +13 -0
  44. package/dist/types/chrome/transcript-status.d.ts +15 -3
  45. package/dist/types/components/box.d.ts +7 -0
  46. package/dist/types/components/disclosure.d.ts +9 -0
  47. package/dist/types/components/editor.d.ts +42 -0
  48. package/dist/types/components/form.d.ts +14 -0
  49. package/dist/types/components/image.d.ts +7 -0
  50. package/dist/types/components/input.d.ts +20 -1
  51. package/dist/types/components/key-value-list.d.ts +3 -0
  52. package/dist/types/components/layout/geometry.d.ts +16 -0
  53. package/dist/types/components/layout/row.d.ts +7 -0
  54. package/dist/types/components/layout/split-pane.d.ts +8 -0
  55. package/dist/types/components/layout/stack.d.ts +6 -0
  56. package/dist/types/components/loader.d.ts +48 -0
  57. package/dist/types/components/markdown.d.ts +8 -0
  58. package/dist/types/components/metric.d.ts +7 -0
  59. package/dist/types/components/progress-bar.d.ts +3 -0
  60. package/dist/types/components/scroll-view.d.ts +6 -0
  61. package/dist/types/components/section.d.ts +3 -0
  62. package/dist/types/components/select-list.d.ts +33 -0
  63. package/dist/types/components/settings-list.d.ts +68 -0
  64. package/dist/types/components/spacer.d.ts +4 -0
  65. package/dist/types/components/tab-bar.d.ts +9 -0
  66. package/dist/types/components/table.d.ts +7 -0
  67. package/dist/types/components/text.d.ts +6 -0
  68. package/dist/types/components/tree-view.d.ts +9 -0
  69. package/dist/types/components/truncated-text.d.ts +3 -0
  70. package/dist/types/components/wizard-step.d.ts +6 -0
  71. package/dist/types/hotkeys-markdown.d.ts +24 -0
  72. package/dist/types/index.d.ts +5 -0
  73. package/dist/types/latex-block.d.ts +7 -0
  74. package/dist/types/loop-watchdog.d.ts +9 -0
  75. package/dist/types/native/apply.d.ts +39 -0
  76. package/dist/types/native/backend.d.ts +94 -0
  77. package/dist/types/native/blobs.d.ts +29 -0
  78. package/dist/types/native/describe.d.ts +56 -0
  79. package/dist/types/native/encode.d.ts +50 -0
  80. package/dist/types/native/icons.d.ts +18 -0
  81. package/dist/types/native/memo.d.ts +27 -0
  82. package/dist/types/native/node.d.ts +107 -0
  83. package/dist/types/native/overlay.d.ts +64 -0
  84. package/dist/types/native/picker.d.ts +124 -0
  85. package/dist/types/native/reconcile.d.ts +41 -0
  86. package/dist/types/native/settle.d.ts +11 -0
  87. package/dist/types/native/spans.d.ts +21 -0
  88. package/dist/types/native/state.d.ts +6 -0
  89. package/dist/types/native/tone.d.ts +24 -0
  90. package/dist/types/overlays/advisor-config.d.ts +20 -0
  91. package/dist/types/overlays/agent-hub-renderer.d.ts +27 -11
  92. package/dist/types/overlays/agent-hub.d.ts +10 -0
  93. package/dist/types/overlays/agent-transcript-viewer.d.ts +7 -0
  94. package/dist/types/overlays/agents-hub.d.ts +8 -0
  95. package/dist/types/overlays/annotation-overlay.d.ts +3 -0
  96. package/dist/types/overlays/ask-dialog.d.ts +23 -0
  97. package/dist/types/overlays/bordered-loader.d.ts +3 -0
  98. package/dist/types/overlays/btw-history-panel.d.ts +9 -0
  99. package/dist/types/overlays/btw-panel.d.ts +3 -0
  100. package/dist/types/overlays/cleanse-panel.d.ts +5 -2
  101. package/dist/types/overlays/composer-shape-preview.d.ts +7 -1
  102. package/dist/types/overlays/copy-selector.d.ts +38 -0
  103. package/dist/types/overlays/error-banner.d.ts +9 -0
  104. package/dist/types/overlays/extensions/extension-list.d.ts +1 -0
  105. package/dist/types/overlays/history-search.d.ts +18 -0
  106. package/dist/types/overlays/hook-editor.d.ts +28 -1
  107. package/dist/types/overlays/hook-input.d.ts +3 -0
  108. package/dist/types/overlays/hook-selector.d.ts +10 -0
  109. package/dist/types/overlays/hub-frame.d.ts +18 -0
  110. package/dist/types/overlays/jobs-panel.d.ts +24 -0
  111. package/dist/types/overlays/login-dialog.d.ts +10 -0
  112. package/dist/types/overlays/logout-account-selector.d.ts +4 -0
  113. package/dist/types/overlays/mcp-add-wizard.d.ts +4 -0
  114. package/dist/types/overlays/model-browser.d.ts +69 -0
  115. package/dist/types/overlays/model-hub.d.ts +7 -0
  116. package/dist/types/overlays/model-picker.d.ts +9 -1
  117. package/dist/types/overlays/move-overlay.d.ts +3 -0
  118. package/dist/types/overlays/oauth-selector.d.ts +4 -0
  119. package/dist/types/overlays/omfg-panel.d.ts +3 -0
  120. package/dist/types/overlays/pause-screen.d.ts +12 -0
  121. package/dist/types/overlays/plan-review-overlay.d.ts +5 -0
  122. package/dist/types/overlays/plan-save-overlay.d.ts +10 -0
  123. package/dist/types/overlays/plugin-selector.d.ts +4 -0
  124. package/dist/types/overlays/plugin-settings.d.ts +30 -0
  125. package/dist/types/overlays/queue-mode-selector.d.ts +4 -0
  126. package/dist/types/overlays/reset-usage-selector.d.ts +8 -0
  127. package/dist/types/overlays/rewind-selector.d.ts +5 -0
  128. package/dist/types/overlays/session-info-overlay.d.ts +19 -1
  129. package/dist/types/overlays/session-selector.d.ts +64 -1
  130. package/dist/types/overlays/settings-defs.d.ts +14 -0
  131. package/dist/types/overlays/settings-selector.d.ts +21 -0
  132. package/dist/types/overlays/show-images-selector.d.ts +4 -0
  133. package/dist/types/overlays/snapcompact-shape-preview.d.ts +2 -0
  134. package/dist/types/overlays/stats-notice.d.ts +8 -0
  135. package/dist/types/overlays/theme-selector.d.ts +11 -0
  136. package/dist/types/overlays/thinking-selector.d.ts +4 -0
  137. package/dist/types/overlays/tree-selector.d.ts +60 -2
  138. package/dist/types/overlays/usage-dashboard.d.ts +26 -3
  139. package/dist/types/overlays/usage-row.d.ts +36 -2
  140. package/dist/types/prompt/attachment-chips.d.ts +8 -0
  141. package/dist/types/prompt/composer-attachments.d.ts +15 -3
  142. package/dist/types/prompt/composer.d.ts +18 -1
  143. package/dist/types/prompt/custom-editor.d.ts +48 -2
  144. package/dist/types/prompt/editor-top-gap.d.ts +2 -0
  145. package/dist/types/prompt/macos-spelling.d.ts +6 -0
  146. package/dist/types/prompt/magic-keywords.d.ts +9 -0
  147. package/dist/types/prompt/queued-messages.d.ts +23 -0
  148. package/dist/types/prompt/skill-tokens.d.ts +4 -2
  149. package/dist/types/prompt/welcome.d.ts +16 -0
  150. package/dist/types/render/code-cell.d.ts +10 -0
  151. package/dist/types/render/file-list.d.ts +8 -0
  152. package/dist/types/render/hyperlink.d.ts +14 -0
  153. package/dist/types/render/output-block.d.ts +43 -0
  154. package/dist/types/render/output-pane.d.ts +17 -0
  155. package/dist/types/render/tool-card.d.ts +8 -0
  156. package/dist/types/render/tree-list.d.ts +8 -0
  157. package/dist/types/render/width-aware-text.d.ts +7 -0
  158. package/dist/types/setup/scenes/outro.d.ts +7 -0
  159. package/dist/types/setup/scenes/sign-in.d.ts +16 -9
  160. package/dist/types/setup/scenes/splash.d.ts +8 -0
  161. package/dist/types/setup/scenes/types.d.ts +6 -27
  162. package/dist/types/setup/wizard-overlay.d.ts +9 -0
  163. package/dist/types/status-line/component.d.ts +49 -5
  164. package/dist/types/status-line/context-usage.d.ts +20 -0
  165. package/dist/types/status-line/footer.d.ts +8 -0
  166. package/dist/types/status-line/metrics.d.ts +1 -2
  167. package/dist/types/status-line/segments.d.ts +10 -1
  168. package/dist/types/status-line/types.d.ts +40 -1
  169. package/dist/types/stdin-buffer.d.ts +10 -7
  170. package/dist/types/terminal-capabilities.d.ts +1 -1
  171. package/dist/types/terminal.d.ts +36 -0
  172. package/dist/types/theme/defaults/index.d.ts +100 -0
  173. package/dist/types/theme/schema.d.ts +2 -0
  174. package/dist/types/theme/shimmer.d.ts +8 -0
  175. package/dist/types/theme/theme-class.d.ts +2 -0
  176. package/dist/types/theme/theme.d.ts +33 -1
  177. package/dist/types/tools/ask.d.ts +3 -0
  178. package/dist/types/tools/ast-edit.d.ts +10 -1
  179. package/dist/types/tools/ast-grep.d.ts +10 -1
  180. package/dist/types/tools/autoresearch.d.ts +21 -4
  181. package/dist/types/tools/bash.d.ts +30 -1
  182. package/dist/types/tools/cfg-render.d.ts +5 -1
  183. package/dist/types/tools/debug.d.ts +3 -1
  184. package/dist/types/tools/default-renderer.d.ts +6 -1
  185. package/dist/types/tools/edit.d.ts +14 -1
  186. package/dist/types/tools/eval.d.ts +12 -1
  187. package/dist/types/tools/fetch.d.ts +16 -1
  188. package/dist/types/tools/find.d.ts +15 -1
  189. package/dist/types/tools/github.d.ts +3 -0
  190. package/dist/types/tools/glob.d.ts +14 -1
  191. package/dist/types/tools/goal.d.ts +3 -1
  192. package/dist/types/tools/grep.d.ts +14 -1
  193. package/dist/types/tools/grouped-file-output.d.ts +58 -0
  194. package/dist/types/tools/json-tree.d.ts +20 -0
  195. package/dist/types/tools/lsp.d.ts +3 -10
  196. package/dist/types/tools/mcp.d.ts +16 -1
  197. package/dist/types/tools/memory.d.ts +26 -0
  198. package/dist/types/tools/native-view.d.ts +90 -0
  199. package/dist/types/tools/proc-render.d.ts +7 -1
  200. package/dist/types/tools/read.d.ts +23 -1
  201. package/dist/types/tools/renderer.d.ts +57 -0
  202. package/dist/types/tools/report-tool-issue.d.ts +3 -0
  203. package/dist/types/tools/resolve.d.ts +14 -1
  204. package/dist/types/tools/task.d.ts +3 -0
  205. package/dist/types/tools/think.d.ts +3 -0
  206. package/dist/types/tools/todo.d.ts +12 -0
  207. package/dist/types/tools/vibe.d.ts +3 -1
  208. package/dist/types/tools/wait.d.ts +3 -0
  209. package/dist/types/tools/web-search-types.d.ts +90 -0
  210. package/dist/types/tools/web-search.d.ts +9 -168
  211. package/dist/types/tools/write.d.ts +14 -1
  212. package/dist/types/tools/xdev.d.ts +13 -0
  213. package/dist/types/tui.d.ts +49 -0
  214. package/package.json +9 -9
  215. package/src/apps/autoresearch-dashboard.ts +362 -4
  216. package/src/apps/cleanse-board.ts +219 -1
  217. package/src/apps/cleanse-picker.ts +9 -1
  218. package/src/apps/debug/log-viewer.ts +15 -15
  219. package/src/apps/debug/protocol-probe.ts +2 -20
  220. package/src/apps/git/avatar.ts +2 -22
  221. package/src/apps/git/git-tui.ts +406 -59
  222. package/src/apps/git/help.ts +130 -0
  223. package/src/apps/git/sidebar.ts +491 -0
  224. package/src/apps/live-visualizer.ts +65 -0
  225. package/src/apps/ps-top.ts +448 -17
  226. package/src/apps/session-picker.ts +1 -0
  227. package/src/apps/setup-model-picker.ts +5 -1
  228. package/src/apps/standalone-picker.ts +55 -1
  229. package/src/autocomplete.ts +44 -1
  230. package/src/chat/advisor-message.ts +72 -3
  231. package/src/chat/assistant-message.ts +538 -51
  232. package/src/chat/background-tan-message.ts +4 -4
  233. package/src/chat/bash-execution.ts +81 -0
  234. package/src/chat/cache-invalidation-marker.ts +8 -0
  235. package/src/chat/chat-transcript-builder.ts +37 -6
  236. package/src/chat/collab-prompt-message.ts +15 -3
  237. package/src/chat/compaction-summary-message.ts +74 -1
  238. package/src/chat/custom-message.ts +3 -1
  239. package/src/chat/eval-execution.ts +57 -0
  240. package/src/chat/execution-shared.ts +153 -1
  241. package/src/chat/hook-message.ts +1 -0
  242. package/src/chat/late-diagnostics-message.ts +85 -2
  243. package/src/chat/read-tool-group.ts +341 -1
  244. package/src/chat/served-model-marker.ts +8 -0
  245. package/src/chat/skill-message.ts +63 -0
  246. package/src/chat/stripped-tool-calls-placeholder.ts +18 -10
  247. package/src/chat/thinking-display.ts +73 -11
  248. package/src/chat/todo-reminder.ts +34 -4
  249. package/src/chat/tool-execution.ts +385 -10
  250. package/src/chat/transcript-actions.ts +38 -0
  251. package/src/chat/transcript-browser.ts +2 -9
  252. package/src/chat/transcript-entry.ts +10 -1
  253. package/src/chat/transcript-render-helpers.ts +16 -15
  254. package/src/chat/ttsr-notification.ts +38 -1
  255. package/src/chat/user-message.ts +167 -4
  256. package/src/chrome/collab-qrcode.ts +27 -2
  257. package/src/chrome/context-thresholds.ts +34 -0
  258. package/src/chrome/countdown-timer.ts +24 -1
  259. package/src/chrome/diff.ts +60 -1
  260. package/src/chrome/dynamic-border.ts +7 -0
  261. package/src/chrome/format.ts +12 -0
  262. package/src/chrome/message-divider.ts +33 -1
  263. package/src/chrome/message-frame.ts +53 -10
  264. package/src/chrome/message-notice.ts +71 -0
  265. package/src/chrome/overlay-box.ts +45 -2
  266. package/src/chrome/qrcode.ts +28 -0
  267. package/src/chrome/segment-track.ts +26 -0
  268. package/src/chrome/selector-helpers.ts +1 -17
  269. package/src/chrome/status-notice.ts +46 -0
  270. package/src/chrome/streaming-panel.ts +25 -1
  271. package/src/chrome/tool-activity.ts +20 -0
  272. package/src/chrome/transcript-container.ts +139 -17
  273. package/src/chrome/transcript-status.ts +40 -11
  274. package/src/components/box.ts +51 -0
  275. package/src/components/disclosure.ts +33 -0
  276. package/src/components/editor.ts +239 -36
  277. package/src/components/form.ts +93 -9
  278. package/src/components/image.ts +30 -0
  279. package/src/components/input.ts +77 -26
  280. package/src/components/key-value-list.ts +18 -0
  281. package/src/components/layout/geometry.ts +44 -0
  282. package/src/components/layout/row.ts +30 -0
  283. package/src/components/layout/split-pane.ts +65 -0
  284. package/src/components/layout/stack.ts +27 -0
  285. package/src/components/loader.ts +183 -1
  286. package/src/components/markdown.ts +131 -56
  287. package/src/components/metric.ts +39 -0
  288. package/src/components/progress-bar.ts +28 -0
  289. package/src/components/scroll-view.ts +23 -0
  290. package/src/components/section.ts +16 -0
  291. package/src/components/select-list.ts +174 -25
  292. package/src/components/settings-list.ts +264 -7
  293. package/src/components/spacer.ts +17 -0
  294. package/src/components/tab-bar.ts +42 -0
  295. package/src/components/table.ts +34 -0
  296. package/src/components/text.ts +23 -0
  297. package/src/components/tree-view.ts +65 -0
  298. package/src/components/truncated-text.ts +14 -0
  299. package/src/components/wizard-step.ts +18 -9
  300. package/src/debug-server.ts +14 -7
  301. package/src/hotkeys-markdown.ts +251 -69
  302. package/src/index.ts +6 -0
  303. package/src/latex-block.ts +11 -0
  304. package/src/loop-watchdog.ts +38 -10
  305. package/src/native/apply.ts +275 -0
  306. package/src/native/backend.ts +682 -0
  307. package/src/native/blobs.ts +70 -0
  308. package/src/native/describe.ts +124 -0
  309. package/src/native/encode.ts +233 -0
  310. package/src/native/icons.ts +184 -0
  311. package/src/native/memo.ts +64 -0
  312. package/src/native/node.ts +112 -0
  313. package/src/native/overlay.ts +131 -0
  314. package/src/native/picker.ts +333 -0
  315. package/src/native/reconcile.ts +1063 -0
  316. package/src/native/settle.ts +23 -0
  317. package/src/native/spans.ts +308 -0
  318. package/src/native/state.ts +28 -0
  319. package/src/native/tone.ts +79 -0
  320. package/src/overlays/advisor-config.ts +420 -0
  321. package/src/overlays/agent-hub-renderer.ts +155 -18
  322. package/src/overlays/agent-hub.ts +1037 -44
  323. package/src/overlays/agent-transcript-viewer.ts +129 -0
  324. package/src/overlays/agents-hub.ts +688 -53
  325. package/src/overlays/annotation-overlay.ts +391 -52
  326. package/src/overlays/ask-dialog.ts +435 -24
  327. package/src/overlays/bordered-loader.ts +17 -0
  328. package/src/overlays/btw-history-panel.ts +182 -0
  329. package/src/overlays/btw-panel.ts +68 -2
  330. package/src/overlays/cleanse-panel.ts +105 -15
  331. package/src/overlays/codex-reset-fireworks.ts +65 -5
  332. package/src/overlays/composer-shape-preview.ts +26 -1
  333. package/src/overlays/copy-selector.ts +545 -23
  334. package/src/overlays/error-banner.ts +44 -0
  335. package/src/overlays/extensions/extension-list.ts +23 -17
  336. package/src/overlays/history-search.ts +175 -33
  337. package/src/overlays/hook-editor.ts +113 -6
  338. package/src/overlays/hook-input.ts +22 -1
  339. package/src/overlays/hook-selector.ts +311 -22
  340. package/src/overlays/hub-frame.ts +80 -0
  341. package/src/overlays/jobs-panel.ts +112 -0
  342. package/src/overlays/login-dialog.ts +183 -1
  343. package/src/overlays/logout-account-selector.ts +102 -4
  344. package/src/overlays/mcp-add-wizard.ts +232 -53
  345. package/src/overlays/model-browser.ts +681 -22
  346. package/src/overlays/model-hub.ts +1402 -78
  347. package/src/overlays/model-picker.ts +184 -7
  348. package/src/overlays/move-overlay.ts +45 -0
  349. package/src/overlays/oauth-selector.ts +227 -23
  350. package/src/overlays/omfg-panel.ts +86 -2
  351. package/src/overlays/pause-screen.ts +55 -4
  352. package/src/overlays/plan-review-overlay.ts +352 -0
  353. package/src/overlays/plan-save-overlay.ts +45 -0
  354. package/src/overlays/plugin-selector.ts +21 -1
  355. package/src/overlays/plugin-settings.ts +195 -5
  356. package/src/overlays/queue-mode-selector.ts +19 -1
  357. package/src/overlays/reset-usage-selector.ts +110 -40
  358. package/src/overlays/rewind-selector.ts +458 -44
  359. package/src/overlays/session-account-selector.ts +1 -1
  360. package/src/overlays/session-info-overlay.ts +137 -1
  361. package/src/overlays/session-selector.ts +807 -46
  362. package/src/overlays/settings-defs.ts +41 -0
  363. package/src/overlays/settings-selector.ts +585 -33
  364. package/src/overlays/show-images-selector.ts +18 -1
  365. package/src/overlays/snapcompact-shape-preview.ts +48 -3
  366. package/src/overlays/stats-notice.ts +31 -0
  367. package/src/overlays/theme-selector.ts +31 -1
  368. package/src/overlays/thinking-selector.ts +22 -1
  369. package/src/overlays/tree-selector.ts +570 -110
  370. package/src/overlays/usage-dashboard.ts +587 -12
  371. package/src/overlays/usage-row.ts +161 -25
  372. package/src/prompt/attachment-chips.ts +60 -0
  373. package/src/prompt/composer-attachments.ts +31 -9
  374. package/src/prompt/composer.ts +55 -2
  375. package/src/prompt/custom-editor.ts +302 -4
  376. package/src/prompt/editor-top-gap.ts +8 -0
  377. package/src/prompt/macos-spelling.ts +24 -9
  378. package/src/prompt/magic-keywords.ts +22 -1
  379. package/src/prompt/model-mention-autocomplete.ts +1 -0
  380. package/src/prompt/queued-messages.ts +101 -0
  381. package/src/prompt/skill-tokens.ts +5 -3
  382. package/src/prompt/welcome.ts +213 -6
  383. package/src/render/code-cell.ts +103 -2
  384. package/src/render/file-list.ts +29 -0
  385. package/src/render/hyperlink.ts +32 -0
  386. package/src/render/output-block.ts +110 -0
  387. package/src/render/output-pane.ts +37 -0
  388. package/src/render/tool-card.ts +137 -0
  389. package/src/render/tree-list.ts +39 -0
  390. package/src/render/width-aware-text.ts +20 -0
  391. package/src/setup/scenes/composer.ts +29 -0
  392. package/src/setup/scenes/glyph.ts +15 -0
  393. package/src/setup/scenes/model.ts +36 -8
  394. package/src/setup/scenes/outro.ts +28 -1
  395. package/src/setup/scenes/sign-in.ts +138 -24
  396. package/src/setup/scenes/splash.ts +28 -1
  397. package/src/setup/scenes/theme.ts +88 -3
  398. package/src/setup/scenes/types.ts +7 -28
  399. package/src/setup/startup-splash.ts +46 -9
  400. package/src/setup/wizard-overlay.ts +140 -23
  401. package/src/setup/wizard.ts +1 -1
  402. package/src/status-line/component.ts +414 -18
  403. package/src/status-line/context-usage.ts +279 -50
  404. package/src/status-line/footer.ts +94 -1
  405. package/src/status-line/metrics.ts +3 -6
  406. package/src/status-line/segments.ts +463 -97
  407. package/src/status-line/separators.ts +3 -16
  408. package/src/status-line/types.ts +43 -1
  409. package/src/stdin-buffer.ts +27 -21
  410. package/src/terminal-capabilities.ts +7 -0
  411. package/src/terminal.ts +153 -11
  412. package/src/theme/defaults/dark-neon-noir.json +100 -0
  413. package/src/theme/defaults/index.ts +2 -0
  414. package/src/theme/defaults/light-prism.json +5 -5
  415. package/src/theme/defaults/onyx.json +62 -62
  416. package/src/theme/mermaid-cache.ts +10 -1
  417. package/src/theme/schema.ts +15 -0
  418. package/src/theme/shimmer.ts +33 -0
  419. package/src/theme/theme-class.ts +24 -19
  420. package/src/theme/theme.ts +111 -9
  421. package/src/theme/tui-adapters.ts +14 -1
  422. package/src/tools/ask.ts +157 -1
  423. package/src/tools/ast-edit.ts +174 -1
  424. package/src/tools/ast-grep.ts +82 -2
  425. package/src/tools/autoresearch.ts +149 -1
  426. package/src/tools/bash.ts +233 -62
  427. package/src/tools/cfg-render.ts +66 -1
  428. package/src/tools/debug.ts +78 -1
  429. package/src/tools/default-renderer.ts +35 -1
  430. package/src/tools/edit.ts +357 -31
  431. package/src/tools/eval.ts +257 -1
  432. package/src/tools/fetch.ts +102 -3
  433. package/src/tools/find.ts +127 -1
  434. package/src/tools/github.ts +119 -10
  435. package/src/tools/glob.ts +116 -1
  436. package/src/tools/goal.ts +56 -1
  437. package/src/tools/grep.ts +83 -2
  438. package/src/tools/grouped-file-output.ts +205 -0
  439. package/src/tools/json-tree.ts +116 -1
  440. package/src/tools/lsp.ts +318 -1
  441. package/src/tools/mcp.ts +80 -1
  442. package/src/tools/memory.ts +93 -11
  443. package/src/tools/native-view.ts +292 -0
  444. package/src/tools/proc-render.ts +221 -1
  445. package/src/tools/read.ts +199 -4
  446. package/src/tools/renderer.ts +61 -0
  447. package/src/tools/report-tool-issue.ts +7 -1
  448. package/src/tools/resolve.ts +63 -1
  449. package/src/tools/streaming-output.ts +79 -16
  450. package/src/tools/task.ts +406 -4
  451. package/src/tools/think.ts +19 -1
  452. package/src/tools/todo.ts +89 -0
  453. package/src/tools/vibe.ts +230 -2
  454. package/src/tools/wait.ts +181 -1
  455. package/src/tools/web-search-types.ts +99 -0
  456. package/src/tools/web-search.ts +111 -170
  457. package/src/tools/write.ts +144 -5
  458. package/src/tools/xdev.ts +64 -1
  459. package/src/tui.ts +295 -4
  460. package/dist/types/setup/scenes/providers.d.ts +0 -3
  461. package/dist/types/setup/scenes/web-search.d.ts +0 -22
  462. package/src/setup/scenes/providers.ts +0 -110
  463. package/src/setup/scenes/web-search.ts +0 -165
@@ -14,7 +14,10 @@ import { wrapTextWithAnsi } from "../../utils";
14
14
  import { getAgentDbPath } from "@oh-my-pi/pi-utils";
15
15
  import { OAuthSelectorComponent } from "../../overlays/oauth-selector";
16
16
  import { theme } from "../../theme/theme";
17
- import type { SetupSceneHost, SetupTab } from "./types";
17
+ import { col, node, span, text } from "../../native/describe";
18
+ import type { NativeChild, NativeNode } from "../../native/node";
19
+ import { Memo } from "../../native/memo";
20
+ import type { SetupScene, SetupSceneController, SetupSceneHost, StyledLine } from "./types";
18
21
 
19
22
  function loginUrlLink(url: string): string {
20
23
  return `\x1b]8;;${url}\x07Open login URL\x1b]8;;\x07`;
@@ -27,10 +30,12 @@ function loginCopyHint(): string {
27
30
  class CopyablePromptInput implements Component, Focusable {
28
31
  #input: Input;
29
32
  #onCopy: () => void;
33
+ readonly #native: NativeNode;
30
34
 
31
35
  constructor(input: Input, onCopy: () => void) {
32
36
  this.#input = input;
33
37
  this.#onCopy = onCopy;
38
+ this.#native = col([input]);
34
39
  }
35
40
 
36
41
  get focused(): boolean {
@@ -49,6 +54,11 @@ class CopyablePromptInput implements Component, Focusable {
49
54
  return this.#input.render(width);
50
55
  }
51
56
 
57
+ /** The wrapped field describes itself (`input`, caret while focused); alt+c stays a key here. */
58
+ describe(): NativeNode {
59
+ return this.#native;
60
+ }
61
+
52
62
  handleInput(data: string): void {
53
63
  if (matchesKey(data, "alt+c")) {
54
64
  this.#onCopy();
@@ -69,17 +79,20 @@ interface PromptState {
69
79
  }
70
80
 
71
81
  /**
72
- * "Sign in" panel: lets the user authenticate one or more model providers via
73
- * OAuth. Unlike a standalone scene it never auto-advances the wizard — the user
74
- * may sign in to several providers and then continue with Esc.
82
+ * "Sign in" scene: lets the user authenticate one or more model providers via
83
+ * OAuth. It never auto-advances the wizard — the user may sign in to several
84
+ * providers and then continue with Esc.
75
85
  */
76
- export class SignInTab implements SetupTab {
77
- readonly id = "sign-in";
78
- readonly label = "Sign in";
86
+ export class SignInScene implements SetupSceneController {
87
+ readonly title = "Sign in to your providers";
88
+ get subtitle(): string {
89
+ return `Sign in to one or more providers. Press ${editorKey("tui.select.cancel")} when you're done.`;
90
+ }
79
91
 
80
92
  #authStorage: AuthStorage;
81
93
  #selector: OAuthSelectorComponent;
82
- #statusLines: string[] = [];
94
+ /** Status copy under the selector or login flow; replaced (never mutated) on change. */
95
+ #statusLines: readonly StyledLine[] = [];
83
96
  #authUrl: string | undefined;
84
97
  #authLaunchUrl: string | undefined;
85
98
  #prompt: PromptState | undefined;
@@ -90,6 +103,7 @@ export class SignInTab implements SetupTab {
90
103
  #loggingInProvider: string | undefined;
91
104
  #disposed = false;
92
105
  #step: WizardStep | undefined;
106
+ #native = new Memo();
93
107
 
94
108
  readonly #host: SetupSceneHost;
95
109
 
@@ -99,11 +113,6 @@ export class SignInTab implements SetupTab {
99
113
  this.#selector = this.#createSelector();
100
114
  }
101
115
 
102
- /** Modal while an OAuth flow is running so the scene won't switch tabs or finish. */
103
- get modal(): boolean {
104
- return this.#loggingInProvider !== undefined;
105
- }
106
-
107
116
  dispose(): void {
108
117
  this.#disposed = true;
109
118
  this.#selector.stopValidation();
@@ -112,6 +121,7 @@ export class SignInTab implements SetupTab {
112
121
  }
113
122
 
114
123
  invalidate(): void {
124
+ this.#native.clear();
115
125
  this.#step?.invalidate();
116
126
  this.#selector.invalidate();
117
127
  this.#prompt?.input.invalidate();
@@ -177,7 +187,7 @@ export class SignInTab implements SetupTab {
177
187
  }
178
188
  }
179
189
  for (const line of this.#statusLines) {
180
- for (const wrapped of wrapTextWithAnsi(line, width)) {
190
+ for (const wrapped of wrapTextWithAnsi(theme.fg(line.color, line.text), width)) {
181
191
  tail.addChild(new Text(wrapped, 0, 0));
182
192
  }
183
193
  }
@@ -208,6 +218,98 @@ export class SignInTab implements SetupTab {
208
218
  return this.#step.render(width);
209
219
  }
210
220
 
221
+ /**
222
+ * Picking: intro, the provider selector (describes itself) and the last
223
+ * outcome. Signing in: a spinner heading, the login link (with the full
224
+ * URL once, char-wrapped), any code prompt and the flow's progress lines.
225
+ */
226
+ describe(): NativeNode {
227
+ const provider = this.#loggingInProvider;
228
+ const authUrl = this.#authUrl;
229
+ const launchUrl = this.#authLaunchUrl;
230
+ const prompt = this.#prompt;
231
+ const statusLines = this.#statusLines;
232
+ const copyKey = formatKeyHint("alt+c");
233
+ return this.#native.get([provider, authUrl, launchUrl, prompt, statusLines, this.#selector, copyKey], () => {
234
+ const tail: NativeChild[] = [];
235
+ if (authUrl) {
236
+ tail.push(
237
+ node(
238
+ "text",
239
+ {
240
+ spans: [
241
+ span("Browser login: ", "accent"),
242
+ span("Open login URL", "accent link", { href: authUrl }),
243
+ span(` (clipboard copy attempted; ${copyKey} retries)`, "dim"),
244
+ ],
245
+ },
246
+ undefined,
247
+ "login",
248
+ ),
249
+ node(
250
+ "text",
251
+ { spans: [span(authUrl, "dim link", { href: authUrl })], wrap: "char", actions: { menu: ["copy"] } },
252
+ undefined,
253
+ "url",
254
+ ),
255
+ );
256
+ if (launchUrl) {
257
+ tail.push(
258
+ node(
259
+ "text",
260
+ {
261
+ spans: [
262
+ span("Local shortcut (this machine only): ", "dim"),
263
+ span(launchUrl, "dim link", { href: launchUrl }),
264
+ ],
265
+ wrap: "char",
266
+ },
267
+ undefined,
268
+ "launch",
269
+ ),
270
+ );
271
+ }
272
+ }
273
+ if (prompt) {
274
+ const promptChildren: NativeChild[] = [text([span(prompt.message, "warning")])];
275
+ if (prompt.placeholder) promptChildren.push(text([span(prompt.placeholder, "dim")]));
276
+ promptChildren.push(prompt.input);
277
+ tail.push(node("col", {}, promptChildren, "prompt"));
278
+ }
279
+ statusLines.forEach((line, index) => {
280
+ tail.push(node("text", { spans: [span(line.text, line.color)] }, undefined, `status:${index}`));
281
+ });
282
+
283
+ if (provider) {
284
+ return col(
285
+ [
286
+ node(
287
+ "row",
288
+ { gap: "sm", align: "center" },
289
+ [node("spinner", {}), text([span(`Signing in to ${provider}`, "strong")])],
290
+ "heading",
291
+ ),
292
+ ...tail,
293
+ ],
294
+ { gap: "sm", role: "omp.setup.sign-in", tone: "pending" },
295
+ );
296
+ }
297
+ return col(
298
+ [
299
+ node(
300
+ "text",
301
+ { spans: [span("Pick a provider to sign in — you can connect more than one.", "muted")] },
302
+ undefined,
303
+ "intro",
304
+ ),
305
+ this.#selector,
306
+ ...tail,
307
+ ],
308
+ { gap: "sm", role: "omp.setup.sign-in" },
309
+ );
310
+ });
311
+ }
312
+
211
313
  #createSelector(): OAuthSelectorComponent {
212
314
  return new OAuthSelectorComponent(
213
315
  "login",
@@ -225,7 +327,7 @@ export class SignInTab implements SetupTab {
225
327
  const useManualInput = PASTE_CODE_LOGIN_PROVIDERS.has(providerId);
226
328
  this.#selector.stopValidation();
227
329
  this.#loggingInProvider = providerId;
228
- this.#statusLines = [theme.fg("dim", "Starting OAuth flow…")];
330
+ this.#statusLines = [{ text: "Starting OAuth flow…", color: "dim" }];
229
331
  this.#authUrl = undefined;
230
332
  this.#authLaunchUrl = undefined;
231
333
  this.#loginAbort = new AbortController();
@@ -247,20 +349,21 @@ export class SignInTab implements SetupTab {
247
349
  // shortcut for wide-terminal local users.
248
350
  this.#authUrl = info.url;
249
351
  this.#authLaunchUrl = info.launchUrl && info.launchUrl !== info.url ? info.launchUrl : undefined;
250
- this.#statusLines = [];
352
+ const statusLines: StyledLine[] = [];
251
353
  if (info.instructions) {
252
- this.#statusLines.push(theme.fg("warning", info.instructions));
354
+ statusLines.push({ text: info.instructions, color: "warning" });
253
355
  }
254
356
  if (useManualInput) {
255
- this.#statusLines.push(theme.fg("dim", "Paste the returned code or redirect URL when prompted."));
357
+ statusLines.push({ text: "Paste the returned code or redirect URL when prompted.", color: "dim" });
256
358
  }
359
+ this.#statusLines = statusLines;
257
360
  void this.#copyAuthUrl();
258
361
  this.#host.ctx.openInBrowser(info.url);
259
362
  this.#host.requestRender();
260
363
  },
261
364
  onPrompt: prompt => this.#showPrompt(prompt),
262
365
  onProgress: message => {
263
- this.#statusLines.push(theme.fg("dim", message));
366
+ this.#statusLines = [...this.#statusLines, { text: message, color: "dim" }];
264
367
  this.#host.requestRender();
265
368
  },
266
369
  onManualCodeInput: signal =>
@@ -271,8 +374,8 @@ export class SignInTab implements SetupTab {
271
374
  await this.#host.ctx.refreshProvider(providerId);
272
375
  if (this.#disposed) return;
273
376
  this.#statusLines = [
274
- theme.fg("success", `${theme.status.success} Signed in to ${providerId}`),
275
- theme.fg("dim", `Credentials saved to ${getAgentDbPath()}`),
377
+ { text: `${theme.status.success} Signed in to ${providerId}`, color: "success" },
378
+ { text: `Credentials saved to ${getAgentDbPath()}`, color: "dim" },
276
379
  ];
277
380
  this.#authUrl = undefined;
278
381
  this.#authLaunchUrl = undefined;
@@ -285,14 +388,17 @@ export class SignInTab implements SetupTab {
285
388
  } catch (error) {
286
389
  if (this.#disposed) return;
287
390
  if (this.#loginAbort?.signal.aborted) {
288
- this.#statusLines = [theme.fg("dim", "Login cancelled.")];
391
+ this.#statusLines = [{ text: "Login cancelled.", color: "dim" }];
289
392
  this.#authUrl = undefined;
290
393
  this.#authLaunchUrl = undefined;
291
394
  } else {
292
395
  const message = error instanceof Error ? error.message : String(error);
293
396
  this.#statusLines = [
294
- theme.fg("error", `Login failed: ${message}`),
295
- theme.fg("dim", `Choose another provider or press ${editorKey("tui.select.cancel")} to continue.`),
397
+ { text: `Login failed: ${message}`, color: "error" },
398
+ {
399
+ text: `Choose another provider or press ${editorKey("tui.select.cancel")} to continue.`,
400
+ color: "dim",
401
+ },
296
402
  ];
297
403
  this.#authUrl = undefined;
298
404
  this.#authLaunchUrl = undefined;
@@ -373,3 +479,11 @@ export class SignInTab implements SetupTab {
373
479
  this.#host.requestRender();
374
480
  }
375
481
  }
482
+
483
+ /** Onboarding scene for provider sign-in. */
484
+ export const providersSetupScene: SetupScene = {
485
+ id: "providers",
486
+ title: "Sign in to your providers",
487
+ minVersion: 1,
488
+ mount: host => new SignInScene(host),
489
+ };
@@ -1,8 +1,11 @@
1
1
  import { centerLine, visibleWidth } from "../../utils";
2
2
  import { padToWidth } from "../../render/utils";
3
- import { gradientEscape, gradientLogo, PI_LOGO, type ShineConfig } from "../../prompt/welcome";
3
+ import { gradientEscape, gradientLogo, logoNode, PI_LOGO, type ShineConfig } from "../../prompt/welcome";
4
4
  import { theme } from "../../theme/theme";
5
5
  import { formatKeyHint } from "../../app-keybindings";
6
+ import { col, node, span, text } from "../../native/describe";
7
+ import type { NativeNode } from "../../native/node";
8
+ import { Memo } from "../../native/memo";
6
9
 
7
10
  export const SETUP_SPLASH_MS = 2600;
8
11
  export const SETUP_TICK_MS = 33;
@@ -181,6 +184,30 @@ export function renderSetupSplash(width: number, height: number, elapsedMs: numb
181
184
  return cells.map(row => row.join(""));
182
185
  }
183
186
 
187
+ const splashMemo = new Memo();
188
+
189
+ /**
190
+ * Native splash: the 2x brand mark with a terminal-clocked shimmer, the
191
+ * wordmark, and the skip hint pinned to the bottom. The water and starfield
192
+ * are cell paintings with no semantic counterpart. A click on the splash
193
+ * sends the `skip` action.
194
+ */
195
+ export function describeSetupSplash(): NativeNode {
196
+ const hint = skipHint();
197
+ return splashMemo.get([hint], () =>
198
+ col(
199
+ [
200
+ node("spacer", { grow: 1 }),
201
+ logoNode(LARGE_LOGO, true),
202
+ text([span("O h M y P i", "strong")], { wrap: "none" }),
203
+ node("spacer", { grow: 1 }),
204
+ text([span(hint, "dim")], { wrap: "none" }),
205
+ ],
206
+ { align: "center", gap: "md", grow: 1, role: "omp.setup.splash", actions: { click: "skip" } },
207
+ ),
208
+ );
209
+ }
210
+
184
211
  /** Centered fallback for windows too small to hold the full scene. */
185
212
  function renderCompactSplash(width: number, height: number, phase: number, shine: ShineConfig): string[] {
186
213
  const art = height >= 14 ? LARGE_LOGO : PI_LOGO;
@@ -18,6 +18,9 @@ import {
18
18
  setSymbolPreset,
19
19
  theme,
20
20
  } from "../../theme/theme";
21
+ import { col, node, span, text } from "../../native/describe";
22
+ import type { NativeChild, NativeNode } from "../../native/node";
23
+ import { Memo } from "../../native/memo";
21
24
  import type { SetupScene, SetupSceneController, SetupSceneHost } from "./types";
22
25
 
23
26
  type ThemeMode = "curated" | "all";
@@ -85,6 +88,50 @@ function renderThemePreview(width: number): string[] {
85
88
  ];
86
89
  }
87
90
 
91
+ /**
92
+ * Native theme preview: status samples, a status bar and a read-only editor
93
+ * in the highlighted theme's tokens. The terminal draws the bar and editor
94
+ * chrome, so none of the ANSI mock's box or fill math applies.
95
+ */
96
+ function describeThemePreview(): NativeNode {
97
+ return col(
98
+ [
99
+ text([span("Preview", "strong")]),
100
+ text([
101
+ span(`${theme.status.success} success`, "success"),
102
+ span(" "),
103
+ span(`${theme.status.warning} warning`, "warning"),
104
+ span(" "),
105
+ span(`${theme.status.error} error`, "error"),
106
+ span(" "),
107
+ span("accent", "accent"),
108
+ ]),
109
+ text([span("Status line", "muted")]),
110
+ node("status", {}, [
111
+ node("seg", { spans: [span(`${theme.icon.model} sonnet`, "statusLineModel")], side: "left" }),
112
+ node("seg", { spans: [span("~/project", "statusLinePath")], side: "left" }),
113
+ node("seg", { spans: [span(`${theme.icon.git} main +2`, "statusLineGitDirty")], side: "left" }),
114
+ node("seg", { spans: [span(`${theme.icon.context} 42%`, "statusLineContext")], side: "right" }),
115
+ node("seg", { spans: [span(`${theme.icon.cost} 0.18`, "statusLineCost")], side: "right" }),
116
+ ]),
117
+ text([span("Editor", "muted")]),
118
+ node("input", {
119
+ text: "Ask anything, edit files, run tools",
120
+ cursor: "Ask anything, edit files, run tools".length,
121
+ prompt: [span(">", "accent")],
122
+ readonly: true,
123
+ }),
124
+ text([
125
+ span(
126
+ `${editorKey("tui.input.submit")} send · ${editorKey("tui.input.newLine")} newline · / commands`,
127
+ "dim",
128
+ ),
129
+ ]),
130
+ ],
131
+ { role: "omp.setup.theme.preview" },
132
+ );
133
+ }
134
+
88
135
  class ThemeSceneController implements SetupSceneController {
89
136
  title = "Pick a theme";
90
137
  get subtitle(): string {
@@ -93,10 +140,12 @@ class ThemeSceneController implements SetupSceneController {
93
140
  #mode: ThemeMode = "curated";
94
141
  #selectList: SelectList;
95
142
  #loadingAllThemes = false;
143
+ /** Error copy shown under the list (raw text; styled at render/describe time). */
96
144
  #message: string | undefined;
97
145
  #previewRequest = 0;
98
146
  #disposed = false;
99
147
  #step: WizardStep | undefined;
148
+ #native = new Memo();
100
149
  readonly #originalTheme = getCurrentThemeName();
101
150
  readonly #originalSymbolPreset: SymbolPreset;
102
151
  readonly #originalColorBlindMode: boolean;
@@ -115,6 +164,7 @@ class ThemeSceneController implements SetupSceneController {
115
164
  }
116
165
 
117
166
  invalidate(): void {
167
+ this.#native.clear();
118
168
  this.#step?.invalidate();
119
169
  this.#selectList.invalidate();
120
170
  }
@@ -168,7 +218,7 @@ class ThemeSceneController implements SetupSceneController {
168
218
  preview.addChild(new Text(line, 0, 0));
169
219
  }
170
220
  const loading = this.#loadingAllThemes ? new Text(theme.fg("dim", "Loading themes…"), 0, 0) : undefined;
171
- const status = this.#message ? new Text(this.#message, 0, 0) : undefined;
221
+ const status = this.#message ? new Text(theme.fg("error", this.#message), 0, 0) : undefined;
172
222
  if (!this.#step) {
173
223
  this.#step = new WizardStep({
174
224
  kind: loading ? "async" : "choice",
@@ -194,6 +244,41 @@ class ThemeSceneController implements SetupSceneController {
194
244
  return this.#step.render(width);
195
245
  }
196
246
 
247
+ /**
248
+ * Intro hints, the live preview, the theme list (a spinner while every
249
+ * theme loads) and any preview error. Theme switches re-describe through
250
+ * `invalidate()`, so the preview's tokens follow the highlighted theme.
251
+ */
252
+ describe(): NativeNode {
253
+ const confirm = editorKey("tui.select.confirm");
254
+ const cancel = editorKey("tui.select.cancel");
255
+ return this.#native.get(
256
+ [this.#mode, this.#loadingAllThemes, this.#selectList, this.#message, confirm, cancel],
257
+ () => {
258
+ const children: NativeChild[] = [
259
+ col([
260
+ text([span(`Theme changes preview live. Nothing is saved until you press ${confirm}.`, "muted")]),
261
+ text([
262
+ span(
263
+ this.#mode === "all"
264
+ ? `Browsing all themes · ${cancel} returns to curated choices`
265
+ : `${cancel} skips this step`,
266
+ "dim",
267
+ ),
268
+ ]),
269
+ ]),
270
+ describeThemePreview(),
271
+ this.#loadingAllThemes
272
+ ? node("spinner", { label: [span("Loading themes…", "dim")] }, undefined, "loading")
273
+ : this.#selectList,
274
+ ];
275
+ if (this.#message)
276
+ children.push(node("text", { spans: [span(this.#message, "error")] }, undefined, "status"));
277
+ return col(children, { gap: "sm", role: "omp.setup.theme" });
278
+ },
279
+ );
280
+ }
281
+
197
282
  #createSelectList(items: readonly SelectItem[], selectedIndex: number): SelectList {
198
283
  const list = new SelectList(items, Math.min(10, Math.max(1, items.length)), getSelectListTheme());
199
284
  list.setSelectedIndex(selectedIndex);
@@ -256,7 +341,7 @@ class ThemeSceneController implements SetupSceneController {
256
341
  this.#selectList = this.#createSelectList(items, selectedIndex);
257
342
  } catch (error) {
258
343
  const message = error instanceof Error ? error.message : String(error);
259
- this.#message = theme.fg("error", `Failed to load themes: ${message}`);
344
+ this.#message = `Failed to load themes: ${message}`;
260
345
  } finally {
261
346
  this.#loadingAllThemes = false;
262
347
  this.#host.requestRender();
@@ -320,7 +405,7 @@ class ThemeSceneController implements SetupSceneController {
320
405
  }
321
406
  if (request !== this.#previewRequest || this.#disposed) return;
322
407
  if (!result.success) {
323
- this.#message = theme.fg("error", result.error ?? "Theme preview failed");
408
+ this.#message = result.error ?? "Theme preview failed";
324
409
  }
325
410
  this.#host.ctx.ui.invalidate();
326
411
  this.#host.requestRender();
@@ -4,10 +4,15 @@ import type { SgrMouseEvent } from "../../mouse";
4
4
  import type { ComposerPreviewStatusSource } from "../../overlays/composer-shape-preview";
5
5
  import type { ComposerShape } from "../../overlays/composer-shape-registry";
6
6
  import type { ModelBrowserSource } from "../../overlays/model-browser";
7
- import type { SymbolPreset } from "../../theme/theme";
8
- import type { SearchProviderId } from "../../tools/web-search";
7
+ import type { SymbolPreset, ThemeColor } from "../../theme/theme";
9
8
  import type { Component, TUI } from "../../tui";
10
9
 
10
+ /** One line of status copy kept as raw text plus its theme colour, never as pre-styled ANSI. */
11
+ export interface StyledLine {
12
+ readonly text: string;
13
+ readonly color: ThemeColor;
14
+ }
15
+
11
16
  /** Terminal capabilities used by setup overlays and the startup splash. */
12
17
  export interface SetupUiHost {
13
18
  readonly ui: Pick<TUI, "showOverlay" | "setFocus" | "requestRender" | "invalidate"> & {
@@ -21,7 +26,6 @@ export interface SetupHost extends SetupUiHost {
21
26
  readonly composerShape: ComposerShape;
22
27
  readonly symbolPreset: SymbolPreset;
23
28
  readonly colorBlindMode: boolean;
24
- readonly webSearchOrder: readonly string[];
25
29
  readonly disabledProviders: readonly string[];
26
30
  readonly authStorage: AuthStorage;
27
31
  readonly modelSource: ModelBrowserSource;
@@ -33,8 +37,6 @@ export interface SetupHost extends SetupUiHost {
33
37
  saveSymbolPreset(preset: SymbolPreset): void;
34
38
  saveColorBlindMode(enabled: boolean): void;
35
39
  saveTheme(mode: "dark" | "light", name: string): void;
36
- isSearchProviderAvailable(id: SearchProviderId): Promise<boolean>;
37
- saveSearchProvider(id: SearchProviderId | "auto"): void;
38
40
  captureBrowserSession(request: OAuthBrowserSessionRequest, signal?: AbortSignal): Promise<string>;
39
41
  copyToClipboard(text: string): Promise<void>;
40
42
  openInBrowser(url: string): void;
@@ -78,29 +80,6 @@ export interface SetupSceneController extends Component {
78
80
  routeMouse?(event: SgrMouseEvent, line: number, col: number): void;
79
81
  }
80
82
 
81
- /**
82
- * A single panel inside a tabbed setup scene. The host scene owns the tab bar
83
- * and forwards rendering/input to the active tab.
84
- */
85
- export interface SetupTab {
86
- readonly id: string;
87
- readonly label: string;
88
- /**
89
- * While `true` the tab owns all keyboard input (e.g. an in-progress OAuth
90
- * login). The parent scene MUST NOT switch tabs or finish while modal.
91
- */
92
- readonly modal: boolean;
93
- /** See {@link SetupSceneController.render}: `maxLines` is the tab-local row budget. */
94
- render(width: number, maxLines?: number): readonly string[];
95
- handleInput(data: string): void;
96
- invalidate(): void;
97
- /** Called when the tab becomes active (including initial mount). */
98
- onActivate?(): void;
99
- /** Mouse routing at tab-local coordinates; see {@link SetupSceneController.routeMouse}. */
100
- routeMouse?(event: SgrMouseEvent, line: number, col: number): void;
101
- dispose(): void;
102
- }
103
-
104
83
  /** Versioned onboarding scene definition. */
105
84
  export interface SetupScene {
106
85
  id: string;
@@ -1,7 +1,11 @@
1
1
  import { type Component, type OverlayFocusOwner } from "../tui";
2
2
  import { matchesKey } from "../keys";
3
+ import { col } from "../native/describe";
4
+ import type { NativeNode, NativeUiEvent } from "../native/node";
5
+ import { Memo } from "../native/memo";
6
+ import { isNativeRendering } from "../native/state";
3
7
  import type { SetupUiHost } from "./scenes/types";
4
- import { renderSetupSplash, SETUP_SPLASH_MS, SETUP_TICK_MS } from "./scenes/splash";
8
+ import { describeSetupSplash, renderSetupSplash, SETUP_SPLASH_MS, SETUP_TICK_MS } from "./scenes/splash";
5
9
 
6
10
  /** Timing controls for the standalone startup animation. */
7
11
  export interface RunStartupSplashOptions {
@@ -13,6 +17,9 @@ export interface RunStartupSplashOptions {
13
17
  class StartupSplashComponent implements Component, OverlayFocusOwner {
14
18
  #phaseStartedAt = 0;
15
19
  #timer: NodeJS.Timeout | undefined;
20
+ /** Native path: one-shot at the end of the splash; the terminal clocks the motion. */
21
+ #deadline: NodeJS.Timeout | undefined;
22
+ #native = new Memo();
16
23
  #done = Promise.withResolvers<void>();
17
24
  #disposed = false;
18
25
  readonly #durationMs: number;
@@ -60,20 +67,50 @@ class StartupSplashComponent implements Component, OverlayFocusOwner {
60
67
  return renderSetupSplash(Math.max(1, width), Math.max(1, this.ctx.ui.terminal.rows), elapsedMs);
61
68
  }
62
69
 
70
+ describe(): NativeNode {
71
+ const splash = describeSetupSplash();
72
+ return this.#native.get([splash], () => col([splash], { grow: 1, role: "omp.app.startup-splash" }));
73
+ }
74
+
75
+ handleNativeEvent(event: NativeUiEvent): void {
76
+ if (event.type === "action" && event.act === "skip") this.#complete();
77
+ }
78
+
79
+ /**
80
+ * ANSI: repaint every tick. Native: no repaint loop, only a one-shot at
81
+ * the end of the splash (re-armed if it fires early).
82
+ */
63
83
  #startTimer(): void {
64
- if (this.#timer) return;
65
- this.#timer = setInterval(() => {
66
- if (this.#disposed) return;
67
- const elapsed = this.#now() - this.#phaseStartedAt;
68
- if (elapsed >= this.#durationMs) {
69
- this.#complete();
70
- return;
84
+ if (isNativeRendering()) {
85
+ if (this.#timer) {
86
+ clearInterval(this.#timer);
87
+ this.#timer = undefined;
71
88
  }
89
+ clearTimeout(this.#deadline);
90
+ const remaining = this.#durationMs - (this.#now() - this.#phaseStartedAt);
91
+ this.#deadline = setTimeout(() => this.#tick(), Math.max(0, remaining));
92
+ return;
93
+ }
94
+ if (this.#timer) return;
95
+ this.#timer = setInterval(() => this.#tick(), this.#tickMs);
96
+ }
97
+
98
+ #tick(): void {
99
+ if (this.#disposed) return;
100
+ const elapsed = this.#now() - this.#phaseStartedAt;
101
+ if (elapsed >= this.#durationMs) {
102
+ this.#complete();
103
+ } else if (isNativeRendering() || !this.#timer) {
104
+ // Re-arm the deadline, or switch loops when the native surface opened/closed.
105
+ this.#startTimer();
106
+ } else {
72
107
  this.ctx.ui.requestRender();
73
- }, this.#tickMs);
108
+ }
74
109
  }
75
110
 
76
111
  #stopTimer(): void {
112
+ clearTimeout(this.#deadline);
113
+ this.#deadline = undefined;
77
114
  if (!this.#timer) return;
78
115
  clearInterval(this.#timer);
79
116
  this.#timer = undefined;