@oh-my-pi/pi-tui 18.4.3 → 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 (447) hide show
  1. package/CHANGELOG.md +36 -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/todo-reminder.d.ts +4 -1
  22. package/dist/types/chat/tool-execution.d.ts +25 -1
  23. package/dist/types/chat/transcript-actions.d.ts +37 -0
  24. package/dist/types/chat/transcript-entry.d.ts +3 -1
  25. package/dist/types/chat/user-message.d.ts +25 -0
  26. package/dist/types/chrome/collab-qrcode.d.ts +7 -0
  27. package/dist/types/chrome/context-thresholds.d.ts +11 -0
  28. package/dist/types/chrome/countdown-timer.d.ts +9 -3
  29. package/dist/types/chrome/diff.d.ts +12 -0
  30. package/dist/types/chrome/dynamic-border.d.ts +3 -0
  31. package/dist/types/chrome/format.d.ts +6 -0
  32. package/dist/types/chrome/message-divider.d.ts +13 -0
  33. package/dist/types/chrome/message-frame.d.ts +10 -0
  34. package/dist/types/chrome/message-notice.d.ts +23 -0
  35. package/dist/types/chrome/overlay-box.d.ts +11 -2
  36. package/dist/types/chrome/qrcode.d.ts +7 -0
  37. package/dist/types/chrome/segment-track.d.ts +7 -0
  38. package/dist/types/chrome/selector-helpers.d.ts +0 -6
  39. package/dist/types/chrome/status-notice.d.ts +14 -0
  40. package/dist/types/chrome/streaming-panel.d.ts +3 -0
  41. package/dist/types/chrome/tool-activity.d.ts +3 -0
  42. package/dist/types/chrome/transcript-container.d.ts +13 -0
  43. package/dist/types/chrome/transcript-status.d.ts +15 -3
  44. package/dist/types/components/box.d.ts +7 -0
  45. package/dist/types/components/disclosure.d.ts +9 -0
  46. package/dist/types/components/editor.d.ts +37 -0
  47. package/dist/types/components/form.d.ts +14 -0
  48. package/dist/types/components/image.d.ts +7 -0
  49. package/dist/types/components/input.d.ts +20 -1
  50. package/dist/types/components/key-value-list.d.ts +3 -0
  51. package/dist/types/components/layout/geometry.d.ts +16 -0
  52. package/dist/types/components/layout/row.d.ts +7 -0
  53. package/dist/types/components/layout/split-pane.d.ts +8 -0
  54. package/dist/types/components/layout/stack.d.ts +6 -0
  55. package/dist/types/components/loader.d.ts +48 -0
  56. package/dist/types/components/markdown.d.ts +8 -0
  57. package/dist/types/components/metric.d.ts +7 -0
  58. package/dist/types/components/progress-bar.d.ts +3 -0
  59. package/dist/types/components/scroll-view.d.ts +6 -0
  60. package/dist/types/components/section.d.ts +3 -0
  61. package/dist/types/components/select-list.d.ts +33 -0
  62. package/dist/types/components/settings-list.d.ts +68 -0
  63. package/dist/types/components/spacer.d.ts +4 -0
  64. package/dist/types/components/tab-bar.d.ts +9 -0
  65. package/dist/types/components/table.d.ts +7 -0
  66. package/dist/types/components/text.d.ts +6 -0
  67. package/dist/types/components/tree-view.d.ts +9 -0
  68. package/dist/types/components/truncated-text.d.ts +3 -0
  69. package/dist/types/components/wizard-step.d.ts +6 -0
  70. package/dist/types/hotkeys-markdown.d.ts +24 -0
  71. package/dist/types/index.d.ts +5 -0
  72. package/dist/types/latex-block.d.ts +7 -0
  73. package/dist/types/native/apply.d.ts +39 -0
  74. package/dist/types/native/backend.d.ts +94 -0
  75. package/dist/types/native/blobs.d.ts +29 -0
  76. package/dist/types/native/describe.d.ts +56 -0
  77. package/dist/types/native/encode.d.ts +50 -0
  78. package/dist/types/native/icons.d.ts +18 -0
  79. package/dist/types/native/memo.d.ts +27 -0
  80. package/dist/types/native/node.d.ts +107 -0
  81. package/dist/types/native/overlay.d.ts +64 -0
  82. package/dist/types/native/picker.d.ts +124 -0
  83. package/dist/types/native/reconcile.d.ts +41 -0
  84. package/dist/types/native/settle.d.ts +11 -0
  85. package/dist/types/native/spans.d.ts +21 -0
  86. package/dist/types/native/state.d.ts +6 -0
  87. package/dist/types/native/tone.d.ts +24 -0
  88. package/dist/types/overlays/advisor-config.d.ts +20 -0
  89. package/dist/types/overlays/agent-hub-renderer.d.ts +27 -11
  90. package/dist/types/overlays/agent-hub.d.ts +10 -0
  91. package/dist/types/overlays/agent-transcript-viewer.d.ts +7 -0
  92. package/dist/types/overlays/agents-hub.d.ts +8 -0
  93. package/dist/types/overlays/annotation-overlay.d.ts +3 -0
  94. package/dist/types/overlays/ask-dialog.d.ts +23 -0
  95. package/dist/types/overlays/bordered-loader.d.ts +3 -0
  96. package/dist/types/overlays/btw-history-panel.d.ts +9 -0
  97. package/dist/types/overlays/btw-panel.d.ts +3 -0
  98. package/dist/types/overlays/cleanse-panel.d.ts +5 -2
  99. package/dist/types/overlays/composer-shape-preview.d.ts +7 -1
  100. package/dist/types/overlays/copy-selector.d.ts +38 -0
  101. package/dist/types/overlays/error-banner.d.ts +9 -0
  102. package/dist/types/overlays/extensions/extension-list.d.ts +1 -0
  103. package/dist/types/overlays/history-search.d.ts +18 -0
  104. package/dist/types/overlays/hook-editor.d.ts +28 -1
  105. package/dist/types/overlays/hook-input.d.ts +3 -0
  106. package/dist/types/overlays/hook-selector.d.ts +10 -0
  107. package/dist/types/overlays/hub-frame.d.ts +18 -0
  108. package/dist/types/overlays/jobs-panel.d.ts +24 -0
  109. package/dist/types/overlays/login-dialog.d.ts +10 -0
  110. package/dist/types/overlays/logout-account-selector.d.ts +4 -0
  111. package/dist/types/overlays/mcp-add-wizard.d.ts +4 -0
  112. package/dist/types/overlays/model-browser.d.ts +69 -0
  113. package/dist/types/overlays/model-hub.d.ts +7 -0
  114. package/dist/types/overlays/model-picker.d.ts +7 -0
  115. package/dist/types/overlays/move-overlay.d.ts +3 -0
  116. package/dist/types/overlays/oauth-selector.d.ts +4 -0
  117. package/dist/types/overlays/omfg-panel.d.ts +3 -0
  118. package/dist/types/overlays/pause-screen.d.ts +12 -0
  119. package/dist/types/overlays/plan-review-overlay.d.ts +5 -0
  120. package/dist/types/overlays/plan-save-overlay.d.ts +10 -0
  121. package/dist/types/overlays/plugin-selector.d.ts +4 -0
  122. package/dist/types/overlays/plugin-settings.d.ts +30 -0
  123. package/dist/types/overlays/queue-mode-selector.d.ts +4 -0
  124. package/dist/types/overlays/reset-usage-selector.d.ts +8 -0
  125. package/dist/types/overlays/rewind-selector.d.ts +5 -0
  126. package/dist/types/overlays/session-info-overlay.d.ts +19 -1
  127. package/dist/types/overlays/session-selector.d.ts +64 -1
  128. package/dist/types/overlays/settings-defs.d.ts +14 -0
  129. package/dist/types/overlays/settings-selector.d.ts +21 -0
  130. package/dist/types/overlays/show-images-selector.d.ts +4 -0
  131. package/dist/types/overlays/snapcompact-shape-preview.d.ts +2 -0
  132. package/dist/types/overlays/stats-notice.d.ts +8 -0
  133. package/dist/types/overlays/theme-selector.d.ts +11 -0
  134. package/dist/types/overlays/thinking-selector.d.ts +4 -0
  135. package/dist/types/overlays/tree-selector.d.ts +60 -2
  136. package/dist/types/overlays/usage-dashboard.d.ts +26 -3
  137. package/dist/types/overlays/usage-row.d.ts +36 -2
  138. package/dist/types/prompt/attachment-chips.d.ts +8 -0
  139. package/dist/types/prompt/composer-attachments.d.ts +15 -3
  140. package/dist/types/prompt/composer.d.ts +18 -1
  141. package/dist/types/prompt/custom-editor.d.ts +48 -2
  142. package/dist/types/prompt/editor-top-gap.d.ts +2 -0
  143. package/dist/types/prompt/macos-spelling.d.ts +6 -0
  144. package/dist/types/prompt/magic-keywords.d.ts +9 -0
  145. package/dist/types/prompt/queued-messages.d.ts +23 -0
  146. package/dist/types/prompt/skill-tokens.d.ts +4 -2
  147. package/dist/types/prompt/welcome.d.ts +16 -0
  148. package/dist/types/render/code-cell.d.ts +10 -0
  149. package/dist/types/render/file-list.d.ts +8 -0
  150. package/dist/types/render/hyperlink.d.ts +14 -0
  151. package/dist/types/render/output-block.d.ts +43 -0
  152. package/dist/types/render/output-pane.d.ts +17 -0
  153. package/dist/types/render/tool-card.d.ts +8 -0
  154. package/dist/types/render/tree-list.d.ts +8 -0
  155. package/dist/types/render/width-aware-text.d.ts +7 -0
  156. package/dist/types/setup/scenes/outro.d.ts +7 -0
  157. package/dist/types/setup/scenes/sign-in.d.ts +7 -0
  158. package/dist/types/setup/scenes/splash.d.ts +8 -0
  159. package/dist/types/setup/scenes/types.d.ts +6 -1
  160. package/dist/types/setup/wizard-overlay.d.ts +9 -0
  161. package/dist/types/status-line/component.d.ts +49 -5
  162. package/dist/types/status-line/context-usage.d.ts +20 -0
  163. package/dist/types/status-line/footer.d.ts +8 -0
  164. package/dist/types/status-line/metrics.d.ts +1 -2
  165. package/dist/types/status-line/segments.d.ts +10 -1
  166. package/dist/types/status-line/types.d.ts +40 -1
  167. package/dist/types/terminal-capabilities.d.ts +1 -1
  168. package/dist/types/terminal.d.ts +27 -0
  169. package/dist/types/theme/defaults/index.d.ts +100 -0
  170. package/dist/types/theme/schema.d.ts +2 -0
  171. package/dist/types/theme/shimmer.d.ts +8 -0
  172. package/dist/types/theme/theme-class.d.ts +2 -0
  173. package/dist/types/theme/theme.d.ts +33 -1
  174. package/dist/types/tools/ask.d.ts +3 -0
  175. package/dist/types/tools/ast-edit.d.ts +10 -1
  176. package/dist/types/tools/ast-grep.d.ts +10 -1
  177. package/dist/types/tools/autoresearch.d.ts +21 -4
  178. package/dist/types/tools/bash.d.ts +30 -1
  179. package/dist/types/tools/cfg-render.d.ts +5 -1
  180. package/dist/types/tools/debug.d.ts +3 -1
  181. package/dist/types/tools/default-renderer.d.ts +6 -1
  182. package/dist/types/tools/edit.d.ts +14 -1
  183. package/dist/types/tools/eval.d.ts +12 -1
  184. package/dist/types/tools/fetch.d.ts +16 -1
  185. package/dist/types/tools/find.d.ts +15 -1
  186. package/dist/types/tools/github.d.ts +3 -0
  187. package/dist/types/tools/glob.d.ts +14 -1
  188. package/dist/types/tools/goal.d.ts +3 -1
  189. package/dist/types/tools/grep.d.ts +14 -1
  190. package/dist/types/tools/grouped-file-output.d.ts +58 -0
  191. package/dist/types/tools/json-tree.d.ts +20 -0
  192. package/dist/types/tools/lsp.d.ts +3 -10
  193. package/dist/types/tools/mcp.d.ts +16 -1
  194. package/dist/types/tools/memory.d.ts +26 -0
  195. package/dist/types/tools/native-view.d.ts +90 -0
  196. package/dist/types/tools/proc-render.d.ts +7 -1
  197. package/dist/types/tools/read.d.ts +23 -1
  198. package/dist/types/tools/renderer.d.ts +57 -0
  199. package/dist/types/tools/report-tool-issue.d.ts +3 -0
  200. package/dist/types/tools/resolve.d.ts +14 -1
  201. package/dist/types/tools/task.d.ts +3 -0
  202. package/dist/types/tools/think.d.ts +3 -0
  203. package/dist/types/tools/todo.d.ts +12 -0
  204. package/dist/types/tools/vibe.d.ts +3 -1
  205. package/dist/types/tools/wait.d.ts +3 -0
  206. package/dist/types/tools/web-search.d.ts +8 -0
  207. package/dist/types/tools/write.d.ts +14 -1
  208. package/dist/types/tools/xdev.d.ts +13 -0
  209. package/dist/types/tui.d.ts +49 -0
  210. package/package.json +9 -9
  211. package/src/apps/autoresearch-dashboard.ts +362 -4
  212. package/src/apps/cleanse-board.ts +219 -1
  213. package/src/apps/cleanse-picker.ts +9 -1
  214. package/src/apps/debug/log-viewer.ts +15 -15
  215. package/src/apps/debug/protocol-probe.ts +2 -20
  216. package/src/apps/git/avatar.ts +2 -22
  217. package/src/apps/git/git-tui.ts +406 -59
  218. package/src/apps/git/help.ts +130 -0
  219. package/src/apps/git/sidebar.ts +491 -0
  220. package/src/apps/live-visualizer.ts +65 -0
  221. package/src/apps/ps-top.ts +448 -17
  222. package/src/apps/session-picker.ts +1 -0
  223. package/src/apps/setup-model-picker.ts +5 -1
  224. package/src/apps/standalone-picker.ts +55 -1
  225. package/src/autocomplete.ts +44 -1
  226. package/src/chat/advisor-message.ts +72 -3
  227. package/src/chat/assistant-message.ts +346 -11
  228. package/src/chat/background-tan-message.ts +4 -4
  229. package/src/chat/bash-execution.ts +81 -0
  230. package/src/chat/cache-invalidation-marker.ts +8 -0
  231. package/src/chat/chat-transcript-builder.ts +37 -6
  232. package/src/chat/collab-prompt-message.ts +15 -3
  233. package/src/chat/compaction-summary-message.ts +74 -1
  234. package/src/chat/custom-message.ts +3 -1
  235. package/src/chat/eval-execution.ts +57 -0
  236. package/src/chat/execution-shared.ts +153 -1
  237. package/src/chat/hook-message.ts +1 -0
  238. package/src/chat/late-diagnostics-message.ts +85 -2
  239. package/src/chat/read-tool-group.ts +341 -1
  240. package/src/chat/served-model-marker.ts +8 -0
  241. package/src/chat/skill-message.ts +63 -0
  242. package/src/chat/stripped-tool-calls-placeholder.ts +18 -10
  243. package/src/chat/todo-reminder.ts +34 -4
  244. package/src/chat/tool-execution.ts +385 -10
  245. package/src/chat/transcript-actions.ts +38 -0
  246. package/src/chat/transcript-browser.ts +2 -9
  247. package/src/chat/transcript-entry.ts +10 -1
  248. package/src/chat/transcript-render-helpers.ts +16 -15
  249. package/src/chat/ttsr-notification.ts +38 -1
  250. package/src/chat/user-message.ts +167 -4
  251. package/src/chrome/collab-qrcode.ts +27 -2
  252. package/src/chrome/context-thresholds.ts +34 -0
  253. package/src/chrome/countdown-timer.ts +24 -1
  254. package/src/chrome/diff.ts +60 -1
  255. package/src/chrome/dynamic-border.ts +7 -0
  256. package/src/chrome/format.ts +12 -0
  257. package/src/chrome/message-divider.ts +33 -1
  258. package/src/chrome/message-frame.ts +53 -10
  259. package/src/chrome/message-notice.ts +71 -0
  260. package/src/chrome/overlay-box.ts +45 -2
  261. package/src/chrome/qrcode.ts +28 -0
  262. package/src/chrome/segment-track.ts +26 -0
  263. package/src/chrome/selector-helpers.ts +1 -17
  264. package/src/chrome/status-notice.ts +46 -0
  265. package/src/chrome/streaming-panel.ts +25 -1
  266. package/src/chrome/tool-activity.ts +20 -0
  267. package/src/chrome/transcript-container.ts +37 -0
  268. package/src/chrome/transcript-status.ts +40 -11
  269. package/src/components/box.ts +51 -0
  270. package/src/components/disclosure.ts +33 -0
  271. package/src/components/editor.ts +216 -27
  272. package/src/components/form.ts +93 -9
  273. package/src/components/image.ts +30 -0
  274. package/src/components/input.ts +77 -26
  275. package/src/components/key-value-list.ts +18 -0
  276. package/src/components/layout/geometry.ts +44 -0
  277. package/src/components/layout/row.ts +30 -0
  278. package/src/components/layout/split-pane.ts +65 -0
  279. package/src/components/layout/stack.ts +27 -0
  280. package/src/components/loader.ts +183 -1
  281. package/src/components/markdown.ts +21 -0
  282. package/src/components/metric.ts +39 -0
  283. package/src/components/progress-bar.ts +28 -0
  284. package/src/components/scroll-view.ts +23 -0
  285. package/src/components/section.ts +16 -0
  286. package/src/components/select-list.ts +174 -25
  287. package/src/components/settings-list.ts +264 -7
  288. package/src/components/spacer.ts +17 -0
  289. package/src/components/tab-bar.ts +42 -0
  290. package/src/components/table.ts +34 -0
  291. package/src/components/text.ts +23 -0
  292. package/src/components/tree-view.ts +65 -0
  293. package/src/components/truncated-text.ts +14 -0
  294. package/src/components/wizard-step.ts +18 -9
  295. package/src/debug-server.ts +14 -7
  296. package/src/hotkeys-markdown.ts +251 -69
  297. package/src/index.ts +6 -0
  298. package/src/latex-block.ts +11 -0
  299. package/src/native/apply.ts +275 -0
  300. package/src/native/backend.ts +682 -0
  301. package/src/native/blobs.ts +70 -0
  302. package/src/native/describe.ts +124 -0
  303. package/src/native/encode.ts +233 -0
  304. package/src/native/icons.ts +184 -0
  305. package/src/native/memo.ts +64 -0
  306. package/src/native/node.ts +112 -0
  307. package/src/native/overlay.ts +131 -0
  308. package/src/native/picker.ts +333 -0
  309. package/src/native/reconcile.ts +1063 -0
  310. package/src/native/settle.ts +23 -0
  311. package/src/native/spans.ts +308 -0
  312. package/src/native/state.ts +28 -0
  313. package/src/native/tone.ts +79 -0
  314. package/src/overlays/advisor-config.ts +420 -0
  315. package/src/overlays/agent-hub-renderer.ts +155 -18
  316. package/src/overlays/agent-hub.ts +1037 -44
  317. package/src/overlays/agent-transcript-viewer.ts +129 -0
  318. package/src/overlays/agents-hub.ts +688 -53
  319. package/src/overlays/annotation-overlay.ts +391 -52
  320. package/src/overlays/ask-dialog.ts +435 -24
  321. package/src/overlays/bordered-loader.ts +17 -0
  322. package/src/overlays/btw-history-panel.ts +182 -0
  323. package/src/overlays/btw-panel.ts +68 -2
  324. package/src/overlays/cleanse-panel.ts +105 -15
  325. package/src/overlays/codex-reset-fireworks.ts +65 -5
  326. package/src/overlays/composer-shape-preview.ts +26 -1
  327. package/src/overlays/copy-selector.ts +545 -23
  328. package/src/overlays/error-banner.ts +44 -0
  329. package/src/overlays/extensions/extension-list.ts +23 -17
  330. package/src/overlays/history-search.ts +175 -33
  331. package/src/overlays/hook-editor.ts +113 -6
  332. package/src/overlays/hook-input.ts +22 -1
  333. package/src/overlays/hook-selector.ts +311 -22
  334. package/src/overlays/hub-frame.ts +80 -0
  335. package/src/overlays/jobs-panel.ts +112 -0
  336. package/src/overlays/login-dialog.ts +183 -1
  337. package/src/overlays/logout-account-selector.ts +102 -4
  338. package/src/overlays/mcp-add-wizard.ts +232 -53
  339. package/src/overlays/model-browser.ts +681 -22
  340. package/src/overlays/model-hub.ts +1402 -78
  341. package/src/overlays/model-picker.ts +175 -1
  342. package/src/overlays/move-overlay.ts +45 -0
  343. package/src/overlays/oauth-selector.ts +227 -23
  344. package/src/overlays/omfg-panel.ts +86 -2
  345. package/src/overlays/pause-screen.ts +55 -4
  346. package/src/overlays/plan-review-overlay.ts +352 -0
  347. package/src/overlays/plan-save-overlay.ts +45 -0
  348. package/src/overlays/plugin-selector.ts +21 -1
  349. package/src/overlays/plugin-settings.ts +195 -5
  350. package/src/overlays/queue-mode-selector.ts +19 -1
  351. package/src/overlays/reset-usage-selector.ts +110 -40
  352. package/src/overlays/rewind-selector.ts +458 -44
  353. package/src/overlays/session-account-selector.ts +1 -1
  354. package/src/overlays/session-info-overlay.ts +137 -1
  355. package/src/overlays/session-selector.ts +807 -46
  356. package/src/overlays/settings-defs.ts +41 -0
  357. package/src/overlays/settings-selector.ts +583 -23
  358. package/src/overlays/show-images-selector.ts +18 -1
  359. package/src/overlays/snapcompact-shape-preview.ts +48 -3
  360. package/src/overlays/stats-notice.ts +31 -0
  361. package/src/overlays/theme-selector.ts +31 -1
  362. package/src/overlays/thinking-selector.ts +22 -1
  363. package/src/overlays/tree-selector.ts +570 -110
  364. package/src/overlays/usage-dashboard.ts +587 -12
  365. package/src/overlays/usage-row.ts +161 -25
  366. package/src/prompt/attachment-chips.ts +60 -0
  367. package/src/prompt/composer-attachments.ts +31 -9
  368. package/src/prompt/composer.ts +55 -2
  369. package/src/prompt/custom-editor.ts +302 -4
  370. package/src/prompt/editor-top-gap.ts +8 -0
  371. package/src/prompt/macos-spelling.ts +24 -9
  372. package/src/prompt/magic-keywords.ts +22 -1
  373. package/src/prompt/model-mention-autocomplete.ts +1 -0
  374. package/src/prompt/queued-messages.ts +101 -0
  375. package/src/prompt/skill-tokens.ts +5 -3
  376. package/src/prompt/welcome.ts +213 -6
  377. package/src/render/code-cell.ts +103 -2
  378. package/src/render/file-list.ts +29 -0
  379. package/src/render/hyperlink.ts +32 -0
  380. package/src/render/output-block.ts +110 -0
  381. package/src/render/output-pane.ts +37 -0
  382. package/src/render/tool-card.ts +137 -0
  383. package/src/render/tree-list.ts +39 -0
  384. package/src/render/width-aware-text.ts +20 -0
  385. package/src/setup/scenes/composer.ts +29 -0
  386. package/src/setup/scenes/glyph.ts +15 -0
  387. package/src/setup/scenes/model.ts +36 -8
  388. package/src/setup/scenes/outro.ts +28 -1
  389. package/src/setup/scenes/sign-in.ts +122 -13
  390. package/src/setup/scenes/splash.ts +28 -1
  391. package/src/setup/scenes/theme.ts +88 -3
  392. package/src/setup/scenes/types.ts +7 -1
  393. package/src/setup/startup-splash.ts +46 -9
  394. package/src/setup/wizard-overlay.ts +140 -23
  395. package/src/status-line/component.ts +398 -16
  396. package/src/status-line/context-usage.ts +279 -50
  397. package/src/status-line/footer.ts +94 -1
  398. package/src/status-line/metrics.ts +3 -6
  399. package/src/status-line/segments.ts +463 -97
  400. package/src/status-line/separators.ts +3 -16
  401. package/src/status-line/types.ts +43 -1
  402. package/src/terminal-capabilities.ts +7 -0
  403. package/src/terminal.ts +130 -2
  404. package/src/theme/defaults/dark-neon-noir.json +100 -0
  405. package/src/theme/defaults/index.ts +2 -0
  406. package/src/theme/defaults/light-prism.json +5 -5
  407. package/src/theme/defaults/onyx.json +62 -62
  408. package/src/theme/schema.ts +15 -0
  409. package/src/theme/shimmer.ts +33 -0
  410. package/src/theme/theme-class.ts +24 -19
  411. package/src/theme/theme.ts +111 -9
  412. package/src/tools/ask.ts +157 -1
  413. package/src/tools/ast-edit.ts +174 -1
  414. package/src/tools/ast-grep.ts +82 -2
  415. package/src/tools/autoresearch.ts +149 -1
  416. package/src/tools/bash.ts +180 -49
  417. package/src/tools/cfg-render.ts +66 -1
  418. package/src/tools/debug.ts +78 -1
  419. package/src/tools/default-renderer.ts +35 -1
  420. package/src/tools/edit.ts +247 -2
  421. package/src/tools/eval.ts +257 -1
  422. package/src/tools/fetch.ts +102 -3
  423. package/src/tools/find.ts +127 -1
  424. package/src/tools/github.ts +119 -10
  425. package/src/tools/glob.ts +116 -1
  426. package/src/tools/goal.ts +56 -1
  427. package/src/tools/grep.ts +83 -2
  428. package/src/tools/grouped-file-output.ts +205 -0
  429. package/src/tools/json-tree.ts +116 -1
  430. package/src/tools/lsp.ts +318 -1
  431. package/src/tools/mcp.ts +80 -1
  432. package/src/tools/memory.ts +93 -11
  433. package/src/tools/native-view.ts +292 -0
  434. package/src/tools/proc-render.ts +221 -1
  435. package/src/tools/read.ts +199 -4
  436. package/src/tools/renderer.ts +61 -0
  437. package/src/tools/report-tool-issue.ts +7 -1
  438. package/src/tools/resolve.ts +63 -1
  439. package/src/tools/task.ts +406 -4
  440. package/src/tools/think.ts +19 -1
  441. package/src/tools/todo.ts +89 -0
  442. package/src/tools/vibe.ts +230 -2
  443. package/src/tools/wait.ts +181 -1
  444. package/src/tools/web-search.ts +113 -1
  445. package/src/tools/write.ts +144 -5
  446. package/src/tools/xdev.ts +64 -1
  447. package/src/tui.ts +294 -3
@@ -1,6 +1,8 @@
1
1
  import type { Component } from "../index.js";
2
2
  import type { RenderResultOptions } from "./renderer.js";
3
3
  import type { Theme } from "../theme/theme.js";
4
+ import type { TspChecklistPhase } from "@oh-my-pi/pi-wire";
5
+ import type { NativeToolView, ToolRenderResult } from "./renderer.js";
4
6
  /** Lifecycle state of a todo item. */
5
7
  export type TodoStatus = "pending" | "in_progress" | "completed" | "abandoned" | "blocked";
6
8
  /** Operation names accepted by the todo tool and echoed in successful result details. */
@@ -102,6 +104,14 @@ export declare const TODO_STRIKE_REVEAL_FRAMES = 12;
102
104
  export declare const TODO_STRIKE_TOTAL_FRAMES: number;
103
105
  /** Wire the live-subagent description source for {@link todoToolRenderer}. */
104
106
  export declare function setActiveTodoDescriptionsProvider(provider: () => readonly string[]): void;
107
+ /**
108
+ * Checklist phases for native terminals: plain phase titles (no roman
109
+ * numerals — the terminal numbers nothing), completed phases folded.
110
+ */
111
+ export declare function todoChecklistPhases(phases: readonly {
112
+ name: string;
113
+ tasks: readonly TodoItem[];
114
+ }[], isMatched?: (task: TodoItem) => boolean): TspChecklistPhase[];
105
115
  /** Render todo operations and phased task snapshots. */
106
116
  export declare const todoToolRenderer: {
107
117
  renderCall(args: TodoRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component;
@@ -113,6 +123,8 @@ export declare const todoToolRenderer: {
113
123
  details?: TodoToolDetails;
114
124
  isError?: boolean;
115
125
  }, options: RenderResultOptions, uiTheme: Theme, args?: TodoRenderArgs): Component;
126
+ describeCall(args: TodoRenderArgs): NativeToolView;
127
+ describeResult(result: ToolRenderResult<TodoToolDetails>, options: RenderResultOptions): NativeToolView | undefined;
116
128
  mergeCallAndResult: true;
117
129
  };
118
130
  export {};
@@ -1,6 +1,6 @@
1
1
  import type { Component } from "../tui.js";
2
2
  import type { Theme } from "../theme/theme.js";
3
- import type { RenderResultOptions } from "./renderer.js";
3
+ import type { NativeToolView, RenderResultOptions, ToolRenderResult } from "./renderer.js";
4
4
  /** Operation represented by a worker-session tool result. */
5
5
  export type VibeOp = "spawn" | "send" | "wait" | "kill" | "list";
6
6
  /** Details payload shared by every vibe tool for TUI rendering. */
@@ -120,5 +120,7 @@ export declare function createVibeToolRenderer(op: VibeOp): {
120
120
  details?: VibeToolDetails;
121
121
  isError?: boolean;
122
122
  }, options: RenderResultOptions, uiTheme: Theme, args?: VibeRenderArgs): Component;
123
+ describeCall(args: VibeRenderArgs): NativeToolView | undefined;
124
+ describeResult(result: ToolRenderResult<VibeToolDetails>, _options: RenderResultOptions, args?: VibeRenderArgs): NativeToolView | undefined;
123
125
  };
124
126
  export {};
@@ -5,6 +5,7 @@ import { type ConfiguredThinkingLevel } from "../render/render-utils.js";
5
5
  import type { StructuredSubagentOutput } from "./task.js";
6
6
  import type { RenderResultOptions, ToolActivitySummary } from "./renderer.js";
7
7
  import type { IrcDeliveryReceipt, IrcMessage } from "./irc.js";
8
+ import type { NativeToolView, ToolRenderResult } from "./renderer.js";
8
9
  /** Whether a wait snapshot contains only running jobs and no cancellations. */
9
10
  export declare function isWaitingPollDetails(details: unknown): boolean;
10
11
  /** Coordination details retained by wait and background job operations. */
@@ -119,6 +120,8 @@ export declare const waitToolRenderer: {
119
120
  mergeCallAndResult: true;
120
121
  activitySummary(): ToolActivitySummary;
121
122
  renderCall: typeof waitRenderCall;
123
+ describeCall(): NativeToolView;
124
+ describeResult(result: ToolRenderResult<CoordinationDetails>, options: RenderResultOptions): NativeToolView | undefined;
122
125
  renderResult(result: {
123
126
  content: Array<{
124
127
  type: string;
@@ -1,3 +1,4 @@
1
+ import type { NativeToolView, ToolRenderResult } from "./renderer.js";
1
2
  /**
2
3
  * Web Search TUI Rendering
3
4
  *
@@ -28,9 +29,16 @@ export declare function renderSearchCall(args: {
28
29
  query?: string;
29
30
  [key: string]: unknown;
30
31
  }, _options: RenderResultOptions, theme: Theme): Component;
32
+ type SearchRenderArgs = {
33
+ query?: string;
34
+ [key: string]: unknown;
35
+ };
31
36
  /** Render web search queries, answers, and cited sources. */
32
37
  export declare const webSearchToolRenderer: {
33
38
  renderCall: typeof renderSearchCall;
34
39
  renderResult: typeof renderSearchResult;
40
+ describeCall(args: SearchRenderArgs): NativeToolView;
41
+ describeResult(result: ToolRenderResult<SearchRenderDetails>, _options: RenderResultOptions, args?: SearchRenderArgs): NativeToolView | undefined;
35
42
  mergeCallAndResult: true;
36
43
  };
44
+ export {};
@@ -6,7 +6,7 @@ import { type ProcWriteDetails } from "./proc-render.js";
6
6
  import { type CfgWriteDetails } from "./cfg-render.js";
7
7
  import type { FileDiagnosticsResult } from "./lsp.js";
8
8
  import type { OutputMeta } from "./output-meta.js";
9
- import type { RenderResultOptions, ToolActivityContext, ToolActivitySummary } from "./renderer.js";
9
+ import type { NativeToolView, RenderResultOptions, ToolActivityContext, ToolActivitySummary } from "./renderer.js";
10
10
  import { type XdevRenderDispatch, type XdevMountedRenderer } from "./xdev.js";
11
11
  /** Details returned by the write tool for transcript rendering. */
12
12
  export interface WriteToolDetails {
@@ -76,6 +76,19 @@ export declare const writeToolRenderer: {
76
76
  }, options: RenderResultOptions & {
77
77
  renderContext?: WriteRenderContext;
78
78
  }, uiTheme: Theme, args?: WriteRenderArgs): Component;
79
+ describeCall(args: WriteRenderArgs, options: RenderResultOptions & {
80
+ renderContext?: WriteRenderContext;
81
+ }): NativeToolView | undefined;
82
+ describeResult(result: {
83
+ content: Array<{
84
+ type: string;
85
+ text?: string;
86
+ }>;
87
+ details?: WriteToolDetails;
88
+ isError?: boolean;
89
+ }, options: RenderResultOptions & {
90
+ renderContext?: WriteRenderContext;
91
+ }, args?: WriteRenderArgs): NativeToolView | undefined;
79
92
  mergeCallAndResult: true;
80
93
  forceFirstResultViewportRepaint: (args: unknown, options: RenderResultOptions) => boolean;
81
94
  };
@@ -2,9 +2,12 @@ import type { ToolTier } from "@oh-my-pi/pi-agent-core";
2
2
  import { type Component } from "../index.js";
3
3
  import type { Theme } from "../theme/theme.js";
4
4
  import type { RenderResultOptions, ToolActivitySummary, ToolRenderer } from "./renderer.js";
5
+ import type { NativeToolView } from "./renderer.js";
5
6
  /** Mounted device display callbacks, independent of tool execution state. */
6
7
  export interface XdevMountedRenderer {
7
8
  label?: string;
9
+ describeCall?: ToolRenderer["describeCall"];
10
+ describeResult?: ToolRenderer["describeResult"];
8
11
  renderCall?(...args: Parameters<ToolRenderer["renderCall"]>): unknown;
9
12
  renderResult?(...args: Parameters<ToolRenderer["renderResult"]>): unknown;
10
13
  mergeCallAndResult?: boolean;
@@ -50,6 +53,16 @@ export declare function xdevActivitySummary(name: string, content: unknown, reso
50
53
  * nothing) when no renderer produces output.
51
54
  */
52
55
  export declare function renderXdevCall(name: string, content: unknown, options: RenderResultOptions, theme: Theme, resolveMounted?: (name: string) => XdevMountedRenderer | undefined): Component | undefined;
56
+ /** TSP call view for an `xd://` write: queued card until execution, then the device renderer's own view. */
57
+ export declare function describeXdevCall(name: string, content: unknown, options: RenderResultOptions, resolveMounted?: (name: string) => XdevMountedRenderer | undefined): NativeToolView | undefined;
58
+ /** TSP result view for an `xd://` dispatch, forwarded to the device renderer. */
59
+ export declare function describeXdevResult(dispatch: XdevRenderDispatch, result: {
60
+ content: Array<{
61
+ type: string;
62
+ text?: string;
63
+ }>;
64
+ isError?: boolean;
65
+ }, options: RenderResultOptions, resolveMounted?: (name: string) => XdevMountedRenderer | undefined): NativeToolView | undefined;
53
66
  /** Forward an `xd://` dispatch result to the mounted tool's renderer. */
54
67
  export declare function renderXdevResult(dispatch: XdevRenderDispatch, result: {
55
68
  content: Array<{
@@ -1,4 +1,6 @@
1
+ import type { TspFrame, TspNode, TspText } from "@oh-my-pi/pi-wire";
1
2
  import { ImageBudget } from "./components/image.js";
3
+ import type { DescribeContext, NativeNode, NativeUiEvent } from "./native/node.js";
2
4
  import { type Terminal } from "./terminal.js";
3
5
  import { visibleWidth } from "./utils.js";
4
6
  /** Full-attribute reset terminating each rendered content row. */
@@ -109,6 +111,35 @@ export interface Component {
109
111
  * last time.
110
112
  */
111
113
  render(width: number): readonly string[];
114
+ /**
115
+ * Describe the component semantically for a Tern Surface Protocol
116
+ * terminal (see `native/node.ts`). Called instead of `render()` when the
117
+ * native backend is active. Return the same node object while nothing
118
+ * changed; return null to fall back to `render()` rows.
119
+ */
120
+ describe?(cx: DescribeContext): NativeNode | null;
121
+ /**
122
+ * Props for the native `overlay` wrapper when this component is shown as
123
+ * an overlay: the sheet's `role` (Tern styles `omp.overlay.*` roles as
124
+ * glass sheets, so the component's own root must not draw a second frame),
125
+ * `head` spans for the sheet's title row, and `size`/`anchor` overriding
126
+ * the ones derived from the overlay options.
127
+ */
128
+ nativeOverlay?: {
129
+ role?: string;
130
+ head?: TspText;
131
+ size?: "sm" | "md" | "lg" | "full";
132
+ anchor?: "center" | "top" | "bottom";
133
+ };
134
+ /**
135
+ * True when this component, shown as an overlay, describes a data-first
136
+ * sheet (`picker`, `prefs`) that is its own frame: the backend puts it
137
+ * directly in `layer` with no `overlay` wrapper. Usually
138
+ * `cx.supports("picker")`, so older terminals keep the wrapped fallback.
139
+ */
140
+ nativeSheet?(cx: DescribeContext): boolean;
141
+ /** User actions on nodes this component described (toggle, select, activate, custom). */
142
+ handleNativeEvent?(event: NativeUiEvent): void;
112
143
  /**
113
144
  * Optional handler for keyboard input when component has focus
114
145
  */
@@ -269,6 +300,7 @@ export declare class Container implements Component {
269
300
  */
270
301
  dispose(): void;
271
302
  render(width: number): readonly string[];
303
+ describe(_cx: DescribeContext): NativeNode | null;
272
304
  }
273
305
  /**
274
306
  * Merge runs of byte-adjacent SGR sequences (`CSI [0-9;:]* m`) into one. Only
@@ -382,6 +414,23 @@ export declare class TUI extends Container {
382
414
  setInlineMouseTrackingProvider(provider: (() => boolean) | undefined): void;
383
415
  invalidate(): void;
384
416
  start(options?: TUIStartOptions): void;
417
+ /** Whether frames go to a Tern Surface Protocol surface instead of the row renderer. */
418
+ get nativeRendering(): boolean;
419
+ /**
420
+ * Close the TSP surfaces ahead of {@link stop}, before the exit drains
421
+ * input: the terminal answers nothing once they are closed, and whatever it
422
+ * already sent (acks, events) is read and dropped here instead of reaching
423
+ * the shell as typed text. A render already requested (the exit's status
424
+ * line) goes out first; none is forced, and nothing renders from now until
425
+ * `stop()`.
426
+ */
427
+ closeNative(): void;
428
+ /** Reference document the TSP terminal should hold (debug mirror only). */
429
+ getNativeDocument(): TspNode | undefined;
430
+ /** Most recent TSP frames sent (debug mirror only). */
431
+ getNativeFrames(count?: number): readonly TspFrame[];
432
+ /** `rows` fallback nodes in the last native frame. */
433
+ get nativeFallbackCount(): number;
385
434
  /**
386
435
  * Take ownership of stdin after a `deferInput` start: raw mode, input
387
436
  * handlers, and the response-eliciting capability probes start() skipped.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-tui",
4
- "version": "18.4.3",
4
+ "version": "18.4.4",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": {
@@ -41,14 +41,14 @@
41
41
  "gen:glyphs": "bun scripts/gen-glyphs.ts"
42
42
  },
43
43
  "dependencies": {
44
- "@oh-my-pi/omptype": "18.4.3",
45
- "@oh-my-pi/pi-agent-core": "18.4.3",
46
- "@oh-my-pi/pi-ai": "18.4.3",
47
- "@oh-my-pi/pi-catalog": "18.4.3",
48
- "@oh-my-pi/pi-natives": "18.4.3",
49
- "@oh-my-pi/pi-utils": "18.4.3",
50
- "@oh-my-pi/pi-wire": "18.4.3",
51
- "@oh-my-pi/snapcompact": "18.4.3"
44
+ "@oh-my-pi/omptype": "18.4.4",
45
+ "@oh-my-pi/pi-agent-core": "18.4.4",
46
+ "@oh-my-pi/pi-ai": "18.4.4",
47
+ "@oh-my-pi/pi-catalog": "18.4.4",
48
+ "@oh-my-pi/pi-natives": "18.4.4",
49
+ "@oh-my-pi/pi-utils": "18.4.4",
50
+ "@oh-my-pi/pi-wire": "18.4.4",
51
+ "@oh-my-pi/snapcompact": "18.4.4"
52
52
  },
53
53
  "devDependencies": {
54
54
  "kitty-vt-wasm": "^0.2.0"
@@ -15,6 +15,28 @@ import {
15
15
  isBetter,
16
16
  } from "./autoresearch-data";
17
17
  import { formatNum, type ExperimentResult, type ExperimentState } from "../tools/autoresearch";
18
+ import type { TspSpan, TspTableColumn, TspText } from "@oh-my-pi/pi-wire";
19
+ import { card, col, elapsed, keyed, node, row, span, text } from "../native/describe";
20
+ import type { DescribeContext, NativeNode } from "../native/node";
21
+ import { hintsRow } from "../native/overlay";
22
+ import { Memo } from "../native/memo";
23
+ import { isNativeRendering } from "../native/state";
24
+
25
+ /** The widget's ANSI `Text`, describing itself from the runtime instead of its pre-rendered lines. */
26
+ class DashboardWidget extends Text {
27
+ readonly #build: (cx: DescribeContext) => NativeNode;
28
+ #node: NativeNode | undefined;
29
+
30
+ constructor(content: string, build: (cx: DescribeContext) => NativeNode) {
31
+ super(content, 0, 0);
32
+ this.#build = build;
33
+ }
34
+
35
+ override describe(cx: DescribeContext): NativeNode {
36
+ this.#node ??= this.#build(cx);
37
+ return this.#node;
38
+ }
39
+ }
18
40
 
19
41
  /** Experiment runtime fields rendered by the dashboard. */
20
42
  export interface AutoresearchDashboardRuntime {
@@ -86,7 +108,9 @@ export function createDashboardController(): DashboardController {
86
108
 
87
109
  ctx.ui.setWidget("autoresearch", (_tui, theme) => {
88
110
  if (state.results.length === 0 && runtime.runningExperiment) {
89
- return new Text(renderRunningOnly(runtime, state, theme), 0, 0);
111
+ return new DashboardWidget(renderRunningOnly(runtime, state, theme), () =>
112
+ describeRunningOnly(runtime, state),
113
+ );
90
114
  }
91
115
  if (runtime.dashboardExpanded) {
92
116
  const width = process.stdout.columns ?? 120;
@@ -94,9 +118,19 @@ export function createDashboardController(): DashboardController {
94
118
  renderExpandedHeader(runtime, width, theme),
95
119
  ...renderDashboardLines(runtime, width, theme, 8),
96
120
  ];
97
- return new Text(lines.join("\n"), 0, 0);
121
+ return new DashboardWidget(lines.join("\n"), cx =>
122
+ card({ role: "omp.widget.autoresearch", head: describeTitle(runtime) }, [
123
+ ...describeDashboard(runtime, 8, cx.supports("chart")),
124
+ hintsRow([
125
+ { keys: ["ctrl+x"], label: "collapse" },
126
+ { keys: ["ctrl+shift+x"], label: "overlay" },
127
+ ]),
128
+ ]),
129
+ );
98
130
  }
99
- return new Text(renderCollapsedLine(runtime, state, theme), 0, 0);
131
+ return new DashboardWidget(renderCollapsedLine(runtime, state, theme), () =>
132
+ describeCollapsed(runtime, state),
133
+ );
100
134
  });
101
135
  },
102
136
  async showOverlay(ctx, runtime): Promise<void> {
@@ -104,7 +138,8 @@ export function createDashboardController(): DashboardController {
104
138
  await ctx.ui.custom<void>(
105
139
  (tui, theme, _keybindings, done) => {
106
140
  overlayTui = tui;
107
- if (!spinnerTimer) {
141
+ // Repaint-only: the native overlay declares a spinner and elapsed timer instead.
142
+ if (!spinnerTimer && !isNativeRendering()) {
108
143
  spinnerTimer = setInterval(() => {
109
144
  spinnerFrame += 1;
110
145
  requestRender();
@@ -112,7 +147,56 @@ export function createDashboardController(): DashboardController {
112
147
  }
113
148
 
114
149
  let scrollView: ScrollView | undefined;
150
+ const native = new Memo();
115
151
  return {
152
+ /** A glass sheet titled by the experiment (the panels' sheet style); the body is borderless. */
153
+ get nativeOverlay() {
154
+ return { role: "omp.overlay.autoresearch", head: describeTitle(runtime), size: "lg" as const };
155
+ },
156
+ describe(cx: DescribeContext): NativeNode {
157
+ const state = runtime.state;
158
+ const chart = cx.supports("chart");
159
+ return native.get(
160
+ [
161
+ chart,
162
+ state,
163
+ state.results.length,
164
+ state.results.at(-1),
165
+ state.bestMetric,
166
+ state.confidence,
167
+ state.currentSegment,
168
+ state.name,
169
+ runtime.autoresearchMode,
170
+ runtime.lastRunSummary,
171
+ runtime.runningExperiment,
172
+ ],
173
+ () => {
174
+ const running = runtime.runningExperiment;
175
+ const children: NativeNode[] = describeDashboard(runtime, 0, chart);
176
+ if (running) {
177
+ children.push(
178
+ row(
179
+ [
180
+ node("spinner", { label: [span("running", "warning")], tone: "warning" }),
181
+ elapsed(Date.now() - running.startedAt),
182
+ text([span(replaceTabs(running.command), "warning")], { truncate: "end" }),
183
+ ],
184
+ { gap: "sm" },
185
+ ),
186
+ );
187
+ }
188
+ children.push(
189
+ hintsRow([
190
+ { keys: ["up", "down", "j", "k"], label: "scroll" },
191
+ { keys: ["pageUp", "pageDown"], label: "page" },
192
+ { keys: ["g", "shift+g"], label: "top/bottom" },
193
+ { keys: ["escape"], label: "close" },
194
+ ]),
195
+ );
196
+ return col(children, { gap: "md", role: "omp.app.autoresearch" });
197
+ },
198
+ );
199
+ },
116
200
  render(width: number): readonly string[] {
117
201
  const terminalRows = process.stdout.rows ?? 40;
118
202
  const header = renderExpandedHeader(runtime, width, theme);
@@ -163,6 +247,280 @@ export function createDashboardController(): DashboardController {
163
247
  };
164
248
  }
165
249
 
250
+ // -- native ------------------------------------------------------------------
251
+
252
+ /** Card/overlay title: the experiment name plus its mode status. */
253
+ function describeTitle(runtime: AutoresearchDashboardRuntime): TspSpan[] {
254
+ const state = runtime.state;
255
+ const spans = [span(state.name ? `autoresearch: ${replaceTabs(state.name)}` : "autoresearch", "accent")];
256
+ const status = renderModeStatus(runtime, state);
257
+ if (status) spans.push(span(` · ${status}`, "muted"));
258
+ return spans;
259
+ }
260
+
261
+ /** Widget shown while the very first run is in flight. */
262
+ function describeRunningOnly(runtime: AutoresearchDashboardRuntime, state: ExperimentState): NativeNode {
263
+ const children: NativeNode[] = [
264
+ node("spinner", { label: [span("autoresearch", "accent"), span(" running", "warning")], tone: "warning" }),
265
+ ];
266
+ if (runtime.runningExperiment) children.push(elapsed(Date.now() - runtime.runningExperiment.startedAt));
267
+ const details: TspSpan[] = [];
268
+ if (state.name) details.push(span(`| ${replaceTabs(state.name)}`, "dim"));
269
+ if (runtime.runningExperiment) details.push(span(` | ${replaceTabs(runtime.runningExperiment.command)}`, "dim"));
270
+ if (details.length > 0) children.push(text(details, { truncate: "end" }));
271
+ return row(children, { gap: "sm", role: "omp.widget.autoresearch" });
272
+ }
273
+
274
+ /** One-line collapsed widget: run counts, best/baseline, confidence and mode. */
275
+ function describeCollapsed(runtime: AutoresearchDashboardRuntime, state: ExperimentState): NativeNode {
276
+ const role = "omp.widget.autoresearch";
277
+ const hint = hintsRow([{ keys: ["ctrl+x"], label: "expand" }]);
278
+ if (runtime.lastRunSummary) {
279
+ const spans = [
280
+ span("autoresearch", "accent"),
281
+ span(` pending run #${runtime.lastRunSummary.runNumber}`, "warning"),
282
+ span(runtime.lastRunSummary.passed ? " pass" : " fail", "dim"),
283
+ ];
284
+ if (runtime.lastRunSummary.parsedPrimary !== null) {
285
+ spans.push(
286
+ span(
287
+ ` | ${state.metricName}=${formatNum(runtime.lastRunSummary.parsedPrimary, state.metricUnit)}`,
288
+ "muted",
289
+ ),
290
+ );
291
+ }
292
+ spans.push(span(" | log_experiment required", "warning"));
293
+ if (!runtime.autoresearchMode) spans.push(span(" | mode off", "dim"));
294
+ return text(spans, { truncate: "end", role });
295
+ }
296
+ if (state.results.length === 0) {
297
+ const spans = [
298
+ span("autoresearch", "accent"),
299
+ span(` ${runtime.autoresearchMode ? "baseline pending" : "mode off"}`, "warning"),
300
+ ];
301
+ if (state.name) spans.push(span(` | ${replaceTabs(state.name)}`, "dim"));
302
+ if (runtime.autoresearchMode) spans.push(span(" | run the baseline", "dim"));
303
+ return text(spans, { truncate: "end", role });
304
+ }
305
+ const current = currentResults(state.results, state.currentSegment);
306
+ const counts = statusCounts(current);
307
+ const best = findBestResult(state);
308
+ const archivedRuns = Math.max(0, state.results.length - current.length);
309
+ const spans = [
310
+ span("autoresearch", "accent"),
311
+ span(` ${current.length} runs`, "muted"),
312
+ span(` ${counts.keep} kept`, "success"),
313
+ ];
314
+ if (archivedRuns > 0) spans.push(span(` +${archivedRuns} archived`, "dim"));
315
+ if (counts.crash > 0) spans.push(span(` ${counts.crash} crash`, "error"));
316
+ if (counts.checks_failed > 0) spans.push(span(` ${counts.checks_failed} checks_failed`, "error"));
317
+ spans.push(span(" | ", "dim"));
318
+ if (best && state.bestMetric !== null && best.result.metric !== state.bestMetric) {
319
+ spans.push(span(`best ${formatNum(best.result.metric, state.metricUnit)}`, "warning"));
320
+ spans.push(span(` baseline ${formatNum(state.bestMetric, state.metricUnit)}`, "dim"));
321
+ } else if (state.bestMetric !== null) {
322
+ spans.push(span(`baseline ${formatNum(state.bestMetric, state.metricUnit)}`, "warning"));
323
+ } else {
324
+ spans.push(span("no kept runs yet", "warning"));
325
+ }
326
+ if (state.confidence !== null) {
327
+ spans.push(span(" | ", "dim"));
328
+ spans.push(span(`conf ${state.confidence.toFixed(1)}x`, confidenceToken(state.confidence)));
329
+ }
330
+ const children: NativeNode[] = [text(spans, { truncate: "end" })];
331
+ if (runtime.runningExperiment) {
332
+ children.push(text([span("| running", "dim")]), elapsed(Date.now() - runtime.runningExperiment.startedAt));
333
+ } else if (!runtime.autoresearchMode) {
334
+ children.push(text([span(`| ${renderModeStatus(runtime, state)}`, "dim")]));
335
+ }
336
+ children.push(hint);
337
+ return row(children, { gap: "sm", role });
338
+ }
339
+
340
+ /**
341
+ * Summary `kv`, the metric per run as a `bars` chart when the terminal draws
342
+ * `chart` (`chart`), and the run `table`; `maxRows > 0` keeps only the latest runs.
343
+ */
344
+ function describeDashboard(runtime: AutoresearchDashboardRuntime, maxRows: number, chart: boolean): NativeNode[] {
345
+ const state = runtime.state;
346
+ if (state.results.length === 0) {
347
+ const pending = runtime.lastRunSummary;
348
+ if (pending) {
349
+ const items: { k: string; v: TspText }[] = [
350
+ { k: "Pending run", v: `#${pending.runNumber}` },
351
+ {
352
+ k: "Result",
353
+ v: `${pending.passed ? "passed" : "failed"}${pending.parsedPrimary !== null ? ` ${state.metricName} ${formatNum(pending.parsedPrimary, state.metricUnit)}` : ""}`,
354
+ },
355
+ { k: "Next action", v: "finish log_experiment before starting another run." },
356
+ ];
357
+ if (!runtime.autoresearchMode) items.push({ k: "Mode", v: "off" });
358
+ return [node("kv", { items, layout: "grid" }, undefined, "summary")];
359
+ }
360
+ if (runtime.autoresearchMode) {
361
+ return [
362
+ node(
363
+ "kv",
364
+ {
365
+ items: [
366
+ { k: "Current segment", v: "0 runs" },
367
+ { k: "Baseline", v: "pending" },
368
+ { k: "Next action", v: "run and log the baseline experiment." },
369
+ ],
370
+ layout: "grid",
371
+ },
372
+ undefined,
373
+ "summary",
374
+ ),
375
+ ];
376
+ }
377
+ return [keyed(text([span("No experiments logged yet.", "dim")]), "summary")];
378
+ }
379
+
380
+ const current = currentResults(state.results, state.currentSegment);
381
+ const counts = statusCounts(current);
382
+ const baseline = findBaselineMetric(state.results, state.currentSegment);
383
+ const baselineRunNumber = findBaselineRunNumber(state.results, state.currentSegment);
384
+ const baselineSecondary = findBaselineSecondary(state.results, state.currentSegment, state.secondaryMetrics);
385
+ const best = findBestResult(state);
386
+ const items: { k: string; v: TspText }[] = [
387
+ {
388
+ k: "Current segment",
389
+ v: [
390
+ span(`${current.length} runs `),
391
+ span(`${counts.keep} kept`, "success"),
392
+ span(` ${counts.discard} discarded`, "warning"),
393
+ span(` ${counts.crash} crashed`, counts.crash > 0 ? "error" : undefined),
394
+ span(` ${counts.checks_failed} checks_failed`, counts.checks_failed > 0 ? "error" : undefined),
395
+ ],
396
+ },
397
+ {
398
+ k: "Baseline",
399
+ v: `${formatNum(baseline, state.metricUnit)}${baselineRunNumber ? ` (#${baselineRunNumber})` : ""}`,
400
+ },
401
+ ];
402
+ if (state.results.length > current.length) {
403
+ items.push({ k: "Archived", v: `${state.results.length - current.length} runs from earlier segments` });
404
+ }
405
+ if (runtime.lastRunSummary) {
406
+ items.push({
407
+ k: "Pending run",
408
+ v: [
409
+ span(`#${runtime.lastRunSummary.runNumber} (${runtime.lastRunSummary.passed ? "passed" : "failed"})`),
410
+ span(" — log_experiment required", "warning"),
411
+ ],
412
+ });
413
+ }
414
+ if (!runtime.autoresearchMode) items.push({ k: "Mode", v: renderModeStatus(runtime, state) });
415
+ if (best) {
416
+ const bestRunNumber = best.result.runNumber ?? best.index + 1;
417
+ const value: TspSpan[] = [
418
+ span(`${formatNum(best.result.metric, state.metricUnit)} (#${bestRunNumber})`, "strong"),
419
+ ];
420
+ if (baseline !== null && baseline !== 0 && best.result.metric !== baseline) {
421
+ const delta = ((best.result.metric - baseline) / baseline) * 100;
422
+ value.push(span(` ${delta > 0 ? "+" : ""}${delta.toFixed(1)}%`, "num"));
423
+ }
424
+ if (state.confidence !== null) {
425
+ value.push(span(` conf ${state.confidence.toFixed(1)}x`, confidenceToken(state.confidence)));
426
+ }
427
+ items.push({ k: "Best", v: value });
428
+ const details = state.secondaryMetrics
429
+ .map(metric =>
430
+ renderSecondarySummary(
431
+ metric.name,
432
+ best.result.metrics[metric.name],
433
+ baselineSecondary[metric.name],
434
+ metric.unit,
435
+ ),
436
+ )
437
+ .filter((detail): detail is string => Boolean(detail));
438
+ if (details.length > 0) items.push({ k: "Secondary", v: details.join(" ") });
439
+ }
440
+
441
+ const cols: TspTableColumn[] = [
442
+ { id: "run", head: [span("#", "muted")], align: "end", priority: 3 },
443
+ { id: "commit", head: [span("commit", "muted")], truncate: "end", priority: 2 },
444
+ { id: "metric", head: [span(state.metricName, "warning")], align: "end", priority: 5 },
445
+ ...state.secondaryMetrics.map((metric, index): TspTableColumn => ({
446
+ id: `secondary${index}`,
447
+ head: [span(metric.name, "muted")],
448
+ align: "end",
449
+ truncate: "end",
450
+ priority: 1,
451
+ })),
452
+ { id: "status", head: [span("status", "muted")], priority: 4 },
453
+ { id: "description", head: [span("description", "muted")], truncate: "end", grow: 1, priority: 2 },
454
+ ];
455
+ const indexed = state.results
456
+ .map((result, index) => ({ result, index }))
457
+ .filter(({ result }) => result.segment === state.currentSegment);
458
+ const visible = maxRows > 0 ? indexed.slice(-maxRows) : indexed;
459
+ const rows = visible.map(({ result, index }) => {
460
+ const token = result.status === "keep" ? "success" : result.status === "discard" ? "warning" : "error";
461
+ const cells: Record<string, TspText> = {
462
+ run: [span(String(result.runNumber ?? index + 1), "dim")],
463
+ commit: [span(result.commit || "-", "accent")],
464
+ metric: [span(formatNum(result.metric, state.metricUnit), token)],
465
+ status: [span(result.status, token)],
466
+ description: [span(replaceTabs(result.description), "muted")],
467
+ };
468
+ state.secondaryMetrics.forEach((metric, metricIndex) => {
469
+ cells[`secondary${metricIndex}`] = renderSecondaryCell(
470
+ result.metrics[metric.name],
471
+ metric.unit,
472
+ baselineSecondary[metric.name],
473
+ );
474
+ });
475
+ return { id: String(index), cells };
476
+ });
477
+ const children: NativeNode[] = [node("kv", { items, layout: "grid" }, undefined, "summary")];
478
+ if (chart && visible.length >= 2) {
479
+ children.push(
480
+ node(
481
+ "chart",
482
+ {
483
+ kind: "bars",
484
+ series: visible.map(({ result, index }) => {
485
+ const run = result.runNumber ?? index + 1;
486
+ return {
487
+ label: `#${run}`,
488
+ value: result.metric,
489
+ title: `#${run} ${result.status} · ${formatNum(result.metric, state.metricUnit)} · ${replaceTabs(result.description)}`,
490
+ };
491
+ }),
492
+ token: "accent",
493
+ summary: [
494
+ span(`${state.metricName} per run`, "muted"),
495
+ ...(best ? [span(` · best ${formatNum(best.result.metric, state.metricUnit)}`, "success")] : []),
496
+ ],
497
+ size: "md",
498
+ role: "omp.autoresearch.trend",
499
+ },
500
+ undefined,
501
+ "trend",
502
+ ),
503
+ );
504
+ }
505
+ if (visible.length < indexed.length) {
506
+ children.push(keyed(text([span(`… ${indexed.length - visible.length} earlier runs hidden`, "dim")]), "hidden"));
507
+ }
508
+ children.push(node("table", { cols, rows, role: "omp.autoresearch.runs" }, undefined, "runs"));
509
+ return [keyed(col(children, { gap: "sm" }), "dashboard")];
510
+ }
511
+
512
+ function statusCounts(results: readonly ExperimentResult[]): Record<ExperimentResult["status"], number> {
513
+ const counts: Record<ExperimentResult["status"], number> = { keep: 0, discard: 0, crash: 0, checks_failed: 0 };
514
+ for (const result of results) counts[result.status] += 1;
515
+ return counts;
516
+ }
517
+
518
+ function confidenceToken(confidence: number): string {
519
+ return confidence >= 2 ? "success" : confidence >= 1 ? "warning" : "error";
520
+ }
521
+
522
+ // -- ANSI --------------------------------------------------------------------
523
+
166
524
  function renderRunningOnly(runtime: AutoresearchDashboardRuntime, state: ExperimentState, theme: Theme): string {
167
525
  const parts = [theme.fg("accent", "autoresearch"), theme.fg("warning", " running...")];
168
526
  if (state.name) {