@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
@@ -2,6 +2,11 @@ import { BracketedPasteHandler, decodeReencodedPasteControls } from "../brackete
2
2
  import { getKeybindings } from "../keybindings";
3
3
  import { extractPrintableText, matchesKey } from "../keys";
4
4
  import { KillRing } from "../kill-ring";
5
+ import type { TspInputProps } from "@oh-my-pi/pi-wire";
6
+ import { node } from "../native/describe";
7
+ import { sameProps } from "../native/memo";
8
+ import { plainText } from "../native/spans";
9
+ import type { DescribeContext, NativeNode } from "../native/node";
5
10
  import { SpaceHoldGesture } from "../space-hold";
6
11
  import { type Component, CURSOR_MARKER, type Focusable } from "../tui";
7
12
  import { cursorColumnWindow } from "./scroll-viewport";
@@ -58,6 +63,8 @@ export class Input implements Component, Focusable {
58
63
  prompt = "> ";
59
64
  /** Render the editable value as bullets while retaining the real value internally. */
60
65
  mask = false;
66
+ /** Dim hint a native terminal shows while the value is empty. */
67
+ placeholder: string | undefined;
61
68
  onSubmit?: (value: string) => void;
62
69
  onEscape?: () => void;
63
70
  /** Space-bar push-to-talk; set its `handler` to enable it. */
@@ -81,9 +88,17 @@ export class Input implements Component, Focusable {
81
88
  /** Code units of the current volatile speech-to-text preview (see {@link setVolatileText}). */
82
89
  #volatileTextLen = 0;
83
90
 
91
+ #native?: { props: TspInputProps; node: NativeNode };
92
+
84
93
  getValue(): string {
85
94
  return this.#value;
86
95
  }
96
+
97
+ /** The caret as a UTF-16 offset into {@link getValue}. */
98
+ getCursor(): number {
99
+ return this.#cursor;
100
+ }
101
+
87
102
  /** Return bounded input content and cursor state for debug inspection. */
88
103
  debugState(): Record<string, unknown> {
89
104
  return {
@@ -112,7 +127,14 @@ export class Input implements Component, Focusable {
112
127
  return this.#useTerminalCursor;
113
128
  }
114
129
 
115
- handleInput(data: string): void {
130
+ /**
131
+ * Apply one key: the editor's text bindings (motion, deletion, kill ring,
132
+ * undo), pastes and printable text. Returns whether the key was the
133
+ * field's: false for keys it has no binding for, and for cancel/submit
134
+ * without an `onEscape`/`onSubmit`, so a host (a list's search field) can
135
+ * route everything else on.
136
+ */
137
+ handleInput(data: string): boolean {
116
138
  // Handle bracketed paste mode
117
139
  const paste = this.#pasteHandler.process(data);
118
140
  if (paste.handled) {
@@ -122,77 +144,79 @@ export class Input implements Component, Focusable {
122
144
  this.handleInput(paste.remaining);
123
145
  }
124
146
  }
125
- return;
147
+ return true;
126
148
  }
127
149
 
128
150
  // Space-hold push-to-talk: a sustained space bar starts/stops STT instead of typing spaces.
129
151
  switch (this.spaceHold.process(matchesKey(data, "space"))) {
130
152
  case "type":
131
153
  this.#insertCharacter(" ");
132
- return;
154
+ return true;
133
155
  case "swallow":
134
- return;
156
+ return true;
135
157
  }
136
158
 
137
159
  const kb = getKeybindings();
138
160
 
139
161
  // Escape/Cancel
140
162
  if (kb.matches(data, "tui.select.cancel")) {
141
- if (this.onEscape) this.onEscape();
142
- return;
163
+ if (!this.onEscape) return false;
164
+ this.onEscape();
165
+ return true;
143
166
  }
144
167
 
145
168
  // Undo
146
169
  if (kb.matches(data, "tui.editor.undo")) {
147
170
  this.#undo();
148
- return;
171
+ return true;
149
172
  }
150
173
 
151
174
  // Submit
152
175
  if (kb.matches(data, "tui.input.submit") || data === "\n") {
153
- if (this.onSubmit) this.onSubmit(this.#value);
154
- return;
176
+ if (!this.onSubmit) return false;
177
+ this.onSubmit(this.#value);
178
+ return true;
155
179
  }
156
180
 
157
181
  // Deletion
158
182
  if (kb.matches(data, "tui.editor.deleteCharBackward")) {
159
183
  this.#handleBackspace();
160
- return;
184
+ return true;
161
185
  }
162
186
 
163
187
  if (kb.matches(data, "tui.editor.deleteCharForward")) {
164
188
  this.#handleForwardDelete();
165
- return;
189
+ return true;
166
190
  }
167
191
 
168
192
  if (kb.matches(data, "tui.editor.deleteWordBackward")) {
169
193
  this.#deleteWordBackwards();
170
- return;
194
+ return true;
171
195
  }
172
196
 
173
197
  if (kb.matches(data, "tui.editor.deleteWordForward")) {
174
198
  this.#deleteWordForward();
175
- return;
199
+ return true;
176
200
  }
177
201
 
178
202
  if (kb.matches(data, "tui.editor.deleteToLineStart")) {
179
203
  this.#deleteToLineStart();
180
- return;
204
+ return true;
181
205
  }
182
206
 
183
207
  if (kb.matches(data, "tui.editor.deleteToLineEnd")) {
184
208
  this.#deleteToLineEnd();
185
- return;
209
+ return true;
186
210
  }
187
211
 
188
212
  // Kill ring actions
189
213
  if (kb.matches(data, "tui.editor.yank")) {
190
214
  this.#yank();
191
- return;
215
+ return true;
192
216
  }
193
217
  if (kb.matches(data, "tui.editor.yankPop")) {
194
218
  this.#yankPop();
195
- return;
219
+ return true;
196
220
  }
197
221
 
198
222
  // Cursor movement
@@ -204,7 +228,7 @@ export class Input implements Component, Focusable {
204
228
  const lastGrapheme = graphemes[graphemes.length - 1];
205
229
  this.#cursor -= lastGrapheme ? lastGrapheme.segment.length : 1;
206
230
  }
207
- return;
231
+ return true;
208
232
  }
209
233
 
210
234
  if (kb.matches(data, "tui.editor.cursorRight")) {
@@ -215,36 +239,36 @@ export class Input implements Component, Focusable {
215
239
  const firstGrapheme = graphemes[0];
216
240
  this.#cursor += firstGrapheme ? firstGrapheme.segment.length : 1;
217
241
  }
218
- return;
242
+ return true;
219
243
  }
220
244
 
221
245
  if (kb.matches(data, "tui.editor.cursorLineStart")) {
222
246
  this.#lastAction = null;
223
247
  this.#cursor = 0;
224
- return;
248
+ return true;
225
249
  }
226
250
 
227
251
  if (kb.matches(data, "tui.editor.cursorLineEnd")) {
228
252
  this.#lastAction = null;
229
253
  this.#cursor = this.#value.length;
230
- return;
254
+ return true;
231
255
  }
232
256
 
233
257
  if (kb.matches(data, "tui.editor.cursorWordLeft")) {
234
258
  this.#moveWordBackwards();
235
- return;
259
+ return true;
236
260
  }
237
261
 
238
262
  if (kb.matches(data, "tui.editor.cursorWordRight")) {
239
263
  this.#moveWordForwards();
240
- return;
264
+ return true;
241
265
  }
242
266
 
243
267
  // Regular character input, including Kitty CSI-u text-producing sequences.
244
268
  const printableText = extractPrintableText(data);
245
- if (printableText) {
246
- this.#insertCharacter(printableText);
247
- }
269
+ if (!printableText) return false;
270
+ this.#insertCharacter(printableText);
271
+ return true;
248
272
  }
249
273
 
250
274
  /** Apply terminal paste semantics to text from non-bracketed paste transports
@@ -484,6 +508,33 @@ export class Input implements Component, Focusable {
484
508
  // No cached state to invalidate currently
485
509
  }
486
510
 
511
+ /**
512
+ * An `input` with the value, the caret as a UTF-16 offset and the prompt;
513
+ * the terminal draws the caret, scrolls horizontally and places the IME.
514
+ * A masked input sends one bullet per grapheme, with the caret mapped onto
515
+ * them, so the secret never leaves the process.
516
+ */
517
+ describe(_cx: DescribeContext): NativeNode {
518
+ let value = this.#value;
519
+ let cursor = this.#cursor;
520
+ if (this.mask) {
521
+ const graphemes = [...segmenter.segment(this.#value)];
522
+ value = "•".repeat(graphemes.length);
523
+ cursor = graphemes.filter(grapheme => grapheme.index < this.#cursor).length;
524
+ }
525
+ const prompt = plainText(this.prompt);
526
+ const props: TspInputProps = {
527
+ text: value,
528
+ cursor,
529
+ prompt: prompt || undefined,
530
+ placeholder: this.placeholder,
531
+ };
532
+ if (this.#native && sameProps(this.#native.props, props)) return this.#native.node;
533
+ const described = node("input", props);
534
+ this.#native = { props, node: described };
535
+ return described;
536
+ }
537
+
487
538
  render(width: number): readonly string[] {
488
539
  width = Number.isFinite(width) ? Math.max(0, Math.trunc(width)) : 0;
489
540
  // Calculate visible window
@@ -1,3 +1,6 @@
1
+ import { compactText, styleSpans } from "../native/spans";
2
+ import { node } from "../native/describe";
3
+ import type { DescribeContext, NativeNode } from "../native/node";
1
4
  import type { Component } from "../tui";
2
5
  import { Ellipsis, getWidthConfigEpoch, replaceTabs, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../utils";
3
6
 
@@ -31,6 +34,7 @@ export class KeyValueList implements Component {
31
34
  #rows: readonly KeyValueRow[];
32
35
  readonly #options: KeyValueListOptions;
33
36
  #cache: { width: number; epoch: number; lines: readonly string[] } | undefined;
37
+ #native: NativeNode | undefined;
34
38
 
35
39
  constructor(rows: readonly KeyValueRow[], options: KeyValueListOptions) {
36
40
  this.#rows = rows;
@@ -41,11 +45,25 @@ export class KeyValueList implements Component {
41
45
  if (this.#rows === rows) return false;
42
46
  this.#rows = rows;
43
47
  this.#cache = undefined;
48
+ this.#native = undefined;
44
49
  return true;
45
50
  }
46
51
 
47
52
  invalidate(): void {
48
53
  this.#cache = undefined;
54
+ this.#native = undefined;
55
+ }
56
+
57
+ /** An aligned `kv` grid; label width and value wrapping are the terminal's. */
58
+ describe(_cx: DescribeContext): NativeNode {
59
+ this.#native ??= node("kv", {
60
+ layout: "grid",
61
+ items: this.#rows.map(row => ({
62
+ k: compactText(styleSpans(singleLine(row.label), row.labelStyle)),
63
+ v: compactText(styleSpans(singleLine(row.value), row.valueStyle)),
64
+ })),
65
+ });
66
+ return this.#native;
49
67
  }
50
68
 
51
69
  render(width: number): readonly string[] {
@@ -1,3 +1,4 @@
1
+ import type { TspProps, TspSpace } from "@oh-my-pi/pi-wire";
1
2
  import type { MouseRoutable } from "../../mouse";
2
3
  import type { Component } from "../../tui";
3
4
  import { padding, truncateToWidth, visibleWidth } from "../../utils";
@@ -51,6 +52,49 @@ export interface LayoutAllocation {
51
52
  max?: number;
52
53
  }
53
54
 
55
+ const kNativeAdapter = Symbol("layout.nativeAdapter");
56
+ type AdaptedRenderer = LayoutRenderer & { [kNativeAdapter]?: Component };
57
+
58
+ /**
59
+ * Describe child for layout content: components describe themselves; a lazy
60
+ * row renderer becomes a stable adapter component the native engine renders
61
+ * as a `rows` fallback (it can only produce width-bound rows).
62
+ */
63
+ export function nativeLayoutChild(content: LayoutContent): Component {
64
+ if (typeof content !== "function") return content;
65
+ const adapted = content as AdaptedRenderer;
66
+ adapted[kNativeAdapter] ??= { render: width => content(width, undefined) };
67
+ return adapted[kNativeAdapter];
68
+ }
69
+
70
+ /** Spacing step standing in for a textual gap decoration (the terminal draws no divider glyphs). */
71
+ export function nativeLayoutGap(decoration: LayoutDecoration | undefined): TspSpace | undefined {
72
+ const length = layoutDecorationText(decoration).length;
73
+ if (length === 0) return undefined;
74
+ if (length === 1) return "xs";
75
+ if (length === 2) return "sm";
76
+ return "md";
77
+ }
78
+
79
+ /** Flex props for one layout slot along `axis` (`w` for rows, `h` for stacks). */
80
+ export function nativeSlotProps(
81
+ axis: "w" | "h",
82
+ slot: { fixed?: number; grow?: number; min?: number; max?: number },
83
+ ): TspProps<"col"> {
84
+ const bound = (cells: number): { w: `${number}ch` } | { h: `${number}lines` } =>
85
+ axis === "w" ? { w: `${cells}ch` } : { h: `${cells}lines` };
86
+ const fixed = optionalLayoutSize(slot.fixed);
87
+ if (fixed !== undefined) return { grow: 0, shrink: 0, min: bound(fixed), max: bound(fixed) };
88
+ const min = optionalLayoutSize(slot.min);
89
+ const max = optionalLayoutSize(slot.max);
90
+ return {
91
+ grow: slot.grow === undefined ? undefined : layoutSize(slot.grow),
92
+ basis: "content",
93
+ min: min === undefined || min === 0 ? undefined : bound(min),
94
+ max: max === undefined ? undefined : bound(max),
95
+ };
96
+ }
97
+
54
98
  /** Clamp an external size to a finite, non-negative integer cell count. */
55
99
  export function layoutSize(value: number | undefined, fallback = 0): number {
56
100
  const resolved = value === undefined || !Number.isFinite(value) ? fallback : value;
@@ -1,4 +1,6 @@
1
1
  import type { MouseRoutable, SgrMouseEvent } from "../../mouse";
2
+ import { col, row } from "../../native/describe";
3
+ import type { DescribeContext, NativeNode } from "../../native/node";
2
4
  import type { Component } from "../../tui";
3
5
  import { padding, visibleWidth } from "../../utils";
4
6
  import {
@@ -15,6 +17,9 @@ import {
15
17
  type LayoutInsets,
16
18
  type LayoutRect,
17
19
  layoutSize,
20
+ nativeLayoutChild,
21
+ nativeLayoutGap,
22
+ nativeSlotProps,
18
23
  optionalLayoutSize,
19
24
  renderLayoutContent,
20
25
  uniqueLayoutComponents,
@@ -87,6 +92,7 @@ export class Row implements Component, MouseRoutable {
87
92
  #frames: LayoutRect[] = [];
88
93
  #memo: RowMemo | undefined;
89
94
  #ignoreTight = false;
95
+ #native: { children: RowChild[]; gap: LayoutDecoration | undefined; node: NativeNode } | undefined;
90
96
 
91
97
  constructor(options: RowOptions) {
92
98
  this.#children = options.children.map(child => ({ ...child, padding: { ...child.padding } }));
@@ -168,6 +174,30 @@ export class Row implements Component, MouseRoutable {
168
174
  }
169
175
  }
170
176
 
177
+ /**
178
+ * A flex `row`: each child sits in a slot carrying its width bounds
179
+ * (fixed → min = max `ch`, else grow/min/max). Decorations become gap
180
+ * spacing; clipping and the exact row budget are the terminal's.
181
+ */
182
+ describe(_cx: DescribeContext): NativeNode {
183
+ const cached = this.#native;
184
+ if (cached?.children === this.#children && cached.gap === this.#gap) return cached.node;
185
+ const slots = this.#children.map(child =>
186
+ col(
187
+ [nativeLayoutChild(child.content)],
188
+ nativeSlotProps("w", {
189
+ fixed: child.width,
190
+ grow: child.width === undefined ? layoutSize(child.grow, 1) : undefined,
191
+ min: child.minWidth,
192
+ max: child.maxWidth,
193
+ }),
194
+ ),
195
+ );
196
+ const described = row(slots, { gap: nativeLayoutGap(this.#gap), align: this.#align });
197
+ this.#native = { children: this.#children, gap: this.#gap, node: described };
198
+ return described;
199
+ }
200
+
171
201
  /** Translate a row-local point into a child's local coordinates. */
172
202
  locate(line: number, col: number): RowHit | undefined {
173
203
  for (let index = 0; index < this.#frames.length; index++) {
@@ -1,4 +1,7 @@
1
1
  import type { MouseRoutable, SgrMouseEvent } from "../../mouse";
2
+ import type { TspProps } from "@oh-my-pi/pi-wire";
3
+ import { col, node, row } from "../../native/describe";
4
+ import type { DescribeContext, NativeNode } from "../../native/node";
2
5
  import type { Component } from "../../tui";
3
6
  import { visibleWidth } from "../../utils";
4
7
  import {
@@ -11,6 +14,9 @@ import {
11
14
  type LayoutRect,
12
15
  layoutRatio,
13
16
  layoutSize,
17
+ nativeLayoutChild,
18
+ nativeLayoutGap,
19
+ nativeSlotProps,
14
20
  optionalLayoutSize,
15
21
  uniqueLayoutComponents,
16
22
  } from "./geometry";
@@ -88,6 +94,16 @@ export class SplitPane implements Component, MouseRoutable {
88
94
  #measureMemo: SplitMeasureMemo | undefined;
89
95
  #rowMode: "split" | PaneSide = "split";
90
96
  #rowLeftWidth = -1;
97
+ #native:
98
+ | {
99
+ leftSize: SplitPaneSize;
100
+ rightMinWidth: number;
101
+ narrowPane: PaneSide | undefined;
102
+ divider: LayoutDecoration | undefined;
103
+ height: number | undefined;
104
+ node: NativeNode;
105
+ }
106
+ | undefined;
91
107
 
92
108
  constructor(options: SplitPaneOptions) {
93
109
  this.#left = options.left;
@@ -268,6 +284,55 @@ export class SplitPane implements Component, MouseRoutable {
268
284
  return geometry;
269
285
  }
270
286
 
287
+ /**
288
+ * Two flex slots in a `row`: the left pane fixed (`ch`) or a fraction of
289
+ * the width within its bounds, the right pane growing from its minimum.
290
+ * With a narrow pane configured the row may wrap, stacking the panes on
291
+ * narrow terminals instead of hiding one.
292
+ */
293
+ describe(_cx: DescribeContext): NativeNode {
294
+ const cached = this.#native;
295
+ if (
296
+ cached?.leftSize === this.#leftSize &&
297
+ cached.rightMinWidth === this.#rightMinWidth &&
298
+ cached.narrowPane === this.#narrowPane &&
299
+ cached.divider === this.#divider &&
300
+ cached.height === this.#height
301
+ ) {
302
+ return cached.node;
303
+ }
304
+ const size = this.#leftSize;
305
+ const leftProps: TspProps<"col"> =
306
+ size.fixed !== undefined
307
+ ? nativeSlotProps("w", { fixed: size.fixed })
308
+ : {
309
+ ...nativeSlotProps("w", { grow: 0, min: size.min, max: size.max }),
310
+ basis: layoutRatio(size.ratio, 0.5),
311
+ };
312
+ const rightProps = nativeSlotProps("w", { grow: 1, min: this.#rightMinWidth });
313
+ const height = this.#height;
314
+ const described = row(
315
+ [
316
+ node("col", leftProps, [nativeLayoutChild(this.#left)], "left"),
317
+ node("col", rightProps, [nativeLayoutChild(this.#right)], "right"),
318
+ ],
319
+ { gap: nativeLayoutGap(this.#divider), align: this.#align, wrap: this.#narrowPane !== undefined },
320
+ );
321
+ const result =
322
+ height === undefined
323
+ ? described
324
+ : col([described], { min: { h: `${height}lines` }, max: { h: `${height}lines` } });
325
+ this.#native = {
326
+ leftSize: size,
327
+ rightMinWidth: this.#rightMinWidth,
328
+ narrowPane: this.#narrowPane,
329
+ divider: this.#divider,
330
+ height,
331
+ node: result,
332
+ };
333
+ return result;
334
+ }
335
+
271
336
  /** Translate a split-local point into pane-local coordinates. */
272
337
  locate(line: number, col: number): SplitPaneHit | undefined {
273
338
  const panes: readonly [PaneSide, LayoutContent, LayoutRect | undefined][] = [
@@ -1,4 +1,6 @@
1
1
  import type { MouseRoutable, SgrMouseEvent } from "../../mouse";
2
+ import { col } from "../../native/describe";
3
+ import type { DescribeContext, NativeNode } from "../../native/node";
2
4
  import type { Component } from "../../tui";
3
5
  import { padding } from "../../utils";
4
6
  import {
@@ -13,6 +15,8 @@ import {
13
15
  type LayoutInsets,
14
16
  type LayoutRect,
15
17
  layoutSize,
18
+ nativeLayoutChild,
19
+ nativeSlotProps,
16
20
  optionalLayoutSize,
17
21
  renderLayoutContent,
18
22
  uniqueLayoutComponents,
@@ -76,6 +80,7 @@ export class Stack implements Component, MouseRoutable {
76
80
  #frames: LayoutRect[] = [];
77
81
  #memo: StackMemo | undefined;
78
82
  #ignoreTight = false;
83
+ #native: { children: StackChild[]; height: number | undefined; node: NativeNode } | undefined;
79
84
 
80
85
  constructor(options: StackOptions) {
81
86
  this.#children = options.children.map(child => ({ ...child, padding: { ...child.padding } }));
@@ -141,6 +146,28 @@ export class Stack implements Component, MouseRoutable {
141
146
  }
142
147
  }
143
148
 
149
+ /**
150
+ * A `col` of slots carrying each child's height bounds (fixed → min = max
151
+ * `lines`, else grow/min/max); an exact stack height bounds the column.
152
+ */
153
+ describe(_cx: DescribeContext): NativeNode {
154
+ const cached = this.#native;
155
+ if (cached?.children === this.#children && cached.height === this.#height) return cached.node;
156
+ const slots = this.#children.map(child =>
157
+ col(
158
+ [nativeLayoutChild(child.content)],
159
+ nativeSlotProps("h", { fixed: child.height, grow: child.grow, min: child.minHeight, max: child.maxHeight }),
160
+ ),
161
+ );
162
+ const height = this.#height;
163
+ const described = col(
164
+ slots,
165
+ height === undefined ? undefined : { min: { h: `${height}lines` }, max: { h: `${height}lines` } },
166
+ );
167
+ this.#native = { children: this.#children, height, node: described };
168
+ return described;
169
+ }
170
+
144
171
  /** Translate a stack-local point into a child's local coordinates. */
145
172
  locate(line: number, col: number): StackHit | undefined {
146
173
  for (let index = 0; index < this.#frames.length; index++) {