@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,5 +1,11 @@
1
- import type { ToolRenderer } from "./renderer";
1
+ import type { NativeToolView, ToolRenderer, ToolRenderResult } from "./renderer";
2
2
  import { type Component, padding, Text, visibleWidth } from "../index";
3
+ import type { TspTone } from "@oh-my-pi/pi-wire";
4
+ import { ansi, compact, item, list, md, node, span, text } from "../native/describe";
5
+ import type { NativeChild, NativeNode } from "../native/node";
6
+ import { OwnerMemo } from "../native/memo";
7
+ import { plainText } from "../native/spans";
8
+ import { errorView, noteText, toolHead } from "./native-view";
3
9
  import type { RenderResultOptions } from "./renderer";
4
10
  import type { Theme, ThemeColor } from "../theme/theme";
5
11
  import { outputBlockContentWidth, renderStatusLine } from "../render";
@@ -50,36 +56,41 @@ function formatOpTitle(op: string | undefined): string {
50
56
  return "GitHub";
51
57
  }
52
58
 
53
- function extractIssueId(value: string | undefined): string | undefined {
59
+ type FitText = (value: string, width: number) => string;
60
+
61
+ /** Native views keep full values: the terminal truncates headers itself. */
62
+ const KEEP_TEXT: FitText = value => value;
63
+
64
+ function extractIssueId(value: string | undefined, fit: FitText = truncateVisualWidth): string | undefined {
54
65
  if (!value) return undefined;
55
66
  const trimmed = value.trim();
56
67
  if (!trimmed) return undefined;
57
68
  if (/^\d+$/.test(trimmed)) return `#${trimmed}`;
58
69
  const match = trimmed.match(/\/(?:issues|pull)\/(\d+)/);
59
70
  if (match) return `#${match[1]}`;
60
- return truncateVisualWidth(trimmed, TRUNCATE_LENGTHS.SHORT);
71
+ return fit(trimmed, TRUNCATE_LENGTHS.SHORT);
61
72
  }
62
73
 
63
- function formatPrIdentifier(pr: string | string[] | undefined): string | undefined {
74
+ function formatPrIdentifier(pr: string | string[] | undefined, fit: FitText = truncateVisualWidth): string | undefined {
64
75
  if (pr === undefined) return undefined;
65
76
  if (Array.isArray(pr)) {
66
- const parts = pr.map(p => extractIssueId(p)).filter((p): p is string => p !== undefined);
77
+ const parts = pr.map(p => extractIssueId(p, fit)).filter((p): p is string => p !== undefined);
67
78
  if (parts.length === 0) return undefined;
68
79
  if (parts.length > 3) {
69
80
  return `${parts.slice(0, 3).join(", ")}, +${parts.length - 3} more`;
70
81
  }
71
82
  return parts.join(", ");
72
83
  }
73
- return extractIssueId(pr);
84
+ return extractIssueId(pr, fit);
74
85
  }
75
86
 
76
- function buildOpMeta(args: GithubToolRenderArgs): string[] {
87
+ function buildOpMeta(args: GithubToolRenderArgs, fit: FitText = truncateVisualWidth): string[] {
77
88
  const meta: string[] = [];
78
89
  const op = args.op;
79
90
  switch (op) {
80
91
  case "pr_checkout":
81
92
  case "pr_push": {
82
- const id = formatPrIdentifier(args.pr);
93
+ const id = formatPrIdentifier(args.pr, fit);
83
94
  if (id) meta.push(id);
84
95
  else if (args.branch) meta.push(args.branch);
85
96
  if (args.repo) meta.push(args.repo);
@@ -89,12 +100,12 @@ function buildOpMeta(args: GithubToolRenderArgs): string[] {
89
100
  case "search_prs":
90
101
  case "search_code":
91
102
  case "search_commits": {
92
- if (args.query) meta.push(truncateVisualWidth(args.query, TRUNCATE_LENGTHS.CONTENT));
103
+ if (args.query) meta.push(fit(args.query, TRUNCATE_LENGTHS.CONTENT));
93
104
  if (args.repo) meta.push(args.repo);
94
105
  break;
95
106
  }
96
107
  case "search_repos": {
97
- if (args.query) meta.push(truncateVisualWidth(args.query, TRUNCATE_LENGTHS.CONTENT));
108
+ if (args.query) meta.push(fit(args.query, TRUNCATE_LENGTHS.CONTENT));
98
109
  break;
99
110
  }
100
111
  case "repo_view": {
@@ -410,6 +421,79 @@ function renderWatchCall(args: GithubToolRenderArgs, options: RenderResultOption
410
421
  return new Text(`${header}\n${wait}`, 0, 0);
411
422
  }
412
423
 
424
+ function jobTone(job: GhRunWatchJobDetails): TspTone {
425
+ if (job.conclusion && SUCCESS_CONCLUSIONS.has(job.conclusion)) return "success";
426
+ if (job.conclusion && FAILURE_CONCLUSIONS.has(job.conclusion)) return "error";
427
+ if (job.status && RUNNING_STATUSES.has(job.status)) return "warning";
428
+ return "muted";
429
+ }
430
+
431
+ /** One workflow run: a section headed by workflow + branch/sha + id, listing its jobs. */
432
+ function describeRun(run: GhRunWatchRunDetails): NativeNode {
433
+ const metaParts = getRunMeta(run);
434
+ const head = [span(plainText(getRunLabel(run)), "accent")];
435
+ metaParts.forEach((part, index) => {
436
+ head.push(span(" "), span(plainText(part), index === metaParts.length - 1 ? "muted" : "text"));
437
+ });
438
+ const jobs =
439
+ run.jobs.length === 0
440
+ ? noteText("waiting for workflow jobs...")
441
+ : list(
442
+ run.jobs.map(job => {
443
+ const tone = jobTone(job);
444
+ return item(`${job.id}`, {
445
+ label: [span(plainText(job.name), tone)],
446
+ tone,
447
+ icon: tone === "success" ? "check" : undefined,
448
+ value: job.durationSeconds !== undefined ? [span(`${job.durationSeconds}s`, tone)] : undefined,
449
+ });
450
+ }),
451
+ );
452
+ return node("section", { head }, [jobs], `run:${run.id}`);
453
+ }
454
+
455
+ function describeWatch(watch: GhRunWatchViewDetails, isError: boolean): NativeToolView {
456
+ const runs: NativeChild[] = [];
457
+ if (watch.mode === "run" && watch.run) runs.push(describeRun(watch.run));
458
+ else if (watch.mode === "commit") {
459
+ const commitRuns = watch.runs ?? [];
460
+ if (commitRuns.length === 0) runs.push(noteText("waiting for workflow runs..."));
461
+ for (const run of commitRuns) runs.push(describeRun(run));
462
+ }
463
+ const failed = (watch.failedLogs ?? []).flatMap((entry): NativeChild[] => {
464
+ const context = entry.workflowName ? `${entry.workflowName} #${entry.runId}` : `run #${entry.runId}`;
465
+ const title = text([span(plainText(entry.jobName), "error"), span(` ${plainText(context)}`, "muted")]);
466
+ if (!entry.available || !entry.tail) return [title, noteText("log tail unavailable")];
467
+ return [title, ansi(entry.tail, { follow: true, preview: { lines: PREVIEW_LIMITS.OUTPUT_COLLAPSED } })];
468
+ });
469
+ return {
470
+ head: toolHead("GitHub Run Watch", getWatchHeader(watch)),
471
+ tone: isError ? "error" : undefined,
472
+ body: compact([
473
+ watch.note ? noteText(watch.note) : undefined,
474
+ ...runs,
475
+ failed.length > 0
476
+ ? node("section", { head: [span("failed logs", "error")], tone: "error" }, failed, "failed")
477
+ : undefined,
478
+ ]),
479
+ };
480
+ }
481
+
482
+ function describeFallback(result: ToolRenderResult<GhToolDetails>, args: GithubToolRenderArgs): NativeToolView {
483
+ const output = extractText(result.content).trim();
484
+ const title = formatOpTitle(args.op);
485
+ const meta = buildOpMeta(args, KEEP_TEXT);
486
+ if (result.isError === true) return errorView(title, output || "request failed", ...meta);
487
+ if (!output) return { head: toolHead(title, ...meta), tone: "warning", body: [noteText("no output")] };
488
+ return {
489
+ head: toolHead(title, ...meta),
490
+ body: [md(plainText(output))],
491
+ preview: { lines: PREVIEW_LIMITS.OUTPUT_EXPANDED },
492
+ };
493
+ }
494
+
495
+ const githubResultMemo = new OwnerMemo<NativeToolView | undefined>();
496
+
413
497
  /** Render GitHub operations and live workflow status. */
414
498
  export const githubToolRenderer = {
415
499
  // No animatedPendingPreview: renderCall materializes plain Text components
@@ -483,6 +567,31 @@ export const githubToolRenderer = {
483
567
  return renderFallbackComponent(result, options, uiTheme, args ?? {});
484
568
  },
485
569
 
570
+ describeCall(args: GithubToolRenderArgs): NativeToolView {
571
+ const op = typeof args.op === "string" && args.op.trim().length > 0 ? args.op.trim() : undefined;
572
+ if (op !== "run_watch") {
573
+ return { head: toolHead(formatOpTitle(op), ...buildOpMeta({ ...args, op }, KEEP_TEXT)) };
574
+ }
575
+ const runId = typeof args.run === "string" && args.run.trim().length > 0 ? args.run.trim() : undefined;
576
+ const branch = typeof args.branch === "string" && args.branch.trim().length > 0 ? args.branch.trim() : undefined;
577
+ return {
578
+ head: toolHead("GitHub Run Watch", runId ? `#${runId}` : (branch ?? "current HEAD")),
579
+ body: [noteText("waiting for workflow data...")],
580
+ };
581
+ },
582
+
583
+ describeResult(
584
+ result: ToolRenderResult<GhToolDetails>,
585
+ options: RenderResultOptions,
586
+ args?: GithubToolRenderArgs,
587
+ ): NativeToolView | undefined {
588
+ const watch = result.details?.watch;
589
+ const deps = [args?.op, options.isPartial, watch?.state, watch?.pollCount];
590
+ return githubResultMemo.get(result, deps, () =>
591
+ watch ? describeWatch(watch, result.isError === true) : describeFallback(result, args ?? {}),
592
+ );
593
+ },
594
+
486
595
  mergeCallAndResult: true,
487
596
  } satisfies ToolRenderer<GithubToolRenderArgs, GhToolDetails>;
488
597
 
package/src/tools/glob.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  import type { Component } from "../tui";
2
2
  import { Text } from "../components/text";
3
- import type { RenderResultOptions, ToolRenderer } from "./renderer";
3
+ import type { NativeToolHead, NativeToolView, RenderResultOptions, ToolRenderer } from "./renderer";
4
+ import { col, compact, keyed, node, row, span, text } from "../native/describe";
5
+ import type { NativeChild, NativeNode } from "../native/node";
6
+ import { fileHref, fileRow, footnoteText, inlineErrorView, resultText } from "./native-view";
4
7
  import { type Theme } from "../theme/theme";
5
8
  import type { OutputMeta } from "./output-meta";
6
9
  import type { TruncationResult } from "./streaming-output";
@@ -56,6 +59,51 @@ function globStatusIcon(uiTheme: Theme): string {
56
59
  return uiTheme.fg("toolTitle", uiTheme.symbol("icon.search"));
57
60
  }
58
61
 
62
+ /** Most files a native glob lists as rows; more wrap as chips (§7.3 glob). */
63
+ const NATIVE_LIST_MAX = 6;
64
+ /** Collapsed clamp: the whole ≤ 6-row list, or about six rows of chips. */
65
+ const NATIVE_PREVIEW_LINES = 8;
66
+
67
+ /**
68
+ * Native glob files: 22px path rows when there are few, else a wrap of
69
+ * chips (glyph and name, the full path in the tooltip). Paths link when the
70
+ * search `cwd` is known.
71
+ */
72
+ function describeGlobFiles(files: readonly string[], cwd: string | undefined): NativeNode {
73
+ const links = files.map(file => (cwd && !file.endsWith("/") ? fileHref(path.resolve(cwd, file)) : undefined));
74
+ if (files.length <= NATIVE_LIST_MAX) {
75
+ return col(
76
+ files.map((file, i) => fileRow(file, { href: links[i] })),
77
+ { role: "omp.tool.files", gap: "none" },
78
+ );
79
+ }
80
+ return row(
81
+ files.map((file, i) => {
82
+ const isDir = file.endsWith("/");
83
+ const name = path.basename(file) + (isDir ? "/" : "");
84
+ const link = links[i];
85
+ return keyed(
86
+ row(
87
+ [
88
+ node("icon", { name: isDir ? "folder" : "file" }),
89
+ text([span(name, "strong", link ? { href: link } : undefined)], { wrap: "none" }),
90
+ ],
91
+ { role: "omp.tool.chip", gap: "xs", align: "center", title: file },
92
+ ),
93
+ file,
94
+ );
95
+ }),
96
+ { role: "omp.tool.files", gap: "xs", wrap: true },
97
+ );
98
+ }
99
+
100
+ /** Native glob head: the pattern, then `meta` (the result counts, or the call's `limit`). */
101
+ function globNativeHead(args: GlobRenderArgs | undefined, meta: readonly string[] = []): NativeToolHead {
102
+ const parts = [...meta];
103
+ if (meta.length === 0 && args?.limit !== undefined) parts.push(`limit:${args.limit}`);
104
+ return { title: "Glob", target: formatGlobRenderPaths(args) || "*", targetKind: "pattern", meta: parts };
105
+ }
106
+
59
107
  /** Render glob calls and results in the transcript. */
60
108
  export const globToolRenderer = {
61
109
  inline: true,
@@ -209,5 +257,72 @@ export const globToolRenderer = {
209
257
  { paddingX: 1 },
210
258
  );
211
259
  },
260
+ describeCall(args: GlobRenderArgs): NativeToolView {
261
+ return { tool: globNativeHead(args), inline: true };
262
+ },
263
+
264
+ /**
265
+ * Inline (§7.3 glob): `Glob “pattern” 5 files`, then the files as rows
266
+ * (≤ 6) or a wrap of chips; one quiet footnote for limits and skipped paths.
267
+ */
268
+ describeResult(
269
+ result: { content: Array<{ type: string; text?: string }>; details?: GlobToolDetails; isError?: boolean },
270
+ _options: RenderResultOptions,
271
+ args?: GlobRenderArgs,
272
+ ): NativeToolView {
273
+ const details = result.details;
274
+ if (result.isError || details?.error) {
275
+ return inlineErrorView(globNativeHead(args), details?.error || resultText(result) || "Unknown error");
276
+ }
277
+ if (details?.fileCount === undefined) {
278
+ const textContent = resultText(result);
279
+ if (
280
+ !textContent.trim() ||
281
+ textContent.includes("No files matching") ||
282
+ textContent.includes("No files found")
283
+ ) {
284
+ return { tool: globNativeHead(args, ["0 files"]), tone: "warning", inline: true };
285
+ }
286
+ const lines = textContent.split("\n").filter(l => l.trim());
287
+ return {
288
+ tool: globNativeHead(args, [formatCount("file", lines.length)]),
289
+ inline: true,
290
+ body: [describeGlobFiles(lines, undefined)],
291
+ preview: { lines: NATIVE_PREVIEW_LINES },
292
+ };
293
+ }
294
+ const truncation = details.truncation ?? details.meta?.truncation;
295
+ const limits = details.meta?.limits;
296
+ const truncated = Boolean(details.truncated || truncation || details.resultLimitReached || limits?.resultLimit);
297
+ const missingPaths = details.missingPaths ?? [];
298
+ const missingNote = missingPaths.length > 0 ? `skipped missing: ${missingPaths.join(", ")}` : undefined;
299
+ const scope = details.scopePath ? `in ${details.scopePath}` : undefined;
300
+ if (details.fileCount === 0) {
301
+ const foot = footnoteText(compact([missingNote]));
302
+ return {
303
+ // `truncated` on an empty result means the scan timed out mid-walk.
304
+ tool: { ...globNativeHead(args, compact(["0 files", scope])), note: truncated ? "timed out" : undefined },
305
+ tone: "warning",
306
+ inline: true,
307
+ body: foot ? [foot] : undefined,
308
+ };
309
+ }
310
+ const reasons: string[] = [];
311
+ if (details.resultLimitReached) reasons.push(`limit ${details.resultLimitReached} results`);
312
+ if (limits?.resultLimit) reasons.push(`limit ${limits.resultLimit.reached} results`);
313
+ if (truncation) reasons.push(truncation.truncatedBy === "lines" ? "line limit" : "size limit");
314
+ const artifactId = truncation && "artifactId" in truncation ? truncation.artifactId : undefined;
315
+ if (artifactId) reasons.push(formatFullOutputReference(artifactId));
316
+ const head = globNativeHead(args, compact([formatCount("file", details.fileCount), scope]));
317
+ return {
318
+ tool: truncated ? { ...head, badges: [{ text: "truncated", tone: "warning" }] } : head,
319
+ inline: true,
320
+ body: compact<NativeChild>([
321
+ describeGlobFiles(details.files ?? [], details.cwd),
322
+ footnoteText(compact([reasons.length > 0 && `truncated: ${reasons.join(", ")}`, missingNote])),
323
+ ]),
324
+ preview: { lines: NATIVE_PREVIEW_LINES },
325
+ };
326
+ },
212
327
  mergeCallAndResult: true,
213
328
  } satisfies ToolRenderer<GlobRenderArgs, GlobToolDetails>;
package/src/tools/goal.ts CHANGED
@@ -4,7 +4,11 @@ import type { Theme, ThemeColor } from "../theme/theme";
4
4
  import { formatDuration, formatErrorDetail, formatNumber, TRUNCATE_LENGTHS } from "../render/render-utils";
5
5
  import { renderStatusLine, truncateToWidth } from "../render/index";
6
6
  import { framedToolCard } from "../render/tool-card";
7
- import type { RenderResultOptions, ToolRenderer } from "./renderer";
7
+ import type { TspSpan } from "@oh-my-pi/pi-wire";
8
+ import { compact, node, span, text } from "../native/describe";
9
+ import { OwnerMemo } from "../native/memo";
10
+ import { errorView, noteText, resultText, toolHead } from "./native-view";
11
+ import type { NativeToolView, RenderResultOptions, ToolRenderer, ToolRenderResult } from "./renderer";
8
12
  /** Lifecycle state of a tracked goal. */
9
13
  export type GoalStatus = "active" | "paused" | "budget-limited" | "complete" | "dropped";
10
14
 
@@ -64,6 +68,39 @@ interface GoalRenderArgs {
64
68
  token_budget?: number;
65
69
  }
66
70
 
71
+ function describeGoalResult(result: ToolRenderResult<GoalToolDetails>, args?: GoalRenderArgs): NativeToolView {
72
+ const details = result.details;
73
+ const description = describeOp(details?.op ?? args?.op);
74
+ if (result.isError) return errorView("Goal", resultText(result) || "Goal tool failed", description);
75
+ const goal = details?.goal ?? null;
76
+ if (!goal) return { head: toolHead("Goal", description, "no active goal"), tone: "warning" };
77
+
78
+ const head = [
79
+ ...toolHead("Goal", description),
80
+ span(" "),
81
+ span(goal.status, `${goalBadgeColor(goal.status)} strong`),
82
+ ];
83
+ const used = formatNumber(goal.tokensUsed);
84
+ const left = goal.tokenBudget !== undefined ? Math.max(0, goal.tokenBudget - goal.tokensUsed) : 0;
85
+ const tokens =
86
+ goal.tokenBudget !== undefined
87
+ ? `${used} / ${formatNumber(goal.tokenBudget)} tokens (${formatNumber(left)} left)`
88
+ : `${used} tokens`;
89
+ const meta = [tokens];
90
+ if (goal.timeUsedSeconds > 0) meta.push(`${formatDuration(goal.timeUsedSeconds * 1000)} elapsed`);
91
+ const report = details?.completionBudgetReport;
92
+ return {
93
+ head,
94
+ body: compact([
95
+ text([span(`"${goal.objective.trim()}"`, "muted")], { wrap: "word" }),
96
+ text([span(meta.join(" · "), "dim")], { wrap: "word" }),
97
+ report ? node("section", { head: [span("Report", "toolTitle")] }, [noteText(report)], "report") : undefined,
98
+ ]),
99
+ };
100
+ }
101
+
102
+ const goalResultMemo = new OwnerMemo<NativeToolView | undefined>();
103
+
67
104
  /** Renders goal creation, status, and lifecycle results. */
68
105
  export const goalToolRenderer = {
69
106
  renderCall(args: GoalRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component {
@@ -149,5 +186,23 @@ export const goalToolRenderer = {
149
186
  }));
150
187
  },
151
188
 
189
+ describeCall(args: GoalRenderArgs): NativeToolView {
190
+ const head: TspSpan[] = toolHead("Goal", describeOp(args.op));
191
+ const objective = args.objective?.trim();
192
+ if (args.op === "create" && objective) head.push(span(" "), span(`"${objective}"`, "muted"));
193
+ if (args.op === "create" && args.token_budget !== undefined) {
194
+ head.push(span(" "), span(`budget ${formatNumber(args.token_budget)}`, "muted"));
195
+ }
196
+ return { head };
197
+ },
198
+
199
+ describeResult(
200
+ result: ToolRenderResult<GoalToolDetails>,
201
+ _options: RenderResultOptions,
202
+ args?: GoalRenderArgs,
203
+ ): NativeToolView | undefined {
204
+ return goalResultMemo.get(result, [args?.op], () => describeGoalResult(result, args));
205
+ },
206
+
152
207
  mergeCallAndResult: true,
153
208
  } satisfies ToolRenderer<GoalRenderArgs, GoalToolDetails>;
package/src/tools/grep.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import type { Component } from "../tui";
2
2
  import { Text } from "../components/text";
3
- import type { RenderResultOptions, ToolRenderer } from "./renderer";
3
+ import type { NativeToolHead, NativeToolView, RenderResultOptions, ToolRenderer } from "./renderer";
4
+ import { getLanguageFromPath } from "../lang-from-path";
5
+ import { compact } from "../native/describe";
6
+ import type { NativeChild } from "../native/node";
7
+ import { footnoteText, inlineErrorView, resultText } from "./native-view";
4
8
  import { type Theme } from "../theme/theme";
5
9
  import type { OutputMeta } from "./output-meta";
6
10
  import type { TruncationResult } from "./streaming-output";
@@ -24,7 +28,7 @@ import {
24
28
  PREVIEW_LIMITS,
25
29
  replaceTabs,
26
30
  } from "../render/render-utils";
27
- import { classifyGroupedLines, groupLineIndicesByBlank } from "./grouped-file-output";
31
+ import { classifyGroupedLines, describeGroupedOutput, groupLineIndicesByBlank } from "./grouped-file-output";
28
32
 
29
33
  /** Display metadata for grep tool results. */
30
34
  export interface GrepToolDetails {
@@ -79,6 +83,9 @@ const COLLAPSED_TEXT_LIMIT = PREVIEW_LIMITS.COLLAPSED_LINES * 2;
79
83
  * whose matches span the whole file can't dump its entire length. */
80
84
  const EXPANDED_TEXT_LIMIT = PREVIEW_LIMITS.EXPANDED_LINES * 2;
81
85
 
86
+ /** Files a collapsed native grep shows (§7.3). */
87
+ const NATIVE_COLLAPSED_FILES = 2;
88
+
82
89
  const SEARCH_CODE_FRAME_LINE_RE = /^\s*\*?(\d+)│/;
83
90
 
84
91
  function searchScopeMeta(details: GrepToolDetails | undefined): string | undefined {
@@ -381,5 +388,79 @@ export const grepToolRenderer = {
381
388
  { paddingX: 1 },
382
389
  );
383
390
  },
391
+ describeCall(args: GrepRenderArgs): NativeToolView {
392
+ return { tool: grepNativeHead(args), inline: true };
393
+ },
394
+
395
+ /**
396
+ * Inline (§7.3 grep): `Grep “pattern” 5 matches · 2 files in src`, then
397
+ * the matches grouped by file; collapsed shows the first two files.
398
+ */
399
+ describeResult(
400
+ result: { content: Array<{ type: string; text?: string }>; details?: GrepToolDetails; isError?: boolean },
401
+ options: RenderResultOptions,
402
+ args?: GrepRenderArgs,
403
+ ): NativeToolView {
404
+ const details = result.details;
405
+ if (result.isError || details?.error) {
406
+ return inlineErrorView(grepNativeHead(args), details?.error || resultText(result) || "Unknown error");
407
+ }
408
+ const textContent = details?.displayContent ?? resultText(result);
409
+ const missing = details?.missingPaths ?? [];
410
+ const missingNote = missing.length > 0 ? `skipped missing: ${missing.join(", ")}` : undefined;
411
+ const scope = details?.scopePath ? `in ${details.scopePath}` : undefined;
412
+ const hasDetailedData = details?.matchCount !== undefined || details?.fileCount !== undefined;
413
+ const matchCount = details?.matchCount ?? 0;
414
+ if (
415
+ (!hasDetailedData && (!textContent || textContent === "No matches found")) ||
416
+ (hasDetailedData && matchCount === 0)
417
+ ) {
418
+ const foot = footnoteText(compact([missingNote]));
419
+ return {
420
+ tool: grepNativeHead(args, compact(["0 matches", scope])),
421
+ tone: "warning",
422
+ inline: true,
423
+ body: foot ? [foot] : undefined,
424
+ };
425
+ }
426
+ const truncated = Boolean(
427
+ details?.truncated || details?.meta?.truncation || details?.meta?.limits?.columnTruncated,
428
+ );
429
+ const fileCount = details?.fileCount ?? 0;
430
+ const counts = hasDetailedData
431
+ ? `${formatCount("match", matchCount)} · ${formatCount("file", fileCount)}`
432
+ : undefined;
433
+ const head = grepNativeHead(args, compact([counts, scope]));
434
+ const hiddenFiles = options.expanded ? 0 : Math.max(0, fileCount - NATIVE_COLLAPSED_FILES);
435
+ const foot = footnoteText(
436
+ compact([hiddenFiles > 0 && formatCount("more file", hiddenFiles), missingNote]),
437
+ details?.meta,
438
+ );
439
+ return {
440
+ tool: truncated ? { ...head, badges: [{ text: "truncated", tone: "warning" }] } : head,
441
+ inline: true,
442
+ body: compact<NativeChild>([
443
+ ...describeGroupedOutput(textContent.split("\n"), {
444
+ lang: getLanguageFromPath,
445
+ maxFiles: options.expanded ? undefined : NATIVE_COLLAPSED_FILES,
446
+ }),
447
+ foot,
448
+ ]),
449
+ preview: { lines: PREVIEW_LIMITS.EXPANDED_LINES },
450
+ };
451
+ },
384
452
  mergeCallAndResult: true,
385
453
  } satisfies ToolRenderer<GrepRenderArgs, GrepToolDetails>;
454
+
455
+ /** Native grep head: the pattern, then the result `meta` or, before a result, the scope/flag arguments. */
456
+ function grepNativeHead(args: GrepRenderArgs | undefined, meta?: readonly string[]): NativeToolHead {
457
+ const parts = meta ? [...meta] : [];
458
+ if (!meta && args) {
459
+ const paths = toPathList(args.path ?? args.paths);
460
+ if (paths.length) parts.push(`in ${paths.join(", ")}`);
461
+ if (args.case === false) parts.push("case:insensitive");
462
+ if (args.gitignore === false) parts.push("gitignore:false");
463
+ if (args.skip !== undefined && args.skip > 0) parts.push(`skip:${args.skip}`);
464
+ }
465
+ return { title: "Grep", target: args?.pattern || "?", targetKind: "pattern", meta: parts };
466
+ }