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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/types/apps/cleanse-board.d.ts +17 -0
  3. package/dist/types/apps/git/help.d.ts +16 -0
  4. package/dist/types/apps/git/sidebar.d.ts +18 -0
  5. package/dist/types/apps/live-visualizer.d.ts +10 -0
  6. package/dist/types/apps/ps-top.d.ts +15 -0
  7. package/dist/types/apps/standalone-picker.d.ts +3 -0
  8. package/dist/types/autocomplete.d.ts +8 -0
  9. package/dist/types/chat/advisor-message.d.ts +12 -2
  10. package/dist/types/chat/assistant-message.d.ts +20 -0
  11. package/dist/types/chat/bash-execution.d.ts +9 -0
  12. package/dist/types/chat/chat-transcript-builder.d.ts +6 -1
  13. package/dist/types/chat/collab-prompt-message.d.ts +4 -0
  14. package/dist/types/chat/compaction-summary-message.d.ts +15 -0
  15. package/dist/types/chat/eval-execution.d.ts +8 -0
  16. package/dist/types/chat/execution-shared.d.ts +58 -0
  17. package/dist/types/chat/late-diagnostics-message.d.ts +15 -1
  18. package/dist/types/chat/read-tool-group.d.ts +15 -0
  19. package/dist/types/chat/skill-message.d.ts +9 -0
  20. package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +3 -0
  21. package/dist/types/chat/thinking-display.d.ts +2 -0
  22. package/dist/types/chat/todo-reminder.d.ts +4 -1
  23. package/dist/types/chat/tool-execution.d.ts +25 -1
  24. package/dist/types/chat/transcript-actions.d.ts +37 -0
  25. package/dist/types/chat/transcript-entry.d.ts +3 -1
  26. package/dist/types/chat/user-message.d.ts +25 -0
  27. package/dist/types/chrome/collab-qrcode.d.ts +7 -0
  28. package/dist/types/chrome/context-thresholds.d.ts +11 -0
  29. package/dist/types/chrome/countdown-timer.d.ts +9 -3
  30. package/dist/types/chrome/diff.d.ts +12 -0
  31. package/dist/types/chrome/dynamic-border.d.ts +3 -0
  32. package/dist/types/chrome/format.d.ts +6 -0
  33. package/dist/types/chrome/message-divider.d.ts +13 -0
  34. package/dist/types/chrome/message-frame.d.ts +10 -0
  35. package/dist/types/chrome/message-notice.d.ts +23 -0
  36. package/dist/types/chrome/overlay-box.d.ts +11 -2
  37. package/dist/types/chrome/qrcode.d.ts +7 -0
  38. package/dist/types/chrome/segment-track.d.ts +7 -0
  39. package/dist/types/chrome/selector-helpers.d.ts +0 -6
  40. package/dist/types/chrome/status-notice.d.ts +14 -0
  41. package/dist/types/chrome/streaming-panel.d.ts +3 -0
  42. package/dist/types/chrome/tool-activity.d.ts +3 -0
  43. package/dist/types/chrome/transcript-container.d.ts +13 -0
  44. package/dist/types/chrome/transcript-status.d.ts +15 -3
  45. package/dist/types/components/box.d.ts +7 -0
  46. package/dist/types/components/disclosure.d.ts +9 -0
  47. package/dist/types/components/editor.d.ts +42 -0
  48. package/dist/types/components/form.d.ts +14 -0
  49. package/dist/types/components/image.d.ts +7 -0
  50. package/dist/types/components/input.d.ts +20 -1
  51. package/dist/types/components/key-value-list.d.ts +3 -0
  52. package/dist/types/components/layout/geometry.d.ts +16 -0
  53. package/dist/types/components/layout/row.d.ts +7 -0
  54. package/dist/types/components/layout/split-pane.d.ts +8 -0
  55. package/dist/types/components/layout/stack.d.ts +6 -0
  56. package/dist/types/components/loader.d.ts +48 -0
  57. package/dist/types/components/markdown.d.ts +8 -0
  58. package/dist/types/components/metric.d.ts +7 -0
  59. package/dist/types/components/progress-bar.d.ts +3 -0
  60. package/dist/types/components/scroll-view.d.ts +6 -0
  61. package/dist/types/components/section.d.ts +3 -0
  62. package/dist/types/components/select-list.d.ts +33 -0
  63. package/dist/types/components/settings-list.d.ts +68 -0
  64. package/dist/types/components/spacer.d.ts +4 -0
  65. package/dist/types/components/tab-bar.d.ts +9 -0
  66. package/dist/types/components/table.d.ts +7 -0
  67. package/dist/types/components/text.d.ts +6 -0
  68. package/dist/types/components/tree-view.d.ts +9 -0
  69. package/dist/types/components/truncated-text.d.ts +3 -0
  70. package/dist/types/components/wizard-step.d.ts +6 -0
  71. package/dist/types/hotkeys-markdown.d.ts +24 -0
  72. package/dist/types/index.d.ts +5 -0
  73. package/dist/types/latex-block.d.ts +7 -0
  74. package/dist/types/loop-watchdog.d.ts +9 -0
  75. package/dist/types/native/apply.d.ts +39 -0
  76. package/dist/types/native/backend.d.ts +94 -0
  77. package/dist/types/native/blobs.d.ts +29 -0
  78. package/dist/types/native/describe.d.ts +56 -0
  79. package/dist/types/native/encode.d.ts +50 -0
  80. package/dist/types/native/icons.d.ts +18 -0
  81. package/dist/types/native/memo.d.ts +27 -0
  82. package/dist/types/native/node.d.ts +107 -0
  83. package/dist/types/native/overlay.d.ts +64 -0
  84. package/dist/types/native/picker.d.ts +124 -0
  85. package/dist/types/native/reconcile.d.ts +41 -0
  86. package/dist/types/native/settle.d.ts +11 -0
  87. package/dist/types/native/spans.d.ts +21 -0
  88. package/dist/types/native/state.d.ts +6 -0
  89. package/dist/types/native/tone.d.ts +24 -0
  90. package/dist/types/overlays/advisor-config.d.ts +20 -0
  91. package/dist/types/overlays/agent-hub-renderer.d.ts +27 -11
  92. package/dist/types/overlays/agent-hub.d.ts +10 -0
  93. package/dist/types/overlays/agent-transcript-viewer.d.ts +7 -0
  94. package/dist/types/overlays/agents-hub.d.ts +8 -0
  95. package/dist/types/overlays/annotation-overlay.d.ts +3 -0
  96. package/dist/types/overlays/ask-dialog.d.ts +23 -0
  97. package/dist/types/overlays/bordered-loader.d.ts +3 -0
  98. package/dist/types/overlays/btw-history-panel.d.ts +9 -0
  99. package/dist/types/overlays/btw-panel.d.ts +3 -0
  100. package/dist/types/overlays/cleanse-panel.d.ts +5 -2
  101. package/dist/types/overlays/composer-shape-preview.d.ts +7 -1
  102. package/dist/types/overlays/copy-selector.d.ts +38 -0
  103. package/dist/types/overlays/error-banner.d.ts +9 -0
  104. package/dist/types/overlays/extensions/extension-list.d.ts +1 -0
  105. package/dist/types/overlays/history-search.d.ts +18 -0
  106. package/dist/types/overlays/hook-editor.d.ts +28 -1
  107. package/dist/types/overlays/hook-input.d.ts +3 -0
  108. package/dist/types/overlays/hook-selector.d.ts +10 -0
  109. package/dist/types/overlays/hub-frame.d.ts +18 -0
  110. package/dist/types/overlays/jobs-panel.d.ts +24 -0
  111. package/dist/types/overlays/login-dialog.d.ts +10 -0
  112. package/dist/types/overlays/logout-account-selector.d.ts +4 -0
  113. package/dist/types/overlays/mcp-add-wizard.d.ts +4 -0
  114. package/dist/types/overlays/model-browser.d.ts +69 -0
  115. package/dist/types/overlays/model-hub.d.ts +7 -0
  116. package/dist/types/overlays/model-picker.d.ts +9 -1
  117. package/dist/types/overlays/move-overlay.d.ts +3 -0
  118. package/dist/types/overlays/oauth-selector.d.ts +4 -0
  119. package/dist/types/overlays/omfg-panel.d.ts +3 -0
  120. package/dist/types/overlays/pause-screen.d.ts +12 -0
  121. package/dist/types/overlays/plan-review-overlay.d.ts +5 -0
  122. package/dist/types/overlays/plan-save-overlay.d.ts +10 -0
  123. package/dist/types/overlays/plugin-selector.d.ts +4 -0
  124. package/dist/types/overlays/plugin-settings.d.ts +30 -0
  125. package/dist/types/overlays/queue-mode-selector.d.ts +4 -0
  126. package/dist/types/overlays/reset-usage-selector.d.ts +8 -0
  127. package/dist/types/overlays/rewind-selector.d.ts +5 -0
  128. package/dist/types/overlays/session-info-overlay.d.ts +19 -1
  129. package/dist/types/overlays/session-selector.d.ts +64 -1
  130. package/dist/types/overlays/settings-defs.d.ts +14 -0
  131. package/dist/types/overlays/settings-selector.d.ts +21 -0
  132. package/dist/types/overlays/show-images-selector.d.ts +4 -0
  133. package/dist/types/overlays/snapcompact-shape-preview.d.ts +2 -0
  134. package/dist/types/overlays/stats-notice.d.ts +8 -0
  135. package/dist/types/overlays/theme-selector.d.ts +11 -0
  136. package/dist/types/overlays/thinking-selector.d.ts +4 -0
  137. package/dist/types/overlays/tree-selector.d.ts +60 -2
  138. package/dist/types/overlays/usage-dashboard.d.ts +26 -3
  139. package/dist/types/overlays/usage-row.d.ts +36 -2
  140. package/dist/types/prompt/attachment-chips.d.ts +8 -0
  141. package/dist/types/prompt/composer-attachments.d.ts +15 -3
  142. package/dist/types/prompt/composer.d.ts +18 -1
  143. package/dist/types/prompt/custom-editor.d.ts +48 -2
  144. package/dist/types/prompt/editor-top-gap.d.ts +2 -0
  145. package/dist/types/prompt/macos-spelling.d.ts +6 -0
  146. package/dist/types/prompt/magic-keywords.d.ts +9 -0
  147. package/dist/types/prompt/queued-messages.d.ts +23 -0
  148. package/dist/types/prompt/skill-tokens.d.ts +4 -2
  149. package/dist/types/prompt/welcome.d.ts +16 -0
  150. package/dist/types/render/code-cell.d.ts +10 -0
  151. package/dist/types/render/file-list.d.ts +8 -0
  152. package/dist/types/render/hyperlink.d.ts +14 -0
  153. package/dist/types/render/output-block.d.ts +43 -0
  154. package/dist/types/render/output-pane.d.ts +17 -0
  155. package/dist/types/render/tool-card.d.ts +8 -0
  156. package/dist/types/render/tree-list.d.ts +8 -0
  157. package/dist/types/render/width-aware-text.d.ts +7 -0
  158. package/dist/types/setup/scenes/outro.d.ts +7 -0
  159. package/dist/types/setup/scenes/sign-in.d.ts +16 -9
  160. package/dist/types/setup/scenes/splash.d.ts +8 -0
  161. package/dist/types/setup/scenes/types.d.ts +6 -27
  162. package/dist/types/setup/wizard-overlay.d.ts +9 -0
  163. package/dist/types/status-line/component.d.ts +49 -5
  164. package/dist/types/status-line/context-usage.d.ts +20 -0
  165. package/dist/types/status-line/footer.d.ts +8 -0
  166. package/dist/types/status-line/metrics.d.ts +1 -2
  167. package/dist/types/status-line/segments.d.ts +10 -1
  168. package/dist/types/status-line/types.d.ts +40 -1
  169. package/dist/types/stdin-buffer.d.ts +10 -7
  170. package/dist/types/terminal-capabilities.d.ts +1 -1
  171. package/dist/types/terminal.d.ts +36 -0
  172. package/dist/types/theme/defaults/index.d.ts +100 -0
  173. package/dist/types/theme/schema.d.ts +2 -0
  174. package/dist/types/theme/shimmer.d.ts +8 -0
  175. package/dist/types/theme/theme-class.d.ts +2 -0
  176. package/dist/types/theme/theme.d.ts +33 -1
  177. package/dist/types/tools/ask.d.ts +3 -0
  178. package/dist/types/tools/ast-edit.d.ts +10 -1
  179. package/dist/types/tools/ast-grep.d.ts +10 -1
  180. package/dist/types/tools/autoresearch.d.ts +21 -4
  181. package/dist/types/tools/bash.d.ts +30 -1
  182. package/dist/types/tools/cfg-render.d.ts +5 -1
  183. package/dist/types/tools/debug.d.ts +3 -1
  184. package/dist/types/tools/default-renderer.d.ts +6 -1
  185. package/dist/types/tools/edit.d.ts +14 -1
  186. package/dist/types/tools/eval.d.ts +12 -1
  187. package/dist/types/tools/fetch.d.ts +16 -1
  188. package/dist/types/tools/find.d.ts +15 -1
  189. package/dist/types/tools/github.d.ts +3 -0
  190. package/dist/types/tools/glob.d.ts +14 -1
  191. package/dist/types/tools/goal.d.ts +3 -1
  192. package/dist/types/tools/grep.d.ts +14 -1
  193. package/dist/types/tools/grouped-file-output.d.ts +58 -0
  194. package/dist/types/tools/json-tree.d.ts +20 -0
  195. package/dist/types/tools/lsp.d.ts +3 -10
  196. package/dist/types/tools/mcp.d.ts +16 -1
  197. package/dist/types/tools/memory.d.ts +26 -0
  198. package/dist/types/tools/native-view.d.ts +90 -0
  199. package/dist/types/tools/proc-render.d.ts +7 -1
  200. package/dist/types/tools/read.d.ts +23 -1
  201. package/dist/types/tools/renderer.d.ts +57 -0
  202. package/dist/types/tools/report-tool-issue.d.ts +3 -0
  203. package/dist/types/tools/resolve.d.ts +14 -1
  204. package/dist/types/tools/task.d.ts +3 -0
  205. package/dist/types/tools/think.d.ts +3 -0
  206. package/dist/types/tools/todo.d.ts +12 -0
  207. package/dist/types/tools/vibe.d.ts +3 -1
  208. package/dist/types/tools/wait.d.ts +3 -0
  209. package/dist/types/tools/web-search-types.d.ts +90 -0
  210. package/dist/types/tools/web-search.d.ts +9 -168
  211. package/dist/types/tools/write.d.ts +14 -1
  212. package/dist/types/tools/xdev.d.ts +13 -0
  213. package/dist/types/tui.d.ts +49 -0
  214. package/package.json +9 -9
  215. package/src/apps/autoresearch-dashboard.ts +362 -4
  216. package/src/apps/cleanse-board.ts +219 -1
  217. package/src/apps/cleanse-picker.ts +9 -1
  218. package/src/apps/debug/log-viewer.ts +15 -15
  219. package/src/apps/debug/protocol-probe.ts +2 -20
  220. package/src/apps/git/avatar.ts +2 -22
  221. package/src/apps/git/git-tui.ts +406 -59
  222. package/src/apps/git/help.ts +130 -0
  223. package/src/apps/git/sidebar.ts +491 -0
  224. package/src/apps/live-visualizer.ts +65 -0
  225. package/src/apps/ps-top.ts +448 -17
  226. package/src/apps/session-picker.ts +1 -0
  227. package/src/apps/setup-model-picker.ts +5 -1
  228. package/src/apps/standalone-picker.ts +55 -1
  229. package/src/autocomplete.ts +44 -1
  230. package/src/chat/advisor-message.ts +72 -3
  231. package/src/chat/assistant-message.ts +538 -51
  232. package/src/chat/background-tan-message.ts +4 -4
  233. package/src/chat/bash-execution.ts +81 -0
  234. package/src/chat/cache-invalidation-marker.ts +8 -0
  235. package/src/chat/chat-transcript-builder.ts +37 -6
  236. package/src/chat/collab-prompt-message.ts +15 -3
  237. package/src/chat/compaction-summary-message.ts +74 -1
  238. package/src/chat/custom-message.ts +3 -1
  239. package/src/chat/eval-execution.ts +57 -0
  240. package/src/chat/execution-shared.ts +153 -1
  241. package/src/chat/hook-message.ts +1 -0
  242. package/src/chat/late-diagnostics-message.ts +85 -2
  243. package/src/chat/read-tool-group.ts +341 -1
  244. package/src/chat/served-model-marker.ts +8 -0
  245. package/src/chat/skill-message.ts +63 -0
  246. package/src/chat/stripped-tool-calls-placeholder.ts +18 -10
  247. package/src/chat/thinking-display.ts +73 -11
  248. package/src/chat/todo-reminder.ts +34 -4
  249. package/src/chat/tool-execution.ts +385 -10
  250. package/src/chat/transcript-actions.ts +38 -0
  251. package/src/chat/transcript-browser.ts +2 -9
  252. package/src/chat/transcript-entry.ts +10 -1
  253. package/src/chat/transcript-render-helpers.ts +16 -15
  254. package/src/chat/ttsr-notification.ts +38 -1
  255. package/src/chat/user-message.ts +167 -4
  256. package/src/chrome/collab-qrcode.ts +27 -2
  257. package/src/chrome/context-thresholds.ts +34 -0
  258. package/src/chrome/countdown-timer.ts +24 -1
  259. package/src/chrome/diff.ts +60 -1
  260. package/src/chrome/dynamic-border.ts +7 -0
  261. package/src/chrome/format.ts +12 -0
  262. package/src/chrome/message-divider.ts +33 -1
  263. package/src/chrome/message-frame.ts +53 -10
  264. package/src/chrome/message-notice.ts +71 -0
  265. package/src/chrome/overlay-box.ts +45 -2
  266. package/src/chrome/qrcode.ts +28 -0
  267. package/src/chrome/segment-track.ts +26 -0
  268. package/src/chrome/selector-helpers.ts +1 -17
  269. package/src/chrome/status-notice.ts +46 -0
  270. package/src/chrome/streaming-panel.ts +25 -1
  271. package/src/chrome/tool-activity.ts +20 -0
  272. package/src/chrome/transcript-container.ts +139 -17
  273. package/src/chrome/transcript-status.ts +40 -11
  274. package/src/components/box.ts +51 -0
  275. package/src/components/disclosure.ts +33 -0
  276. package/src/components/editor.ts +239 -36
  277. package/src/components/form.ts +93 -9
  278. package/src/components/image.ts +30 -0
  279. package/src/components/input.ts +77 -26
  280. package/src/components/key-value-list.ts +18 -0
  281. package/src/components/layout/geometry.ts +44 -0
  282. package/src/components/layout/row.ts +30 -0
  283. package/src/components/layout/split-pane.ts +65 -0
  284. package/src/components/layout/stack.ts +27 -0
  285. package/src/components/loader.ts +183 -1
  286. package/src/components/markdown.ts +131 -56
  287. package/src/components/metric.ts +39 -0
  288. package/src/components/progress-bar.ts +28 -0
  289. package/src/components/scroll-view.ts +23 -0
  290. package/src/components/section.ts +16 -0
  291. package/src/components/select-list.ts +174 -25
  292. package/src/components/settings-list.ts +264 -7
  293. package/src/components/spacer.ts +17 -0
  294. package/src/components/tab-bar.ts +42 -0
  295. package/src/components/table.ts +34 -0
  296. package/src/components/text.ts +23 -0
  297. package/src/components/tree-view.ts +65 -0
  298. package/src/components/truncated-text.ts +14 -0
  299. package/src/components/wizard-step.ts +18 -9
  300. package/src/debug-server.ts +14 -7
  301. package/src/hotkeys-markdown.ts +251 -69
  302. package/src/index.ts +6 -0
  303. package/src/latex-block.ts +11 -0
  304. package/src/loop-watchdog.ts +38 -10
  305. package/src/native/apply.ts +275 -0
  306. package/src/native/backend.ts +682 -0
  307. package/src/native/blobs.ts +70 -0
  308. package/src/native/describe.ts +124 -0
  309. package/src/native/encode.ts +233 -0
  310. package/src/native/icons.ts +184 -0
  311. package/src/native/memo.ts +64 -0
  312. package/src/native/node.ts +112 -0
  313. package/src/native/overlay.ts +131 -0
  314. package/src/native/picker.ts +333 -0
  315. package/src/native/reconcile.ts +1063 -0
  316. package/src/native/settle.ts +23 -0
  317. package/src/native/spans.ts +308 -0
  318. package/src/native/state.ts +28 -0
  319. package/src/native/tone.ts +79 -0
  320. package/src/overlays/advisor-config.ts +420 -0
  321. package/src/overlays/agent-hub-renderer.ts +155 -18
  322. package/src/overlays/agent-hub.ts +1037 -44
  323. package/src/overlays/agent-transcript-viewer.ts +129 -0
  324. package/src/overlays/agents-hub.ts +688 -53
  325. package/src/overlays/annotation-overlay.ts +391 -52
  326. package/src/overlays/ask-dialog.ts +435 -24
  327. package/src/overlays/bordered-loader.ts +17 -0
  328. package/src/overlays/btw-history-panel.ts +182 -0
  329. package/src/overlays/btw-panel.ts +68 -2
  330. package/src/overlays/cleanse-panel.ts +105 -15
  331. package/src/overlays/codex-reset-fireworks.ts +65 -5
  332. package/src/overlays/composer-shape-preview.ts +26 -1
  333. package/src/overlays/copy-selector.ts +545 -23
  334. package/src/overlays/error-banner.ts +44 -0
  335. package/src/overlays/extensions/extension-list.ts +23 -17
  336. package/src/overlays/history-search.ts +175 -33
  337. package/src/overlays/hook-editor.ts +113 -6
  338. package/src/overlays/hook-input.ts +22 -1
  339. package/src/overlays/hook-selector.ts +311 -22
  340. package/src/overlays/hub-frame.ts +80 -0
  341. package/src/overlays/jobs-panel.ts +112 -0
  342. package/src/overlays/login-dialog.ts +183 -1
  343. package/src/overlays/logout-account-selector.ts +102 -4
  344. package/src/overlays/mcp-add-wizard.ts +232 -53
  345. package/src/overlays/model-browser.ts +681 -22
  346. package/src/overlays/model-hub.ts +1402 -78
  347. package/src/overlays/model-picker.ts +184 -7
  348. package/src/overlays/move-overlay.ts +45 -0
  349. package/src/overlays/oauth-selector.ts +227 -23
  350. package/src/overlays/omfg-panel.ts +86 -2
  351. package/src/overlays/pause-screen.ts +55 -4
  352. package/src/overlays/plan-review-overlay.ts +352 -0
  353. package/src/overlays/plan-save-overlay.ts +45 -0
  354. package/src/overlays/plugin-selector.ts +21 -1
  355. package/src/overlays/plugin-settings.ts +195 -5
  356. package/src/overlays/queue-mode-selector.ts +19 -1
  357. package/src/overlays/reset-usage-selector.ts +110 -40
  358. package/src/overlays/rewind-selector.ts +458 -44
  359. package/src/overlays/session-account-selector.ts +1 -1
  360. package/src/overlays/session-info-overlay.ts +137 -1
  361. package/src/overlays/session-selector.ts +807 -46
  362. package/src/overlays/settings-defs.ts +41 -0
  363. package/src/overlays/settings-selector.ts +585 -33
  364. package/src/overlays/show-images-selector.ts +18 -1
  365. package/src/overlays/snapcompact-shape-preview.ts +48 -3
  366. package/src/overlays/stats-notice.ts +31 -0
  367. package/src/overlays/theme-selector.ts +31 -1
  368. package/src/overlays/thinking-selector.ts +22 -1
  369. package/src/overlays/tree-selector.ts +570 -110
  370. package/src/overlays/usage-dashboard.ts +587 -12
  371. package/src/overlays/usage-row.ts +161 -25
  372. package/src/prompt/attachment-chips.ts +60 -0
  373. package/src/prompt/composer-attachments.ts +31 -9
  374. package/src/prompt/composer.ts +55 -2
  375. package/src/prompt/custom-editor.ts +302 -4
  376. package/src/prompt/editor-top-gap.ts +8 -0
  377. package/src/prompt/macos-spelling.ts +24 -9
  378. package/src/prompt/magic-keywords.ts +22 -1
  379. package/src/prompt/model-mention-autocomplete.ts +1 -0
  380. package/src/prompt/queued-messages.ts +101 -0
  381. package/src/prompt/skill-tokens.ts +5 -3
  382. package/src/prompt/welcome.ts +213 -6
  383. package/src/render/code-cell.ts +103 -2
  384. package/src/render/file-list.ts +29 -0
  385. package/src/render/hyperlink.ts +32 -0
  386. package/src/render/output-block.ts +110 -0
  387. package/src/render/output-pane.ts +37 -0
  388. package/src/render/tool-card.ts +137 -0
  389. package/src/render/tree-list.ts +39 -0
  390. package/src/render/width-aware-text.ts +20 -0
  391. package/src/setup/scenes/composer.ts +29 -0
  392. package/src/setup/scenes/glyph.ts +15 -0
  393. package/src/setup/scenes/model.ts +36 -8
  394. package/src/setup/scenes/outro.ts +28 -1
  395. package/src/setup/scenes/sign-in.ts +138 -24
  396. package/src/setup/scenes/splash.ts +28 -1
  397. package/src/setup/scenes/theme.ts +88 -3
  398. package/src/setup/scenes/types.ts +7 -28
  399. package/src/setup/startup-splash.ts +46 -9
  400. package/src/setup/wizard-overlay.ts +140 -23
  401. package/src/setup/wizard.ts +1 -1
  402. package/src/status-line/component.ts +414 -18
  403. package/src/status-line/context-usage.ts +279 -50
  404. package/src/status-line/footer.ts +94 -1
  405. package/src/status-line/metrics.ts +3 -6
  406. package/src/status-line/segments.ts +463 -97
  407. package/src/status-line/separators.ts +3 -16
  408. package/src/status-line/types.ts +43 -1
  409. package/src/stdin-buffer.ts +27 -21
  410. package/src/terminal-capabilities.ts +7 -0
  411. package/src/terminal.ts +153 -11
  412. package/src/theme/defaults/dark-neon-noir.json +100 -0
  413. package/src/theme/defaults/index.ts +2 -0
  414. package/src/theme/defaults/light-prism.json +5 -5
  415. package/src/theme/defaults/onyx.json +62 -62
  416. package/src/theme/mermaid-cache.ts +10 -1
  417. package/src/theme/schema.ts +15 -0
  418. package/src/theme/shimmer.ts +33 -0
  419. package/src/theme/theme-class.ts +24 -19
  420. package/src/theme/theme.ts +111 -9
  421. package/src/theme/tui-adapters.ts +14 -1
  422. package/src/tools/ask.ts +157 -1
  423. package/src/tools/ast-edit.ts +174 -1
  424. package/src/tools/ast-grep.ts +82 -2
  425. package/src/tools/autoresearch.ts +149 -1
  426. package/src/tools/bash.ts +233 -62
  427. package/src/tools/cfg-render.ts +66 -1
  428. package/src/tools/debug.ts +78 -1
  429. package/src/tools/default-renderer.ts +35 -1
  430. package/src/tools/edit.ts +357 -31
  431. package/src/tools/eval.ts +257 -1
  432. package/src/tools/fetch.ts +102 -3
  433. package/src/tools/find.ts +127 -1
  434. package/src/tools/github.ts +119 -10
  435. package/src/tools/glob.ts +116 -1
  436. package/src/tools/goal.ts +56 -1
  437. package/src/tools/grep.ts +83 -2
  438. package/src/tools/grouped-file-output.ts +205 -0
  439. package/src/tools/json-tree.ts +116 -1
  440. package/src/tools/lsp.ts +318 -1
  441. package/src/tools/mcp.ts +80 -1
  442. package/src/tools/memory.ts +93 -11
  443. package/src/tools/native-view.ts +292 -0
  444. package/src/tools/proc-render.ts +221 -1
  445. package/src/tools/read.ts +199 -4
  446. package/src/tools/renderer.ts +61 -0
  447. package/src/tools/report-tool-issue.ts +7 -1
  448. package/src/tools/resolve.ts +63 -1
  449. package/src/tools/streaming-output.ts +79 -16
  450. package/src/tools/task.ts +406 -4
  451. package/src/tools/think.ts +19 -1
  452. package/src/tools/todo.ts +89 -0
  453. package/src/tools/vibe.ts +230 -2
  454. package/src/tools/wait.ts +181 -1
  455. package/src/tools/web-search-types.ts +99 -0
  456. package/src/tools/web-search.ts +111 -170
  457. package/src/tools/write.ts +144 -5
  458. package/src/tools/xdev.ts +64 -1
  459. package/src/tui.ts +295 -4
  460. package/dist/types/setup/scenes/providers.d.ts +0 -3
  461. package/dist/types/setup/scenes/web-search.d.ts +0 -22
  462. package/src/setup/scenes/providers.ts +0 -110
  463. package/src/setup/scenes/web-search.ts +0 -165
@@ -2,12 +2,21 @@ import * as url from "node:url";
2
2
  import type { ImageContent } from "@oh-my-pi/pi-ai";
3
3
  import { BracketedPasteHandler } from "../bracketed-paste";
4
4
  import { BRACKETED_PASTE_END, BRACKETED_PASTE_START } from "../stdin-buffer";
5
- import { Editor, type EditorTextDecorationContext, type EditorTheme } from "../components/editor";
5
+ import {
6
+ Editor,
7
+ type EditorTextDecorationContext,
8
+ type EditorTheme,
9
+ type NativeEditorLayout,
10
+ } from "../components/editor";
6
11
  import { addKeyAliases, canonicalKeyId, getKeybindings } from "../keybindings";
7
12
  import { type KeyId, parseKey, parseKittySequence } from "../keys";
8
13
  import { SpaceHoldGesture } from "../space-hold";
9
- import { TUI } from "../tui";
14
+ import { type Component, TUI } from "../tui";
10
15
  import type { AppKeybinding } from "../app-keybindings";
16
+ import { formatKeyHint } from "../key-hint-format";
17
+ import { compact, keyed, node, row, span } from "../native/describe";
18
+ import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node";
19
+ import type { ComposerFacts, ComposerFactsSource } from "../status-line/types";
11
20
  import { allowsModelMentions, allowsSkillTokens, SKILL_TOKEN_RE } from "./skill-tokens";
12
21
  import { expandModelMentionTags, MODEL_MENTION_RE, modelMentionToken } from "./model-mention-syntax";
13
22
  import { imageAttachmentSource } from "./image-source";
@@ -30,11 +39,42 @@ import {
30
39
  skillToken,
31
40
  } from "./composer-attachments";
32
41
  import { type MacOSSpellingFeatures, MacOSSpellingProvider } from "./macos-spelling";
33
- import { hasMagicKeyword, highlightMagicKeywords } from "./magic-keywords";
42
+ import { hasMagicKeyword, highlightMagicKeywords, magicKeywordRanges } from "./magic-keywords";
43
+ import type { TspEditorDecoration } from "@oh-my-pi/pi-wire";
44
+ import { isNativeRendering } from "../native/state";
34
45
  import { isQueuedMessageList, parseQueueShorthand, QUEUE_LIST_MARKER_RE } from "./queue-input";
35
46
  import { type WordCompletionMethod, WordCompletionProvider } from "./word-completion";
36
47
  import { fgOrPlain, theme } from "../theme/theme";
37
48
 
49
+ /** A shell-mode draft's sigil (`!`, `!!`, `$`, `$$`) with its surrounding blanks; the mode chip stands in for it natively. */
50
+ const SHELL_SIGIL_RE = /^\s*(?:!!?|\$\$?)[ \t]?/;
51
+
52
+ /** The composer's TSP placeholder; the rotating ANSI hints (thinking effort, …) move into control tooltips. */
53
+ const NATIVE_COMPOSER_PLACEHOLDER = "Ask omp — / commands · @ files · ! bash";
54
+
55
+ /** Live composer state the TSP layout shows; the interactive host wires {@link CustomEditor.composerState}. */
56
+ export interface ComposerNativeState {
57
+ /** The draft runs as a shell command (`!`, `!!`) or Python (`$`, `$$`); `excluded` keeps it from the model. */
58
+ readonly shell?: { readonly kind: "bash" | "python"; readonly excluded: boolean };
59
+ /** Thinking effort word (`high`, `off`, `auto`); undefined when the model has no thinking. */
60
+ readonly thinking?: string;
61
+ /** A turn is running: the send keycap becomes a Stop button. */
62
+ readonly running: boolean;
63
+ }
64
+
65
+ const IDLE_COMPOSER: ComposerNativeState = { running: false };
66
+
67
+ /** Filled steps (of four) of the effort chip's meter per thinking level; `auto` before it resolves has none known. */
68
+ const EFFORT_STEPS: Partial<Record<string, number>> = {
69
+ off: 0,
70
+ minimal: 1,
71
+ low: 1,
72
+ medium: 2,
73
+ high: 3,
74
+ xhigh: 4,
75
+ max: 4,
76
+ };
77
+
38
78
  /** Independently switchable prose-assistance features of the composer. */
39
79
  export interface SpellingFeatures extends MacOSSpellingFeatures {
40
80
  /** Word-completion engine; `off` disables ghost text. */
@@ -838,6 +878,67 @@ export class CustomEditor extends Editor {
838
878
  );
839
879
  };
840
880
 
881
+ /**
882
+ * TSP decorations: magic keywords shimmer (terminal-clocked) in the accent
883
+ * color, chips and markers take their token colors, misspellings are marked,
884
+ * and queue-composer markers are dimmed/accented, all as ranges over the raw
885
+ * buffer instead of painted text. A shell-mode draft is code: only its sigil
886
+ * is decorated, hidden behind the mode chip.
887
+ */
888
+ override describeDecorations = (lines: readonly string[]): readonly TspEditorDecoration[] => {
889
+ const text = lines.join("\n");
890
+ if (this.composerState().shell) {
891
+ const sigil = SHELL_SIGIL_RE.exec(text)?.[0].length ?? 0;
892
+ return sigil > 0 ? [{ from: 0, to: sigil, s: "hide" }] : [];
893
+ }
894
+ this.#syncComposerTokenPattern();
895
+ const decor: TspEditorDecoration[] = [];
896
+ let offset = 0;
897
+ const mark = (length: number, s: string): string => {
898
+ decor.push({ from: offset, to: offset + length, s });
899
+ offset += length;
900
+ return "";
901
+ };
902
+ renderPlaceholders(
903
+ text,
904
+ {
905
+ renderText: value => {
906
+ offset += value.length;
907
+ return "";
908
+ },
909
+ renderSkill: label => mark(label.length, "customMessageLabel strong"),
910
+ renderMention: label => mark(label.length, "statusLineModel strong"),
911
+ renderReference: value => mark(value.length, "accent strong"),
912
+ },
913
+ this.atomicTokenPattern,
914
+ );
915
+
916
+ const fx = this.#shimmerEnabled() ? "shimmer" : undefined;
917
+ for (const range of magicKeywordRanges(text)) decor.push({ ...range, s: "accent", fx });
918
+
919
+ const queueBody = parseQueueShorthand(text);
920
+ const queueList = queueBody !== undefined && isQueuedMessageList(queueBody);
921
+ let lineStart = 0;
922
+ for (let line = 0; line < lines.length; line++) {
923
+ const value = lines[line] ?? "";
924
+ if (queueBody !== undefined && (value.startsWith("->") || value.startsWith("=>"))) {
925
+ decor.push({ from: lineStart, to: lineStart + 2, s: "dim" });
926
+ }
927
+ if (queueList) {
928
+ const marker = QUEUE_LIST_MARKER_RE.exec(value);
929
+ if (marker) {
930
+ const indent = marker[1]?.length ?? 0;
931
+ decor.push({ from: lineStart + indent, to: lineStart + marker[0].length, s: "accent" });
932
+ }
933
+ }
934
+ for (const typo of this.#spelling.typoRanges(value, { editorText: text, lines, line, startCol: 0 })) {
935
+ decor.push({ from: lineStart + typo.start, to: lineStart + typo.start + typo.length, s: "mark" });
936
+ }
937
+ lineStart += value.length + 1;
938
+ }
939
+ return decor.sort((a, b) => a.from - b.from);
940
+ };
941
+
841
942
  /** Optional test override for the magic-keyword shimmer gate. */
842
943
  magicKeywordsEnabledOverride: boolean | undefined;
843
944
 
@@ -877,13 +978,210 @@ export class CustomEditor extends Editor {
877
978
  * decides whether to schedule another, so the chain stops by itself when
878
979
  * `focused` flips off or the keyword leaves the buffer. */
879
980
  #scheduleShimmerFrame(): void {
880
- if (this.#shimmerTimer || !this.#requestShimmerRepaint) return;
981
+ // A TSP terminal animates the keyword shimmer from `describeDecorations`.
982
+ if (this.#shimmerTimer || !this.#requestShimmerRepaint || isNativeRendering()) return;
881
983
  this.#shimmerTimer = setTimeout(() => {
882
984
  this.#shimmerTimer = undefined;
883
985
  this.#requestShimmerRepaint?.();
884
986
  }, CustomEditor.SHIMMER_FRAME_MS);
885
987
  this.#shimmerTimer.unref?.();
886
988
  }
989
+ override nativePlaceholder: string | undefined = NATIVE_COMPOSER_PLACEHOLDER;
990
+ /** A shell-mode draft highlights as its language. */
991
+ override describeLanguage = (): string | undefined => this.composerState().shell?.kind;
992
+ /** Host-owned live state for the TSP composer (shell mode, effort chip, send/stop). */
993
+ composerState: () => ComposerNativeState = () => IDLE_COMPOSER;
994
+ /** The attachment band, described inside the composer on a TSP terminal (ANSI renders it above). */
995
+ attachmentChips: Component | undefined;
996
+ /** The status line's facts the TSP composer carries (context, model, usage, the other segments). */
997
+ composerFacts: ComposerFactsSource | undefined;
998
+ #nativeComposer:
999
+ | {
1000
+ key: string;
1001
+ facts: ComposerFacts | undefined;
1002
+ chips: Component | undefined;
1003
+ input: NativeNode;
1004
+ mode: NativeNode | undefined;
1005
+ bar: NativeNode;
1006
+ layout: NativeEditorLayout;
1007
+ }
1008
+ | undefined;
1009
+
1010
+ /**
1011
+ * The TSP composer: role `omp.editor[.bash|.python]` (tone `pending` while
1012
+ * a turn runs) over the context hairline, the attachment chips, a `line`
1013
+ * row of the shell-mode chip and the input, and the `bar`: model chip,
1014
+ * effort chip, the other status facts, usage, then send (Stop while a turn
1015
+ * runs). Clicks come back as `status.model`, `thinking.cycle`, `submit`
1016
+ * and `interrupt` actions.
1017
+ */
1018
+ override describeLayout = (input: NativeNode, _cx: DescribeContext): NativeEditorLayout => {
1019
+ const state = this.composerState();
1020
+ const shell = state.shell;
1021
+ const facts = this.composerFacts?.describeComposerFacts();
1022
+ const thinkingKey = this.#actionKeys.get("app.thinking.cycle")?.[0];
1023
+ const modelKey = this.#actionKeys.get("app.model.selectTemporary")?.[0];
1024
+ const interruptKey = this.#actionKeys.get("app.interrupt")?.[0] ?? "escape";
1025
+ const key = [
1026
+ shell?.kind,
1027
+ shell?.excluded,
1028
+ state.thinking,
1029
+ state.running,
1030
+ thinkingKey,
1031
+ modelKey,
1032
+ interruptKey,
1033
+ ].join("\0");
1034
+ const chips = this.attachmentChips;
1035
+ const memo = this.#nativeComposer;
1036
+ if (memo && memo.key === key && memo.facts === facts && memo.input === input && memo.chips === chips) {
1037
+ return memo.layout;
1038
+ }
1039
+ const { mode, bar } =
1040
+ memo?.key === key && memo.facts === facts
1041
+ ? memo
1042
+ : this.#describeComposerControls(state, facts, thinkingKey, modelKey, interruptKey);
1043
+ const line = keyed(row(compact([mode, input]), { role: "omp.composer.line", align: "start", gap: "sm" }), "line");
1044
+ const layout: NativeEditorLayout = {
1045
+ role: shell ? `omp.editor.${shell.kind}` : "omp.editor",
1046
+ tone: state.running ? "pending" : undefined,
1047
+ children: compact([facts?.context, chips, line, bar]),
1048
+ caret: "line/input",
1049
+ };
1050
+ this.#nativeComposer = { key, facts, chips, input, mode, bar, layout };
1051
+ return layout;
1052
+ };
1053
+
1054
+ /** The shell-mode chip before the input, and the bar under it. */
1055
+ #describeComposerControls(
1056
+ state: ComposerNativeState,
1057
+ facts: ComposerFacts | undefined,
1058
+ thinkingKey: KeyId | undefined,
1059
+ modelKey: KeyId | undefined,
1060
+ interruptKey: KeyId,
1061
+ ): { mode: NativeNode | undefined; bar: NativeNode } {
1062
+ const shell = state.shell;
1063
+ const model =
1064
+ facts &&
1065
+ node(
1066
+ "row",
1067
+ {
1068
+ role: "omp.composer.model",
1069
+ gap: "xs",
1070
+ align: "center",
1071
+ tone: facts.model.tone,
1072
+ title: modelKey ? `Switch model ${formatKeyHint(modelKey)}` : "Switch model",
1073
+ actions: { click: "status.model" },
1074
+ },
1075
+ [
1076
+ node("icon", { name: "model" }, undefined, "icon"),
1077
+ node("text", { spans: facts.model.spans, wrap: "none" }, undefined, "name"),
1078
+ node("icon", { name: "chev" }, undefined, "chev"),
1079
+ ],
1080
+ "model",
1081
+ );
1082
+ const effortSteps = state.thinking === undefined ? undefined : EFFORT_STEPS[state.thinking];
1083
+ const effort =
1084
+ state.thinking !== undefined &&
1085
+ node(
1086
+ "row",
1087
+ {
1088
+ role: "omp.composer.effort",
1089
+ gap: "xs",
1090
+ align: "center",
1091
+ title: thinkingKey ? `Thinking effort ${formatKeyHint(thinkingKey)}` : "Thinking effort",
1092
+ actions: { click: "thinking.cycle" },
1093
+ },
1094
+ [
1095
+ node(
1096
+ "meter",
1097
+ { value: effortSteps === undefined ? null : effortSteps / 4, style: "blocks", steps: 4 },
1098
+ undefined,
1099
+ "meter",
1100
+ ),
1101
+ node("text", { text: state.thinking, wrap: "none" }, undefined, "level"),
1102
+ ],
1103
+ "effort",
1104
+ );
1105
+ const submit = state.running
1106
+ ? node(
1107
+ "text",
1108
+ {
1109
+ role: "omp.composer.stop",
1110
+ text: "Stop",
1111
+ tone: "error",
1112
+ title: `Stop ${interruptKey === "escape" ? "esc" : formatKeyHint(interruptKey)}`,
1113
+ actions: { click: "interrupt" },
1114
+ },
1115
+ undefined,
1116
+ "stop",
1117
+ )
1118
+ : node(
1119
+ "kbd",
1120
+ {
1121
+ role: "omp.composer.send",
1122
+ keys: ["enter"],
1123
+ title: `Send ${formatKeyHint("enter")}`,
1124
+ actions: { click: "submit" },
1125
+ },
1126
+ undefined,
1127
+ "send",
1128
+ );
1129
+ // The status facts are the bar's flexible space; without them a spacer keeps send at the end.
1130
+ const bar = keyed(
1131
+ row(compact([model, effort, facts?.extras ?? node("row", { grow: 1 }, [], "gap"), facts?.usage, submit]), {
1132
+ role: "omp.composer.bar",
1133
+ gap: "sm",
1134
+ align: "center",
1135
+ }),
1136
+ "bar",
1137
+ );
1138
+ if (!shell) return { mode: undefined, bar };
1139
+ const runs = shell.kind === "bash" ? "Runs in your shell" : "Runs in Python";
1140
+ const mode = keyed(
1141
+ row(
1142
+ compact([
1143
+ shell.excluded &&
1144
+ node("icon", { name: "eye-off", title: "Not sent to the model" }, undefined, "excluded"),
1145
+ node(
1146
+ "text",
1147
+ { spans: [span(shell.kind, shell.kind === "bash" ? "bashMode" : "pythonMode")], wrap: "none" },
1148
+ undefined,
1149
+ "label",
1150
+ ),
1151
+ ]),
1152
+ {
1153
+ role: "omp.composer.mode",
1154
+ gap: "xs",
1155
+ align: "center",
1156
+ title: shell.excluded ? `${runs} · not sent to the model` : runs,
1157
+ },
1158
+ ),
1159
+ "mode",
1160
+ );
1161
+ return { mode, bar };
1162
+ }
1163
+
1164
+ /**
1165
+ * Clicks on the composer's controls take the same paths as their keys: ⇧⇥,
1166
+ * ⏎ and Esc; the status facts' clicks (`status.*`) go to their source.
1167
+ */
1168
+ handleNativeEvent(event: NativeUiEvent): void {
1169
+ if (event.type !== "action") return;
1170
+ switch (event.act) {
1171
+ case "thinking.cycle":
1172
+ this.onCycleThinkingLevel?.();
1173
+ return;
1174
+ case "submit":
1175
+ this.submit();
1176
+ return;
1177
+ case "interrupt":
1178
+ this.onEscape?.();
1179
+ return;
1180
+ default:
1181
+ this.composerFacts?.handleNativeEvent(event);
1182
+ }
1183
+ }
1184
+
887
1185
  onEscape?: () => void;
888
1186
  onClear?: () => void;
889
1187
  onExit?: () => void;
@@ -1,4 +1,6 @@
1
1
  import type { Component } from "../index";
2
+ import type { NativeNode } from "../native/node";
3
+ import { col } from "../native/describe";
2
4
  let composerShape = "box";
3
5
 
4
6
  /** Set the process-wide editor gap layout. */
@@ -8,6 +10,8 @@ export function setEditorGapComposerShape(shape: string): void {
8
10
 
9
11
  const GAP: readonly string[] = [""];
10
12
  const FLUSH: readonly string[] = [];
13
+ /** A TSP terminal spaces the dock itself; the gap describes nothing. */
14
+ const NATIVE_GAP: NativeNode = col([]);
11
15
 
12
16
  /**
13
17
  * One-line top margin between the working/status HUD row and the editor.
@@ -25,4 +29,8 @@ export class EditorTopGap implements Component {
25
29
  render(_width: number): readonly string[] {
26
30
  return composerShape === "band" && this.statusRowOccupied() ? FLUSH : GAP;
27
31
  }
32
+
33
+ describe(): NativeNode {
34
+ return NATIVE_GAP;
35
+ }
28
36
  }
@@ -96,10 +96,27 @@ export class MacOSSpellingProvider implements EditorTextAssistProvider {
96
96
  context: SpellingDecorationContext,
97
97
  decorate: (span: string) => string = value => value,
98
98
  ): string {
99
- if (!this.#available || !this.#features.typoDetection || text.length === 0) return decorate(text);
100
- if (!this.#prose.isProse(context, context.startCol, context.startCol + text.length)) {
101
- return decorate(text);
99
+ const ranges = this.typoRanges(text, context);
100
+ if (ranges.length === 0) return decorate(text);
101
+ let rendered = "";
102
+ let cursor = 0;
103
+ for (const range of ranges) {
104
+ const end = range.start + range.length;
105
+ rendered += decorate(text.slice(cursor, range.start));
106
+ rendered += this.#marks.start + decorate(text.slice(range.start, end)) + this.#marks.end;
107
+ cursor = end;
102
108
  }
109
+ return rendered + decorate(text.slice(cursor));
110
+ }
111
+
112
+ /**
113
+ * Misspelled prose ranges in `text` (offsets into it), in order and
114
+ * non-overlapping. Schedules the verification check for uncached text; its
115
+ * result arrives through {@link onUpdate}.
116
+ */
117
+ typoRanges(text: string, context: SpellingDecorationContext): readonly native.SpellingRange[] {
118
+ if (!this.#available || !this.#features.typoDetection || text.length === 0) return [];
119
+ if (!this.#prose.isProse(context, context.startCol, context.startCol + text.length)) return [];
103
120
  const lane = `${context.line}:${context.startCol}`;
104
121
  const cached = this.#typoCache.get(text);
105
122
  // A cache hit obsoletes any older text queued for this lane. A miss must
@@ -110,9 +127,8 @@ export class MacOSSpellingProvider implements EditorTextAssistProvider {
110
127
  if (cached === undefined) this.#scheduleTypoRanges(text, lane);
111
128
  else this.#automaticTypoQueue.delete(lane);
112
129
  const ranges = cached ?? this.#projectTypoRanges(text);
113
- if (!ranges) return decorate(text);
114
- if (ranges.length === 0) return decorate(text);
115
- let rendered = "";
130
+ if (!ranges || ranges.length === 0) return [];
131
+ const kept: native.SpellingRange[] = [];
116
132
  let cursor = 0;
117
133
  for (const range of ranges) {
118
134
  const end = range.start + range.length;
@@ -123,11 +139,10 @@ export class MacOSSpellingProvider implements EditorTextAssistProvider {
123
139
  if (!this.#prose.isProse(context, context.startCol + range.start, context.startCol + end)) {
124
140
  continue;
125
141
  }
126
- rendered += decorate(text.slice(cursor, range.start));
127
- rendered += this.#marks.start + decorate(text.slice(range.start, end)) + this.#marks.end;
142
+ kept.push(range);
128
143
  cursor = end;
129
144
  }
130
- return rendered + decorate(text.slice(cursor));
145
+ return kept;
131
146
  }
132
147
 
133
148
  /** Return the confident macOS correction after a completed prose word. */
@@ -1,5 +1,5 @@
1
1
  import { createGradientHighlighter, type KeywordHighlighter } from "./gradient-highlight";
2
- import { keywordInProse } from "./markdown-prose";
2
+ import { keywordInProse, maskNonProse } from "./markdown-prose";
3
3
 
4
4
  /**
5
5
  * Magic-keyword engine: standalone prose words the host registers via
@@ -39,6 +39,8 @@ function magicKeywordRegex(word: string, flags = ""): RegExp {
39
39
  interface RegisteredKeyword {
40
40
  readonly word: string;
41
41
  readonly highlight: KeywordHighlighter;
42
+ /** Global standalone-prose matcher, walked over masked text. */
43
+ readonly pattern: RegExp;
42
44
  }
43
45
 
44
46
  let registry: readonly RegisteredKeyword[] = [];
@@ -62,6 +64,7 @@ function matcherFor(word: string): RegExp {
62
64
  export function setMagicKeywords(specs: readonly MagicKeywordSpec[]): void {
63
65
  registry = specs.map(({ word, hue: [from, to] }) => ({
64
66
  word,
67
+ pattern: magicKeywordRegex(word, "g"),
65
68
  highlight: createGradientHighlighter({
66
69
  probe: word,
67
70
  highlight: magicKeywordRegex(word, "g"),
@@ -110,6 +113,24 @@ export function highlightMagicKeywords(text: string, resetTo?: string, phase?: n
110
113
  return out;
111
114
  }
112
115
 
116
+ /**
117
+ * UTF-16 ranges of every registered keyword standing as prose in `text`
118
+ * (never inside code or XML/HTML sections), for decorating the keywords
119
+ * without painting them: a TSP terminal draws the gradient sweep itself.
120
+ */
121
+ export function magicKeywordRanges(text: string): { from: number; to: number }[] {
122
+ const ranges: { from: number; to: number }[] = [];
123
+ let masked: string | undefined;
124
+ for (const keyword of registry) {
125
+ if (!text.includes(keyword.word)) continue;
126
+ masked ??= maskNonProse(text);
127
+ for (const match of masked.matchAll(keyword.pattern)) {
128
+ ranges.push({ from: match.index, to: match.index + match[0].length });
129
+ }
130
+ }
131
+ return ranges.sort((a, b) => a.from - b.from);
132
+ }
133
+
113
134
  /**
114
135
  * Cheap test for "does this text contain any registered keyword as standalone
115
136
  * prose?". Short-circuits on a substring probe before paying for the
@@ -50,6 +50,7 @@ export function getModelMentionSuggestions(
50
50
  label: item.selector,
51
51
  description: modelMentionDisplayName(item.model),
52
52
  icon: theme.symbol("icon.model"),
53
+ iconName: "model",
53
54
  }));
54
55
  return items.length > 0 ? { items, prefix } : null;
55
56
  }
@@ -0,0 +1,101 @@
1
+ import { Container } from "../tui";
2
+ import { Spacer } from "../components/spacer";
3
+ import { TruncatedText } from "../components/truncated-text";
4
+ import { formatKeyHint } from "../key-hint-format";
5
+ import type { KeyId } from "../keys";
6
+ import { kbd, node, text } from "../native/describe";
7
+ import type { NativeNode, NativeUiEvent } from "../native/node";
8
+ import { replaceTabs } from "../utils";
9
+ import { theme } from "../theme/theme";
10
+
11
+ /** Queued messages under one heading ("Steering", "After yield"). */
12
+ export interface QueuedMessageGroup {
13
+ readonly label: string;
14
+ readonly messages: readonly string[];
15
+ }
16
+
17
+ /**
18
+ * Messages queued while the agent works, above the editor. ANSI: a heading
19
+ * per group, numbered dim rows and the dequeue hint. Natively (§8.1): a
20
+ * stack of pills, each `corner-down-right` · the text · `⌥↑ Edit`, the total
21
+ * count in the first pill when more than one waits; the edit control sends
22
+ * `queue.edit`, answered like the dequeue key.
23
+ */
24
+ export class QueuedMessagesBand extends Container {
25
+ readonly #native: NativeNode;
26
+
27
+ constructor(
28
+ groups: readonly QueuedMessageGroup[],
29
+ dequeueKey: KeyId,
30
+ private readonly onEdit: () => void,
31
+ ) {
32
+ super();
33
+ this.addChild(new Spacer(1));
34
+ for (const group of groups) {
35
+ const heading = theme.fg("muted", `${group.label}${theme.sep.dot}${group.messages.length}`);
36
+ this.addChild(new TruncatedText(heading, 1, 0));
37
+ for (let index = 0; index < group.messages.length; index++) {
38
+ const message = replaceTabs(group.messages[index] ?? "").replace(/\r?\n/g, " ↵ ");
39
+ this.addChild(new TruncatedText(theme.fg("dim", ` ${index + 1}. ${message}`), 1, 0));
40
+ }
41
+ }
42
+ const editKey = formatKeyHint(dequeueKey);
43
+ this.addChild(new TruncatedText(theme.fg("dim", ` ${theme.tree.hook} ${editKey} to edit`), 1, 0));
44
+
45
+ const count = groups.reduce((sum, group) => sum + group.messages.length, 0);
46
+ const pills: NativeNode[] = [];
47
+ for (const group of groups) {
48
+ group.messages.forEach((message, index) => {
49
+ const children: NativeNode[] = [
50
+ node("icon", { name: "corner-down-right" }, undefined, "icon"),
51
+ node(
52
+ "text",
53
+ {
54
+ text: replaceTabs(message).replace(/\s*\r?\n\s*/g, " ↵ "),
55
+ wrap: "none",
56
+ truncate: "end",
57
+ grow: 1,
58
+ },
59
+ undefined,
60
+ "text",
61
+ ),
62
+ ];
63
+ if (pills.length === 0 && count > 1) {
64
+ children.push(node("badge", { text: `${count}`, role: "omp.queue.count" }, undefined, "count"));
65
+ }
66
+ children.push(
67
+ node(
68
+ "row",
69
+ {
70
+ role: "omp.queue.edit",
71
+ gap: "xs",
72
+ align: "center",
73
+ title: `Edit ${editKey}`,
74
+ actions: { click: "queue.edit" },
75
+ },
76
+ [kbd(dequeueKey), text("Edit")],
77
+ "edit",
78
+ ),
79
+ );
80
+ pills.push(
81
+ node(
82
+ "row",
83
+ { role: "omp.queue.item", align: "center", gap: "sm", title: group.label },
84
+ children,
85
+ `${group.label}/${index}`,
86
+ ),
87
+ );
88
+ });
89
+ }
90
+ this.#native = node("col", { role: "omp.queue", gap: "xs" }, pills);
91
+ }
92
+
93
+ override describe(): NativeNode {
94
+ return this.#native;
95
+ }
96
+
97
+ /** The pills' Edit control: the dequeue key's path (queued messages back into the editor). */
98
+ handleNativeEvent(event: NativeUiEvent): void {
99
+ if (event.type === "action" && event.act === "queue.edit") this.onEdit();
100
+ }
101
+ }
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * One `/skill:<name>` token delimited by whitespace or line edges. Group 1 is
3
- * the leading delimiter (empty at line start), group 2 the bare skill name.
4
- * Global so callers can walk every token; reset `lastIndex` before reuse.
3
+ * the leading delimiter (empty at line start), group 2 the skill name: a bare
4
+ * name or a collision-namespaced `<namespace>/<name>` (exactly one `/`; deeper
5
+ * paths never match). Global so callers can walk every token; reset
6
+ * `lastIndex` before reuse.
5
7
  */
6
- export const SKILL_TOKEN_RE = /(^|\s)\/skill:([^\s/]+)(?=\s|$)/g;
8
+ export const SKILL_TOKEN_RE = /(^|\s)\/skill:([^\s/]+(?:\/[^\s/]+)?)(?=\s|$)/g;
7
9
 
8
10
  /**
9
11
  * Whether the (already left-trimmed) draft begins with a TUI local-execution