@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
@@ -25,10 +25,10 @@ export function createBackgroundTanDispatchBlock(message: CustomMessage<unknown>
25
25
  return new TranscriptStatusBlock([
26
26
  {
27
27
  parts: [
28
- theme.fg("muted", `${theme.icon.output} Tangent dispatched`),
29
- theme.fg("dim", "[task]"),
30
- theme.fg("accent", jobId),
31
- work ? theme.fg("dim", `${theme.format.dash} ${work}`) : undefined,
28
+ { text: `${theme.icon.output} Tangent dispatched`, color: "muted" },
29
+ { text: "[task]", color: "dim" },
30
+ { text: jobId, color: "accent" },
31
+ work ? { text: `${theme.format.dash} ${work}`, color: "dim" } : undefined,
32
32
  ],
33
33
  },
34
34
  ]);
@@ -21,10 +21,17 @@ import {
21
21
  buildExecutionFrame,
22
22
  buildStatusFooter,
23
23
  clampDisplayLine,
24
+ describeExecutionCard,
25
+ describeExecutionTool,
26
+ type ExecutionColorKey,
24
27
  type ExecutionStatus,
25
28
  PREVIEW_LINES,
26
29
  resolveExecutionStatus,
27
30
  } from "./execution-shared";
31
+ import { span, text } from "../native/describe";
32
+ import { type DescribeContext, type NativeNode, type NativeUiEvent, rootToggleExpanded } from "../native/node";
33
+ import { NativeImageCache } from "../native/blobs";
34
+ import { Memo } from "../native/memo";
28
35
 
29
36
  const STREAMING_LINE_CAP = PREVIEW_LINES * 5;
30
37
  // Minimum interval between processing incoming chunks for display (ms).
@@ -78,6 +85,13 @@ export class BashExecutionComponent extends Container {
78
85
  #showImages = true;
79
86
  readonly #instanceId = nextBashExecutionId++;
80
87
  readonly #command: string;
88
+ readonly #colorKey: ExecutionColorKey;
89
+ readonly #startedAt = performance.now();
90
+ #endedAt: number | undefined;
91
+ // Bumped whenever the displayed output lines change.
92
+ #outputVersion = 0;
93
+ readonly #native = new Memo();
94
+ readonly #nativeImages = new NativeImageCache();
81
95
 
82
96
  constructor(command: string, ui: TUI, excludeFromContext = false) {
83
97
  super();
@@ -86,6 +100,7 @@ export class BashExecutionComponent extends Container {
86
100
 
87
101
  // Use dim border for excluded-from-context commands (!! prefix)
88
102
  const colorKey = excludeFromContext ? "dim" : "bashMode";
103
+ this.#colorKey = colorKey;
89
104
  const { contentContainer, loader } = buildExecutionFrame(this, ui, colorKey);
90
105
  this.#contentContainer = contentContainer;
91
106
  this.#loader = loader;
@@ -136,6 +151,68 @@ export class BashExecutionComponent extends Container {
136
151
  this.#updateDisplay();
137
152
  }
138
153
 
154
+ handleNativeEvent(event: NativeUiEvent): void {
155
+ const expanded = rootToggleExpanded(event);
156
+ if (expanded !== undefined) this.setExpanded(expanded);
157
+ }
158
+
159
+ /**
160
+ * The agent's bash `tool` frame (role `omp.bash`) with a `you` badge: the
161
+ * command in the head, the output as an `ansi` mini terminal following its
162
+ * tail. Terminals without the `tool` kind get a `card` headed by the
163
+ * command.
164
+ */
165
+ override describe(cx?: DescribeContext): NativeNode {
166
+ const dataFirst = cx?.supports("tool") === true;
167
+ const key = [
168
+ dataFirst,
169
+ this.#outputVersion,
170
+ this.#blockVersion,
171
+ this.#status,
172
+ this.#expanded,
173
+ this.#showImages,
174
+ this.#images.length,
175
+ ];
176
+ return this.#native.get(key, () => {
177
+ const images = this.#images.map((image, index) =>
178
+ this.#showImages
179
+ ? this.#nativeImages.get(`img${index}`, image.data, image.mimeType)
180
+ : text([
181
+ span(
182
+ imageFallback(image.mimeType, getImageDimensions(image.data, image.mimeType) ?? undefined),
183
+ "muted",
184
+ ),
185
+ ]),
186
+ );
187
+ const common = {
188
+ role: "omp.bash",
189
+ status: this.#status,
190
+ startedAt: this.#startedAt,
191
+ expanded: this.#expanded,
192
+ output: this.#outputLines.join("\n"),
193
+ images,
194
+ exitCode: this.#exitCode,
195
+ truncation: this.#truncation,
196
+ artifactError: this.#artifactError,
197
+ };
198
+ return dataFirst
199
+ ? describeExecutionTool({
200
+ ...common,
201
+ name: "bash",
202
+ title: "Bash",
203
+ command: this.#command,
204
+ lang: "bash",
205
+ excluded: this.#colorKey === "dim",
206
+ endedAt: this.#endedAt,
207
+ })
208
+ : describeExecutionCard({
209
+ ...common,
210
+ head: [span(`$ ${this.#command}`, `${this.#colorKey} strong`)],
211
+ muted: this.#colorKey === "dim",
212
+ });
213
+ });
214
+ }
215
+
139
216
  appendOutput(chunk: string): void {
140
217
  if (this.#ptyMode) return;
141
218
  // During high-throughput output (e.g. seq 1 500M), processing every
@@ -165,6 +242,7 @@ export class BashExecutionComponent extends Container {
165
242
  }
166
243
 
167
244
  this.#displayDirty = true;
245
+ this.#outputVersion++;
168
246
  }
169
247
 
170
248
  /** Switch to PTY rendering and feed raw terminal bytes through the vterm replay. */
@@ -240,6 +318,7 @@ export class BashExecutionComponent extends Container {
240
318
  const base = theme.getFgAnsi("muted");
241
319
  this.#outputLines = rows.map(row => (row ? styleTerminalRow(row, base) : ""));
242
320
  this.#displayDirty = true;
321
+ this.#outputVersion++;
243
322
  }
244
323
 
245
324
  /** Final full-scrollback read; the terminal is disposed once lines are snapshotted. */
@@ -268,6 +347,7 @@ export class BashExecutionComponent extends Container {
268
347
  ): void {
269
348
  this.#exitCode = exitCode;
270
349
  this.#status = resolveExecutionStatus(exitCode, cancelled);
350
+ this.#endedAt ??= performance.now();
271
351
  this.#truncation = options?.truncation;
272
352
  this.#artifactError = options?.artifactError;
273
353
  this.#images = options?.images ?? [];
@@ -376,6 +456,7 @@ export class BashExecutionComponent extends Container {
376
456
  #setOutput(output: string): void {
377
457
  const clean = sanitizeWithOptionalSixelPassthrough(output, sanitizeText);
378
458
  this.#outputLines = clean ? this.#clampLinesPreservingSixel(clean.split("\n")) : [];
459
+ this.#outputVersion++;
379
460
  }
380
461
 
381
462
  /**
@@ -87,6 +87,14 @@ export class CacheInvalidationMarkerComponent extends MessageDividerComponent {
87
87
  labelColor: "muted",
88
88
  ruleColor: "dim",
89
89
  ruleWidth: 10,
90
+ role: "omp.marker.cache-miss",
91
+ native: {
92
+ icon: "database",
93
+ label: () =>
94
+ info.reprocessedTokens > 0
95
+ ? `Cache miss · ${formatNumber(info.reprocessedTokens)} tokens`
96
+ : "Cache miss",
97
+ },
90
98
  // Too narrow to frame — preserve the legacy bare label.
91
99
  truncateWhenNarrow: false,
92
100
  });
@@ -27,7 +27,12 @@ import {
27
27
  SKILL_PROMPT_MESSAGE_TYPE,
28
28
  type SkillPromptDetails,
29
29
  } from "./messages";
30
- import { textContent, type TranscriptEntryLike as TranscriptEntry, transcriptEntryMessage } from "./transcript-entry";
30
+ import {
31
+ imageContent,
32
+ textContent,
33
+ type TranscriptEntryLike as TranscriptEntry,
34
+ transcriptEntryMessage,
35
+ } from "./transcript-entry";
31
36
  import { theme } from "../theme";
32
37
  import {
33
38
  assistantHasVisibleContent,
@@ -54,12 +59,16 @@ import {
54
59
  } from "./compaction-summary-message";
55
60
  import { CustomMessageComponent } from "./custom-message";
56
61
  import { EvalExecutionComponent } from "./eval-execution";
57
- import { type LateDiagnosticsFile, LateDiagnosticsMessageComponent } from "./late-diagnostics-message";
62
+ import {
63
+ type LateDiagnosticsFile,
64
+ LateDiagnosticsMessageComponent,
65
+ routeLateDiagnostics,
66
+ } from "./late-diagnostics-message";
58
67
  import { groupedReadUsageCallIds, ReadToolGroupComponent, readArgsCollapseIntoGroup } from "./read-tool-group";
59
68
  import { SkillMessageComponent } from "./skill-message";
60
69
  import { ToolExecutionComponent } from "./tool-execution";
61
70
  import { TranscriptContainer } from "../chrome/transcript-container";
62
- import { createUsageRowBlock, turnElapsedMs } from "../overlays/usage-row";
71
+ import { createUsageRowBlock, TurnUsageTally, turnElapsedMs } from "../overlays/usage-row";
63
72
  import { CollapsedSyntheticMessageComponent, UserMessageComponent } from "./user-message";
64
73
 
65
74
  export interface ChatTranscriptBuilderDeps {
@@ -88,6 +97,7 @@ export class ChatTranscriptBuilder {
88
97
  #pendingReadUsageCallIds: string[] | undefined;
89
98
  #pendingUsageElapsedMs: number | undefined;
90
99
  #turnStartedAt: number | undefined;
100
+ readonly #turnUsage = new TurnUsageTally();
91
101
  #lastAssistantUsage: Usage | undefined;
92
102
  #servedModelTracker = new ServedModelTracker();
93
103
  #waitingPoll: ToolExecutionComponent | null = null;
@@ -124,7 +134,12 @@ export class ChatTranscriptBuilder {
124
134
  if (this.#readArgs.size === 0 && this.#pendingTools.size === 0) this.#flushPendingUsage();
125
135
  }
126
136
 
127
- /** Toggle tool-output expansion across every expandable component. */
137
+ /**
138
+ * Toggle tool-output expansion across every expandable component. Cards a
139
+ * TSP terminal collapsed or expanded locally mirror that into their own
140
+ * state, so this re-applies the transcript-wide state to every one of them
141
+ * even when it equals the previous value.
142
+ */
128
143
  setExpanded(expanded: boolean): void {
129
144
  this.#expanded = expanded;
130
145
  for (const component of this.#expandables) component.setExpanded(expanded);
@@ -156,6 +171,7 @@ export class ChatTranscriptBuilder {
156
171
  this.#pendingReadUsageCallIds = undefined;
157
172
  this.#pendingUsageElapsedMs = undefined;
158
173
  this.#turnStartedAt = undefined;
174
+ this.#turnUsage.reset();
159
175
  this.#lastAssistantUsage = undefined;
160
176
  this.#servedModelTracker = new ServedModelTracker();
161
177
  this.#waitingPoll = null;
@@ -282,7 +298,9 @@ export class ChatTranscriptBuilder {
282
298
  // agent-attributed `user` message (advisor tool-loop redirect) must not.
283
299
  if (message.role === "user" && message.attribution !== "agent") {
284
300
  this.#turnStartedAt = message.timestamp;
301
+ this.#turnUsage.reset();
285
302
  } else if (message.role === "developer" && message.synthetic) {
303
+ this.#turnUsage.reset();
286
304
  // A synthetic developer message initiates a fresh run (auto-
287
305
  // continue, /goal, approved plan): replay must not inherit the
288
306
  // preceding user prompt's timestamp, mirroring the live
@@ -313,6 +331,8 @@ export class ChatTranscriptBuilder {
313
331
  this.container.addChild(
314
332
  new UserMessageComponent(userText, {
315
333
  liveSteered: message.role === "user" && message.liveSteered === true,
334
+ timestamp: message.timestamp,
335
+ images: imageContent(message.content),
316
336
  }),
317
337
  );
318
338
  }
@@ -348,6 +368,7 @@ export class ChatTranscriptBuilder {
348
368
  // message does.
349
369
  if (message.role === "custom" && isUserTurnInitiator(message as CustomMessage)) {
350
370
  this.#turnStartedAt = message.timestamp;
371
+ this.#turnUsage.reset();
351
372
  }
352
373
  this.#appendCustomMessage(message);
353
374
  break;
@@ -398,6 +419,7 @@ export class ChatTranscriptBuilder {
398
419
  this.#trackExpandable(assistantComponent);
399
420
  assistantComponent.pickReactionTarget(this.container.children);
400
421
  this.container.addChild(assistantComponent);
422
+ let lastAssistantComponent = assistantComponent;
401
423
 
402
424
  if (displayPreferences.cacheMissMarker) {
403
425
  const invalidation = detectCacheInvalidation(this.#lastAssistantUsage, message.usage);
@@ -433,6 +455,7 @@ export class ChatTranscriptBuilder {
433
455
  component.setToolResultImagesVisible(!displayPreferences.hideToolActivity);
434
456
  this.#trackExpandable(component);
435
457
  this.container.addChild(component);
458
+ lastAssistantComponent = component;
436
459
  };
437
460
 
438
461
  for (const content of message.content) {
@@ -491,6 +514,8 @@ export class ChatTranscriptBuilder {
491
514
  }
492
515
  appendAssistantSegment(afterToolSegment);
493
516
  }
517
+ const turnUsage = this.#turnUsage.add(message, this.#turnStartedAt);
518
+ if (turnUsage) lastAssistantComponent.setTurnUsage(turnUsage);
494
519
 
495
520
  this.#pendingUsage =
496
521
  displayPreferences.showTokenUsage && assistantUsageIsBilled(message.usage) ? message.usage : undefined;
@@ -544,7 +569,10 @@ export class ChatTranscriptBuilder {
544
569
  }
545
570
  if (message.customType === LSP_LATE_DIAGNOSTIC_MESSAGE_TYPE) {
546
571
  const details = (message as CustomMessage<{ files?: LateDiagnosticsFile[] }>).details;
547
- const component = new LateDiagnosticsMessageComponent(details?.files ?? []);
572
+ // Native: into the edit/write frames they belong to; the rest stand alone.
573
+ const files = routeLateDiagnostics(this.container.children, details?.files ?? []);
574
+ if (files.length === 0) return;
575
+ const component = new LateDiagnosticsMessageComponent(files);
548
576
  this.#trackExpandable(component);
549
577
  this.container.addChild(component);
550
578
  return;
@@ -570,7 +598,10 @@ export class ChatTranscriptBuilder {
570
598
  }
571
599
  if (message.customType === "advisor") {
572
600
  const details = (message as CustomMessage<AdvisorMessageDetails>).details;
573
- this.container.addChild(createAdvisorMessageCard(details, () => this.#expanded, theme));
601
+ const card = createAdvisorMessageCard(details, () => this.#expanded, theme);
602
+ // Tracked so a transcript-wide toggle also clears a per-card native toggle.
603
+ this.#trackExpandable(card);
604
+ this.container.addChild(card);
574
605
  return;
575
606
  }
576
607
  if (message.customType === LAUNCH_COMPLETION_MESSAGE_TYPE) {
@@ -5,12 +5,16 @@ import { Text } from "../components/text";
5
5
  import type { CollabPromptDetails } from "./messages";
6
6
  import type { CustomMessage } from "./messages";
7
7
  import { getMarkdownTheme, theme } from "../theme";
8
+ import { card, md, span } from "../native/describe";
9
+ import type { NativeNode } from "../native/node";
8
10
 
9
11
  /**
10
12
  * Renders a collab guest prompt on every participant's transcript: a
11
13
  * user-message-styled bubble prefixed with the author's name.
12
14
  */
13
15
  export class CollabPromptMessageComponent extends Container {
16
+ readonly #native: NativeNode;
17
+
14
18
  constructor(message: CustomMessage<CollabPromptDetails>) {
15
19
  super();
16
20
  const from = message.details?.from?.trim() || "guest";
@@ -24,11 +28,19 @@ export class CollabPromptMessageComponent extends Container {
24
28
  .filter((content): content is TextContent => content.type === "text")
25
29
  .map(content => content.text)
26
30
  .join("");
27
- const md = new Markdown(text, 1, 1, getMarkdownTheme(), {
31
+ const markdown = new Markdown(text, 1, 1, getMarkdownTheme(), {
28
32
  bgColor: (value: string) => theme.bg("userMessageBg", value),
29
33
  color: (value: string) => theme.fgOnBg("userMessageText", "userMessageBg", value),
30
34
  });
31
- md.setIgnoreTight(true);
32
- this.addChild(md);
35
+ markdown.setIgnoreTight(true);
36
+ this.addChild(markdown);
37
+ this.#native = card({ role: "omp.user.collab", tone: "user", head: [span(`«${from}» ›`, "accent strong")] }, [
38
+ md(text),
39
+ ]);
40
+ }
41
+
42
+ /** A user-toned card headed by the guest's name, with the prompt as markdown. */
43
+ override describe(): NativeNode {
44
+ return this.#native;
33
45
  }
34
46
  }
@@ -3,9 +3,13 @@ import { Disclosure } from "../components/disclosure";
3
3
  import { type Component } from "../tui";
4
4
  import { Markdown } from "../components/markdown";
5
5
  import { formatNumber } from "@oh-my-pi/pi-utils";
6
- import { getMarkdownTheme, theme } from "../theme";
6
+ import { getMarkdownTheme, getThemeEpoch, theme } from "../theme";
7
7
  import { expandKeyHint } from "../render/render-utils";
8
8
  import type { BranchSummaryMessage, CompactionSummaryMessage, CustomMessage } from "./messages";
9
+ import type { TspSpan } from "@oh-my-pi/pi-wire";
10
+ import { md, node, span, text } from "../native/describe";
11
+ import { type NativeChild, type NativeNode, type NativeUiEvent, rootToggleExpanded } from "../native/node";
12
+ import { Memo } from "../native/memo";
9
13
 
10
14
  /** Divider labels per compaction method; unknown/legacy methods fall back to "compacted". */
11
15
  const COMPACTION_METHOD_LABELS: Record<string, string> = {
@@ -24,7 +28,13 @@ function compactionAmount(message: CompactionSummaryMessage): string | undefined
24
28
 
25
29
  interface SummaryDividerOptions {
26
30
  label: () => string;
31
+ /** Themed spans of the label for native terminals. */
32
+ nativeLabel: () => TspSpan[];
27
33
  detailMarkdown: () => string;
34
+ /** Native body when it differs from the markdown detail. */
35
+ nativeDetail?: () => NativeChild[];
36
+ /** Semantic role of the native section. */
37
+ role: string;
28
38
  }
29
39
 
30
40
  /**
@@ -83,6 +93,8 @@ class SummaryMessageComponent implements Component {
83
93
  #disclosure: Disclosure;
84
94
  #ignoreTight: boolean | undefined;
85
95
  #disposed = false;
96
+ #expanded = false;
97
+ readonly #native = new Memo();
86
98
 
87
99
  readonly #options: SummaryDividerOptions;
88
100
 
@@ -92,9 +104,35 @@ class SummaryMessageComponent implements Component {
92
104
  }
93
105
 
94
106
  setExpanded(expanded: boolean): void {
107
+ this.#expanded = expanded;
95
108
  this.#disclosure.setExpanded(expanded);
96
109
  }
97
110
 
111
+ /**
112
+ * A collapsible `section` headed by the divider label, with the summary
113
+ * markdown as its body; expanding is terminal-local and mirrored back
114
+ * through {@link handleNativeEvent}.
115
+ */
116
+ describe(): NativeNode {
117
+ return this.#native.get([this.#expanded, getThemeEpoch()], () =>
118
+ node(
119
+ "section",
120
+ {
121
+ role: this.#options.role,
122
+ head: this.#options.nativeLabel(),
123
+ collapsible: true,
124
+ collapsed: !this.#expanded,
125
+ },
126
+ this.#options.nativeDetail?.() ?? [md(this.#options.detailMarkdown())],
127
+ ),
128
+ );
129
+ }
130
+
131
+ handleNativeEvent(event: NativeUiEvent): void {
132
+ const expanded = rootToggleExpanded(event);
133
+ if (expanded !== undefined) this.setExpanded(expanded);
134
+ }
135
+
98
136
  setIgnoreTight(ignore: boolean): this {
99
137
  if (this.#disposed || this.#ignoreTight === ignore) return this;
100
138
  this.#ignoreTight = ignore;
@@ -160,11 +198,42 @@ export class CompactionSummaryMessageComponent extends SummaryMessageComponent {
160
198
  // A dead-end warning stamped by the progress guard badges the bar;
161
199
  // the full text lives in the ctrl+o detail block below.
162
200
  label: () => compactionLabel(message),
201
+ nativeLabel: () => compactionNativeLabel(message),
202
+ nativeDetail: () => compactionNativeDetail(message),
163
203
  detailMarkdown: () => compactionDetailMarkdown(message),
204
+ role: "omp.compaction",
164
205
  });
165
206
  }
166
207
  }
167
208
 
209
+ /** The divider chip: `Soft-compacted · 19K → 6.9K tokens`, the arrow dimmed. */
210
+ function compactionNativeLabel(message: CompactionSummaryMessage): TspSpan[] {
211
+ const name = (message.method && COMPACTION_METHOD_LABELS[message.method]) || "compacted";
212
+ const spans = [span(`${name[0]!.toUpperCase()}${name.slice(1)}`, "muted")];
213
+ if (message.tokensAfter !== undefined && message.tokensBefore > 0) {
214
+ spans.push(
215
+ span(` · ${formatNumber(message.tokensBefore)}`, "muted mono"),
216
+ span(" → ", "dim"),
217
+ span(`${formatNumber(message.tokensAfter)} tokens`, "muted mono"),
218
+ );
219
+ }
220
+ if (message.warning) spans.push(span(` ${theme.icon.warning}`, "warning"));
221
+ return spans;
222
+ }
223
+
224
+ /** The expanded divider: a caption, the warning if any, then the summary itself (the chip already has the amounts). */
225
+ function compactionNativeDetail(message: CompactionSummaryMessage): NativeChild[] {
226
+ const frames = message.images?.length ?? 0;
227
+ const caption =
228
+ frames > 0
229
+ ? `Summary · ${frames} snapcompact frame${frames === 1 ? "" : "s"} attached`
230
+ : "Summary of the earlier conversation";
231
+ const detail: NativeChild[] = [text([span(caption, "dim")], { role: "omp.compaction.caption", key: "caption" })];
232
+ if (message.warning) detail.push(text([span(message.warning, "warning")], { wrap: "word", key: "warning" }));
233
+ detail.push(md(message.summary, { key: "summary" }));
234
+ return detail;
235
+ }
236
+
168
237
  function compactionLabel(message: CompactionSummaryMessage): string {
169
238
  const name = (message.method && COMPACTION_METHOD_LABELS[message.method]) || "compacted";
170
239
  let label = `${theme.icon.camera} ${name}`;
@@ -199,6 +268,8 @@ export class HandoffSummaryMessageComponent extends SummaryMessageComponent {
199
268
  constructor(message: CustomMessage<unknown>) {
200
269
  super({
201
270
  label: () => `${theme.icon.context} handed-off`,
271
+ nativeLabel: () => [span("Handed off", "muted")],
272
+ role: "omp.handoff",
202
273
  detailMarkdown: () => {
203
274
  const document = extractHandoffDocument(getCustomMessageText(message));
204
275
  return `**Handoff context**\n\n${document || "_No handoff content._"}`;
@@ -226,6 +297,8 @@ export class BranchSummaryMessageComponent extends SummaryMessageComponent {
226
297
  constructor(message: BranchSummaryMessage) {
227
298
  super({
228
299
  label: () => `${theme.icon.branch} branch`,
300
+ nativeLabel: () => [span("Branch summarized", "muted")],
301
+ role: "omp.branch",
229
302
  detailMarkdown: () => `**Branch summary**\n\n${message.summary}`,
230
303
  });
231
304
  }
@@ -10,11 +10,13 @@ import { type CustomMessage, LIVE_DELEGATION_MESSAGE_TYPE } from "./messages";
10
10
  export class CustomMessageComponent extends FramedMessageComponent<CustomMessage<unknown>> {
11
11
  constructor(message: CustomMessage<unknown>, customRenderer?: MessageRenderer) {
12
12
  const isLiveDelegation = message.customType === LIVE_DELEGATION_MESSAGE_TYPE;
13
+ const isHook = String(message.role) === "hookMessage";
13
14
  super({
14
15
  message,
16
+ role: isHook ? "omp.hook" : isLiveDelegation ? "omp.custom.delegation" : "omp.custom",
15
17
  // The transcript dispatch routes both `custom` and legacy `hookMessage` roles here:
16
18
  // tag hooks with the hook glyph, other injected messages with a neutral package.
17
- icon: () => (String(message.role) === "hookMessage" ? theme.icon.extensionHook : theme.icon.package),
19
+ icon: () => (isHook ? theme.icon.extensionHook : theme.icon.package),
18
20
  hideHeader: isLiveDelegation,
19
21
  borderColor: isLiveDelegation ? "borderAccent" : undefined,
20
22
  customRenderer,
@@ -15,11 +15,16 @@ import {
15
15
  buildExecutionFrame,
16
16
  buildStatusFooter,
17
17
  clampDisplayLine,
18
+ describeExecutionCard,
19
+ describeExecutionTool,
18
20
  type ExecutionColorKey,
19
21
  type ExecutionStatus,
20
22
  PREVIEW_LINES,
21
23
  resolveExecutionStatus,
22
24
  } from "./execution-shared";
25
+ import { code, span } from "../native/describe";
26
+ import { type DescribeContext, type NativeNode, type NativeUiEvent, rootToggleExpanded } from "../native/node";
27
+ import { Memo } from "../native/memo";
23
28
 
24
29
  export type EvalExecutionLanguage = "python" | "js";
25
30
 
@@ -40,6 +45,11 @@ export class EvalExecutionComponent extends Container {
40
45
  readonly #code: string;
41
46
  readonly #excludeFromContext: boolean;
42
47
  readonly #language: EvalExecutionLanguage;
48
+ readonly #startedAt = performance.now();
49
+ #endedAt: number | undefined;
50
+ // Bumped whenever the output pane's text changes.
51
+ #outputVersion = 0;
52
+ readonly #native = new Memo();
43
53
 
44
54
  #highlightLang(): "python" | "javascript" {
45
55
  return this.#language === "js" ? "javascript" : "python";
@@ -107,9 +117,54 @@ export class EvalExecutionComponent extends Container {
107
117
  this.#updateDisplay();
108
118
  }
109
119
 
120
+ handleNativeEvent(event: NativeUiEvent): void {
121
+ const expanded = rootToggleExpanded(event);
122
+ if (expanded !== undefined) this.setExpanded(expanded);
123
+ }
124
+
125
+ /**
126
+ * The agent's eval `tool` frame (role `omp.eval`) with a `you` badge: the
127
+ * cell source in the head, its output as an `ansi` mini terminal. Terminals
128
+ * without the `tool` kind get a `card` with the cell as `code` over the output.
129
+ */
130
+ override describe(cx?: DescribeContext): NativeNode {
131
+ const dataFirst = cx?.supports("tool") === true;
132
+ const key = [dataFirst, this.#outputVersion, this.#status, this.#expanded];
133
+ return this.#native.get(key, () => {
134
+ const title = this.#language === "js" ? "JavaScript" : "Python";
135
+ const common = {
136
+ role: "omp.eval",
137
+ status: this.#status,
138
+ startedAt: this.#startedAt,
139
+ expanded: this.#expanded,
140
+ output: this.#outputPane.getText(),
141
+ exitCode: this.#exitCode,
142
+ truncation: this.#truncation,
143
+ artifactError: this.#artifactError,
144
+ };
145
+ return dataFirst
146
+ ? describeExecutionTool({
147
+ ...common,
148
+ name: "eval",
149
+ title,
150
+ command: this.#code,
151
+ lang: this.#highlightLang(),
152
+ excluded: this.#excludeFromContext,
153
+ endedAt: this.#endedAt,
154
+ })
155
+ : describeExecutionCard({
156
+ ...common,
157
+ head: [span(title, `${this.#excludeFromContext ? "dim" : "pythonMode"} strong`)],
158
+ muted: this.#excludeFromContext,
159
+ lead: [code(this.#code, { lang: this.#highlightLang(), key: "code" })],
160
+ });
161
+ });
162
+ }
163
+
110
164
  appendOutput(chunk: string): void {
111
165
  // Chunk is pre-sanitized by OutputSink.push() — no need to sanitize again.
112
166
  this.#outputPane.append(chunk);
167
+ this.#outputVersion++;
113
168
  this.#updateDisplay();
114
169
  }
115
170
 
@@ -120,12 +175,14 @@ export class EvalExecutionComponent extends Container {
120
175
  ): void {
121
176
  this.#exitCode = exitCode;
122
177
  this.#status = resolveExecutionStatus(exitCode, cancelled);
178
+ this.#endedAt ??= performance.now();
123
179
  this.#truncation = options?.truncation;
124
180
  this.#artifactError = options?.artifactError;
125
181
  this.#outputPane.finish();
126
182
  if (options?.output !== undefined) {
127
183
  this.#setOutput(options.output);
128
184
  }
185
+ this.#outputVersion++;
129
186
 
130
187
  this.#loader.stop();
131
188
  this.#updateDisplay();