@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
@@ -5,6 +5,11 @@ import { type KeyId, matchesKey } from "../keys";
5
5
  import { sliceWithWidth, truncateToWidth, visibleWidth } from "../utils";
6
6
  import { sanitizeDisplaySingleLine } from "../overlays/extensions/display-text";
7
7
  import { type ThemeColor, theme } from "../theme/theme";
8
+ import type { TspTone } from "@oh-my-pi/pi-wire";
9
+ import { card, node, row, span, text } from "../native/describe";
10
+ import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node";
11
+ import { actionBar, actionButton } from "../native/overlay";
12
+ import { Memo } from "../native/memo";
8
13
 
9
14
  /** Distinct states of a realtime call connection. */
10
15
  export type LivePhase = "connecting" | "listening" | "working" | "speaking" | "muted" | "error";
@@ -25,7 +30,17 @@ const PHASE_COLORS: Record<LivePhase, ThemeColor> = {
25
30
  muted: "dim",
26
31
  error: "error",
27
32
  };
33
+ const PHASE_TONES: Record<LivePhase, TspTone> = {
34
+ connecting: "muted",
35
+ listening: "success",
36
+ working: "warning",
37
+ speaking: "accent",
38
+ muted: "muted",
39
+ error: "error",
40
+ };
28
41
  const SPECTRUM_BLOCKS = [" ", "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"] as const;
42
+ /** Native mic meter resolution: the level snaps to 1/20 steps so decay ticks don't rebuild every frame. */
43
+ const METER_STEPS = 20;
29
44
 
30
45
  /** Configuration callbacks for user interactions in the visualizer. */
31
46
  export interface LiveVisualizerOptions {
@@ -56,6 +71,7 @@ export class LiveVisualizer implements Component {
56
71
  #displayLevel = 0;
57
72
  #frame = 0;
58
73
  #userTranscript = "";
74
+ readonly #native = new Memo();
59
75
 
60
76
  #cache:
61
77
  | {
@@ -135,6 +151,55 @@ export class LiveVisualizer implements Component {
135
151
  this.#panel.invalidate();
136
152
  }
137
153
 
154
+ /** The call panel's buttons run the same code as their keys. */
155
+ handleNativeEvent(event: NativeUiEvent): void {
156
+ if (event.type !== "action") return;
157
+ if (event.act === "mute") this.#options.onToggleMute();
158
+ else if (event.act === "end") this.#options.onStop();
159
+ }
160
+
161
+ /**
162
+ * Native call panel: phase status (a spinner while working), the mic level
163
+ * as a `meter` (a `progress` bar on terminals without it), the streaming
164
+ * transcript and the Mute/End buttons. The spectrum animation is
165
+ * ANSI-only; frame ticks leave this node unchanged.
166
+ */
167
+ describe(cx: DescribeContext): NativeNode {
168
+ const energy = this.#phase === "muted" ? 0 : Math.min(1, Math.sqrt(this.#displayLevel * 5));
169
+ const level = Math.round(energy * METER_STEPS) / METER_STEPS;
170
+ const meter = cx.supports("meter");
171
+ return this.#native.get([this.#phase, level, this.#userTranscript, meter], () => {
172
+ const phase = this.#phase;
173
+ const status =
174
+ phase === "working"
175
+ ? node("spinner", { label: [span(phase, PHASE_COLORS[phase])], tone: PHASE_TONES[phase] })
176
+ : text([span(`${PHASE_ICONS[phase]} ${phase}`, PHASE_COLORS[phase])]);
177
+ const tone = phase === "muted" ? "muted" : phase === "error" ? "error" : "success";
178
+ return card({ role: "omp.app.live", tone: PHASE_TONES[phase] }, [
179
+ node("row", { gap: "sm", align: "center" }, [status], "head"),
180
+ meter
181
+ ? row(
182
+ [
183
+ text([span("mic", "muted")]),
184
+ node("meter", { value: level, style: "bar", size: "md", tone, grow: 1 }),
185
+ ],
186
+ {
187
+ gap: "sm",
188
+ align: "center",
189
+ role: "omp.app.live.level",
190
+ },
191
+ )
192
+ : node("progress", { value: level, tone, label: [span("mic", "muted")] }),
193
+ text([span(this.#userTranscript, "accent")], { wrap: "none", truncate: "start" }),
194
+ actionBar([
195
+ null,
196
+ actionButton(phase === "muted" ? "Unmute" : "Mute", "mute", { keys: "space" }),
197
+ actionButton("End call", "end", { keys: "escape", tone: "error" }),
198
+ ]),
199
+ ]);
200
+ });
201
+ }
202
+
138
203
  /** Renders the microphone spectrum into a compact fixed-height panel. */
139
204
  render(width: number): readonly string[] {
140
205
  if (
@@ -6,6 +6,7 @@
6
6
  * `x` kill, `r` restart, `a` toggle all scopes, `q`/`esc`/`ctrl+c` quit.
7
7
  * Sub-views (info, logs): `esc`/`q` back.
8
8
  */
9
+ import * as path from "node:path";
9
10
  import { formatKeyHint, formatKeyHints } from "../app-keybindings";
10
11
  import { KeyValueList, type KeyValueRow } from "../components/key-value-list";
11
12
  import { ScrollView } from "../components/scroll-view";
@@ -13,6 +14,11 @@ import { renderTableRow, type TableColumn } from "../components/table";
13
14
  import { matchesKey } from "../keys";
14
15
  import { ProcessTerminal } from "../terminal";
15
16
  import { type Component, TUI } from "../tui";
17
+ import type { TspSpan, TspText, TspTone } from "@oh-my-pi/pi-wire";
18
+ import { col, compact, elapsed, keyed, node, row, span, stableKey, text } from "../native/describe";
19
+ import type { NativeNode, NativeUiEvent } from "../native/node";
20
+ import { actionBar, actionButton } from "../native/overlay";
21
+ import { Memo } from "../native/memo";
16
22
  import { truncateToWidth } from "../utils";
17
23
  import { formatDuration } from "@oh-my-pi/pi-utils";
18
24
  import chalk from "@oh-my-pi/pi-utils/chalk";
@@ -26,6 +32,7 @@ import {
26
32
  type PsScopeReport,
27
33
  type PsTarget,
28
34
  scopeHeader,
35
+ flagsCell,
29
36
  TABLE_HEADER,
30
37
  TERMINAL_STATES,
31
38
  tableCells,
@@ -42,6 +49,15 @@ interface FlatRow {
42
49
 
43
50
  type PsTopView = "table" | "info" | "logs";
44
51
 
52
+ type PsStatusTone = "success" | "warning" | "error" | "muted";
53
+
54
+ const STATUS_PAINT: Record<PsStatusTone, (text: string) => string> = {
55
+ success: chalk.green,
56
+ warning: chalk.yellow,
57
+ error: chalk.red,
58
+ muted: chalk.dim,
59
+ };
60
+
45
61
  /** Options accepted by the interactive monitor: scope selection from the list flags. */
46
62
  export interface PsTopOptions extends PsTarget {
47
63
  all: boolean;
@@ -81,8 +97,14 @@ export class PsTopComponent implements Component {
81
97
  #refreshing = false;
82
98
  #lastRefresh = 0;
83
99
  #status = "";
100
+ #statusText = "";
101
+ #statusTone: PsStatusTone = "muted";
84
102
  #statusAt = 0;
103
+ #logsError: string | undefined;
104
+ /** Process key a pointer `Kill` waits on for confirmation. */
105
+ #killConfirm: string | undefined;
85
106
  #disposed = false;
107
+ readonly #native = new Memo();
86
108
 
87
109
  constructor(ui: TUI, options: PsTopOptions, host: PsTopHost) {
88
110
  this.#ui = ui;
@@ -122,7 +144,7 @@ export class PsTopComponent implements Component {
122
144
  this.#restoreSelection();
123
145
  this.#ui.requestRender();
124
146
  } catch (error) {
125
- this.#setStatus(chalk.red(error instanceof Error ? error.message : String(error)));
147
+ this.#setStatus("error", error instanceof Error ? error.message : String(error));
126
148
  } finally {
127
149
  this.#refreshing = false;
128
150
  }
@@ -140,8 +162,10 @@ export class PsTopComponent implements Component {
140
162
  this.#selectedKey = this.#flat[this.#selected] ? flatKey(this.#flat[this.#selected]) : undefined;
141
163
  }
142
164
 
143
- #setStatus(text: string): void {
144
- this.#status = text;
165
+ #setStatus(tone: PsStatusTone, text: string): void {
166
+ this.#status = STATUS_PAINT[tone](text);
167
+ this.#statusText = text;
168
+ this.#statusTone = tone;
145
169
  this.#statusAt = Date.now();
146
170
  this.#ui.requestRender();
147
171
  }
@@ -152,19 +176,16 @@ export class PsTopComponent implements Component {
152
176
  const entry = this.#flat[this.#selected];
153
177
  if (!entry) return;
154
178
  const name = entry.row.snapshot.name;
155
- this.#setStatus(chalk.yellow(`${verb} ${name}…`));
179
+ this.#setStatus("warning", `${verb} ${name}…`);
156
180
  try {
157
181
  const daemon = await this.#host.act(entry.scope, name, verb);
158
182
  this.#setStatus(
159
- chalk.green(
160
- `${verb === "restart" ? "Restarted" : verb === "kill" ? "Killed" : "Stopped"} ${daemonLabel(daemon)}`,
161
- ),
183
+ "success",
184
+ `${verb === "restart" ? "Restarted" : verb === "kill" ? "Killed" : "Stopped"} ${daemonLabel(daemon)}`,
162
185
  );
163
186
  void this.#refresh();
164
187
  } catch (error) {
165
- this.#setStatus(
166
- chalk.red(`${verb} ${name} failed: ${error instanceof Error ? error.message : String(error)}`),
167
- );
188
+ this.#setStatus("error", `${verb} ${name} failed: ${error instanceof Error ? error.message : String(error)}`);
168
189
  }
169
190
  }
170
191
 
@@ -176,7 +197,7 @@ export class PsTopComponent implements Component {
176
197
  this.#view = "info";
177
198
  this.#ui.requestRender();
178
199
  } catch (error) {
179
- this.#setStatus(chalk.red(error instanceof Error ? error.message : String(error)));
200
+ this.#setStatus("error", error instanceof Error ? error.message : String(error));
180
201
  }
181
202
  }
182
203
 
@@ -186,6 +207,7 @@ export class PsTopComponent implements Component {
186
207
  this.#view = "logs";
187
208
  this.#logsLines = [];
188
209
  this.#logsState = "";
210
+ this.#logsError = undefined;
189
211
  const poll = async (): Promise<void> => {
190
212
  const current = this.#flat[this.#selected];
191
213
  if (this.#disposed || this.#view !== "logs" || !current) return;
@@ -197,9 +219,11 @@ export class PsTopComponent implements Component {
197
219
  );
198
220
  this.#logsLines = result.terminalRows ?? result.text.replace(/\n$/, "").split("\n");
199
221
  this.#logsState = result.state;
222
+ this.#logsError = undefined;
200
223
  this.#ui.requestRender();
201
224
  } catch (error) {
202
- this.#logsLines = [chalk.red(error instanceof Error ? error.message : String(error))];
225
+ this.#logsError = error instanceof Error ? error.message : String(error);
226
+ this.#logsLines = [chalk.red(this.#logsError)];
203
227
  this.#ui.requestRender();
204
228
  }
205
229
  };
@@ -236,17 +260,20 @@ export class PsTopComponent implements Component {
236
260
  }
237
261
  if (matchesKey(data, "up") || data === "k") this.#moveSelection(-1);
238
262
  else if (matchesKey(data, "down") || data === "j") this.#moveSelection(1);
239
- else if (data === "a") {
240
- this.#all = !this.#all;
241
- this.#setStatus(chalk.dim(this.#all ? "Showing all scopes" : "Showing current scope"));
242
- void this.#refresh();
243
- } else if (matchesKey(data, "enter") || data === "i") void this.#openInfo();
263
+ else if (data === "a") this.#toggleAll();
264
+ else if (matchesKey(data, "enter") || data === "i") void this.#openInfo();
244
265
  else if (data === "l") this.#openLogs();
245
266
  else if (data === "s") void this.#act("stop");
246
267
  else if (data === "x") void this.#act("kill");
247
268
  else if (data === "r") void this.#act("restart");
248
269
  }
249
270
 
271
+ #toggleAll(): void {
272
+ this.#all = !this.#all;
273
+ this.#setStatus("muted", this.#all ? "Showing all scopes" : "Showing current scope");
274
+ void this.#refresh();
275
+ }
276
+
250
277
  #moveSelection(delta: number): void {
251
278
  if (this.#flat.length === 0) return;
252
279
  this.#selected = Math.max(0, Math.min(this.#flat.length - 1, this.#selected + delta));
@@ -254,6 +281,340 @@ export class PsTopComponent implements Component {
254
281
  this.#ui.requestRender();
255
282
  }
256
283
 
284
+ // -- native --------------------------------------------------------------
285
+
286
+ /**
287
+ * Pointer actions: a click selects a process, a double click opens its info
288
+ * (Enter); the scope control switches between the current and all scopes;
289
+ * the action bar runs the same code as the keys, except that a pointer
290
+ * `Kill` asks first (the `x` key stays immediate).
291
+ */
292
+ handleNativeEvent(event: NativeUiEvent): void {
293
+ if (event.type === "action") {
294
+ this.#nativeAction(event.act);
295
+ return;
296
+ }
297
+ if (event.type !== "select" && event.type !== "activate") return;
298
+ if (event.item === "current" || event.item === "all") {
299
+ if ((event.item === "all") !== this.#all) this.#toggleAll();
300
+ return;
301
+ }
302
+ if (this.#view !== "table") return;
303
+ const index = this.#flat.findIndex(entry => stableKey(flatKey(entry)) === event.item);
304
+ if (index < 0) return;
305
+ this.#selected = index;
306
+ this.#selectedKey = flatKey(this.#flat[index]);
307
+ this.#killConfirm = undefined;
308
+ if (event.type === "activate") void this.#openInfo();
309
+ else this.#ui.requestRender();
310
+ }
311
+
312
+ #nativeAction(act: string): void {
313
+ switch (act) {
314
+ case "info":
315
+ void this.#openInfo();
316
+ return;
317
+ case "logs":
318
+ this.#openLogs();
319
+ return;
320
+ case "stop":
321
+ case "restart":
322
+ void this.#act(act);
323
+ return;
324
+ case "kill":
325
+ this.#killConfirm = this.#selectedKey;
326
+ this.#ui.requestRender();
327
+ return;
328
+ case "kill-confirm":
329
+ this.#killConfirm = undefined;
330
+ void this.#act("kill");
331
+ return;
332
+ case "kill-cancel":
333
+ this.#killConfirm = undefined;
334
+ this.#ui.requestRender();
335
+ return;
336
+ case "back":
337
+ this.#closeView();
338
+ return;
339
+ case "quit":
340
+ this.#done.resolve();
341
+ return;
342
+ }
343
+ }
344
+
345
+ /**
346
+ * The process monitor as a native page: a head (title, counts, the scope
347
+ * control, freshness, close), one section per broker scope with a
348
+ * selectable process list, the transient status, and an action bar that
349
+ * mirrors the keys. Info and logs replace the list.
350
+ */
351
+ describe(): NativeNode {
352
+ const statusVisible = Date.now() - this.#statusAt < STATUS_TTL_MS;
353
+ return this.#native.get(
354
+ [
355
+ this.#view,
356
+ this.#reports,
357
+ this.#selected,
358
+ this.#all,
359
+ this.#lastRefresh,
360
+ this.#info,
361
+ this.#logsLines,
362
+ this.#logsState,
363
+ this.#logsError,
364
+ statusVisible,
365
+ this.#statusText,
366
+ this.#statusTone,
367
+ this.#killConfirm,
368
+ ],
369
+ () => {
370
+ const body =
371
+ this.#view === "info"
372
+ ? this.#describeInfo()
373
+ : this.#view === "logs"
374
+ ? this.#describeLogs()
375
+ : this.#describeTable();
376
+ return col(
377
+ compact([
378
+ this.#describeHead(),
379
+ body,
380
+ statusVisible &&
381
+ this.#statusText !== "" &&
382
+ keyed(
383
+ text([span(this.#statusText, this.#statusTone)], { wrap: "word", role: "omp.app.status" }),
384
+ "status",
385
+ ),
386
+ this.#describeActions(),
387
+ ]),
388
+ { role: "omp.app.ps", gap: "md" },
389
+ );
390
+ },
391
+ );
392
+ }
393
+
394
+ #describeHead(): NativeNode {
395
+ const entry = this.#flat[this.#selected];
396
+ const left: NativeNode[] = [];
397
+ if (this.#view === "table") {
398
+ const running = this.#flat.filter(flat => !TERMINAL_STATES[flat.row.snapshot.state]).length;
399
+ const stopped = this.#flat.length - running;
400
+ left.push(
401
+ text("Processes", { role: "omp.app.title" }),
402
+ text(
403
+ [
404
+ span(`${running} running`, running > 0 ? "success" : "muted"),
405
+ ...(stopped > 0 ? [span(` · ${stopped} stopped`, "muted")] : []),
406
+ span(` · ${this.#reports.length} scope${this.#reports.length === 1 ? "" : "s"}`, "muted"),
407
+ ],
408
+ { truncate: "end" },
409
+ ),
410
+ );
411
+ } else {
412
+ left.push(
413
+ node("icon", {
414
+ name: "back",
415
+ role: "omp.app.ibtn",
416
+ title: "Back esc",
417
+ aria: "Back",
418
+ actions: { click: "back" },
419
+ }),
420
+ text(
421
+ this.#view === "logs" ? `Logs · ${entry?.row.snapshot.name ?? "?"}` : (entry?.row.snapshot.name ?? "?"),
422
+ {
423
+ role: "omp.app.title",
424
+ truncate: "end",
425
+ },
426
+ ),
427
+ );
428
+ const daemon = this.#view === "info" ? this.#info?.daemon : entry?.row.snapshot;
429
+ if (daemon) left.push(node("badge", { text: stateLabel(daemon), tone: daemonTone(daemon) }));
430
+ if (this.#view === "logs" && this.#logsState) left.push(text([span(this.#logsState, "muted")]));
431
+ }
432
+ const right: NativeNode[] = [];
433
+ if (this.#view === "table") {
434
+ right.push(
435
+ node(
436
+ "tabs",
437
+ {
438
+ items: [
439
+ {
440
+ id: "current",
441
+ label:
442
+ this.#target.dir !== undefined || this.#target.global !== undefined
443
+ ? "Target"
444
+ : "This project",
445
+ },
446
+ { id: "all", label: "All scopes" },
447
+ ],
448
+ active: this.#all ? "all" : "current",
449
+ role: "omp.app.seg",
450
+ },
451
+ undefined,
452
+ "scope",
453
+ ),
454
+ );
455
+ }
456
+ right.push(
457
+ this.#lastRefresh
458
+ ? row(
459
+ [text([span("updated", "dim")]), elapsed(Date.now() - this.#lastRefresh), text([span("ago", "dim")])],
460
+ {
461
+ gap: "xs",
462
+ align: "center",
463
+ role: "omp.app.fresh",
464
+ },
465
+ )
466
+ : row([node("spinner", { style: "dots" }), text([span("updating", "dim")])], {
467
+ gap: "xs",
468
+ align: "center",
469
+ role: "omp.app.fresh",
470
+ }),
471
+ node("icon", { name: "x", role: "omp.app.ibtn", title: "Quit q", aria: "Quit", actions: { click: "quit" } }),
472
+ );
473
+ return keyed(
474
+ row(
475
+ [
476
+ row(left, { gap: "sm", align: "center", role: "omp.app.where" }),
477
+ row(right, { gap: "md", align: "center", role: "omp.app.tools" }),
478
+ ],
479
+ { justify: "between", align: "center", role: "omp.app.head" },
480
+ ),
481
+ "head",
482
+ );
483
+ }
484
+
485
+ /** The action bar for the view, or the kill confirmation that replaces it. */
486
+ #describeActions(): NativeNode {
487
+ const entry = this.#flat[this.#selected];
488
+ if (
489
+ this.#view === "table" &&
490
+ entry &&
491
+ this.#killConfirm === this.#selectedKey &&
492
+ this.#killConfirm !== undefined
493
+ ) {
494
+ const pid = entry.row.snapshot.pid;
495
+ return keyed(
496
+ row(
497
+ [
498
+ text(
499
+ [
500
+ span(`Kill ${entry.row.snapshot.name}${pid === undefined ? "" : ` (pid ${pid})`}?`, "strong"),
501
+ span(" It stops at once, without cleanup.", "muted"),
502
+ ],
503
+ { truncate: "end", grow: 1 },
504
+ ),
505
+ actionButton("Cancel", "kill-cancel"),
506
+ actionButton("Kill", "kill-confirm", { tone: "error" }),
507
+ ],
508
+ { gap: "sm", align: "center", role: "omp.app.confirm", tone: "error" },
509
+ ),
510
+ "actions",
511
+ );
512
+ }
513
+ if (this.#view !== "table") {
514
+ return actionBar([
515
+ actionButton("Back", "back", { keys: "escape", tone: "accent" }),
516
+ ...(this.#view === "info" ? [actionButton("Logs", "logs")] : []),
517
+ ]);
518
+ }
519
+ if (!entry) return actionBar([null, actionButton("Quit", "quit", { keys: "q" })]);
520
+ return actionBar([
521
+ actionButton("Info", "info", { keys: "enter", tone: "accent" }),
522
+ actionButton("Logs", "logs", { keys: "l" }),
523
+ actionButton("Restart", "restart", { keys: "r" }),
524
+ actionButton("Stop", "stop", { keys: "s" }),
525
+ actionButton("Kill", "kill", { keys: "x", tone: "error", title: "Kill the process (asks first)" }),
526
+ null,
527
+ actionButton("Quit", "quit", { keys: "q" }),
528
+ ]);
529
+ }
530
+
531
+ #describeTable(): NativeNode {
532
+ if (this.#reports.length === 0) {
533
+ return keyed(
534
+ col(
535
+ [
536
+ text("No broker scopes", { role: "omp.app.empty-title" }),
537
+ text([
538
+ span("No omp process broker runs here. ", "muted"),
539
+ span(this.#all ? "Nothing runs anywhere." : "Show every scope with ", "muted"),
540
+ ...(this.#all ? [] : [span("a", "key"), span(".", "muted")]),
541
+ ]),
542
+ ],
543
+ { gap: "xs", align: "center", role: "omp.app.empty" },
544
+ ),
545
+ "empty",
546
+ );
547
+ }
548
+ const selected = this.#flat[this.#selected];
549
+ const sections = this.#reports.map(report =>
550
+ node(
551
+ "section",
552
+ { head: scopeSpans(report.scope), role: "omp.app.ps.scope" },
553
+ [
554
+ node(
555
+ "list",
556
+ {
557
+ selected:
558
+ selected && selected.scope.runtimeDir === report.scope.runtimeDir
559
+ ? stableKey(flatKey(selected))
560
+ : null,
561
+ empty: "No processes",
562
+ role: "omp.ps.processes",
563
+ },
564
+ report.daemons.map(daemon => describeProcess(report.scope, daemon)),
565
+ ),
566
+ ],
567
+ stableKey(report.scope.runtimeDir),
568
+ ),
569
+ );
570
+ return keyed(col(sections, { gap: "lg", grow: 1, role: "omp.app.ps.scopes" }), "scopes");
571
+ }
572
+
573
+ #describeInfo(): NativeNode {
574
+ const info = this.#info;
575
+ if (!info) {
576
+ return keyed(
577
+ row([node("spinner", { style: "dots" }), text([span("Loading…", "muted")])], { gap: "sm" }),
578
+ "info",
579
+ );
580
+ }
581
+ const { daemon, spec } = info;
582
+ const items: { k: string; v: TspText }[] = [
583
+ { k: "Command", v: [span(collapseCommand(formatCommand(spec)), "mono")] },
584
+ { k: "Directory", v: [span(spec.cwd, "path")] },
585
+ ];
586
+ if (daemon.pid !== undefined && !TERMINAL_STATES[daemon.state])
587
+ items.push({ k: "PID", v: [span(String(daemon.pid), "num")] });
588
+ if (daemon.exitReason) items.push({ k: "Exit", v: [span(daemon.exitReason, "error")] });
589
+ items.push({ k: "Restarts", v: `${daemon.restartCount} (policy ${spec.restart})` });
590
+ items.push({ k: "Owner", v: daemon.owner ?? "—" });
591
+ const flags = [spec.pty && "pty", spec.persist && "persist", spec.detached && "detached"].filter(Boolean);
592
+ items.push({ k: "Flags", v: flags.length > 0 ? flags.join(" · ") : "—" });
593
+ const body: NativeNode[] = [];
594
+ if (!TERMINAL_STATES[daemon.state]) {
595
+ body.push(
596
+ row([text([span("Up for", "muted")]), elapsed(Date.now() - daemon.startedAt)], {
597
+ gap: "xs",
598
+ role: "omp.app.fresh",
599
+ }),
600
+ );
601
+ }
602
+ body.push(node("kv", { items, layout: "grid" }));
603
+ return keyed(col(body, { role: "omp.ps.info", gap: "md" }), "info");
604
+ }
605
+
606
+ #describeLogs(): NativeNode {
607
+ if (this.#logsError) {
608
+ return keyed(text([span(this.#logsError, "error mono")], { wrap: "word", role: "omp.ps.logs" }), "logs");
609
+ }
610
+ return node(
611
+ "ansi",
612
+ { text: this.#logsLines.join("\n"), follow: true, role: "omp.ps.logs", grow: 1 },
613
+ undefined,
614
+ "logs",
615
+ );
616
+ }
617
+
257
618
  // -- render ------------------------------------------------------------
258
619
 
259
620
  render(width: number): readonly string[] {
@@ -407,6 +768,76 @@ function flatKey(entry: FlatRow): string {
407
768
  return `${entry.scope.runtimeDir}\u0000${entry.row.snapshot.name}`;
408
769
  }
409
770
 
771
+ /** Semantic tone of a process state (the ANSI STATE cell's colour). */
772
+ function daemonTone(snapshot: DaemonSnapshot): TspTone {
773
+ if (snapshot.state === "ready" || snapshot.state === "running") return "success";
774
+ if (snapshot.state === "failed") return "error";
775
+ return TERMINAL_STATES[snapshot.state] ? "muted" : "warning";
776
+ }
777
+
778
+ /** Scope heading spans, e.g. `project /work/pi — broker pid 1234`. */
779
+ function scopeSpans(scope: PsScope): TspSpan[] {
780
+ const spans =
781
+ scope.kind === "global"
782
+ ? [span("global "), span(scope.service ?? path.basename(scope.runtimeDir), "strong")]
783
+ : [span("project "), span(scope.projectDir ?? path.basename(scope.runtimeDir), "strong path")];
784
+ spans.push(span(" — ", "dim"));
785
+ spans.push(
786
+ scope.brokerPid !== undefined
787
+ ? span(`broker pid ${scope.brokerPid}`, "success")
788
+ : span("broker not running", "dim"),
789
+ );
790
+ return spans;
791
+ }
792
+
793
+ /** A state as the table shows it: `ready`, `exited(143)`. */
794
+ function stateLabel(snapshot: DaemonSnapshot): string {
795
+ return TERMINAL_STATES[snapshot.state] && snapshot.exitCode !== undefined
796
+ ? `${snapshot.state}(${snapshot.exitCode})`
797
+ : snapshot.state;
798
+ }
799
+
800
+ /** Status icon of a process state (tinted by {@link daemonTone}). */
801
+ const STATE_ICON: Record<TspTone, string> = {
802
+ success: "check",
803
+ error: "x",
804
+ muted: "stop",
805
+ warning: "clock",
806
+ neutral: "activity",
807
+ accent: "activity",
808
+ info: "activity",
809
+ pending: "clock",
810
+ user: "user",
811
+ };
812
+
813
+ /** One selectable process row: name, state/pid/uptime/restarts/flags, and the launch command. */
814
+ function describeProcess(scope: PsScope, daemon: PsDaemonRow): NativeNode {
815
+ const { snapshot } = daemon;
816
+ const terminal = TERMINAL_STATES[snapshot.state] === true;
817
+ const state = stateLabel(snapshot);
818
+ const meta = [
819
+ snapshot.pid !== undefined && !terminal ? `pid ${snapshot.pid}` : undefined,
820
+ terminal ? undefined : formatDuration(Date.now() - snapshot.startedAt),
821
+ `${snapshot.restartCount} restart${snapshot.restartCount === 1 ? "" : "s"}`,
822
+ flagsCell(daemon) || undefined,
823
+ ].filter(part => part !== undefined);
824
+ const command = collapseCommand(daemon.command);
825
+ const tone = daemonTone(snapshot);
826
+ return node(
827
+ "item",
828
+ {
829
+ label: [span(snapshot.name, terminal ? "dim" : "strong")],
830
+ detail: command ? [span(command, "mono muted")] : undefined,
831
+ value: [span(state, tone === "muted" ? "dim" : tone), span(` · ${meta.join(" · ")}`, "muted")],
832
+ icon: STATE_ICON[tone],
833
+ tone,
834
+ title: daemonLabel(snapshot),
835
+ },
836
+ undefined,
837
+ stableKey(flatKey({ scope, row: daemon })),
838
+ );
839
+ }
840
+
410
841
  /** Run the fullscreen interactive process monitor until the user quits. */
411
842
  export async function runPsTop(options: PsTopOptions, host: PsTopHost): Promise<void> {
412
843
  const ui = new TUI(new ProcessTerminal());
@@ -68,6 +68,7 @@ export async function selectSession<T extends SessionSelectorEntry>(
68
68
  allSessions: options.allSessions,
69
69
  getTerminalRows: () => ui.terminal.rows,
70
70
  fillHeight: true,
71
+ standalone: true,
71
72
  title: options.title,
72
73
  scopeLabel: options.scopeLabel,
73
74
  showCwd: options.showCwd,
@@ -17,5 +17,9 @@ export async function selectSetupModel(
17
17
  items: SelectItem[],
18
18
  currentValue: string,
19
19
  ): Promise<string | null> {
20
- return selectStandaloneItem(title, items, { currentValue, maxVisible: 10 });
20
+ return selectStandaloneItem(title, items, {
21
+ currentValue,
22
+ maxVisible: 10,
23
+ picker: { icon: "model", noun: "models" },
24
+ });
21
25
  }