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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/types/apps/cleanse-board.d.ts +17 -0
  3. package/dist/types/apps/git/help.d.ts +16 -0
  4. package/dist/types/apps/git/sidebar.d.ts +18 -0
  5. package/dist/types/apps/live-visualizer.d.ts +10 -0
  6. package/dist/types/apps/ps-top.d.ts +15 -0
  7. package/dist/types/apps/standalone-picker.d.ts +3 -0
  8. package/dist/types/autocomplete.d.ts +8 -0
  9. package/dist/types/chat/advisor-message.d.ts +12 -2
  10. package/dist/types/chat/assistant-message.d.ts +20 -0
  11. package/dist/types/chat/bash-execution.d.ts +9 -0
  12. package/dist/types/chat/chat-transcript-builder.d.ts +6 -1
  13. package/dist/types/chat/collab-prompt-message.d.ts +4 -0
  14. package/dist/types/chat/compaction-summary-message.d.ts +15 -0
  15. package/dist/types/chat/eval-execution.d.ts +8 -0
  16. package/dist/types/chat/execution-shared.d.ts +58 -0
  17. package/dist/types/chat/late-diagnostics-message.d.ts +15 -1
  18. package/dist/types/chat/read-tool-group.d.ts +15 -0
  19. package/dist/types/chat/skill-message.d.ts +9 -0
  20. package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +3 -0
  21. package/dist/types/chat/thinking-display.d.ts +2 -0
  22. package/dist/types/chat/todo-reminder.d.ts +4 -1
  23. package/dist/types/chat/tool-execution.d.ts +25 -1
  24. package/dist/types/chat/transcript-actions.d.ts +37 -0
  25. package/dist/types/chat/transcript-entry.d.ts +3 -1
  26. package/dist/types/chat/user-message.d.ts +25 -0
  27. package/dist/types/chrome/collab-qrcode.d.ts +7 -0
  28. package/dist/types/chrome/context-thresholds.d.ts +11 -0
  29. package/dist/types/chrome/countdown-timer.d.ts +9 -3
  30. package/dist/types/chrome/diff.d.ts +12 -0
  31. package/dist/types/chrome/dynamic-border.d.ts +3 -0
  32. package/dist/types/chrome/format.d.ts +6 -0
  33. package/dist/types/chrome/message-divider.d.ts +13 -0
  34. package/dist/types/chrome/message-frame.d.ts +10 -0
  35. package/dist/types/chrome/message-notice.d.ts +23 -0
  36. package/dist/types/chrome/overlay-box.d.ts +11 -2
  37. package/dist/types/chrome/qrcode.d.ts +7 -0
  38. package/dist/types/chrome/segment-track.d.ts +7 -0
  39. package/dist/types/chrome/selector-helpers.d.ts +0 -6
  40. package/dist/types/chrome/status-notice.d.ts +14 -0
  41. package/dist/types/chrome/streaming-panel.d.ts +3 -0
  42. package/dist/types/chrome/tool-activity.d.ts +3 -0
  43. package/dist/types/chrome/transcript-container.d.ts +13 -0
  44. package/dist/types/chrome/transcript-status.d.ts +15 -3
  45. package/dist/types/components/box.d.ts +7 -0
  46. package/dist/types/components/disclosure.d.ts +9 -0
  47. package/dist/types/components/editor.d.ts +42 -0
  48. package/dist/types/components/form.d.ts +14 -0
  49. package/dist/types/components/image.d.ts +7 -0
  50. package/dist/types/components/input.d.ts +20 -1
  51. package/dist/types/components/key-value-list.d.ts +3 -0
  52. package/dist/types/components/layout/geometry.d.ts +16 -0
  53. package/dist/types/components/layout/row.d.ts +7 -0
  54. package/dist/types/components/layout/split-pane.d.ts +8 -0
  55. package/dist/types/components/layout/stack.d.ts +6 -0
  56. package/dist/types/components/loader.d.ts +48 -0
  57. package/dist/types/components/markdown.d.ts +8 -0
  58. package/dist/types/components/metric.d.ts +7 -0
  59. package/dist/types/components/progress-bar.d.ts +3 -0
  60. package/dist/types/components/scroll-view.d.ts +6 -0
  61. package/dist/types/components/section.d.ts +3 -0
  62. package/dist/types/components/select-list.d.ts +33 -0
  63. package/dist/types/components/settings-list.d.ts +68 -0
  64. package/dist/types/components/spacer.d.ts +4 -0
  65. package/dist/types/components/tab-bar.d.ts +9 -0
  66. package/dist/types/components/table.d.ts +7 -0
  67. package/dist/types/components/text.d.ts +6 -0
  68. package/dist/types/components/tree-view.d.ts +9 -0
  69. package/dist/types/components/truncated-text.d.ts +3 -0
  70. package/dist/types/components/wizard-step.d.ts +6 -0
  71. package/dist/types/hotkeys-markdown.d.ts +24 -0
  72. package/dist/types/index.d.ts +5 -0
  73. package/dist/types/latex-block.d.ts +7 -0
  74. package/dist/types/loop-watchdog.d.ts +9 -0
  75. package/dist/types/native/apply.d.ts +39 -0
  76. package/dist/types/native/backend.d.ts +94 -0
  77. package/dist/types/native/blobs.d.ts +29 -0
  78. package/dist/types/native/describe.d.ts +56 -0
  79. package/dist/types/native/encode.d.ts +50 -0
  80. package/dist/types/native/icons.d.ts +18 -0
  81. package/dist/types/native/memo.d.ts +27 -0
  82. package/dist/types/native/node.d.ts +107 -0
  83. package/dist/types/native/overlay.d.ts +64 -0
  84. package/dist/types/native/picker.d.ts +124 -0
  85. package/dist/types/native/reconcile.d.ts +41 -0
  86. package/dist/types/native/settle.d.ts +11 -0
  87. package/dist/types/native/spans.d.ts +21 -0
  88. package/dist/types/native/state.d.ts +6 -0
  89. package/dist/types/native/tone.d.ts +24 -0
  90. package/dist/types/overlays/advisor-config.d.ts +20 -0
  91. package/dist/types/overlays/agent-hub-renderer.d.ts +27 -11
  92. package/dist/types/overlays/agent-hub.d.ts +10 -0
  93. package/dist/types/overlays/agent-transcript-viewer.d.ts +7 -0
  94. package/dist/types/overlays/agents-hub.d.ts +8 -0
  95. package/dist/types/overlays/annotation-overlay.d.ts +3 -0
  96. package/dist/types/overlays/ask-dialog.d.ts +23 -0
  97. package/dist/types/overlays/bordered-loader.d.ts +3 -0
  98. package/dist/types/overlays/btw-history-panel.d.ts +9 -0
  99. package/dist/types/overlays/btw-panel.d.ts +3 -0
  100. package/dist/types/overlays/cleanse-panel.d.ts +5 -2
  101. package/dist/types/overlays/composer-shape-preview.d.ts +7 -1
  102. package/dist/types/overlays/copy-selector.d.ts +38 -0
  103. package/dist/types/overlays/error-banner.d.ts +9 -0
  104. package/dist/types/overlays/extensions/extension-list.d.ts +1 -0
  105. package/dist/types/overlays/history-search.d.ts +18 -0
  106. package/dist/types/overlays/hook-editor.d.ts +28 -1
  107. package/dist/types/overlays/hook-input.d.ts +3 -0
  108. package/dist/types/overlays/hook-selector.d.ts +10 -0
  109. package/dist/types/overlays/hub-frame.d.ts +18 -0
  110. package/dist/types/overlays/jobs-panel.d.ts +24 -0
  111. package/dist/types/overlays/login-dialog.d.ts +10 -0
  112. package/dist/types/overlays/logout-account-selector.d.ts +4 -0
  113. package/dist/types/overlays/mcp-add-wizard.d.ts +4 -0
  114. package/dist/types/overlays/model-browser.d.ts +69 -0
  115. package/dist/types/overlays/model-hub.d.ts +7 -0
  116. package/dist/types/overlays/model-picker.d.ts +9 -1
  117. package/dist/types/overlays/move-overlay.d.ts +3 -0
  118. package/dist/types/overlays/oauth-selector.d.ts +4 -0
  119. package/dist/types/overlays/omfg-panel.d.ts +3 -0
  120. package/dist/types/overlays/pause-screen.d.ts +12 -0
  121. package/dist/types/overlays/plan-review-overlay.d.ts +5 -0
  122. package/dist/types/overlays/plan-save-overlay.d.ts +10 -0
  123. package/dist/types/overlays/plugin-selector.d.ts +4 -0
  124. package/dist/types/overlays/plugin-settings.d.ts +30 -0
  125. package/dist/types/overlays/queue-mode-selector.d.ts +4 -0
  126. package/dist/types/overlays/reset-usage-selector.d.ts +8 -0
  127. package/dist/types/overlays/rewind-selector.d.ts +5 -0
  128. package/dist/types/overlays/session-info-overlay.d.ts +19 -1
  129. package/dist/types/overlays/session-selector.d.ts +64 -1
  130. package/dist/types/overlays/settings-defs.d.ts +14 -0
  131. package/dist/types/overlays/settings-selector.d.ts +21 -0
  132. package/dist/types/overlays/show-images-selector.d.ts +4 -0
  133. package/dist/types/overlays/snapcompact-shape-preview.d.ts +2 -0
  134. package/dist/types/overlays/stats-notice.d.ts +8 -0
  135. package/dist/types/overlays/theme-selector.d.ts +11 -0
  136. package/dist/types/overlays/thinking-selector.d.ts +4 -0
  137. package/dist/types/overlays/tree-selector.d.ts +60 -2
  138. package/dist/types/overlays/usage-dashboard.d.ts +26 -3
  139. package/dist/types/overlays/usage-row.d.ts +36 -2
  140. package/dist/types/prompt/attachment-chips.d.ts +8 -0
  141. package/dist/types/prompt/composer-attachments.d.ts +15 -3
  142. package/dist/types/prompt/composer.d.ts +18 -1
  143. package/dist/types/prompt/custom-editor.d.ts +48 -2
  144. package/dist/types/prompt/editor-top-gap.d.ts +2 -0
  145. package/dist/types/prompt/macos-spelling.d.ts +6 -0
  146. package/dist/types/prompt/magic-keywords.d.ts +9 -0
  147. package/dist/types/prompt/queued-messages.d.ts +23 -0
  148. package/dist/types/prompt/skill-tokens.d.ts +4 -2
  149. package/dist/types/prompt/welcome.d.ts +16 -0
  150. package/dist/types/render/code-cell.d.ts +10 -0
  151. package/dist/types/render/file-list.d.ts +8 -0
  152. package/dist/types/render/hyperlink.d.ts +14 -0
  153. package/dist/types/render/output-block.d.ts +43 -0
  154. package/dist/types/render/output-pane.d.ts +17 -0
  155. package/dist/types/render/tool-card.d.ts +8 -0
  156. package/dist/types/render/tree-list.d.ts +8 -0
  157. package/dist/types/render/width-aware-text.d.ts +7 -0
  158. package/dist/types/setup/scenes/outro.d.ts +7 -0
  159. package/dist/types/setup/scenes/sign-in.d.ts +16 -9
  160. package/dist/types/setup/scenes/splash.d.ts +8 -0
  161. package/dist/types/setup/scenes/types.d.ts +6 -27
  162. package/dist/types/setup/wizard-overlay.d.ts +9 -0
  163. package/dist/types/status-line/component.d.ts +49 -5
  164. package/dist/types/status-line/context-usage.d.ts +20 -0
  165. package/dist/types/status-line/footer.d.ts +8 -0
  166. package/dist/types/status-line/metrics.d.ts +1 -2
  167. package/dist/types/status-line/segments.d.ts +10 -1
  168. package/dist/types/status-line/types.d.ts +40 -1
  169. package/dist/types/stdin-buffer.d.ts +10 -7
  170. package/dist/types/terminal-capabilities.d.ts +1 -1
  171. package/dist/types/terminal.d.ts +36 -0
  172. package/dist/types/theme/defaults/index.d.ts +100 -0
  173. package/dist/types/theme/schema.d.ts +2 -0
  174. package/dist/types/theme/shimmer.d.ts +8 -0
  175. package/dist/types/theme/theme-class.d.ts +2 -0
  176. package/dist/types/theme/theme.d.ts +33 -1
  177. package/dist/types/tools/ask.d.ts +3 -0
  178. package/dist/types/tools/ast-edit.d.ts +10 -1
  179. package/dist/types/tools/ast-grep.d.ts +10 -1
  180. package/dist/types/tools/autoresearch.d.ts +21 -4
  181. package/dist/types/tools/bash.d.ts +30 -1
  182. package/dist/types/tools/cfg-render.d.ts +5 -1
  183. package/dist/types/tools/debug.d.ts +3 -1
  184. package/dist/types/tools/default-renderer.d.ts +6 -1
  185. package/dist/types/tools/edit.d.ts +14 -1
  186. package/dist/types/tools/eval.d.ts +12 -1
  187. package/dist/types/tools/fetch.d.ts +16 -1
  188. package/dist/types/tools/find.d.ts +15 -1
  189. package/dist/types/tools/github.d.ts +3 -0
  190. package/dist/types/tools/glob.d.ts +14 -1
  191. package/dist/types/tools/goal.d.ts +3 -1
  192. package/dist/types/tools/grep.d.ts +14 -1
  193. package/dist/types/tools/grouped-file-output.d.ts +58 -0
  194. package/dist/types/tools/json-tree.d.ts +20 -0
  195. package/dist/types/tools/lsp.d.ts +3 -10
  196. package/dist/types/tools/mcp.d.ts +16 -1
  197. package/dist/types/tools/memory.d.ts +26 -0
  198. package/dist/types/tools/native-view.d.ts +90 -0
  199. package/dist/types/tools/proc-render.d.ts +7 -1
  200. package/dist/types/tools/read.d.ts +23 -1
  201. package/dist/types/tools/renderer.d.ts +57 -0
  202. package/dist/types/tools/report-tool-issue.d.ts +3 -0
  203. package/dist/types/tools/resolve.d.ts +14 -1
  204. package/dist/types/tools/task.d.ts +3 -0
  205. package/dist/types/tools/think.d.ts +3 -0
  206. package/dist/types/tools/todo.d.ts +12 -0
  207. package/dist/types/tools/vibe.d.ts +3 -1
  208. package/dist/types/tools/wait.d.ts +3 -0
  209. package/dist/types/tools/web-search-types.d.ts +90 -0
  210. package/dist/types/tools/web-search.d.ts +9 -168
  211. package/dist/types/tools/write.d.ts +14 -1
  212. package/dist/types/tools/xdev.d.ts +13 -0
  213. package/dist/types/tui.d.ts +49 -0
  214. package/package.json +9 -9
  215. package/src/apps/autoresearch-dashboard.ts +362 -4
  216. package/src/apps/cleanse-board.ts +219 -1
  217. package/src/apps/cleanse-picker.ts +9 -1
  218. package/src/apps/debug/log-viewer.ts +15 -15
  219. package/src/apps/debug/protocol-probe.ts +2 -20
  220. package/src/apps/git/avatar.ts +2 -22
  221. package/src/apps/git/git-tui.ts +406 -59
  222. package/src/apps/git/help.ts +130 -0
  223. package/src/apps/git/sidebar.ts +491 -0
  224. package/src/apps/live-visualizer.ts +65 -0
  225. package/src/apps/ps-top.ts +448 -17
  226. package/src/apps/session-picker.ts +1 -0
  227. package/src/apps/setup-model-picker.ts +5 -1
  228. package/src/apps/standalone-picker.ts +55 -1
  229. package/src/autocomplete.ts +44 -1
  230. package/src/chat/advisor-message.ts +72 -3
  231. package/src/chat/assistant-message.ts +538 -51
  232. package/src/chat/background-tan-message.ts +4 -4
  233. package/src/chat/bash-execution.ts +81 -0
  234. package/src/chat/cache-invalidation-marker.ts +8 -0
  235. package/src/chat/chat-transcript-builder.ts +37 -6
  236. package/src/chat/collab-prompt-message.ts +15 -3
  237. package/src/chat/compaction-summary-message.ts +74 -1
  238. package/src/chat/custom-message.ts +3 -1
  239. package/src/chat/eval-execution.ts +57 -0
  240. package/src/chat/execution-shared.ts +153 -1
  241. package/src/chat/hook-message.ts +1 -0
  242. package/src/chat/late-diagnostics-message.ts +85 -2
  243. package/src/chat/read-tool-group.ts +341 -1
  244. package/src/chat/served-model-marker.ts +8 -0
  245. package/src/chat/skill-message.ts +63 -0
  246. package/src/chat/stripped-tool-calls-placeholder.ts +18 -10
  247. package/src/chat/thinking-display.ts +73 -11
  248. package/src/chat/todo-reminder.ts +34 -4
  249. package/src/chat/tool-execution.ts +385 -10
  250. package/src/chat/transcript-actions.ts +38 -0
  251. package/src/chat/transcript-browser.ts +2 -9
  252. package/src/chat/transcript-entry.ts +10 -1
  253. package/src/chat/transcript-render-helpers.ts +16 -15
  254. package/src/chat/ttsr-notification.ts +38 -1
  255. package/src/chat/user-message.ts +167 -4
  256. package/src/chrome/collab-qrcode.ts +27 -2
  257. package/src/chrome/context-thresholds.ts +34 -0
  258. package/src/chrome/countdown-timer.ts +24 -1
  259. package/src/chrome/diff.ts +60 -1
  260. package/src/chrome/dynamic-border.ts +7 -0
  261. package/src/chrome/format.ts +12 -0
  262. package/src/chrome/message-divider.ts +33 -1
  263. package/src/chrome/message-frame.ts +53 -10
  264. package/src/chrome/message-notice.ts +71 -0
  265. package/src/chrome/overlay-box.ts +45 -2
  266. package/src/chrome/qrcode.ts +28 -0
  267. package/src/chrome/segment-track.ts +26 -0
  268. package/src/chrome/selector-helpers.ts +1 -17
  269. package/src/chrome/status-notice.ts +46 -0
  270. package/src/chrome/streaming-panel.ts +25 -1
  271. package/src/chrome/tool-activity.ts +20 -0
  272. package/src/chrome/transcript-container.ts +139 -17
  273. package/src/chrome/transcript-status.ts +40 -11
  274. package/src/components/box.ts +51 -0
  275. package/src/components/disclosure.ts +33 -0
  276. package/src/components/editor.ts +239 -36
  277. package/src/components/form.ts +93 -9
  278. package/src/components/image.ts +30 -0
  279. package/src/components/input.ts +77 -26
  280. package/src/components/key-value-list.ts +18 -0
  281. package/src/components/layout/geometry.ts +44 -0
  282. package/src/components/layout/row.ts +30 -0
  283. package/src/components/layout/split-pane.ts +65 -0
  284. package/src/components/layout/stack.ts +27 -0
  285. package/src/components/loader.ts +183 -1
  286. package/src/components/markdown.ts +131 -56
  287. package/src/components/metric.ts +39 -0
  288. package/src/components/progress-bar.ts +28 -0
  289. package/src/components/scroll-view.ts +23 -0
  290. package/src/components/section.ts +16 -0
  291. package/src/components/select-list.ts +174 -25
  292. package/src/components/settings-list.ts +264 -7
  293. package/src/components/spacer.ts +17 -0
  294. package/src/components/tab-bar.ts +42 -0
  295. package/src/components/table.ts +34 -0
  296. package/src/components/text.ts +23 -0
  297. package/src/components/tree-view.ts +65 -0
  298. package/src/components/truncated-text.ts +14 -0
  299. package/src/components/wizard-step.ts +18 -9
  300. package/src/debug-server.ts +14 -7
  301. package/src/hotkeys-markdown.ts +251 -69
  302. package/src/index.ts +6 -0
  303. package/src/latex-block.ts +11 -0
  304. package/src/loop-watchdog.ts +38 -10
  305. package/src/native/apply.ts +275 -0
  306. package/src/native/backend.ts +682 -0
  307. package/src/native/blobs.ts +70 -0
  308. package/src/native/describe.ts +124 -0
  309. package/src/native/encode.ts +233 -0
  310. package/src/native/icons.ts +184 -0
  311. package/src/native/memo.ts +64 -0
  312. package/src/native/node.ts +112 -0
  313. package/src/native/overlay.ts +131 -0
  314. package/src/native/picker.ts +333 -0
  315. package/src/native/reconcile.ts +1063 -0
  316. package/src/native/settle.ts +23 -0
  317. package/src/native/spans.ts +308 -0
  318. package/src/native/state.ts +28 -0
  319. package/src/native/tone.ts +79 -0
  320. package/src/overlays/advisor-config.ts +420 -0
  321. package/src/overlays/agent-hub-renderer.ts +155 -18
  322. package/src/overlays/agent-hub.ts +1037 -44
  323. package/src/overlays/agent-transcript-viewer.ts +129 -0
  324. package/src/overlays/agents-hub.ts +688 -53
  325. package/src/overlays/annotation-overlay.ts +391 -52
  326. package/src/overlays/ask-dialog.ts +435 -24
  327. package/src/overlays/bordered-loader.ts +17 -0
  328. package/src/overlays/btw-history-panel.ts +182 -0
  329. package/src/overlays/btw-panel.ts +68 -2
  330. package/src/overlays/cleanse-panel.ts +105 -15
  331. package/src/overlays/codex-reset-fireworks.ts +65 -5
  332. package/src/overlays/composer-shape-preview.ts +26 -1
  333. package/src/overlays/copy-selector.ts +545 -23
  334. package/src/overlays/error-banner.ts +44 -0
  335. package/src/overlays/extensions/extension-list.ts +23 -17
  336. package/src/overlays/history-search.ts +175 -33
  337. package/src/overlays/hook-editor.ts +113 -6
  338. package/src/overlays/hook-input.ts +22 -1
  339. package/src/overlays/hook-selector.ts +311 -22
  340. package/src/overlays/hub-frame.ts +80 -0
  341. package/src/overlays/jobs-panel.ts +112 -0
  342. package/src/overlays/login-dialog.ts +183 -1
  343. package/src/overlays/logout-account-selector.ts +102 -4
  344. package/src/overlays/mcp-add-wizard.ts +232 -53
  345. package/src/overlays/model-browser.ts +681 -22
  346. package/src/overlays/model-hub.ts +1402 -78
  347. package/src/overlays/model-picker.ts +184 -7
  348. package/src/overlays/move-overlay.ts +45 -0
  349. package/src/overlays/oauth-selector.ts +227 -23
  350. package/src/overlays/omfg-panel.ts +86 -2
  351. package/src/overlays/pause-screen.ts +55 -4
  352. package/src/overlays/plan-review-overlay.ts +352 -0
  353. package/src/overlays/plan-save-overlay.ts +45 -0
  354. package/src/overlays/plugin-selector.ts +21 -1
  355. package/src/overlays/plugin-settings.ts +195 -5
  356. package/src/overlays/queue-mode-selector.ts +19 -1
  357. package/src/overlays/reset-usage-selector.ts +110 -40
  358. package/src/overlays/rewind-selector.ts +458 -44
  359. package/src/overlays/session-account-selector.ts +1 -1
  360. package/src/overlays/session-info-overlay.ts +137 -1
  361. package/src/overlays/session-selector.ts +807 -46
  362. package/src/overlays/settings-defs.ts +41 -0
  363. package/src/overlays/settings-selector.ts +585 -33
  364. package/src/overlays/show-images-selector.ts +18 -1
  365. package/src/overlays/snapcompact-shape-preview.ts +48 -3
  366. package/src/overlays/stats-notice.ts +31 -0
  367. package/src/overlays/theme-selector.ts +31 -1
  368. package/src/overlays/thinking-selector.ts +22 -1
  369. package/src/overlays/tree-selector.ts +570 -110
  370. package/src/overlays/usage-dashboard.ts +587 -12
  371. package/src/overlays/usage-row.ts +161 -25
  372. package/src/prompt/attachment-chips.ts +60 -0
  373. package/src/prompt/composer-attachments.ts +31 -9
  374. package/src/prompt/composer.ts +55 -2
  375. package/src/prompt/custom-editor.ts +302 -4
  376. package/src/prompt/editor-top-gap.ts +8 -0
  377. package/src/prompt/macos-spelling.ts +24 -9
  378. package/src/prompt/magic-keywords.ts +22 -1
  379. package/src/prompt/model-mention-autocomplete.ts +1 -0
  380. package/src/prompt/queued-messages.ts +101 -0
  381. package/src/prompt/skill-tokens.ts +5 -3
  382. package/src/prompt/welcome.ts +213 -6
  383. package/src/render/code-cell.ts +103 -2
  384. package/src/render/file-list.ts +29 -0
  385. package/src/render/hyperlink.ts +32 -0
  386. package/src/render/output-block.ts +110 -0
  387. package/src/render/output-pane.ts +37 -0
  388. package/src/render/tool-card.ts +137 -0
  389. package/src/render/tree-list.ts +39 -0
  390. package/src/render/width-aware-text.ts +20 -0
  391. package/src/setup/scenes/composer.ts +29 -0
  392. package/src/setup/scenes/glyph.ts +15 -0
  393. package/src/setup/scenes/model.ts +36 -8
  394. package/src/setup/scenes/outro.ts +28 -1
  395. package/src/setup/scenes/sign-in.ts +138 -24
  396. package/src/setup/scenes/splash.ts +28 -1
  397. package/src/setup/scenes/theme.ts +88 -3
  398. package/src/setup/scenes/types.ts +7 -28
  399. package/src/setup/startup-splash.ts +46 -9
  400. package/src/setup/wizard-overlay.ts +140 -23
  401. package/src/setup/wizard.ts +1 -1
  402. package/src/status-line/component.ts +414 -18
  403. package/src/status-line/context-usage.ts +279 -50
  404. package/src/status-line/footer.ts +94 -1
  405. package/src/status-line/metrics.ts +3 -6
  406. package/src/status-line/segments.ts +463 -97
  407. package/src/status-line/separators.ts +3 -16
  408. package/src/status-line/types.ts +43 -1
  409. package/src/stdin-buffer.ts +27 -21
  410. package/src/terminal-capabilities.ts +7 -0
  411. package/src/terminal.ts +153 -11
  412. package/src/theme/defaults/dark-neon-noir.json +100 -0
  413. package/src/theme/defaults/index.ts +2 -0
  414. package/src/theme/defaults/light-prism.json +5 -5
  415. package/src/theme/defaults/onyx.json +62 -62
  416. package/src/theme/mermaid-cache.ts +10 -1
  417. package/src/theme/schema.ts +15 -0
  418. package/src/theme/shimmer.ts +33 -0
  419. package/src/theme/theme-class.ts +24 -19
  420. package/src/theme/theme.ts +111 -9
  421. package/src/theme/tui-adapters.ts +14 -1
  422. package/src/tools/ask.ts +157 -1
  423. package/src/tools/ast-edit.ts +174 -1
  424. package/src/tools/ast-grep.ts +82 -2
  425. package/src/tools/autoresearch.ts +149 -1
  426. package/src/tools/bash.ts +233 -62
  427. package/src/tools/cfg-render.ts +66 -1
  428. package/src/tools/debug.ts +78 -1
  429. package/src/tools/default-renderer.ts +35 -1
  430. package/src/tools/edit.ts +357 -31
  431. package/src/tools/eval.ts +257 -1
  432. package/src/tools/fetch.ts +102 -3
  433. package/src/tools/find.ts +127 -1
  434. package/src/tools/github.ts +119 -10
  435. package/src/tools/glob.ts +116 -1
  436. package/src/tools/goal.ts +56 -1
  437. package/src/tools/grep.ts +83 -2
  438. package/src/tools/grouped-file-output.ts +205 -0
  439. package/src/tools/json-tree.ts +116 -1
  440. package/src/tools/lsp.ts +318 -1
  441. package/src/tools/mcp.ts +80 -1
  442. package/src/tools/memory.ts +93 -11
  443. package/src/tools/native-view.ts +292 -0
  444. package/src/tools/proc-render.ts +221 -1
  445. package/src/tools/read.ts +199 -4
  446. package/src/tools/renderer.ts +61 -0
  447. package/src/tools/report-tool-issue.ts +7 -1
  448. package/src/tools/resolve.ts +63 -1
  449. package/src/tools/streaming-output.ts +79 -16
  450. package/src/tools/task.ts +406 -4
  451. package/src/tools/think.ts +19 -1
  452. package/src/tools/todo.ts +89 -0
  453. package/src/tools/vibe.ts +230 -2
  454. package/src/tools/wait.ts +181 -1
  455. package/src/tools/web-search-types.ts +99 -0
  456. package/src/tools/web-search.ts +111 -170
  457. package/src/tools/write.ts +144 -5
  458. package/src/tools/xdev.ts +64 -1
  459. package/src/tui.ts +295 -4
  460. package/dist/types/setup/scenes/providers.d.ts +0 -3
  461. package/dist/types/setup/scenes/web-search.d.ts +0 -22
  462. package/src/setup/scenes/providers.ts +0 -110
  463. package/src/setup/scenes/web-search.ts +0 -165
@@ -1,4 +1,4 @@
1
- import type { ToolRenderer } from "./renderer";
1
+ import type { NativeToolView, ToolRenderer, ToolRenderResult } from "./renderer";
2
2
  /**
3
3
  * Web Search TUI Rendering
4
4
  *
@@ -22,6 +22,12 @@ import {
22
22
  } from "../render/render-utils";
23
23
  import { renderStatusLine, renderTreeList, urlHyperlink } from "../render";
24
24
  import { framedToolCard } from "../render/tool-card";
25
+ import { getSearchProviderLabel, type SearchResponse } from "./web-search-types";
26
+ import { compact, md, node, span, text } from "../native/describe";
27
+ import type { NativeChild } from "../native/node";
28
+ import { OwnerMemo } from "../native/memo";
29
+ import { plainText } from "../native/spans";
30
+ import { errorText, noteText, resultText } from "./native-view";
25
31
 
26
32
  const MAX_COLLAPSED_ITEMS = PREVIEW_LIMITS.COLLAPSED_ITEMS;
27
33
 
@@ -240,181 +246,116 @@ export function renderSearchCall(
240
246
  return new Text(text, 0, 0);
241
247
  }
242
248
 
243
- /** Render web search queries, answers, and cited sources. */
244
- export const webSearchToolRenderer = {
245
- renderCall: renderSearchCall,
246
- renderResult: renderSearchResult,
247
- mergeCallAndResult: true,
248
- } satisfies ToolRenderer<{ query?: string; [key: string]: unknown }, SearchRenderDetails>;
249
+ type SearchRenderArgs = { query?: string; [key: string]: unknown };
249
250
 
250
- /**
251
- * Web Search Types
252
- *
253
- * Unified types for web search responses across supported providers.
254
- */
251
+ const SEARCH_TITLE = "Web search";
255
252
 
256
- export const SEARCH_PROVIDER_OPTIONS = [
257
- {
258
- value: "auto",
259
- label: "Auto",
260
- description: "Automatically uses the first configured web-search provider",
261
- },
262
- {
263
- value: "parallel",
264
- label: "Parallel",
265
- description: "Uses API auth when configured; otherwise searches through the keyless public MCP",
266
- },
267
- {
268
- value: "perplexity",
269
- label: "Perplexity",
270
- description: "Uses auth when configured; explicit selection falls back to anonymous search",
271
- },
272
- {
273
- value: "gemini",
274
- label: "Gemini",
275
- description: "Google Search grounding via Gemini (uses google-gemini-cli or google-antigravity OAuth)",
276
- },
277
- {
278
- value: "anthropic",
279
- label: "Anthropic",
280
- description: "Claude's native web_search tool (uses Anthropic OAuth or ANTHROPIC_API_KEY)",
281
- },
282
- {
283
- value: "codex",
284
- label: "OpenAI Codex",
285
- description: "OpenAI's native web_search (uses ChatGPT OAuth via /login openai-codex)",
286
- },
287
- {
288
- value: "openai",
289
- label: "OpenAI API",
290
- description:
291
- "OpenAI hosted web_search via OPENAI_API_KEY or OpenAI API-key registry credentials; billed by API usage",
292
- },
293
- {
294
- value: "xai",
295
- label: "xAI",
296
- description:
297
- "Grok web search via xAI Responses API (uses SuperGrok/X Premium+ OAuth via /login xai-oauth, or XAI_API_KEY)",
298
- },
299
- {
300
- value: "openrouter",
301
- label: "OpenRouter",
302
- description: "OpenRouter plugins-based web search with model-selected grounding",
303
- },
304
- { value: "zai", label: "Z.AI", description: "Calls Z.AI webSearchPrime MCP" },
305
- { value: "exa", label: "Exa", description: "API via /login exa or EXA_API_KEY; explicit keyless fallback via MCP" },
306
- { value: "tinyfish", label: "TinyFish", description: "Requires TINYFISH_API_KEY" },
307
- { value: "jina", label: "Jina", description: "Requires JINA_API_KEY" },
308
- { value: "kagi", label: "Kagi", description: "Requires KAGI_API_KEY and Kagi Search API beta access" },
309
- { value: "tavily", label: "Tavily", description: "Requires TAVILY_API_KEY" },
310
- {
311
- value: "firecrawl",
312
- label: "Firecrawl",
313
- description: "Uses Firecrawl API when FIRECRAWL_API_KEY is set; falls back to keyless mode",
314
- },
315
- { value: "brave", label: "Brave", description: "Requires BRAVE_API_KEY" },
316
- {
317
- value: "kimi",
318
- label: "Kimi",
319
- description:
320
- "Kimi Code search (requires a Kimi Code Console key via KIMI_SEARCH_API_KEY/MOONSHOT_SEARCH_API_KEY or /login kimi-code; not MOONSHOT_API_KEY)",
321
- },
322
- { value: "synthetic", label: "Synthetic", description: "Requires SYNTHETIC_API_KEY" },
323
- { value: "ollama", label: "Ollama", description: "Requires OLLAMA_CLOUD_API_KEY" },
324
- { value: "searxng", label: "SearXNG", description: "Requires SEARXNG_ENDPOINT or searxng.endpoint" },
325
- {
326
- value: "startpage",
327
- label: "Startpage",
328
- description: "Credential-free scrape of Startpage (Google-backed) results; may be bot-challenged",
329
- },
330
- {
331
- value: "duckduckgo",
332
- label: "DuckDuckGo",
333
- description: "Credential-free best-effort fallback; may be bot-challenged on datacenter/shared-egress IPs",
334
- },
335
- {
336
- value: "ecosia",
337
- label: "Ecosia",
338
- description: "Credential-free browser-backed scrape of Ecosia (Google-backed) results",
339
- },
340
- {
341
- value: "google",
342
- label: "Google",
343
- description: "Credential-free browser-backed fallback; slower and may be bot-challenged",
344
- },
345
- {
346
- value: "mojeek",
347
- label: "Mojeek",
348
- description: "Credential-free browser-backed scrape of Mojeek's independent index",
349
- },
350
- {
351
- value: "public",
352
- label: "Public Web",
353
- description: "Queries every credential-free engine in parallel and consolidates deduplicated results",
354
- },
355
- ] as const;
356
-
357
- /** Supported web search providers (every option except `auto`). */
358
- export type SearchProviderId = Exclude<(typeof SEARCH_PROVIDER_OPTIONS)[number]["value"], "auto">;
359
-
360
- /** Display labels, derived from {@link SEARCH_PROVIDER_OPTIONS}. */
361
- export const SEARCH_PROVIDER_LABELS = Object.fromEntries(
362
- SEARCH_PROVIDER_OPTIONS.flatMap(option => (option.value === "auto" ? [] : [[option.value, option.label] as const])),
363
- ) as Record<SearchProviderId, string>;
364
-
365
- /** Source returned by search (all providers) */
366
- export interface SearchSource {
367
- title: string;
368
- url: string;
369
- snippet?: string;
370
- /** ISO date string or relative ("2d ago") */
371
- publishedDate?: string;
372
- /** Age in seconds for consistent formatting */
373
- ageSeconds?: number;
374
- author?: string;
253
+ function searchHead(query: string | undefined, meta?: string, badge?: { text: string; title?: string }) {
254
+ return {
255
+ title: SEARCH_TITLE,
256
+ target: query ? plainText(query) : undefined,
257
+ targetKind: "query" as const,
258
+ meta: meta ? [meta] : undefined,
259
+ badges: badge ? [badge] : undefined,
260
+ };
375
261
  }
376
262
 
377
- /** Citation with text reference (LLM-mediated providers) */
378
- export interface SearchCitation {
379
- url: string;
380
- title: string;
381
- citedText?: string;
263
+ /** One cited source row: domain-initial mark, linked title, muted `domain · age`. */
264
+ function sourceRow(src: SearchResponse["sources"][number], index: number): NativeChild {
265
+ const url = typeof src.url === "string" ? src.url : "";
266
+ const title = typeof src.title === "string" && src.title.trim() ? src.title : url.trim() ? url : "Untitled";
267
+ const domain = url ? getDomain(url) : "";
268
+ const age =
269
+ formatAge(src.ageSeconds).replace(/ ago$/, "") ||
270
+ (typeof src.publishedDate === "string" ? src.publishedDate : "");
271
+ const meta = [domain, age].filter(Boolean).join(" · ");
272
+ const initial = (domain.replace(/^www\./, "")[0] ?? "?").toUpperCase();
273
+ return node(
274
+ "row",
275
+ { gap: "sm", align: "baseline", role: "omp.tool.source", href: url || undefined },
276
+ compact([
277
+ node("badge", { text: initial, title: domain || undefined }),
278
+ text([span(plainText(title), "link", url ? { href: url } : undefined)], { lines: 1, truncate: "end" }),
279
+ meta ? text([span(plainText(meta), "muted")], { lines: 1 }) : undefined,
280
+ ]),
281
+ `${index}:${url}`,
282
+ );
382
283
  }
383
284
 
384
- /** Usage metrics */
385
- export interface SearchUsage {
386
- inputTokens?: number;
387
- outputTokens?: number;
388
- /** Anthropic: number of web search requests made */
389
- searchRequests?: number;
390
- /** Perplexity: combined token count */
391
- totalTokens?: number;
392
- }
285
+ function describeSearchResult(
286
+ result: ToolRenderResult<SearchRenderDetails>,
287
+ args: SearchRenderArgs | undefined,
288
+ ): NativeToolView {
289
+ const details = result.details;
290
+ const argQuery = typeof args?.query === "string" ? args.query : undefined;
291
+ if (details?.error) {
292
+ const provider = details.response?.provider;
293
+ const label = provider && provider !== "none" ? getSearchProviderLabel(provider) : undefined;
294
+ return {
295
+ tool: searchHead(argQuery, label),
296
+ tone: "error",
297
+ body: [errorText(plainText(details.error).trim() || "Web search failed")],
298
+ };
299
+ }
393
300
 
394
- /** Unified response across providers */
395
- export interface SearchResponse {
396
- provider: SearchProviderId | "none";
397
- /** Synthesized answer text (LLM-mediated providers) */
398
- answer?: string;
399
- /** Search result sources */
400
- sources: SearchSource[];
401
- /** Text citations with context */
402
- citations?: SearchCitation[];
403
- /** Intermediate search queries (anthropic) */
404
- searchQueries?: string[];
405
- /** Follow-up question suggestions (provider-dependent) */
406
- relatedQuestions?: string[];
407
- /** Token usage metrics */
408
- usage?: SearchUsage;
409
- /** Model used */
410
- model?: string;
411
- /** Request ID for debugging */
412
- requestId?: string;
413
- /** Authentication mode used by the provider (e.g. oauth, api-key) */
414
- authMode?: string;
415
- }
301
+ const rawText = resultText(result).trim();
302
+ const response = details?.response;
303
+ if (!response) {
304
+ return {
305
+ tool: searchHead(argQuery),
306
+ tone: "warning",
307
+ body: [noteText(rawText || "No response data")],
308
+ };
309
+ }
310
+
311
+ const sources = Array.isArray(response.sources) ? response.sources : [];
312
+ const searchQueries = Array.isArray(response.searchQueries)
313
+ ? response.searchQueries.filter(entry => typeof entry === "string")
314
+ : [];
315
+ const providerLabel = response.provider !== "none" ? getSearchProviderLabel(response.provider) : "None";
316
+ const query = argQuery || searchQueries[0];
317
+ const answer = (typeof response.answer === "string" ? response.answer.trim() : "") || rawText;
416
318
 
417
- /** Cheap, sync metadata accessor — never triggers a provider load. */
418
- export function getSearchProviderLabel(id: SearchProviderId): string {
419
- return SEARCH_PROVIDER_LABELS[id] ?? id;
319
+ const authShort =
320
+ response.authMode === "oauth" ? "OAuth" : response.authMode === "api_key" ? "API" : response.authMode;
321
+ let providerInfo = response.model ? `${response.model} @ ${providerLabel}` : providerLabel;
322
+ if (authShort) providerInfo += ` (${authShort})`;
323
+ const usage = response.usage;
324
+ const usageParts: string[] = [];
325
+ if (usage?.inputTokens !== undefined) usageParts.push(`in ${usage.inputTokens}`);
326
+ if (usage?.outputTokens !== undefined) usageParts.push(`out ${usage.outputTokens}`);
327
+ if (usage?.totalTokens !== undefined) usageParts.push(`total ${usage.totalTokens}`);
328
+ if (usage?.searchRequests !== undefined) usageParts.push(`search ${usage.searchRequests}`);
329
+ const tooltip = plainText([providerInfo, usageParts.join(" · ")].filter(Boolean).join("\n"));
330
+ const badge = response.model ? { text: plainText(response.model), title: tooltip } : undefined;
331
+
332
+ return {
333
+ tool: searchHead(query, `${providerLabel} · ${formatCount("source", sources.length)}`, badge),
334
+ tone: sources.length > 0 ? undefined : "warning",
335
+ body: compact([
336
+ answer ? { ...md(plainText(answer), { title: tooltip }), key: "answer" } : noteText("No answer text returned"),
337
+ sources.length > 0
338
+ ? node("col", { role: "omp.tool.files" }, sources.map(sourceRow), "sources")
339
+ : noteText("No sources returned"),
340
+ ]),
341
+ };
420
342
  }
343
+
344
+ const searchResultMemo = new OwnerMemo<NativeToolView | undefined>();
345
+
346
+ /** Render web search queries, answers, and cited sources. */
347
+ export const webSearchToolRenderer = {
348
+ renderCall: renderSearchCall,
349
+ renderResult: renderSearchResult,
350
+ describeCall(args: SearchRenderArgs): NativeToolView {
351
+ return { tool: searchHead(typeof args.query === "string" ? args.query : undefined), inline: true };
352
+ },
353
+ describeResult(
354
+ result: ToolRenderResult<SearchRenderDetails>,
355
+ _options: RenderResultOptions,
356
+ args?: SearchRenderArgs,
357
+ ): NativeToolView | undefined {
358
+ return searchResultMemo.get(result, [args?.query ?? ""], () => describeSearchResult(result, args));
359
+ },
360
+ mergeCallAndResult: true,
361
+ } satisfies ToolRenderer<{ query?: string; [key: string]: unknown }, SearchRenderDetails>;
@@ -22,23 +22,47 @@ import {
22
22
  truncateToWidth,
23
23
  } from "../render/render-utils";
24
24
  import type { CoordinationDetails } from "./wait";
25
- import { renderAgentWrite, renderProcWrite, type ProcWriteAction, type ProcWriteDetails } from "./proc-render";
26
- import { renderCfgWrite, type CfgWriteDetails } from "./cfg-render";
25
+ import {
26
+ describeAgentWrite,
27
+ describeProcWrite,
28
+ renderAgentWrite,
29
+ renderProcWrite,
30
+ type ProcWriteAction,
31
+ type ProcWriteDetails,
32
+ } from "./proc-render";
33
+ import type { TspTone } from "@oh-my-pi/pi-wire";
34
+ import { code, compact, node, span } from "../native/describe";
35
+ import type { NativeChild } from "../native/node";
36
+ import { diagnosticsBadge, diagnosticsSection, displayPath, errorText, fileHref, resultText } from "./native-view";
37
+ import { describeCfgWrite, renderCfgWrite, type CfgWriteDetails } from "./cfg-render";
27
38
  import type { FileDiagnosticsResult } from "./lsp";
28
39
  import type { OutputMeta } from "./output-meta";
29
40
  import type { CardToolResult } from "./result-card";
30
- import type { RenderResultOptions, ToolActivityContext, ToolActivitySummary, ToolRenderer } from "./renderer";
41
+ import type {
42
+ NativeToolHead,
43
+ NativeToolView,
44
+ RenderResultOptions,
45
+ ToolActivityContext,
46
+ ToolActivitySummary,
47
+ ToolRenderer,
48
+ } from "./renderer";
31
49
  import { splitUrlScheme } from "./url-scheme-host";
32
50
  import { couldBecomeXdUrl, parseXdUrl } from "./xd-url";
33
51
  import {
52
+ describeXdevCall,
53
+ describeXdevResult,
34
54
  renderXdevCall,
35
55
  renderXdevResult,
36
56
  xdevActivitySummary,
37
57
  type XdevRenderDispatch,
38
58
  type XdevMountedRenderer,
39
59
  } from "./xdev";
40
- import { isResolutionDeviceName, renderResolutionDeviceCall } from "./resolve";
41
- import { REPORT_ISSUE_DEVICE_NAME, renderReportIssueDeviceCall } from "./report-tool-issue";
60
+ import { describeResolutionDeviceCall, isResolutionDeviceName, renderResolutionDeviceCall } from "./resolve";
61
+ import {
62
+ describeReportIssueDeviceCall,
63
+ REPORT_ISSUE_DEVICE_NAME,
64
+ renderReportIssueDeviceCall,
65
+ } from "./report-tool-issue";
42
66
  import { pendingFileLinkPath } from "./read";
43
67
 
44
68
  /** Details returned by the write tool for transcript rendering. */
@@ -64,6 +88,8 @@ interface WriteRenderArgs {
64
88
  }
65
89
 
66
90
  const WRITE_PREVIEW_LINES = 6;
91
+ /** Collapsed native write body: the first lines of the file (§7.3). */
92
+ const NATIVE_WRITE_PREVIEW = { lines: 8 } as const;
67
93
 
68
94
  function countLines(text: string): number {
69
95
  if (!text) return 0;
@@ -416,6 +442,48 @@ function couldBecomeWriteCardUrl(lowerPath: string): boolean {
416
442
  return false;
417
443
  }
418
444
 
445
+ /** Native view of a `proc://`, `agent://` or `cfg://` write. */
446
+ function describeWriteUrl(
447
+ routed: { card: WriteUrlCard; target: string },
448
+ url: string,
449
+ content: unknown,
450
+ result: CardToolResult | undefined,
451
+ details: WriteToolDetails | undefined,
452
+ ): NativeToolView {
453
+ const body = typeof content === "string" ? content : undefined;
454
+ switch (routed.card.detailsKey) {
455
+ case "message":
456
+ return describeAgentWrite(routed.target, body ?? "", result, details?.message);
457
+ case "proc": {
458
+ const { id, action } = procWriteTarget(routed.target);
459
+ return describeProcWrite(id, action, body, result, details?.proc);
460
+ }
461
+ case "cfg":
462
+ return describeCfgWrite(url, body, result, details?.cfg);
463
+ }
464
+ }
465
+
466
+ /** Native write head shared by the call and result: `Write · path · 22 lines`, executable/diagnostics chips. */
467
+ function writeToolHead(
468
+ rawPath: string,
469
+ content: string,
470
+ details?: Pick<WriteToolDetails, "madeExecutable" | "resolvedPath" | "diagnostics">,
471
+ ): NativeToolHead {
472
+ const lineCount = countLines(content);
473
+ const badges: { text: string; tone?: TspTone }[] = [];
474
+ if (details?.madeExecutable) badges.push({ text: "executable", tone: "success" });
475
+ const diagnostics = diagnosticsBadge([details?.diagnostics]);
476
+ if (diagnostics) badges.push(diagnostics);
477
+ return {
478
+ title: "Write",
479
+ target: rawPath ? displayPath(rawPath) : undefined,
480
+ targetKind: "path",
481
+ href: fileHref(details?.resolvedPath),
482
+ meta: lineCount > 0 ? [`${lineCount} line${lineCount === 1 ? "" : "s"}`] : undefined,
483
+ badges: badges.length > 0 ? badges : undefined,
484
+ };
485
+ }
486
+
419
487
  /** Render file writes and delegated tool-device calls. */
420
488
  export const writeToolRenderer = {
421
489
  /** Compact one-line activity: device writes read as the mounted tool (`LSP · references foo`), file writes as `Write · <path>`. */
@@ -618,6 +686,77 @@ export const writeToolRenderer = {
618
686
  };
619
687
  });
620
688
  },
689
+ describeCall(
690
+ args: WriteRenderArgs,
691
+ options: RenderResultOptions & { renderContext?: WriteRenderContext },
692
+ ): NativeToolView | undefined {
693
+ const rawPath =
694
+ typeof args.file_path === "string" ? args.file_path : typeof args.path === "string" ? args.path : "";
695
+ // Same gating as renderCall: nothing until the path provably is not a device/card URL.
696
+ if (args.path === undefined && args.file_path === undefined) return undefined;
697
+ const pathSettled = args.content !== undefined || options.argsComplete === true;
698
+ const hasStringPath = typeof args.file_path === "string" || typeof args.path === "string";
699
+ if (hasStringPath && !pathSettled && couldBecomeWriteCardUrl(rawPath.toLowerCase())) return undefined;
700
+ const routed = writeUrlCard(rawPath);
701
+ if (routed) return describeWriteUrl(routed, rawPath, args.content, undefined, undefined);
702
+ if (rawPath && couldBecomeXdUrl(rawPath)) {
703
+ const xdev = parseXdUrl(rawPath);
704
+ if (!xdev?.name || args.content === undefined) return undefined;
705
+ if (isResolutionDeviceName(xdev.name)) return describeResolutionDeviceCall(xdev.name, args.content);
706
+ if (xdev.name === REPORT_ISSUE_DEVICE_NAME) return describeReportIssueDeviceCall(args.content);
707
+ return describeXdevCall(xdev.name, args.content, options, options.renderContext?.resolveXdevMounted);
708
+ }
709
+ const content = normalizeDisplayText(args.content);
710
+ return {
711
+ tool: writeToolHead(rawPath, content),
712
+ body: content
713
+ ? [
714
+ code(content, {
715
+ lang: rawPath ? getLanguageFromPath(rawPath) : undefined,
716
+ numbers: true,
717
+ }),
718
+ ]
719
+ : [],
720
+ preview: NATIVE_WRITE_PREVIEW,
721
+ };
722
+ },
723
+
724
+ describeResult(
725
+ result: { content: Array<{ type: string; text?: string }>; details?: WriteToolDetails; isError?: boolean },
726
+ options: RenderResultOptions & { renderContext?: WriteRenderContext },
727
+ args?: WriteRenderArgs,
728
+ ): NativeToolView | undefined {
729
+ const cardPath =
730
+ typeof args?.path === "string" ? args.path : typeof args?.file_path === "string" ? args.file_path : "";
731
+ const routed = writeUrlCard(cardPath, result.details);
732
+ if (routed) return describeWriteUrl(routed, cardPath, args?.content, result, result.details);
733
+ const xdev = result.details?.xdev;
734
+ if (xdev) return describeXdevResult(xdev, result, options, options.renderContext?.resolveXdevMounted);
735
+ const rawPath =
736
+ typeof args?.file_path === "string" ? args.file_path : typeof args?.path === "string" ? args.path : "";
737
+ const fileContent = normalizeDisplayText(args?.content);
738
+ const isPartial = options.isPartial === true;
739
+ const diagnostics = isPartial ? undefined : result.details?.diagnostics;
740
+ const tool = writeToolHead(rawPath, fileContent, {
741
+ madeExecutable: !isPartial && result.details?.madeExecutable === true,
742
+ resolvedPath: result.details?.resolvedPath,
743
+ diagnostics,
744
+ });
745
+ if (result.isError) return { tool, tone: "error", body: [errorText(resultText(result))] };
746
+ const progressText = resultText(result);
747
+ const body = compact<NativeChild>([
748
+ isPartial &&
749
+ progressText.length > 0 &&
750
+ node("text", { spans: [span(progressText, "muted")], truncate: "end" }),
751
+ fileContent.length > 0 &&
752
+ code(fileContent, {
753
+ lang: rawPath ? getLanguageFromPath(rawPath) : undefined,
754
+ numbers: true,
755
+ }),
756
+ diagnosticsSection(diagnostics),
757
+ ]);
758
+ return { tool, body, preview: NATIVE_WRITE_PREVIEW };
759
+ },
621
760
  mergeCallAndResult: true,
622
761
  // The collapsed pending preview follows the streaming edge with a tail
623
762
  // window once the content outgrows it (`… (N earlier lines)` + last rows);
package/src/tools/xdev.ts CHANGED
@@ -4,12 +4,16 @@ import { type Component, Container, Text } from "../index";
4
4
  import type { Theme } from "../theme/theme";
5
5
  import { replaceTabs } from "../render/render-utils";
6
6
  import type { RenderResultOptions, ToolActivitySummary, ToolRenderer } from "./renderer";
7
- import { renderDefaultToolExecution } from "./default-renderer";
7
+ import { describeDefaultToolExecution, renderDefaultToolExecution } from "./default-renderer";
8
+ import type { NativeToolView } from "./renderer";
9
+ import { text } from "../native/describe";
8
10
  import { parseMCPToolName } from "./mcp";
9
11
 
10
12
  /** Mounted device display callbacks, independent of tool execution state. */
11
13
  export interface XdevMountedRenderer {
12
14
  label?: string;
15
+ describeCall?: ToolRenderer["describeCall"];
16
+ describeResult?: ToolRenderer["describeResult"];
13
17
  renderCall?(...args: Parameters<ToolRenderer["renderCall"]>): unknown;
14
18
  renderResult?(...args: Parameters<ToolRenderer["renderResult"]>): unknown;
15
19
  mergeCallAndResult?: boolean;
@@ -162,6 +166,65 @@ export function renderXdevCall(
162
166
  return renderDefaultToolExecution({ label: mounted?.label ?? name, args, options }, theme);
163
167
  }
164
168
 
169
+ /** Native form of {@link resolveDeviceRenderer}: the first renderer that can describe. */
170
+ function resolveDeviceDescriber(
171
+ name: string,
172
+ mounted: XdevMountedRenderer | undefined,
173
+ ): XdevMountedRenderer | undefined {
174
+ if (mounted && (mounted.describeCall || mounted.describeResult)) return mounted;
175
+ return rendererLookup?.(name);
176
+ }
177
+
178
+ /** TSP call view for an `xd://` write: queued card until execution, then the device renderer's own view. */
179
+ export function describeXdevCall(
180
+ name: string,
181
+ content: unknown,
182
+ options: RenderResultOptions,
183
+ resolveMounted?: (name: string) => XdevMountedRenderer | undefined,
184
+ ): NativeToolView | undefined {
185
+ const mounted = resolveMounted?.(name);
186
+ const args = decodeInnerArgs(content);
187
+ if (!options.executionStarted) {
188
+ return describeDefaultToolExecution({
189
+ label: `queued ${displayDeviceLabel(name, mounted)}`,
190
+ args: displayDeviceArgs(args),
191
+ options: { ...options, isPartial: true, spinnerFrame: undefined },
192
+ });
193
+ }
194
+ const renderer = resolveDeviceDescriber(name, mounted);
195
+ if (renderer?.describeCall) return renderer.describeCall(args, options);
196
+ return describeDefaultToolExecution({ label: mounted?.label ?? name, args, options });
197
+ }
198
+
199
+ /** TSP result view for an `xd://` dispatch, forwarded to the device renderer. */
200
+ export function describeXdevResult(
201
+ dispatch: XdevRenderDispatch,
202
+ result: { content: Array<{ type: string; text?: string }>; isError?: boolean },
203
+ options: RenderResultOptions,
204
+ resolveMounted?: (name: string) => XdevMountedRenderer | undefined,
205
+ ): NativeToolView | undefined {
206
+ const output = result.content
207
+ .map(block => (block.type === "text" ? block.text : ""))
208
+ .filter(Boolean)
209
+ .join("\n");
210
+ if (dispatch.mode === "help") return output ? { body: [text(output, { wrap: "word" })] } : undefined;
211
+ const mounted = resolveMounted?.(dispatch.tool);
212
+ const renderer = resolveDeviceDescriber(dispatch.tool, mounted);
213
+ if (renderer?.describeResult) {
214
+ const innerResult = { content: result.content, details: dispatch.inner, isError: result.isError };
215
+ const view = renderer.describeResult(innerResult, options, dispatch.args ?? {});
216
+ if (!view || renderer.mergeCallAndResult || !renderer.describeCall) return view;
217
+ const call = renderer.describeCall(dispatch.args ?? {}, { ...options, isPartial: false });
218
+ return { ...view, head: view.head ?? call?.head, body: [...(call?.body ?? []), ...(view.body ?? [])] };
219
+ }
220
+ return describeDefaultToolExecution({
221
+ label: mounted?.label ?? dispatch.tool,
222
+ args: dispatch.args ?? {},
223
+ result: { output, isError: result.isError },
224
+ options,
225
+ });
226
+ }
227
+
165
228
  /** Forward an `xd://` dispatch result to the mounted tool's renderer. */
166
229
  export function renderXdevResult(
167
230
  dispatch: XdevRenderDispatch,