@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
@@ -28,13 +28,14 @@
28
28
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
29
29
  import {
30
30
  type Component,
31
- extractPrintableText,
31
+ Input,
32
32
  matchesKey,
33
33
  padding,
34
34
  routeSgrMouseInput,
35
35
  sliceByColumn,
36
36
  type TUI,
37
37
  truncateToWidth,
38
+ visibleWidth,
38
39
  } from "../index";
39
40
  import type { MessageRenderer } from "../chat/extension-types";
40
41
  import { recentTranscriptEntries, type TranscriptEntryLike as TranscriptEntry } from "../chat/transcript-entry";
@@ -56,6 +57,23 @@ import {
56
57
  positionRail,
57
58
  userTurnLabel,
58
59
  } from "../chat/transcript-outline";
60
+ import type { TspPickerItem, TspPickerProps } from "@oh-my-pi/pi-wire";
61
+ import { compact, node, span, text } from "../native/describe";
62
+ import type { DescribeContext, NativeChild, NativeNode, NativeUiEvent } from "../native/node";
63
+ import { actionHint, hintsRow, overlayCard } from "../native/overlay";
64
+ import { CLOSE_ACTION, type PickerEvent, picker, pickerAction, pickerEvent, pickerQuery } from "../native/picker";
65
+ import { isNativeRendering } from "../native/state";
66
+ import {
67
+ collectBlocks,
68
+ EARLIER_TURNS_KEY,
69
+ earlierTurnsItem,
70
+ TIMELINE_COLUMNS,
71
+ TimelineItems,
72
+ targetCopy,
73
+ timelineItem,
74
+ turnItem,
75
+ turnPreview,
76
+ } from "./copy-selector";
59
77
 
60
78
  /** One alternate branch at a divergence: its root and message path root → most-recent leaf. */
61
79
  export interface BranchVariantPath {
@@ -88,6 +106,10 @@ interface SiblingColumn {
88
106
  targets: OutlineTarget[];
89
107
  /** Short label for the column header: the branch's first user prompt. */
90
108
  label: string;
109
+ /** Native list items for this column, built on first describe. */
110
+ nativeItems?: NativeNode[];
111
+ /** Picker catalogue while this column's tab is open: the main items, then this branch's. */
112
+ pickerItems?: { main: readonly TspPickerItem[]; items: TspPickerItem[] };
91
113
  }
92
114
 
93
115
  /** Blank columns between branch-strip columns. */
@@ -121,12 +143,26 @@ export class RewindSelectorComponent implements Component {
121
143
  #entries: TranscriptEntry[];
122
144
  /** True while older history is still unreplayed. */
123
145
  #truncated = false;
146
+ /** Filter field while the filter prompt is open; undefined shows the full transcript. */
147
+ #filterInput: Input | undefined;
124
148
  /** Filter query while the filter prompt is open; undefined shows the full transcript. */
125
- #filter: string | undefined;
149
+ get #filter(): string | undefined {
150
+ return this.#filterInput?.getValue();
151
+ }
126
152
  /** Main transcript rows from the last frame; the filter matches what is on screen. */
127
153
  #mainRows: readonly (readonly string[])[] = [];
128
154
  /** Lowercased plain text per rendered child row array (row arrays are cached, so identity is stable). */
129
155
  #rowText = new WeakMap<readonly string[], string>();
156
+ /** Native filter haystack: lowercased turn text per main target (no rendered rows under TSP). */
157
+ #nativeTexts: { targets: OutlineTarget[]; texts: string[] } | undefined;
158
+ /** Last described root and the state it was built from. */
159
+ #native: { memo: string; targets: OutlineTarget[]; node: NativeNode } | undefined;
160
+ /** Main-path list items, rebuilt only when the replayed targets change. */
161
+ #nativeItems: { targets: OutlineTarget[]; truncated: boolean; items: NativeNode[] } | undefined;
162
+ /** Timeline picker items of the replayed main path. */
163
+ #pickerItems = new TimelineItems();
164
+ /** Last described picker and the state it was built from. */
165
+ #picker: { memo: string; targets: OutlineTarget[]; node: NativeNode } | undefined;
130
166
 
131
167
  constructor(
132
168
  entries: TranscriptEntry[],
@@ -239,6 +275,11 @@ export class RewindSelectorComponent implements Component {
239
275
  const from = this.#slidePosition(now);
240
276
  this.#slide = { from, to: variant, startedAt: now };
241
277
  this.#activeVariant = variant;
278
+ // The camera slide is repaint-only; a native surface has no camera to move.
279
+ if (isNativeRendering()) {
280
+ this.deps.requestRender();
281
+ return;
282
+ }
242
283
  this.#slideTimer ??= setInterval(() => {
243
284
  if (!this.#slide || Date.now() - this.#slide.startedAt >= SLIDE_MS) this.#stopSlide();
244
285
  this.deps.requestRender();
@@ -287,13 +328,7 @@ export class RewindSelectorComponent implements Component {
287
328
  return;
288
329
  }
289
330
  if (matchesKey(data, "f")) {
290
- // The filter must search the whole branch, not just the startup tail.
291
- this.#loadFullHistory();
292
- this.#filter = "";
293
- this.#activeVariant = 0;
294
- this.#siblingSelected = 0;
295
- this.#stopSlide();
296
- this.deps.requestRender();
331
+ this.#openFilter();
297
332
  return;
298
333
  }
299
334
  if (matchesAppToolsExpand(data)) {
@@ -309,18 +344,11 @@ export class RewindSelectorComponent implements Component {
309
344
  return;
310
345
  }
311
346
  if (matchesKey(data, "left")) {
312
- if (this.#activeVariant > 0) this.#slideTo(this.#activeVariant - 1);
313
- else this.#move(-1, target => target.isUserTurn);
347
+ this.#left();
314
348
  return;
315
349
  }
316
350
  if (matchesKey(data, "right")) {
317
- const columns = this.#stripColumns();
318
- if (this.#activeVariant < columns.length) {
319
- this.#siblingSelected = 0;
320
- this.#slideTo(this.#activeVariant + 1);
321
- } else if (this.#activeVariant === 0) {
322
- this.#move(1, target => target.isUserTurn);
323
- }
351
+ this.#right();
324
352
  return;
325
353
  }
326
354
  if (data === "a" || data === "A") {
@@ -328,8 +356,7 @@ export class RewindSelectorComponent implements Component {
328
356
  return;
329
357
  }
330
358
  if (matchesKey(data, "enter") || matchesKey(data, "return") || data === "\n") {
331
- const target = this.#outlinedTarget();
332
- if (target) this.deps.onSelect(target.entryId);
359
+ this.#selectOutlined();
333
360
  return;
334
361
  }
335
362
  // Page/home/end/shift+arrow scrolling without moving the selection.
@@ -338,6 +365,49 @@ export class RewindSelectorComponent implements Component {
338
365
  }
339
366
  }
340
367
 
368
+ /** `f`: open the filter over the whole branch. */
369
+ #openFilter(): void {
370
+ // The filter must search the whole branch, not just the startup tail.
371
+ this.#loadFullHistory();
372
+ const input = new Input();
373
+ input.prompt = `${theme.fg("accent", "filter:")} `;
374
+ input.placeholder = "words…";
375
+ this.#filterInput = input;
376
+ this.#activeVariant = 0;
377
+ this.#siblingSelected = 0;
378
+ this.#stopSlide();
379
+ this.deps.requestRender();
380
+ }
381
+
382
+ /** Left: the previous branch at a fork, else the previous user turn. */
383
+ #left(): void {
384
+ if (this.#activeVariant > 0) this.#slideTo(this.#activeVariant - 1);
385
+ else this.#move(-1, target => target.isUserTurn);
386
+ }
387
+
388
+ /** Right: the next branch at a fork, else the next user turn. */
389
+ #right(): void {
390
+ const columns = this.#stripColumns();
391
+ if (this.#activeVariant < columns.length) {
392
+ this.#siblingSelected = 0;
393
+ this.#slideTo(this.#activeVariant + 1);
394
+ } else if (this.#activeVariant === 0) {
395
+ this.#move(1, target => target.isUserTurn);
396
+ }
397
+ }
398
+
399
+ /** Enter while filtering: rewind to the selection when it matches. */
400
+ #selectFiltered(): void {
401
+ const target = this.#filterMatches().includes(this.#selected) ? this.#targets[this.#selected] : undefined;
402
+ if (target) this.deps.onSelect(target.entryId);
403
+ }
404
+
405
+ /** Enter: rewind to the outlined turn (main path or the active branch column). */
406
+ #selectOutlined(): void {
407
+ const target = this.#outlinedTarget();
408
+ if (target) this.deps.onSelect(target.entryId);
409
+ }
410
+
341
411
  #toggleExpanded(): void {
342
412
  this.#expanded = !this.#expanded;
343
413
  this.#builder.setExpanded(this.#expanded);
@@ -357,8 +427,7 @@ export class RewindSelectorComponent implements Component {
357
427
  return;
358
428
  }
359
429
  if (matchesKey(data, "enter") || matchesKey(data, "return") || data === "\n") {
360
- const target = this.#filterMatches().includes(this.#selected) ? this.#targets[this.#selected] : undefined;
361
- if (target) this.deps.onSelect(target.entryId);
430
+ this.#selectFiltered();
362
431
  return;
363
432
  }
364
433
  if (matchesAppToolsExpand(data)) {
@@ -375,17 +444,15 @@ export class RewindSelectorComponent implements Component {
375
444
  this.#stepFiltered(1, userTurnsOnly);
376
445
  return;
377
446
  }
378
- if (matchesKey(data, "backspace")) {
379
- if (this.#filter!.length === 0) {
380
- this.#closeFilter();
381
- return;
382
- }
383
- this.#setFilter(this.#filter!.slice(0, -1));
447
+ const input = this.#filterInput!;
448
+ const before = input.getValue();
449
+ if (matchesKey(data, "backspace") && before.length === 0) {
450
+ this.#closeFilter();
384
451
  return;
385
452
  }
386
- const printable = extractPrintableText(data);
387
- if (printable) {
388
- this.#setFilter(this.#filter! + printable);
453
+ if (input.handleInput(data)) {
454
+ if (input.getValue() !== before) this.#filterChanged();
455
+ else this.deps.requestRender();
389
456
  return;
390
457
  }
391
458
  if (this.#browser.handleScrollKey(data)) {
@@ -395,13 +462,12 @@ export class RewindSelectorComponent implements Component {
395
462
 
396
463
  /** Leave the filter, keeping the selected item outlined in the full transcript. */
397
464
  #closeFilter(): void {
398
- this.#filter = undefined;
465
+ this.#filterInput = undefined;
399
466
  this.deps.requestRender();
400
467
  }
401
468
 
402
- /** Update the query; keep the selection when it still matches, else rest on the newest match above it. */
403
- #setFilter(query: string): void {
404
- this.#filter = query;
469
+ /** The query changed; keep the selection when it still matches, else rest on the newest match above it. */
470
+ #filterChanged(): void {
405
471
  const matches = this.#filterMatches();
406
472
  if (!matches.includes(this.#selected)) {
407
473
  this.#selected = matches.findLast(index => index < this.#selected) ?? matches.at(-1) ?? this.#selected;
@@ -434,18 +500,31 @@ export class RewindSelectorComponent implements Component {
434
500
  ? new RegExp(`(?<![\\p{L}\\p{N}_])${RegExp.escape(word)}(?![\\p{L}\\p{N}_])`, "u")
435
501
  : new RegExp(RegExp.escape(word), "u"),
436
502
  );
503
+ if (isNativeRendering() && this.#nativeTexts?.targets !== this.#targets) {
504
+ this.#nativeTexts = {
505
+ targets: this.#targets,
506
+ // Turn text plus its commands and tool output, like the expanded rendered rows.
507
+ texts: this.#targets.map(target => {
508
+ const blocks = collectBlocks(target.entries);
509
+ const parts = [targetCopy(target, blocks).content, ...blocks.map(block => block.content)];
510
+ return parts.join("\n").toLowerCase();
511
+ }),
512
+ };
513
+ }
437
514
  const matches: number[] = [];
438
515
  for (let index = 0; index < this.#targets.length; index++) {
439
516
  if (!this.#isMainSelectable(index)) continue;
440
517
  const target = this.#targets[index]!;
441
- const texts = this.#mainRows.slice(target.start, target.end).map(rows => {
442
- let text = this.#rowText.get(rows);
443
- if (text === undefined) {
444
- text = Bun.stripANSI(rows.join("\n")).toLowerCase();
445
- this.#rowText.set(rows, text);
446
- }
447
- return text;
448
- });
518
+ const texts = isNativeRendering()
519
+ ? [this.#nativeTexts?.texts[index] ?? ""]
520
+ : this.#mainRows.slice(target.start, target.end).map(rows => {
521
+ let text = this.#rowText.get(rows);
522
+ if (text === undefined) {
523
+ text = Bun.stripANSI(rows.join("\n")).toLowerCase();
524
+ this.#rowText.set(rows, text);
525
+ }
526
+ return text;
527
+ });
449
528
  if (patterns.every(pattern => texts.some(text => pattern.test(text)))) matches.push(index);
450
529
  }
451
530
  return matches;
@@ -499,6 +578,341 @@ export class RewindSelectorComponent implements Component {
499
578
  return this.#mainVisible?.[index] ?? true;
500
579
  }
501
580
 
581
+ // ========================================================================
582
+ // Native
583
+ // ========================================================================
584
+
585
+ /** A `picker` is its own sheet: the backend mounts it in `layer`, over the transcript. */
586
+ nativeSheet(cx: DescribeContext): boolean {
587
+ return cx.supports("picker");
588
+ }
589
+
590
+ /** A branch tab click moves between the current path and its alternates, as Left/Right do. */
591
+ #showVariant(value: string | undefined): void {
592
+ const variant = Number(value);
593
+ if (!Number.isInteger(variant) || variant === this.#activeVariant) return;
594
+ if (variant < 0 || variant > this.#stripColumns().length) return;
595
+ this.#siblingSelected = 0;
596
+ if (variant === 0) {
597
+ this.#activeVariant = 0;
598
+ this.#stopSlide();
599
+ this.deps.requestRender();
600
+ } else {
601
+ this.#slideTo(variant);
602
+ }
603
+ }
604
+
605
+ /**
606
+ * Picker pointer events: a row click outlines that turn, a second click
607
+ * rewinds there (Enter); the action bar and tabs run their keys' paths.
608
+ */
609
+ #handlePickerEvent(event: PickerEvent): void {
610
+ if (event.kind === "action") {
611
+ switch (event.act) {
612
+ case "tab":
613
+ this.#showVariant(event.value);
614
+ return;
615
+ case "rewind":
616
+ if (this.#filter === undefined) this.#selectOutlined();
617
+ else this.#selectFiltered();
618
+ return;
619
+ case "lateral":
620
+ // A click steps back a user turn, or on to the next branch (wrapping to the current path).
621
+ if (this.#filter !== undefined || this.#stripColumns().length === 0) this.#left();
622
+ else if (this.#activeVariant < this.#stripColumns().length) this.#right();
623
+ else this.#showVariant("0");
624
+ return;
625
+ case "filter":
626
+ this.#openFilter();
627
+ return;
628
+ case "earlier":
629
+ this.#loadFullHistory();
630
+ return;
631
+ case "close":
632
+ if (this.#filter === undefined) this.deps.onCancel();
633
+ else this.#closeFilter();
634
+ return;
635
+ case "clear":
636
+ this.#closeFilter();
637
+ return;
638
+ default:
639
+ return;
640
+ }
641
+ }
642
+ if (!this.#outline(event.item)) return;
643
+ this.deps.requestRender();
644
+ if (event.kind === "activate") {
645
+ if (this.#filter === undefined) this.#selectOutlined();
646
+ else this.#selectFiltered();
647
+ }
648
+ }
649
+
650
+ /** Outline the turn `id`: on the active branch tab, or on the main path (leaving the tab). */
651
+ #outline(id: string): boolean {
652
+ if (this.#activeVariant > 0) {
653
+ const targets = this.#stripColumns()[this.#activeVariant - 1]?.targets ?? [];
654
+ const index = targets.findIndex(target => target.turnId === id);
655
+ if (index >= 0) {
656
+ this.#siblingSelected = index;
657
+ return true;
658
+ }
659
+ }
660
+ const index = this.#targets.findIndex(target => target.turnId === id);
661
+ if (index < 0) return false;
662
+ if (this.#filter !== undefined && !this.#filterMatches().includes(index)) return false;
663
+ this.#selected = index;
664
+ this.#activeVariant = 0;
665
+ this.#siblingSelected = 0;
666
+ this.#stopSlide();
667
+ return true;
668
+ }
669
+
670
+ handleNativeEvent(event: NativeUiEvent): void {
671
+ const picked = pickerEvent(event);
672
+ if (picked) {
673
+ this.#handlePickerEvent(picked);
674
+ return;
675
+ }
676
+ if (event.type !== "select" && event.type !== "activate") return;
677
+ if (event.key === "branches") {
678
+ this.#showVariant(event.item);
679
+ return;
680
+ }
681
+ // A click on an item outlines it and rewinds there, as Enter would.
682
+ if (event.key === "list") {
683
+ if (event.item === EARLIER_TURNS_KEY) {
684
+ this.#loadFullHistory();
685
+ return;
686
+ }
687
+ const index = this.#targets.findIndex(target => target.turnId === event.item);
688
+ if (index < 0) return;
689
+ this.#selected = index;
690
+ this.#activeVariant = 0;
691
+ this.#siblingSelected = 0;
692
+ this.#stopSlide();
693
+ } else if (event.key === "branch" && this.#activeVariant > 0) {
694
+ const targets = this.#stripColumns()[this.#activeVariant - 1]?.targets ?? [];
695
+ const index = targets.findIndex(target => target.turnId === event.item);
696
+ if (index < 0) return;
697
+ this.#siblingSelected = index;
698
+ } else {
699
+ return;
700
+ }
701
+ this.deps.requestRender();
702
+ this.#selectOutlined();
703
+ }
704
+
705
+ describe(cx: DescribeContext): NativeNode {
706
+ return cx.supports("picker") ? this.#describePicker() : this.#describeCard();
707
+ }
708
+
709
+ /**
710
+ * The `timeline` picker: one row per turn, the branch tabs at a fork, the
711
+ * filter as the query, and the outlined turn's own transcript components
712
+ * as the preview under the drop warning.
713
+ */
714
+ #describePicker(): NativeNode {
715
+ const filter = this.#filter;
716
+ const memo = `${this.#selected}|${this.#activeVariant}|${this.#siblingSelected}|${this.#truncated}|${filter ?? "\0"}|${this.#filterInput?.getCursor()}`;
717
+ const cached = this.#picker;
718
+ if (cached?.memo === memo && cached.targets === this.#targets) return cached.node;
719
+
720
+ const main = this.#pickerItems.of(this.#targets);
721
+ const columns = filter === undefined ? this.#stripColumns() : [];
722
+ const column = columns[this.#activeVariant - 1];
723
+ const matches = filter === undefined ? undefined : this.#filterMatches();
724
+ const props: TspPickerProps = {
725
+ title: "Rewind",
726
+ subtitle: "Pick the point to continue from",
727
+ icon: "rewind",
728
+ noun: "turns",
729
+ size: "lg",
730
+ layout: "timeline",
731
+ preview: "side",
732
+ ...pickerQuery(this.#filterInput ?? null),
733
+ placeholder: "Filter turns…",
734
+ columns: TIMELINE_COLUMNS,
735
+ items: main,
736
+ selected: this.#targets[this.#selected]?.turnId ?? null,
737
+ total: this.#targets.length,
738
+ empty: "Nothing to rewind to",
739
+ };
740
+ if (matches) {
741
+ props.order = matches.map(index => this.#targets[index]!.turnId);
742
+ if (!matches.includes(this.#selected)) props.selected = null;
743
+ }
744
+ if (columns.length > 0) {
745
+ props.tabs = [
746
+ { id: "0", label: "Current" },
747
+ ...columns.map((strip, index) => ({
748
+ id: String(index + 1),
749
+ label: strip.label.length > 32 ? `${strip.label.slice(0, 31)}…` : strip.label,
750
+ })),
751
+ ];
752
+ props.tab = String(this.#activeVariant);
753
+ }
754
+ if (column) {
755
+ // The shared history above the fork, then the alternate branch.
756
+ if (column.pickerItems?.main !== main) {
757
+ column.pickerItems = { main, items: [...main, ...column.targets.map(timelineItem)] };
758
+ }
759
+ props.items = column.pickerItems.items;
760
+ props.order = [
761
+ ...this.#targets.slice(0, this.#selected).map(target => target.turnId),
762
+ ...column.targets.map(target => target.turnId),
763
+ ];
764
+ props.selected = column.targets[this.#siblingSelected]?.turnId ?? null;
765
+ }
766
+ props.actions = compact([
767
+ pickerAction("rewind", "Rewind here", "enter", { primary: true }),
768
+ pickerAction("lateral", columns.length > 0 ? "Branches" : "User turns", ["left", "right"]),
769
+ filter === undefined ? pickerAction("filter", "Filter", "f") : undefined,
770
+ filter === undefined && this.#truncated ? pickerAction("earlier", "Earlier turns", "a") : undefined,
771
+ filter === undefined ? CLOSE_ACTION : { ...CLOSE_ACTION, label: "Show all" },
772
+ ]);
773
+
774
+ const preview: NativeChild[] = [];
775
+ const outlined = column ? column.targets[this.#siblingSelected] : this.#targets[this.#selected];
776
+ if (outlined && props.selected !== null) {
777
+ // A user turn rewinds past itself (its text returns to the editor); anything else keeps itself.
778
+ const kept = column || this.#targets[this.#selected]!.isUserTurn ? this.#selected : this.#selected + 1;
779
+ const dropped = this.#targets.length - kept;
780
+ preview.push(
781
+ text(
782
+ dropped > 0
783
+ ? [
784
+ span("Continue from here: everything below is dropped", "warning"),
785
+ span(`${theme.sep.dot}${dropped} turn${dropped === 1 ? "" : "s"}`, "dim"),
786
+ ]
787
+ : [span("Continue from here: nothing below to drop", "warning")],
788
+ { role: "omp.rewind.drop" },
789
+ ),
790
+ ...(column?.builder ?? this.#builder).container.children.slice(outlined.start, outlined.end),
791
+ );
792
+ }
793
+ const root = picker(props, preview);
794
+ this.#picker = { memo, targets: this.#targets, node: root };
795
+ return root;
796
+ }
797
+
798
+ #describeCard(): NativeNode {
799
+ const memo = `${this.#selected}|${this.#activeVariant}|${this.#siblingSelected}|${this.#truncated}|${this.#filter ?? "\0"}|${this.#filterInput?.getCursor()}`;
800
+ const cached = this.#native;
801
+ if (cached?.memo === memo && cached.targets === this.#targets) return cached.node;
802
+
803
+ const filter = this.#filter;
804
+ const children: NativeChild[] = [];
805
+ const allItems = this.#mainItems();
806
+ const columns = filter === undefined ? this.#stripColumns() : [];
807
+ const matches = filter === undefined ? undefined : this.#filterMatches();
808
+ if (filter !== undefined && matches) {
809
+ children.push(
810
+ this.#filterInput!,
811
+ node(
812
+ "list",
813
+ {
814
+ selected: matches.includes(this.#selected) ? (this.#targets[this.#selected]?.turnId ?? null) : null,
815
+ filter,
816
+ empty: `No items match "${filter}"`,
817
+ virtual: true,
818
+ max: 0.5,
819
+ },
820
+ matches.map(index => allItems[index + (this.#truncated ? 1 : 0)]!),
821
+ "list",
822
+ ),
823
+ );
824
+ } else {
825
+ children.push(
826
+ node(
827
+ "list",
828
+ {
829
+ selected: this.#targets[this.#selected]?.turnId ?? null,
830
+ empty: "Nothing to rewind to",
831
+ virtual: true,
832
+ max: 0.5,
833
+ },
834
+ allItems,
835
+ "list",
836
+ ),
837
+ );
838
+ }
839
+ if (columns.length > 0) {
840
+ children.push(
841
+ node(
842
+ "tabs",
843
+ {
844
+ items: [
845
+ { id: "0", label: "current" },
846
+ ...columns.map((column, index) => ({ id: String(index + 1), label: column.label })),
847
+ ],
848
+ active: String(this.#activeVariant),
849
+ },
850
+ undefined,
851
+ "branches",
852
+ ),
853
+ );
854
+ const column = columns[this.#activeVariant - 1];
855
+ if (column) {
856
+ column.nativeItems ??= column.targets.map(target => turnItem(target));
857
+ children.push(
858
+ node(
859
+ "list",
860
+ { selected: column.targets[this.#siblingSelected]?.turnId ?? null, virtual: true, max: 0.4 },
861
+ column.nativeItems,
862
+ "branch",
863
+ ),
864
+ );
865
+ }
866
+ }
867
+ const outlined = filter === undefined ? this.#outlinedTarget() : this.#targets[this.#selected];
868
+ if (outlined && (!matches || matches.includes(this.#selected))) {
869
+ const item = targetCopy(outlined, collectBlocks(outlined.entries));
870
+ children.push(
871
+ node("section", { head: [span(item.label, "strong")] }, [turnPreview(outlined, item.content)], "preview"),
872
+ );
873
+ }
874
+ const upDown = actionHint(["tui.select.up", "tui.select.down"], "step");
875
+ children.push(
876
+ hintsRow(
877
+ filter === undefined
878
+ ? [
879
+ upDown,
880
+ { keys: ["left", "right"], label: columns.length > 0 ? "branches" : "user turns" },
881
+ { keys: ["f"], label: "filter" },
882
+ { keys: ["enter"], label: "rewind" },
883
+ this.#truncated ? { keys: ["a"], label: "earlier turns" } : undefined,
884
+ actionHint("tui.select.cancel", "cancel"),
885
+ ]
886
+ : [
887
+ upDown,
888
+ { keys: ["left", "right"], label: "user turns" },
889
+ { keys: ["enter"], label: "rewind" },
890
+ actionHint("tui.select.cancel", "show all"),
891
+ ],
892
+ ),
893
+ );
894
+ const root = overlayCard(
895
+ "omp.overlay.rewind",
896
+ [
897
+ span(`${theme.icon.rewind} `),
898
+ span("Rewind", "strong"),
899
+ span(`${theme.sep.dot}pick the point to continue from`, "dim"),
900
+ ],
901
+ children,
902
+ );
903
+ this.#native = { memo, targets: this.#targets, node: root };
904
+ return root;
905
+ }
906
+
907
+ #mainItems(): NativeNode[] {
908
+ const cached = this.#nativeItems;
909
+ if (cached?.targets === this.#targets && cached.truncated === this.#truncated) return cached.items;
910
+ const items = this.#targets.map(target => turnItem(target));
911
+ if (this.#truncated) items.unshift(earlierTurnsItem);
912
+ this.#nativeItems = { targets: this.#targets, truncated: this.#truncated, items };
913
+ return items;
914
+ }
915
+
502
916
  // ========================================================================
503
917
  // Render
504
918
  // ========================================================================
@@ -592,7 +1006,7 @@ export class RewindSelectorComponent implements Component {
592
1006
  : undefined,
593
1007
  },
594
1008
  footer: [
595
- `${theme.fg("accent", "filter:")} ${query}${theme.fg("accent", "▏")} ${count} ${theme.fg("dim", keys)}`,
1009
+ `${this.#filterInput!.render(visibleWidth(`filter: ${query}`) + 1)[0]} ${count} ${theme.fg("dim", keys)}`,
596
1010
  ],
597
1011
  };
598
1012
  }
@@ -29,7 +29,7 @@ export class SessionAccountSelectorComponent extends OverlayPanel {
29
29
  onSelect: (account: SessionPinAccount) => void,
30
30
  onCancel: () => void,
31
31
  ) {
32
- super(`Select a ${providerName} account for this session`);
32
+ super(`Select a ${providerName} account for this session`, "omp.overlay.session-account");
33
33
  const accountsByValue = new Map<string, SessionPinAccount>();
34
34
  const items: SelectItem[] = accounts.map(account => {
35
35
  const value = String(account.credentialId);