@pellux/goodvibes-tui 2.0.21 → 2.1.1

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 (391) hide show
  1. package/CHANGELOG.md +65 -1
  2. package/README.md +30 -29
  3. package/docs/README.md +8 -5
  4. package/docs/foundation-artifacts/operator-contract.json +1 -1
  5. package/package.json +28 -19
  6. package/src/cli/management.ts +5 -2
  7. package/src/cli/tui-startup.ts +34 -39
  8. package/src/core/agent-view-render.ts +157 -0
  9. package/src/core/approval-alert.ts +49 -11
  10. package/src/core/bookmark-navigation.ts +7 -1
  11. package/src/core/budget-breach-notifier.ts +27 -8
  12. package/src/core/compaction-receipt.ts +1 -1
  13. package/src/core/context-usage.ts +1 -1
  14. package/src/core/conversation-compaction-render.ts +3 -3
  15. package/src/core/conversation-display-only.ts +86 -0
  16. package/src/core/conversation-event-navigation.ts +27 -0
  17. package/src/core/conversation-line-cache.ts +216 -447
  18. package/src/core/conversation-render-context.ts +20 -27
  19. package/src/core/conversation-rendering.ts +157 -575
  20. package/src/core/conversation-splash-state.ts +6 -1
  21. package/src/core/conversation-types.ts +35 -0
  22. package/src/core/conversation-usage.ts +12 -0
  23. package/src/core/conversation.ts +130 -131
  24. package/src/core/long-task-notifier.ts +100 -31
  25. package/src/core/notices.ts +75 -0
  26. package/src/core/pairing-tailscale-gateway.ts +1 -1
  27. package/src/core/process-output-log.ts +143 -0
  28. package/src/core/rewind-receipt.ts +1 -1
  29. package/src/core/session-focus.ts +190 -0
  30. package/src/core/session-resume-core.ts +23 -81
  31. package/src/core/stream-event-wiring.ts +31 -5
  32. package/src/core/system-message-noise.ts +2 -2
  33. package/src/core/system-message-router.ts +16 -18
  34. package/src/core/turn-event-wiring.ts +272 -33
  35. package/src/core/work-tree-focus.ts +290 -0
  36. package/src/core/work-tree-fold-store.ts +143 -0
  37. package/src/core/work-tree-model.ts +799 -0
  38. package/src/core/work-tree-render.ts +384 -0
  39. package/src/core/work-tree-sources.ts +184 -0
  40. package/src/core/work-tree-wiring.ts +176 -0
  41. package/src/core/workstream-notification.ts +36 -6
  42. package/src/core/wrfc-notice-titles.ts +37 -0
  43. package/src/input/agents-modal-text.ts +119 -0
  44. package/src/input/agents-modal.ts +699 -0
  45. package/src/input/bookmark-modal.ts +33 -9
  46. package/src/input/changes-git.ts +251 -0
  47. package/src/input/changes-modal.ts +629 -0
  48. package/src/input/changes-model.ts +125 -0
  49. package/src/input/command-palette-types.ts +41 -0
  50. package/src/input/command-palette.ts +272 -0
  51. package/src/input/command-reference.ts +2 -2
  52. package/src/input/command-registry.ts +77 -35
  53. package/src/input/commands/acp-runtime.ts +19 -9
  54. package/src/input/commands/channel-runtime.ts +2 -2
  55. package/src/input/commands/ci-runtime.ts +1 -1
  56. package/src/input/commands/codebase-runtime.ts +1 -1
  57. package/src/input/commands/config.ts +7 -1
  58. package/src/input/commands/context-window.ts +25 -19
  59. package/src/input/commands/control-room-runtime.ts +18 -18
  60. package/src/input/commands/conversation-runtime.ts +0 -1
  61. package/src/input/commands/cost-runtime.ts +29 -20
  62. package/src/input/commands/diff-runtime.ts +35 -181
  63. package/src/input/commands/eval.ts +1 -1
  64. package/src/input/commands/experience-runtime.ts +3 -7
  65. package/src/input/commands/fresh-conversation.ts +86 -0
  66. package/src/input/commands/git-runtime.ts +5 -22
  67. package/src/input/commands/graph-runtime.ts +1 -1
  68. package/src/input/commands/guidance-runtime.ts +1 -1
  69. package/src/input/commands/health-runtime.ts +8 -9
  70. package/src/input/commands/hooks-runtime.ts +2 -2
  71. package/src/input/commands/hosted-runtime.ts +3 -3
  72. package/src/input/commands/incident-runtime.ts +3 -3
  73. package/src/input/commands/intelligence-runtime.ts +6 -9
  74. package/src/input/commands/knowledge.ts +2 -2
  75. package/src/input/commands/legacy-panel-command.ts +57 -0
  76. package/src/input/commands/local-auth-runtime.ts +8 -9
  77. package/src/input/commands/local-provider-runtime.ts +7 -4
  78. package/src/input/commands/local-runtime.ts +12 -15
  79. package/src/input/commands/local-setup-review.ts +1 -1
  80. package/src/input/commands/local-setup.ts +13 -19
  81. package/src/input/commands/memory.ts +1 -1
  82. package/src/input/commands/notify-runtime.ts +9 -0
  83. package/src/input/commands/operator-runtime.ts +10 -12
  84. package/src/input/commands/permissions-provenance.ts +3 -3
  85. package/src/input/commands/planning-runtime.ts +7 -7
  86. package/src/input/commands/platform-sandbox-runtime.ts +2 -2
  87. package/src/input/commands/platform-services-runtime.ts +1 -1
  88. package/src/input/commands/policy-dispatch.ts +2 -2
  89. package/src/input/commands/policy.ts +3 -3
  90. package/src/input/commands/provider.ts +1 -1
  91. package/src/input/commands/remote-runtime.ts +1 -1
  92. package/src/input/commands/review-runtime.ts +39 -94
  93. package/src/input/commands/rewind-runtime.ts +81 -108
  94. package/src/input/commands/runtime-services.ts +15 -17
  95. package/src/input/commands/services-runtime.ts +2 -2
  96. package/src/input/commands/session-content.ts +21 -5
  97. package/src/input/commands/session-workflow.ts +13 -38
  98. package/src/input/commands/settings-sync-runtime.ts +2 -2
  99. package/src/input/commands/shell-core.ts +19 -4
  100. package/src/input/commands/skills-runtime.ts +2 -2
  101. package/src/input/commands/status-runtime.ts +13 -0
  102. package/src/input/commands/subscription-runtime.ts +1 -1
  103. package/src/input/commands/tasks-runtime.ts +2 -8
  104. package/src/input/commands/work-plan-runtime.ts +4 -4
  105. package/src/input/commands/workstream-attempts.ts +24 -47
  106. package/src/input/commands/workstream-runtime.ts +2 -2
  107. package/src/input/commands/worktree-runtime.ts +3 -3
  108. package/src/input/commands.ts +3 -1
  109. package/src/input/composer-editor.ts +44 -0
  110. package/src/input/concealed-input.ts +1 -1
  111. package/src/input/config-modal-types.ts +20 -8
  112. package/src/input/config-modal.ts +106 -105
  113. package/src/input/confirm-dialog-types.ts +28 -0
  114. package/src/input/confirm-dialog.ts +70 -0
  115. package/src/input/delete-key-policy.ts +3 -3
  116. package/src/input/feed-context-factory.ts +15 -16
  117. package/src/input/handler-command-route.ts +7 -42
  118. package/src/input/handler-content-actions.ts +16 -15
  119. package/src/input/handler-feed-routes.ts +26 -211
  120. package/src/input/handler-feed.ts +68 -95
  121. package/src/input/handler-interactions.ts +5 -3
  122. package/src/input/handler-modal-routes.ts +215 -216
  123. package/src/input/handler-modal-stack.ts +81 -11
  124. package/src/input/handler-modal-token-routes.ts +4 -0
  125. package/src/input/handler-onboarding.ts +0 -1
  126. package/src/input/handler-picker-routes.ts +65 -107
  127. package/src/input/handler-session-view-route.ts +149 -0
  128. package/src/input/handler-shortcuts.ts +16 -154
  129. package/src/input/handler-types.ts +4 -2
  130. package/src/input/handler-ui-state.ts +45 -15
  131. package/src/input/handler-work-tree-route.ts +123 -0
  132. package/src/input/handler.ts +25 -70
  133. package/src/input/keybindings.ts +16 -71
  134. package/src/input/masked-entry-modal.ts +117 -0
  135. package/src/input/mcp-workspace.ts +48 -17
  136. package/src/input/model-picker-filter.ts +8 -0
  137. package/src/input/model-picker-open.ts +99 -0
  138. package/src/input/model-picker-types.ts +1 -1
  139. package/src/input/model-picker.ts +92 -9
  140. package/src/input/notifications-modal.ts +123 -0
  141. package/src/input/overlay-filter.ts +26 -0
  142. package/src/input/profile-picker-modal.ts +37 -8
  143. package/src/input/search.ts +3 -3
  144. package/src/input/selection-modal-queue.ts +2 -0
  145. package/src/input/selection-modal.ts +28 -16
  146. package/src/input/session-picker-modal.ts +33 -8
  147. package/src/input/settings-modal-activation.ts +7 -2
  148. package/src/input/settings-modal-data.ts +11 -6
  149. package/src/input/settings-modal-types.ts +1 -1
  150. package/src/input/settings-modal.ts +20 -20
  151. package/src/input/submission-intent.ts +1 -1
  152. package/src/input/submission-router.ts +4 -9
  153. package/src/input/surface-modal-host.ts +110 -0
  154. package/src/input/theme-settings-actions.ts +82 -0
  155. package/src/input/usage-modal.ts +183 -0
  156. package/src/input/views.ts +97 -0
  157. package/src/main.ts +175 -165
  158. package/src/permissions/hunk-selection.ts +1 -1
  159. package/src/permissions/prompt-card.ts +511 -0
  160. package/src/permissions/prompt.ts +59 -622
  161. package/src/renderer/agents-modal.ts +310 -0
  162. package/src/renderer/autocomplete-overlay.ts +42 -220
  163. package/src/renderer/back-to-bottom.ts +80 -0
  164. package/src/renderer/block-actions-overlay.ts +30 -48
  165. package/src/renderer/bookmark-modal.ts +48 -79
  166. package/src/renderer/changes-modal.ts +325 -0
  167. package/src/renderer/code-block.ts +184 -106
  168. package/src/renderer/command-palette.ts +93 -0
  169. package/src/renderer/composer-fragments.ts +4 -4
  170. package/src/renderer/composer.ts +146 -0
  171. package/src/renderer/compositor.ts +26 -160
  172. package/src/renderer/config-modal.ts +185 -81
  173. package/src/renderer/confirm-dialog.ts +50 -0
  174. package/src/renderer/context-inspector.ts +116 -154
  175. package/src/renderer/context-status-hint.ts +4 -4
  176. package/src/renderer/conversation-layout.ts +20 -0
  177. package/src/renderer/conversation-overlays.ts +94 -84
  178. package/src/renderer/conversation-surface.ts +19 -38
  179. package/src/renderer/diff-tint.ts +98 -0
  180. package/src/renderer/file-picker-overlay.ts +63 -90
  181. package/src/renderer/footer-targets.ts +38 -0
  182. package/src/renderer/git-status.ts +3 -4
  183. package/src/renderer/header-line.ts +140 -117
  184. package/src/renderer/help-overlay.ts +133 -219
  185. package/src/renderer/history-search-overlay.ts +15 -12
  186. package/src/renderer/lane-graph/bead.ts +800 -0
  187. package/src/renderer/lane-graph/glyphs.ts +134 -0
  188. package/src/renderer/lane-graph/layout.ts +248 -0
  189. package/src/renderer/lane-graph/paint.ts +537 -0
  190. package/src/renderer/lane-graph/semantic-memo.ts +77 -0
  191. package/src/renderer/layout-engine.ts +2 -57
  192. package/src/renderer/layout.ts +7 -13
  193. package/src/renderer/markdown-inline.ts +2 -1
  194. package/src/renderer/markdown-table.ts +17 -12
  195. package/src/renderer/markdown.ts +92 -34
  196. package/src/renderer/masked-entry-modal.ts +78 -0
  197. package/src/renderer/mcp-workspace.ts +166 -203
  198. package/src/renderer/model-workspace.ts +381 -436
  199. package/src/renderer/notifications-modal.ts +116 -0
  200. package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
  201. package/src/renderer/process-view.ts +192 -0
  202. package/src/renderer/profile-picker-modal.ts +58 -110
  203. package/src/renderer/search-overlay.ts +6 -3
  204. package/src/renderer/selection-modal-overlay.ts +87 -327
  205. package/src/renderer/semantic-diff.ts +2 -2
  206. package/src/renderer/session-chips.ts +102 -0
  207. package/src/renderer/session-picker-modal.ts +177 -297
  208. package/src/renderer/settings-modal-connections.ts +14 -23
  209. package/src/renderer/settings-modal-context.ts +367 -0
  210. package/src/renderer/settings-modal-helpers.ts +6 -11
  211. package/src/renderer/settings-modal.ts +322 -726
  212. package/src/renderer/shell-surface.ts +277 -175
  213. package/src/renderer/shortcuts-overlay.ts +217 -0
  214. package/src/renderer/status-line.ts +475 -0
  215. package/src/renderer/surface-compose.ts +174 -0
  216. package/src/renderer/surface-kit-extra.ts +303 -0
  217. package/src/renderer/surface-kit-list.ts +366 -0
  218. package/src/renderer/surface-kit-parts.ts +360 -0
  219. package/src/renderer/surface-kit.ts +568 -0
  220. package/src/renderer/syntax-highlighter.ts +280 -197
  221. package/src/renderer/syntax-theme.ts +51 -0
  222. package/src/renderer/system-message.ts +0 -1
  223. package/src/renderer/term-caps.ts +42 -1
  224. package/src/renderer/terminal-bg-probe.ts +116 -19
  225. package/src/renderer/terminal-palette-probe.ts +322 -0
  226. package/src/renderer/terminal-palette-reader.ts +183 -0
  227. package/src/renderer/terminal-palette.ts +58 -0
  228. package/src/renderer/theme-mode-config.ts +16 -1
  229. package/src/renderer/theme.ts +234 -207
  230. package/src/renderer/thinking.ts +0 -1
  231. package/src/renderer/throbber.ts +188 -0
  232. package/src/renderer/toast-center.ts +119 -0
  233. package/src/renderer/ui-factory.ts +39 -602
  234. package/src/renderer/ui-primitives.ts +8 -25
  235. package/src/renderer/usage-modal.ts +353 -0
  236. package/src/renderer/user-message.ts +58 -0
  237. package/src/renderer/voice-capture-chip.ts +53 -0
  238. package/src/runtime/bootstrap-command-context.ts +0 -5
  239. package/src/runtime/bootstrap-command-parts.ts +38 -89
  240. package/src/runtime/bootstrap-core.ts +13 -15
  241. package/src/runtime/bootstrap-hook-bridge.ts +12 -21
  242. package/src/runtime/bootstrap-notifier-sync.ts +17 -1
  243. package/src/runtime/bootstrap-shell.ts +16 -50
  244. package/src/runtime/bootstrap.ts +14 -14
  245. package/src/runtime/client/fleet-union.ts +5 -5
  246. package/src/runtime/client/hosted-exit.ts +2 -2
  247. package/src/runtime/client/hosted-sessions.ts +1 -1
  248. package/src/runtime/client/spine-adoption.ts +1 -1
  249. package/src/runtime/context-accounting-source.ts +5 -4
  250. package/src/runtime/index.ts +1 -0
  251. package/src/runtime/notification-dispatch.ts +102 -29
  252. package/src/runtime/recovery-offer-wiring.ts +4 -1
  253. package/src/runtime/recovery-prompt.ts +31 -15
  254. package/src/runtime/runtime-services-types.ts +10 -6
  255. package/src/runtime/services.ts +17 -12
  256. package/src/runtime/session-continuity-hints.ts +2 -5
  257. package/src/runtime/session-inbound-inputs.ts +1 -1
  258. package/src/runtime/session-resume-liveness-confirm.ts +14 -2
  259. package/src/runtime/startup-typeahead-gate.ts +103 -0
  260. package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
  261. package/src/runtime/store/domains/index.ts +0 -8
  262. package/src/runtime/store/selectors/index.ts +0 -28
  263. package/src/runtime/store/state.ts +0 -8
  264. package/src/runtime/ui-services.ts +4 -6
  265. package/src/runtime/usage-tracker.ts +348 -0
  266. package/src/runtime/wrfc-persistence.ts +4 -4
  267. package/src/shell/blocking-input.ts +92 -2
  268. package/src/shell/recovery-input-helpers.ts +1 -1
  269. package/src/shell/session-views.ts +539 -0
  270. package/src/shell/status-report.ts +86 -0
  271. package/src/shell/transcript-scroll.ts +68 -0
  272. package/src/shell/ui-openers.ts +84 -172
  273. package/src/shell/view-openers.ts +205 -0
  274. package/src/tools/wrfc-agent-guard.ts +22 -2
  275. package/src/utils/format-duration.ts +4 -8
  276. package/src/utils/splash-lines.ts +9 -1
  277. package/src/utils/terminal-width.ts +56 -0
  278. package/src/verification/live-verifier.ts +0 -10
  279. package/src/version.ts +1 -1
  280. package/src/{panels → views}/agent-inspector-shared.ts +2 -2
  281. package/src/{panels → views}/builtin-modals.ts +22 -21
  282. package/src/views/builtin-views.ts +135 -0
  283. package/src/{panels → views}/confirm-state.ts +9 -9
  284. package/src/{panels → views}/diff-review-model.ts +10 -3
  285. package/src/{panels → views}/eval-registry.ts +1 -1
  286. package/src/{panels → views}/fleet-acts.ts +49 -85
  287. package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
  288. package/src/{panels → views}/fleet-gateway.ts +5 -5
  289. package/src/{panels → views}/fleet-observed-render.ts +16 -16
  290. package/src/{panels → views}/fleet-read-model.ts +9 -9
  291. package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
  292. package/src/{panels → views}/fleet-spawn.ts +33 -49
  293. package/src/{panels → views}/fleet-steer.ts +12 -12
  294. package/src/{panels → views}/fleet-stop.ts +4 -4
  295. package/src/{panels → views}/fleet-transcript.ts +26 -27
  296. package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
  297. package/src/{panels → views}/hosted-session-feed.ts +6 -6
  298. package/src/views/modal-surface-registry.ts +41 -0
  299. package/src/{panels → views}/modals/devices-modal.ts +2 -2
  300. package/src/{panels → views}/modals/hooks-modal.ts +13 -13
  301. package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
  302. package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
  303. package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
  304. package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
  305. package/src/{panels → views}/modals/memory-modal.ts +8 -8
  306. package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
  307. package/src/{panels → views}/modals/pairing-modal.ts +9 -9
  308. package/src/{panels → views}/modals/planning-modal.ts +15 -20
  309. package/src/{panels → views}/modals/plugins-modal.ts +6 -6
  310. package/src/{panels → views}/modals/policy-modal.ts +13 -5
  311. package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
  312. package/src/{panels → views}/modals/remote-modal.ts +3 -3
  313. package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
  314. package/src/{panels → views}/modals/security-modal.ts +22 -16
  315. package/src/{panels → views}/modals/services-modal.ts +3 -3
  316. package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
  317. package/src/{panels → views}/modals/skills-modal.ts +9 -9
  318. package/src/{panels → views}/modals/subscription-modal.ts +3 -3
  319. package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
  320. package/src/views/notifications-feed.ts +314 -0
  321. package/src/{panels → views}/polish-core.ts +38 -36
  322. package/src/{panels → views}/polish-tables.ts +35 -26
  323. package/src/{panels → views}/polish.ts +101 -95
  324. package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
  325. package/src/{panels → views}/provider-health-routes.ts +14 -14
  326. package/src/{panels → views}/search-focus.ts +8 -8
  327. package/src/{panels → views}/session-maintenance.ts +11 -11
  328. package/src/views/skills-discovery.ts +159 -0
  329. package/src/views/view-deps.ts +80 -0
  330. package/src/views/view-panel-adapter.ts +53 -0
  331. package/src/{panels → views}/workstream-graph-render.ts +1 -1
  332. package/src/core/conversation-fold.ts +0 -101
  333. package/src/core/conversation-turn-structure.ts +0 -464
  334. package/src/core/conversation-user-receipts.ts +0 -42
  335. package/src/input/commands/operator-panel-runtime.ts +0 -186
  336. package/src/input/panel-integration-actions.ts +0 -33
  337. package/src/input/panel-mouse-geometry.ts +0 -97
  338. package/src/input/panel-paste-flood-guard.ts +0 -86
  339. package/src/panels/base-panel.ts +0 -301
  340. package/src/panels/builtin/agent.ts +0 -27
  341. package/src/panels/builtin/development.ts +0 -92
  342. package/src/panels/builtin/knowledge.ts +0 -12
  343. package/src/panels/builtin/operations.ts +0 -177
  344. package/src/panels/builtin/session.ts +0 -81
  345. package/src/panels/builtin/shared.ts +0 -357
  346. package/src/panels/builtin-panels.ts +0 -28
  347. package/src/panels/cost-tracker-panel.ts +0 -746
  348. package/src/panels/diff-panel.ts +0 -797
  349. package/src/panels/diff-review-panel.ts +0 -395
  350. package/src/panels/expandable-list-panel.ts +0 -189
  351. package/src/panels/fleet-deep-link.ts +0 -31
  352. package/src/panels/fleet-panel.ts +0 -799
  353. package/src/panels/git-panel.ts +0 -800
  354. package/src/panels/hosted-session-panel.ts +0 -221
  355. package/src/panels/index.ts +0 -21
  356. package/src/panels/local-auth-panel.ts +0 -478
  357. package/src/panels/notifications-feed.ts +0 -127
  358. package/src/panels/notifications-panel.ts +0 -160
  359. package/src/panels/panel-confirm-overlay.ts +0 -72
  360. package/src/panels/panel-manager.ts +0 -791
  361. package/src/panels/plugins-panel.ts +0 -371
  362. package/src/panels/scrollable-list-panel.ts +0 -498
  363. package/src/panels/skills-panel.ts +0 -454
  364. package/src/panels/token-budget-panel.ts +0 -688
  365. package/src/panels/types.ts +0 -191
  366. package/src/panels/wrfc-panel-format.ts +0 -133
  367. package/src/renderer/diff-view.ts +0 -134
  368. package/src/renderer/fleet-tab-strip.ts +0 -56
  369. package/src/renderer/footer-tips.ts +0 -53
  370. package/src/renderer/fullscreen-primitives.ts +0 -146
  371. package/src/renderer/fullscreen-workspace.ts +0 -194
  372. package/src/renderer/hint-grammar.ts +0 -52
  373. package/src/renderer/modal-factory.ts +0 -480
  374. package/src/renderer/overlay-box.ts +0 -154
  375. package/src/renderer/overlay-viewport.ts +0 -104
  376. package/src/renderer/panel-composite.ts +0 -145
  377. package/src/renderer/panel-workspace-bar.ts +0 -54
  378. package/src/renderer/process-indicator.ts +0 -163
  379. package/src/renderer/tab-strip.ts +0 -222
  380. package/src/renderer/text-layout.ts +0 -31
  381. package/src/renderer/tool-call.ts +0 -276
  382. package/src/renderer/tool-result-expanded-lines.ts +0 -48
  383. package/src/renderer/tool-result-summary.ts +0 -219
  384. package/src/runtime/diagnostics/panels/index.ts +0 -21
  385. package/src/runtime/diagnostics/panels/ops.ts +0 -156
  386. package/src/runtime/perf/panel-contracts.ts +0 -32
  387. package/src/runtime/store/domains/panels.ts +0 -117
  388. package/src/verification/verification-ledger.ts +0 -707
  389. /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
  390. /package/src/{panels → views}/modals/modal-theme.ts +0 -0
  391. /package/src/{panels → views}/provider-health-domains.ts +0 -0
@@ -0,0 +1,188 @@
1
+ /**
2
+ * throbber.ts, the one row above the input area that says what the main
3
+ * session is doing right now. It shows only while main is working (a turn
4
+ * runs, or the conversation is being compacted) and is gone at rest.
5
+ *
6
+ * col 3 the spinner (brand gradient on the glyph only)
7
+ * col 5..w-4 what is happening, then its elapsed time
8
+ *
9
+ * It is its own surface: never inside the input area, and never on the
10
+ * status line, which keeps session state (mode, cost, context bar) and the
11
+ * keys (esc interrupt).
12
+ *
13
+ * What it names, first match wins:
14
+ * - a permission prompt waiting on you: Waiting for your approval · bash · npm test · 12s
15
+ * - a compaction: Compacting the conversation · 4s
16
+ * - a running tool: Running bash · npm test · 3s
17
+ * - the model (the honest waiting phrase from the SDK): Thinking... · 12s · first token 1.2s · 40 tok/s
18
+ *
19
+ * Inside an agent or process view the row keeps main in sight the same way,
20
+ * led by "main ·" so it is never read as the view's own activity.
21
+ */
22
+
23
+ import { type Line, createEmptyLine } from '@pellux/goodvibes-sdk/platform/types';
24
+ import type { ToolCall } from '@pellux/goodvibes-sdk/platform/types';
25
+ import { getDisplayWidth, interpolateColor, truncateDisplay } from '../utils/terminal-width.ts';
26
+ import { formatElapsed } from '../utils/format-elapsed.ts';
27
+ import { beadArgument, beadName } from './lane-graph/bead.ts';
28
+ import { activeTokens } from './theme.ts';
29
+
30
+ /** Column of the spinner (the input area's first fill column). */
31
+ const THROBBER_SPINNER_X = 3;
32
+ /** First text column (the input area's text column). */
33
+ const THROBBER_TEXT_X = 5;
34
+ /** The most a tool's argument takes before it is cut, so the elapsed time stays on the row. */
35
+ const ARGUMENT_MAX = 60;
36
+ const SEP = ' · ';
37
+
38
+ /** What the main session is doing, as the throbber names it. */
39
+ export type ThrobberActivity =
40
+ | { readonly kind: 'approval'; readonly tool: string; readonly argument: string; readonly elapsedMs?: number }
41
+ | { readonly kind: 'compacting'; readonly elapsedMs?: number }
42
+ | { readonly kind: 'tool'; readonly tool: string; readonly argument: string; readonly elapsedMs?: number }
43
+ | { readonly kind: 'model'; readonly phrase: string; readonly elapsedMs?: number; readonly ttftMs?: number; readonly tokenSpeed?: number };
44
+
45
+ /** One frame of the throbber. */
46
+ export interface ThrobberState {
47
+ /** The spinner glyph for this frame. */
48
+ readonly spinner: string;
49
+ /** Animation frame, used for the spinner's gradient position. */
50
+ readonly frame: number;
51
+ readonly activity: ThrobberActivity;
52
+ /** Set inside an agent or process view: whose activity this is ("main"). */
53
+ readonly owner?: string;
54
+ }
55
+
56
+ /** A tool call as the throbber needs it: its name and arguments. */
57
+ export interface ThrobberToolCall {
58
+ readonly name: string;
59
+ readonly args?: Record<string, unknown>;
60
+ }
61
+
62
+ export interface ThrobberActivityInput {
63
+ /** A main turn is running. */
64
+ readonly turnActive: boolean;
65
+ /** A compaction of the main conversation is running (inside a turn or not). */
66
+ readonly compacting: boolean;
67
+ /** When the running compaction started (epoch ms), once known. */
68
+ readonly compactingSinceMs?: number;
69
+ /** The permission prompt the turn is blocked on. */
70
+ readonly pendingApproval?: ThrobberToolCall | null;
71
+ /** The tool the turn is executing now, and when it started (epoch ms). */
72
+ readonly activeTool?: (ThrobberToolCall & { readonly startedAtMs?: number }) | null;
73
+ /** The model's honest waiting phrase (UIFactory.busyPhrase). */
74
+ readonly modelPhrase: string;
75
+ /** When the turn's current stream started (epoch ms); 0 or undefined when unknown. */
76
+ readonly turnStartMs?: number;
77
+ readonly ttftMs?: number;
78
+ readonly tokenSpeed?: number;
79
+ readonly now: number;
80
+ }
81
+
82
+ /** "bash", "npm test": a call's short name and key argument, the way its bead names it. */
83
+ function describeToolCall(call: ThrobberToolCall): { tool: string; argument: string } {
84
+ const asCall = { id: '', name: call.name, arguments: call.args ?? {} } as ToolCall;
85
+ let argument = '';
86
+ try { argument = beadArgument(asCall); } catch { argument = ''; }
87
+ return { tool: beadName(asCall), argument: truncateDisplay(argument, ARGUMENT_MAX) };
88
+ }
89
+
90
+ /** What main is doing now, or null at rest (the throbber is not drawn). */
91
+ export function resolveThrobberActivity(input: ThrobberActivityInput): ThrobberActivity | null {
92
+ if (!input.turnActive && !input.compacting) return null;
93
+ const since = (start: number | undefined): number | undefined => (start !== undefined && start > 0 ? Math.max(0, input.now - start) : undefined);
94
+ const turnElapsed = since(input.turnStartMs);
95
+ if (input.turnActive && input.pendingApproval) {
96
+ return { kind: 'approval', ...describeToolCall(input.pendingApproval), elapsedMs: turnElapsed };
97
+ }
98
+ if (input.compacting) return { kind: 'compacting', elapsedMs: since(input.compactingSinceMs) };
99
+ if (input.activeTool) {
100
+ return { kind: 'tool', ...describeToolCall(input.activeTool), elapsedMs: since(input.activeTool.startedAtMs) ?? turnElapsed };
101
+ }
102
+ return {
103
+ kind: 'model',
104
+ phrase: input.modelPhrase,
105
+ elapsedMs: turnElapsed,
106
+ ttftMs: input.ttftMs !== undefined && input.ttftMs > 0 ? input.ttftMs : undefined,
107
+ tokenSpeed: input.tokenSpeed !== undefined && input.tokenSpeed > 0 ? input.tokenSpeed : undefined,
108
+ };
109
+ }
110
+
111
+ interface ThrobberText {
112
+ readonly label: string;
113
+ readonly subject: string;
114
+ readonly tail: readonly string[];
115
+ }
116
+
117
+ function textOf(activity: ThrobberActivity): ThrobberText {
118
+ const elapsed = activity.elapsedMs !== undefined ? [formatElapsed(activity.elapsedMs)] : [];
119
+ switch (activity.kind) {
120
+ case 'approval':
121
+ return { label: 'Waiting for your approval', subject: [activity.tool, activity.argument].filter(Boolean).join(SEP), tail: elapsed };
122
+ case 'compacting':
123
+ return { label: 'Compacting the conversation', subject: '', tail: elapsed };
124
+ case 'tool':
125
+ return { label: `Running ${activity.tool}`, subject: activity.argument, tail: elapsed };
126
+ case 'model': {
127
+ const tail = [...elapsed];
128
+ if (activity.ttftMs !== undefined) tail.push(`first token ${formatElapsed(activity.ttftMs)}`);
129
+ if (activity.tokenSpeed !== undefined) tail.push(`${Math.round(activity.tokenSpeed)} tok/s`);
130
+ return { label: activity.phrase, subject: '', tail };
131
+ }
132
+ }
133
+ }
134
+
135
+ function put(line: Line, x: number, endX: number, text: string, fg: string, bold = false): number {
136
+ let cx = x;
137
+ for (const ch of text) {
138
+ const w = getDisplayWidth(ch);
139
+ if (w <= 0) continue;
140
+ if (cx + w > endX) break;
141
+ line[cx] = { char: ch, fg, bg: '', bold, dim: false, underline: false, italic: false, strikethrough: false };
142
+ if (w === 2 && cx + 1 < line.length) line[cx + 1] = { ...line[cx]!, char: '' };
143
+ cx += w;
144
+ }
145
+ return cx;
146
+ }
147
+
148
+ /**
149
+ * Draw the throbber row. The text ends at width-4 or earlier. When the row is
150
+ * short the elapsed pieces go first, then the subject is cut, then the label.
151
+ */
152
+ export function renderThrobberLine(width: number, state: ThrobberState): Line {
153
+ const t = activeTokens();
154
+ const line = createEmptyLine(width);
155
+ for (const cell of line) cell.bg = '';
156
+ const endX = Math.max(THROBBER_TEXT_X, width - 3); // exclusive: the last text column is width-4
157
+ if (width <= THROBBER_TEXT_X) return line;
158
+ const glyphFg = interpolateColor(t.brand, t.brandEnd, (Math.sin(state.frame / 6) + 1) / 2);
159
+ put(line, THROBBER_SPINNER_X, endX, state.spinner, glyphFg, true);
160
+
161
+ const { label, subject, tail } = textOf(state.activity);
162
+ const room = endX - THROBBER_TEXT_X;
163
+ const owner = state.owner ? `${state.owner}${SEP}` : '';
164
+ const head = owner + label;
165
+ const tailText = tail.length > 0 ? SEP + tail.join(SEP) : '';
166
+ const subjectText = subject ? SEP + subject : '';
167
+ let x = THROBBER_TEXT_X;
168
+ const fits = (w: number): boolean => w <= room;
169
+ const headW = getDisplayWidth(head);
170
+ const subjectW = getDisplayWidth(subjectText);
171
+ const tailW = getDisplayWidth(tailText);
172
+ // The label stays whole as long as it can; its trailing dots go before a letter does.
173
+ const bare = head.replace(/(\.\.\.|…)$/, '');
174
+ const headShown = fits(headW) ? head : fits(getDisplayWidth(bare)) ? bare : truncateDisplay(head, room);
175
+ if (owner && headShown.startsWith(owner)) {
176
+ x = put(line, x, endX, owner, t.textFaint);
177
+ x = put(line, x, endX, headShown.slice(owner.length), t.textMuted);
178
+ } else {
179
+ x = put(line, x, endX, headShown, t.textMuted);
180
+ }
181
+ const showTail = fits(headW + subjectW + tailW) || (subject === '' && fits(headW + tailW));
182
+ const subjectRoom = endX - x - (showTail ? tailW : 0);
183
+ if (subjectText && subjectRoom > getDisplayWidth(SEP) + 1) {
184
+ x = put(line, x, endX, truncateDisplay(subjectText, subjectRoom), t.text);
185
+ }
186
+ if (showTail && x + tailW <= endX) put(line, x, endX, tailText, t.textFaint);
187
+ return line;
188
+ }
@@ -0,0 +1,119 @@
1
+ /**
2
+ * toast-center.ts, the toast primitive's state.
3
+ *
4
+ * A toast appears in the top right corner (drawn by renderToasts in
5
+ * surface-kit-parts.ts: a colored ┃ on both sides, the title bold, the body
6
+ * wrapped in full) and disappears after five seconds. Newest first; at most
7
+ * three are kept, older ones leave early rather than stacking down the screen.
8
+ *
9
+ * Producers: commandContext.showToast (any command), and the shared
10
+ * notification feed (bridgeNotificationFeedToToasts): every conversation
11
+ * system notice toasts ([WRFC] …, [Agents] …, compaction receipts; see
12
+ * core/notices.ts), and of the routed notifications only warning and critical
13
+ * ones do. Everything that toasts stays in the feed, which /notifications
14
+ * shows in full.
15
+ */
16
+
17
+ import type { NotificationFeedEntry, NotificationFeed } from '../views/notifications-feed.ts';
18
+ import type { ToastSpec, ToastTone } from './surface-kit-parts.ts';
19
+
20
+ /** How long a toast stays up. */
21
+ const TOAST_DURATION_MS = 5_000;
22
+ /** How many toasts are shown at once. */
23
+ const MAX_TOASTS = 3;
24
+
25
+ interface LiveToast {
26
+ readonly id: number;
27
+ readonly spec: ToastSpec;
28
+ readonly expiresAt: number;
29
+ }
30
+
31
+ export type ToastScheduler = (run: () => void, delayMs: number) => void;
32
+
33
+ const defaultScheduler: ToastScheduler = (run, delayMs) => {
34
+ const timer = setTimeout(run, delayMs);
35
+ // A pending toast expiry must never keep the process alive on exit.
36
+ (timer as { unref?: () => void }).unref?.();
37
+ };
38
+
39
+ export class ToastCenter {
40
+ private toasts: LiveToast[] = [];
41
+ private nextId = 1;
42
+
43
+ /** Called whenever the visible set changes (wired to the render request). */
44
+ onChange: (() => void) | null = null;
45
+
46
+ constructor(
47
+ private readonly clock: () => number = Date.now,
48
+ private readonly schedule: ToastScheduler = defaultScheduler,
49
+ ) {}
50
+
51
+ show(spec: ToastSpec, durationMs: number = TOAST_DURATION_MS): void {
52
+ const toast: LiveToast = { id: this.nextId++, spec, expiresAt: this.clock() + durationMs };
53
+ this.toasts = [toast, ...this.toasts].slice(0, MAX_TOASTS);
54
+ this.schedule(() => this.expire(toast.id), durationMs);
55
+ this.onChange?.();
56
+ }
57
+
58
+ /** The toasts to draw now, newest first. */
59
+ visible(): ToastSpec[] {
60
+ const now = this.clock();
61
+ return this.toasts.filter((t) => t.expiresAt > now).map((t) => t.spec);
62
+ }
63
+
64
+ clear(): void {
65
+ if (this.toasts.length === 0) return;
66
+ this.toasts = [];
67
+ this.onChange?.();
68
+ }
69
+
70
+ private expire(id: number): void {
71
+ const before = this.toasts.length;
72
+ this.toasts = this.toasts.filter((t) => t.id !== id);
73
+ if (this.toasts.length !== before) this.onChange?.();
74
+ }
75
+ }
76
+
77
+ let shared: ToastCenter | null = null;
78
+
79
+ /** The process-wide toast center (lazily created). */
80
+ export function getSharedToastCenter(): ToastCenter {
81
+ shared ??= new ToastCenter();
82
+ return shared;
83
+ }
84
+
85
+ function toneForLevel(level: NotificationFeedEntry['level']): ToastTone | null {
86
+ if (level === 'critical') return 'error';
87
+ if (level === 'warning') return 'warning';
88
+ return null;
89
+ }
90
+
91
+ /** A system notice always toasts; its level picks the bar color. */
92
+ function toneForNotice(level: NotificationFeedEntry['level']): ToastTone {
93
+ return toneForLevel(level) ?? 'info';
94
+ }
95
+
96
+ /**
97
+ * Toast every new warning or critical entry of the notification feed. A
98
+ * collapsed burst toasts once per growth of its running count, with the count
99
+ * in the title. Returns an unsubscribe function.
100
+ */
101
+ export function bridgeNotificationFeedToToasts(feed: NotificationFeed, toasts: ToastCenter): () => void {
102
+ // Per entry: the count last toasted for, and whether it has toasted at that
103
+ // count. An entry toasts when its count grows, or once when a second arrival
104
+ // of the same event (feed eventKey folding) makes a quiet entry one that
105
+ // toasts; a fold never toasts an entry twice.
106
+ const seen = new Map<string, { readonly count: number; readonly toasted: boolean }>();
107
+ for (const entry of feed.list()) seen.set(entry.key, { count: entry.collapsedCount, toasted: true });
108
+ return feed.subscribe(() => {
109
+ for (const entry of feed.list()) {
110
+ const previous = seen.get(entry.key);
111
+ const tone = entry.toast === 'never' ? null : entry.toast === 'always' ? toneForNotice(entry.level) : toneForLevel(entry.level);
112
+ if (previous && previous.count === entry.collapsedCount && (previous.toasted || !tone)) continue;
113
+ seen.set(entry.key, { count: entry.collapsedCount, toasted: Boolean(tone) });
114
+ if (!tone) continue;
115
+ const title = entry.collapsedCount > 1 ? `${entry.title} (${entry.collapsedCount} times)` : entry.title;
116
+ toasts.show({ title, body: entry.body, tone });
117
+ }
118
+ });
119
+ }