@pellux/goodvibes-tui 2.0.21 → 2.1.0

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 (388) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +16 -16
  3. package/docs/README.md +4 -4
  4. package/docs/foundation-artifacts/operator-contract.json +1 -1
  5. package/package.json +16 -6
  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-registry.ts +77 -35
  52. package/src/input/commands/acp-runtime.ts +19 -9
  53. package/src/input/commands/channel-runtime.ts +2 -2
  54. package/src/input/commands/ci-runtime.ts +1 -1
  55. package/src/input/commands/codebase-runtime.ts +1 -1
  56. package/src/input/commands/config.ts +7 -1
  57. package/src/input/commands/context-window.ts +25 -19
  58. package/src/input/commands/control-room-runtime.ts +18 -18
  59. package/src/input/commands/conversation-runtime.ts +0 -1
  60. package/src/input/commands/cost-runtime.ts +29 -20
  61. package/src/input/commands/diff-runtime.ts +35 -181
  62. package/src/input/commands/eval.ts +1 -1
  63. package/src/input/commands/experience-runtime.ts +3 -7
  64. package/src/input/commands/fresh-conversation.ts +86 -0
  65. package/src/input/commands/git-runtime.ts +5 -22
  66. package/src/input/commands/graph-runtime.ts +1 -1
  67. package/src/input/commands/guidance-runtime.ts +1 -1
  68. package/src/input/commands/health-runtime.ts +8 -9
  69. package/src/input/commands/hooks-runtime.ts +2 -2
  70. package/src/input/commands/hosted-runtime.ts +3 -3
  71. package/src/input/commands/incident-runtime.ts +3 -3
  72. package/src/input/commands/intelligence-runtime.ts +6 -9
  73. package/src/input/commands/knowledge.ts +2 -2
  74. package/src/input/commands/legacy-panel-command.ts +57 -0
  75. package/src/input/commands/local-auth-runtime.ts +8 -9
  76. package/src/input/commands/local-provider-runtime.ts +7 -4
  77. package/src/input/commands/local-runtime.ts +12 -15
  78. package/src/input/commands/local-setup-review.ts +1 -1
  79. package/src/input/commands/local-setup.ts +13 -19
  80. package/src/input/commands/memory.ts +1 -1
  81. package/src/input/commands/notify-runtime.ts +9 -0
  82. package/src/input/commands/operator-runtime.ts +10 -12
  83. package/src/input/commands/permissions-provenance.ts +3 -3
  84. package/src/input/commands/planning-runtime.ts +7 -7
  85. package/src/input/commands/platform-sandbox-runtime.ts +2 -2
  86. package/src/input/commands/platform-services-runtime.ts +1 -1
  87. package/src/input/commands/policy-dispatch.ts +2 -2
  88. package/src/input/commands/policy.ts +3 -3
  89. package/src/input/commands/provider.ts +1 -1
  90. package/src/input/commands/remote-runtime.ts +1 -1
  91. package/src/input/commands/review-runtime.ts +39 -94
  92. package/src/input/commands/rewind-runtime.ts +81 -108
  93. package/src/input/commands/runtime-services.ts +15 -17
  94. package/src/input/commands/services-runtime.ts +2 -2
  95. package/src/input/commands/session-content.ts +21 -5
  96. package/src/input/commands/session-workflow.ts +13 -38
  97. package/src/input/commands/settings-sync-runtime.ts +2 -2
  98. package/src/input/commands/shell-core.ts +19 -4
  99. package/src/input/commands/skills-runtime.ts +2 -2
  100. package/src/input/commands/status-runtime.ts +13 -0
  101. package/src/input/commands/subscription-runtime.ts +1 -1
  102. package/src/input/commands/tasks-runtime.ts +2 -8
  103. package/src/input/commands/work-plan-runtime.ts +4 -4
  104. package/src/input/commands/workstream-attempts.ts +24 -47
  105. package/src/input/commands/workstream-runtime.ts +2 -2
  106. package/src/input/commands/worktree-runtime.ts +3 -3
  107. package/src/input/commands.ts +3 -1
  108. package/src/input/composer-editor.ts +44 -0
  109. package/src/input/concealed-input.ts +1 -1
  110. package/src/input/config-modal-types.ts +20 -8
  111. package/src/input/config-modal.ts +106 -105
  112. package/src/input/confirm-dialog-types.ts +28 -0
  113. package/src/input/confirm-dialog.ts +70 -0
  114. package/src/input/delete-key-policy.ts +3 -3
  115. package/src/input/feed-context-factory.ts +15 -16
  116. package/src/input/handler-command-route.ts +7 -42
  117. package/src/input/handler-content-actions.ts +16 -15
  118. package/src/input/handler-feed-routes.ts +26 -211
  119. package/src/input/handler-feed.ts +68 -95
  120. package/src/input/handler-interactions.ts +5 -3
  121. package/src/input/handler-modal-routes.ts +215 -216
  122. package/src/input/handler-modal-stack.ts +81 -11
  123. package/src/input/handler-modal-token-routes.ts +4 -0
  124. package/src/input/handler-onboarding.ts +0 -1
  125. package/src/input/handler-picker-routes.ts +65 -107
  126. package/src/input/handler-session-view-route.ts +149 -0
  127. package/src/input/handler-shortcuts.ts +16 -154
  128. package/src/input/handler-types.ts +4 -2
  129. package/src/input/handler-ui-state.ts +45 -15
  130. package/src/input/handler-work-tree-route.ts +123 -0
  131. package/src/input/handler.ts +25 -70
  132. package/src/input/keybindings.ts +16 -71
  133. package/src/input/masked-entry-modal.ts +117 -0
  134. package/src/input/mcp-workspace.ts +48 -17
  135. package/src/input/model-picker-filter.ts +8 -0
  136. package/src/input/model-picker-open.ts +99 -0
  137. package/src/input/model-picker-types.ts +1 -1
  138. package/src/input/model-picker.ts +92 -9
  139. package/src/input/notifications-modal.ts +123 -0
  140. package/src/input/overlay-filter.ts +26 -0
  141. package/src/input/profile-picker-modal.ts +37 -8
  142. package/src/input/search.ts +3 -3
  143. package/src/input/selection-modal-queue.ts +2 -0
  144. package/src/input/selection-modal.ts +28 -16
  145. package/src/input/session-picker-modal.ts +33 -8
  146. package/src/input/settings-modal-activation.ts +7 -2
  147. package/src/input/settings-modal-data.ts +11 -6
  148. package/src/input/settings-modal-types.ts +1 -1
  149. package/src/input/settings-modal.ts +20 -20
  150. package/src/input/submission-intent.ts +1 -1
  151. package/src/input/submission-router.ts +4 -9
  152. package/src/input/surface-modal-host.ts +110 -0
  153. package/src/input/theme-settings-actions.ts +82 -0
  154. package/src/input/usage-modal.ts +183 -0
  155. package/src/input/views.ts +97 -0
  156. package/src/main.ts +175 -165
  157. package/src/permissions/hunk-selection.ts +1 -1
  158. package/src/permissions/prompt-card.ts +511 -0
  159. package/src/permissions/prompt.ts +59 -622
  160. package/src/renderer/agents-modal.ts +310 -0
  161. package/src/renderer/autocomplete-overlay.ts +42 -220
  162. package/src/renderer/back-to-bottom.ts +80 -0
  163. package/src/renderer/block-actions-overlay.ts +30 -48
  164. package/src/renderer/bookmark-modal.ts +48 -79
  165. package/src/renderer/changes-modal.ts +325 -0
  166. package/src/renderer/code-block.ts +184 -106
  167. package/src/renderer/command-palette.ts +93 -0
  168. package/src/renderer/composer-fragments.ts +4 -4
  169. package/src/renderer/composer.ts +146 -0
  170. package/src/renderer/compositor.ts +26 -160
  171. package/src/renderer/config-modal.ts +185 -81
  172. package/src/renderer/confirm-dialog.ts +50 -0
  173. package/src/renderer/context-inspector.ts +116 -154
  174. package/src/renderer/context-status-hint.ts +4 -4
  175. package/src/renderer/conversation-layout.ts +20 -0
  176. package/src/renderer/conversation-overlays.ts +94 -84
  177. package/src/renderer/conversation-surface.ts +19 -38
  178. package/src/renderer/diff-tint.ts +98 -0
  179. package/src/renderer/file-picker-overlay.ts +63 -90
  180. package/src/renderer/footer-targets.ts +38 -0
  181. package/src/renderer/git-status.ts +3 -4
  182. package/src/renderer/header-line.ts +140 -117
  183. package/src/renderer/help-overlay.ts +133 -219
  184. package/src/renderer/history-search-overlay.ts +15 -12
  185. package/src/renderer/lane-graph/bead.ts +800 -0
  186. package/src/renderer/lane-graph/glyphs.ts +134 -0
  187. package/src/renderer/lane-graph/layout.ts +248 -0
  188. package/src/renderer/lane-graph/paint.ts +537 -0
  189. package/src/renderer/lane-graph/semantic-memo.ts +77 -0
  190. package/src/renderer/layout-engine.ts +2 -57
  191. package/src/renderer/layout.ts +7 -13
  192. package/src/renderer/markdown-inline.ts +2 -1
  193. package/src/renderer/markdown-table.ts +17 -12
  194. package/src/renderer/markdown.ts +92 -34
  195. package/src/renderer/masked-entry-modal.ts +78 -0
  196. package/src/renderer/mcp-workspace.ts +166 -203
  197. package/src/renderer/model-workspace.ts +381 -436
  198. package/src/renderer/notifications-modal.ts +116 -0
  199. package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
  200. package/src/renderer/process-view.ts +192 -0
  201. package/src/renderer/profile-picker-modal.ts +58 -110
  202. package/src/renderer/search-overlay.ts +6 -3
  203. package/src/renderer/selection-modal-overlay.ts +87 -327
  204. package/src/renderer/semantic-diff.ts +2 -2
  205. package/src/renderer/session-chips.ts +102 -0
  206. package/src/renderer/session-picker-modal.ts +177 -297
  207. package/src/renderer/settings-modal-connections.ts +14 -23
  208. package/src/renderer/settings-modal-context.ts +367 -0
  209. package/src/renderer/settings-modal-helpers.ts +6 -11
  210. package/src/renderer/settings-modal.ts +322 -726
  211. package/src/renderer/shell-surface.ts +277 -175
  212. package/src/renderer/shortcuts-overlay.ts +217 -0
  213. package/src/renderer/status-line.ts +475 -0
  214. package/src/renderer/surface-compose.ts +174 -0
  215. package/src/renderer/surface-kit-extra.ts +303 -0
  216. package/src/renderer/surface-kit-list.ts +366 -0
  217. package/src/renderer/surface-kit-parts.ts +360 -0
  218. package/src/renderer/surface-kit.ts +568 -0
  219. package/src/renderer/syntax-highlighter.ts +280 -197
  220. package/src/renderer/syntax-theme.ts +51 -0
  221. package/src/renderer/system-message.ts +0 -1
  222. package/src/renderer/term-caps.ts +42 -1
  223. package/src/renderer/terminal-bg-probe.ts +116 -19
  224. package/src/renderer/terminal-palette-probe.ts +322 -0
  225. package/src/renderer/terminal-palette-reader.ts +183 -0
  226. package/src/renderer/terminal-palette.ts +58 -0
  227. package/src/renderer/theme-mode-config.ts +16 -1
  228. package/src/renderer/theme.ts +234 -207
  229. package/src/renderer/thinking.ts +0 -1
  230. package/src/renderer/throbber.ts +188 -0
  231. package/src/renderer/toast-center.ts +119 -0
  232. package/src/renderer/ui-factory.ts +39 -602
  233. package/src/renderer/ui-primitives.ts +8 -25
  234. package/src/renderer/usage-modal.ts +353 -0
  235. package/src/renderer/user-message.ts +58 -0
  236. package/src/renderer/voice-capture-chip.ts +53 -0
  237. package/src/runtime/bootstrap-command-context.ts +0 -5
  238. package/src/runtime/bootstrap-command-parts.ts +38 -89
  239. package/src/runtime/bootstrap-core.ts +13 -15
  240. package/src/runtime/bootstrap-hook-bridge.ts +12 -21
  241. package/src/runtime/bootstrap-notifier-sync.ts +17 -1
  242. package/src/runtime/bootstrap-shell.ts +16 -50
  243. package/src/runtime/bootstrap.ts +14 -14
  244. package/src/runtime/client/fleet-union.ts +5 -5
  245. package/src/runtime/client/hosted-exit.ts +2 -2
  246. package/src/runtime/client/hosted-sessions.ts +1 -1
  247. package/src/runtime/client/spine-adoption.ts +1 -1
  248. package/src/runtime/context-accounting-source.ts +5 -4
  249. package/src/runtime/index.ts +1 -0
  250. package/src/runtime/notification-dispatch.ts +102 -29
  251. package/src/runtime/recovery-offer-wiring.ts +4 -1
  252. package/src/runtime/recovery-prompt.ts +31 -15
  253. package/src/runtime/runtime-services-types.ts +10 -6
  254. package/src/runtime/services.ts +17 -12
  255. package/src/runtime/session-continuity-hints.ts +2 -5
  256. package/src/runtime/session-inbound-inputs.ts +1 -1
  257. package/src/runtime/session-resume-liveness-confirm.ts +14 -2
  258. package/src/runtime/startup-typeahead-gate.ts +103 -0
  259. package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
  260. package/src/runtime/store/domains/index.ts +0 -8
  261. package/src/runtime/store/selectors/index.ts +0 -28
  262. package/src/runtime/store/state.ts +0 -8
  263. package/src/runtime/ui-services.ts +4 -6
  264. package/src/runtime/usage-tracker.ts +348 -0
  265. package/src/runtime/wrfc-persistence.ts +4 -4
  266. package/src/shell/blocking-input.ts +92 -2
  267. package/src/shell/recovery-input-helpers.ts +1 -1
  268. package/src/shell/session-views.ts +539 -0
  269. package/src/shell/status-report.ts +86 -0
  270. package/src/shell/transcript-scroll.ts +68 -0
  271. package/src/shell/ui-openers.ts +84 -172
  272. package/src/shell/view-openers.ts +205 -0
  273. package/src/tools/wrfc-agent-guard.ts +22 -2
  274. package/src/utils/format-duration.ts +4 -8
  275. package/src/utils/splash-lines.ts +9 -1
  276. package/src/utils/terminal-width.ts +56 -0
  277. package/src/verification/verification-ledger.ts +18 -16
  278. package/src/{panels → views}/agent-inspector-shared.ts +2 -2
  279. package/src/{panels → views}/builtin-modals.ts +22 -21
  280. package/src/views/builtin-views.ts +135 -0
  281. package/src/{panels → views}/confirm-state.ts +9 -9
  282. package/src/{panels → views}/diff-review-model.ts +10 -3
  283. package/src/{panels → views}/eval-registry.ts +1 -1
  284. package/src/{panels → views}/fleet-acts.ts +49 -85
  285. package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
  286. package/src/{panels → views}/fleet-gateway.ts +5 -5
  287. package/src/{panels → views}/fleet-observed-render.ts +16 -16
  288. package/src/{panels → views}/fleet-read-model.ts +9 -9
  289. package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
  290. package/src/{panels → views}/fleet-spawn.ts +33 -49
  291. package/src/{panels → views}/fleet-steer.ts +12 -12
  292. package/src/{panels → views}/fleet-stop.ts +4 -4
  293. package/src/{panels → views}/fleet-transcript.ts +26 -27
  294. package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
  295. package/src/{panels → views}/hosted-session-feed.ts +6 -6
  296. package/src/views/modal-surface-registry.ts +41 -0
  297. package/src/{panels → views}/modals/devices-modal.ts +2 -2
  298. package/src/{panels → views}/modals/hooks-modal.ts +13 -13
  299. package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
  300. package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
  301. package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
  302. package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
  303. package/src/{panels → views}/modals/memory-modal.ts +8 -8
  304. package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
  305. package/src/{panels → views}/modals/pairing-modal.ts +9 -9
  306. package/src/{panels → views}/modals/planning-modal.ts +15 -20
  307. package/src/{panels → views}/modals/plugins-modal.ts +6 -6
  308. package/src/{panels → views}/modals/policy-modal.ts +13 -5
  309. package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
  310. package/src/{panels → views}/modals/remote-modal.ts +3 -3
  311. package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
  312. package/src/{panels → views}/modals/security-modal.ts +22 -16
  313. package/src/{panels → views}/modals/services-modal.ts +3 -3
  314. package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
  315. package/src/{panels → views}/modals/skills-modal.ts +9 -9
  316. package/src/{panels → views}/modals/subscription-modal.ts +3 -3
  317. package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
  318. package/src/views/notifications-feed.ts +314 -0
  319. package/src/{panels → views}/polish-core.ts +38 -36
  320. package/src/{panels → views}/polish-tables.ts +35 -26
  321. package/src/{panels → views}/polish.ts +101 -95
  322. package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
  323. package/src/{panels → views}/provider-health-routes.ts +14 -14
  324. package/src/{panels → views}/search-focus.ts +8 -8
  325. package/src/{panels → views}/session-maintenance.ts +11 -11
  326. package/src/views/skills-discovery.ts +159 -0
  327. package/src/views/view-deps.ts +80 -0
  328. package/src/views/view-panel-adapter.ts +53 -0
  329. package/src/{panels → views}/workstream-graph-render.ts +1 -1
  330. package/src/core/conversation-fold.ts +0 -101
  331. package/src/core/conversation-turn-structure.ts +0 -464
  332. package/src/core/conversation-user-receipts.ts +0 -42
  333. package/src/input/commands/operator-panel-runtime.ts +0 -186
  334. package/src/input/panel-integration-actions.ts +0 -33
  335. package/src/input/panel-mouse-geometry.ts +0 -97
  336. package/src/input/panel-paste-flood-guard.ts +0 -86
  337. package/src/panels/base-panel.ts +0 -301
  338. package/src/panels/builtin/agent.ts +0 -27
  339. package/src/panels/builtin/development.ts +0 -92
  340. package/src/panels/builtin/knowledge.ts +0 -12
  341. package/src/panels/builtin/operations.ts +0 -177
  342. package/src/panels/builtin/session.ts +0 -81
  343. package/src/panels/builtin/shared.ts +0 -357
  344. package/src/panels/builtin-panels.ts +0 -28
  345. package/src/panels/cost-tracker-panel.ts +0 -746
  346. package/src/panels/diff-panel.ts +0 -797
  347. package/src/panels/diff-review-panel.ts +0 -395
  348. package/src/panels/expandable-list-panel.ts +0 -189
  349. package/src/panels/fleet-deep-link.ts +0 -31
  350. package/src/panels/fleet-panel.ts +0 -799
  351. package/src/panels/git-panel.ts +0 -800
  352. package/src/panels/hosted-session-panel.ts +0 -221
  353. package/src/panels/index.ts +0 -21
  354. package/src/panels/local-auth-panel.ts +0 -478
  355. package/src/panels/notifications-feed.ts +0 -127
  356. package/src/panels/notifications-panel.ts +0 -160
  357. package/src/panels/panel-confirm-overlay.ts +0 -72
  358. package/src/panels/panel-manager.ts +0 -791
  359. package/src/panels/plugins-panel.ts +0 -371
  360. package/src/panels/scrollable-list-panel.ts +0 -498
  361. package/src/panels/skills-panel.ts +0 -454
  362. package/src/panels/token-budget-panel.ts +0 -688
  363. package/src/panels/types.ts +0 -191
  364. package/src/panels/wrfc-panel-format.ts +0 -133
  365. package/src/renderer/diff-view.ts +0 -134
  366. package/src/renderer/fleet-tab-strip.ts +0 -56
  367. package/src/renderer/footer-tips.ts +0 -53
  368. package/src/renderer/fullscreen-primitives.ts +0 -146
  369. package/src/renderer/fullscreen-workspace.ts +0 -194
  370. package/src/renderer/hint-grammar.ts +0 -52
  371. package/src/renderer/modal-factory.ts +0 -480
  372. package/src/renderer/overlay-box.ts +0 -154
  373. package/src/renderer/overlay-viewport.ts +0 -104
  374. package/src/renderer/panel-composite.ts +0 -145
  375. package/src/renderer/panel-workspace-bar.ts +0 -54
  376. package/src/renderer/process-indicator.ts +0 -163
  377. package/src/renderer/tab-strip.ts +0 -222
  378. package/src/renderer/text-layout.ts +0 -31
  379. package/src/renderer/tool-call.ts +0 -276
  380. package/src/renderer/tool-result-expanded-lines.ts +0 -48
  381. package/src/renderer/tool-result-summary.ts +0 -219
  382. package/src/runtime/diagnostics/panels/index.ts +0 -21
  383. package/src/runtime/diagnostics/panels/ops.ts +0 -156
  384. package/src/runtime/perf/panel-contracts.ts +0 -32
  385. package/src/runtime/store/domains/panels.ts +0 -117
  386. /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
  387. /package/src/{panels → views}/modals/modal-theme.ts +0 -0
  388. /package/src/{panels → views}/provider-health-domains.ts +0 -0
@@ -0,0 +1,367 @@
1
+ /**
2
+ * settings-modal-context.ts, the documentation the settings modal shows for
3
+ * its selected row: every setting's key, current and default value, type,
4
+ * source, lock and conflict state, description, possible values (with the
5
+ * per-value meaning for enums), editing notes, and the full feature-unit,
6
+ * MCP-trust, subscription and connection documentation. Split out of
7
+ * settings-modal.ts for the 800-line file cap. Pure text; the renderer wraps
8
+ * and styles it.
9
+ */
10
+
11
+ import type { SettingsModal, SettingEntry, McpEntry, SubscriptionEntry, SettingsCategory } from '../input/settings-modal.ts';
12
+ import { FEATURE_SETTINGS_BY_ID, isFeatureValueEnabled } from '@pellux/goodvibes-terminal-shell';
13
+ import { CATEGORY_INFO, describeUiRouting, formatValue, getSettingLabel, inferSubscriptionRouteReason } from './settings-modal-helpers.ts';
14
+ import { buildConnectionContext } from './settings-modal-connections.ts';
15
+ import { isSecretConfigKey } from '../config/secret-config.ts';
16
+ import { maskConcealedText } from '../input/concealed-input.ts';
17
+ import { CVV_PROMPT_TRADEOFF_WARNING } from '@pellux/goodvibes-sdk/platform/payments';
18
+ import { GLYPHS } from './ui-primitives.ts';
19
+
20
+ const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
21
+ 'display.themeMode': {
22
+ auto: 'Probe the terminal background colour (OSC 11) once at startup and pick light or dark. Falls back to dark on unreadable/unsupported terminals. Only evaluated at startup: selecting auto takes effect next launch.',
23
+ dark: 'Force the dark theme regardless of terminal background. Applies immediately.',
24
+ light: 'Force the light theme regardless of terminal background. Applies immediately.',
25
+ },
26
+ 'behavior.hitlMode': {
27
+ quiet: 'Minimize operational interruptions and surface fewer Human-in-the-Loop prompts.',
28
+ balanced: 'Show important Human-in-the-Loop prompts without turning routine work into noise.',
29
+ operator: 'Surface more operational detail for users actively supervising agents, tools, services, and automation.',
30
+ },
31
+ 'behavior.guidanceMode': {
32
+ off: 'Do not add extra guidance beyond direct command output.',
33
+ minimal: 'Show concise guidance only when it helps avoid mistakes.',
34
+ guided: 'Provide more explanation and next-step context during configuration and operations.',
35
+ },
36
+ 'permissions.mode': {
37
+ prompt: 'Normal: ask before powerful or risky actions according to tool policy.',
38
+ plan: 'Plan mode: read-only planning posture; writes, commands, and network calls are blocked so the model can plan without changing anything. Toggle with /plan or Shift+Tab.',
39
+ 'accept-edits': 'Accept edits: file writes and edits are auto-approved, but exec, network, and escalations are still gated.',
40
+ 'allow-all': 'Auto: allow all actions without prompting. Fast, but removes an important safety gate.',
41
+ custom: 'Use per-tool-class permission settings from the rows below.',
42
+ },
43
+ 'permissions.backgroundAgents': {
44
+ inherit: 'Background and subagent tool calls run through the SAME session permission mode as foreground work.',
45
+ 'allow-all': 'Background and subagent tool calls are exempt from prompting (auto-approved) even when foreground work is gated.',
46
+ },
47
+ 'diagnostics.postEdit': {
48
+ on: 'After the model edits or writes a file, run language diagnostics on it and surface any new problems.',
49
+ off: 'Do not run diagnostics automatically after edits.',
50
+ },
51
+ 'storage.secretPolicy': {
52
+ preferred_secure: 'Use secure secret storage when available, with supported fallback behavior.',
53
+ require_secure: 'Require secure secret storage and reject plaintext fallback.',
54
+ plaintext_allowed: 'Allow plaintext fallback when secure storage is unavailable.',
55
+ },
56
+ 'batch.mode': {
57
+ off: 'Keep daemon work on the immediate local path.',
58
+ explicit: 'Use batch only when callers explicitly request batch execution.',
59
+ 'eligible-by-default': 'Allow eligible daemon work to use the batch path unless callers opt out.',
60
+ },
61
+ 'controlPlane.hostMode': {
62
+ localhost: 'Bind only to this computer.',
63
+ network: 'Bind for LAN access using the default network host.',
64
+ custom: 'Use the explicit host value in the related host setting.',
65
+ },
66
+ 'httpListener.hostMode': {
67
+ localhost: 'Bind only to this computer.',
68
+ network: 'Bind for LAN/webhook access using the default network host.',
69
+ custom: 'Use the explicit host value in the related host setting.',
70
+ },
71
+ 'web.hostMode': {
72
+ localhost: 'Serve the browser UI only on this computer.',
73
+ network: 'Serve the browser UI on the LAN.',
74
+ custom: 'Use the explicit host value in the related host setting.',
75
+ },
76
+ 'ui.systemMessages': {
77
+ panel: 'Kept for older settings files: shows system messages inline in the transcript, same as conversation.',
78
+ conversation: 'Show system messages inline in the transcript.',
79
+ both: 'Shows system messages inline in the transcript, same as conversation.',
80
+ },
81
+ 'ui.operationalMessages': {
82
+ panel: 'Kept for older settings files: shows operational messages inline in the transcript, same as conversation.',
83
+ conversation: 'Show operational messages inline in the transcript.',
84
+ both: 'Shows operational messages inline in the transcript, same as conversation.',
85
+ },
86
+ 'ui.wrfcMessages': {
87
+ panel: 'Kept for older settings files: shows WRFC messages inline in the transcript, same as conversation.',
88
+ conversation: 'Show WRFC messages inline in the transcript.',
89
+ both: 'Shows WRFC messages inline in the transcript, same as conversation.',
90
+ },
91
+ 'surfaces.telegram.mode': {
92
+ webhook: 'Receive Telegram updates through webhook delivery.',
93
+ polling: 'Poll Telegram for updates from the service.',
94
+ },
95
+ 'surfaces.whatsapp.provider': {
96
+ 'meta-cloud': 'Use Meta Cloud API credentials and identifiers.',
97
+ bridge: 'Use a bridge service URL/token flow instead of direct Meta Cloud API delivery.',
98
+ },
99
+ 'payments.cvvHandling': {
100
+ stored: 'Store the CVV through the secret manager so the daemon can complete a purchase unattended.',
101
+ prompt: CVV_PROMPT_TRADEOFF_WARNING,
102
+ },
103
+ };
104
+
105
+ function formatDefaultValue(value: unknown): string {
106
+ if (value === '') return '(empty)';
107
+ if (value === null || value === undefined) return '(unset)';
108
+ return String(value);
109
+ }
110
+
111
+ export function currentSettingValue(modal: SettingsModal, entry: SettingEntry, selected: boolean): string {
112
+ if (selected && modal.editingMode) {
113
+ // Secret-backed keys (surfaces.*.botToken, .signingSecret, etc., see
114
+ // secret-config.ts) must never echo the in-progress plaintext buffer:
115
+ // not in the row, not in the "Current: ..." context line, not in search
116
+ // results. Reuse the composer's concealed-input mask (concealed-input.ts)
117
+ // rather than a second masking implementation, same bullet-per-character
118
+ // shape, so keystrokes still visibly register without revealing content.
119
+ const buffer = isSecretConfigKey(entry.setting.key) ? maskConcealedText(modal.editBuffer) : modal.editBuffer;
120
+ return `${buffer}${GLYPHS.surface.cursor}`;
121
+ }
122
+ return formatValue(entry);
123
+ }
124
+
125
+ function buildSettingContext(modal: SettingsModal, entry: SettingEntry): string[] {
126
+ const lines: string[] = [
127
+ getSettingLabel(entry),
128
+ `Key: ${entry.setting.key}`,
129
+ `Current: ${currentSettingValue(modal, entry, true)}`,
130
+ `Default: ${formatDefaultValue(entry.setting.default)}`,
131
+ `Type: ${entry.setting.type}${entry.setting.enumValues ? ` with ${entry.setting.enumValues.length} possible value(s)` : ''}`,
132
+ `Source: ${entry.effectiveSource ?? 'default'}${entry.sourceLabel ? ` from ${entry.sourceLabel}` : ''}`,
133
+ ];
134
+
135
+ if (entry.locked) lines.push(`Locked: ${entry.lockReason ?? 'This setting is locked by a higher-priority layer.'}`);
136
+ if (entry.conflict) lines.push(`Conflict: resolve with /settings-sync resolve ${entry.setting.key} local|synced.`);
137
+
138
+ // A settings sub-row owned by a feature unit names its feature so "what does this do" is answerable without scrolling back to the header row.
139
+ if (entry.ownerFlagId) {
140
+ const owner = FEATURE_SETTINGS_BY_ID.get(entry.ownerFlagId);
141
+ if (owner) lines.push(`Part of feature: ${owner.name} (the header row above).`);
142
+ }
143
+
144
+ lines.push('', entry.setting.description);
145
+
146
+ if (
147
+ entry.setting.key === 'ui.systemMessages'
148
+ || entry.setting.key === 'ui.operationalMessages'
149
+ || entry.setting.key === 'ui.wrfcMessages'
150
+ ) {
151
+ lines.push(`Routing meaning: ${describeUiRouting(String(entry.currentValue))}.`);
152
+ }
153
+
154
+ if (entry.setting.type === 'boolean') {
155
+ lines.push('');
156
+ lines.push('Possible values:');
157
+ lines.push('true: enabled or allowed for this setting.');
158
+ lines.push('false: disabled or not allowed for this setting.');
159
+ }
160
+
161
+ if (entry.setting.type === 'enum' && entry.setting.enumValues) {
162
+ lines.push('');
163
+ lines.push('Possible values:');
164
+ const descriptions = ENUM_VALUE_DESCRIPTIONS[entry.setting.key] ?? {};
165
+ for (const value of entry.setting.enumValues) {
166
+ lines.push(`${value}: ${descriptions[value] ?? `Use ${value} for this setting.`}`);
167
+ }
168
+ }
169
+
170
+ if (isSecretConfigKey(entry.setting.key)) {
171
+ lines.push('');
172
+ lines.push('Secret handling: raw values entered here are stored through the secret manager and the config receives a goodvibes:// secret reference. Empty input clears the config value.');
173
+ }
174
+
175
+ if (entry.setting.type === 'number') {
176
+ lines.push('');
177
+ lines.push('Editing: Enter opens inline edit, then type the value and press Enter to save. Arrow keys only navigate.');
178
+ }
179
+
180
+ if (entry.setting.type === 'string' && !isSecretConfigKey(entry.setting.key)) {
181
+ lines.push('');
182
+ lines.push('Editing: Enter opens inline edit. Delete the current text to save an empty value when that is valid for the setting.');
183
+ }
184
+
185
+ return lines;
186
+ }
187
+
188
+ /**
189
+ * The option shape of a feature header, rendered from the same schema the
190
+ * write path uses: enum headers list every mode choice (marking the current
191
+ * value and which values keep the feature active), boolean headers state the
192
+ * two positions.
193
+ */
194
+ function buildFeatureOptionLines(entry: SettingEntry): string[] {
195
+ const feature = entry.flag!.feature;
196
+ const setting = entry.setting;
197
+ const lines: string[] = [];
198
+ if (setting.type === 'enum' && setting.enumValues) {
199
+ lines.push('', `Mode choices for ${setting.key}:`);
200
+ const activeValues = feature.enablement.enabledValues ?? [];
201
+ const descriptions = ENUM_VALUE_DESCRIPTIONS[setting.key] ?? {};
202
+ for (const value of setting.enumValues) {
203
+ const marks: string[] = [];
204
+ if (value === String(entry.currentValue)) marks.push('current');
205
+ if (feature.enablement.kind === 'enum') {
206
+ marks.push(activeValues.includes(value) ? 'feature on' : 'feature off');
207
+ }
208
+ const suffix = marks.length > 0 ? ` (${marks.join(', ')})` : '';
209
+ lines.push(`${value}${suffix}: ${descriptions[value] ?? `Use ${value} for this setting.`}`);
210
+ }
211
+ } else if (setting.type === 'boolean') {
212
+ lines.push('');
213
+ lines.push('Possible values:');
214
+ lines.push('true: the feature is enabled.');
215
+ lines.push('false: the feature is disabled.');
216
+ }
217
+ return lines;
218
+ }
219
+
220
+ /**
221
+ * Under-cursor documentation for a feature-unit header, rendered entirely
222
+ * from the SDK's per-feature settings metadata: full behavior description,
223
+ * the real option shape, every settings key that tunes the feature, and the
224
+ * honest live/restart state from the gate manager.
225
+ */
226
+ function buildFlagContext(entry: SettingEntry | null): string[] {
227
+ const flagEntry = entry?.flag ?? null;
228
+ if (!entry || !flagEntry) return ['Features', 'No feature is selected.'];
229
+ const { feature, flag, state, persistedState, pendingRestart } = flagEntry;
230
+ const configOn = isFeatureValueEnabled(feature, entry.currentValue);
231
+ const displayState = state === 'killed' ? 'killed' : configOn ? 'enabled' : 'disabled';
232
+ const lines: string[] = [
233
+ feature.name,
234
+ `Feature: ${feature.id} (${feature.domain} domain)`,
235
+ `Setting: ${feature.enablement.key} = ${formatValue(entry)}`,
236
+ `State: ${displayState}`,
237
+ // A capability the registry declares not operable reads as disabled no
238
+ // matter what its settings key says. Without this line the row shows a
239
+ // value of true beside a state of disabled and explains nothing, the
240
+ // written reason exists in the registry, so render it where the user meets
241
+ // the contradiction rather than leaving it to be discovered.
242
+ ...(feature.operable === false && feature.inoperableDetail
243
+ ? [`Not available in this build: ${feature.inoperableDetail}`]
244
+ : []),
245
+ `Default: ${feature.defaultEnabled ? 'enabled' : 'disabled'}`,
246
+ `Applies: ${feature.restartRequired ? 'on next launch (startup-gated)' : 'immediately'}`,
247
+ ...(pendingRestart
248
+ ? [`Pending restart: saved as ${persistedState}; effective state stays ${state} until the next launch.`]
249
+ : []),
250
+ '',
251
+ feature.description,
252
+ ];
253
+
254
+ lines.push(...buildFeatureOptionLines(entry));
255
+
256
+ lines.push('');
257
+ if (feature.enablement.kind === 'enum') {
258
+ lines.push(`How it turns on: active while ${feature.enablement.key} is ${(feature.enablement.enabledValues ?? []).join(' or ')}.`);
259
+ } else if (feature.enablement.kind === 'constant' && entry.setting.type !== 'boolean') {
260
+ lines.push('How it turns on: always active; the settings listed below tune its behavior directly.');
261
+ } else {
262
+ lines.push(`How it turns on: ${feature.enablement.key} set to true.`);
263
+ }
264
+
265
+ if (feature.settings.length > 1) {
266
+ lines.push('', 'Settings in this feature:');
267
+ for (const key of feature.settings) {
268
+ lines.push(key === feature.enablement.key ? `${key} (this row)` : key);
269
+ }
270
+ }
271
+
272
+ if (state === 'killed' && flag.killReason) {
273
+ lines.push('', `Kill reason: ${flag.killReason}`);
274
+ }
275
+ return lines;
276
+ }
277
+
278
+ function buildMcpContext(modal: SettingsModal, entry: McpEntry | null): string[] {
279
+ if (!entry) return ['MCP trust', 'No MCP server is selected.'];
280
+ const scope = entry.allowedPaths.length > 0
281
+ ? `Allowed paths: ${entry.allowedPaths.join(', ')}`
282
+ : entry.allowedHosts.length > 0
283
+ ? `Allowed hosts: ${entry.allowedHosts.join(', ')}`
284
+ : 'No explicit path or host scope is configured.';
285
+ const confirmation = modal.mcpAllowAllConfirmationTarget === entry.name
286
+ ? `Confirmation required: type ALLOW ALL ${entry.name} to grant unrestricted trust.`
287
+ : 'Enter edits the trust mode. Valid values are constrained, ask-on-risk, allow-all, and blocked.';
288
+ return [
289
+ entry.name,
290
+ `Connection: ${entry.connected ? 'connected' : 'disconnected'}`,
291
+ `Role: ${entry.role}`,
292
+ `Trust mode: ${entry.trustMode}`,
293
+ confirmation,
294
+ '',
295
+ scope,
296
+ '',
297
+ 'Trust meanings:',
298
+ 'constrained: keep MCP activity inside declared paths/hosts and prompt on risk.',
299
+ 'ask-on-risk: allow routine MCP operations but ask before risky behavior.',
300
+ 'allow-all: allow unrestricted MCP operations for this server after explicit confirmation.',
301
+ 'blocked: prevent this MCP server from being used.',
302
+ ];
303
+ }
304
+
305
+ function buildSubscriptionContext(modal: SettingsModal, entry: SubscriptionEntry | null): string[] {
306
+ if (!entry) return ['Subscriptions', 'No subscription provider is selected.'];
307
+ const expires = entry.expiresAt ? new Date(entry.expiresAt).toISOString() : 'not reported';
308
+ const routeReason = inferSubscriptionRouteReason(entry);
309
+ const logout = entry.state === 'active' || entry.state === 'pending'
310
+ ? modal.subscriptionLogoutConfirmationTarget === entry.provider
311
+ ? `Sign out ${entry.provider}? Enter/y to confirm, n/Esc to cancel.`
312
+ : 'Press Enter to begin sign-out for this provider session.'
313
+ : `Use /subscription login ${entry.provider} start to begin OAuth sign-in for this provider.`;
314
+ return [
315
+ entry.provider,
316
+ `State: ${entry.state}`,
317
+ ...(routeReason ? [routeReason] : []),
318
+ logout,
319
+ `Active route: ${entry.activeRoute ?? 'n/a'}`,
320
+ `Preferred route: ${entry.preferredRoute ?? 'n/a'}`,
321
+ `OAuth configured: ${entry.oauthConfigured ? 'yes' : 'no'}`,
322
+ `Freshness: ${entry.authFreshness ?? 'n/a'}`,
323
+ `Expires: ${expires}`,
324
+ ...((entry.issues ?? []).length > 0 ? ['', 'Issues:', ...(entry.issues ?? [])] : []),
325
+ ...((entry.nextActions ?? []).length > 0 ? ['', 'Next actions:', ...(entry.nextActions ?? [])] : []),
326
+ ];
327
+ }
328
+
329
+ /**
330
+ * The documentation for whatever the settings list has selected, one entry
331
+ * per line (unwrapped; '' separates paragraphs). The first line names the
332
+ * selection; the renderer shows it under the selected row, wrapped in full.
333
+ */
334
+ export function settingContextLines(modal: SettingsModal): string[] {
335
+ const category = modal.currentCategory;
336
+ if (modal.searchFocused) {
337
+ const selected = modal.getSelected();
338
+ if (selected) return buildSettingContext(modal, selected);
339
+ return [
340
+ modal.searchQuery.trim().length === 0
341
+ ? 'Type a query to search across all settings categories.'
342
+ : 'No settings matched the search query.',
343
+ ];
344
+ }
345
+ const lines: string[] = [];
346
+ if (category === 'mcp') lines.push(...buildMcpContext(modal, modal.getSelectedMcp()));
347
+ else if (category === 'subscriptions') lines.push(...buildSubscriptionContext(modal, modal.getSelectedSubscription()));
348
+ else if (category === 'connections') lines.push(...buildConnectionContext(modal));
349
+ else {
350
+ const selected = modal.getSelected();
351
+ // A feature-unit header shows the feature's documentation (full
352
+ // description, option shape, settings list, live/restart state); its
353
+ // settings sub-rows and plain settings show the setting context.
354
+ if (selected?.flag) lines.push(...buildFlagContext(selected));
355
+ else if (selected) lines.push(...buildSettingContext(modal, selected));
356
+ else lines.push('No setting is selected in this category.');
357
+ }
358
+ lines.push('', `Category purpose: ${CATEGORY_INFO[category]}`);
359
+ return lines;
360
+ }
361
+
362
+ export function categoryItemCount(modal: SettingsModal, category: SettingsCategory): number {
363
+ if (category === 'mcp') return modal.mcpEntries.length;
364
+ if (category === 'subscriptions') return modal.subscriptionEntries.length;
365
+ if (category === 'connections') return modal.connectionEntries.length;
366
+ return modal.groups.get(category)?.length ?? 0;
367
+ }
@@ -7,13 +7,7 @@
7
7
  import type { SettingEntry, McpEntry, SubscriptionEntry, SettingsCategory } from '../input/settings-modal-types.ts';
8
8
  import { SETTINGS_CATEGORIES } from '../input/settings-modal-types.ts';
9
9
  import { isSecretConfigKey, isSecretReferenceValue } from '../config/secret-config.ts';
10
- import { UI_TONES } from './ui-primitives.ts';
11
-
12
- /**
13
- * "Modified / active" accent for settings rows, cyan-green, no UI_TONES
14
- * role matches it (preserved byte-exact as a named constant).
15
- */
16
- const SETTINGS_ACCENT = '#00ffcc';
10
+ import { activeTokens } from './theme.ts';
17
11
 
18
12
  function maskSecretValue(value: string): string {
19
13
  if (value.length === 0) return '(empty)';
@@ -43,8 +37,9 @@ export function formatValue(entry: SettingEntry): string {
43
37
  }
44
38
 
45
39
  export function valueColor(entry: SettingEntry): string {
46
- if (!entry.isDefault) return SETTINGS_ACCENT; // cyan-green = modified
47
- return '244'; // dim = default
40
+ // Modified values use the theme accent; defaults read muted.
41
+ if (!entry.isDefault) return activeTokens().accent;
42
+ return activeTokens().textMuted;
48
43
  }
49
44
 
50
45
 
@@ -268,11 +263,11 @@ export function getSettingLabel(entry: SettingEntry): string {
268
263
  export function describeUiRouting(value: string): string {
269
264
  switch (value) {
270
265
  case 'panel':
271
- return 'render in panels only';
266
+ return 'render inline in conversation (older setting value)';
272
267
  case 'conversation':
273
268
  return 'render inline in conversation';
274
269
  case 'both':
275
- return 'render in both conversation and panels';
270
+ return 'render inline in conversation';
276
271
  default:
277
272
  return value;
278
273
  }