@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
@@ -1,8 +1,11 @@
1
- import type { Usage } from "@oh-my-pi/pi-ai";
2
- import { Container, Spacer } from "../index";
1
+ import type { AssistantMessage, Usage } from "@oh-my-pi/pi-ai";
2
+ import { Container } from "../tui";
3
+ import { Spacer } from "../components/spacer";
3
4
  import { formatDuration, formatNumber } from "@oh-my-pi/pi-utils";
4
5
  import { theme } from "../theme/theme";
5
6
  import { formatMetricRow, MetricRow, type MetricSpec } from "../components/metric";
7
+ import { node, row, span, text } from "../native/describe";
8
+ import type { NativeChild, NativeNode } from "../native/node";
6
9
 
7
10
  /** Below this the rate is nonsense (cached/instant responses yield absurd tok/s). */
8
11
  const MIN_DURATION_MS = 100;
@@ -32,13 +35,84 @@ export function turnElapsedMs(
32
35
  return elapsed > 0 ? Math.round(elapsed) : undefined;
33
36
  }
34
37
 
35
- function usageRowSpecs(
36
- usage: Usage,
37
- durationMs?: number,
38
- ttftMs?: number,
39
- timestamp?: number,
40
- turnElapsedMs?: number,
41
- ): MetricSpec[] {
38
+ /** A finished turn's totals, the native `omp.turn.usage` line under its last answer. */
39
+ export interface TurnUsageSummary {
40
+ /** Prompt→yield wall time; undefined when either end is unknown. */
41
+ readonly elapsedMs: number | undefined;
42
+ /**
43
+ * Prompt tokens: input, cache writes and orchestration input. Cache reads
44
+ * re-read the context each request, so they stay out (as in the status
45
+ * line's total).
46
+ */
47
+ readonly input: number;
48
+ /** Output tokens, orchestration output included. */
49
+ readonly output: number;
50
+ /** Billed cost in dollars. */
51
+ readonly cost: number;
52
+ }
53
+
54
+ /**
55
+ * Sums the requests of a turn. {@link add} returns the turn's summary on the
56
+ * message that ends the run (any stop but `toolUse`) and starts over.
57
+ */
58
+ export class TurnUsageTally {
59
+ #input = 0;
60
+ #output = 0;
61
+ #cost = 0;
62
+
63
+ /** Drop a partial turn (a new prompt, a fresh run). */
64
+ reset(): void {
65
+ this.#input = 0;
66
+ this.#output = 0;
67
+ this.#cost = 0;
68
+ }
69
+
70
+ add(message: AssistantMessage, turnStartedAt: number | undefined): TurnUsageSummary | undefined {
71
+ const { usage } = message;
72
+ this.#input += usage.input + usage.cacheWrite + (usage.orchestration?.input ?? 0);
73
+ this.#output += usage.output + (usage.orchestration?.output ?? 0);
74
+ this.#cost += usage.cost.total;
75
+ if (message.stopReason === "toolUse") return undefined;
76
+ const summary =
77
+ this.#input + this.#output > 0 || this.#cost > 0
78
+ ? {
79
+ elapsedMs: turnElapsedMs(turnStartedAt, message),
80
+ input: this.#input,
81
+ output: this.#output,
82
+ cost: this.#cost,
83
+ }
84
+ : undefined;
85
+ this.reset();
86
+ return summary;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * The native turn line: `12.4s · 19K tok · $0.02 this turn` (the time drops
92
+ * out when unknown, the cost when nothing was billed), and its tooltip with
93
+ * exact counts.
94
+ */
95
+ export function formatTurnUsage(summary: TurnUsageSummary): { text: string; title: string } {
96
+ const tokens = summary.input + summary.output;
97
+ const cost = summary.cost > 0 ? (summary.cost < 0.005 ? "<$0.01" : `$${summary.cost.toFixed(2)}`) : undefined;
98
+ const time = summary.elapsedMs === undefined ? undefined : formatDuration(summary.elapsedMs);
99
+ const text = [time, `${formatNumber(tokens)} tok`, cost].filter(part => part !== undefined).join(" · ");
100
+ const exact = `${tokens.toLocaleString("en-US")} tokens (${summary.input.toLocaleString("en-US")} in · ${summary.output.toLocaleString("en-US")} out)`;
101
+ const title = [time, exact, cost].filter(part => part !== undefined).join(" · ");
102
+ return { text: `${text} this turn`, title: `This turn: ${title}` };
103
+ }
104
+
105
+ /** Output tokens per second over the whole request; undefined when the duration is too short to mean anything. */
106
+ function usageThroughput(usage: Usage, durationMs: number | undefined): number | undefined {
107
+ if (!durationMs || durationMs <= MIN_DURATION_MS || usage.output <= 0) return undefined;
108
+ // TPS over the total request duration — the post-TTFT window undercounts
109
+ // generation time when reasoning tokens are hidden before the first
110
+ // visible byte, inflating the rate.
111
+ return (usage.output / durationMs) * 1000;
112
+ }
113
+
114
+ /** Every metric except throughput, which the native row declares as a `rate`. */
115
+ function usageRowBaseSpecs(usage: Usage, ttftMs?: number, timestamp?: number, turnElapsedMs?: number): MetricSpec[] {
42
116
  const totalInput = usage.input + usage.cacheWrite;
43
117
  const specs: MetricSpec[] = [];
44
118
  // Lead with the turn's local wall-clock time (down to the second), log-line style.
@@ -61,16 +135,88 @@ function usageRowSpecs(
61
135
  if (ttftMs && ttftMs > 0) {
62
136
  specs.push({ leading: theme.icon.time, value: `${(ttftMs / 1000).toFixed(1)}s` });
63
137
  }
64
- if (durationMs && durationMs > MIN_DURATION_MS && usage.output > 0) {
65
- // TPS over the total request duration — the post-TTFT window undercounts
66
- // generation time when reasoning tokens are hidden before the first
67
- // visible byte, inflating the rate.
68
- const tokPerSec = (usage.output / durationMs) * 1000;
138
+ return specs;
139
+ }
140
+
141
+ function usageRowSpecs(
142
+ usage: Usage,
143
+ durationMs?: number,
144
+ ttftMs?: number,
145
+ timestamp?: number,
146
+ turnElapsedMs?: number,
147
+ ): MetricSpec[] {
148
+ const specs = usageRowBaseSpecs(usage, ttftMs, timestamp, turnElapsedMs);
149
+ const tokPerSec = usageThroughput(usage, durationMs);
150
+ if (tokPerSec !== undefined) {
69
151
  specs.push({ leading: theme.icon.throughput, value: `${tokPerSec.toFixed(1)}/s` });
70
152
  }
71
153
  return specs;
72
154
  }
73
155
 
156
+ /** Per-turn usage block: a dim metric strip under the turn; natively a wrapping row with a `rate` for throughput. */
157
+ class UsageRowBlock extends Container {
158
+ readonly #usage: Usage;
159
+ readonly #durationMs: number | undefined;
160
+ readonly #ttftMs: number | undefined;
161
+ readonly #timestamp: number | undefined;
162
+ readonly #turnElapsedMs: number | undefined;
163
+ #nativeNode: NativeNode | undefined;
164
+
165
+ constructor(usage: Usage, durationMs?: number, ttftMs?: number, timestamp?: number, turnElapsedMs?: number) {
166
+ super();
167
+ this.#usage = usage;
168
+ this.#durationMs = durationMs;
169
+ this.#ttftMs = ttftMs;
170
+ this.#timestamp = timestamp;
171
+ this.#turnElapsedMs = turnElapsedMs;
172
+ this.addChild(new Spacer(1));
173
+ this.addChild(
174
+ new MetricRow(usageRowSpecs(usage, durationMs, ttftMs, timestamp, turnElapsedMs), {
175
+ separator: " ",
176
+ overflow: "wrap",
177
+ paddingX: 1,
178
+ paddingY: 0,
179
+ style: text => theme.fg("dim", text),
180
+ }),
181
+ );
182
+ }
183
+
184
+ /**
185
+ * One quiet mono line (`18:02 · Δ 6.2s · in 18.4K · out 640 · cache 12K ·
186
+ * ttft 0.9s · 96 tok/s`): worded metrics instead of the ANSI icons, the
187
+ * full timestamp in the tooltip, and throughput as a `rate`.
188
+ */
189
+ override describe(): NativeNode {
190
+ if (this.#nativeNode) return this.#nativeNode;
191
+ const usage = this.#usage;
192
+ const parts: string[] = [];
193
+ const timestamp = this.#timestamp;
194
+ const stamped = timestamp !== undefined && Number.isFinite(timestamp) && timestamp > 0;
195
+ if (stamped) parts.push(formatUsageTimestamp(timestamp).slice(11, 16));
196
+ if (this.#turnElapsedMs !== undefined && this.#turnElapsedMs > 0) {
197
+ parts.push(`Δ ${formatDuration(Math.round(this.#turnElapsedMs))}`);
198
+ }
199
+ parts.push(`in ${formatNumber(usage.input + usage.cacheWrite)}`, `out ${formatNumber(usage.output)}`);
200
+ if (usage.cacheRead > 0) parts.push(`cache ${formatNumber(usage.cacheRead)}`);
201
+ if (this.#ttftMs && this.#ttftMs > 0) parts.push(`ttft ${(this.#ttftMs / 1000).toFixed(1)}s`);
202
+ const children: NativeChild[] = [text([span(parts.join(" · "), "dim")])];
203
+ const tokPerSec = usageThroughput(usage, this.#durationMs);
204
+ if (tokPerSec !== undefined) {
205
+ children.push(
206
+ text([span(" · ", "dim")]),
207
+ node("rate", { value: Math.round(tokPerSec * 10) / 10, unit: "tok/s" }),
208
+ );
209
+ }
210
+ this.#nativeNode = row(children, {
211
+ role: "omp.usage.turn",
212
+ gap: "none",
213
+ align: "baseline",
214
+ ...(stamped ? { title: formatUsageTimestamp(timestamp) } : {}),
215
+ });
216
+ return this.#nativeNode;
217
+ }
218
+ }
219
+
74
220
  /** Format the metrics shared by standalone usage blocks and compact tool groups. */
75
221
  export function formatUsageRow(
76
222
  usage: Usage,
@@ -102,17 +248,7 @@ export function createUsageRowBlock(
102
248
  timestamp?: number,
103
249
  turnElapsedMs?: number,
104
250
  ): Container {
105
- const block = new Container();
106
- block.addChild(new Spacer(1));
107
- block.addChild(
108
- new MetricRow(usageRowSpecs(usage, durationMs, ttftMs, timestamp, turnElapsedMs), {
109
- separator: " ",
110
- overflow: "wrap",
111
- paddingX: 1,
112
- paddingY: 0,
113
- style: text => theme.fg("dim", text),
114
- }),
115
- );
251
+ const block = new UsageRowBlock(usage, durationMs, ttftMs, timestamp, turnElapsedMs);
116
252
  usageRowBlocks.add(block);
117
253
  return block;
118
254
  }
@@ -12,6 +12,10 @@ import {
12
12
  visibleWidth,
13
13
  } from "../index";
14
14
  import { fileHyperlink } from "../render/hyperlink";
15
+ import { registerNativeBlob } from "../native/blobs";
16
+ import { node, row, span } from "../native/describe";
17
+ import { plainText } from "../native/spans";
18
+ import type { DescribeContext, NativeNode } from "../native/node";
15
19
  import { convertImageToPng } from "../chat/image-loading";
16
20
  import { attachmentSgr } from "./composer-attachments";
17
21
  import { cachedImageDimensions, setCachedImageDimensions } from "./image-references";
@@ -29,9 +33,12 @@ const RESET_FG = "\x1b[39m";
29
33
  * (pastes are usually re-encoded JPEG/WebP) convert before transmit — the same pipeline
30
34
  * the transcript uses. `null` = conversion in flight or failed. */
31
35
  const kImagePng = Symbol("omp.imagePng");
36
+ /** Content address of the draft image's decoded bytes, registered once for TSP `image` nodes. */
37
+ const kImageBlob = Symbol("omp.imageBlob");
32
38
 
33
39
  interface ImageContentWithPng extends ImageContent {
34
40
  [kImagePng]?: ImageContent | null;
41
+ [kImageBlob]?: string;
35
42
  }
36
43
 
37
44
  /**
@@ -50,6 +57,59 @@ export class AttachmentChipsBand implements Component {
50
57
  private readonly requestRender: () => void,
51
58
  ) {}
52
59
 
60
+ #native: { chips: readonly ComposerChipDescriptor[]; node: NativeNode } | undefined;
61
+
62
+ /**
63
+ * A wrapping `row` of chip `card`s (`omp.composer.chip`) titled with the
64
+ * buffer token (`<icon> #N`): images and videos show the image itself,
65
+ * pastes their leading lines; the caption carries pixel size or line/char
66
+ * count. Hidden while nothing is staged.
67
+ */
68
+ describe(_cx: DescribeContext): NativeNode {
69
+ const chips = this.editor.composerChips();
70
+ if (this.#native?.chips === chips) return this.#native.node;
71
+ const cards: NativeNode[] = [];
72
+ for (const chip of chips) {
73
+ const icon = theme.symbol(
74
+ chip.kind === "paste" ? "chip.paste" : chip.kind === "video" ? "chip.video" : "chip.image",
75
+ );
76
+ const title = `${icon} #${chip.n}`;
77
+ let content: NativeNode;
78
+ let caption: string;
79
+ if (chip.kind === "paste") {
80
+ caption = chip.text.lineCount > 1 ? `+${chip.text.lineCount} lines` : `${chip.text.charCount} chars`;
81
+ content = node("text", {
82
+ spans: [span(plainText(chip.text.content.split("\n", 4).join("\n")), "muted")],
83
+ wrap: "none",
84
+ lines: 4,
85
+ });
86
+ } else {
87
+ const dims = this.#imageDims(chip.image);
88
+ caption = dims ? `${dims.width}x${dims.height}` : "";
89
+ const image = chip.image as ImageContentWithPng;
90
+ const blob = image[kImageBlob] ?? registerNativeBlob(Buffer.from(image.data, "base64"), image.mimeType);
91
+ image[kImageBlob] = blob;
92
+ content = node("image", {
93
+ blob,
94
+ alt: title,
95
+ w: dims?.width,
96
+ h: dims?.height,
97
+ max: { w: "12ch", h: "4lines" },
98
+ });
99
+ }
100
+ const head =
101
+ chip.kind !== "paste" && chip.link ? [span(title, "strong", { href: chip.link })] : [span(title, "strong")];
102
+ const children: NativeNode[] = [content];
103
+ if (caption) children.push(node("text", { spans: [span(caption, "dim")], wrap: "none" }));
104
+ cards.push(
105
+ node("card", { role: "omp.composer.chip", tone: "accent", head }, children, `${chip.kind}:${chip.n}`),
106
+ );
107
+ }
108
+ const described = row(cards, { gap: "sm", wrap: true, role: "omp.composer.chips", hidden: cards.length === 0 });
109
+ this.#native = { chips, node: described };
110
+ return described;
111
+ }
112
+
53
113
  render(width: number): readonly string[] {
54
114
  const chips = this.editor.composerChips();
55
115
  if (chips.length === 0) return [];
@@ -47,8 +47,10 @@ export function modelChipStyle(label: string, restore = "\x1b[39m\x1b[49m"): str
47
47
  /** Every glyph a skill chip may start with, across all symbol presets. */
48
48
  const SKILL_ICONS = [...new Set(Object.values(SYMBOL_PRESETS).map(m => m["icon.extensionSkill"]))];
49
49
 
50
- /** Skill names as they appear in chips: word characters and dashes, dots only between segments. */
51
- const SKILL_NAME_SOURCE = "[\\w-]+(?:\\.[\\w-]+)*";
50
+ /** Skill names as they appear in chips: word characters and dashes, dots only between segments,
51
+ * optionally behind one collision namespace (`<namespace>/<name>`). */
52
+ const SKILL_NAME_SEGMENT_SOURCE = "[\\w-]+(?:\\.[\\w-]+)*";
53
+ const SKILL_NAME_SOURCE = `${SKILL_NAME_SEGMENT_SOURCE}(?:/${SKILL_NAME_SEGMENT_SOURCE})?`;
52
54
 
53
55
  /** Regex source for a chip glyph; word glyphs (ASCII preset) must not continue a preceding word. */
54
56
  function glyphSource(icon: string): string {
@@ -214,12 +216,26 @@ export function composerTokenRegex(mentionLabels: Iterable<string>): RegExp {
214
216
 
215
217
  const VISION_MARKER_REGEX = /\[(Image|Video) #([1-9]\d*)((?:,[^\]\n]*)?)\](?: attachment:\/\/(\2))?/g;
216
218
 
217
- /** Offsets image marker indices, including matching `attachment://` references. */
218
- export function shiftImageMarkers(text: string, offset: number): string {
219
- if (offset === 0) return text;
219
+ /** Marker for the Nth attached image or video preview: `[Image #N, WxH]`, or `[Image #N]` without dims. */
220
+ export function formatVisionMarker(
221
+ kind: "image" | "video",
222
+ n: number,
223
+ dims?: { width: number; height: number },
224
+ ): string {
225
+ const label = `${kind === "video" ? "Video" : "Image"} #${n}`;
226
+ return dims ? `[${label}, ${dims.width}x${dims.height}]` : `[${label}]`;
227
+ }
228
+
229
+ /**
230
+ * Offsets image marker indices, including matching `attachment://` references. With `imageCount`,
231
+ * markers above it are left alone: like `compactImageMarkers`, they are not this text's attachments.
232
+ */
233
+ export function shiftImageMarkers(text: string, offset: number, imageCount?: number): string {
234
+ if (offset === 0 || imageCount === 0) return text;
220
235
  return text.replace(
221
236
  VISION_MARKER_REGEX,
222
- (_match, kind: string, idx: string, tail: string, attachmentIdx: string | undefined) => {
237
+ (match, kind: string, idx: string, tail: string, attachmentIdx: string | undefined) => {
238
+ if (imageCount !== undefined && Number(idx) > imageCount) return match;
223
239
  const marker = `[${kind} #${Number(idx) + offset}${tail}]`;
224
240
  return attachmentIdx === undefined ? marker : `${marker} attachment://${Number(attachmentIdx) + offset}`;
225
241
  },
@@ -249,8 +265,14 @@ export function collapseImageMarkers(
249
265
  /**
250
266
  * Drops unreferenced vision attachments from a submission and densely remaps
251
267
  * retained image/video markers. Returns `null` when no compaction is needed.
268
+ * With `byAppearance`, retained markers are also renumbered in the order they first
269
+ * appear, for editors whose images attach out of order (concurrent path loads).
252
270
  */
253
- export function compactImageMarkers(text: string, imageCount: number): { text: string; keep: number[] } | null {
271
+ export function compactImageMarkers(
272
+ text: string,
273
+ imageCount: number,
274
+ options?: { byAppearance?: boolean },
275
+ ): { text: string; keep: number[] } | null {
254
276
  if (imageCount === 0) return null;
255
277
  const referenced = new Set<number>();
256
278
  const scanner = new RegExp(VISION_MARKER_REGEX.source, "g");
@@ -260,8 +282,8 @@ export function compactImageMarkers(text: string, imageCount: number): { text: s
260
282
  const n = Number(match[2]);
261
283
  if (n <= imageCount) referenced.add(n);
262
284
  }
263
- if (referenced.size === imageCount) return null;
264
- const keep = [...referenced].sort((a, b) => a - b);
285
+ const keep = options?.byAppearance ? [...referenced] : [...referenced].sort((a, b) => a - b);
286
+ if (keep.length === imageCount && keep.every((n, i) => n === i + 1)) return null;
265
287
  const remap = new Map<number, number>(keep.map((n, i) => [n, i + 1]));
266
288
  const rewritten = text.replace(
267
289
  VISION_MARKER_REGEX,
@@ -16,6 +16,8 @@ import {
16
16
  type ViewportSize,
17
17
  } from "../tui";
18
18
  import { sliceWithWidth, visibleWidth } from "../utils";
19
+ import type { NativeChild, NativeSurface, NativeSurfaceProvider } from "../native/node";
20
+ import { sameItems } from "../native/memo";
19
21
  import { postmortem } from "@oh-my-pi/pi-utils";
20
22
  import { CustomEditor } from "./custom-editor";
21
23
  import type { WordCompletionMethod } from "./word-completion";
@@ -99,6 +101,13 @@ export interface RuntimeChildrenOptions {
99
101
  * settled rows it displaces retire to native scrollback.
100
102
  */
101
103
  readonly transient?: readonly Component[];
104
+ /**
105
+ * Dock order on a TSP terminal (no status strip; the composer carries its
106
+ * facts): the native dock stacks HUD pills, the working row and queued messages over
107
+ * the composer in its own order, and may add describe-only roots. Defaults
108
+ * to the roots below the transcript in render order.
109
+ */
110
+ readonly nativeDock?: readonly Component[];
102
111
  }
103
112
 
104
113
  /** Controls the first terminal paint for a composer that does not already own the terminal. */
@@ -114,7 +123,11 @@ export interface ComposerStartOptions {
114
123
  readonly deferInput?: boolean;
115
124
  }
116
125
 
117
- /** Mount slot below the editor: the startup status line, then the session-aware one. */
126
+ /**
127
+ * Mount slot below the editor: the startup status line, then the session-aware
128
+ * one. ANSI only: a TSP terminal has no status strip, the composer carries the
129
+ * status line's facts ({@link StatusLineComponent.describeComposerFacts}).
130
+ */
118
131
  class StatusHost implements Component {
119
132
  #component: Component | undefined;
120
133
 
@@ -189,7 +202,7 @@ function rowTargetCandidates(target: Component): ((local: number) => string[]) |
189
202
  * It owns the terminal, welcome header, and editor; InteractiveMode later supplies authoritative
190
203
  * data and mounts the session-aware runtime children without replacing the visible header.
191
204
  */
192
- export class Composer implements TerminalFrameProvider {
205
+ export class Composer implements TerminalFrameProvider, NativeSurfaceProvider {
193
206
  readonly ui: TUI;
194
207
  #editor: CustomEditor;
195
208
  readonly #header = new Container();
@@ -207,6 +220,7 @@ export class Composer implements TerminalFrameProvider {
207
220
  #headerBefore: readonly Component[] = [];
208
221
  #headerAfter: readonly Component[] = [];
209
222
  #runtimeChildren: readonly Component[] = [];
223
+ #nativeDock: readonly Component[] | undefined;
210
224
  /** Cache-driven status line shown until {@link setStatusComponent} mounts the session's. */
211
225
  #startupStatus: StatusLineComponent | undefined;
212
226
  #runtimeMounted = false;
@@ -263,6 +277,8 @@ export class Composer implements TerminalFrameProvider {
263
277
  #transientChrome: ReadonlySet<Component> = new Set();
264
278
  #transientChromeFloor: number | undefined;
265
279
  #lastInterruptAt = 0;
280
+ /** Last described surface; its arrays are reused while their children are unchanged. */
281
+ #nativeSurface: NativeSurface = { main: [], dock: [] };
266
282
  #started = false;
267
283
  #stopped = false;
268
284
  #transferred = false;
@@ -415,6 +431,41 @@ export class Composer implements TerminalFrameProvider {
415
431
  return { history, viewport: this.#paintHoverBand(mutable, spans) };
416
432
  }
417
433
 
434
+ /**
435
+ * Describe the whole surface for a TSP terminal. `main` is the flowing
436
+ * document: the header (welcome, extras) and every transcript block as its
437
+ * own component child. `dock` is the live chrome below the transcript in
438
+ * render order: pending messages, HUDs, the working row, the editor and the
439
+ * status line. There is no history/viewport split: retirement, resize
440
+ * replay and hover bands are ANSI concerns.
441
+ */
442
+ describeSurface(): NativeSurface {
443
+ if (!this.#started || this.#stopped) return this.#nativeSurface;
444
+ const main: NativeChild[] = [...this.#header.children];
445
+ const dock: NativeChild[] = [];
446
+ if (!this.#runtimeMounted) {
447
+ // The bootstrap gap is row spacing; the terminal owns the dock layout.
448
+ dock.push(this.editor);
449
+ } else {
450
+ const roots = this.#runtimeChildren;
451
+ const transcriptIndex = roots.findIndex(root => root instanceof TranscriptContainer);
452
+ if (transcriptIndex < 0) {
453
+ dock.push(...roots);
454
+ } else {
455
+ const transcript = roots[transcriptIndex] as TranscriptContainer;
456
+ main.push(...roots.slice(0, transcriptIndex), ...transcript.nativeBlocks());
457
+ dock.push(...(this.#nativeDock ?? roots.slice(transcriptIndex + 1)));
458
+ }
459
+ }
460
+ const previous = this.#nativeSurface;
461
+ const nextMain = sameItems(previous.main, main) ? previous.main : main;
462
+ const nextDock = sameItems(previous.dock, dock) ? previous.dock : dock;
463
+ if (nextMain !== previous.main || nextDock !== previous.dock) {
464
+ this.#nativeSurface = { main: nextMain, dock: nextDock };
465
+ }
466
+ return this.#nativeSurface;
467
+ }
468
+
418
469
  /**
419
470
  * Append one below-transcript root's rows to `after`, recording click spans
420
471
  * for its row targets in `after` coordinates.
@@ -837,6 +888,7 @@ export class Composer implements TerminalFrameProvider {
837
888
  this.#disposeStartupStatus();
838
889
  this.#statusHost.setComponent(component);
839
890
  this.editor.setTopBorderProvider(undefined);
891
+ this.editor.composerFacts = component;
840
892
  }
841
893
 
842
894
  #disposeStartupStatus(): void {
@@ -849,6 +901,7 @@ export class Composer implements TerminalFrameProvider {
849
901
  if (this.#stopped) return;
850
902
  this.#transientChrome = new Set(options.transient);
851
903
  this.#transientChromeFloor = undefined;
904
+ this.#nativeDock = options.nativeDock;
852
905
  this.ui.removeChild(this.#statusHost);
853
906
  if (this.#runtimeMounted) {
854
907
  for (const child of this.#runtimeChildren) this.ui.removeChild(child);