@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
@@ -14,7 +14,11 @@ import {
14
14
  } from "../render/render-utils";
15
15
  import { classifyGroupedLines, groupLineIndicesByBlank } from "./grouped-file-output";
16
16
  import type { OutputMeta } from "./output-meta";
17
- import type { RenderResultOptions, ToolRenderer } from "./renderer";
17
+ import type { NativeToolHead, NativeToolView, RenderResultOptions, ToolRenderer } from "./renderer";
18
+ import { code, compact, diff, node, span, text } from "../native/describe";
19
+ import type { NativeChild, NativeNode } from "../native/node";
20
+ import { diffStatsMeta, displayPath, errorText, fileDiffSection, noteText, resultText, statsText } from "./native-view";
21
+ import { getLanguageFromPath } from "../lang-from-path";
18
22
 
19
23
  /** Display metadata returned by ast-edit. */
20
24
  export interface AstEditToolDetails {
@@ -82,6 +86,86 @@ function patternPreview(pat: string | undefined): string | undefined {
82
86
  return collapsed || undefined;
83
87
  }
84
88
 
89
+ const AST_EDIT_HEADER_RE = /^(#+)\s+(.*)$/;
90
+ const AST_EDIT_CHANGE_LINE_RE = /^([+\- ])\s*(\d+)(?:│|[:|])(.*)$/;
91
+ const AST_EDIT_HEADER_SUFFIX_RE = /\s+\([^)]*\)\s*$/;
92
+
93
+ /** One file's proposed rewrite: its unified diff text and change counts. */
94
+ interface AstEditFileDiff {
95
+ path: string;
96
+ lines: string[];
97
+ added: number;
98
+ removed: number;
99
+ lastOld?: number;
100
+ }
101
+
102
+ /**
103
+ * Parse ast-edit display content (`# dir/`, `## file (N replacements)`,
104
+ * `-12│old` / `+12│new`) into one unified diff per file.
105
+ */
106
+ function parseAstEditChanges(lines: readonly string[]): AstEditFileDiff[] {
107
+ const files: AstEditFileDiff[] = [];
108
+ const dirs: string[] = [];
109
+ let file: AstEditFileDiff | undefined;
110
+ const flush = () => {
111
+ if (file && file.lines.length > 0) files.push(file);
112
+ file = undefined;
113
+ };
114
+ for (const line of lines) {
115
+ const header = AST_EDIT_HEADER_RE.exec(line);
116
+ if (header) {
117
+ flush();
118
+ const depth = header[1]!.length;
119
+ const rest = header[2]!.trimEnd().replace(AST_EDIT_HEADER_SUFFIX_RE, "");
120
+ dirs.length = depth - 1;
121
+ if (rest.endsWith("/")) {
122
+ dirs[depth - 1] = rest.slice(0, -1);
123
+ continue;
124
+ }
125
+ const prefix = dirs.filter(Boolean).join("/");
126
+ file = { path: prefix ? `${prefix}/${rest}` : rest, lines: [], added: 0, removed: 0 };
127
+ continue;
128
+ }
129
+ if (!file || line.trim().length === 0) continue;
130
+ const change = AST_EDIT_CHANGE_LINE_RE.exec(line);
131
+ if (!change) continue;
132
+ const lineNumber = Number.parseInt(change[2]!, 10);
133
+ if (file.lastOld === undefined || lineNumber > file.lastOld + 1 || lineNumber < file.lastOld) {
134
+ file.lines.push(`@@ -${lineNumber} +${lineNumber} @@`);
135
+ }
136
+ file.lastOld = lineNumber;
137
+ if (change[1] === "+") file.added++;
138
+ else if (change[1] === "-") file.removed++;
139
+ file.lines.push(`${change[1]}${change[3]}`);
140
+ }
141
+ flush();
142
+ return files;
143
+ }
144
+
145
+ /** A file's proposed rewrite as a `diff`: highlighted by the path's language, no path header. */
146
+ function astEditDiff(file: AstEditFileDiff): NativeNode {
147
+ return diff(file.lines.join("\n"), { lang: getLanguageFromPath(file.path) });
148
+ }
149
+
150
+ /** The single rewrite pattern (`target:"pattern"`), or the rewrite count, for the head. */
151
+ function astEditPatternHead(args: AstEditRenderArgs | undefined): Pick<NativeToolHead, "target" | "targetKind"> {
152
+ const rewriteCount = args?.ops?.length ?? 0;
153
+ if (rewriteCount === 1) {
154
+ const pattern = patternPreview(args?.ops?.[0]?.pat);
155
+ return pattern ? { target: pattern, targetKind: "pattern" } : {};
156
+ }
157
+ return rewriteCount > 1 ? { target: `${rewriteCount} rewrites`, targetKind: "text" } : {};
158
+ }
159
+
160
+ /** Scope facts for the final quiet line: `in src · searched 12 files · limit reached; narrow path`. */
161
+ function astEditScopeStats(details: AstEditToolDetails | undefined): NativeNode | undefined {
162
+ const parts: string[] = [];
163
+ if (details?.scopePath) parts.push(`in ${details.scopePath}`);
164
+ if (details?.filesSearched) parts.push(`searched ${formatCount("file", details.filesSearched)}`);
165
+ if (details?.limitReached) parts.push("limit reached; narrow path");
166
+ return statsText(parts);
167
+ }
168
+
85
169
  /** Render AST edit calls and results. */
86
170
  export const astEditToolRenderer = {
87
171
  inline: true,
@@ -206,5 +290,94 @@ export const astEditToolRenderer = {
206
290
  };
207
291
  });
208
292
  },
293
+ describeCall(args: AstEditRenderArgs): NativeToolView {
294
+ return {
295
+ tool: {
296
+ title: "AST Edit",
297
+ ...astEditPatternHead(args),
298
+ meta: args.paths?.length ? [`in ${args.paths.map(displayPath).join(", ")}`] : undefined,
299
+ },
300
+ };
301
+ },
302
+
303
+ describeResult(
304
+ result: { content: Array<{ type: string; text?: string }>; details?: AstEditToolDetails; isError?: boolean },
305
+ _options: RenderResultOptions,
306
+ args?: AstEditRenderArgs,
307
+ ): NativeToolView {
308
+ const details = result.details;
309
+ const patternHead = astEditPatternHead(args);
310
+ if (result.isError) {
311
+ return {
312
+ tool: { title: "AST Edit", ...patternHead },
313
+ tone: "error",
314
+ body: [errorText(resultText(result) || "Unknown error")],
315
+ };
316
+ }
317
+ const parseErrors = details?.parseErrors ?? [];
318
+ const parseNote: NativeChild | undefined =
319
+ parseErrors.length > 0
320
+ ? node(
321
+ "section",
322
+ {
323
+ head: [span(formatParseErrorsCountLabel(parseErrors, details?.parseErrorsTotal), "warning")],
324
+ collapsible: true,
325
+ collapsed: true,
326
+ },
327
+ [code(parseErrors.join("\n"))],
328
+ "parse-errors",
329
+ )
330
+ : undefined;
331
+ const totalReplacements = details?.totalReplacements ?? 0;
332
+ if (totalReplacements === 0) {
333
+ return {
334
+ tool: { title: "AST Edit", ...patternHead, meta: ["0 replacements"] },
335
+ tone: "warning",
336
+ body: compact<NativeChild>([parseNote, astEditScopeStats(details)]),
337
+ };
338
+ }
339
+ const limitReached = details?.limitReached ?? false;
340
+ const allLines = (details?.displayContent ?? resultText(result)).split("\n");
341
+ const kept = groupLineIndicesByBlank(allLines)
342
+ .filter(indices => {
343
+ const first = allLines[indices[0]!]!;
344
+ return !first.startsWith("Safety cap reached") && !first.startsWith("Parse issues:");
345
+ })
346
+ .flatMap(indices => indices.map(index => allLines[index]!));
347
+ const files = parseAstEditChanges(kept);
348
+ const fileCount = Math.max(details?.filesTouched ?? 0, files.length);
349
+ let added = 0;
350
+ let removed = 0;
351
+ for (const file of files) {
352
+ added += file.added;
353
+ removed += file.removed;
354
+ }
355
+ // Same shape as edit: one file heads the call by path with a bare diff;
356
+ // several head it as `N files` with one borderless section per file.
357
+ const single = fileCount === 1 && files.length === 1 ? files[0] : undefined;
358
+ const changes: NativeChild[] = single
359
+ ? [astEditDiff(single)]
360
+ : files.map(file => fileDiffSection(file, [astEditDiff(file)], { role: "omp.tool.ast_edit.file" }));
361
+ // The head names the files, so a single rewrite's pattern moves to a quiet context line.
362
+ const pattern = args?.ops?.length === 1 ? patternPreview(args.ops[0]?.pat) : undefined;
363
+ return {
364
+ tool: {
365
+ title: "AST Edit",
366
+ target: single ? displayPath(single.path) : formatCount("file", fileCount),
367
+ targetKind: single ? "path" : "text",
368
+ meta: compact([diffStatsMeta(added, removed), formatCount("replacement", totalReplacements)]),
369
+ badges: details?.applied ? undefined : [{ text: "proposed", tone: "warning" }],
370
+ },
371
+ tone: limitReached ? "warning" : undefined,
372
+ body: compact<NativeChild>([
373
+ pattern !== undefined &&
374
+ text([span(pattern, "code")], { lines: 1, truncate: "end", role: "omp.tool.context" }),
375
+ ...(changes.length > 0 ? changes : [noteText(kept.join("\n"))]),
376
+ parseNote,
377
+ astEditScopeStats(details),
378
+ ]),
379
+ preview: { lines: COLLAPSED_CHANGE_LIMIT },
380
+ };
381
+ },
209
382
  mergeCallAndResult: true,
210
383
  } satisfies ToolRenderer<AstEditRenderArgs, AstEditToolDetails>;
@@ -12,9 +12,13 @@ import {
12
12
  PREVIEW_LIMITS,
13
13
  toPathList,
14
14
  } from "../render/render-utils";
15
- import { classifyGroupedLines, groupLineIndicesByBlank } from "./grouped-file-output";
15
+ import { classifyGroupedLines, describeGroupedOutput, groupLineIndicesByBlank } from "./grouped-file-output";
16
+ import { getLanguageFromPath } from "../lang-from-path";
17
+ import { code, compact, node, span } from "../native/describe";
18
+ import type { NativeChild } from "../native/node";
19
+ import { errorText, noteText, resultText, toolHead } from "./native-view";
16
20
  import type { OutputMeta } from "./output-meta";
17
- import type { RenderResultOptions, ToolRenderer } from "./renderer";
21
+ import type { NativeToolView, RenderResultOptions, ToolRenderer } from "./renderer";
18
22
 
19
23
  /** Display metadata returned by ast-grep. */
20
24
  export interface AstGrepToolDetails {
@@ -167,5 +171,81 @@ export const astGrepToolRenderer = {
167
171
  },
168
172
  );
169
173
  },
174
+ describeCall(args: AstGrepRenderArgs): NativeToolView {
175
+ const meta: string[] = [];
176
+ const scopePaths = toPathList(args.path ?? args.paths);
177
+ if (scopePaths.length) meta.push(`in ${scopePaths.join(", ")}`);
178
+ if (args.skip !== undefined && args.skip > 0) meta.push(`skip:${args.skip}`);
179
+ return { head: toolHead("AST Grep", span(args.pat ?? "?", "code"), ...meta) };
180
+ },
181
+
182
+ describeResult(
183
+ result: { content: Array<{ type: string; text?: string }>; details?: AstGrepToolDetails; isError?: boolean },
184
+ _options: RenderResultOptions,
185
+ args?: AstGrepRenderArgs,
186
+ ): NativeToolView {
187
+ const details = result.details;
188
+ const pattern = span(args?.pat ?? "?", "code");
189
+ if (result.isError) {
190
+ return {
191
+ head: toolHead("AST Grep", pattern),
192
+ tone: "error",
193
+ body: [errorText(resultText(result) || "Unknown error")],
194
+ };
195
+ }
196
+ const matchCount = details?.matchCount ?? 0;
197
+ const filesSearched = details?.filesSearched ?? 0;
198
+ const limitReached = details?.limitReached ?? false;
199
+ const parseErrors = details?.parseErrors ?? [];
200
+ const parseNote =
201
+ parseErrors.length > 0
202
+ ? node(
203
+ "section",
204
+ {
205
+ head: [span(formatParseErrorsCountLabel(parseErrors, details?.parseErrorsTotal), "warning")],
206
+ collapsible: true,
207
+ collapsed: true,
208
+ },
209
+ [code(parseErrors.join("\n"))],
210
+ "parse-errors",
211
+ )
212
+ : undefined;
213
+ if (matchCount === 0) {
214
+ const meta = ["0 matches"];
215
+ if (details?.scopePath) meta.push(`in ${details.scopePath}`);
216
+ if (filesSearched > 0) meta.push(`searched ${filesSearched}`);
217
+ return {
218
+ head: toolHead("AST Grep", pattern, ...meta),
219
+ tone: "warning",
220
+ body: compact<NativeChild>([
221
+ noteText("No matches found"),
222
+ parseErrors.length > 0 &&
223
+ noteText("Query may be mis-scoped; narrow `path` before concluding absence", "warning"),
224
+ parseNote,
225
+ ]),
226
+ };
227
+ }
228
+ const meta = [formatCount("match", matchCount), formatCount("file", details?.fileCount ?? 0)];
229
+ if (details?.scopePath) meta.push(`in ${details.scopePath}`);
230
+ meta.push(`searched ${filesSearched}`);
231
+ const head = toolHead("AST Grep", pattern, ...meta);
232
+ if (limitReached) head.push(span(" limit reached", "warning"));
233
+ const allLines = (details?.displayContent ?? resultText(result)).split("\n");
234
+ const kept = groupLineIndicesByBlank(allLines)
235
+ .filter(indices => {
236
+ const first = allLines[indices[0]!]!;
237
+ return !first.startsWith("Result limit reached") && !first.startsWith("Parse issues:");
238
+ })
239
+ .flatMap(indices => [...indices.map(index => allLines[index]!), ""]);
240
+ return {
241
+ head,
242
+ body: compact<NativeChild>([
243
+ ...describeGroupedOutput(kept, { lang: getLanguageFromPath }),
244
+ limitReached && noteText("limit reached; narrow path or increase limit", "warning"),
245
+ parseNote,
246
+ ]),
247
+ preview: { lines: COLLAPSED_MATCH_LIMIT },
248
+ };
249
+ },
170
250
  mergeCallAndResult: true,
171
251
  } satisfies ToolRenderer<AstGrepRenderArgs, AstGrepToolDetails>;
@@ -1,7 +1,13 @@
1
1
  import { Text } from "../components/text";
2
2
  import type { Theme } from "../theme/theme";
3
3
  import { replaceTabs, truncateToWidth, shortenPath } from "../render/render-utils";
4
- import type { ToolRenderer } from "./renderer";
4
+ import type { TspTone } from "@oh-my-pi/pi-wire";
5
+ import { ansi, compact, kv, node, row, span, text } from "../native/describe";
6
+ import type { NativeNode } from "../native/node";
7
+ import { OwnerMemo } from "../native/memo";
8
+ import { plainText } from "../native/spans";
9
+ import { errorView, resultText, toolHead } from "./native-view";
10
+ import type { NativeToolView, ToolRenderer, ToolRenderResult } from "./renderer";
5
11
  import type { TruncationResult } from "./streaming-output";
6
12
 
7
13
  /** Whether a lower or higher metric is better. */
@@ -155,6 +161,35 @@ export interface InitExperimentDetails {
155
161
  baselineCommit: string | null;
156
162
  }
157
163
 
164
+ /** Tone of an experiment disposition: kept succeeds, discarded warns, the rest fail. */
165
+ function experimentTone(status: ExperimentStatus): TspTone {
166
+ return status === "keep" ? "success" : status === "discard" ? "warning" : "error";
167
+ }
168
+
169
+ /** Plain first line of a free-form argument, for single-line heads. */
170
+ function firstLine(value: string | undefined): string {
171
+ return (
172
+ plainText(value ?? "")
173
+ .trim()
174
+ .split("\n")[0] ?? ""
175
+ );
176
+ }
177
+
178
+ /** Result text as a wrapped body, or an error card. */
179
+ function describeTextResult(
180
+ title: string,
181
+ result: ToolRenderResult<unknown>,
182
+ style?: string,
183
+ ): NativeToolView | undefined {
184
+ const output = resultText(result);
185
+ if (result.isError) return errorView(title, output);
186
+ const body = plainText(output).trimEnd();
187
+ return body ? { body: [text(style ? [span(body, style)] : body, { wrap: "word" })] } : undefined;
188
+ }
189
+
190
+ const logResultMemo = new OwnerMemo<NativeToolView | undefined>();
191
+ const runResultMemo = new OwnerMemo<NativeToolView | undefined>();
192
+
158
193
  function renderInitCall(name: string, theme: Theme): string {
159
194
  return `${theme.fg("toolTitle", theme.bold("init_experiment"))} ${theme.fg("accent", truncateToWidth(replaceTabs(name), 100))}`;
160
195
  }
@@ -168,8 +203,42 @@ export const initExperimentToolRenderer = {
168
203
  const text = replaceTabs(result.content.find(part => part.type === "text")?.text ?? "");
169
204
  return new Text(text, 0, 0);
170
205
  },
206
+ describeCall(args): NativeToolView {
207
+ return { head: toolHead("init_experiment", span(firstLine(args.name), "accent")) };
208
+ },
209
+ describeResult(result): NativeToolView | undefined {
210
+ return describeTextResult("init_experiment", result);
211
+ },
171
212
  } satisfies ToolRenderer<{ name: string }, InitExperimentDetails>;
172
213
 
214
+ /** Native log summary: disposition badge, description, and metric/baseline grid. */
215
+ function describeSummary(details: LogDetails): NativeToolView {
216
+ const { experiment, state } = details;
217
+ const tone = experimentTone(experiment.status);
218
+ const deviations = details.scopeDeviations.length;
219
+ return {
220
+ tone,
221
+ body: compact([
222
+ row(
223
+ [
224
+ node("badge", { text: experiment.status.toUpperCase(), tone }),
225
+ text([span(plainText(experiment.description), "muted")], { wrap: "word", grow: 1 }),
226
+ ],
227
+ { gap: "sm" },
228
+ ),
229
+ kv([
230
+ [plainText(state.metricName), [span(formatNum(experiment.metric, state.metricUnit), "accent num")]],
231
+ [
232
+ "baseline",
233
+ state.bestMetric !== null ? [span(formatNum(state.bestMetric, state.metricUnit), "num")] : undefined,
234
+ ],
235
+ ["confidence", state.confidence !== null ? [span(`${state.confidence.toFixed(1)}x`, "num")] : undefined],
236
+ ["deviations", deviations > 0 ? [span(String(deviations), "warning")] : undefined],
237
+ ]),
238
+ ]),
239
+ };
240
+ }
241
+
173
242
  function renderSummary(details: LogDetails, theme: Theme): string {
174
243
  const { experiment, state } = details;
175
244
  const color = experiment.status === "keep" ? "success" : experiment.status === "discard" ? "warning" : "error";
@@ -205,8 +274,46 @@ export const logExperimentToolRenderer = {
205
274
  }
206
275
  return new Text(renderSummary(details, theme), 0, 0);
207
276
  },
277
+ describeCall(args): NativeToolView {
278
+ return {
279
+ head: toolHead(
280
+ "log_experiment",
281
+ args.status ? span(args.status, experimentTone(args.status)) : undefined,
282
+ span(firstLine(args.description), "muted"),
283
+ ),
284
+ };
285
+ },
286
+ describeResult(result): NativeToolView | undefined {
287
+ return logResultMemo.get(result, [], () => {
288
+ const details = result.details;
289
+ if (result.isError || !details) return describeTextResult("log_experiment", result);
290
+ return describeSummary(details);
291
+ });
292
+ },
208
293
  } satisfies ToolRenderer<{ status: ExperimentStatus; description: string }, LogDetails>;
209
294
 
295
+ /** Native run status: TIMEOUT/FAIL/PASS badge with duration and primary metric. */
296
+ function describeStatus(details: RunDetails): { tone: TspTone; node: NativeNode } {
297
+ const duration = `${details.durationSeconds.toFixed(1)}s`;
298
+ let tone: TspTone = "success";
299
+ let label = "PASS";
300
+ let meta = duration;
301
+ if (details.timedOut) {
302
+ tone = "error";
303
+ label = "TIMEOUT";
304
+ } else if (details.exitCode !== 0) {
305
+ tone = "error";
306
+ label = "FAIL";
307
+ meta = `exit=${details.exitCode} ${duration}`;
308
+ } else if (details.parsedPrimary !== null) {
309
+ meta = `${duration} ${plainText(details.metricName)}=${formatNum(details.parsedPrimary, details.metricUnit)}`;
310
+ }
311
+ return {
312
+ tone,
313
+ node: row([node("badge", { text: label, tone }), text([span(meta, tone)], { truncate: "end" })], { gap: "sm" }),
314
+ };
315
+ }
316
+
210
317
  function renderStatus(details: RunDetails, theme: Theme): string {
211
318
  if (details.timedOut) {
212
319
  return theme.fg("error", `TIMEOUT ${details.durationSeconds.toFixed(1)}s`);
@@ -263,6 +370,40 @@ export const runExperimentToolRenderer = {
263
370
  : "";
264
371
  return new Text(preview ? `${statusText}\n${theme.fg("dim", preview)}${suffix}` : statusText, 0, 0);
265
372
  },
373
+ describeCall(): NativeToolView {
374
+ return { head: toolHead("run_experiment", span(DEFAULT_HARNESS_COMMAND, "muted")) };
375
+ },
376
+ describeResult(result): NativeToolView | undefined {
377
+ return runResultMemo.get(result, [], () => {
378
+ const details = result.details;
379
+ if (isProgressDetails(details)) {
380
+ const output = resultText(result);
381
+ return {
382
+ tone: "warning",
383
+ preview: { lines: 6 },
384
+ body: compact([
385
+ node("spinner", { label: [span(`Running ${plainText(details.elapsed)}…`, "warning")] }),
386
+ output.trim() ? ansi(output, { follow: true }) : undefined,
387
+ ]),
388
+ };
389
+ }
390
+ if (result.isError || !details || !isRunDetails(details)) return describeTextResult("run_experiment", result);
391
+ const status = describeStatus(details);
392
+ return {
393
+ tone: status.tone,
394
+ preview: { lines: 6 },
395
+ body: compact([
396
+ status.node,
397
+ details.tailOutput.trim() ? ansi(details.tailOutput, { follow: true }) : undefined,
398
+ details.truncation && details.fullOutputPath
399
+ ? text([span("Full output: ", "warning"), span(shortenPath(details.fullOutputPath), "path")], {
400
+ truncate: "middle",
401
+ })
402
+ : undefined,
403
+ ]),
404
+ };
405
+ });
406
+ },
266
407
  } satisfies ToolRenderer<unknown, RunDetails | RunExperimentProgressDetails>;
267
408
 
268
409
  /** Persisted experiment notes after an update. */
@@ -284,4 +425,11 @@ export const updateNotesToolRenderer = {
284
425
  const text = replaceTabs(result.content.find(part => part.type === "text")?.text ?? "");
285
426
  return new Text(theme.fg("muted", text), 0, 0);
286
427
  },
428
+ describeCall(args): NativeToolView {
429
+ const preview = args.append_idea ?? args.body?.slice(0, 100);
430
+ return { head: toolHead("update_notes", span(firstLine(preview), "muted")) };
431
+ },
432
+ describeResult(result): NativeToolView | undefined {
433
+ return describeTextResult("update_notes", result, "muted");
434
+ },
287
435
  } satisfies ToolRenderer<{ body: string; append_idea?: string }, UpdateNotesDetails>;