@oh-my-pi/pi-tui 18.4.3 → 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 (447) hide show
  1. package/CHANGELOG.md +36 -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/todo-reminder.d.ts +4 -1
  22. package/dist/types/chat/tool-execution.d.ts +25 -1
  23. package/dist/types/chat/transcript-actions.d.ts +37 -0
  24. package/dist/types/chat/transcript-entry.d.ts +3 -1
  25. package/dist/types/chat/user-message.d.ts +25 -0
  26. package/dist/types/chrome/collab-qrcode.d.ts +7 -0
  27. package/dist/types/chrome/context-thresholds.d.ts +11 -0
  28. package/dist/types/chrome/countdown-timer.d.ts +9 -3
  29. package/dist/types/chrome/diff.d.ts +12 -0
  30. package/dist/types/chrome/dynamic-border.d.ts +3 -0
  31. package/dist/types/chrome/format.d.ts +6 -0
  32. package/dist/types/chrome/message-divider.d.ts +13 -0
  33. package/dist/types/chrome/message-frame.d.ts +10 -0
  34. package/dist/types/chrome/message-notice.d.ts +23 -0
  35. package/dist/types/chrome/overlay-box.d.ts +11 -2
  36. package/dist/types/chrome/qrcode.d.ts +7 -0
  37. package/dist/types/chrome/segment-track.d.ts +7 -0
  38. package/dist/types/chrome/selector-helpers.d.ts +0 -6
  39. package/dist/types/chrome/status-notice.d.ts +14 -0
  40. package/dist/types/chrome/streaming-panel.d.ts +3 -0
  41. package/dist/types/chrome/tool-activity.d.ts +3 -0
  42. package/dist/types/chrome/transcript-container.d.ts +13 -0
  43. package/dist/types/chrome/transcript-status.d.ts +15 -3
  44. package/dist/types/components/box.d.ts +7 -0
  45. package/dist/types/components/disclosure.d.ts +9 -0
  46. package/dist/types/components/editor.d.ts +37 -0
  47. package/dist/types/components/form.d.ts +14 -0
  48. package/dist/types/components/image.d.ts +7 -0
  49. package/dist/types/components/input.d.ts +20 -1
  50. package/dist/types/components/key-value-list.d.ts +3 -0
  51. package/dist/types/components/layout/geometry.d.ts +16 -0
  52. package/dist/types/components/layout/row.d.ts +7 -0
  53. package/dist/types/components/layout/split-pane.d.ts +8 -0
  54. package/dist/types/components/layout/stack.d.ts +6 -0
  55. package/dist/types/components/loader.d.ts +48 -0
  56. package/dist/types/components/markdown.d.ts +8 -0
  57. package/dist/types/components/metric.d.ts +7 -0
  58. package/dist/types/components/progress-bar.d.ts +3 -0
  59. package/dist/types/components/scroll-view.d.ts +6 -0
  60. package/dist/types/components/section.d.ts +3 -0
  61. package/dist/types/components/select-list.d.ts +33 -0
  62. package/dist/types/components/settings-list.d.ts +68 -0
  63. package/dist/types/components/spacer.d.ts +4 -0
  64. package/dist/types/components/tab-bar.d.ts +9 -0
  65. package/dist/types/components/table.d.ts +7 -0
  66. package/dist/types/components/text.d.ts +6 -0
  67. package/dist/types/components/tree-view.d.ts +9 -0
  68. package/dist/types/components/truncated-text.d.ts +3 -0
  69. package/dist/types/components/wizard-step.d.ts +6 -0
  70. package/dist/types/hotkeys-markdown.d.ts +24 -0
  71. package/dist/types/index.d.ts +5 -0
  72. package/dist/types/latex-block.d.ts +7 -0
  73. package/dist/types/native/apply.d.ts +39 -0
  74. package/dist/types/native/backend.d.ts +94 -0
  75. package/dist/types/native/blobs.d.ts +29 -0
  76. package/dist/types/native/describe.d.ts +56 -0
  77. package/dist/types/native/encode.d.ts +50 -0
  78. package/dist/types/native/icons.d.ts +18 -0
  79. package/dist/types/native/memo.d.ts +27 -0
  80. package/dist/types/native/node.d.ts +107 -0
  81. package/dist/types/native/overlay.d.ts +64 -0
  82. package/dist/types/native/picker.d.ts +124 -0
  83. package/dist/types/native/reconcile.d.ts +41 -0
  84. package/dist/types/native/settle.d.ts +11 -0
  85. package/dist/types/native/spans.d.ts +21 -0
  86. package/dist/types/native/state.d.ts +6 -0
  87. package/dist/types/native/tone.d.ts +24 -0
  88. package/dist/types/overlays/advisor-config.d.ts +20 -0
  89. package/dist/types/overlays/agent-hub-renderer.d.ts +27 -11
  90. package/dist/types/overlays/agent-hub.d.ts +10 -0
  91. package/dist/types/overlays/agent-transcript-viewer.d.ts +7 -0
  92. package/dist/types/overlays/agents-hub.d.ts +8 -0
  93. package/dist/types/overlays/annotation-overlay.d.ts +3 -0
  94. package/dist/types/overlays/ask-dialog.d.ts +23 -0
  95. package/dist/types/overlays/bordered-loader.d.ts +3 -0
  96. package/dist/types/overlays/btw-history-panel.d.ts +9 -0
  97. package/dist/types/overlays/btw-panel.d.ts +3 -0
  98. package/dist/types/overlays/cleanse-panel.d.ts +5 -2
  99. package/dist/types/overlays/composer-shape-preview.d.ts +7 -1
  100. package/dist/types/overlays/copy-selector.d.ts +38 -0
  101. package/dist/types/overlays/error-banner.d.ts +9 -0
  102. package/dist/types/overlays/extensions/extension-list.d.ts +1 -0
  103. package/dist/types/overlays/history-search.d.ts +18 -0
  104. package/dist/types/overlays/hook-editor.d.ts +28 -1
  105. package/dist/types/overlays/hook-input.d.ts +3 -0
  106. package/dist/types/overlays/hook-selector.d.ts +10 -0
  107. package/dist/types/overlays/hub-frame.d.ts +18 -0
  108. package/dist/types/overlays/jobs-panel.d.ts +24 -0
  109. package/dist/types/overlays/login-dialog.d.ts +10 -0
  110. package/dist/types/overlays/logout-account-selector.d.ts +4 -0
  111. package/dist/types/overlays/mcp-add-wizard.d.ts +4 -0
  112. package/dist/types/overlays/model-browser.d.ts +69 -0
  113. package/dist/types/overlays/model-hub.d.ts +7 -0
  114. package/dist/types/overlays/model-picker.d.ts +7 -0
  115. package/dist/types/overlays/move-overlay.d.ts +3 -0
  116. package/dist/types/overlays/oauth-selector.d.ts +4 -0
  117. package/dist/types/overlays/omfg-panel.d.ts +3 -0
  118. package/dist/types/overlays/pause-screen.d.ts +12 -0
  119. package/dist/types/overlays/plan-review-overlay.d.ts +5 -0
  120. package/dist/types/overlays/plan-save-overlay.d.ts +10 -0
  121. package/dist/types/overlays/plugin-selector.d.ts +4 -0
  122. package/dist/types/overlays/plugin-settings.d.ts +30 -0
  123. package/dist/types/overlays/queue-mode-selector.d.ts +4 -0
  124. package/dist/types/overlays/reset-usage-selector.d.ts +8 -0
  125. package/dist/types/overlays/rewind-selector.d.ts +5 -0
  126. package/dist/types/overlays/session-info-overlay.d.ts +19 -1
  127. package/dist/types/overlays/session-selector.d.ts +64 -1
  128. package/dist/types/overlays/settings-defs.d.ts +14 -0
  129. package/dist/types/overlays/settings-selector.d.ts +21 -0
  130. package/dist/types/overlays/show-images-selector.d.ts +4 -0
  131. package/dist/types/overlays/snapcompact-shape-preview.d.ts +2 -0
  132. package/dist/types/overlays/stats-notice.d.ts +8 -0
  133. package/dist/types/overlays/theme-selector.d.ts +11 -0
  134. package/dist/types/overlays/thinking-selector.d.ts +4 -0
  135. package/dist/types/overlays/tree-selector.d.ts +60 -2
  136. package/dist/types/overlays/usage-dashboard.d.ts +26 -3
  137. package/dist/types/overlays/usage-row.d.ts +36 -2
  138. package/dist/types/prompt/attachment-chips.d.ts +8 -0
  139. package/dist/types/prompt/composer-attachments.d.ts +15 -3
  140. package/dist/types/prompt/composer.d.ts +18 -1
  141. package/dist/types/prompt/custom-editor.d.ts +48 -2
  142. package/dist/types/prompt/editor-top-gap.d.ts +2 -0
  143. package/dist/types/prompt/macos-spelling.d.ts +6 -0
  144. package/dist/types/prompt/magic-keywords.d.ts +9 -0
  145. package/dist/types/prompt/queued-messages.d.ts +23 -0
  146. package/dist/types/prompt/skill-tokens.d.ts +4 -2
  147. package/dist/types/prompt/welcome.d.ts +16 -0
  148. package/dist/types/render/code-cell.d.ts +10 -0
  149. package/dist/types/render/file-list.d.ts +8 -0
  150. package/dist/types/render/hyperlink.d.ts +14 -0
  151. package/dist/types/render/output-block.d.ts +43 -0
  152. package/dist/types/render/output-pane.d.ts +17 -0
  153. package/dist/types/render/tool-card.d.ts +8 -0
  154. package/dist/types/render/tree-list.d.ts +8 -0
  155. package/dist/types/render/width-aware-text.d.ts +7 -0
  156. package/dist/types/setup/scenes/outro.d.ts +7 -0
  157. package/dist/types/setup/scenes/sign-in.d.ts +7 -0
  158. package/dist/types/setup/scenes/splash.d.ts +8 -0
  159. package/dist/types/setup/scenes/types.d.ts +6 -1
  160. package/dist/types/setup/wizard-overlay.d.ts +9 -0
  161. package/dist/types/status-line/component.d.ts +49 -5
  162. package/dist/types/status-line/context-usage.d.ts +20 -0
  163. package/dist/types/status-line/footer.d.ts +8 -0
  164. package/dist/types/status-line/metrics.d.ts +1 -2
  165. package/dist/types/status-line/segments.d.ts +10 -1
  166. package/dist/types/status-line/types.d.ts +40 -1
  167. package/dist/types/terminal-capabilities.d.ts +1 -1
  168. package/dist/types/terminal.d.ts +27 -0
  169. package/dist/types/theme/defaults/index.d.ts +100 -0
  170. package/dist/types/theme/schema.d.ts +2 -0
  171. package/dist/types/theme/shimmer.d.ts +8 -0
  172. package/dist/types/theme/theme-class.d.ts +2 -0
  173. package/dist/types/theme/theme.d.ts +33 -1
  174. package/dist/types/tools/ask.d.ts +3 -0
  175. package/dist/types/tools/ast-edit.d.ts +10 -1
  176. package/dist/types/tools/ast-grep.d.ts +10 -1
  177. package/dist/types/tools/autoresearch.d.ts +21 -4
  178. package/dist/types/tools/bash.d.ts +30 -1
  179. package/dist/types/tools/cfg-render.d.ts +5 -1
  180. package/dist/types/tools/debug.d.ts +3 -1
  181. package/dist/types/tools/default-renderer.d.ts +6 -1
  182. package/dist/types/tools/edit.d.ts +14 -1
  183. package/dist/types/tools/eval.d.ts +12 -1
  184. package/dist/types/tools/fetch.d.ts +16 -1
  185. package/dist/types/tools/find.d.ts +15 -1
  186. package/dist/types/tools/github.d.ts +3 -0
  187. package/dist/types/tools/glob.d.ts +14 -1
  188. package/dist/types/tools/goal.d.ts +3 -1
  189. package/dist/types/tools/grep.d.ts +14 -1
  190. package/dist/types/tools/grouped-file-output.d.ts +58 -0
  191. package/dist/types/tools/json-tree.d.ts +20 -0
  192. package/dist/types/tools/lsp.d.ts +3 -10
  193. package/dist/types/tools/mcp.d.ts +16 -1
  194. package/dist/types/tools/memory.d.ts +26 -0
  195. package/dist/types/tools/native-view.d.ts +90 -0
  196. package/dist/types/tools/proc-render.d.ts +7 -1
  197. package/dist/types/tools/read.d.ts +23 -1
  198. package/dist/types/tools/renderer.d.ts +57 -0
  199. package/dist/types/tools/report-tool-issue.d.ts +3 -0
  200. package/dist/types/tools/resolve.d.ts +14 -1
  201. package/dist/types/tools/task.d.ts +3 -0
  202. package/dist/types/tools/think.d.ts +3 -0
  203. package/dist/types/tools/todo.d.ts +12 -0
  204. package/dist/types/tools/vibe.d.ts +3 -1
  205. package/dist/types/tools/wait.d.ts +3 -0
  206. package/dist/types/tools/web-search.d.ts +8 -0
  207. package/dist/types/tools/write.d.ts +14 -1
  208. package/dist/types/tools/xdev.d.ts +13 -0
  209. package/dist/types/tui.d.ts +49 -0
  210. package/package.json +9 -9
  211. package/src/apps/autoresearch-dashboard.ts +362 -4
  212. package/src/apps/cleanse-board.ts +219 -1
  213. package/src/apps/cleanse-picker.ts +9 -1
  214. package/src/apps/debug/log-viewer.ts +15 -15
  215. package/src/apps/debug/protocol-probe.ts +2 -20
  216. package/src/apps/git/avatar.ts +2 -22
  217. package/src/apps/git/git-tui.ts +406 -59
  218. package/src/apps/git/help.ts +130 -0
  219. package/src/apps/git/sidebar.ts +491 -0
  220. package/src/apps/live-visualizer.ts +65 -0
  221. package/src/apps/ps-top.ts +448 -17
  222. package/src/apps/session-picker.ts +1 -0
  223. package/src/apps/setup-model-picker.ts +5 -1
  224. package/src/apps/standalone-picker.ts +55 -1
  225. package/src/autocomplete.ts +44 -1
  226. package/src/chat/advisor-message.ts +72 -3
  227. package/src/chat/assistant-message.ts +346 -11
  228. package/src/chat/background-tan-message.ts +4 -4
  229. package/src/chat/bash-execution.ts +81 -0
  230. package/src/chat/cache-invalidation-marker.ts +8 -0
  231. package/src/chat/chat-transcript-builder.ts +37 -6
  232. package/src/chat/collab-prompt-message.ts +15 -3
  233. package/src/chat/compaction-summary-message.ts +74 -1
  234. package/src/chat/custom-message.ts +3 -1
  235. package/src/chat/eval-execution.ts +57 -0
  236. package/src/chat/execution-shared.ts +153 -1
  237. package/src/chat/hook-message.ts +1 -0
  238. package/src/chat/late-diagnostics-message.ts +85 -2
  239. package/src/chat/read-tool-group.ts +341 -1
  240. package/src/chat/served-model-marker.ts +8 -0
  241. package/src/chat/skill-message.ts +63 -0
  242. package/src/chat/stripped-tool-calls-placeholder.ts +18 -10
  243. package/src/chat/todo-reminder.ts +34 -4
  244. package/src/chat/tool-execution.ts +385 -10
  245. package/src/chat/transcript-actions.ts +38 -0
  246. package/src/chat/transcript-browser.ts +2 -9
  247. package/src/chat/transcript-entry.ts +10 -1
  248. package/src/chat/transcript-render-helpers.ts +16 -15
  249. package/src/chat/ttsr-notification.ts +38 -1
  250. package/src/chat/user-message.ts +167 -4
  251. package/src/chrome/collab-qrcode.ts +27 -2
  252. package/src/chrome/context-thresholds.ts +34 -0
  253. package/src/chrome/countdown-timer.ts +24 -1
  254. package/src/chrome/diff.ts +60 -1
  255. package/src/chrome/dynamic-border.ts +7 -0
  256. package/src/chrome/format.ts +12 -0
  257. package/src/chrome/message-divider.ts +33 -1
  258. package/src/chrome/message-frame.ts +53 -10
  259. package/src/chrome/message-notice.ts +71 -0
  260. package/src/chrome/overlay-box.ts +45 -2
  261. package/src/chrome/qrcode.ts +28 -0
  262. package/src/chrome/segment-track.ts +26 -0
  263. package/src/chrome/selector-helpers.ts +1 -17
  264. package/src/chrome/status-notice.ts +46 -0
  265. package/src/chrome/streaming-panel.ts +25 -1
  266. package/src/chrome/tool-activity.ts +20 -0
  267. package/src/chrome/transcript-container.ts +37 -0
  268. package/src/chrome/transcript-status.ts +40 -11
  269. package/src/components/box.ts +51 -0
  270. package/src/components/disclosure.ts +33 -0
  271. package/src/components/editor.ts +216 -27
  272. package/src/components/form.ts +93 -9
  273. package/src/components/image.ts +30 -0
  274. package/src/components/input.ts +77 -26
  275. package/src/components/key-value-list.ts +18 -0
  276. package/src/components/layout/geometry.ts +44 -0
  277. package/src/components/layout/row.ts +30 -0
  278. package/src/components/layout/split-pane.ts +65 -0
  279. package/src/components/layout/stack.ts +27 -0
  280. package/src/components/loader.ts +183 -1
  281. package/src/components/markdown.ts +21 -0
  282. package/src/components/metric.ts +39 -0
  283. package/src/components/progress-bar.ts +28 -0
  284. package/src/components/scroll-view.ts +23 -0
  285. package/src/components/section.ts +16 -0
  286. package/src/components/select-list.ts +174 -25
  287. package/src/components/settings-list.ts +264 -7
  288. package/src/components/spacer.ts +17 -0
  289. package/src/components/tab-bar.ts +42 -0
  290. package/src/components/table.ts +34 -0
  291. package/src/components/text.ts +23 -0
  292. package/src/components/tree-view.ts +65 -0
  293. package/src/components/truncated-text.ts +14 -0
  294. package/src/components/wizard-step.ts +18 -9
  295. package/src/debug-server.ts +14 -7
  296. package/src/hotkeys-markdown.ts +251 -69
  297. package/src/index.ts +6 -0
  298. package/src/latex-block.ts +11 -0
  299. package/src/native/apply.ts +275 -0
  300. package/src/native/backend.ts +682 -0
  301. package/src/native/blobs.ts +70 -0
  302. package/src/native/describe.ts +124 -0
  303. package/src/native/encode.ts +233 -0
  304. package/src/native/icons.ts +184 -0
  305. package/src/native/memo.ts +64 -0
  306. package/src/native/node.ts +112 -0
  307. package/src/native/overlay.ts +131 -0
  308. package/src/native/picker.ts +333 -0
  309. package/src/native/reconcile.ts +1063 -0
  310. package/src/native/settle.ts +23 -0
  311. package/src/native/spans.ts +308 -0
  312. package/src/native/state.ts +28 -0
  313. package/src/native/tone.ts +79 -0
  314. package/src/overlays/advisor-config.ts +420 -0
  315. package/src/overlays/agent-hub-renderer.ts +155 -18
  316. package/src/overlays/agent-hub.ts +1037 -44
  317. package/src/overlays/agent-transcript-viewer.ts +129 -0
  318. package/src/overlays/agents-hub.ts +688 -53
  319. package/src/overlays/annotation-overlay.ts +391 -52
  320. package/src/overlays/ask-dialog.ts +435 -24
  321. package/src/overlays/bordered-loader.ts +17 -0
  322. package/src/overlays/btw-history-panel.ts +182 -0
  323. package/src/overlays/btw-panel.ts +68 -2
  324. package/src/overlays/cleanse-panel.ts +105 -15
  325. package/src/overlays/codex-reset-fireworks.ts +65 -5
  326. package/src/overlays/composer-shape-preview.ts +26 -1
  327. package/src/overlays/copy-selector.ts +545 -23
  328. package/src/overlays/error-banner.ts +44 -0
  329. package/src/overlays/extensions/extension-list.ts +23 -17
  330. package/src/overlays/history-search.ts +175 -33
  331. package/src/overlays/hook-editor.ts +113 -6
  332. package/src/overlays/hook-input.ts +22 -1
  333. package/src/overlays/hook-selector.ts +311 -22
  334. package/src/overlays/hub-frame.ts +80 -0
  335. package/src/overlays/jobs-panel.ts +112 -0
  336. package/src/overlays/login-dialog.ts +183 -1
  337. package/src/overlays/logout-account-selector.ts +102 -4
  338. package/src/overlays/mcp-add-wizard.ts +232 -53
  339. package/src/overlays/model-browser.ts +681 -22
  340. package/src/overlays/model-hub.ts +1402 -78
  341. package/src/overlays/model-picker.ts +175 -1
  342. package/src/overlays/move-overlay.ts +45 -0
  343. package/src/overlays/oauth-selector.ts +227 -23
  344. package/src/overlays/omfg-panel.ts +86 -2
  345. package/src/overlays/pause-screen.ts +55 -4
  346. package/src/overlays/plan-review-overlay.ts +352 -0
  347. package/src/overlays/plan-save-overlay.ts +45 -0
  348. package/src/overlays/plugin-selector.ts +21 -1
  349. package/src/overlays/plugin-settings.ts +195 -5
  350. package/src/overlays/queue-mode-selector.ts +19 -1
  351. package/src/overlays/reset-usage-selector.ts +110 -40
  352. package/src/overlays/rewind-selector.ts +458 -44
  353. package/src/overlays/session-account-selector.ts +1 -1
  354. package/src/overlays/session-info-overlay.ts +137 -1
  355. package/src/overlays/session-selector.ts +807 -46
  356. package/src/overlays/settings-defs.ts +41 -0
  357. package/src/overlays/settings-selector.ts +583 -23
  358. package/src/overlays/show-images-selector.ts +18 -1
  359. package/src/overlays/snapcompact-shape-preview.ts +48 -3
  360. package/src/overlays/stats-notice.ts +31 -0
  361. package/src/overlays/theme-selector.ts +31 -1
  362. package/src/overlays/thinking-selector.ts +22 -1
  363. package/src/overlays/tree-selector.ts +570 -110
  364. package/src/overlays/usage-dashboard.ts +587 -12
  365. package/src/overlays/usage-row.ts +161 -25
  366. package/src/prompt/attachment-chips.ts +60 -0
  367. package/src/prompt/composer-attachments.ts +31 -9
  368. package/src/prompt/composer.ts +55 -2
  369. package/src/prompt/custom-editor.ts +302 -4
  370. package/src/prompt/editor-top-gap.ts +8 -0
  371. package/src/prompt/macos-spelling.ts +24 -9
  372. package/src/prompt/magic-keywords.ts +22 -1
  373. package/src/prompt/model-mention-autocomplete.ts +1 -0
  374. package/src/prompt/queued-messages.ts +101 -0
  375. package/src/prompt/skill-tokens.ts +5 -3
  376. package/src/prompt/welcome.ts +213 -6
  377. package/src/render/code-cell.ts +103 -2
  378. package/src/render/file-list.ts +29 -0
  379. package/src/render/hyperlink.ts +32 -0
  380. package/src/render/output-block.ts +110 -0
  381. package/src/render/output-pane.ts +37 -0
  382. package/src/render/tool-card.ts +137 -0
  383. package/src/render/tree-list.ts +39 -0
  384. package/src/render/width-aware-text.ts +20 -0
  385. package/src/setup/scenes/composer.ts +29 -0
  386. package/src/setup/scenes/glyph.ts +15 -0
  387. package/src/setup/scenes/model.ts +36 -8
  388. package/src/setup/scenes/outro.ts +28 -1
  389. package/src/setup/scenes/sign-in.ts +122 -13
  390. package/src/setup/scenes/splash.ts +28 -1
  391. package/src/setup/scenes/theme.ts +88 -3
  392. package/src/setup/scenes/types.ts +7 -1
  393. package/src/setup/startup-splash.ts +46 -9
  394. package/src/setup/wizard-overlay.ts +140 -23
  395. package/src/status-line/component.ts +398 -16
  396. package/src/status-line/context-usage.ts +279 -50
  397. package/src/status-line/footer.ts +94 -1
  398. package/src/status-line/metrics.ts +3 -6
  399. package/src/status-line/segments.ts +463 -97
  400. package/src/status-line/separators.ts +3 -16
  401. package/src/status-line/types.ts +43 -1
  402. package/src/terminal-capabilities.ts +7 -0
  403. package/src/terminal.ts +130 -2
  404. package/src/theme/defaults/dark-neon-noir.json +100 -0
  405. package/src/theme/defaults/index.ts +2 -0
  406. package/src/theme/defaults/light-prism.json +5 -5
  407. package/src/theme/defaults/onyx.json +62 -62
  408. package/src/theme/schema.ts +15 -0
  409. package/src/theme/shimmer.ts +33 -0
  410. package/src/theme/theme-class.ts +24 -19
  411. package/src/theme/theme.ts +111 -9
  412. package/src/tools/ask.ts +157 -1
  413. package/src/tools/ast-edit.ts +174 -1
  414. package/src/tools/ast-grep.ts +82 -2
  415. package/src/tools/autoresearch.ts +149 -1
  416. package/src/tools/bash.ts +180 -49
  417. package/src/tools/cfg-render.ts +66 -1
  418. package/src/tools/debug.ts +78 -1
  419. package/src/tools/default-renderer.ts +35 -1
  420. package/src/tools/edit.ts +247 -2
  421. package/src/tools/eval.ts +257 -1
  422. package/src/tools/fetch.ts +102 -3
  423. package/src/tools/find.ts +127 -1
  424. package/src/tools/github.ts +119 -10
  425. package/src/tools/glob.ts +116 -1
  426. package/src/tools/goal.ts +56 -1
  427. package/src/tools/grep.ts +83 -2
  428. package/src/tools/grouped-file-output.ts +205 -0
  429. package/src/tools/json-tree.ts +116 -1
  430. package/src/tools/lsp.ts +318 -1
  431. package/src/tools/mcp.ts +80 -1
  432. package/src/tools/memory.ts +93 -11
  433. package/src/tools/native-view.ts +292 -0
  434. package/src/tools/proc-render.ts +221 -1
  435. package/src/tools/read.ts +199 -4
  436. package/src/tools/renderer.ts +61 -0
  437. package/src/tools/report-tool-issue.ts +7 -1
  438. package/src/tools/resolve.ts +63 -1
  439. package/src/tools/task.ts +406 -4
  440. package/src/tools/think.ts +19 -1
  441. package/src/tools/todo.ts +89 -0
  442. package/src/tools/vibe.ts +230 -2
  443. package/src/tools/wait.ts +181 -1
  444. package/src/tools/web-search.ts +113 -1
  445. package/src/tools/write.ts +144 -5
  446. package/src/tools/xdev.ts +64 -1
  447. package/src/tui.ts +294 -3
@@ -1,27 +1,56 @@
1
+ import type { TspSpan } from "@oh-my-pi/pi-wire";
1
2
  import { Text } from "../components/text";
3
+ import { col, span, text } from "../native/describe";
4
+ import type { NativeNode } from "../native/node";
5
+ import { type ThemeColor, theme } from "../theme";
2
6
  import { TranscriptBlock } from "./transcript-container";
3
7
 
4
- /** One compact transcript status row assembled from already-styled parts. */
8
+ /** One themed run of a status row. */
9
+ export interface TranscriptStatusPart {
10
+ readonly text: string;
11
+ readonly color: ThemeColor;
12
+ /** Glyph art (tree connectors) drawn only in rows; native terminals draw their own structure. */
13
+ readonly rowsOnly?: boolean;
14
+ }
15
+
16
+ /** One compact transcript status row assembled from themed parts, joined by single spaces. */
5
17
  export interface TranscriptStatusRow {
6
- readonly parts: readonly (string | undefined)[];
18
+ readonly parts: readonly (TranscriptStatusPart | undefined)[];
7
19
  readonly indent?: number;
8
20
  }
9
21
 
10
22
  /** Shared compact status-pill block used by notices and background activity. */
11
23
  export class TranscriptStatusBlock extends TranscriptBlock {
24
+ readonly #rows: TspSpan[][] = [];
25
+ #native: NativeNode | undefined;
26
+
12
27
  constructor(rows: readonly TranscriptStatusRow[]) {
13
28
  super();
14
- for (const row of rows) {
15
- const parts: string[] = [];
16
- for (const part of row.parts) {
17
- if (part) parts.push(part);
18
- }
19
- this.addChild(new Text(parts.join(" "), row.indent ?? 1, 0));
20
- }
29
+ for (const row of rows) this.addLine(row.parts, row.indent);
21
30
  }
22
31
 
23
32
  /** Append a supplemental line such as an artifact warning. */
24
- addLine(text: string, indent = 1): void {
25
- this.addChild(new Text(text, indent, 0));
33
+ addLine(parts: readonly (TranscriptStatusPart | undefined)[], indent = 1): void {
34
+ const styled: string[] = [];
35
+ const spans: TspSpan[] = [];
36
+ for (const part of parts) {
37
+ if (!part) continue;
38
+ styled.push(theme.fg(part.color, part.text));
39
+ if (part.rowsOnly) continue;
40
+ if (spans.length > 0) spans.push(span(" "));
41
+ spans.push(span(part.text, part.color));
42
+ }
43
+ this.addChild(new Text(styled.join(" "), indent, 0));
44
+ this.#rows.push(spans);
45
+ this.#native = undefined;
46
+ }
47
+
48
+ /** One wrapped text line per status row. */
49
+ override describe(): NativeNode {
50
+ this.#native ??= col(
51
+ this.#rows.map(spans => text(spans, { wrap: "word" })),
52
+ { role: "omp.status-block" },
53
+ );
54
+ return this.#native;
26
55
  }
27
56
  }
@@ -1,3 +1,7 @@
1
+ import { backgroundChrome, colorTone, sampleBackground, sampleForeground } from "../native/tone";
2
+ import { sameItems } from "../native/memo";
3
+ import { card, col } from "../native/describe";
4
+ import type { DescribeContext, NativeNode } from "../native/node";
1
5
  import type { Component } from "../tui";
2
6
  import {
3
7
  getPaddingX,
@@ -52,6 +56,13 @@ export class Box implements Component {
52
56
 
53
57
  // Cache for rendered output
54
58
  #cached?: Cache;
59
+ #native?: {
60
+ children: readonly Component[];
61
+ bg: string | undefined;
62
+ border: BoxBorder | undefined;
63
+ borderColor: string | undefined;
64
+ node: NativeNode;
65
+ };
55
66
 
56
67
  constructor(paddingX = 1, paddingY = 1, bgFn?: (text: string) => string, border?: BoxBorder) {
57
68
  this.#paddingX = paddingX;
@@ -124,6 +135,46 @@ export class Box implements Component {
124
135
  }
125
136
  }
126
137
 
138
+ /**
139
+ * A `card` when the box has a border or background: the background token
140
+ * picks tone/role (user message, tool state, selection), a border colour
141
+ * picks the ring tone. A plain `col` otherwise. Padding is the terminal's.
142
+ */
143
+ describe(_cx: DescribeContext): NativeNode {
144
+ const bg = sampleBackground(this.#bgFn);
145
+ const border = this.#border;
146
+ const borderColor = border ? sampleForeground(border.color) : undefined;
147
+ const cached = this.#native;
148
+ if (
149
+ cached !== undefined &&
150
+ cached.bg === bg &&
151
+ cached.border === border &&
152
+ cached.borderColor === borderColor &&
153
+ sameItems(cached.children, this.children)
154
+ ) {
155
+ return cached.node;
156
+ }
157
+ const children = [...this.children];
158
+ let described: NativeNode;
159
+ if (!border && !this.#bgFn) {
160
+ described = col(children);
161
+ } else {
162
+ const chrome = backgroundChrome(bg);
163
+ described = card(
164
+ {
165
+ role: chrome.role ?? "omp.panel",
166
+ tone: borderColor !== undefined ? (colorTone(borderColor) ?? "neutral") : (chrome.tone ?? "neutral"),
167
+ selected: chrome.selected,
168
+ // Fill without a ring: a flat inset panel.
169
+ inset: border ? undefined : true,
170
+ },
171
+ children,
172
+ );
173
+ }
174
+ this.#native = { children, bg, border, borderColor, node: described };
175
+ return described;
176
+ }
177
+
127
178
  render(width: number): readonly string[] {
128
179
  const children = this.children;
129
180
  const count = children.length;
@@ -1,3 +1,5 @@
1
+ import { node } from "../native/describe";
2
+ import type { DescribeContext, NativeChild, NativeNode, NativeUiEvent } from "../native/node";
1
3
  import type { Component } from "../tui";
2
4
 
3
5
  /** A component slot; factory slots are constructed only when their branch is first rendered. */
@@ -48,6 +50,7 @@ export class Disclosure implements Component {
48
50
  #ignoreTight: boolean | undefined;
49
51
  #disposed = false;
50
52
  #cache: RenderCache | undefined;
53
+ #native: { expanded: boolean; node: NativeNode } | undefined;
51
54
  #boundedCache:
52
55
  | {
53
56
  source: readonly string[];
@@ -74,6 +77,7 @@ export class Disclosure implements Component {
74
77
  if (this.#disposed || this.#expanded === expanded) return;
75
78
  this.#expanded = expanded;
76
79
  this.#cache = undefined;
80
+ this.#native = undefined;
77
81
  this.#boundedCache = undefined;
78
82
  }
79
83
 
@@ -131,6 +135,34 @@ export class Disclosure implements Component {
131
135
  return children;
132
136
  }
133
137
 
138
+ /**
139
+ * A collapsible `section`. The summary (and, while collapsed, the preview)
140
+ * form the always-visible header child; the lazily built body is the
141
+ * section body and is only materialized once expanded.
142
+ */
143
+ describe(_cx: DescribeContext): NativeNode {
144
+ if (this.#disposed) return DISPOSED_NODE;
145
+ const expanded = this.#expanded;
146
+ if (this.#native?.expanded === expanded) return this.#native.node;
147
+ const head: NativeChild[] = [];
148
+ const summary = this.#getSummary();
149
+ if (summary) head.push(summary);
150
+ if (!expanded) {
151
+ const preview = this.#getCollapsedBody();
152
+ if (preview) head.push(preview);
153
+ }
154
+ const children: NativeChild[] = [node("col", undefined, head, "head")];
155
+ if (expanded) children.push(this.#getBody());
156
+ const described = node("section", { collapsible: true, collapsed: !expanded }, children);
157
+ this.#native = { expanded, node: described };
158
+ return described;
159
+ }
160
+
161
+ /** Mirror the terminal-local toggle into the controlled state. */
162
+ handleNativeEvent(event: NativeUiEvent): void {
163
+ if (event.type === "toggle" && event.key === "") this.setExpanded(!event.collapsed);
164
+ }
165
+
134
166
  render(width: number): readonly string[] {
135
167
  if (this.#disposed) return EMPTY_ROWS;
136
168
  width = Math.max(1, Math.floor(Number.isFinite(width) ? width : 1));
@@ -232,4 +264,5 @@ function rowsMatchSnapshot(rows: readonly string[], snapshot: readonly string[])
232
264
  }
233
265
 
234
266
  const EMPTY_ROWS: readonly string[] = [];
267
+ const DISPOSED_NODE: NativeNode = node("col", { hidden: true });
235
268
  const EMPTY_COMPONENTS: readonly Component[] = [];
@@ -14,6 +14,11 @@ import { BracketedPasteHandler, decodeReencodedPasteControls } from "../brackete
14
14
  import { canonicalKeyId, getKeybindings, type KeybindingsManager } from "../keybindings";
15
15
  import { extractPrintableText, matchesKey, parseKey } from "../keys";
16
16
  import { KillRing } from "../kill-ring";
17
+ import type { TspEditorDecoration, TspEditorProps, TspTone } from "@oh-my-pi/pi-wire";
18
+ import { col, node } from "../native/describe";
19
+ import { sameItems, sameProps } from "../native/memo";
20
+ import { plainText } from "../native/spans";
21
+ import type { DescribeContext, NativeChild, NativeNode } from "../native/node";
17
22
  import type { SymbolTheme } from "../symbols";
18
23
  import { type Component, CURSOR_MARKER, type Focusable } from "../tui";
19
24
  import {
@@ -52,7 +57,36 @@ export type { EditorBorderStyle, EditorTopBorder };
52
57
 
53
58
  import { type SelectItem, SelectList, type SelectListLayoutOptions, type SelectListTheme } from "./select-list";
54
59
 
60
+ /** The TSP root an {@link Editor.describeLayout} hook builds around the `editor` node. */
61
+ export interface NativeEditorLayout {
62
+ readonly role: string;
63
+ /** Tone of the root (`pending` while a turn runs). */
64
+ readonly tone?: TspTone;
65
+ readonly children: readonly NativeChild[];
66
+ /** Keypath of the `editor` node inside the root (the autocomplete's caret anchor). */
67
+ readonly caret: string;
68
+ }
69
+
70
+ /** Vim mode as the TSP `editor.mode` label. */
71
+ const VIM_MODE_LABELS: Record<VimMode, string> = {
72
+ insert: "INSERT",
73
+ normal: "NORMAL",
74
+ visual: "VISUAL",
75
+ "visual-line": "VISUAL",
76
+ };
77
+
55
78
  const PASSTHROUGH_COLOR = (text: string): string => text;
79
+
80
+ /** Value equality of two decoration lists, so an unchanged set keeps its identity across text edits elsewhere. */
81
+ function sameDecorations(a: readonly TspEditorDecoration[], b: readonly TspEditorDecoration[]): boolean {
82
+ if (a.length !== b.length) return false;
83
+ for (let i = 0; i < a.length; i++) {
84
+ const x = a[i]!;
85
+ const y = b[i]!;
86
+ if (x.from !== y.from || x.to !== y.to || x.s !== y.s || x.fx !== y.fx) return false;
87
+ }
88
+ return true;
89
+ }
56
90
  const MENTION_CONTEXT_RE = /(?:^|\s)\^[^\s]*$/;
57
91
  const AT_TOKEN_RE = /(?:^|\s)(@[^\s]*)$/;
58
92
 
@@ -568,7 +602,30 @@ export class Editor implements Component, Focusable {
568
602
  * Width-changing output is allowed on lines without the cursor; it is truncated
569
603
  * to the content width rather than reflowed. Cursor glyphs and inline hints are excluded. */
570
604
  decorateText: ((text: string, context: EditorTextDecorationContext) => string) | undefined;
605
+ /**
606
+ * TSP counterpart of {@link decorateText}: styled ranges over the buffer
607
+ * (UTF-16 offsets into the lines joined by `\n`). Called only when the text
608
+ * changed or the editor was invalidated since the last description.
609
+ */
610
+ describeDecorations: ((lines: readonly string[]) => readonly TspEditorDecoration[]) | undefined;
611
+ /** TSP code language of the buffer (`python`, `bash`): the terminal highlights it in the mono face. */
612
+ describeLanguage: (() => string | undefined) | undefined;
613
+ /**
614
+ * TSP chrome around the `editor` node (the prompt composer's chips, mode
615
+ * chip, send/stop): the root role, the children with `input` placed where
616
+ * the layout wants it, and the input's keypath for the caret-anchored
617
+ * autocomplete. Unset: a plain `omp.editor` column over the input.
618
+ */
619
+ describeLayout: ((input: NativeNode, cx: DescribeContext) => NativeEditorLayout) | undefined;
620
+ /** TSP placeholder for the empty buffer; natively it replaces the rotating ANSI {@link placeholder} hints. */
621
+ nativePlaceholder: string | undefined;
571
622
  #promptGutter: string | undefined;
623
+ /** Bumped by {@link invalidate}: host-side decoration inputs (spelling results, settings) changed. */
624
+ #nativeGeneration = 0;
625
+ #nativeDecor?: { text: string; generation: number; decor: readonly TspEditorDecoration[] | undefined };
626
+ #nativeEditor?: { props: TspEditorProps; node: NativeNode };
627
+ #nativeOverlay?: { list: SelectList; caret: string; node: NativeNode };
628
+ #nativeRoot?: { role: string; tone: TspTone | undefined; children: readonly NativeChild[]; node: NativeNode };
572
629
 
573
630
  // Store last layout width for cursor navigation
574
631
  #lastLayoutWidth: number = 80;
@@ -1032,7 +1089,7 @@ export class Editor implements Component, Focusable {
1032
1089
  }
1033
1090
 
1034
1091
  invalidate(): void {
1035
- // No cached state to invalidate currently
1092
+ this.#nativeGeneration++;
1036
1093
  }
1037
1094
 
1038
1095
  /** Active chrome style; a hidden border collapses every shape to borderless. */
@@ -1553,6 +1610,125 @@ export class Editor implements Component, Focusable {
1553
1610
  return result;
1554
1611
  }
1555
1612
 
1613
+ /**
1614
+ * An `editor` node (key `input`) carrying the buffer, caret, Vim selection
1615
+ * anchor and mode, decorations, ghost completion, placeholder, prompt and
1616
+ * height cap; the frame, wrapping, scrolling and caret are the terminal's,
1617
+ * so composer shapes play no part. An open autocomplete popup follows as an
1618
+ * `overlay` anchored to the caret around the completion list. Typing and
1619
+ * caret moves change only `text` and `cursor` on the same node.
1620
+ */
1621
+ describe(cx: DescribeContext): NativeNode {
1622
+ // Vertical caret motion walks visual rows; the terminal owns the real
1623
+ // wrap, so the surface width is the closest available layout width.
1624
+ this.#lastLayoutWidth = Math.max(1, cx.cols);
1625
+ const { lines, cursorLine, cursorCol } = this.#state;
1626
+ const text = lines.join("\n");
1627
+ let offset = 0;
1628
+ for (let i = 0; i < cursorLine; i++) offset += (lines[i]?.length ?? 0) + 1;
1629
+ const cursor = offset + cursorCol;
1630
+
1631
+ let decor = this.#nativeDecor;
1632
+ if (decor?.text !== text || decor.generation !== this.#nativeGeneration) {
1633
+ const next = this.describeDecorations?.(lines);
1634
+ decor = {
1635
+ text,
1636
+ generation: this.#nativeGeneration,
1637
+ decor:
1638
+ next && next.length > 0
1639
+ ? decor?.decor && sameDecorations(decor.decor, next)
1640
+ ? decor.decor
1641
+ : next
1642
+ : undefined,
1643
+ };
1644
+ this.#nativeDecor = decor;
1645
+ }
1646
+
1647
+ const placeholder = this.#getPlaceholder();
1648
+ const nativePlaceholder =
1649
+ this.nativePlaceholder !== undefined && !this.#autocompleteState && this.#isEditorEmpty()
1650
+ ? this.nativePlaceholder
1651
+ : placeholder && plainText(placeholder).trim();
1652
+ const atLineEnd = cursorCol >= (lines[cursorLine]?.length ?? 0);
1653
+ const ghost = nativePlaceholder || !atLineEnd ? null : this.#getInlineHint();
1654
+ const vim = this.#vim;
1655
+ let anchor: number | null = null;
1656
+ if (vim?.visual && vim.anchor !== null) {
1657
+ let anchorOffset = 0;
1658
+ for (let i = 0; i < vim.anchor.line; i++) anchorOffset += (lines[i]?.length ?? 0) + 1;
1659
+ if (vim.mode === "visual-line") {
1660
+ // Linewise: stretch the anchor to the far edge of its line.
1661
+ const before =
1662
+ vim.anchor.line < cursorLine || (vim.anchor.line === cursorLine && vim.anchor.col <= cursorCol);
1663
+ anchor = before ? anchorOffset : anchorOffset + (lines[vim.anchor.line]?.length ?? 0);
1664
+ } else {
1665
+ anchor = anchorOffset + vim.anchor.col;
1666
+ }
1667
+ }
1668
+ const prompt = this.#promptGutter === undefined ? "" : plainText(this.#promptGutter);
1669
+ const props: TspEditorProps = {
1670
+ text,
1671
+ cursor,
1672
+ anchor: anchor ?? undefined,
1673
+ decor: decor.decor,
1674
+ ghost: ghost ? plainText(ghost) : undefined,
1675
+ placeholder: nativePlaceholder || undefined,
1676
+ prompt: prompt || undefined,
1677
+ mode: vim ? VIM_MODE_LABELS[vim.mode] : undefined,
1678
+ lang: this.describeLanguage?.(),
1679
+ maxLines: this.#maxHeight,
1680
+ };
1681
+ let editor = this.#nativeEditor;
1682
+ if (!editor || !sameProps(editor.props, props)) {
1683
+ editor = { props, node: node("editor", props, undefined, "input") };
1684
+ this.#nativeEditor = editor;
1685
+ }
1686
+
1687
+ const layout = this.describeLayout?.(editor.node, cx) ?? {
1688
+ role: "omp.editor",
1689
+ children: [editor.node],
1690
+ caret: "input",
1691
+ };
1692
+ const children: NativeChild[] = [...layout.children];
1693
+ const list = this.#visibleAutocompleteList();
1694
+ if (list) {
1695
+ list.setNativeMark(this.#autocompleteMark());
1696
+ const overlay = this.#nativeOverlay;
1697
+ if (overlay?.list !== list || overlay.caret !== layout.caret) {
1698
+ this.#nativeOverlay = {
1699
+ list,
1700
+ caret: layout.caret,
1701
+ node: node("overlay", { anchor: { caret: layout.caret }, role: "omp.autocomplete" }, [list], "complete"),
1702
+ };
1703
+ }
1704
+ children.push(this.#nativeOverlay!.node);
1705
+ } else {
1706
+ this.#nativeOverlay = undefined;
1707
+ }
1708
+ const root = this.#nativeRoot;
1709
+ if (root && root.role === layout.role && root.tone === layout.tone && sameItems(root.children, children)) {
1710
+ return root.node;
1711
+ }
1712
+ const described = col(children, layout.tone ? { role: layout.role, tone: layout.tone } : { role: layout.role });
1713
+ this.#nativeRoot = { role: layout.role, tone: layout.tone, children, node: described };
1714
+ return described;
1715
+ }
1716
+
1717
+ /**
1718
+ * The typed text the open popup matches item labels against, for the TSP
1719
+ * `mark`: the completion prefix (the live `@` token while a file list
1720
+ * narrows in place) without its sigil, from its last path segment on.
1721
+ */
1722
+ #autocompleteMark(): string {
1723
+ let typed = this.#autocompletePrefix;
1724
+ if (typed.startsWith("@")) {
1725
+ const line = this.#state.lines[this.#state.cursorLine] ?? "";
1726
+ typed = AT_TOKEN_RE.exec(line.slice(0, this.#state.cursorCol))?.[1] ?? typed;
1727
+ }
1728
+ typed = typed.replace(/^[/@:#$^]"?/, "");
1729
+ return typed.slice(typed.lastIndexOf("/") + 1);
1730
+ }
1731
+
1556
1732
  handleInput(data: string): void {
1557
1733
  // Iterative, not recursive: the bytes trailing a completed bracketed
1558
1734
  // paste (which may themselves contain further pastes) loop back here,
@@ -1723,31 +1899,8 @@ export class Editor implements Component, Focusable {
1723
1899
  // arrow at end of line moves the cursor.
1724
1900
  this.#cancelAutocomplete();
1725
1901
  this.onAutocompleteUpdate?.();
1726
- } else if (this.#autocompleteProvider) {
1727
- const shouldChainAutocomplete =
1728
- this.#isSlashCommandNameAutocompleteSelection() || isDirectoryCompletionValue(selected.value);
1729
- const result = this.#autocompleteProvider.applyCompletion(
1730
- this.#state.lines,
1731
- this.#state.cursorLine,
1732
- this.#state.cursorCol,
1733
- selected,
1734
- this.#autocompletePrefix,
1735
- );
1736
-
1737
- this.#state.lines = result.lines;
1738
- this.#state.cursorLine = result.cursorLine;
1739
- this.#setCursorCol(result.cursorCol);
1740
-
1741
- this.#cancelAutocomplete();
1742
- this.onAutocompleteUpdate?.();
1743
-
1744
- this.#notifyChange();
1745
-
1746
- result.onApplied?.();
1747
-
1748
- if (shouldChainAutocomplete) {
1749
- queueMicrotask(() => void this.#tryTriggerAutocomplete());
1750
- }
1902
+ } else {
1903
+ this.#acceptAutocompleteSelection(selected);
1751
1904
  }
1752
1905
  // Only an accepted candidate consumes the key; an empty list falls through.
1753
1906
  if (selected) return;
@@ -4111,6 +4264,35 @@ export class Editor implements Component, Focusable {
4111
4264
  }
4112
4265
  await this.#queueAutocompleteRequest({ kind: "regular", explicitTab });
4113
4266
  }
4267
+ /** Apply `selected` the way Tab does: complete it in place and chain into directories/commands. */
4268
+ #acceptAutocompleteSelection(selected: SelectItem): void {
4269
+ if (!this.#autocompleteProvider) return;
4270
+ const shouldChainAutocomplete =
4271
+ this.#isSlashCommandNameAutocompleteSelection() || isDirectoryCompletionValue(selected.value);
4272
+ const result = this.#autocompleteProvider.applyCompletion(
4273
+ this.#state.lines,
4274
+ this.#state.cursorLine,
4275
+ this.#state.cursorCol,
4276
+ selected,
4277
+ this.#autocompletePrefix,
4278
+ );
4279
+
4280
+ this.#state.lines = result.lines;
4281
+ this.#state.cursorLine = result.cursorLine;
4282
+ this.#setCursorCol(result.cursorCol);
4283
+
4284
+ this.#cancelAutocomplete();
4285
+ this.onAutocompleteUpdate?.();
4286
+
4287
+ this.#notifyChange();
4288
+
4289
+ result.onApplied?.();
4290
+
4291
+ if (shouldChainAutocomplete) {
4292
+ queueMicrotask(() => void this.#tryTriggerAutocomplete());
4293
+ }
4294
+ }
4295
+
4114
4296
  #createAutocompleteList(
4115
4297
  prefix: string,
4116
4298
  items: Array<{ value: string; label: string; description?: string }>,
@@ -4120,7 +4302,14 @@ export class Editor implements Component, Focusable {
4120
4302
  : prefix.startsWith("@")
4121
4303
  ? AT_FILE_SELECT_LIST_LAYOUT
4122
4304
  : AUTOCOMPLETE_SELECT_LIST_LAYOUT;
4123
- return new SelectList(items, this.#autocompleteMaxVisible, this.#theme.selectList, layout);
4305
+ const list = new SelectList(items, this.#autocompleteMaxVisible, this.#theme.selectList, layout);
4306
+ // A pointer pick on the popup (TSP `select`/`activate`) accepts it like Tab.
4307
+ list.onSelect = item => {
4308
+ if (this.#autocompleteList !== list) return;
4309
+ if (this.#autocompleteState === "assist") this.#applySpellingSuggestion();
4310
+ else this.#acceptAutocompleteSelection(item);
4311
+ };
4312
+ return list;
4124
4313
  }
4125
4314
 
4126
4315
  async #handleTabCompletion(): Promise<void> {