@pellux/goodvibes-tui 1.16.1 → 1.17.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 +89 -9
- package/README.md +1 -1
- package/docs/foundation-artifacts/operator-contract.json +1091 -271
- package/package.json +7 -7
- package/src/cli/completions/generate.ts +5 -4
- package/src/cli/config-overrides.ts +51 -11
- package/src/cli/doctor.ts +4 -5
- package/src/cli/entrypoint.ts +13 -8
- package/src/cli/help.ts +7 -6
- package/src/cli/launch-auto-update.ts +214 -0
- package/src/cli/parser.ts +5 -0
- package/src/cli/status.ts +13 -0
- package/src/cli/surface-command.ts +5 -5
- package/src/cli/tui-startup.ts +60 -97
- package/src/cli/types.ts +2 -0
- package/src/config/index.ts +1 -1
- package/src/config/tui-extension-settings.ts +33 -0
- package/src/core/composer-state.ts +1 -1
- package/src/core/conversation-line-cache.ts +3 -3
- package/src/core/conversation-rendering.ts +4 -4
- package/src/core/conversation.ts +2 -2
- package/src/core/long-task-notifier.ts +7 -7
- package/src/core/stream-event-wiring.ts +8 -6
- package/src/core/system-message-noise.ts +1 -1
- package/src/core/system-message-router.ts +6 -6
- package/src/core/turn-cancellation.ts +1 -1
- package/src/core/turn-event-wiring.ts +8 -8
- package/src/daemon/cli.ts +20 -5
- package/src/daemon/lifecycle.ts +41 -0
- package/src/daemon/service-commands.ts +5 -5
- package/src/export/cost-utils.ts +128 -6
- package/src/input/autocomplete.ts +2 -2
- package/src/input/command-registry.ts +34 -9
- package/src/input/commands/ci-runtime.ts +5 -1
- package/src/input/commands/codebase-runtime.ts +6 -6
- package/src/input/commands/cost-runtime.ts +1 -1
- package/src/input/commands/health-runtime.ts +2 -2
- package/src/input/commands/intelligence-runtime.ts +1 -1
- package/src/input/commands/local-auth-runtime.ts +1 -1
- package/src/input/commands/local-provider-runtime.ts +49 -10
- package/src/input/commands/local-runtime.ts +53 -5
- package/src/input/commands/memory.ts +2 -2
- package/src/input/commands/operator-panel-runtime.ts +5 -5
- package/src/input/commands/permissions-provenance.ts +1 -1
- package/src/input/commands/permissions-runtime.ts +99 -8
- package/src/input/commands/planning-runtime.ts +3 -3
- package/src/input/commands/platform-sandbox-runtime.ts +1 -1
- package/src/input/commands/provider-accounts-runtime.ts +71 -6
- package/src/input/commands/provider.ts +7 -5
- package/src/input/commands/recall-files-git.ts +13 -51
- package/src/input/commands/recall-files.ts +8 -11
- package/src/input/commands/recall-review.ts +2 -2
- package/src/input/commands/relay-runtime.ts +1 -1
- package/src/input/commands/remote-runtime.ts +1 -1
- package/src/input/commands/runtime-services.ts +4 -4
- package/src/input/commands/schedule-runtime.ts +14 -7
- package/src/input/commands/services-runtime.ts +1 -1
- package/src/input/commands/session-workflow.ts +2 -2
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/share-runtime.ts +1 -1
- package/src/input/commands/shell-core.ts +46 -68
- package/src/input/commands/subscription-runtime.ts +1 -1
- package/src/input/commands/update-runtime.ts +153 -96
- package/src/input/commands/work-plan-runtime.ts +1 -1
- package/src/input/commands/workstream-runtime.ts +2 -2
- package/src/input/commands.ts +0 -2
- package/src/input/config-modal-types.ts +3 -3
- package/src/input/config-modal.ts +10 -11
- package/src/input/feature-unit-layout.ts +93 -82
- package/src/input/feed-context-factory.ts +2 -2
- package/src/input/handler-command-route.ts +2 -2
- package/src/input/handler-content-actions.ts +1 -1
- package/src/input/handler-feed-routes.ts +7 -7
- package/src/input/handler-feed.ts +4 -4
- package/src/input/handler-interactions.ts +3 -2
- package/src/input/handler-modal-routes.ts +12 -4
- package/src/input/handler-modal-token-routes.ts +1 -1
- package/src/input/handler-onboarding-daemon-adopt.ts +2 -2
- package/src/input/handler-onboarding.ts +3 -2
- package/src/input/handler-picker-routes.ts +26 -13
- package/src/input/handler-shortcuts.ts +6 -6
- package/src/input/handler.ts +2 -2
- package/src/input/keybindings.ts +2 -2
- package/src/input/onboarding/onboarding-feature-units.ts +34 -27
- package/src/input/onboarding/onboarding-provider-key-fields.ts +112 -0
- package/src/input/onboarding/onboarding-wizard-apply.ts +22 -21
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +17 -0
- package/src/input/onboarding/onboarding-wizard-network-adopt.ts +2 -2
- package/src/input/onboarding/onboarding-wizard-steps.ts +30 -42
- package/src/input/panel-integration-actions.ts +2 -2
- package/src/input/panel-mouse-geometry.ts +1 -1
- package/src/input/panel-paste-flood-guard.ts +1 -1
- package/src/input/provider-key-intake.ts +167 -0
- package/src/input/sandbox-exec-config.ts +2 -2
- package/src/input/selection-modal.ts +1 -1
- package/src/input/settings-modal-activation.ts +5 -0
- package/src/input/settings-modal-adjustment.ts +4 -31
- package/src/input/settings-modal-data.ts +22 -21
- package/src/input/settings-modal-mutations.ts +12 -68
- package/src/input/settings-modal-types.ts +23 -16
- package/src/input/settings-modal.ts +74 -55
- package/src/main.ts +48 -48
- package/src/panels/agent-inspector-shared.ts +4 -4
- package/src/panels/base-panel.ts +2 -2
- package/src/panels/builtin/agent.ts +4 -4
- package/src/panels/builtin/development.ts +4 -4
- package/src/panels/builtin/knowledge.ts +1 -1
- package/src/panels/builtin/operations.ts +29 -10
- package/src/panels/builtin/session.ts +5 -5
- package/src/panels/builtin/shared.ts +4 -4
- package/src/panels/builtin-modals.ts +10 -10
- package/src/panels/builtin-panels.ts +1 -1
- package/src/panels/cost-tracker-panel.ts +124 -7
- package/src/panels/diff-panel.ts +5 -5
- package/src/panels/eval-registry.ts +2 -2
- package/src/panels/fleet-deep-link.ts +1 -1
- package/src/panels/fleet-panel-format.ts +44 -8
- package/src/panels/fleet-panel.ts +16 -16
- package/src/panels/fleet-read-model.ts +52 -13
- package/src/panels/fleet-steer.ts +2 -2
- package/src/panels/fleet-stop.ts +3 -3
- package/src/panels/fleet-tabs.ts +13 -14
- package/src/panels/fleet-transcript.ts +5 -5
- package/src/panels/git-panel.ts +2 -2
- package/src/panels/index.ts +4 -1
- package/src/panels/local-auth-panel.ts +1 -1
- package/src/panels/modals/hooks-modal.ts +1 -1
- package/src/panels/modals/keybindings-modal.ts +2 -2
- package/src/panels/modals/knowledge-modal.ts +1 -1
- package/src/panels/modals/marketplace-modal.ts +4 -4
- package/src/panels/modals/memory-modal.ts +4 -4
- package/src/panels/modals/modal-surface-helpers.ts +1 -1
- package/src/panels/modals/modal-theme.ts +1 -1
- package/src/panels/modals/pairing-modal.ts +2 -2
- package/src/panels/modals/planning-modal.ts +2 -2
- package/src/panels/modals/plugins-modal.ts +1 -1
- package/src/panels/modals/policy-modal.ts +1 -1
- package/src/panels/modals/security-modal.ts +1 -1
- package/src/panels/modals/skills-modal.ts +1 -1
- package/src/panels/modals/work-plan-modal.ts +3 -3
- package/src/panels/notifications-feed.ts +127 -0
- package/src/panels/notifications-panel.ts +160 -0
- package/src/panels/panel-manager.ts +9 -9
- package/src/panels/plugins-panel.ts +4 -4
- package/src/panels/project-planning-answer-actions.ts +1 -1
- package/src/panels/provider-health-routes.ts +2 -2
- package/src/panels/skills-panel.ts +4 -5
- package/src/panels/token-budget-panel.ts +11 -3
- package/src/panels/types.ts +5 -5
- package/src/permissions/broker-approval-card.ts +201 -0
- package/src/permissions/hunk-selection.ts +28 -4
- package/src/permissions/prompt.ts +244 -29
- package/src/renderer/autocomplete-overlay.ts +107 -54
- package/src/renderer/code-block.ts +2 -2
- package/src/renderer/compaction-history-modal.ts +1 -1
- package/src/renderer/compaction-preview.ts +1 -1
- package/src/renderer/compaction-quality.ts +1 -1
- package/src/renderer/compositor.ts +2 -2
- package/src/renderer/config-modal.ts +1 -1
- package/src/renderer/conversation-overlays.ts +1 -1
- package/src/renderer/footer-tips.ts +3 -3
- package/src/renderer/hint-grammar.ts +1 -1
- package/src/renderer/modal-factory.ts +1 -1
- package/src/renderer/model-picker-overlay.ts +1 -1
- package/src/renderer/model-workspace.ts +7 -2
- package/src/renderer/panel-composite.ts +2 -2
- package/src/renderer/panel-workspace-bar.ts +1 -1
- package/src/renderer/process-indicator.ts +1 -1
- package/src/renderer/selection-modal-overlay.ts +1 -1
- package/src/renderer/session-picker-modal.ts +2 -2
- package/src/renderer/settings-modal-helpers.ts +14 -5
- package/src/renderer/settings-modal.ts +127 -39
- package/src/renderer/shell-surface.ts +3 -0
- package/src/renderer/terminal-bg-probe.ts +1 -1
- package/src/renderer/theme.ts +3 -3
- package/src/renderer/tool-call.ts +1 -1
- package/src/renderer/tool-result-summary.ts +1 -1
- package/src/renderer/turn-injection.ts +7 -6
- package/src/renderer/ui-factory.ts +6 -1
- package/src/runtime/bootstrap-command-context.ts +4 -1
- package/src/runtime/bootstrap-command-parts.ts +6 -4
- package/src/runtime/bootstrap-core.ts +35 -35
- package/src/runtime/bootstrap-hook-bridge.ts +1 -1
- package/src/runtime/bootstrap-shell.ts +6 -5
- package/src/runtime/bootstrap.ts +34 -32
- package/src/runtime/channel-composition.ts +46 -0
- package/src/runtime/code-index-services.ts +3 -4
- package/src/runtime/daemon-attach-notices.ts +120 -0
- package/src/runtime/durability-services.ts +55 -0
- package/src/runtime/embedded-service-factories.ts +40 -0
- package/src/runtime/feature-settings.ts +147 -0
- package/src/runtime/index.ts +4 -21
- package/src/runtime/legacy-daemon-migration.ts +29 -19
- package/src/runtime/memory-fold.ts +1 -1
- package/src/runtime/notification-dispatch.ts +110 -0
- package/src/runtime/onboarding/apply.ts +3 -29
- package/src/runtime/onboarding/fast-path.ts +39 -6
- package/src/runtime/onboarding/provider-key-capture.ts +126 -0
- package/src/runtime/onboarding/snapshot.ts +0 -1
- package/src/runtime/onboarding/types.ts +9 -3
- package/src/runtime/provider-fallback.ts +55 -0
- package/src/runtime/provider-optimizer-wiring.ts +55 -0
- package/src/runtime/release-artifacts.ts +19 -103
- package/src/runtime/resume-notice.ts +1 -1
- package/src/runtime/services.ts +81 -82
- package/src/runtime/session-continuity-hints.ts +38 -0
- package/src/runtime/surface-feature-flags.ts +40 -9
- package/src/runtime/terminal-output-guard.ts +2 -2
- package/src/runtime/trust/workspace-registration.ts +10 -2
- package/src/runtime/trust/workspace-trust.ts +58 -31
- package/src/runtime/ui-services.ts +3 -1
- package/src/runtime/update-check.ts +15 -69
- package/src/runtime/workstream-services.ts +2 -2
- package/src/shell/blocking-input.ts +102 -6
- package/src/shell/ui-openers.ts +38 -6
- package/src/utils/format-duration.ts +1 -1
- package/src/verification/verification-ledger.ts +21 -4
- package/src/version.ts +1 -1
- package/src/input/commands/flags-runtime.ts +0 -328
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import type { PanelManager } from '../panel-manager.ts';
|
|
2
2
|
import type { ResolvedBuiltinPanelDeps } from './shared.ts';
|
|
3
3
|
|
|
4
|
-
//
|
|
4
|
+
// (the purge): thinking, tools, inspector, and wrfc were registered here
|
|
5
5
|
// before the purge. thinking/tools were DELETE-disposition (no surviving
|
|
6
6
|
// human surface — thinking already renders inline in the transcript, tool
|
|
7
7
|
// results render inline plus per-node in Fleet); inspector/wrfc were
|
|
8
8
|
// RETIRE-INTO-FLEET (their live console is subsumed by the Fleet panel,
|
|
9
9
|
// operations.ts:84). See registerOperationsPanels for the fleet
|
|
10
|
-
// registration and .goodvibes/audit/2026-07-04-wave6-briefs.json
|
|
10
|
+
// registration and .goodvibes/audit/2026-07-04-wave6-briefs.json for
|
|
11
11
|
// the full disposition map.
|
|
12
12
|
export function registerAgentPanels(manager: PanelManager, deps: ResolvedBuiltinPanelDeps): void {
|
|
13
13
|
// Compat: '/panel open agent-logs' and 'inspector' (and any saved
|
|
14
14
|
// layout/muscle memory) still resolve — redirected straight to fleet.
|
|
15
|
-
// Repointed from agent-logs->inspector
|
|
15
|
+
// Repointed from agent-logs->inspector now that inspector itself
|
|
16
16
|
// is retired; alias resolution is a single hop (PanelManager._resolveId),
|
|
17
17
|
// so this must point at the real surviving id, not at another alias.
|
|
18
18
|
manager.registerAlias('agent-logs', 'fleet');
|
|
19
19
|
manager.registerAlias('inspector', 'fleet');
|
|
20
20
|
manager.registerAlias('wrfc', 'fleet');
|
|
21
21
|
|
|
22
|
-
//
|
|
22
|
+
// (the purge) — group B: 'work-plan' and 'project-planning'
|
|
23
23
|
// migrated to the 'work-plan-modal' / 'planning-modal' config-modal surfaces.
|
|
24
24
|
// Their surfaces AND panel→modal redirects are registered centrally in
|
|
25
25
|
// registerBuiltinModals (builtin-modals.ts). Panel registrations retired here.
|
|
@@ -6,14 +6,14 @@ import { CostTrackerPanel } from '../cost-tracker-panel.ts';
|
|
|
6
6
|
import type { ResolvedBuiltinPanelDeps } from './shared.ts';
|
|
7
7
|
import { requireUiServices, withUnconfiguredFallback } from './shared.ts';
|
|
8
8
|
|
|
9
|
-
//
|
|
9
|
+
// (the purge): plan, intelligence, explorer, preview, and symbols were
|
|
10
10
|
// registered here before the purge. plan was RETIRE-INTO-FLEET (its
|
|
11
11
|
// execution-plan view is subsumed by Fleet — operations.ts:84); the other
|
|
12
12
|
// four were DELETE-disposition (no surviving human surface — intelligence's
|
|
13
13
|
// read-model still backs the surviving `/intelligence` CLI subcommands, see
|
|
14
14
|
// intelligence-runtime.ts; explorer/preview/symbols had no dedicated
|
|
15
15
|
// read-model to preserve). See .goodvibes/audit/2026-07-04-wave6-briefs.json
|
|
16
|
-
//
|
|
16
|
+
// for the full disposition map.
|
|
17
17
|
export function registerDevelopmentPanels(manager: PanelManager, deps: ResolvedBuiltinPanelDeps): void {
|
|
18
18
|
manager.registerType({
|
|
19
19
|
id: 'git',
|
|
@@ -56,10 +56,10 @@ export function registerDevelopmentPanels(manager: PanelManager, deps: ResolvedB
|
|
|
56
56
|
),
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
//
|
|
59
|
+
// 'inspector' registration moved to builtin/agent.ts (category
|
|
60
60
|
// 'agent') — it now absorbs the merged agent-logs capabilities.
|
|
61
61
|
|
|
62
|
-
//
|
|
62
|
+
// always registered (was gated behind `if (deps.getOrchestratorUsage)`,
|
|
63
63
|
// so `/panel open cost` reported "Unknown panel" on builds without usage
|
|
64
64
|
// tracking wired). Falls back to a "dependency not configured" empty state.
|
|
65
65
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PanelManager } from '../panel-manager.ts';
|
|
2
2
|
import type { ResolvedBuiltinPanelDeps } from './shared.ts';
|
|
3
3
|
|
|
4
|
-
//
|
|
4
|
+
// (the purge) — group B: 'knowledge' and 'memory' migrated to the
|
|
5
5
|
// 'knowledge-modal' / 'memory-modal' config-modal surfaces. Both surfaces and
|
|
6
6
|
// their panel→modal redirects are registered centrally in registerBuiltinModals
|
|
7
7
|
// (src/panels/builtin-modals.ts). This registrar is intentionally empty
|
|
@@ -2,39 +2,40 @@ import type { PanelManager } from '../panel-manager.ts';
|
|
|
2
2
|
import { FleetPanel } from '../fleet-panel.ts';
|
|
3
3
|
import { createFleetReadModel } from '../fleet-read-model.ts';
|
|
4
4
|
import { LocalAuthPanel } from '../local-auth-panel.ts';
|
|
5
|
+
import { NotificationsPanel } from '../notifications-panel.ts';
|
|
5
6
|
import type { ResolvedBuiltinPanelDeps } from './shared.ts';
|
|
6
7
|
import { requireUiServices } from './shared.ts';
|
|
7
8
|
|
|
8
|
-
//
|
|
9
|
+
// the former single 'monitoring' category (33 panels pre-merge) is
|
|
9
10
|
// split into five operator domains, applied per-registration below. Kept in
|
|
10
11
|
// this file's original registration order (rather than physically regrouped
|
|
11
12
|
// by category) because several registrations below close over shared local
|
|
12
13
|
// state — `ui` — defined once near the top of this function.
|
|
13
14
|
//
|
|
14
|
-
//
|
|
15
|
+
// (the purge): cockpit, approval, automation, routes, control-plane,
|
|
15
16
|
// worktrees, tasks, orchestration, ops, ops-control, and communication were
|
|
16
17
|
// RETIRE-INTO-FLEET (their live views are subsumed by the Fleet panel below
|
|
17
18
|
// — each id now redirects there via registerAlias); debug and eval were
|
|
18
19
|
// DELETE-disposition (no surviving human surface). See
|
|
19
|
-
// .goodvibes/audit/2026-07-04-wave6-briefs.json
|
|
20
|
+
// .goodvibes/audit/2026-07-04-wave6-briefs.json for the full
|
|
20
21
|
// disposition map. The rosterReadModel/agent-lifecycle wiring that used to
|
|
21
22
|
// feed CockpitPanel exclusively was removed along with it — Fleet reads the
|
|
22
23
|
// process registry directly via fleetReadModel below, not via the roster
|
|
23
24
|
// read-model.
|
|
24
25
|
//
|
|
25
|
-
//
|
|
26
|
+
// MIGRATE-TO-MODAL: the Providers & Connectivity group (services,
|
|
26
27
|
// subscription, remote, provider-health) and Security group (settings-sync,
|
|
27
28
|
// sandbox) migrated to config-modal surfaces registered in builtin-modals.ts
|
|
28
|
-
|
|
29
|
+
//; the Ecosystem & Governance group (plugins, skills, hooks, security,
|
|
29
30
|
// marketplace, policy, knowledge, memory, docs, qr-code, work-plan,
|
|
30
|
-
// project-planning) migrated to config-modal surfaces
|
|
31
|
+
// project-planning) migrated to config-modal surfaces. All surfaces AND
|
|
31
32
|
// their panel-id redirects are registered centrally in registerBuiltinModals
|
|
32
33
|
// (builtin-modals.ts) now — the interim ecosystem redirect bridge was deleted
|
|
33
34
|
// with the group-B port. local-auth is a DELIBERATE EXCEPTION — see below.
|
|
34
35
|
export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBuiltinPanelDeps): void {
|
|
35
36
|
const ui = requireUiServices(deps);
|
|
36
37
|
|
|
37
|
-
//
|
|
38
|
+
// Fleet — the live unified process tree, read from the single
|
|
38
39
|
// process registry constructed once in runtime/services.ts (shared with
|
|
39
40
|
// every other consumer rather than duplicated here; the registry owns its
|
|
40
41
|
// own coalesced tick, so no manual lifecycle-event wiring is needed).
|
|
@@ -45,7 +46,7 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
|
|
|
45
46
|
manager.registerType({
|
|
46
47
|
id: 'fleet',
|
|
47
48
|
name: 'Fleet',
|
|
48
|
-
//
|
|
49
|
+
// '⊟' verified free against the full icon registry at wiring time.
|
|
49
50
|
icon: '⊟',
|
|
50
51
|
category: 'runtime-ops',
|
|
51
52
|
description: 'Live unified process tree: agents, WRFC chains, workflows, watchers, and background processes, with interrupt/kill/steer controls',
|
|
@@ -82,11 +83,29 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
|
|
|
82
83
|
manager.registerAlias('communication', 'fleet');
|
|
83
84
|
manager.registerAlias('incident', 'fleet');
|
|
84
85
|
// Re-pointed: forensics used to resolve to the (now-retired) incident
|
|
85
|
-
// workspace
|
|
86
|
+
// workspace; both ids now land on fleet directly — alias
|
|
86
87
|
// resolution is a single hop, so this cannot chain through 'incident'.
|
|
87
88
|
manager.registerAlias('forensics', 'fleet');
|
|
88
89
|
|
|
89
|
-
//
|
|
90
|
+
// Notifications — the visible home for the panel_only notification
|
|
91
|
+
// target: anything a NotificationRouter (SDK) routes there (including
|
|
92
|
+
// burst/batch-collapsed groups, shown with their real running count)
|
|
93
|
+
// renders here instead of having nowhere to go. See notifications-feed.ts
|
|
94
|
+
// for why this exists. Not preloaded (only 'tokens' preloads, per the
|
|
95
|
+
// panel-consolidation cleanup below) — the shared feed singleton
|
|
96
|
+
// accumulates independently of whether this view has been opened yet, so
|
|
97
|
+
// nothing is lost by instantiating it lazily on first open like every
|
|
98
|
+
// other panel here.
|
|
99
|
+
manager.registerType({
|
|
100
|
+
id: 'notifications',
|
|
101
|
+
name: 'Notifications',
|
|
102
|
+
icon: 'N',
|
|
103
|
+
category: 'runtime-ops',
|
|
104
|
+
description: 'Notifications routed to the panel-only target (quiet/balanced-mode operational chatter, burst- and batch-collapsed groups) with their real collapsed counts',
|
|
105
|
+
factory: () => new NotificationsPanel(),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// local-auth is a DELIBERATE EXCEPTION to the purge: it stays a
|
|
90
109
|
// registered panel because it is the host for the masked password-entry
|
|
91
110
|
// sub-mode (LocalAuthPanel.openMaskedEntry, driven by
|
|
92
111
|
// ctx.openLocalAuthMaskedEntry — the only path that keeps a plaintext
|
|
@@ -3,7 +3,7 @@ import { TokenBudgetPanel } from '../token-budget-panel.ts';
|
|
|
3
3
|
import type { ResolvedBuiltinPanelDeps } from './shared.ts';
|
|
4
4
|
import { requireUiServices } from './shared.ts';
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// (the purge): panel-list and system-messages were registered here
|
|
7
7
|
// before the purge — both DELETE-disposition. panel-list was a picker over a
|
|
8
8
|
// handful of panels (dead weight now that the registry is much smaller —
|
|
9
9
|
// the picker itself is replaced by a live-registry selection modal on
|
|
@@ -14,7 +14,7 @@ import { requireUiServices } from './shared.ts';
|
|
|
14
14
|
// conversation.addTypedSystemMessage for every kind/target combination — see
|
|
15
15
|
// bootstrap-shell.ts and core/system-message-router.ts.
|
|
16
16
|
//
|
|
17
|
-
//
|
|
17
|
+
// (the purge) — group B: 'qr-code', 'sessions', and 'docs' also
|
|
18
18
|
// migrated. 'qr-code' → the 'pairing-modal' surface; 'docs' → the
|
|
19
19
|
// 'keybindings-modal' surface (merged with the shortcuts-overlay content);
|
|
20
20
|
// 'sessions' folds into the existing session-picker modal ('sessions' redirects
|
|
@@ -25,7 +25,7 @@ export function registerSessionPanels(manager: PanelManager, deps: ResolvedBuilt
|
|
|
25
25
|
manager.registerType({
|
|
26
26
|
id: 'tokens',
|
|
27
27
|
name: 'Tokens',
|
|
28
|
-
//
|
|
28
|
+
// registry previously said 'K' while the live panel's own
|
|
29
29
|
// super() call used 'T' — a pre-existing registry/instance mismatch as
|
|
30
30
|
// well as a collision ('K' with knowledge/skills, 'T' with thinking).
|
|
31
31
|
// Unified to a single unique glyph in both places.
|
|
@@ -35,7 +35,7 @@ export function registerSessionPanels(manager: PanelManager, deps: ResolvedBuilt
|
|
|
35
35
|
// Preloaded (absorbed from the retired ContextVisualizerPanel) so turn
|
|
36
36
|
// history and pressure accumulate in the background even before the user
|
|
37
37
|
// opens the tab. The only builtin panel that still preloads post-purge
|
|
38
|
-
//
|
|
38
|
+
// — see registerBuiltinPanels callers for the others' preload
|
|
39
39
|
// removal.
|
|
40
40
|
preload: true,
|
|
41
41
|
retainOnClose: true,
|
|
@@ -58,7 +58,7 @@ export function registerSessionPanels(manager: PanelManager, deps: ResolvedBuilt
|
|
|
58
58
|
},
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
//
|
|
61
|
+
// compat: the retired 'context' panel id still resolves — redirected
|
|
62
62
|
// to the merged tokens console ('/panel open context', saved layouts).
|
|
63
63
|
manager.registerAlias('context', 'tokens');
|
|
64
64
|
}
|
|
@@ -55,7 +55,7 @@ export interface BuiltinPanelDeps {
|
|
|
55
55
|
subscriptionManager?: SubscriptionManager;
|
|
56
56
|
/** Shared service registry for services-backed panels. */
|
|
57
57
|
serviceRegistry?: ServiceRegistry;
|
|
58
|
-
/** Context window size in tokens. Unused since
|
|
58
|
+
/** Context window size in tokens. Unused since folded ContextVisualizerPanel into TokenBudgetPanel (which reads getCtxWindow instead); kept for source compatibility. */
|
|
59
59
|
contextWindow?: number;
|
|
60
60
|
/** Main Orchestrator instance for TokenBudgetPanel.wire(). */
|
|
61
61
|
orchestrator?: Orchestrator;
|
|
@@ -72,7 +72,7 @@ export interface BuiltinPanelDeps {
|
|
|
72
72
|
/** ForensicsRegistry for the Forensics panel. */
|
|
73
73
|
forensicsRegistry?: import('@/runtime/index.ts').ForensicsRegistry;
|
|
74
74
|
/**
|
|
75
|
-
* EvalRegistry for the `/eval` command surface
|
|
75
|
+
* EvalRegistry for the `/eval` command surface.: 'eval' the panel was
|
|
76
76
|
* deleted (DELETE-disposition), but this field is left in place — no
|
|
77
77
|
* builtin panel factory reads it anymore, and it was never wired at
|
|
78
78
|
* bootstrap in production either way (the eval CLI command reads its own
|
|
@@ -123,7 +123,7 @@ export interface BuiltinPanelDeps {
|
|
|
123
123
|
workPlanStore?: import('../../work-plans/work-plan-store.ts').WorkPlanStore;
|
|
124
124
|
/** Explicit UI-facing runtime services for agent/process/WRFC/remote panels and modals. */
|
|
125
125
|
uiServices?: UiRuntimeServices;
|
|
126
|
-
/** Shared plugin manager for plugin and security panels (widened past the read-only observer surface —
|
|
126
|
+
/** Shared plugin manager for plugin and security panels (widened past the read-only observer surface — — so PluginsPanel can drive enable/disable/verify/lift-quarantine). */
|
|
127
127
|
pluginManager?: PluginManagerControls;
|
|
128
128
|
/** Shared hook dispatcher for the hooks control-room panel. */
|
|
129
129
|
hookDispatcher?: Pick<HookDispatcher, 'listHooks' | 'getChains'>;
|
|
@@ -287,7 +287,7 @@ export function requireKnowledgeApi(deps: BuiltinPanelDeps): KnowledgeApi {
|
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
// ---------------------------------------------------------------------------
|
|
290
|
-
//
|
|
290
|
+
// always-register conditional panels with a "dependency not
|
|
291
291
|
// configured" empty state instead of skipping registration entirely.
|
|
292
292
|
// ---------------------------------------------------------------------------
|
|
293
293
|
|
|
@@ -7,7 +7,7 @@ import { createProviderRuntimeInspectionQuery } from '../runtime/ui-service-quer
|
|
|
7
7
|
import { createRuntimeProviderApi } from '@/runtime/index.ts';
|
|
8
8
|
import { copyToClipboard } from '../utils/clipboard.ts';
|
|
9
9
|
import { getOrCreateCompanionToken, buildCompanionConnectionInfo } from '@pellux/goodvibes-sdk/platform/pairing';
|
|
10
|
-
// ──
|
|
10
|
+
// ── Providers & Connectivity + Security subset ────────────────────────────────
|
|
11
11
|
import { createServicesModalSurface } from './modals/services-modal.ts';
|
|
12
12
|
import { createSubscriptionModalSurface } from './modals/subscription-modal.ts';
|
|
13
13
|
import { createRemoteModalSurface } from './modals/remote-modal.ts';
|
|
@@ -15,7 +15,7 @@ import { createSettingsSyncModalSurface } from './modals/settings-sync-modal.ts'
|
|
|
15
15
|
import { createProviderHealthModalSurface } from './modals/provider-health-modal.ts';
|
|
16
16
|
import { createLocalAuthModalSurface } from './modals/local-auth-modal.ts';
|
|
17
17
|
import { createSandboxModalSurface } from './modals/sandbox-modal.ts';
|
|
18
|
-
// ──
|
|
18
|
+
// ── Ecosystem & Governance ─────────────────────────────────────────────────
|
|
19
19
|
import { createMarketplaceModalSurface } from './modals/marketplace-modal.ts';
|
|
20
20
|
import { createPluginsModalSurface } from './modals/plugins-modal.ts';
|
|
21
21
|
import { createSkillsModalSurface } from './modals/skills-modal.ts';
|
|
@@ -30,22 +30,22 @@ import { createPairingModalSurface, type PairingModalConnectionInfo } from './mo
|
|
|
30
30
|
import { createPlanningModalSurface } from './modals/planning-modal.ts';
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* Register the config-modal surfaces + their panel-id redirects
|
|
34
|
-
*
|
|
33
|
+
* Register the config-modal surfaces + their panel-id redirects, from a prior
|
|
34
|
+
* panel-consolidation cleanup. Called once at startup from registerBuiltinPanels, AFTER the panels'
|
|
35
35
|
* deps are resolved (the surfaces close over the same read-models the retired
|
|
36
|
-
* panels used). For each
|
|
36
|
+
* panels used). For each surface migrated from a standalone panel this does two things:
|
|
37
37
|
* 1. registerModalSurface — the data + actions the config-modal host renders.
|
|
38
38
|
* 2. registerModalRedirect — so `/panel open <old-id>`, saved layouts, and any
|
|
39
39
|
* alias still resolve to the modal.
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
41
|
+
* The Providers & Connectivity + Security subset is registered first, followed by the
|
|
42
|
+
* Ecosystem & Governance set — the 12 ported config-modal
|
|
43
43
|
* surfaces plus the `sessions` fold into the existing session-picker modal.
|
|
44
44
|
*/
|
|
45
45
|
export function registerBuiltinModals(manager: PanelManager, deps: ResolvedBuiltinPanelDeps): void {
|
|
46
46
|
const ui = requireUiServices(deps);
|
|
47
47
|
|
|
48
|
-
// ── Providers & Connectivity
|
|
48
|
+
// ── Providers & Connectivity ─────────────────────────────────────────────────
|
|
49
49
|
manager.registerModalSurface(createServicesModalSurface(deps.serviceRegistry, deps.subscriptionManager));
|
|
50
50
|
manager.registerModalRedirect('services', 'services-modal');
|
|
51
51
|
|
|
@@ -65,7 +65,7 @@ export function registerBuiltinModals(manager: PanelManager, deps: ResolvedBuilt
|
|
|
65
65
|
manager.registerModalRedirect('providers', 'providers-modal');
|
|
66
66
|
manager.registerModalRedirect('accounts', 'providers-modal');
|
|
67
67
|
|
|
68
|
-
// ── Security & Governance
|
|
68
|
+
// ── Security & Governance ────────────────────────────────────────────────────
|
|
69
69
|
manager.registerModalSurface(createSettingsSyncModalSurface(deps.configManager));
|
|
70
70
|
manager.registerModalRedirect('settings-sync', 'settings-sync-modal');
|
|
71
71
|
|
|
@@ -77,7 +77,7 @@ export function registerBuiltinModals(manager: PanelManager, deps: ResolvedBuilt
|
|
|
77
77
|
manager.registerModalSurface(createSandboxModalSurface(deps.configManager, deps.sandboxSessionRegistry, deps.requestRender));
|
|
78
78
|
manager.registerModalRedirect('sandbox', 'sandbox-modal');
|
|
79
79
|
|
|
80
|
-
// ── Ecosystem & Governance
|
|
80
|
+
// ── Ecosystem & Governance ───────────────────────────────────────────────────
|
|
81
81
|
manager.registerModalSurface(createMarketplaceModalSurface({
|
|
82
82
|
readModel: ui.readModels.marketplace,
|
|
83
83
|
ecosystemPaths: {
|
|
@@ -19,7 +19,7 @@ export function registerBuiltinPanels(manager: PanelManager, deps: BuiltinPanelD
|
|
|
19
19
|
registerAgentPanels(manager, resolved);
|
|
20
20
|
registerSessionPanels(manager, resolved);
|
|
21
21
|
registerKnowledgePanels(manager, resolved);
|
|
22
|
-
//
|
|
22
|
+
// (the purge): register MIGRATE-TO-MODAL surfaces + their panel-id
|
|
23
23
|
// redirects. Must run after the panel registrations so a redirected id wins
|
|
24
24
|
// over any lingering panel registration in open().
|
|
25
25
|
registerBuiltinModals(manager, resolved);
|
|
@@ -22,15 +22,15 @@ import {
|
|
|
22
22
|
DEFAULT_PANEL_PALETTE,
|
|
23
23
|
type PanelWorkspaceSection,
|
|
24
24
|
} from './polish.ts';
|
|
25
|
-
import { calcSessionCost, isModelPriced, computeBudgetBreach, readBudgetAlertUsd, BUDGET_ALERT_USD_CONFIG_KEY, type BudgetAlertConfigAccess } from '../export/cost-utils.ts';
|
|
25
|
+
import { calcSessionCost, describePricingSource, isModelPriced, computeBudgetBreach, readBudgetAlertUsd, writeManualModelPrice, BUDGET_ALERT_USD_CONFIG_KEY, type BudgetAlertConfigAccess } from '../export/cost-utils.ts';
|
|
26
26
|
import { abbreviateCount } from '../utils/format-number.ts';
|
|
27
27
|
import { isTextBackspace } from '../input/delete-key-policy.ts';
|
|
28
28
|
|
|
29
29
|
// Pricing lookups are provided by ../export/cost-utils.ts (single source of truth).
|
|
30
30
|
|
|
31
|
-
/** unpriced=true renders
|
|
31
|
+
/** unpriced=true renders the explicit "price unknown" marker instead of a $0.00 that could be mistaken for a real zero cost. */
|
|
32
32
|
function formatCost(usd: number, unpriced = false): string {
|
|
33
|
-
if (unpriced) return '
|
|
33
|
+
if (unpriced) return 'price unknown';
|
|
34
34
|
if (usd === 0) return '$0.00';
|
|
35
35
|
if (usd < 0.0001) return '<$0.0001';
|
|
36
36
|
if (usd < 0.01) return `$${usd.toFixed(4)}`;
|
|
@@ -127,6 +127,12 @@ export class CostTrackerPanel extends BasePanel {
|
|
|
127
127
|
// secret so it is echoed directly.
|
|
128
128
|
private budgetEntry: string | null = null;
|
|
129
129
|
|
|
130
|
+
// Draft buffer for the in-panel manual-price entry mode ('p' key): the one
|
|
131
|
+
// action away from any price display (and from the "price unknown" marker).
|
|
132
|
+
// Format: "input,output" in USD per 1M tokens; persists to the
|
|
133
|
+
// pricing.modelPrices settings key live on Enter.
|
|
134
|
+
private priceEntry: string | null = null;
|
|
135
|
+
|
|
130
136
|
// Scroll offset for agent list
|
|
131
137
|
private scrollOffset = 0;
|
|
132
138
|
|
|
@@ -347,11 +353,12 @@ export class CostTrackerPanel extends BasePanel {
|
|
|
347
353
|
* `Panel.isCapturingTextBurst`.
|
|
348
354
|
*/
|
|
349
355
|
isCapturingTextBurst(): boolean {
|
|
350
|
-
return this.budgetEntry !== null;
|
|
356
|
+
return this.budgetEntry !== null || this.priceEntry !== null;
|
|
351
357
|
}
|
|
352
358
|
|
|
353
359
|
handleInput(key: string): boolean {
|
|
354
360
|
if (this.budgetEntry !== null) return this.handleBudgetEntryInput(key);
|
|
361
|
+
if (this.priceEntry !== null) return this.handlePriceEntryInput(key);
|
|
355
362
|
|
|
356
363
|
if (key === 'b') {
|
|
357
364
|
const threshold = this.currentBudgetThreshold();
|
|
@@ -360,6 +367,16 @@ export class CostTrackerPanel extends BasePanel {
|
|
|
360
367
|
return true;
|
|
361
368
|
}
|
|
362
369
|
|
|
370
|
+
if (key === 'p') {
|
|
371
|
+
// One action from any price display: edit the manual price for the
|
|
372
|
+
// session's provider:model. Needs a wired config (production path) —
|
|
373
|
+
// without one the key falls through rather than opening a dead editor.
|
|
374
|
+
if (!this.configAccess) return false;
|
|
375
|
+
this.priceEntry = '';
|
|
376
|
+
this.markDirty();
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
|
|
363
380
|
switch (key) {
|
|
364
381
|
case 'up': return this.scroll(-1);
|
|
365
382
|
case 'down': return this.scroll(1);
|
|
@@ -402,6 +419,52 @@ export class CostTrackerPanel extends BasePanel {
|
|
|
402
419
|
return true; // absorb everything else while entry is active
|
|
403
420
|
}
|
|
404
421
|
|
|
422
|
+
/** True when the session model can carry a manual price (pricing.modelPrices keys are `provider:model`). */
|
|
423
|
+
private canEditSessionModelPrice(): boolean {
|
|
424
|
+
return this.sessionModel !== 'unknown' && this.sessionModel.includes(':');
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
private handlePriceEntryInput(key: string): boolean {
|
|
428
|
+
if (key === 'escape') {
|
|
429
|
+
this.priceEntry = null;
|
|
430
|
+
this.markDirty();
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
433
|
+
if (key === 'enter' || key === 'return') {
|
|
434
|
+
const raw = (this.priceEntry ?? '').trim();
|
|
435
|
+
if (!this.canEditSessionModelPrice()) {
|
|
436
|
+
// The prompt already explains why; Enter just closes it.
|
|
437
|
+
this.priceEntry = null;
|
|
438
|
+
this.markDirty();
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
const parts = raw.split(/[\s,]+/).filter((part) => part.length > 0);
|
|
442
|
+
const input = Number(parts[0]);
|
|
443
|
+
const output = Number(parts[1]);
|
|
444
|
+
if (parts.length === 2 && Number.isFinite(input) && input >= 0 && Number.isFinite(output) && output >= 0) {
|
|
445
|
+
writeManualModelPrice(this.configAccess!, this.sessionModel, { input, output });
|
|
446
|
+
this.priceEntry = null;
|
|
447
|
+
}
|
|
448
|
+
// Malformed input keeps the editor open so the draft can be corrected.
|
|
449
|
+
this.markDirty();
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
452
|
+
if (isTextBackspace(key)) {
|
|
453
|
+
if (this.priceEntry && this.priceEntry.length > 0) {
|
|
454
|
+
this.priceEntry = this.priceEntry.slice(0, -1);
|
|
455
|
+
this.markDirty();
|
|
456
|
+
}
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
// Two USD amounts separated by a comma (or space) — digits, dots, comma, space.
|
|
460
|
+
if (key.length === 1 && /[0-9., ]/.test(key)) {
|
|
461
|
+
this.priceEntry = (this.priceEntry ?? '') + key;
|
|
462
|
+
this.markDirty();
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
return true; // absorb everything else while entry is active
|
|
466
|
+
}
|
|
467
|
+
|
|
405
468
|
/**
|
|
406
469
|
* Scroll the agent list. Over-consumption fix: only absorbs the key (and
|
|
407
470
|
* only advances) when the agent list is actually long enough to scroll —
|
|
@@ -427,20 +490,29 @@ export class CostTrackerPanel extends BasePanel {
|
|
|
427
490
|
render(width: number, height: number): Line[] {
|
|
428
491
|
if (height <= 0 || width <= 0) return [];
|
|
429
492
|
if (this.budgetEntry !== null) return this.renderBudgetEntryPrompt(width, height);
|
|
493
|
+
if (this.priceEntry !== null) return this.renderPriceEntryPrompt(width, height);
|
|
430
494
|
|
|
431
495
|
const totalInputTokens = this.sessionUsage.input + this.sessionUsage.cacheRead + this.sessionUsage.cacheWrite;
|
|
432
496
|
const sessionCost = calcSessionCost(this.sessionUsage.input, this.sessionUsage.output, this.sessionUsage.cacheRead, this.sessionUsage.cacheWrite, this.sessionModel);
|
|
433
497
|
const budgetThreshold = this.currentBudgetThreshold();
|
|
434
498
|
const overBudget = computeBudgetBreach(sessionCost, budgetThreshold);
|
|
435
499
|
const sparkline = buildSparkline(this.costHistory);
|
|
436
|
-
const
|
|
500
|
+
const sessionPriced = isModelPriced(this.sessionModel);
|
|
501
|
+
const costStr = formatCost(sessionCost, !sessionPriced);
|
|
437
502
|
const costFg = overBudget ? C.bad : C.cost;
|
|
503
|
+
// Dollars carry their source: "your price" for a manual entry,
|
|
504
|
+
// "catalog price, as of <date>" for the dated catalog, etc. The
|
|
505
|
+
// "price unknown" marker carries the one-key action to fix it instead.
|
|
506
|
+
const sourceDescription = sessionPriced ? describePricingSource(this.sessionModel) : null;
|
|
507
|
+
const sourceStr = sessionPriced
|
|
508
|
+
? (sourceDescription ? ` (${sourceDescription})` : '')
|
|
509
|
+
: ' — press p to set a price';
|
|
438
510
|
const budgetStr = budgetThreshold > 0
|
|
439
511
|
? ` / ${formatCost(budgetThreshold)}`
|
|
440
512
|
: '';
|
|
441
513
|
const alertStr = overBudget ? ' ! OVER BUDGET' : '';
|
|
442
514
|
const sessionLines: Line[] = [
|
|
443
|
-
this.renderKeyValue(width, ' Total', `${costStr}${budgetStr}${alertStr}`, costFg),
|
|
515
|
+
this.renderKeyValue(width, ' Total', `${costStr}${budgetStr}${alertStr}${sourceStr}`, costFg),
|
|
444
516
|
];
|
|
445
517
|
// Budget meter — the single most important glance for this panel: how much
|
|
446
518
|
// of the configured budget the session has consumed. Only shown when a
|
|
@@ -455,6 +527,13 @@ export class CostTrackerPanel extends BasePanel {
|
|
|
455
527
|
{ filled: meterFg, empty: C.separator, label: C.label },
|
|
456
528
|
{ prefix: ' Budget [', suffix: `] ${pctStr}` },
|
|
457
529
|
));
|
|
530
|
+
// Unpriced-spend honesty wherever budget state shows: a meter over a
|
|
531
|
+
// partially-unpriced session must say the % undercounts real spend.
|
|
532
|
+
const anyUnpricedSpend = (!sessionPriced && (totalInputTokens > 0 || this.sessionUsage.output > 0))
|
|
533
|
+
|| Array.from(this.agents.values()).some((agent) => agent.inputTokens > 0 && !isModelPriced(agent.model));
|
|
534
|
+
if (anyUnpricedSpend) {
|
|
535
|
+
sessionLines.push(this.renderKeyValue(width, '', 'some spend has no known price and is not counted above', C.warn));
|
|
536
|
+
}
|
|
458
537
|
}
|
|
459
538
|
if (sparkline.length > 0) sessionLines.push(this.renderLabeledLine(width, ' Trend', sparkline, C.good));
|
|
460
539
|
sessionLines.push(this.renderKeyValue(width, ' Input', formatTokens(this.sessionUsage.input), C.label));
|
|
@@ -481,9 +560,11 @@ export class CostTrackerPanel extends BasePanel {
|
|
|
481
560
|
{ keys: 'Up/Down', label: 'scroll agents' },
|
|
482
561
|
{ keys: 'PgUp/PgDn', label: 'page' },
|
|
483
562
|
{ keys: 'b', label: 'set budget' },
|
|
563
|
+
{ keys: 'p', label: 'set model price' },
|
|
484
564
|
], DEFAULT_PANEL_PALETTE)
|
|
485
565
|
: buildKeyboardHints(width, [
|
|
486
566
|
{ keys: 'b', label: 'set budget alert' },
|
|
567
|
+
{ keys: 'p', label: 'set model price' },
|
|
487
568
|
], DEFAULT_PANEL_PALETTE);
|
|
488
569
|
if (agentList.length > 0) {
|
|
489
570
|
const planCost = agentList.reduce((sum, a) => sum + a.cost, 0);
|
|
@@ -562,7 +643,7 @@ export class CostTrackerPanel extends BasePanel {
|
|
|
562
643
|
width,
|
|
563
644
|
' No agents spawned this session',
|
|
564
645
|
'Agent-level cost estimates appear here once delegated or background agents start running.',
|
|
565
|
-
//
|
|
646
|
+
// 'b' already opens the in-panel budget-entry field (see
|
|
566
647
|
// handleInput/handleBudgetEntryInput above) and is advertised in
|
|
567
648
|
// the footer's 'b: set budget' hint, so the printed
|
|
568
649
|
// '/cost budget <usd>' command was a redundant action substitute.
|
|
@@ -626,4 +707,40 @@ export class CostTrackerPanel extends BasePanel {
|
|
|
626
707
|
return workspace.slice(0, height);
|
|
627
708
|
}
|
|
628
709
|
|
|
710
|
+
// Non-masked entry for the 'p' manual-price key. Two USD-per-1M-token
|
|
711
|
+
// amounts (input,output); persists to pricing.modelPrices for the session's
|
|
712
|
+
// provider:model live. A model without a provider prefix cannot carry a
|
|
713
|
+
// manual price (the settings key is keyed provider:model) — the prompt says
|
|
714
|
+
// so instead of accepting a value it could not store.
|
|
715
|
+
private renderPriceEntryPrompt(width: number, height: number): Line[] {
|
|
716
|
+
const editable = this.canEditSessionModelPrice();
|
|
717
|
+
const draft = this.priceEntry ?? '';
|
|
718
|
+
const display = `${draft}█`;
|
|
719
|
+
const promptLines: Line[] = editable
|
|
720
|
+
? [
|
|
721
|
+
buildPanelLine(width, [[` Set your manual price for ${this.sessionModel} (USD per 1M tokens).`, C.label]]),
|
|
722
|
+
buildPanelLine(width, [[' Format: input,output — for example 3.00,15.00', C.dim]]),
|
|
723
|
+
buildPanelLine(width, [['', C.label]]),
|
|
724
|
+
buildPanelLine(width, [[' Price ', C.label], [display, C.cost]]),
|
|
725
|
+
buildPanelLine(width, [['', C.label]]),
|
|
726
|
+
buildPanelLine(width, [[' [Enter] Save [Esc] Cancel [Backspace] Delete char', C.dim]]),
|
|
727
|
+
]
|
|
728
|
+
: [
|
|
729
|
+
buildPanelLine(width, [[` The current model (${this.sessionModel}) has no provider prefix, so a`, C.label]]),
|
|
730
|
+
buildPanelLine(width, [[' manual price cannot be stored for it (prices are keyed provider:model).', C.label]]),
|
|
731
|
+
buildPanelLine(width, [['', C.label]]),
|
|
732
|
+
buildPanelLine(width, [[' [Esc] Close', C.dim]]),
|
|
733
|
+
];
|
|
734
|
+
const workspace = buildPanelWorkspace(width, height, {
|
|
735
|
+
title: ' Cost Tracker — Model Price',
|
|
736
|
+
intro: editable
|
|
737
|
+
? 'Your price wins over provider and catalog prices, immediately and everywhere.'
|
|
738
|
+
: 'Manual prices are stored per provider:model.',
|
|
739
|
+
sections: [{ lines: promptLines }],
|
|
740
|
+
palette: DEFAULT_PANEL_PALETTE,
|
|
741
|
+
});
|
|
742
|
+
while (workspace.length < height) workspace.push(createEmptyLine(width));
|
|
743
|
+
return workspace.slice(0, height);
|
|
744
|
+
}
|
|
745
|
+
|
|
629
746
|
}
|
package/src/panels/diff-panel.ts
CHANGED
|
@@ -27,10 +27,10 @@ import {
|
|
|
27
27
|
// that shares it, including the workspace-chrome aliases (info/dim/value/
|
|
28
28
|
// empty) so the raw-hex count never grows. The title band itself is NOT
|
|
29
29
|
// overridden — buildPanelWorkspace always falls back to the canonical
|
|
30
|
-
// DEFAULT_PANEL_PALETTE.headerBg (
|
|
30
|
+
// DEFAULT_PANEL_PALETTE.headerBg (one title band everywhere).
|
|
31
31
|
// ---------------------------------------------------------------------------
|
|
32
32
|
|
|
33
|
-
// Hunk blue is the shared DIFF_TONES token
|
|
33
|
+
// Hunk blue is the shared DIFF_TONES token — diff-view.ts (conversation)
|
|
34
34
|
// and git-panel.ts's inline diff converge onto this file's pre-existing value.
|
|
35
35
|
const HUNK_BLUE: string = DIFF_TONES.hunk;
|
|
36
36
|
// Context rows and line-number gutter use the shared theme's muted/dim
|
|
@@ -39,7 +39,7 @@ const CONTEXT_GRAY = UI_TONES.fg.muted;
|
|
|
39
39
|
const FILENAME_WHITE = '#ffffff';
|
|
40
40
|
// Add/del text colors are the shared DIFF_TONES tokens, whose values ARE this
|
|
41
41
|
// panel's shipped colors — this panel is the reference diff look (diff-view
|
|
42
|
-
// was unwired dead code until
|
|
42
|
+
// was unwired dead code until, so "majority of surfaces" was a mirage);
|
|
43
43
|
// the conversation surface converges onto these, not the reverse.
|
|
44
44
|
const ADD_GREEN: string = DIFF_TONES.add;
|
|
45
45
|
const ADD_BG = '#001a0d';
|
|
@@ -521,7 +521,7 @@ export class DiffPanel extends BasePanel {
|
|
|
521
521
|
}
|
|
522
522
|
}
|
|
523
523
|
|
|
524
|
-
//
|
|
524
|
+
// (the purge): 'o' used to open the currently selected file in the
|
|
525
525
|
// preview panel via a staged pendingOpenPreview flag + a
|
|
526
526
|
// handlePanelIntegrationAction cross-panel hook (the same bridge
|
|
527
527
|
// FileExplorerPanel used). 'preview' is DELETE-disposition with no
|
|
@@ -597,7 +597,7 @@ export class DiffPanel extends BasePanel {
|
|
|
597
597
|
width,
|
|
598
598
|
' No diff to display.',
|
|
599
599
|
'Load a git diff or select a changed file to populate the workspace. w=working h=HEAD s=staged self-load right here.',
|
|
600
|
-
//
|
|
600
|
+
// corrected — bare /diff loads files changed *this
|
|
601
601
|
// session* (falling back to the full HEAD diff when none are
|
|
602
602
|
// tracked yet), not the working-tree diff the w key already
|
|
603
603
|
// loads in-panel; the old summary text described the wrong
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* EvalRegistry — holds the latest evaluation harness run state.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* (the purge): extracted out of eval-panel.ts. 'eval' was
|
|
5
5
|
* DELETE-disposition (no surviving human surface — the evaluation harness
|
|
6
6
|
* is driven and reviewed via the `/eval` CLI command, input/commands/eval.ts)
|
|
7
7
|
* but this registry is still a live consumer of `/eval run` output, so it
|
|
8
8
|
* survives as a standalone read-model rather than being deleted with the
|
|
9
|
-
* view. See .goodvibes/audit/2026-07-04-wave6-briefs.json
|
|
9
|
+
* view. See .goodvibes/audit/2026-07-04-wave6-briefs.json.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { EvalSuiteResult, EvalGateResult } from '@/runtime/index.ts';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// fleet-deep-link.ts —
|
|
2
|
+
// fleet-deep-link.ts — item 4.
|
|
3
3
|
//
|
|
4
4
|
// PanelManager.open('fleet', pane, target) hands FleetPanel a
|
|
5
5
|
// PanelDeepLinkTarget (a process id + optional ProcessKind) so a cross-panel
|