@pellux/goodvibes-tui 2.0.20 → 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.
- package/CHANGELOG.md +70 -0
- package/README.md +16 -16
- package/docs/README.md +4 -4
- package/docs/foundation-artifacts/operator-contract.json +59 -4
- package/package.json +16 -6
- package/src/cli/management.ts +5 -2
- package/src/cli/tui-startup.ts +34 -39
- package/src/core/agent-view-render.ts +157 -0
- package/src/core/approval-alert.ts +49 -11
- package/src/core/bookmark-navigation.ts +7 -1
- package/src/core/budget-breach-notifier.ts +27 -8
- package/src/core/compaction-receipt.ts +1 -1
- package/src/core/context-usage.ts +1 -1
- package/src/core/conversation-compaction-render.ts +3 -3
- package/src/core/conversation-display-only.ts +86 -0
- package/src/core/conversation-event-navigation.ts +27 -0
- package/src/core/conversation-line-cache.ts +216 -447
- package/src/core/conversation-render-context.ts +20 -27
- package/src/core/conversation-rendering.ts +157 -575
- package/src/core/conversation-splash-state.ts +6 -1
- package/src/core/conversation-types.ts +35 -0
- package/src/core/conversation-usage.ts +12 -0
- package/src/core/conversation.ts +130 -131
- package/src/core/long-task-notifier.ts +100 -31
- package/src/core/notices.ts +75 -0
- package/src/core/pairing-tailscale-gateway.ts +1 -1
- package/src/core/process-output-log.ts +143 -0
- package/src/core/rewind-receipt.ts +1 -1
- package/src/core/session-focus.ts +190 -0
- package/src/core/session-resume-core.ts +23 -81
- package/src/core/stream-event-wiring.ts +31 -5
- package/src/core/system-message-noise.ts +2 -2
- package/src/core/system-message-router.ts +16 -18
- package/src/core/turn-event-wiring.ts +272 -33
- package/src/core/work-tree-focus.ts +290 -0
- package/src/core/work-tree-fold-store.ts +143 -0
- package/src/core/work-tree-model.ts +799 -0
- package/src/core/work-tree-render.ts +384 -0
- package/src/core/work-tree-sources.ts +184 -0
- package/src/core/work-tree-wiring.ts +176 -0
- package/src/core/workstream-notification.ts +36 -6
- package/src/core/wrfc-notice-titles.ts +37 -0
- package/src/input/agents-modal-text.ts +119 -0
- package/src/input/agents-modal.ts +699 -0
- package/src/input/bookmark-modal.ts +33 -9
- package/src/input/changes-git.ts +251 -0
- package/src/input/changes-modal.ts +629 -0
- package/src/input/changes-model.ts +125 -0
- package/src/input/command-palette-types.ts +41 -0
- package/src/input/command-palette.ts +272 -0
- package/src/input/command-registry.ts +77 -35
- package/src/input/commands/acp-runtime.ts +19 -9
- package/src/input/commands/channel-runtime.ts +2 -2
- package/src/input/commands/ci-runtime.ts +1 -1
- package/src/input/commands/codebase-runtime.ts +1 -1
- package/src/input/commands/config.ts +7 -1
- package/src/input/commands/context-window.ts +25 -19
- package/src/input/commands/control-room-runtime.ts +18 -18
- package/src/input/commands/conversation-runtime.ts +0 -1
- package/src/input/commands/cost-runtime.ts +29 -20
- package/src/input/commands/diff-runtime.ts +35 -181
- package/src/input/commands/eval.ts +1 -1
- package/src/input/commands/experience-runtime.ts +3 -7
- package/src/input/commands/fresh-conversation.ts +86 -0
- package/src/input/commands/git-runtime.ts +5 -22
- package/src/input/commands/graph-runtime.ts +1 -1
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-runtime.ts +8 -9
- package/src/input/commands/hooks-runtime.ts +2 -2
- package/src/input/commands/hosted-runtime.ts +3 -3
- package/src/input/commands/incident-runtime.ts +3 -3
- package/src/input/commands/intelligence-runtime.ts +6 -9
- package/src/input/commands/knowledge.ts +2 -2
- package/src/input/commands/legacy-panel-command.ts +57 -0
- package/src/input/commands/local-auth-runtime.ts +8 -9
- package/src/input/commands/local-provider-runtime.ts +7 -4
- package/src/input/commands/local-runtime.ts +12 -15
- package/src/input/commands/local-setup-review.ts +1 -1
- package/src/input/commands/local-setup.ts +13 -19
- package/src/input/commands/memory.ts +1 -1
- package/src/input/commands/notify-runtime.ts +9 -0
- package/src/input/commands/operator-runtime.ts +10 -12
- package/src/input/commands/permissions-provenance.ts +3 -3
- package/src/input/commands/planning-runtime.ts +7 -7
- package/src/input/commands/platform-sandbox-runtime.ts +2 -2
- package/src/input/commands/platform-services-runtime.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +2 -2
- package/src/input/commands/policy.ts +3 -3
- package/src/input/commands/provider.ts +1 -1
- package/src/input/commands/remote-runtime.ts +1 -1
- package/src/input/commands/review-runtime.ts +39 -94
- package/src/input/commands/rewind-runtime.ts +81 -108
- package/src/input/commands/runtime-services.ts +15 -17
- package/src/input/commands/services-runtime.ts +2 -2
- package/src/input/commands/session-content.ts +21 -5
- package/src/input/commands/session-workflow.ts +13 -38
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/shell-core.ts +19 -4
- package/src/input/commands/skills-runtime.ts +2 -2
- package/src/input/commands/status-runtime.ts +13 -0
- package/src/input/commands/subscription-runtime.ts +1 -1
- package/src/input/commands/tasks-runtime.ts +2 -8
- package/src/input/commands/work-plan-runtime.ts +4 -4
- package/src/input/commands/workstream-attempts.ts +24 -47
- package/src/input/commands/workstream-runtime.ts +2 -2
- package/src/input/commands/worktree-runtime.ts +3 -3
- package/src/input/commands.ts +3 -1
- package/src/input/composer-editor.ts +44 -0
- package/src/input/concealed-input.ts +1 -1
- package/src/input/config-modal-types.ts +20 -8
- package/src/input/config-modal.ts +106 -105
- package/src/input/confirm-dialog-types.ts +28 -0
- package/src/input/confirm-dialog.ts +70 -0
- package/src/input/delete-key-policy.ts +3 -3
- package/src/input/feed-context-factory.ts +15 -16
- package/src/input/handler-command-route.ts +7 -42
- package/src/input/handler-content-actions.ts +16 -15
- package/src/input/handler-feed-routes.ts +26 -211
- package/src/input/handler-feed.ts +68 -95
- package/src/input/handler-interactions.ts +5 -3
- package/src/input/handler-modal-routes.ts +215 -216
- package/src/input/handler-modal-stack.ts +81 -11
- package/src/input/handler-modal-token-routes.ts +4 -0
- package/src/input/handler-onboarding.ts +0 -1
- package/src/input/handler-picker-routes.ts +65 -107
- package/src/input/handler-session-view-route.ts +149 -0
- package/src/input/handler-shortcuts.ts +16 -154
- package/src/input/handler-types.ts +4 -2
- package/src/input/handler-ui-state.ts +45 -15
- package/src/input/handler-work-tree-route.ts +123 -0
- package/src/input/handler.ts +25 -70
- package/src/input/keybindings.ts +16 -71
- package/src/input/masked-entry-modal.ts +117 -0
- package/src/input/mcp-workspace.ts +48 -17
- package/src/input/model-picker-filter.ts +8 -0
- package/src/input/model-picker-open.ts +99 -0
- package/src/input/model-picker-types.ts +1 -1
- package/src/input/model-picker.ts +92 -9
- package/src/input/notifications-modal.ts +123 -0
- package/src/input/overlay-filter.ts +26 -0
- package/src/input/profile-picker-modal.ts +37 -8
- package/src/input/search.ts +3 -3
- package/src/input/selection-modal-queue.ts +2 -0
- package/src/input/selection-modal.ts +28 -16
- package/src/input/session-picker-modal.ts +33 -8
- package/src/input/settings-modal-activation.ts +7 -2
- package/src/input/settings-modal-data.ts +11 -6
- package/src/input/settings-modal-types.ts +1 -1
- package/src/input/settings-modal.ts +20 -20
- package/src/input/submission-intent.ts +1 -1
- package/src/input/submission-router.ts +4 -9
- package/src/input/surface-modal-host.ts +110 -0
- package/src/input/theme-settings-actions.ts +82 -0
- package/src/input/usage-modal.ts +183 -0
- package/src/input/views.ts +97 -0
- package/src/main.ts +175 -165
- package/src/permissions/hunk-selection.ts +1 -1
- package/src/permissions/prompt-card.ts +511 -0
- package/src/permissions/prompt.ts +59 -622
- package/src/renderer/agents-modal.ts +310 -0
- package/src/renderer/autocomplete-overlay.ts +42 -220
- package/src/renderer/back-to-bottom.ts +80 -0
- package/src/renderer/block-actions-overlay.ts +30 -48
- package/src/renderer/bookmark-modal.ts +48 -79
- package/src/renderer/changes-modal.ts +325 -0
- package/src/renderer/code-block.ts +184 -106
- package/src/renderer/command-palette.ts +93 -0
- package/src/renderer/composer-fragments.ts +4 -4
- package/src/renderer/composer.ts +146 -0
- package/src/renderer/compositor.ts +26 -160
- package/src/renderer/config-modal.ts +185 -81
- package/src/renderer/confirm-dialog.ts +50 -0
- package/src/renderer/context-inspector.ts +116 -154
- package/src/renderer/context-status-hint.ts +4 -4
- package/src/renderer/conversation-layout.ts +20 -0
- package/src/renderer/conversation-overlays.ts +94 -84
- package/src/renderer/conversation-surface.ts +19 -38
- package/src/renderer/diff-tint.ts +98 -0
- package/src/renderer/file-picker-overlay.ts +63 -90
- package/src/renderer/footer-targets.ts +38 -0
- package/src/renderer/git-status.ts +3 -4
- package/src/renderer/header-line.ts +140 -117
- package/src/renderer/help-overlay.ts +133 -219
- package/src/renderer/history-search-overlay.ts +15 -12
- package/src/renderer/lane-graph/bead.ts +800 -0
- package/src/renderer/lane-graph/glyphs.ts +134 -0
- package/src/renderer/lane-graph/layout.ts +248 -0
- package/src/renderer/lane-graph/paint.ts +537 -0
- package/src/renderer/lane-graph/semantic-memo.ts +77 -0
- package/src/renderer/layout-engine.ts +2 -57
- package/src/renderer/layout.ts +7 -13
- package/src/renderer/markdown-inline.ts +2 -1
- package/src/renderer/markdown-table.ts +17 -12
- package/src/renderer/markdown.ts +92 -34
- package/src/renderer/masked-entry-modal.ts +78 -0
- package/src/renderer/mcp-workspace.ts +166 -203
- package/src/renderer/model-workspace.ts +381 -436
- package/src/renderer/notifications-modal.ts +116 -0
- package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
- package/src/renderer/process-view.ts +192 -0
- package/src/renderer/profile-picker-modal.ts +58 -110
- package/src/renderer/search-overlay.ts +6 -3
- package/src/renderer/selection-modal-overlay.ts +87 -327
- package/src/renderer/semantic-diff.ts +2 -2
- package/src/renderer/session-chips.ts +102 -0
- package/src/renderer/session-picker-modal.ts +177 -297
- package/src/renderer/settings-modal-connections.ts +14 -23
- package/src/renderer/settings-modal-context.ts +367 -0
- package/src/renderer/settings-modal-helpers.ts +6 -11
- package/src/renderer/settings-modal.ts +322 -726
- package/src/renderer/shell-surface.ts +277 -175
- package/src/renderer/shortcuts-overlay.ts +217 -0
- package/src/renderer/status-line.ts +475 -0
- package/src/renderer/surface-compose.ts +174 -0
- package/src/renderer/surface-kit-extra.ts +303 -0
- package/src/renderer/surface-kit-list.ts +366 -0
- package/src/renderer/surface-kit-parts.ts +360 -0
- package/src/renderer/surface-kit.ts +568 -0
- package/src/renderer/syntax-highlighter.ts +280 -197
- package/src/renderer/syntax-theme.ts +51 -0
- package/src/renderer/system-message.ts +0 -1
- package/src/renderer/term-caps.ts +42 -1
- package/src/renderer/terminal-bg-probe.ts +116 -19
- package/src/renderer/terminal-palette-probe.ts +322 -0
- package/src/renderer/terminal-palette-reader.ts +183 -0
- package/src/renderer/terminal-palette.ts +58 -0
- package/src/renderer/theme-mode-config.ts +16 -1
- package/src/renderer/theme.ts +234 -207
- package/src/renderer/thinking.ts +0 -1
- package/src/renderer/throbber.ts +188 -0
- package/src/renderer/toast-center.ts +119 -0
- package/src/renderer/ui-factory.ts +39 -602
- package/src/renderer/ui-primitives.ts +8 -25
- package/src/renderer/usage-modal.ts +353 -0
- package/src/renderer/user-message.ts +58 -0
- package/src/renderer/voice-capture-chip.ts +53 -0
- package/src/runtime/bootstrap-command-context.ts +0 -5
- package/src/runtime/bootstrap-command-parts.ts +38 -89
- package/src/runtime/bootstrap-core.ts +13 -15
- package/src/runtime/bootstrap-hook-bridge.ts +12 -21
- package/src/runtime/bootstrap-notifier-sync.ts +17 -1
- package/src/runtime/bootstrap-shell.ts +16 -50
- package/src/runtime/bootstrap.ts +14 -14
- package/src/runtime/client/fleet-union.ts +5 -5
- package/src/runtime/client/hosted-exit.ts +2 -2
- package/src/runtime/client/hosted-sessions.ts +1 -1
- package/src/runtime/client/spine-adoption.ts +1 -1
- package/src/runtime/context-accounting-source.ts +5 -4
- package/src/runtime/index.ts +1 -0
- package/src/runtime/notification-dispatch.ts +102 -29
- package/src/runtime/recovery-offer-wiring.ts +4 -1
- package/src/runtime/recovery-prompt.ts +31 -15
- package/src/runtime/runtime-services-types.ts +10 -6
- package/src/runtime/services.ts +17 -12
- package/src/runtime/session-continuity-hints.ts +2 -5
- package/src/runtime/session-inbound-inputs.ts +1 -1
- package/src/runtime/session-resume-liveness-confirm.ts +14 -2
- package/src/runtime/startup-typeahead-gate.ts +103 -0
- package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
- package/src/runtime/store/domains/index.ts +0 -8
- package/src/runtime/store/selectors/index.ts +0 -28
- package/src/runtime/store/state.ts +0 -8
- package/src/runtime/ui-services.ts +4 -6
- package/src/runtime/usage-tracker.ts +348 -0
- package/src/runtime/wrfc-persistence.ts +4 -4
- package/src/shell/blocking-input.ts +92 -2
- package/src/shell/recovery-input-helpers.ts +1 -1
- package/src/shell/session-views.ts +539 -0
- package/src/shell/status-report.ts +86 -0
- package/src/shell/transcript-scroll.ts +68 -0
- package/src/shell/ui-openers.ts +84 -172
- package/src/shell/view-openers.ts +205 -0
- package/src/tools/wrfc-agent-guard.ts +22 -2
- package/src/utils/format-duration.ts +4 -8
- package/src/utils/splash-lines.ts +9 -1
- package/src/utils/terminal-width.ts +56 -0
- package/src/verification/verification-ledger.ts +18 -16
- package/src/{panels → views}/agent-inspector-shared.ts +2 -2
- package/src/{panels → views}/builtin-modals.ts +22 -21
- package/src/views/builtin-views.ts +135 -0
- package/src/{panels → views}/confirm-state.ts +9 -9
- package/src/{panels → views}/diff-review-model.ts +10 -3
- package/src/{panels → views}/eval-registry.ts +1 -1
- package/src/{panels → views}/fleet-acts.ts +49 -85
- package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
- package/src/{panels → views}/fleet-gateway.ts +5 -5
- package/src/{panels → views}/fleet-observed-render.ts +16 -16
- package/src/{panels → views}/fleet-read-model.ts +9 -9
- package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
- package/src/{panels → views}/fleet-spawn.ts +33 -49
- package/src/{panels → views}/fleet-steer.ts +12 -12
- package/src/{panels → views}/fleet-stop.ts +4 -4
- package/src/{panels → views}/fleet-transcript.ts +26 -27
- package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
- package/src/{panels → views}/hosted-session-feed.ts +6 -6
- package/src/views/modal-surface-registry.ts +41 -0
- package/src/{panels → views}/modals/devices-modal.ts +2 -2
- package/src/{panels → views}/modals/hooks-modal.ts +13 -13
- package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
- package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
- package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
- package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
- package/src/{panels → views}/modals/memory-modal.ts +8 -8
- package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
- package/src/{panels → views}/modals/pairing-modal.ts +9 -9
- package/src/{panels → views}/modals/planning-modal.ts +15 -20
- package/src/{panels → views}/modals/plugins-modal.ts +6 -6
- package/src/{panels → views}/modals/policy-modal.ts +13 -5
- package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
- package/src/{panels → views}/modals/remote-modal.ts +3 -3
- package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
- package/src/{panels → views}/modals/security-modal.ts +22 -16
- package/src/{panels → views}/modals/services-modal.ts +3 -3
- package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
- package/src/{panels → views}/modals/skills-modal.ts +9 -9
- package/src/{panels → views}/modals/subscription-modal.ts +3 -3
- package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
- package/src/views/notifications-feed.ts +314 -0
- package/src/{panels → views}/polish-core.ts +38 -36
- package/src/{panels → views}/polish-tables.ts +35 -26
- package/src/{panels → views}/polish.ts +101 -95
- package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
- package/src/{panels → views}/provider-health-routes.ts +14 -14
- package/src/{panels → views}/search-focus.ts +8 -8
- package/src/{panels → views}/session-maintenance.ts +11 -11
- package/src/views/skills-discovery.ts +159 -0
- package/src/views/view-deps.ts +80 -0
- package/src/views/view-panel-adapter.ts +53 -0
- package/src/{panels → views}/workstream-graph-render.ts +1 -1
- package/src/core/conversation-fold.ts +0 -101
- package/src/core/conversation-turn-structure.ts +0 -464
- package/src/core/conversation-user-receipts.ts +0 -42
- package/src/input/commands/operator-panel-runtime.ts +0 -186
- package/src/input/panel-integration-actions.ts +0 -33
- package/src/input/panel-mouse-geometry.ts +0 -97
- package/src/input/panel-paste-flood-guard.ts +0 -86
- package/src/panels/base-panel.ts +0 -301
- package/src/panels/builtin/agent.ts +0 -27
- package/src/panels/builtin/development.ts +0 -92
- package/src/panels/builtin/knowledge.ts +0 -12
- package/src/panels/builtin/operations.ts +0 -177
- package/src/panels/builtin/session.ts +0 -81
- package/src/panels/builtin/shared.ts +0 -357
- package/src/panels/builtin-panels.ts +0 -28
- package/src/panels/cost-tracker-panel.ts +0 -746
- package/src/panels/diff-panel.ts +0 -797
- package/src/panels/diff-review-panel.ts +0 -395
- package/src/panels/expandable-list-panel.ts +0 -189
- package/src/panels/fleet-deep-link.ts +0 -31
- package/src/panels/fleet-panel.ts +0 -799
- package/src/panels/git-panel.ts +0 -800
- package/src/panels/hosted-session-panel.ts +0 -221
- package/src/panels/index.ts +0 -21
- package/src/panels/local-auth-panel.ts +0 -478
- package/src/panels/notifications-feed.ts +0 -127
- package/src/panels/notifications-panel.ts +0 -160
- package/src/panels/panel-confirm-overlay.ts +0 -72
- package/src/panels/panel-manager.ts +0 -791
- package/src/panels/plugins-panel.ts +0 -371
- package/src/panels/scrollable-list-panel.ts +0 -498
- package/src/panels/skills-panel.ts +0 -454
- package/src/panels/token-budget-panel.ts +0 -688
- package/src/panels/types.ts +0 -191
- package/src/panels/wrfc-panel-format.ts +0 -133
- package/src/renderer/diff-view.ts +0 -134
- package/src/renderer/fleet-tab-strip.ts +0 -56
- package/src/renderer/footer-tips.ts +0 -53
- package/src/renderer/fullscreen-primitives.ts +0 -146
- package/src/renderer/fullscreen-workspace.ts +0 -194
- package/src/renderer/hint-grammar.ts +0 -52
- package/src/renderer/modal-factory.ts +0 -480
- package/src/renderer/overlay-box.ts +0 -154
- package/src/renderer/overlay-viewport.ts +0 -104
- package/src/renderer/panel-composite.ts +0 -145
- package/src/renderer/panel-workspace-bar.ts +0 -54
- package/src/renderer/process-indicator.ts +0 -163
- package/src/renderer/tab-strip.ts +0 -222
- package/src/renderer/text-layout.ts +0 -31
- package/src/renderer/tool-call.ts +0 -276
- package/src/renderer/tool-result-expanded-lines.ts +0 -48
- package/src/renderer/tool-result-summary.ts +0 -219
- package/src/runtime/diagnostics/panels/index.ts +0 -21
- package/src/runtime/diagnostics/panels/ops.ts +0 -156
- package/src/runtime/perf/panel-contracts.ts +0 -32
- package/src/runtime/store/domains/panels.ts +0 -117
- /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
- /package/src/{panels → views}/modals/modal-theme.ts +0 -0
- /package/src/{panels → views}/provider-health-domains.ts +0 -0
package/src/renderer/theme.ts
CHANGED
|
@@ -1,41 +1,65 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* theme.ts,
|
|
2
|
+
* theme.ts, the TUI's theme runtime.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Every colour the TUI paints comes from ONE resolved token table: the active
|
|
5
|
+
* theme (config `display.theme`) resolved for the active mode (config
|
|
6
|
+
* `display.themeMode`, or the terminal-background probe under `auto`). The
|
|
7
|
+
* theme data itself (bundled themes, the `system` theme generated from the
|
|
8
|
+
* terminal palette, the resolver and its derived fallbacks) lives in the SDK
|
|
9
|
+
* presentation contract; this module only holds the session state and the
|
|
10
|
+
* read paths the renderer uses:
|
|
7
11
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* terminal whose background is unknown.
|
|
12
|
+
* activeTokens() the full resolved table (SDK ThemeTokens shape)
|
|
13
|
+
* activeTheme() transcript tokens (markdown / conversation rendering)
|
|
14
|
+
* activeUiTones() chrome tokens in the legacy TONE_TOKENS shape
|
|
15
|
+
* activeDiffTones() diff add/del/hunk in the legacy DIFF_TONES shape
|
|
13
16
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
+
* Theme names: every bundled theme, 'system', and the legacy 'vaporwave'
|
|
18
|
+
* (an alias of 'goodvibes-neon', the pre-2026-09 look). Unknown names fall
|
|
19
|
+
* back to the default theme. 'system' falls back to the default theme until a
|
|
20
|
+
* terminal palette has been read (and stays there when the terminal answered
|
|
21
|
+
* nothing).
|
|
17
22
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* DEFAULT_OVERLAY_PALETTE all read through ONE mode-resolved path instead of
|
|
23
|
-
* importing the static UI_TONES constant directly, so one mode flip reaches
|
|
24
|
-
* every one of them.
|
|
23
|
+
* IMPORTANT: inline code has NO background token. Differentiate inline code
|
|
24
|
+
* via inlineCodeFg + bold only; the background inherits the terminal.
|
|
25
|
+
*
|
|
26
|
+
* The protected splash gradient does NOT come from here; see splash-lines.ts.
|
|
25
27
|
*/
|
|
26
28
|
|
|
27
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
DEFAULT_THEME_NAME,
|
|
31
|
+
SYSTEM_THEME_NAME,
|
|
32
|
+
generateSystemTheme,
|
|
33
|
+
getBundledTheme,
|
|
34
|
+
listBundledThemes,
|
|
35
|
+
resolveTheme as resolveThemeFile,
|
|
36
|
+
themeToDiffTones,
|
|
37
|
+
themeToTones,
|
|
38
|
+
type DiffToneTokens,
|
|
39
|
+
type ThemeTokens as PaletteTokens,
|
|
40
|
+
type ToneTokens,
|
|
41
|
+
} from '@pellux/goodvibes-sdk/platform/presentation';
|
|
42
|
+
import { getTerminalPalette, type TerminalPalette } from './terminal-palette.ts';
|
|
43
|
+
|
|
44
|
+
export type { PaletteTokens, DiffToneTokens };
|
|
28
45
|
|
|
29
46
|
/** Background mode, dark is the safe default for an unprobed terminal. */
|
|
30
47
|
export type ThemeMode = 'dark' | 'light';
|
|
31
48
|
|
|
32
|
-
/**
|
|
49
|
+
/** User-facing appearance preference: auto probes the terminal; dark/light force. */
|
|
50
|
+
export type ThemeModeSetting = 'auto' | 'dark' | 'light';
|
|
51
|
+
|
|
52
|
+
/** Legacy config value kept working: the old name of goodvibes-neon. */
|
|
53
|
+
const LEGACY_VAPORWAVE_THEME_NAME = 'vaporwave';
|
|
54
|
+
const NEON_THEME_NAME = 'goodvibes-neon';
|
|
55
|
+
|
|
56
|
+
/** Transcript tokens (markdown / conversation rendering), one mode. */
|
|
33
57
|
export interface ThemeTokens {
|
|
34
58
|
/** H1 heading foreground + table header accent */
|
|
35
59
|
heading1: string;
|
|
36
60
|
/** H2 heading foreground */
|
|
37
61
|
heading2: string;
|
|
38
|
-
/** H3 heading foreground
|
|
62
|
+
/** H3 heading foreground */
|
|
39
63
|
heading3: string;
|
|
40
64
|
/** Inline code foreground (bold is applied separately by caller) */
|
|
41
65
|
inlineCodeFg: string;
|
|
@@ -51,7 +75,7 @@ export interface ThemeTokens {
|
|
|
51
75
|
searchCurrentFg: string;
|
|
52
76
|
/** Strikethrough / muted text foreground */
|
|
53
77
|
strikethrough: string;
|
|
54
|
-
/** Blockquote
|
|
78
|
+
/** Blockquote text foreground */
|
|
55
79
|
blockquote: string;
|
|
56
80
|
/** Assistant event-line marker + label accent */
|
|
57
81
|
assistantHeader: string;
|
|
@@ -61,7 +85,7 @@ export interface ThemeTokens {
|
|
|
61
85
|
toolAccent: string;
|
|
62
86
|
/** Collapsed-fragment body background (tool result preview bg) */
|
|
63
87
|
collapsedBodyBg: string;
|
|
64
|
-
/** Checked task-list checkbox foreground
|
|
88
|
+
/** Checked task-list checkbox foreground */
|
|
65
89
|
checkboxChecked: string;
|
|
66
90
|
/** Error / cancelled message bar background */
|
|
67
91
|
errorBarBg: string;
|
|
@@ -73,232 +97,235 @@ export interface ThemeTokens {
|
|
|
73
97
|
diffAccent: string;
|
|
74
98
|
}
|
|
75
99
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
searchMatchBg: '#806600',
|
|
86
|
-
searchMatchFg: '#ffffff',
|
|
87
|
-
searchCurrentBg: '#ffff00',
|
|
88
|
-
searchCurrentFg: '#000000',
|
|
89
|
-
strikethrough: '244',
|
|
90
|
-
blockquote: '244',
|
|
91
|
-
assistantHeader: UI_TONES.accent.control,
|
|
92
|
-
reasoningAccent: UI_TONES.state.reasoning,
|
|
93
|
-
toolAccent: UI_TONES.state.info,
|
|
94
|
-
collapsedBodyBg: '#1a1a1a',
|
|
95
|
-
checkboxChecked: '#22c55e',
|
|
96
|
-
errorBarBg: '#3a1a1a',
|
|
97
|
-
modelNameDim: '#94a3b8',
|
|
98
|
-
toolNameFg: '#e2e8f0',
|
|
99
|
-
diffAccent: '#f59e0b',
|
|
100
|
-
};
|
|
100
|
+
/** Chrome tokens in the legacy TONE_TOKENS shape. */
|
|
101
|
+
export type UiToneTokens = ToneTokens;
|
|
102
|
+
|
|
103
|
+
/** One row of the theme picker: 'system' plus every bundled theme. */
|
|
104
|
+
export interface ThemeChoice {
|
|
105
|
+
readonly name: string;
|
|
106
|
+
readonly label: string;
|
|
107
|
+
readonly variants: readonly ThemeMode[];
|
|
108
|
+
}
|
|
101
109
|
|
|
102
110
|
// ---------------------------------------------------------------------------
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
// Rationale per token:
|
|
106
|
-
// heading1/2: Deep teal (#0077aa), readable on white/cream terminals
|
|
107
|
-
// heading3: ANSI-256 #244 equivalent on light bg → use 24 (dark cyan)
|
|
108
|
-
// inlineCodeFg: Dark orange (#b45309), distinguishable without a box bg
|
|
109
|
-
// link: Standard blue (#0055cc), matches browser convention
|
|
110
|
-
// searchMatchBg: Muted yellow (#ffe066), visible on light bg
|
|
111
|
-
// searchMatchFg: Black (#000000)
|
|
112
|
-
// searchCurrentBg: Strong amber (#f59e0b), current match is more vivid
|
|
113
|
-
// searchCurrentFg: Black (#000000)
|
|
114
|
-
// strikethrough: Medium gray (ANSI-256 244 stays; light terminals map it fine)
|
|
115
|
-
// blockquote: Dim blue-gray (ANSI-256 67)
|
|
116
|
-
// assistantHeader: Dark cyan (#0e7490)
|
|
117
|
-
// reasoningAccent: Dark purple (#7c3aed)
|
|
118
|
-
// toolAccent: Dark sky (#0369a1)
|
|
119
|
-
// collapsedBodyBg: Very light gray (#f3f4f6)
|
|
120
|
-
// checkboxChecked: Forest green (#15803d), AA on white (contrast ~5.2:1 on #fff)
|
|
121
|
-
// errorBarBg: Soft rose (#fee2e2), light error bar bg, legible text on top
|
|
122
|
-
// modelNameDim: Slate-500 (#64748b), dim label; contrast ~4.6:1 on #fff
|
|
123
|
-
// toolNameFg: Slate-800 (#334155), strong enough for tool names
|
|
124
|
-
// diffAccent: Amber-700 (#b45309), darker amber, contrast ~4.7:1 on #fff
|
|
111
|
+
// Theme names
|
|
125
112
|
// ---------------------------------------------------------------------------
|
|
126
|
-
const LIGHT: ThemeTokens = {
|
|
127
|
-
heading1: '#0077aa',
|
|
128
|
-
heading2: '#0077aa',
|
|
129
|
-
heading3: '24',
|
|
130
|
-
inlineCodeFg: '#b45309',
|
|
131
|
-
link: '#0055cc',
|
|
132
|
-
searchMatchBg: '#ffe066',
|
|
133
|
-
searchMatchFg: '#000000',
|
|
134
|
-
searchCurrentBg: '#f59e0b',
|
|
135
|
-
searchCurrentFg: '#000000',
|
|
136
|
-
strikethrough: '244',
|
|
137
|
-
blockquote: '67',
|
|
138
|
-
assistantHeader: '#0e7490',
|
|
139
|
-
reasoningAccent: '#7c3aed',
|
|
140
|
-
toolAccent: '#0369a1',
|
|
141
|
-
collapsedBodyBg: '#f3f4f6',
|
|
142
|
-
checkboxChecked: '#15803d',
|
|
143
|
-
errorBarBg: '#fee2e2',
|
|
144
|
-
modelNameDim: '#64748b',
|
|
145
|
-
toolNameFg: '#334155',
|
|
146
|
-
diffAccent: '#b45309',
|
|
147
|
-
};
|
|
148
113
|
|
|
149
|
-
/**
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
export function resolveTheme(mode: ThemeMode): Readonly<ThemeTokens> {
|
|
156
|
-
return mode === 'light' ? LIGHT : DARK;
|
|
114
|
+
/** Every selectable theme: 'system' first, then the bundled catalog (default first). */
|
|
115
|
+
export function listThemeChoices(): ThemeChoice[] {
|
|
116
|
+
return [
|
|
117
|
+
{ name: SYSTEM_THEME_NAME, label: 'System (terminal colors)', variants: ['dark', 'light'] },
|
|
118
|
+
...listBundledThemes().map(({ name, label, variants }) => ({ name, label, variants })),
|
|
119
|
+
];
|
|
157
120
|
}
|
|
158
121
|
|
|
159
|
-
// Freeze both palette objects so they are truly immutable at runtime,
|
|
160
|
-
// matching the Readonly<ThemeTokens> return type in the doc comment above.
|
|
161
|
-
Object.freeze(DARK);
|
|
162
|
-
Object.freeze(LIGHT);
|
|
163
|
-
|
|
164
122
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
123
|
+
* Turn a configured `display.theme` value into a theme name this runtime can
|
|
124
|
+
* resolve: 'vaporwave' maps to 'goodvibes-neon', unknown or non-string values
|
|
125
|
+
* map to the default theme.
|
|
167
126
|
*/
|
|
168
|
-
export
|
|
127
|
+
export function normalizeThemeName(raw: unknown): string {
|
|
128
|
+
if (typeof raw !== 'string') return DEFAULT_THEME_NAME;
|
|
129
|
+
const name = raw.trim().toLowerCase();
|
|
130
|
+
if (name === LEGACY_VAPORWAVE_THEME_NAME) return NEON_THEME_NAME;
|
|
131
|
+
if (name === SYSTEM_THEME_NAME) return SYSTEM_THEME_NAME;
|
|
132
|
+
return getBundledTheme(name) !== undefined ? name : DEFAULT_THEME_NAME;
|
|
133
|
+
}
|
|
169
134
|
|
|
170
135
|
// ---------------------------------------------------------------------------
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
// UI_TONES (ui-primitives.ts) is the dark entry. The light entry mirrors
|
|
174
|
-
// dark for every role that has no light-appropriate equivalent yet, the
|
|
175
|
-
// deliverable is the mode dimension and single read path, not a
|
|
176
|
-
// shipped light chrome theme (see module doc comment above).
|
|
136
|
+
// Resolution (cached per theme + mode; the system entry per probed palette)
|
|
177
137
|
// ---------------------------------------------------------------------------
|
|
178
138
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
139
|
+
interface ResolvedEntry {
|
|
140
|
+
readonly palette: PaletteTokens;
|
|
141
|
+
transcript?: Readonly<ThemeTokens>;
|
|
142
|
+
tones?: Readonly<UiToneTokens>;
|
|
143
|
+
diff?: Readonly<DiffToneTokens>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const resolvedCache = new Map<string, ResolvedEntry>();
|
|
147
|
+
let systemCachePalette: TerminalPalette | null = null;
|
|
183
148
|
|
|
184
|
-
|
|
149
|
+
/** True when the probe returned at least one usable colour. */
|
|
150
|
+
function paletteHasColours(palette: TerminalPalette): boolean {
|
|
151
|
+
return palette.background !== undefined
|
|
152
|
+
|| palette.foreground !== undefined
|
|
153
|
+
|| palette.ansi.some((slot) => slot !== undefined);
|
|
154
|
+
}
|
|
185
155
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
156
|
+
function resolveEntry(name: string, mode: ThemeMode): ResolvedEntry {
|
|
157
|
+
if (name === SYSTEM_THEME_NAME) {
|
|
158
|
+
const probed = getTerminalPalette();
|
|
159
|
+
if (probed !== systemCachePalette) {
|
|
160
|
+
for (const key of [...resolvedCache.keys()]) {
|
|
161
|
+
if (key.startsWith(`${SYSTEM_THEME_NAME}:`)) resolvedCache.delete(key);
|
|
162
|
+
}
|
|
163
|
+
systemCachePalette = probed;
|
|
164
|
+
}
|
|
165
|
+
if (probed === null || !paletteHasColours(probed)) return resolveEntry(DEFAULT_THEME_NAME, mode);
|
|
166
|
+
}
|
|
167
|
+
const key = `${name}:${mode}`;
|
|
168
|
+
const cached = resolvedCache.get(key);
|
|
169
|
+
if (cached !== undefined) return cached;
|
|
170
|
+
const json = name === SYSTEM_THEME_NAME
|
|
171
|
+
? generateSystemTheme(systemCachePalette!, mode)
|
|
172
|
+
: (getBundledTheme(name) ?? getBundledTheme(DEFAULT_THEME_NAME)!).json;
|
|
173
|
+
const entry: ResolvedEntry = { palette: Object.freeze(resolveThemeFile(json, mode)) };
|
|
174
|
+
resolvedCache.set(key, entry);
|
|
175
|
+
return entry;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function transcriptFrom(p: PaletteTokens): ThemeTokens {
|
|
179
|
+
return {
|
|
180
|
+
heading1: p.markdownHeading,
|
|
181
|
+
heading2: p.markdownHeading,
|
|
182
|
+
heading3: p.markdownHeading,
|
|
183
|
+
inlineCodeFg: p.markdownCode,
|
|
184
|
+
link: p.markdownLink,
|
|
185
|
+
searchMatchBg: p.searchMatchBg,
|
|
186
|
+
searchMatchFg: p.text,
|
|
187
|
+
searchCurrentBg: p.searchCurrentBg,
|
|
188
|
+
searchCurrentFg: p.selectedListItemText,
|
|
189
|
+
strikethrough: p.textMuted,
|
|
190
|
+
blockquote: p.markdownBlockQuote,
|
|
191
|
+
assistantHeader: p.panelControl,
|
|
192
|
+
reasoningAccent: p.reasoning,
|
|
193
|
+
toolAccent: p.info,
|
|
194
|
+
collapsedBodyBg: p.backgroundPanel,
|
|
195
|
+
checkboxChecked: p.success,
|
|
196
|
+
errorBarBg: p.backgroundError,
|
|
197
|
+
modelNameDim: p.textMuted,
|
|
198
|
+
toolNameFg: p.text,
|
|
199
|
+
diffAccent: p.warning,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
230
202
|
|
|
231
203
|
/**
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
204
|
+
* Transcript tokens of the active theme for `mode`. The returned object is
|
|
205
|
+
* frozen and stable per (theme, mode), do not mutate it.
|
|
206
|
+
*/
|
|
207
|
+
export function resolveTheme(mode: ThemeMode): Readonly<ThemeTokens> {
|
|
208
|
+
const entry = resolveEntry(activeThemeName, mode);
|
|
209
|
+
entry.transcript ??= Object.freeze(transcriptFrom(entry.palette));
|
|
210
|
+
return entry.transcript;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Chrome tokens (legacy TONE_TOKENS shape) of the active theme for `mode`.
|
|
215
|
+
* Prefer activeUiTones() at call sites.
|
|
238
216
|
*/
|
|
239
217
|
export function resolveUiTones(mode: ThemeMode): Readonly<UiToneTokens> {
|
|
240
|
-
|
|
218
|
+
const entry = resolveEntry(activeThemeName, mode);
|
|
219
|
+
entry.tones ??= Object.freeze(themeToTones(entry.palette));
|
|
220
|
+
return entry.tones;
|
|
241
221
|
}
|
|
242
222
|
|
|
243
223
|
// ===========================================================================
|
|
244
|
-
// Active
|
|
245
|
-
//
|
|
246
|
-
// The mode is decided ONCE at startup, from appearance config (display.themeMode
|
|
247
|
-
// forced dark/light) or the terminal-background probe (auto), and is then stable
|
|
248
|
-
// for the session. Two read shapes exist because the two token layers are
|
|
249
|
-
// consumed differently:
|
|
224
|
+
// Active theme runtime.
|
|
250
225
|
//
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
// registers an in-place rebuild via registerThemeRefresh(); setActiveThemeMode
|
|
260
|
-
// runs every rebuild in registration order (base palettes before the
|
|
261
|
-
// extendPalette-derived panel palettes) so a single mode flip updates them
|
|
262
|
-
// all. The rebuild is fully reversible: light→dark restores byte-identical
|
|
263
|
-
// dark values (tests rely on this to keep the shared test process's default
|
|
264
|
-
// at dark).
|
|
226
|
+
// Theme name and mode are session state. Transcript tokens are read live per
|
|
227
|
+
// render (activeTheme()). Chrome palettes (DEFAULT_VIEW_PALETTE,
|
|
228
|
+
// DEFAULT_OVERLAY_PALETTE, FULLSCREEN_PALETTE, DEFAULT_STYLE, MODAL_TONES and
|
|
229
|
+
// every extendPalette result) are module-level objects read by reference at
|
|
230
|
+
// hundreds of call sites, so each owner registers an in-place rebuild via
|
|
231
|
+
// registerThemeRefresh(); every theme or mode change runs all rebuilds in
|
|
232
|
+
// registration order (base palettes before the extendPalette-derived ones).
|
|
233
|
+
// Callers that change the theme at runtime also request a full repaint.
|
|
265
234
|
// ===========================================================================
|
|
266
235
|
|
|
267
|
-
/** User-facing appearance preference: auto probes the terminal; dark/light force. */
|
|
268
|
-
export type ThemeModeSetting = 'auto' | 'dark' | 'light';
|
|
269
|
-
|
|
270
236
|
/** The resolved mode in effect for the current session. Dark is the safe default. */
|
|
271
237
|
let activeMode: ThemeMode = 'dark';
|
|
272
238
|
|
|
273
|
-
/**
|
|
239
|
+
/** The theme in effect (already normalized). */
|
|
240
|
+
let activeThemeName: string = DEFAULT_THEME_NAME;
|
|
241
|
+
|
|
242
|
+
/** In-place palette rebuilders, run (in registration order) on every change. */
|
|
274
243
|
const themeRefreshers: Array<() => void> = [];
|
|
275
244
|
|
|
276
245
|
/**
|
|
277
|
-
* Register an in-place palette rebuild to run whenever the active
|
|
278
|
-
* Base-palette owners register at their own module-eval time
|
|
279
|
-
* extendPalette-derived palette
|
|
280
|
-
* base-first, the ordering the extended palettes require to re-merge correctly.
|
|
246
|
+
* Register an in-place palette rebuild to run whenever the active theme or
|
|
247
|
+
* mode changes. Base-palette owners register at their own module-eval time,
|
|
248
|
+
* before any extendPalette-derived palette (which depends on the base).
|
|
281
249
|
*/
|
|
282
250
|
export function registerThemeRefresh(rebuild: () => void): void {
|
|
283
251
|
themeRefreshers.push(rebuild);
|
|
284
252
|
}
|
|
285
253
|
|
|
254
|
+
/** The entry for the active (theme, mode); cleared on every change. */
|
|
255
|
+
let activeEntry: ResolvedEntry | null = null;
|
|
256
|
+
|
|
257
|
+
function currentEntry(): ResolvedEntry {
|
|
258
|
+
activeEntry ??= resolveEntry(activeThemeName, activeMode);
|
|
259
|
+
return activeEntry;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function runRefreshers(): void {
|
|
263
|
+
activeEntry = null;
|
|
264
|
+
for (const rebuild of themeRefreshers) rebuild();
|
|
265
|
+
}
|
|
266
|
+
|
|
286
267
|
/**
|
|
287
|
-
* Set the active background mode and rebuild every registered
|
|
288
|
-
*
|
|
289
|
-
* result) and the settings-modal change hook for forced modes.
|
|
268
|
+
* Set the active background mode and rebuild every registered palette in
|
|
269
|
+
* place. Idempotent and reversible.
|
|
290
270
|
*/
|
|
291
271
|
export function setActiveThemeMode(mode: ThemeMode): void {
|
|
292
272
|
activeMode = mode;
|
|
293
|
-
|
|
273
|
+
runRefreshers();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Set the active theme by (configured) name and rebuild every registered
|
|
278
|
+
* palette in place. Accepts any config value; see normalizeThemeName.
|
|
279
|
+
* Returns the normalized name now in effect.
|
|
280
|
+
*/
|
|
281
|
+
export function setActiveThemeName(name: unknown): string {
|
|
282
|
+
activeThemeName = normalizeThemeName(name);
|
|
283
|
+
runRefreshers();
|
|
284
|
+
return activeThemeName;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Re-resolve after the terminal palette arrived or changed. Only the system
|
|
289
|
+
* theme depends on it; for any other theme this is a no-op returning false.
|
|
290
|
+
*/
|
|
291
|
+
export function refreshForTerminalPalette(): boolean {
|
|
292
|
+
if (activeThemeName !== SYSTEM_THEME_NAME) return false;
|
|
293
|
+
runRefreshers();
|
|
294
|
+
return true;
|
|
294
295
|
}
|
|
295
296
|
|
|
296
|
-
/**
|
|
297
|
+
/** The resolved background mode in effect (dark or light). */
|
|
298
|
+
export function activeThemeMode(): ThemeMode {
|
|
299
|
+
return activeMode;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** The normalized name of the active theme ('system' stays 'system'). */
|
|
303
|
+
export function getActiveThemeName(): string {
|
|
304
|
+
return activeThemeName;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/** Full token table for the active theme and mode, read live. */
|
|
308
|
+
export function activeTokens(): Readonly<PaletteTokens> {
|
|
309
|
+
return currentEntry().palette;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** Transcript tokens for the active theme and mode, read live, per render. */
|
|
297
313
|
export function activeTheme(): Readonly<ThemeTokens> {
|
|
298
|
-
|
|
314
|
+
const entry = currentEntry();
|
|
315
|
+
entry.transcript ??= Object.freeze(transcriptFrom(entry.palette));
|
|
316
|
+
return entry.transcript;
|
|
299
317
|
}
|
|
300
318
|
|
|
301
|
-
/** Chrome tokens for the active mode, used to build (and rebuild) palettes. */
|
|
319
|
+
/** Chrome tokens for the active theme and mode, used to build (and rebuild) palettes. */
|
|
302
320
|
export function activeUiTones(): Readonly<UiToneTokens> {
|
|
303
|
-
|
|
321
|
+
const entry = currentEntry();
|
|
322
|
+
entry.tones ??= Object.freeze(themeToTones(entry.palette));
|
|
323
|
+
return entry.tones;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** Diff add/del/hunk tones for the active theme and mode. */
|
|
327
|
+
export function activeDiffTones(): Readonly<DiffToneTokens> {
|
|
328
|
+
const entry = currentEntry();
|
|
329
|
+
entry.diff ??= Object.freeze(themeToDiffTones(entry.palette));
|
|
330
|
+
return entry.diff;
|
|
304
331
|
}
|