@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,192 @@
1
+ /**
2
+ * process-view.ts, a background process opened full screen: its live output.
3
+ *
4
+ * row 0 blank
5
+ * rows HH:MM:SS at column 3 (faint), the line from column 13,
6
+ * wrapped to width-4 with continuations at column 13; a
7
+ * line that reads as an error in the error color
8
+ * second-last blank
9
+ * last the follow state: "▾ following · new output scrolls in",
10
+ * or how far up you are, or how the process ended; while
11
+ * searching, the search line in its place
12
+ *
13
+ * Follow mode is on by default: the newest output stays in view. Scrolling
14
+ * up leaves it; End (or scrolling back to the bottom) returns to it. A search
15
+ * leaves follow mode and jumps between matching lines.
16
+ */
17
+
18
+ import { createEmptyLine, type Line } from '@pellux/goodvibes-sdk/platform/types';
19
+ import { getDisplayWidth, truncateDisplay, wrapText } from '../utils/terminal-width.ts';
20
+ import { activeTokens } from './theme.ts';
21
+ import { keycapHintsWidth, paintKeycapHints } from './surface-kit-parts.ts';
22
+ import type { ProcessLine } from '../core/process-output-log.ts';
23
+
24
+ const TIME_X = 3;
25
+ const TEXT_X = 13;
26
+
27
+ /** One screen row of output. */
28
+ export interface ProcessRow {
29
+ /** The source line's index in the log. */
30
+ readonly source: number;
31
+ /** Set on the first row of a line. */
32
+ readonly time?: string;
33
+ readonly text: string;
34
+ readonly error: boolean;
35
+ }
36
+
37
+ export interface ProcessSearchState {
38
+ readonly query: string;
39
+ /** Typing the query (the search line takes the keys). */
40
+ readonly editing: boolean;
41
+ /** The log line of the current match (-1 when nothing matches). */
42
+ readonly current: number;
43
+ }
44
+
45
+ export interface ProcessViewInput {
46
+ readonly width: number;
47
+ /** Rows the view may use. */
48
+ readonly height: number;
49
+ readonly rows: readonly ProcessRow[];
50
+ /** Rows scrolled up from the newest; 0 follows the output. */
51
+ readonly scrollFromBottom: number;
52
+ readonly color: string;
53
+ /** How the process ended, once it has ("exited with code 0 · 12m 04s"). */
54
+ readonly ended?: { readonly text: string; readonly ok: boolean } | null;
55
+ readonly search?: ProcessSearchState | null;
56
+ /** Lines the log dropped off the front (its bound). */
57
+ readonly dropped?: number;
58
+ }
59
+
60
+ function twoDigits(n: number): string {
61
+ return n < 10 ? `0${n}` : String(n);
62
+ }
63
+
64
+ /** HH:MM:SS in local time. */
65
+ function clockTime(at: number): string {
66
+ const d = new Date(at);
67
+ return `${twoDigits(d.getHours())}:${twoDigits(d.getMinutes())}:${twoDigits(d.getSeconds())}`;
68
+ }
69
+
70
+ /** Wrap log lines into screen rows (the caller caches this per width and line count). */
71
+ export function processRows(lines: readonly ProcessLine[], width: number, formatTime: (at: number) => string = clockTime): ProcessRow[] {
72
+ const room = Math.max(10, width - 4 - TEXT_X);
73
+ const rows: ProcessRow[] = [];
74
+ lines.forEach((line, source) => {
75
+ const parts = line.text.length === 0 ? [''] : wrapText(line.text, room);
76
+ parts.forEach((text, k) => rows.push({ source, time: k === 0 ? formatTime(line.at) : undefined, text, error: line.error }));
77
+ });
78
+ return rows;
79
+ }
80
+
81
+ /** Source indexes of lines containing the query (case-insensitive). */
82
+ export function processMatches(lines: readonly ProcessLine[], query: string): number[] {
83
+ const q = query.toLowerCase();
84
+ if (!q) return [];
85
+ const out: number[] = [];
86
+ lines.forEach((line, i) => { if (line.text.toLowerCase().includes(q)) out.push(i); });
87
+ return out;
88
+ }
89
+
90
+ function put(line: Line, x: number, endX: number, text: string, style: { fg: string; bg?: string; bold?: boolean }): number {
91
+ let cx = x;
92
+ for (const ch of text) {
93
+ const w = getDisplayWidth(ch);
94
+ if (w <= 0) continue;
95
+ if (cx + w > endX || cx >= line.length) break;
96
+ line[cx] = { char: ch, fg: style.fg, bg: style.bg ?? '', bold: style.bold ?? false, dim: false, underline: false, italic: false, strikethrough: false };
97
+ if (w === 2 && cx + 1 < line.length) line[cx + 1] = { ...line[cx]!, char: '' };
98
+ cx += w;
99
+ }
100
+ return cx;
101
+ }
102
+
103
+ function blank(width: number): Line {
104
+ const line = createEmptyLine(width);
105
+ for (const cell of line) cell.bg = '';
106
+ return line;
107
+ }
108
+
109
+ /** Tint every occurrence of the query on a drawn row. */
110
+ function markMatches(line: Line, text: string, query: string, bg: string): void {
111
+ if (!query) return;
112
+ const lower = text.toLowerCase();
113
+ const q = query.toLowerCase();
114
+ let from = 0;
115
+ for (;;) {
116
+ const at = lower.indexOf(q, from);
117
+ if (at < 0) return;
118
+ const x0 = TEXT_X + getDisplayWidth(text.slice(0, at));
119
+ const w = getDisplayWidth(text.slice(at, at + q.length));
120
+ for (let x = x0; x < x0 + w && x < line.length; x++) line[x] = { ...line[x]!, bg };
121
+ from = at + q.length;
122
+ }
123
+ }
124
+
125
+ /** The largest scrollFromBottom that still shows rows. */
126
+ export function processMaxScroll(rowCount: number, height: number): number {
127
+ return Math.max(0, rowCount - Math.max(1, height - 3));
128
+ }
129
+
130
+ export function renderProcessView(input: ProcessViewInput): Line[] {
131
+ const t = activeTokens();
132
+ const { width } = input;
133
+ const logRows = Math.max(1, input.height - 3);
134
+ const end = width - 3;
135
+ const scroll = Math.max(0, Math.min(input.scrollFromBottom, processMaxScroll(input.rows.length, input.height)));
136
+ const last = input.rows.length - scroll;
137
+ const first = Math.max(0, last - logRows);
138
+ const search = input.search ?? null;
139
+
140
+ const out: Line[] = [blank(width)];
141
+ if (input.rows.length === 0) {
142
+ const line = blank(width);
143
+ put(line, TIME_X, end, input.ended ? 'The process printed nothing.' : 'No output yet.', { fg: t.textFaint });
144
+ out.push(line);
145
+ }
146
+ if (first === 0 && (input.dropped ?? 0) > 0 && input.rows.length > 0) {
147
+ const line = blank(width);
148
+ put(line, TIME_X, end, `… ${input.dropped} earlier lines are no longer kept`, { fg: t.textFaint });
149
+ out.push(line);
150
+ }
151
+ for (let r = first; r < last; r++) {
152
+ const row = input.rows[r]!;
153
+ const line = blank(width);
154
+ if (row.time) put(line, TIME_X, TEXT_X - 1, row.time, { fg: t.textFaint });
155
+ put(line, TEXT_X, end, row.text, { fg: row.error ? t.error : t.text });
156
+ if (search && search.query) markMatches(line, row.text, search.query, row.source === search.current ? t.searchCurrentBg : t.searchMatchBg);
157
+ out.push(line);
158
+ }
159
+ while (out.length < input.height - 2) out.push(blank(width));
160
+ out.length = Math.min(out.length, Math.max(0, input.height - 2));
161
+ out.push(blank(width));
162
+ out.push(statusRow(input, scroll, end));
163
+ return out;
164
+ }
165
+
166
+ function statusRow(input: ProcessViewInput, scroll: number, end: number): Line {
167
+ const t = activeTokens();
168
+ const line = blank(input.width);
169
+ const search = input.search ?? null;
170
+ if (search && (search.editing || search.query)) {
171
+ let x = put(line, TIME_X, end, '/', { fg: input.color, bold: true });
172
+ x = put(line, x + 1, end, search.query, { fg: t.text });
173
+ if (search.editing) x = put(line, x, end, '▏', { fg: input.color });
174
+ const hints: Array<[string, string]> = search.editing ? [['⏎', 'next'], ['esc', 'close']] : [['n', 'next'], ['/', 'edit'], ['esc', 'close']];
175
+ const hintsW = keycapHintsWidth(hints);
176
+ if (x + 3 + hintsW <= end) paintKeycapHints(line, x + 3, end, hints, { fg: t.textFaint });
177
+ return line;
178
+ }
179
+ if (scroll > 0) {
180
+ const x = put(line, TIME_X, end, '▴', { fg: input.color, bold: true });
181
+ put(line, x + 1, end, truncateDisplay(`paused · ${scroll} newer row${scroll === 1 ? '' : 's'} below · end follows again`, Math.max(0, end - x - 1)), { fg: t.textFaint });
182
+ return line;
183
+ }
184
+ if (input.ended) {
185
+ const x = put(line, TIME_X, end, '■', { fg: input.ended.ok ? t.success : t.error, bold: true });
186
+ put(line, x + 1, end, truncateDisplay(input.ended.text, Math.max(0, end - x - 1)), { fg: input.ended.ok ? t.textFaint : t.error });
187
+ return line;
188
+ }
189
+ const x = put(line, TIME_X, end, '▾', { fg: input.color, bold: true });
190
+ put(line, x + 1, end, 'following · new output scrolls in', { fg: t.textFaint });
191
+ return line;
192
+ }
@@ -1,128 +1,76 @@
1
1
  /**
2
- * renderProfilePickerModal, renders the /profiles picker modal as Line[]
3
- * using ModalFactory.
4
- *
5
- * Shows a list of saved profiles with:
6
- * - name, timestamp (formatted)
7
- * Footer hints: [Up/Down] Navigate [Enter] Load [d] Arm/Delete [s] Save current [Esc] Close
2
+ * renderProfilePickerModal, the /profiles picker drawn with the modal surface
3
+ * kit: the always-live search row (filters by name), one kit row per saved
4
+ * profile (name, saved time right-aligned), an armed delete shown in the
5
+ * error color with its "press d again" prompt, the status line, and keycap
6
+ * hints: ↑↓ move · ⏎ load · d delete · s save current.
8
7
  */
9
8
 
10
- import type { Line } from '@pellux/goodvibes-sdk/platform/types';
11
- import { ModalFactory } from './modal-factory.ts';
12
9
  import type { ProfilePickerModal } from '../input/profile-picker-modal.ts';
13
10
  import { formatTimestamp } from './modal-utils.ts';
14
- import { fitDisplay } from '../utils/terminal-width.ts';
15
- import { getOverlaySurfaceMetrics, getStableOverlayContentRows } from './overlay-viewport.ts';
11
+ import { activeTokens } from './theme.ts';
12
+ import {
13
+ beginModal,
14
+ finishModal,
15
+ searchRow,
16
+ scrollCountText,
17
+ type KitHint,
18
+ type SurfaceLayer,
19
+ } from './surface-kit.ts';
20
+ import { drawList, type KitRow } from './surface-kit-list.ts';
21
+ import { drawTextBlock, listHeight, modalHeightFor, modalTextWidth, textBlockHeight, type TextLine } from './surface-kit-extra.ts';
16
22
 
17
- // ---------------------------------------------------------------------------
18
- // Renderer
19
- // ---------------------------------------------------------------------------
23
+ const HINTS: readonly KitHint[] = [['↑↓', 'move'], ['⏎', 'load'], ['d', 'delete'], ['s', 'save current']];
20
24
 
21
25
  /**
22
- * Render the profile picker modal as Line[] for overlay in the viewport.
23
- *
24
- * @param modal ProfilePickerModal state object.
25
- * @param width Terminal width.
26
+ * Render the profile picker modal as a SurfaceLayer in screen coordinates.
26
27
  */
27
28
  export function renderProfilePickerModal(
28
29
  modal: ProfilePickerModal,
29
- width: number,
30
- viewportHeight = 24,
31
- ): Line[] {
32
- const metrics = getOverlaySurfaceMetrics(width, viewportHeight, {
33
- chromeRows: 6,
34
- minContentRows: 5,
35
- maxContentRows: 9,
36
- });
37
- const boxMargin = metrics.margin;
38
- const boxW = metrics.boxWidth;
39
- const contentW = metrics.contentWidth;
40
- const visibleRows = metrics.contentRows;
41
- const targetContentRows = getStableOverlayContentRows(metrics.contentRows, 8);
42
- modal.setVisibleRows(visibleRows);
30
+ screenWidth: number,
31
+ screenHeight = 24,
32
+ ): SurfaceLayer {
33
+ const t = activeTokens();
34
+ const visible = modal.visibleProfiles;
35
+ const armed = modal.deleteConfirmationTarget;
36
+ const rows: KitRow[] = visible.map((profile, i) => ({
37
+ label: profile.name,
38
+ right: formatTimestamp(profile.timestamp),
39
+ selected: i === modal.selectedIndex,
40
+ danger: armed === profile.name,
41
+ mark: armed === profile.name ? '✕' : undefined,
42
+ markFg: t.error,
43
+ }));
43
44
 
44
- const sections: import('./modal-factory.ts').ModalSection[] = [];
45
+ const notes: TextLine[] = [];
46
+ if (armed) notes.push({ text: `Press d again to permanently delete ${armed}.`, style: { fg: t.warning, bold: true } });
47
+ else if (modal.statusMessage) notes.push({ text: modal.statusMessage, style: { fg: t.accent } });
45
48
 
46
- if (modal.profiles.length === 0) {
47
- sections.push({
48
- type: 'text',
49
- content: 'No saved profiles.',
50
- style: { fg: '244', dim: true },
51
- });
52
- sections.push({
53
- type: 'text',
54
- content: 'Press [s] to save the current settings as a profile.',
55
- style: { fg: '240', dim: true },
56
- });
57
- } else {
58
- // Proportional column widths that adapt to the modal's content width:
59
- // timestamp ~22% (clamped 10..16); the name column absorbs the remainder
60
- // (ported from session-picker-modal.ts). Reserves 4 cols, 2 for the
61
- // name/timestamp separator and 2 for the list row's selection indicator
62
- // ("▸ ") that ModalFactory prepends outside the wrapped label, so the
63
- // row never spills the timestamp's embedded space onto a wrapped line.
64
- const tsW = Math.min(16, Math.max(10, Math.floor(contentW * 0.22)));
65
- const nameW = Math.max(8, contentW - tsW - 4);
66
-
67
- // Column header
68
- const nameHdr = fitDisplay('Name', nameW);
69
- const tsHdr = fitDisplay('Saved', tsW);
70
- sections.push({
71
- type: 'text',
72
- content: `${nameHdr} ${tsHdr}`,
73
- style: { fg: '240', dim: true },
74
- });
75
- sections.push({ type: 'separator' });
76
-
77
- const visibleProfiles = modal.profiles.slice(modal.scrollOffset, modal.scrollOffset + visibleRows);
78
- const listItems: import('./modal-factory.ts').ModalListItem[] = visibleProfiles.map((prof, idx) => {
79
- const isSelected = modal.scrollOffset + idx === modal.selectedIndex;
49
+ const width = modalTextWidth(screenWidth, screenHeight);
50
+ const allRows = modal.profiles.map((profile): KitRow => ({ label: profile.name, right: formatTimestamp(profile.timestamp) }));
51
+ const emptyLines: TextLine[] = [
52
+ { text: 'No saved profiles.', style: { fg: t.textMuted } },
53
+ { text: 'Press s to save the current settings as a profile.', style: { fg: t.textFaint } },
54
+ ];
55
+ const listRows = allRows.length > 0 ? listHeight(allRows, 0, width - 1) : textBlockHeight(emptyLines, width);
56
+ const noteRows = notes.length > 0 ? textBlockHeight(notes, width) + 1 : 0;
57
+ const height = modalHeightFor(screenWidth, screenHeight, { hints: HINTS }, 2 + listRows + noteRows);
80
58
 
81
- const nameStr = fitDisplay(prof.name, nameW);
59
+ const f = beginModal(screenWidth, screenHeight, { title: 'Profiles', hints: HINTS, height });
60
+ const total = modal.profiles.length;
61
+ searchRow(f, f.top, modal.query, 'Filter profiles', modal.query ? `${visible.length} of ${total}` : `${total} saved`);
82
62
 
83
- const tsStr = fitDisplay(formatTimestamp(prof.timestamp), tsW);
63
+ const top = f.top + 2;
64
+ const listBottom = f.bottom - noteRows;
65
+ if (notes.length > 0) drawTextBlock(f.canvas, f.l, listBottom + 2, f.r - f.l + 1, notes, f.bottom);
84
66
 
85
- const label = `${nameStr} ${tsStr}`;
86
- return { label, selected: isSelected };
87
- });
88
-
89
- sections.push({ type: 'list', items: listItems });
90
- if (modal.profiles.length > visibleRows) {
91
- sections.push({ type: 'separator' });
92
- sections.push({
93
- type: 'text',
94
- content: `[${modal.scrollOffset + 1}-${Math.min(modal.profiles.length, modal.scrollOffset + visibleRows)} of ${modal.profiles.length}]`,
95
- style: { fg: '244', dim: true },
96
- });
97
- }
98
- }
99
-
100
- // Status message if present
101
- if (modal.statusMessage) {
102
- sections.push({ type: 'separator' });
103
- sections.push({
104
- type: 'text',
105
- content: modal.statusMessage,
106
- style: { fg: '#00ffcc' },
107
- });
108
- }
109
- if (modal.deleteConfirmationTarget) {
110
- sections.push({
111
- type: 'text',
112
- content: `Press [d] again to permanently delete ${modal.deleteConfirmationTarget}.`,
113
- style: { fg: '#f59e0b', dim: true },
114
- });
67
+ if (total === 0) {
68
+ drawTextBlock(f.canvas, f.l, top, f.r - f.l + 1, emptyLines, listBottom);
69
+ } else if (rows.length === 0) {
70
+ drawTextBlock(f.canvas, f.l, top, f.r - f.l + 1, [{ text: `No profiles match "${modal.query}".`, style: { fg: t.textMuted } }], listBottom);
71
+ } else {
72
+ const res = drawList(f.canvas, { rows, top, bottom: listBottom, x0: f.l, x1: f.r });
73
+ f.hintRight = scrollCountText(res.above, res.below);
115
74
  }
116
-
117
- return ModalFactory.createModal(
118
- {
119
- title: 'Profiles',
120
- width: boxW,
121
- margin: boxMargin,
122
- targetContentRows,
123
- sections,
124
- hints: ['[Up/Down] Navigate', '[Enter] Load', '[d] Arm/Delete', '[s] Save current', '[Esc] Close'],
125
- },
126
- width,
127
- );
75
+ return finishModal(f);
128
76
  }
@@ -2,6 +2,7 @@ import type { Line } from '@pellux/goodvibes-sdk/platform/types';
2
2
  import { fitDisplay, getDisplayWidth, truncateDisplay } from '../utils/terminal-width.ts';
3
3
  import type { SearchManager } from '../input/search.ts';
4
4
  import { createBottomBarLine, writeBottomBarText } from '@pellux/goodvibes-terminal-shell';
5
+ import { activeTokens } from './theme.ts';
5
6
 
6
7
  /**
7
8
  * Render the search bar as a single Line[] overlay at the bottom of the viewport.
@@ -65,13 +66,15 @@ export function renderSearchOverlay(
65
66
 
66
67
  // Build the full line text (match count embedded for positional tracking)
67
68
  const fullLine = truncatedLeft + matchStr + hints + ' ';
68
- const line = createBottomBarLine(width, { fg: '#000000', bg: '#00ffcc' });
69
- writeBottomBarText(line, 0, width, fitDisplay(truncateDisplay(fullLine, width), width), { fg: '#000000', bg: '#00ffcc' });
69
+ const p = activeTokens();
70
+ const line = createBottomBarLine(width, { fg: p.selectedListItemText, bg: p.accent });
71
+ writeBottomBarText(line, 0, width, fitDisplay(truncateDisplay(fullLine, width), width), { fg: p.selectedListItemText, bg: p.accent });
70
72
 
71
73
  // Overwrite match count segment with dim grey styling
72
74
  if (matchStr.length > 0) {
73
75
  const matchStart = getDisplayWidth(truncatedLeft);
74
- writeBottomBarText(line, matchStart, matchStrW, matchStr, { fg: '#888888', bg: '#00ffcc', dim: true });
76
+ // dim kept: de-emphasis on the accent bar, where a faint grey would not read.
77
+ writeBottomBarText(line, matchStart, matchStrW, matchStr, { fg: p.selectedListItemText, bg: p.accent, dim: true });
75
78
  }
76
79
 
77
80
  return [line];