@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,38 @@
1
+ /**
2
+ * footer-targets.ts, which footer rows open a view when clicked.
3
+ *
4
+ * The status line (the row carrying the context bar and cost) opens the
5
+ * Usage modal on a click. The footer builder tags those Line arrays with a symbol-keyed
6
+ * property (invisible to rendering, iteration and golden frames); the shell
7
+ * turns the tags into screen rows each frame and the mouse route reads them.
8
+ */
9
+
10
+ import type { Line } from '@pellux/goodvibes-sdk/platform/types';
11
+
12
+ /** What a clickable footer row opens. */
13
+ export type FooterTarget = 'usage';
14
+
15
+ const FOOTER_TARGET = Symbol('footer-target');
16
+
17
+ type TaggedLine = Line & { [FOOTER_TARGET]?: FooterTarget };
18
+
19
+ /** Mark a footer row as opening `target` when clicked; returns the same line. */
20
+ export function tagFooterLine(line: Line, target: FooterTarget): Line {
21
+ (line as TaggedLine)[FOOTER_TARGET] = target;
22
+ return line;
23
+ }
24
+
25
+ /** The target a footer row opens, or undefined. */
26
+ function footerTargetOf(line: Line): FooterTarget | undefined {
27
+ return (line as TaggedLine)[FOOTER_TARGET];
28
+ }
29
+
30
+ /** Screen row → target for a footer drawn with its first row at `startRow`. */
31
+ export function footerTargetRows(footer: readonly Line[], startRow: number): ReadonlyMap<number, FooterTarget> {
32
+ const rows = new Map<number, FooterTarget>();
33
+ footer.forEach((line, index) => {
34
+ const target = footerTargetOf(line);
35
+ if (target) rows.set(startRow + index, target);
36
+ });
37
+ return rows;
38
+ }
@@ -55,10 +55,9 @@ export class GitStatusProvider {
55
55
  }
56
56
 
57
57
  /**
58
- * Start a lightweight live-repo-state poll. Mirrors DiffPanel's principle of
59
- * never trusting a cached "is this a repo" flag (see diff-panel.ts
60
- * showGitDiff/showFileDiffs/showStagedDiff, all gated on a fresh
61
- * GitService.isGitRepo() check) but amortizes the cost for the header: the
58
+ * Start a lightweight live-repo-state poll. Follows the Changes modal's principle of
59
+ * never trusting a cached "is this a repo" flag (its git diff actions are
60
+ * all gated on a fresh GitService.isGitRepo() check) but amortizes the cost for the header: the
62
61
  * cheap synchronous isGitRepo() spawn runs every tick; the heavier async
63
62
  * status()+branch() fetch (this.refresh()) only runs when that boolean
64
63
  * actually flips, e.g. an external `git init`, or `.git` removed.
@@ -1,146 +1,169 @@
1
1
  /**
2
- * header-line.ts, the top-of-screen header row: brand, version, optional
3
- * conversation title, optional git segment, and the right-hand model/provider
4
- * pair.
2
+ * header-line.ts, the one-row header.
5
3
  *
6
- * Extracted from ui-factory.ts (which sits on the 800-line source gate) when
7
- * the header gained the failover divergence marker. `UIFactory.createHeader`
8
- * remains the call name everywhere and delegates here.
4
+ * col 1 GoodVibes, bold, in the theme's brand -> brandEnd gradient
5
+ * (the theme's gradient, never the protected splash constant)
6
+ * then the version (faint) and the session title (muted)
7
+ * right the branch with a warning-colored dirty dot (ahead/behind counts
8
+ * muted), 3 columns, then the serving model ending at width-2,
9
+ * followed by the failover marker in the warning color while the
10
+ * serving backend is not the configured one
9
11
  *
10
- * The model/provider pair rendered here is the SERVING backend, resolved by
11
- * core/active-model-identity.ts, the same resolution the footer uses, so the
12
- * two surfaces can no longer disagree about who is answering. `note` carries
13
- * the divergence marker naming the user's configured selection when serving
14
- * has moved off it.
12
+ * No rule row under it; on the main screen one empty row (withHeaderGap)
13
+ * keeps the output off it. The header is the one place for session identity:
14
+ * title, branch, model. Inside an agent or process view the title gives way
15
+ * to the breadcrumb (main › engineer, the last name in its own color) and the
16
+ * right side names that session: the agent's model, or the process's pid,
17
+ * uptime and port. On a narrow row the marker falls back to its short
18
+ * form, then is dropped whole (a half-cut marker reads worse than none); the
19
+ * branch goes before the marker does, the title before either.
15
20
  */
16
21
 
17
22
  import { type Line, createEmptyLine } from '@pellux/goodvibes-sdk/platform/types';
18
23
  import { VERSION } from '../version.ts';
19
- import { getDisplayWidth } from '../utils/terminal-width.ts';
24
+ import { getDisplayWidth, interpolateColor, truncateDisplay } from '../utils/terminal-width.ts';
20
25
  import type { GitHeaderInfo } from './git-status.ts';
21
- import { activeUiTones } from './theme.ts';
26
+ import { activeTokens } from './theme.ts';
22
27
 
23
- /** Build the git segment string and its display width. Single source of truth for header layout. */
24
- function buildGitSegment(gitInfo: GitHeaderInfo): { text: string; width: number } {
25
- const branch = ` git:${gitInfo.branch}`;
26
- if (gitInfo.dirty) {
27
- const text = `${branch} * `;
28
- return { text, width: getDisplayWidth(text) };
29
- }
30
- if (gitInfo.ahead > 0 || gitInfo.behind > 0) {
31
- const arrows = (gitInfo.ahead > 0 ? ` +${gitInfo.ahead}` : '') + (gitInfo.behind > 0 ? ` -${gitInfo.behind}` : '');
32
- const text = `${branch}${arrows} `;
33
- return { text, width: getDisplayWidth(text) };
28
+ const BRAND = 'GoodVibes';
29
+ const BRAND_X = 1;
30
+ const GAP = 3;
31
+
32
+ interface Seg { readonly text: string; readonly fg: string; readonly bold?: boolean }
33
+
34
+ /** An agent or process view: the breadcrumb in place of the title, the session's own right side. */
35
+ export interface HeaderView {
36
+ /** main, then each level down to the one shown; the last is drawn bold in its color. */
37
+ readonly crumbs: ReadonlyArray<{ readonly text: string; readonly fg: string; readonly bold?: boolean }>;
38
+ /** Replaces the branch and model on the right (the agent's model; pid · uptime · port). */
39
+ readonly right: string;
40
+ readonly rightFg?: string;
41
+ }
42
+
43
+ function put(line: Line, x: number, endX: number, seg: Seg): number {
44
+ let cx = x;
45
+ for (const ch of seg.text) {
46
+ const w = getDisplayWidth(ch);
47
+ if (w <= 0) continue;
48
+ if (cx + w > endX) break;
49
+ line[cx] = { char: ch, fg: seg.fg, bg: '', bold: seg.bold ?? false, dim: false, underline: false, italic: false, strikethrough: false };
50
+ if (w === 2 && cx + 1 < line.length) line[cx + 1] = { ...line[cx]!, char: '' };
51
+ cx += w;
34
52
  }
35
- const text = `${branch} `;
36
- return { text, width: getDisplayWidth(text) };
53
+ return cx;
37
54
  }
38
55
 
39
- /**
40
- * Pick the widest divergence marker that still fits beside the brand and the
41
- * model/provider pair.
42
- *
43
- * Graded, never truncated mid-word: the full marker (which names the
44
- * configured selection) is preferred; a bare "divergent" keyword is the
45
- * fallback on a narrow terminal; on a very narrow terminal the marker is
46
- * dropped entirely. Dropping it is safe, what remains is still the SERVING
47
- * backend, so the header never claims the configured backend is answering.
48
- * The footer carries the full marker with far more room (see ui-factory's
49
- * prioritized context segments).
50
- */
51
- function fitHeaderNote(note: string, usedWidth: number, width: number): string {
52
- if (!note) return '';
53
- const full = `· ${note} `;
54
- if (usedWidth + getDisplayWidth(full) <= width) return full;
55
- const short = '· divergent ';
56
- return usedWidth + getDisplayWidth(short) <= width ? short : '';
56
+ function branchSegments(gitInfo: GitHeaderInfo): Seg[] {
57
+ const t = activeTokens();
58
+ const segs: Seg[] = [{ text: gitInfo.branch, fg: t.textMuted }];
59
+ if (gitInfo.ahead > 0) segs.push({ text: ` +${gitInfo.ahead}`, fg: t.textMuted });
60
+ if (gitInfo.behind > 0) segs.push({ text: ` -${gitInfo.behind}`, fg: t.textMuted });
61
+ if (gitInfo.dirty) segs.push({ text: ' ●', fg: t.warning });
62
+ return segs;
57
63
  }
58
64
 
59
65
  /**
60
- * Render the header row plus its underline.
66
+ * Render the header row.
61
67
  *
62
- * @param width - Terminal columns.
63
- * @param model - Serving model id (already resolved; see file doc).
64
- * @param provider - Serving provider id.
65
- * @param title - Optional conversation title, truncated to fit.
66
- * @param gitInfo - Optional git branch/dirty/ahead-behind segment.
67
- * @param version - Defaults to the live build VERSION; tests pass a pinned
68
- * fixture so golden snapshots survive release bumps.
69
- * @param note - Divergence marker naming the configured selection when the
70
- * serving backend is not the one the user chose; '' otherwise.
68
+ * @param width - Terminal columns.
69
+ * @param model - Serving model id (core/active-model-identity.ts).
70
+ * @param title - Optional session title, truncated to fit.
71
+ * @param gitInfo - Optional branch/dirty/ahead-behind.
72
+ * @param version - Defaults to the live build VERSION; tests pin a fixture.
73
+ * @param modelNote - The failover marker (core/active-model-identity.ts), set
74
+ * only while serving differs from the configured model.
71
75
  */
72
76
  export function renderHeaderLine(
73
77
  width: number,
74
78
  model: string,
75
- provider: string,
76
79
  title?: string,
77
80
  gitInfo?: GitHeaderInfo,
78
81
  version: string = VERSION,
79
- note: string = '',
82
+ modelNote?: string,
83
+ view?: HeaderView,
80
84
  ): Line[] {
81
- const lines: Line[] = [];
82
- // Header/footer/thinking paint on the transparent terminal background, so
83
- // they read chrome.* (light-terminal-aware), NOT fg.*/state.*, which stay
84
- // tuned for the opaque dark modal/panel boxes. Read live per render so a
85
- // mode flip re-resolves without any module reload (see theme.ts).
86
- const t = activeUiTones();
87
- const CYAN = t.accent.brand;
88
- const GREY = t.chrome.faint;
89
- const TITLE_COLOR = t.chrome.label;
90
- const brand = ` GoodVibes `;
91
- const ver = `v${version} `;
92
- const stats = ` ${model} `;
93
- const prov = `(${provider}) `;
94
- const gitWidth = gitInfo ? buildGitSegment(gitInfo).width : 0;
95
- // Resolve the marker before the title so the title's fit calculation
96
- // reserves room for it too.
97
- const noteStr = fitHeaderNote(note, getDisplayWidth(brand + ver + stats + prov) + gitWidth, width);
85
+ const t = activeTokens();
98
86
  const line = createEmptyLine(width);
99
- let curX = 0;
100
- for (const char of brand) { line[curX++] = { char, fg: CYAN, bg: '', bold: true, dim: false, underline: false, italic: false, strikethrough: false }; }
101
- for (const char of ver) { line[curX++] = { char, fg: GREY, bg: '', bold: false, dim: true, underline: false, italic: false, strikethrough: false }; }
102
- // Optional conversation title, shown after brand/ver, truncated to fit
87
+ for (const cell of line) cell.bg = '';
88
+ const end = width - 1; // exclusive: the model ends at width-2
89
+ if (view) return [renderViewHeader(line, width, version, view)];
90
+
91
+ // Right side first, so the title knows how much room it has.
92
+ const leftMin = BRAND_X + BRAND.length + 1 + getDisplayWidth(version);
93
+ const fits = (w: number): boolean => leftMin + GAP + w <= end;
94
+ let note = '';
95
+ if (modelNote) {
96
+ const full = ` · ${modelNote}`;
97
+ const short = ' · divergent';
98
+ const baseW = getDisplayWidth(model);
99
+ if (fits(baseW + getDisplayWidth(full))) note = full;
100
+ else if (fits(baseW + getDisplayWidth(short))) note = short;
101
+ }
102
+ const modelW = getDisplayWidth(model) + getDisplayWidth(note);
103
+ const branch = gitInfo ? branchSegments(gitInfo) : [];
104
+ const branchW = branch.reduce((s, seg) => s + getDisplayWidth(seg.text), 0);
105
+ const showBranch = branchW > 0 && fits(branchW + GAP + modelW);
106
+ const rightW = modelW + (showBranch ? branchW + GAP : 0);
107
+ const rightX = Math.max(leftMin + GAP, end - rightW);
108
+
109
+ // Brand, version, title.
110
+ let x = BRAND_X;
111
+ [...BRAND].forEach((ch, i) => {
112
+ x = put(line, x, end, { text: ch, fg: interpolateColor(t.brand, t.brandEnd, i / (BRAND.length - 1)), bold: true });
113
+ });
114
+ x = put(line, x + 1, end, { text: version, fg: t.textFaint });
103
115
  if (title) {
104
- const titleStr = `│ ${title} `;
105
- // Reserve space for git info (if present) + model/provider + marker on the right
106
- const rightReserved = getDisplayWidth(stats + prov + noteStr) + gitWidth;
107
- const maxTitleW = width - curX - rightReserved - 1;
108
- let displayTitle: string;
109
- if (getDisplayWidth(titleStr) <= maxTitleW) {
110
- displayTitle = titleStr;
111
- } else {
112
- let truncated = '';
113
- let w = 0;
114
- for (const ch of titleStr) {
115
- const cw = getDisplayWidth(ch);
116
- if (w + cw > maxTitleW - 3) { truncated += '...'; break; }
117
- truncated += ch;
118
- w += cw;
119
- }
120
- displayTitle = truncated;
121
- }
122
- for (const char of displayTitle) { if (curX < width) line[curX++] = { char, fg: TITLE_COLOR, bg: '', bold: false, dim: true, underline: false, italic: false, strikethrough: false }; }
116
+ const room = rightX - GAP - (x + 2);
117
+ if (room >= 4) put(line, x + 2, rightX - GAP, { text: truncateDisplay(title, room), fg: t.textMuted });
123
118
  }
124
- // Build git info segment
125
- let gitStr = '';
126
- let gitFg: string = t.chrome.faint;
127
- if (gitInfo) {
128
- gitStr = buildGitSegment(gitInfo).text;
129
- if (gitInfo.dirty || gitInfo.ahead > 0 || gitInfo.behind > 0) {
130
- gitFg = t.chrome.warn; // yellow when dirty or out-of-sync
131
- }
119
+
120
+ let rx = rightX;
121
+ if (showBranch) {
122
+ for (const seg of branch) rx = put(line, rx, end, seg);
123
+ rx += GAP;
132
124
  }
133
- const rightSideW = getDisplayWidth(stats + prov + noteStr) + getDisplayWidth(gitStr);
134
- let rightX = width - rightSideW;
135
- for (const char of gitStr) { if (rightX >= 0 && rightX < width) line[rightX++] = { char, fg: gitFg, bg: '', bold: false, dim: !gitInfo?.dirty && !(gitInfo?.ahead || gitInfo?.behind), underline: false, italic: false, strikethrough: false }; }
136
- for (const char of stats) { if (rightX < width) line[rightX++] = { char, fg: CYAN, bg: '', bold: true, dim: false, underline: false, italic: false, strikethrough: false }; }
137
- for (const char of prov) { if (rightX < width) line[rightX++] = { char, fg: GREY, bg: '', bold: false, dim: true, underline: false, italic: false, strikethrough: false }; }
138
- // The marker reads as a warning, not as chrome: serving has left the
139
- // selection the user made and that is worth noticing.
140
- for (const char of noteStr) { if (rightX >= 0 && rightX < width) line[rightX++] = { char, fg: t.chrome.warn, bg: '', bold: false, dim: false, underline: false, italic: false, strikethrough: false }; }
141
- lines.push(line);
142
- const underline = createEmptyLine(width);
143
- for (let x = 0; x < width; x++) underline[x] = { char: '━', fg: t.chrome.faint, bg: '', bold: false, dim: false, underline: false, italic: false, strikethrough: false };
144
- lines.push(underline);
145
- return lines;
125
+ rx = put(line, rx, end, { text: model, fg: t.text });
126
+ if (note) put(line, rx, end, { text: note, fg: t.warning });
127
+ return [line];
146
128
  }
129
+
130
+ /** The header inside an agent or process view. */
131
+ function renderViewHeader(line: Line, width: number, version: string, view: HeaderView): Line {
132
+ const t = activeTokens();
133
+ const end = width - 1;
134
+ let x = BRAND_X;
135
+ [...BRAND].forEach((ch, i) => {
136
+ x = put(line, x, end, { text: ch, fg: interpolateColor(t.brand, t.brandEnd, i / (BRAND.length - 1)), bold: true });
137
+ });
138
+ x = put(line, x + 1, end, { text: version, fg: t.textFaint });
139
+ const crumbsW = view.crumbs.reduce((s, c, i) => s + (i > 0 ? 3 : 0) + getDisplayWidth(c.text), 0);
140
+ // The right side yields before the breadcrumb does: where you are matters more than the model name.
141
+ const roomForRight = end - (x + 2 + crumbsW + GAP);
142
+ const right = roomForRight >= 4 ? truncateDisplay(view.right, roomForRight) : '';
143
+ const rightX = end - getDisplayWidth(right);
144
+ const crumbEnd = right ? rightX - GAP : end;
145
+ x += 2;
146
+ view.crumbs.forEach((crumb, i) => {
147
+ if (i > 0) x = put(line, x + 1, crumbEnd, { text: '›', fg: t.textFaint }) + 1;
148
+ const last = i === view.crumbs.length - 1;
149
+ const room = crumbEnd - x;
150
+ x = put(line, x, crumbEnd, { text: last ? truncateDisplay(crumb.text, Math.max(0, room)) : crumb.text, fg: crumb.fg, bold: crumb.bold });
151
+ });
152
+ if (right) put(line, rightX, end, { text: right, fg: view.rightFg ?? t.text });
153
+ return line;
154
+ }
155
+
156
+ /**
157
+ * The main screen's header block with its gap: the header row (and the
158
+ * session chips row, when it shows), then one empty row, so output never
159
+ * touches the header. An agent or process view's body starts with its own
160
+ * empty row, so a view does not take this one.
161
+ */
162
+ export function withHeaderGap(header: readonly Line[], width: number): Line[] {
163
+ const gap = createEmptyLine(width);
164
+ for (const cell of gap) cell.bg = '';
165
+ return [...header, gap];
166
+ }
167
+
168
+ /** Rows the gap under the main screen's header adds. */
169
+ export const HEADER_GAP_ROWS = 1;