@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.
- package/CHANGELOG.md +58 -0
- package/README.md +16 -16
- package/docs/README.md +4 -4
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- 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
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* theme-settings-actions, the `display.theme` picker opened from settings.
|
|
3
|
+
*
|
|
4
|
+
* Lists 'system' plus every bundled theme (label + the modes it was authored
|
|
5
|
+
* for). Moving the cursor previews the highlighted theme live (palettes
|
|
6
|
+
* rebuild, full repaint); Enter stores it in `display.theme`; Esc restores the
|
|
7
|
+
* theme that was active when the picker opened.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { CommandContext } from './command-registry.ts';
|
|
11
|
+
import type { SelectionItem } from './selection-modal.ts';
|
|
12
|
+
import {
|
|
13
|
+
getActiveThemeName,
|
|
14
|
+
listThemeChoices,
|
|
15
|
+
normalizeThemeName,
|
|
16
|
+
setActiveThemeName,
|
|
17
|
+
type ThemeChoice,
|
|
18
|
+
} from '../renderer/theme.ts';
|
|
19
|
+
import { THEME_NAME_CONFIG_KEY } from '../renderer/theme-mode-config.ts';
|
|
20
|
+
import { getTerminalPalette } from '../renderer/terminal-palette.ts';
|
|
21
|
+
|
|
22
|
+
function variantText(choice: ThemeChoice): string {
|
|
23
|
+
return choice.variants.length > 1 ? `${choice.variants.join(' + ')}` : `${choice.variants[0] ?? 'dark'} only`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function systemNote(): string {
|
|
27
|
+
const palette = getTerminalPalette();
|
|
28
|
+
const answered = palette !== null
|
|
29
|
+
&& (palette.background !== undefined || palette.foreground !== undefined || palette.ansi.some((slot) => slot !== undefined));
|
|
30
|
+
return answered ? 'from your terminal colors' : 'terminal colors not read; shows GoodVibes';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Build the picker rows (exported for tests). */
|
|
34
|
+
export function buildThemePickerItems(current: string): SelectionItem[] {
|
|
35
|
+
return listThemeChoices().map((choice) => {
|
|
36
|
+
const detailParts = [choice.name === 'system' ? systemNote() : variantText(choice)];
|
|
37
|
+
if (choice.name === current) detailParts.push('(current)');
|
|
38
|
+
return {
|
|
39
|
+
id: choice.name,
|
|
40
|
+
label: choice.label,
|
|
41
|
+
detail: detailParts.join(' '),
|
|
42
|
+
category: choice.name === 'system' ? 'follow the terminal' : 'bundled themes',
|
|
43
|
+
primaryAction: 'select',
|
|
44
|
+
actions: '[Enter] use theme [Esc] keep previous',
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Open the theme picker. Returns false when this runtime has no selection modal. */
|
|
50
|
+
export function openThemePicker(ctx: CommandContext): boolean {
|
|
51
|
+
if (!ctx.openSelection) return false;
|
|
52
|
+
const configured = normalizeThemeName(ctx.platform.configManager.get(THEME_NAME_CONFIG_KEY));
|
|
53
|
+
const previous = getActiveThemeName();
|
|
54
|
+
const repaint = (): void => {
|
|
55
|
+
ctx.requestFullRepaint?.();
|
|
56
|
+
ctx.renderRequest();
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
ctx.openSelection('Choose Theme', buildThemePickerItems(configured), {
|
|
60
|
+
preSelectId: configured,
|
|
61
|
+
allowSearch: true,
|
|
62
|
+
primaryVerbLabel: 'Use',
|
|
63
|
+
onHighlight: (item) => {
|
|
64
|
+
if (!item || item.id === getActiveThemeName()) return;
|
|
65
|
+
setActiveThemeName(item.id);
|
|
66
|
+
repaint();
|
|
67
|
+
},
|
|
68
|
+
}, (result) => {
|
|
69
|
+
if (!result) {
|
|
70
|
+
if (getActiveThemeName() !== previous) {
|
|
71
|
+
setActiveThemeName(previous);
|
|
72
|
+
repaint();
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
ctx.platform.configManager.setDynamic(THEME_NAME_CONFIG_KEY, result.item.id);
|
|
77
|
+
const applied = setActiveThemeName(result.item.id);
|
|
78
|
+
ctx.print(`Theme set to ${applied}.`);
|
|
79
|
+
repaint();
|
|
80
|
+
});
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* usage-modal.ts, the Usage modal (/usage, /cost, ctrl+p "usage").
|
|
3
|
+
*
|
|
4
|
+
* Reads the session's UsageTracker (runtime/usage-tracker.ts), which has been
|
|
5
|
+
* collecting since startup, so opening this late loses nothing.
|
|
6
|
+
*
|
|
7
|
+
* Keys: tab / shift+tab (or ← →) switch Overview, Turns and Agents; ↑↓ scroll
|
|
8
|
+
* the turns or pick an agent; c compacts the context now (the modal closes
|
|
9
|
+
* first so the compaction's own output is visible); b edits the budget alert;
|
|
10
|
+
* p sets your own price for the current model; r refreshes. Esc closes an open
|
|
11
|
+
* entry first, then the modal.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { InputToken } from '@pellux/goodvibes-sdk/platform/core';
|
|
15
|
+
import type { SurfaceModal, SurfaceModalHost } from './surface-modal-host.ts';
|
|
16
|
+
import type { SurfaceLayer } from '../renderer/surface-kit.ts';
|
|
17
|
+
import { renderUsageModal, USAGE_TABS, type UsageModalView, type UsageTab } from '../renderer/usage-modal.ts';
|
|
18
|
+
import type { UsageTracker } from '../runtime/usage-tracker.ts';
|
|
19
|
+
import { isTextBackspace } from './delete-key-policy.ts';
|
|
20
|
+
|
|
21
|
+
export interface UsageModalOptions {
|
|
22
|
+
readonly tracker: UsageTracker;
|
|
23
|
+
/** Run the context compaction (the /compact command). */
|
|
24
|
+
readonly compact: () => void;
|
|
25
|
+
/** Which tab to open on. */
|
|
26
|
+
readonly tab?: UsageTab;
|
|
27
|
+
/** Repaint (the tracker changed, a poll landed). */
|
|
28
|
+
readonly requestRender?: () => void;
|
|
29
|
+
/** How often running agents' usage is re-read while the modal is open. */
|
|
30
|
+
readonly pollMs?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class UsageModal implements SurfaceModal, UsageModalView {
|
|
34
|
+
readonly name = 'usage';
|
|
35
|
+
tab: UsageTab;
|
|
36
|
+
turnOffset = 0;
|
|
37
|
+
agentIndex = 0;
|
|
38
|
+
entry: { kind: 'budget' | 'price'; draft: string } | null = null;
|
|
39
|
+
status: string | null = null;
|
|
40
|
+
private readonly unsubscribe: () => void;
|
|
41
|
+
private pollTimer: ReturnType<typeof setInterval> | null = null;
|
|
42
|
+
|
|
43
|
+
constructor(private readonly options: UsageModalOptions) {
|
|
44
|
+
this.tab = options.tab ?? 'overview';
|
|
45
|
+
this.unsubscribe = options.tracker.subscribe(() => {
|
|
46
|
+
this.turnOffset = Math.min(this.turnOffset, Math.max(0, this.tracker.turns().length - 1));
|
|
47
|
+
});
|
|
48
|
+
const pollMs = options.pollMs ?? 3_000;
|
|
49
|
+
if (pollMs > 0) {
|
|
50
|
+
this.pollTimer = setInterval(() => {
|
|
51
|
+
if (this.tracker.pollRunningAgents()) options.requestRender?.();
|
|
52
|
+
}, pollMs);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get tracker(): UsageTracker {
|
|
57
|
+
return this.options.tracker;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
onClose(): void {
|
|
61
|
+
this.unsubscribe();
|
|
62
|
+
if (this.pollTimer !== null) clearInterval(this.pollTimer);
|
|
63
|
+
this.pollTimer = null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
escape(): boolean {
|
|
67
|
+
if (this.entry) {
|
|
68
|
+
this.entry = null;
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private stepTab(direction: 1 | -1): void {
|
|
75
|
+
const index = USAGE_TABS.indexOf(this.tab);
|
|
76
|
+
this.tab = USAGE_TABS[(index + direction + USAGE_TABS.length) % USAGE_TABS.length]!;
|
|
77
|
+
this.status = null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private scroll(delta: number): void {
|
|
81
|
+
if (this.tab === 'agents') {
|
|
82
|
+
const count = this.tracker.agents().length;
|
|
83
|
+
if (count === 0) return;
|
|
84
|
+
this.agentIndex = Math.max(0, Math.min(count - 1, this.agentIndex + delta));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const count = this.tracker.turns().length;
|
|
88
|
+
if (count === 0) return;
|
|
89
|
+
// Up goes back in time (a larger offset from the newest turn).
|
|
90
|
+
this.turnOffset = Math.max(0, Math.min(count - 1, this.turnOffset - delta));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private openEntry(kind: 'budget' | 'price'): void {
|
|
94
|
+
if (kind === 'budget') {
|
|
95
|
+
const current = this.tracker.budget();
|
|
96
|
+
this.entry = { kind, draft: current > 0 ? String(current) : '' };
|
|
97
|
+
} else {
|
|
98
|
+
this.entry = { kind, draft: '' };
|
|
99
|
+
}
|
|
100
|
+
this.status = null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private commitEntry(): void {
|
|
104
|
+
const entry = this.entry;
|
|
105
|
+
if (!entry) return;
|
|
106
|
+
if (entry.kind === 'budget') {
|
|
107
|
+
const raw = entry.draft.trim();
|
|
108
|
+
const usd = Number(raw);
|
|
109
|
+
if (raw.length === 0 || !this.tracker.setBudget(usd)) {
|
|
110
|
+
this.status = 'Budget not changed: type an amount in USD, 0 turns the alert off.';
|
|
111
|
+
} else {
|
|
112
|
+
this.status = usd > 0 ? `Budget alert set to $${usd.toFixed(2)}.` : 'Budget alert turned off.';
|
|
113
|
+
}
|
|
114
|
+
this.entry = null;
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (!this.tracker.canSetModelPrice()) {
|
|
118
|
+
this.entry = null;
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const parts = entry.draft.trim().split(/[\s,]+/).filter(Boolean);
|
|
122
|
+
const input = Number(parts[0]);
|
|
123
|
+
const output = Number(parts[1]);
|
|
124
|
+
if (parts.length === 2 && this.tracker.setModelPrice(input, output)) {
|
|
125
|
+
this.status = `Price saved for ${this.tracker.modelId()}.`;
|
|
126
|
+
this.entry = null;
|
|
127
|
+
} else {
|
|
128
|
+
// A malformed price keeps the entry open so it can be corrected.
|
|
129
|
+
this.status = 'Type two amounts: input,output in USD per 1M tokens.';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private handleEntryToken(token: InputToken): void {
|
|
134
|
+
const entry = this.entry!;
|
|
135
|
+
if (token.type === 'text') {
|
|
136
|
+
const allowed = entry.kind === 'budget' ? /[0-9.]/ : /[0-9., ]/;
|
|
137
|
+
for (const ch of token.value) {
|
|
138
|
+
if (!allowed.test(ch)) continue;
|
|
139
|
+
if (entry.kind === 'budget' && ch === '.' && entry.draft.includes('.')) continue;
|
|
140
|
+
entry.draft += ch;
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (token.type !== 'key') return;
|
|
145
|
+
const key = token.logicalName ?? '';
|
|
146
|
+
if (key === 'enter') this.commitEntry();
|
|
147
|
+
else if (isTextBackspace(key)) entry.draft = entry.draft.slice(0, -1);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
handleToken(token: InputToken, host: SurfaceModalHost): void {
|
|
151
|
+
if (this.entry) {
|
|
152
|
+
this.handleEntryToken(token);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (token.type === 'text') {
|
|
156
|
+
const ch = token.value;
|
|
157
|
+
if (ch === 'c') {
|
|
158
|
+
host.close(this, 'done');
|
|
159
|
+
this.options.compact();
|
|
160
|
+
} else if (ch === 'b') this.openEntry('budget');
|
|
161
|
+
else if (ch === 'p') this.openEntry('price');
|
|
162
|
+
else if (ch === 'r') {
|
|
163
|
+
this.tracker.pollRunningAgents();
|
|
164
|
+
this.status = 'Refreshed.';
|
|
165
|
+
} else if (ch === 'j') this.scroll(1);
|
|
166
|
+
else if (ch === 'k') this.scroll(-1);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (token.type !== 'key') return;
|
|
170
|
+
const key = token.logicalName ?? '';
|
|
171
|
+
if (key === 'tab' && token.shift) this.stepTab(-1);
|
|
172
|
+
else if (key === 'tab' || key === 'right') this.stepTab(1);
|
|
173
|
+
else if (key === 'left' || key === '\x1b[Z') this.stepTab(-1);
|
|
174
|
+
else if (key === 'up') this.scroll(-1);
|
|
175
|
+
else if (key === 'down') this.scroll(1);
|
|
176
|
+
else if (key === 'pageup') this.scroll(-5);
|
|
177
|
+
else if (key === 'pagedown') this.scroll(5);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
render(screenWidth: number, screenHeight: number): SurfaceLayer {
|
|
181
|
+
return renderUsageModal(this, screenWidth, screenHeight);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* views.ts, where every old view name goes now.
|
|
3
|
+
*
|
|
4
|
+
* Views live in four kit modals (Usage, Changes, Agents, Notifications), the
|
|
5
|
+
* session picker and the config-modal surfaces. Old names still arrive from
|
|
6
|
+
* many places: `/panel open <id>`, notifications that name the view they are
|
|
7
|
+
* about, cross-modal jumps (the work plan's "show this agent"), saved muscle
|
|
8
|
+
* memory. resolveViewName turns any of them into the modal that holds that
|
|
9
|
+
* content now, so none of them dead-ends.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** A specific row to select when a view opens (a fleet process id, optionally its kind). */
|
|
13
|
+
export interface ViewTarget {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly kind?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type ViewRoute =
|
|
19
|
+
| { readonly kind: 'agents'; readonly hosted?: boolean }
|
|
20
|
+
| { readonly kind: 'usage'; readonly tab?: 'agents' }
|
|
21
|
+
| { readonly kind: 'changes'; readonly mode?: 'review' | 'git' }
|
|
22
|
+
| { readonly kind: 'notifications' }
|
|
23
|
+
| { readonly kind: 'sessions' }
|
|
24
|
+
| { readonly kind: 'modal'; readonly name: string };
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Every old name for the live process console. Fleet absorbed these consoles
|
|
28
|
+
* before; the Agents modal holds that content now, and the palette uses the
|
|
29
|
+
* list as search words so typing an old name finds it.
|
|
30
|
+
*/
|
|
31
|
+
export const AGENT_VIEW_NAMES: readonly string[] = [
|
|
32
|
+
'agents', 'fleet', 'cockpit', 'approval', 'automation', 'routes', 'control-plane', 'worktrees',
|
|
33
|
+
'tasks', 'orchestration', 'ops', 'ops-control', 'communication', 'incident', 'forensics',
|
|
34
|
+
'agent-logs', 'inspector', 'wrfc', 'plan', 'processes',
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
/** Old names for the context and cost consoles. */
|
|
38
|
+
export const USAGE_VIEW_NAMES: readonly string[] = ['usage', 'tokens', 'context', 'cost'];
|
|
39
|
+
|
|
40
|
+
/** Old names for the git, diff and review consoles. */
|
|
41
|
+
export const CHANGES_VIEW_NAMES: readonly string[] = ['changes', 'git', 'diff', 'review'];
|
|
42
|
+
|
|
43
|
+
/** Parse `<id>[:<kind>]` (the `--target` flag's value). */
|
|
44
|
+
export function parseViewTarget(raw: string | undefined): ViewTarget | undefined {
|
|
45
|
+
if (!raw) return undefined;
|
|
46
|
+
const sep = raw.indexOf(':');
|
|
47
|
+
return sep >= 0 ? { id: raw.slice(0, sep), kind: raw.slice(sep + 1) || undefined } : { id: raw };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Remove `--target <id>[:<kind>]` from `args` (in place) and return it, so
|
|
52
|
+
* positional arguments are read the same wherever the flag appears.
|
|
53
|
+
*/
|
|
54
|
+
export function takeTargetFlag(args: string[]): ViewTarget | undefined {
|
|
55
|
+
const index = args.indexOf('--target');
|
|
56
|
+
if (index < 0) return undefined;
|
|
57
|
+
const raw = args[index + 1];
|
|
58
|
+
args.splice(index, raw === undefined ? 1 : 2);
|
|
59
|
+
return parseViewTarget(raw);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The modal an old or current view name opens, or null when nothing holds it.
|
|
64
|
+
* `modalRedirect` resolves config-modal names ('providers', 'services', ...).
|
|
65
|
+
*/
|
|
66
|
+
export function resolveViewName(name: string, modalRedirect: (name: string) => string | undefined): ViewRoute | null {
|
|
67
|
+
const id = name.trim().toLowerCase();
|
|
68
|
+
if (!id) return null;
|
|
69
|
+
if (id === 'hosted') return { kind: 'agents', hosted: true };
|
|
70
|
+
if (AGENT_VIEW_NAMES.includes(id)) return { kind: 'agents' };
|
|
71
|
+
// The old cost view's heart was the per-agent cost ledger: Usage's Agents tab.
|
|
72
|
+
if (id === 'cost') return { kind: 'usage', tab: 'agents' };
|
|
73
|
+
if (USAGE_VIEW_NAMES.includes(id)) return { kind: 'usage' };
|
|
74
|
+
if (id === 'review') return { kind: 'changes', mode: 'review' };
|
|
75
|
+
if (id === 'git') return { kind: 'changes', mode: 'git' };
|
|
76
|
+
if (CHANGES_VIEW_NAMES.includes(id)) return { kind: 'changes' };
|
|
77
|
+
if (id === 'notifications') return { kind: 'notifications' };
|
|
78
|
+
if (id === 'sessions' || id === 'session-picker') return { kind: 'sessions' };
|
|
79
|
+
if (id === 'local-auth') return { kind: 'modal', name: 'local-auth-modal' };
|
|
80
|
+
const redirect = modalRedirect(id);
|
|
81
|
+
if (redirect === 'sessionPicker') return { kind: 'sessions' };
|
|
82
|
+
if (redirect) return { kind: 'modal', name: redirect };
|
|
83
|
+
if (id.endsWith('-modal')) return { kind: 'modal', name: id };
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** A one-line description of where a view name goes, for `/panel list`. */
|
|
88
|
+
export function describeViewRoute(route: ViewRoute): string {
|
|
89
|
+
switch (route.kind) {
|
|
90
|
+
case 'agents': return route.hosted ? 'Agents (the hosted session)' : 'Agents';
|
|
91
|
+
case 'usage': return 'Usage';
|
|
92
|
+
case 'changes': return route.mode === 'review' ? 'Changes (review)' : 'Changes';
|
|
93
|
+
case 'notifications': return 'Notifications';
|
|
94
|
+
case 'sessions': return 'Sessions';
|
|
95
|
+
case 'modal': return route.name;
|
|
96
|
+
}
|
|
97
|
+
}
|