@pellux/goodvibes-tui 1.1.0 → 1.9.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 +85 -21
- package/README.md +28 -18
- package/docs/foundation-artifacts/operator-contract.json +4045 -1763
- package/package.json +2 -2
- package/src/audio/spoken-turn-controller.ts +12 -2
- package/src/audio/spoken-turn-wiring.ts +2 -1
- package/src/cli/help.ts +8 -1
- package/src/cli/service-posture.ts +2 -1
- package/src/cli/status.ts +2 -1
- package/src/cli/surface-command.ts +2 -2
- package/src/core/alert-gating.ts +67 -0
- package/src/core/approval-alert.ts +72 -0
- package/src/core/budget-breach-notifier.ts +106 -0
- package/src/core/composer-state.ts +11 -3
- package/src/core/conversation-line-cache.ts +27 -3
- package/src/core/conversation-rendering.ts +90 -14
- package/src/core/conversation.ts +18 -0
- package/src/core/focus-tracker.ts +41 -0
- package/src/core/long-task-notifier.ts +33 -6
- package/src/core/stream-event-wiring.ts +20 -1
- package/src/core/system-message-noise.ts +87 -0
- package/src/core/system-message-router.ts +104 -51
- package/src/core/turn-cancellation.ts +25 -0
- package/src/core/turn-event-wiring.ts +72 -3
- package/src/daemon/cli.ts +29 -2
- package/src/daemon/handlers/register.ts +8 -1
- package/src/daemon/service-commands.ts +329 -0
- package/src/export/cost-utils.ts +36 -0
- package/src/input/autocomplete.ts +27 -1
- package/src/input/command-registry.ts +84 -5
- package/src/input/commands/checkpoint-runtime.ts +280 -0
- package/src/input/commands/codebase-runtime.ts +232 -0
- package/src/input/commands/config.ts +43 -3
- package/src/input/commands/eval.ts +1 -1
- package/src/input/commands/health-runtime.ts +10 -2
- package/src/input/commands/image-runtime.ts +112 -0
- package/src/input/commands/intelligence-runtime.ts +11 -1
- package/src/input/commands/local-auth-runtime.ts +4 -1
- package/src/input/commands/local-runtime.ts +9 -3
- package/src/input/commands/marketplace-runtime.ts +2 -2
- package/src/input/commands/memory.ts +73 -35
- package/src/input/commands/operator-panel-runtime.ts +71 -31
- package/src/input/commands/planning-runtime.ts +116 -4
- package/src/input/commands/platform-sandbox-runtime.ts +1 -6
- package/src/input/commands/plugin-runtime.ts +2 -2
- package/src/input/commands/policy-dispatch.ts +21 -0
- package/src/input/commands/provider-accounts-runtime.ts +1 -1
- package/src/input/commands/qrcode-runtime.ts +26 -6
- package/src/input/commands/recall-review.ts +35 -0
- package/src/input/commands/remote-runtime-setup.ts +5 -3
- package/src/input/commands/remote-runtime.ts +3 -3
- package/src/input/commands/runtime-services.ts +54 -13
- package/src/input/commands/services-runtime.ts +1 -1
- package/src/input/commands/session-content.ts +20 -9
- package/src/input/commands/session-workflow.ts +16 -1
- package/src/input/commands/settings-sync-runtime.ts +16 -4
- package/src/input/commands/shell-core.ts +25 -8
- package/src/input/commands/skills-runtime.ts +2 -8
- package/src/input/commands/subscription-runtime.ts +2 -2
- package/src/input/commands/test-runtime.ts +277 -0
- package/src/input/commands/websearch-runtime.ts +101 -0
- package/src/input/commands/work-plan-runtime.ts +36 -10
- package/src/input/commands/workstream-runtime.ts +488 -0
- package/src/input/commands.ts +12 -0
- package/src/input/config-modal-types.ts +175 -0
- package/src/input/config-modal.ts +592 -0
- package/src/input/feed-context-factory.ts +10 -8
- package/src/input/handler-command-route.ts +37 -20
- package/src/input/handler-content-actions.ts +17 -2
- package/src/input/handler-feed-routes.ts +74 -114
- package/src/input/handler-feed.ts +79 -27
- package/src/input/handler-interactions.ts +1 -3
- package/src/input/handler-modal-routes.ts +136 -6
- package/src/input/handler-modal-stack.ts +14 -7
- package/src/input/handler-modal-token-routes.ts +16 -49
- package/src/input/handler-onboarding-daemon-adopt.ts +149 -0
- package/src/input/handler-onboarding.ts +71 -59
- package/src/input/handler-picker-routes.ts +26 -102
- package/src/input/handler-shortcuts.ts +74 -14
- package/src/input/handler-types.ts +2 -6
- package/src/input/handler-ui-state.ts +10 -22
- package/src/input/handler.ts +12 -29
- package/src/input/keybindings.ts +23 -8
- package/src/input/model-picker-types.ts +24 -6
- package/src/input/model-picker.ts +77 -2
- package/src/input/onboarding/onboarding-runtime-status.ts +10 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +8 -1
- package/src/input/onboarding/onboarding-wizard-constants.ts +4 -1
- package/src/input/onboarding/onboarding-wizard-network-adopt.ts +136 -0
- package/src/input/onboarding/onboarding-wizard-steps.ts +9 -6
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/panel-integration-actions.ts +9 -170
- package/src/input/panel-mouse-geometry.ts +97 -0
- package/src/input/panel-paste-flood-guard.ts +86 -0
- package/src/input/selection-modal.ts +11 -0
- package/src/input/session-picker-modal.ts +44 -4
- package/src/input/settings-modal-data.ts +146 -2
- package/src/input/settings-modal-mutations.ts +6 -4
- package/src/input/settings-modal-types.ts +4 -2
- package/src/main.ts +49 -51
- package/src/panels/agent-inspector-shared.ts +2 -1
- package/src/panels/base-panel.ts +22 -1
- package/src/panels/builtin/agent.ts +21 -107
- package/src/panels/builtin/development.ts +15 -61
- package/src/panels/builtin/knowledge.ts +8 -32
- package/src/panels/builtin/operations.ts +84 -428
- package/src/panels/builtin/session.ts +21 -112
- package/src/panels/builtin/shared.ts +18 -46
- package/src/panels/builtin-modals.ts +218 -0
- package/src/panels/builtin-panels.ts +5 -0
- package/src/panels/cost-tracker-panel.ts +36 -10
- package/src/panels/diff-panel.ts +12 -43
- package/src/panels/eval-registry.ts +60 -0
- package/src/panels/fleet-deep-link.ts +31 -0
- package/src/panels/fleet-panel-format.ts +62 -0
- package/src/panels/fleet-panel-worktree-detail.ts +48 -0
- package/src/panels/fleet-panel.ts +758 -0
- package/src/panels/fleet-read-model.ts +520 -0
- package/src/panels/fleet-steer.ts +125 -0
- package/src/panels/fleet-stop.ts +153 -0
- package/src/panels/fleet-tabs.ts +230 -0
- package/src/panels/fleet-transcript.ts +356 -0
- package/src/panels/index.ts +7 -31
- package/src/panels/modals/hooks-modal.ts +187 -0
- package/src/panels/modals/keybindings-modal.ts +166 -0
- package/src/panels/modals/knowledge-modal.ts +158 -0
- package/src/panels/modals/local-auth-modal.ts +132 -0
- package/src/panels/modals/marketplace-modal.ts +218 -0
- package/src/panels/modals/memory-modal.ts +180 -0
- package/src/panels/modals/modal-surface-helpers.ts +54 -0
- package/src/panels/modals/modal-theme.ts +42 -0
- package/src/panels/modals/pairing-modal.ts +163 -0
- package/src/panels/modals/planning-modal.ts +304 -0
- package/src/panels/modals/plugins-modal.ts +174 -0
- package/src/panels/modals/policy-modal.ts +256 -0
- package/src/panels/modals/provider-health-modal.ts +136 -0
- package/src/panels/modals/remote-modal.ts +115 -0
- package/src/panels/modals/sandbox-modal.ts +150 -0
- package/src/panels/modals/security-modal.ts +217 -0
- package/src/panels/modals/services-modal.ts +179 -0
- package/src/panels/modals/settings-sync-modal.ts +142 -0
- package/src/panels/modals/skills-modal.ts +189 -0
- package/src/panels/modals/subscription-modal.ts +172 -0
- package/src/panels/modals/work-plan-modal.ts +177 -0
- package/src/panels/panel-confirm-overlay.ts +72 -0
- package/src/panels/panel-manager.ts +123 -9
- package/src/panels/polish-core.ts +38 -25
- package/src/panels/project-planning-answer-actions.ts +8 -11
- package/src/panels/skills-panel.ts +7 -51
- package/src/panels/types.ts +37 -0
- package/src/permissions/hunk-selection.ts +179 -0
- package/src/permissions/prompt.ts +216 -13
- package/src/renderer/autocomplete-overlay.ts +28 -2
- package/src/renderer/compaction-history-modal.ts +19 -3
- package/src/renderer/compaction-preview.ts +13 -2
- package/src/renderer/compaction-quality.ts +100 -0
- package/src/renderer/compositor.ts +2 -3
- package/src/renderer/config-modal.ts +95 -0
- package/src/renderer/conversation-overlays.ts +10 -17
- package/src/renderer/fleet-tab-strip.ts +56 -0
- package/src/renderer/footer-tips.ts +15 -3
- package/src/renderer/fullscreen-primitives.ts +32 -22
- package/src/renderer/git-status.ts +43 -1
- package/src/renderer/help-overlay.ts +2 -2
- package/src/renderer/layout.ts +0 -4
- package/src/renderer/markdown.ts +7 -3
- package/src/renderer/modal-factory.ts +25 -20
- package/src/renderer/model-workspace.ts +62 -4
- package/src/renderer/overlay-box.ts +21 -17
- package/src/renderer/panel-workspace-bar.ts +8 -2
- package/src/renderer/process-indicator.ts +14 -3
- package/src/renderer/selection-modal-overlay.ts +6 -1
- package/src/renderer/session-picker-modal.ts +196 -3
- package/src/renderer/settings-modal-helpers.ts +2 -0
- package/src/renderer/settings-modal.ts +7 -0
- package/src/renderer/shell-surface.ts +8 -1
- package/src/renderer/status-glyphs.ts +14 -15
- package/src/renderer/system-message.ts +15 -3
- package/src/renderer/terminal-bg-probe.ts +339 -0
- package/src/renderer/terminal-escapes.ts +20 -0
- package/src/renderer/theme-mode-config.ts +67 -0
- package/src/renderer/theme.ts +91 -1
- package/src/renderer/thinking.ts +11 -3
- package/src/renderer/tool-call.ts +15 -9
- package/src/renderer/tool-result-summary.ts +148 -0
- package/src/renderer/turn-injection.ts +133 -0
- package/src/renderer/ui-factory.ts +154 -85
- package/src/renderer/ui-primitives.ts +30 -129
- package/src/runtime/bootstrap-command-context.ts +27 -1
- package/src/runtime/bootstrap-command-parts.ts +41 -10
- package/src/runtime/bootstrap-core.ts +47 -15
- package/src/runtime/bootstrap-hook-bridge.ts +7 -0
- package/src/runtime/bootstrap-shell.ts +48 -17
- package/src/runtime/bootstrap.ts +129 -22
- package/src/runtime/code-index-services.ts +135 -0
- package/src/runtime/legacy-daemon-migration.ts +516 -0
- package/src/runtime/memory-fold.ts +26 -0
- package/src/runtime/onboarding/derivation.ts +7 -2
- package/src/runtime/onboarding/snapshot.ts +27 -1
- package/src/runtime/onboarding/types.ts +31 -1
- package/src/runtime/operator-token-cleanup.ts +82 -1
- package/src/runtime/orchestrator-core-services.ts +59 -0
- package/src/runtime/process-lifecycle.ts +3 -1
- package/src/runtime/resume-notice.ts +209 -0
- package/src/runtime/services.ts +98 -46
- package/src/runtime/session-inbound-inputs.ts +252 -0
- package/src/runtime/session-spine-transport.ts +64 -0
- package/src/runtime/terminal-output-guard.ts +15 -8
- package/src/runtime/ui-services.ts +27 -3
- package/src/runtime/workstream-services.ts +327 -0
- package/src/runtime/wrfc-persistence.ts +124 -17
- package/src/shell/blocking-input.ts +68 -4
- package/src/shell/recovery-input-helpers.ts +170 -1
- package/src/shell/ui-openers.ts +171 -26
- package/src/utils/format-duration.ts +8 -18
- package/src/utils/splash-lines.ts +1 -1
- package/src/utils/terminal-width.ts +52 -0
- package/src/version.ts +1 -1
- package/src/panels/agent-inspector-panel.ts +0 -786
- package/src/panels/approval-panel.ts +0 -252
- package/src/panels/automation-control-panel.ts +0 -479
- package/src/panels/cockpit-panel.ts +0 -481
- package/src/panels/cockpit-read-model.ts +0 -238
- package/src/panels/communication-panel.ts +0 -256
- package/src/panels/control-plane-panel.ts +0 -470
- package/src/panels/debug-panel.ts +0 -615
- package/src/panels/docs-panel.ts +0 -384
- package/src/panels/eval-panel.ts +0 -627
- package/src/panels/file-explorer-panel.ts +0 -673
- package/src/panels/file-preview-panel.ts +0 -517
- package/src/panels/hooks-panel.ts +0 -401
- package/src/panels/incident-review-panel.ts +0 -406
- package/src/panels/intelligence-panel.ts +0 -383
- package/src/panels/knowledge-graph-panel.ts +0 -515
- package/src/panels/marketplace-panel.ts +0 -399
- package/src/panels/memory-panel.ts +0 -558
- package/src/panels/ops-control-panel.ts +0 -329
- package/src/panels/ops-strategy-panel.ts +0 -321
- package/src/panels/orchestration-panel.ts +0 -465
- package/src/panels/panel-list-panel.ts +0 -566
- package/src/panels/plan-dashboard-panel.ts +0 -707
- package/src/panels/policy-panel.ts +0 -517
- package/src/panels/project-planning-panel.ts +0 -731
- package/src/panels/provider-health-panel.ts +0 -678
- package/src/panels/provider-health-tracker.ts +0 -310
- package/src/panels/provider-health-views.ts +0 -567
- package/src/panels/qr-panel.ts +0 -280
- package/src/panels/remote-panel.ts +0 -534
- package/src/panels/routes-panel.ts +0 -241
- package/src/panels/sandbox-panel.ts +0 -456
- package/src/panels/security-panel.ts +0 -447
- package/src/panels/services-panel.ts +0 -329
- package/src/panels/session-browser-panel.ts +0 -496
- package/src/panels/settings-sync-panel.ts +0 -398
- package/src/panels/subscription-panel.ts +0 -342
- package/src/panels/symbol-outline-panel.ts +0 -619
- package/src/panels/system-messages-panel.ts +0 -364
- package/src/panels/tasks-panel.ts +0 -608
- package/src/panels/thinking-panel.ts +0 -333
- package/src/panels/tool-inspector-panel.ts +0 -537
- package/src/panels/work-plan-panel.ts +0 -540
- package/src/panels/worktree-panel.ts +0 -360
- package/src/panels/wrfc-panel.ts +0 -790
- package/src/renderer/agent-detail-modal.ts +0 -466
- package/src/renderer/live-tail-modal.ts +0 -156
- package/src/renderer/process-modal.ts +0 -671
- package/src/renderer/qr-renderer.ts +0 -120
|
@@ -1,678 +0,0 @@
|
|
|
1
|
-
import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
2
|
-
import { BasePanel } from './base-panel.ts';
|
|
3
|
-
import type { Line } from '../types/grid.ts';
|
|
4
|
-
import type { ModelDomainState, ProviderEvent, TurnEvent } from '@/runtime/index.ts';
|
|
5
|
-
import { createInitialModelState, evaluateSessionMaintenance } from '@/runtime/index.ts';
|
|
6
|
-
import type { UiEventFeed } from '../runtime/ui-events.ts';
|
|
7
|
-
import {
|
|
8
|
-
type ProviderRuntimeInspectionQuery,
|
|
9
|
-
} from '../runtime/ui-service-queries.ts';
|
|
10
|
-
import {
|
|
11
|
-
ProviderHealthTracker,
|
|
12
|
-
type ProviderHealthMeta,
|
|
13
|
-
} from './provider-health-tracker.ts';
|
|
14
|
-
import {
|
|
15
|
-
buildAccountPosture,
|
|
16
|
-
type ProviderAccountPosture,
|
|
17
|
-
} from './provider-health-routes.ts';
|
|
18
|
-
import {
|
|
19
|
-
buildProviderHealthDomainSummaries,
|
|
20
|
-
type HealthDomainSummary,
|
|
21
|
-
} from './provider-health-domains.ts';
|
|
22
|
-
import {
|
|
23
|
-
ProviderHealthDataProvider,
|
|
24
|
-
type FallbackChainData,
|
|
25
|
-
type ProviderHealthEntry,
|
|
26
|
-
} from '../runtime/ui/provider-health/index.ts';
|
|
27
|
-
import type { PanelIntegrationContext } from './types.ts';
|
|
28
|
-
import type {
|
|
29
|
-
UiContinuitySnapshot,
|
|
30
|
-
UiIntelligenceSnapshot,
|
|
31
|
-
UiLocalAuthSnapshot,
|
|
32
|
-
UiProvidersSnapshot,
|
|
33
|
-
UiReadModel,
|
|
34
|
-
UiRemoteSnapshot,
|
|
35
|
-
UiSecuritySnapshot,
|
|
36
|
-
UiSessionSnapshot,
|
|
37
|
-
UiSettingsSnapshot,
|
|
38
|
-
UiWorktreeSnapshot,
|
|
39
|
-
} from '../runtime/ui-read-models.ts';
|
|
40
|
-
import {
|
|
41
|
-
buildEmptyState,
|
|
42
|
-
buildKeyboardHints,
|
|
43
|
-
buildPanelWorkspace,
|
|
44
|
-
buildSummaryBlock,
|
|
45
|
-
DEFAULT_PANEL_PALETTE,
|
|
46
|
-
extendPalette,
|
|
47
|
-
resolvePrimaryScrollableSection,
|
|
48
|
-
type PanelWorkspaceSection,
|
|
49
|
-
} from './polish.ts';
|
|
50
|
-
import {
|
|
51
|
-
buildChainLines,
|
|
52
|
-
buildDomainLines,
|
|
53
|
-
buildMaintenanceLines,
|
|
54
|
-
buildPostureLines,
|
|
55
|
-
buildProviderColumnHeader,
|
|
56
|
-
buildProviderRow,
|
|
57
|
-
buildRouteColumnHeader,
|
|
58
|
-
buildRouteViewLines,
|
|
59
|
-
buildSelectedDetailSection,
|
|
60
|
-
} from './provider-health-views.ts';
|
|
61
|
-
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
// Types
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
|
-
|
|
66
|
-
export interface ProviderHealthPanelDeps {
|
|
67
|
-
readonly configManager: Pick<ConfigManager, 'get'>;
|
|
68
|
-
readonly turnEvents: UiEventFeed<TurnEvent>;
|
|
69
|
-
readonly providerEvents: UiEventFeed<ProviderEvent>;
|
|
70
|
-
readonly providers: UiReadModel<UiProvidersSnapshot>;
|
|
71
|
-
readonly session: UiReadModel<UiSessionSnapshot>;
|
|
72
|
-
readonly security: UiReadModel<UiSecuritySnapshot>;
|
|
73
|
-
readonly localAuth: UiReadModel<UiLocalAuthSnapshot>;
|
|
74
|
-
readonly settings: UiReadModel<UiSettingsSnapshot>;
|
|
75
|
-
readonly remote: UiReadModel<UiRemoteSnapshot>;
|
|
76
|
-
readonly intelligence: UiReadModel<UiIntelligenceSnapshot>;
|
|
77
|
-
readonly continuity: UiReadModel<UiContinuitySnapshot>;
|
|
78
|
-
readonly worktrees: UiReadModel<UiWorktreeSnapshot>;
|
|
79
|
-
/**
|
|
80
|
-
* Model-domain access wired from the runtime store at the composition root
|
|
81
|
-
* (selectModel over RuntimeStore). Drives fallback-chain rendering and
|
|
82
|
-
* TURN_ERROR attribution to the active provider.
|
|
83
|
-
*/
|
|
84
|
-
readonly modelState?: {
|
|
85
|
-
readonly get: () => ModelDomainState;
|
|
86
|
-
readonly subscribe: (listener: () => void) => () => void;
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
type ConsoleView = 'providers' | 'routes' | 'domains';
|
|
91
|
-
|
|
92
|
-
const CONSOLE_VIEWS: readonly ConsoleView[] = ['providers', 'routes', 'domains'] as const;
|
|
93
|
-
|
|
94
|
-
// Base chrome plus console accents (domain accents only — hex ratchet).
|
|
95
|
-
const C = extendPalette(DEFAULT_PANEL_PALETTE, {
|
|
96
|
-
title: '#00ffff',
|
|
97
|
-
unknown: '244',
|
|
98
|
-
rowSelectBg: '#111827',
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const INTRO = 'Provider console: status, latency timelines, error attribution, auth routes, and fallback posture.';
|
|
102
|
-
|
|
103
|
-
// ---------------------------------------------------------------------------
|
|
104
|
-
// ProviderHealthPanel — the merged provider console (WO-112)
|
|
105
|
-
// ---------------------------------------------------------------------------
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Single provider console. Absorbs the retired providers (stats) and accounts
|
|
109
|
-
* panels:
|
|
110
|
-
* - Status, latency avg/p95, error attribution, sparkline timelines, and
|
|
111
|
-
* per-provider token/cost totals in one table (ProviderHealthDataProvider).
|
|
112
|
-
* - Fallback chain with current node and fallover count.
|
|
113
|
-
* - Auth routes with per-route freshness, issues, and repair hints
|
|
114
|
-
* (ProviderRuntimeInspectionQuery.inspectAll() is the single route source).
|
|
115
|
-
* - Repair Domains + Session Maintenance as a secondary 't' view.
|
|
116
|
-
* - Enter dispatches '/accounts repair <provider>' through the panel
|
|
117
|
-
* integration context; r forces a posture refresh.
|
|
118
|
-
*/
|
|
119
|
-
export class ProviderHealthPanel extends BasePanel {
|
|
120
|
-
private _unsubs: Array<() => void> = [];
|
|
121
|
-
private _tickTimerId: ReturnType<typeof setInterval> | null = null;
|
|
122
|
-
private _selectedIndex = 0;
|
|
123
|
-
private _scrollOffset = 0;
|
|
124
|
-
private _view: ConsoleView = 'providers';
|
|
125
|
-
private _accountRecords = new Map<string, ProviderAccountPosture>();
|
|
126
|
-
private _accountRefreshAt = 0;
|
|
127
|
-
private _accountLoading = false;
|
|
128
|
-
private _inflightProvider: string | null = null;
|
|
129
|
-
private _lastResponseProvider: string | null = null;
|
|
130
|
-
private _unattributedError: string | null = null;
|
|
131
|
-
private _modelState: ModelDomainState;
|
|
132
|
-
private readonly _dataProvider: ProviderHealthDataProvider;
|
|
133
|
-
private readonly providerHealthTracker = new ProviderHealthTracker();
|
|
134
|
-
|
|
135
|
-
constructor(
|
|
136
|
-
private readonly providerRuntime: ProviderRuntimeInspectionQuery,
|
|
137
|
-
private readonly deps: ProviderHealthPanelDeps,
|
|
138
|
-
private readonly requestRender: () => void = () => {},
|
|
139
|
-
) {
|
|
140
|
-
super('provider-health', 'Health', 'N', 'providers');
|
|
141
|
-
this._modelState = deps.modelState?.get() ?? this._syntheticModelState();
|
|
142
|
-
this._dataProvider = new ProviderHealthDataProvider(this._buildHealthState(), this._modelState);
|
|
143
|
-
this._subscribe();
|
|
144
|
-
void this._refreshAccountPosture(true);
|
|
145
|
-
// Background 30s posture refresh (auth routes go stale otherwise); cleared on destroy.
|
|
146
|
-
this.registerTimer(setInterval(() => { void this._refreshAccountPosture(); }, 30_000));
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// -------------------------------------------------------------------------
|
|
150
|
-
// Event subscription
|
|
151
|
-
// -------------------------------------------------------------------------
|
|
152
|
-
|
|
153
|
-
private _subscribe(): void {
|
|
154
|
-
this._unsubs.push(
|
|
155
|
-
this.deps.turnEvents.on('TURN_SUBMITTED', () => {
|
|
156
|
-
this.providerHealthTracker.onTurnStart();
|
|
157
|
-
}),
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
this._unsubs.push(
|
|
161
|
-
this.deps.turnEvents.on('STREAM_START', () => {
|
|
162
|
-
this.providerHealthTracker.onStreamStart();
|
|
163
|
-
}),
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
// The provider named on the in-flight LLM request is the authoritative
|
|
167
|
-
// attribution target when the turn subsequently errors.
|
|
168
|
-
this._unsubs.push(
|
|
169
|
-
this.deps.turnEvents.on('LLM_REQUEST_STARTED', (payload) => {
|
|
170
|
-
this._inflightProvider = payload.provider;
|
|
171
|
-
}),
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
this._unsubs.push(
|
|
175
|
-
this.deps.turnEvents.on('LLM_RESPONSE_RECEIVED', (payload) => {
|
|
176
|
-
this.providerHealthTracker.onLlmResponse(payload.provider, {
|
|
177
|
-
model: payload.model,
|
|
178
|
-
inputTokens: payload.inputTokens,
|
|
179
|
-
outputTokens: payload.outputTokens,
|
|
180
|
-
...(payload.cacheReadTokens !== undefined ? { cacheReadTokens: payload.cacheReadTokens } : {}),
|
|
181
|
-
...(payload.cacheWriteTokens !== undefined ? { cacheWriteTokens: payload.cacheWriteTokens } : {}),
|
|
182
|
-
});
|
|
183
|
-
this._lastResponseProvider = payload.provider;
|
|
184
|
-
this._pushHealthState();
|
|
185
|
-
this._markDirtyAndRender();
|
|
186
|
-
}),
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
this._unsubs.push(
|
|
190
|
-
this.deps.turnEvents.on('TURN_ERROR', (payload) => {
|
|
191
|
-
const providerId = this._resolveActiveProviderId();
|
|
192
|
-
if (providerId) {
|
|
193
|
-
this.providerHealthTracker.onTurnError(payload.error, providerId);
|
|
194
|
-
this._unattributedError = null;
|
|
195
|
-
} else {
|
|
196
|
-
// No provider is resolvable (nothing registered yet) — surface the
|
|
197
|
-
// error in the posture block instead of inventing a phantom row.
|
|
198
|
-
this._unattributedError = payload.error.slice(0, 120);
|
|
199
|
-
}
|
|
200
|
-
this._inflightProvider = null;
|
|
201
|
-
this._pushHealthState();
|
|
202
|
-
this._markDirtyAndRender();
|
|
203
|
-
}),
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
this._unsubs.push(
|
|
207
|
-
this.deps.turnEvents.on('TURN_COMPLETED', () => {
|
|
208
|
-
this._inflightProvider = null;
|
|
209
|
-
}),
|
|
210
|
-
);
|
|
211
|
-
|
|
212
|
-
this._unsubs.push(
|
|
213
|
-
this.deps.turnEvents.on('TURN_CANCEL', () => {
|
|
214
|
-
this._inflightProvider = null;
|
|
215
|
-
}),
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
this._unsubs.push(
|
|
219
|
-
this.deps.providerEvents.on('PROVIDERS_CHANGED', () => {
|
|
220
|
-
this.providerHealthTracker.onProvidersChanged(this._knownProviders());
|
|
221
|
-
void this._refreshAccountPosture(true);
|
|
222
|
-
this._pushHealthState();
|
|
223
|
-
this._markDirtyAndRender();
|
|
224
|
-
}),
|
|
225
|
-
);
|
|
226
|
-
|
|
227
|
-
if (this.deps.modelState) {
|
|
228
|
-
const modelState = this.deps.modelState;
|
|
229
|
-
this._unsubs.push(modelState.subscribe(() => {
|
|
230
|
-
const next = modelState.get();
|
|
231
|
-
if (next !== this._modelState) {
|
|
232
|
-
this._modelState = next;
|
|
233
|
-
this._dataProvider.updateModelState(next);
|
|
234
|
-
this._markDirtyAndRender();
|
|
235
|
-
}
|
|
236
|
-
}));
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
for (const readModel of [
|
|
240
|
-
this.deps.providers,
|
|
241
|
-
this.deps.session,
|
|
242
|
-
this.deps.security,
|
|
243
|
-
this.deps.localAuth,
|
|
244
|
-
this.deps.settings,
|
|
245
|
-
this.deps.remote,
|
|
246
|
-
this.deps.intelligence,
|
|
247
|
-
this.deps.continuity,
|
|
248
|
-
this.deps.worktrees,
|
|
249
|
-
] as const) {
|
|
250
|
-
this._unsubs.push(readModel.subscribe(() => this._markDirtyAndRender()));
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
private _markDirtyAndRender(): void {
|
|
255
|
-
this.markDirty();
|
|
256
|
-
this.requestRender();
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// -------------------------------------------------------------------------
|
|
260
|
-
// Lifecycle
|
|
261
|
-
// -------------------------------------------------------------------------
|
|
262
|
-
|
|
263
|
-
override onActivate(): void {
|
|
264
|
-
super.onActivate();
|
|
265
|
-
this.markDirty();
|
|
266
|
-
void this._refreshAccountPosture(true);
|
|
267
|
-
this._startTickTimer();
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
override onDeactivate(): void {
|
|
271
|
-
super.onDeactivate();
|
|
272
|
-
// Stop the per-second display tick while hidden (TokenBudgetPanel pattern);
|
|
273
|
-
// the 30s posture refresh keeps running so data stays warm for preload.
|
|
274
|
-
this._stopTickTimer();
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
override onDestroy(): void {
|
|
278
|
-
super.onDestroy();
|
|
279
|
-
this._tickTimerId = null;
|
|
280
|
-
this._dataProvider.dispose();
|
|
281
|
-
for (const unsub of this._unsubs) unsub();
|
|
282
|
-
this._unsubs = [];
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
private _startTickTimer(): void {
|
|
286
|
-
if (this._tickTimerId !== null) return;
|
|
287
|
-
this._tickTimerId = this.registerTimer(setInterval(() => {
|
|
288
|
-
this.markDirty();
|
|
289
|
-
this.requestRender();
|
|
290
|
-
}, 1_000));
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
private _stopTickTimer(): void {
|
|
294
|
-
if (this._tickTimerId !== null) {
|
|
295
|
-
this.clearTimer(this._tickTimerId);
|
|
296
|
-
this._tickTimerId = null;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// -------------------------------------------------------------------------
|
|
301
|
-
// Input
|
|
302
|
-
// -------------------------------------------------------------------------
|
|
303
|
-
|
|
304
|
-
handleInput(key: string): boolean {
|
|
305
|
-
if (key === 't' || key === 'tab') {
|
|
306
|
-
const next = CONSOLE_VIEWS[(CONSOLE_VIEWS.indexOf(this._view) + 1) % CONSOLE_VIEWS.length];
|
|
307
|
-
this._view = next ?? 'providers';
|
|
308
|
-
this._scrollOffset = 0;
|
|
309
|
-
this.markDirty();
|
|
310
|
-
return true;
|
|
311
|
-
}
|
|
312
|
-
if (key === 'r') {
|
|
313
|
-
void this._refreshAccountPosture(true);
|
|
314
|
-
this.markDirty();
|
|
315
|
-
return true;
|
|
316
|
-
}
|
|
317
|
-
const providers = this._knownProviders();
|
|
318
|
-
if (providers.length === 0) return false;
|
|
319
|
-
if (key === 'j' || key === 'down' || key === '\x1b[B') {
|
|
320
|
-
this._selectedIndex = Math.min(providers.length - 1, this._selectedIndex + 1);
|
|
321
|
-
this.markDirty();
|
|
322
|
-
return true;
|
|
323
|
-
}
|
|
324
|
-
if (key === 'k' || key === 'up' || key === '\x1b[A') {
|
|
325
|
-
this._selectedIndex = Math.max(0, this._selectedIndex - 1);
|
|
326
|
-
this.markDirty();
|
|
327
|
-
return true;
|
|
328
|
-
}
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/** Enter dispatches the real repair command for the selected provider. */
|
|
333
|
-
handlePanelIntegrationAction(key: string, ctx: PanelIntegrationContext): boolean {
|
|
334
|
-
if (key !== 'enter' && key !== 'return') return false;
|
|
335
|
-
if (!ctx.executeCommand) return false;
|
|
336
|
-
const provider = this._selectedProvider();
|
|
337
|
-
if (!provider) return false;
|
|
338
|
-
void ctx.executeCommand('accounts', ['repair', provider]).catch(() => {
|
|
339
|
-
// Command output surfaces in conversation; dispatch failures are non-fatal here.
|
|
340
|
-
});
|
|
341
|
-
return true;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// -------------------------------------------------------------------------
|
|
345
|
-
// Data plumbing
|
|
346
|
-
// -------------------------------------------------------------------------
|
|
347
|
-
|
|
348
|
-
private _knownProviders(): string[] {
|
|
349
|
-
const known = new Set<string>([
|
|
350
|
-
...this.deps.providers.getSnapshot().providerIds,
|
|
351
|
-
...this.providerRuntime.listProviderIds(),
|
|
352
|
-
...this._accountRecords.keys(),
|
|
353
|
-
]);
|
|
354
|
-
for (const health of this.providerHealthTracker.getAll()) known.add(health.name);
|
|
355
|
-
return [...known].sort();
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
private _selectedProvider(): string | undefined {
|
|
359
|
-
const providers = this._knownProviders();
|
|
360
|
-
return providers[Math.min(this._selectedIndex, Math.max(0, providers.length - 1))];
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* Resolve the provider that should own a TURN_ERROR: the in-flight LLM
|
|
365
|
-
* request's provider, then the store model domain, then the configured
|
|
366
|
-
* provider.model, then the last responding provider, then the sole known
|
|
367
|
-
* provider. Never returns 'unknown'.
|
|
368
|
-
*/
|
|
369
|
-
private _resolveActiveProviderId(): string | undefined {
|
|
370
|
-
if (this._inflightProvider) return this._inflightProvider;
|
|
371
|
-
if (this.deps.modelState) {
|
|
372
|
-
const storeProvider = this.deps.modelState.get().activeProviderId;
|
|
373
|
-
if (storeProvider && storeProvider !== 'unknown') return storeProvider;
|
|
374
|
-
}
|
|
375
|
-
const raw = this.deps.configManager.get('provider.model');
|
|
376
|
-
if (typeof raw === 'string' && raw.includes(':')) {
|
|
377
|
-
const providerId = raw.split(':')[0];
|
|
378
|
-
if (providerId) return providerId;
|
|
379
|
-
}
|
|
380
|
-
if (this._lastResponseProvider) return this._lastResponseProvider;
|
|
381
|
-
const known = this._knownProviders();
|
|
382
|
-
if (known.length === 1) return known[0];
|
|
383
|
-
return undefined;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
private _syntheticModelState(): ModelDomainState {
|
|
387
|
-
const base = createInitialModelState();
|
|
388
|
-
const raw = this.deps.configManager.get('provider.model');
|
|
389
|
-
if (typeof raw !== 'string' || !raw.includes(':')) return base;
|
|
390
|
-
const [providerId = '', ...rest] = raw.split(':');
|
|
391
|
-
const modelId = rest.join(':');
|
|
392
|
-
if (!providerId || !modelId) return base;
|
|
393
|
-
return {
|
|
394
|
-
...base,
|
|
395
|
-
activeProviderId: providerId,
|
|
396
|
-
activeModelId: modelId,
|
|
397
|
-
displayName: raw,
|
|
398
|
-
registryKey: raw,
|
|
399
|
-
source: 'provider-health-panel',
|
|
400
|
-
lastUpdatedAt: Date.now(),
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
private _buildHealthState() {
|
|
405
|
-
const activeId = this._resolveActiveProviderId();
|
|
406
|
-
const meta: ProviderHealthMeta[] = this._knownProviders().map((providerId) => {
|
|
407
|
-
const account = this._accountRecords.get(providerId);
|
|
408
|
-
return {
|
|
409
|
-
providerId,
|
|
410
|
-
isActive: providerId === activeId,
|
|
411
|
-
isConfigured: account ? account.activeRoute !== 'unconfigured' : true,
|
|
412
|
-
};
|
|
413
|
-
});
|
|
414
|
-
return this.providerHealthTracker.buildHealthDomainState(meta);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
private _pushHealthState(): void {
|
|
418
|
-
this._dataProvider.updateHealthState(this._buildHealthState());
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
private async _refreshAccountPosture(force = false): Promise<void> {
|
|
422
|
-
if (this._accountLoading) return;
|
|
423
|
-
if (!force && Date.now() - this._accountRefreshAt < 15_000) return;
|
|
424
|
-
this._accountLoading = true;
|
|
425
|
-
try {
|
|
426
|
-
const snapshots = await this.providerRuntime.inspectAll();
|
|
427
|
-
this._accountRecords = new Map(
|
|
428
|
-
snapshots
|
|
429
|
-
.map((snapshot) => buildAccountPosture(snapshot))
|
|
430
|
-
.map((record) => [record.providerId, record] as const),
|
|
431
|
-
);
|
|
432
|
-
this._accountRefreshAt = Date.now();
|
|
433
|
-
this._pushHealthState();
|
|
434
|
-
this.markDirty();
|
|
435
|
-
this.requestRender();
|
|
436
|
-
} finally {
|
|
437
|
-
this._accountLoading = false;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
private _collectDomainSummaries(): HealthDomainSummary[] {
|
|
442
|
-
return [...buildProviderHealthDomainSummaries({
|
|
443
|
-
configManager: this.deps.configManager,
|
|
444
|
-
auth: this.deps.localAuth.getSnapshot(),
|
|
445
|
-
settings: this.deps.settings.getSnapshot(),
|
|
446
|
-
remote: this.deps.remote.getSnapshot(),
|
|
447
|
-
security: this.deps.security.getSnapshot(),
|
|
448
|
-
intelligence: this.deps.intelligence.getSnapshot(),
|
|
449
|
-
continuity: this.deps.continuity.getSnapshot(),
|
|
450
|
-
worktrees: this.deps.worktrees.getSnapshot(),
|
|
451
|
-
session: this.deps.session.getSnapshot(),
|
|
452
|
-
})];
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
private _evaluateMaintenance() {
|
|
456
|
-
const session = this.deps.session.getSnapshot();
|
|
457
|
-
return evaluateSessionMaintenance({
|
|
458
|
-
configManager: this.deps.configManager,
|
|
459
|
-
currentTokens: session.estimatedContextTokens,
|
|
460
|
-
contextWindow: session.contextWindow,
|
|
461
|
-
messageCount: session.messageCount,
|
|
462
|
-
session: session.session,
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
// -------------------------------------------------------------------------
|
|
467
|
-
// Rendering
|
|
468
|
-
// -------------------------------------------------------------------------
|
|
469
|
-
|
|
470
|
-
override render(width: number, height: number): Line[] {
|
|
471
|
-
const palette = { ...DEFAULT_PANEL_PALETTE, header: C.title };
|
|
472
|
-
|
|
473
|
-
const providers = this._knownProviders();
|
|
474
|
-
this._selectedIndex = Math.min(this._selectedIndex, Math.max(0, providers.length - 1));
|
|
475
|
-
|
|
476
|
-
if (providers.length === 0) {
|
|
477
|
-
return buildPanelWorkspace(width, height, {
|
|
478
|
-
title: 'Health',
|
|
479
|
-
intro: INTRO,
|
|
480
|
-
sections: [{
|
|
481
|
-
lines: buildEmptyState(
|
|
482
|
-
width,
|
|
483
|
-
' No providers registered.',
|
|
484
|
-
'Provider health appears here once model providers are available and the runtime begins making requests.',
|
|
485
|
-
[
|
|
486
|
-
{ command: '/provider', summary: 'review current provider and model selection' },
|
|
487
|
-
{ command: '/subscription', summary: 'review provider login and subscription state' },
|
|
488
|
-
],
|
|
489
|
-
palette,
|
|
490
|
-
),
|
|
491
|
-
}],
|
|
492
|
-
palette,
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
const snapshot = this._dataProvider.getSnapshot();
|
|
497
|
-
const entriesById = new Map(snapshot.entries.map((entry) => [entry.providerId, entry] as const));
|
|
498
|
-
const selectedName = providers[this._selectedIndex];
|
|
499
|
-
|
|
500
|
-
const footerHint = buildKeyboardHints(width, [
|
|
501
|
-
{ keys: 'j/k', label: 'select provider' },
|
|
502
|
-
{ keys: 'enter', label: 'repair auth routes' },
|
|
503
|
-
{ keys: 'r', label: 'refresh posture' },
|
|
504
|
-
{ keys: 't', label: `view: ${this._view}` },
|
|
505
|
-
{ keys: '/provider', label: 'switch model' },
|
|
506
|
-
], palette);
|
|
507
|
-
|
|
508
|
-
const collapsedDomains = this._view !== 'domains'
|
|
509
|
-
? {
|
|
510
|
-
attention: this._collectDomainSummaries().filter((summary) => summary.level === 'warn' || summary.level === 'bad').length,
|
|
511
|
-
maintenanceLevel: this._evaluateMaintenance().level,
|
|
512
|
-
}
|
|
513
|
-
: undefined;
|
|
514
|
-
|
|
515
|
-
const postureSection: PanelWorkspaceSection = {
|
|
516
|
-
lines: buildSummaryBlock(width, 'Provider console posture', buildPostureLines(width, C, palette, {
|
|
517
|
-
providers,
|
|
518
|
-
entriesById,
|
|
519
|
-
accounts: this._accountRecords,
|
|
520
|
-
trackerRecords: this.providerHealthTracker.getAll(),
|
|
521
|
-
compositeStatus: snapshot.compositeStatus,
|
|
522
|
-
falloverCount: snapshot.fallbackChain.falloverCount,
|
|
523
|
-
activeProvider: this._resolveActiveProviderId(),
|
|
524
|
-
...(collapsedDomains ? { collapsedDomains } : {}),
|
|
525
|
-
unattributedError: this._unattributedError,
|
|
526
|
-
}), palette),
|
|
527
|
-
};
|
|
528
|
-
|
|
529
|
-
if (this._view === 'domains') {
|
|
530
|
-
return this._renderDomainsView(width, height, postureSection, footerHint, palette);
|
|
531
|
-
}
|
|
532
|
-
if (this._view === 'routes') {
|
|
533
|
-
return this._renderRoutesView(width, height, postureSection, footerHint, palette, selectedName);
|
|
534
|
-
}
|
|
535
|
-
return this._renderProvidersView(width, height, postureSection, footerHint, palette, providers, entriesById, snapshot.fallbackChain, selectedName);
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
private _renderProvidersView(
|
|
539
|
-
width: number,
|
|
540
|
-
height: number,
|
|
541
|
-
postureSection: PanelWorkspaceSection,
|
|
542
|
-
footerHint: Line,
|
|
543
|
-
palette: typeof DEFAULT_PANEL_PALETTE,
|
|
544
|
-
providers: readonly string[],
|
|
545
|
-
entriesById: ReadonlyMap<string, ProviderHealthEntry>,
|
|
546
|
-
chain: FallbackChainData,
|
|
547
|
-
selectedName: string | undefined,
|
|
548
|
-
): Line[] {
|
|
549
|
-
const chainLines = buildChainLines(width, C, palette, chain);
|
|
550
|
-
const chainSections: PanelWorkspaceSection[] = chainLines.length > 0
|
|
551
|
-
? [{ title: 'Fallback Chain', lines: chainLines }]
|
|
552
|
-
: [];
|
|
553
|
-
|
|
554
|
-
const rows = providers.map((name, absolute) => buildProviderRow(width, C, {
|
|
555
|
-
name,
|
|
556
|
-
entry: entriesById.get(name),
|
|
557
|
-
health: this.providerHealthTracker.get(name),
|
|
558
|
-
account: this._accountRecords.get(name),
|
|
559
|
-
selected: absolute === this._selectedIndex,
|
|
560
|
-
}));
|
|
561
|
-
|
|
562
|
-
const selectedSections: PanelWorkspaceSection[] = selectedName
|
|
563
|
-
? [buildSelectedDetailSection(width, C, palette, {
|
|
564
|
-
selectedName,
|
|
565
|
-
entry: entriesById.get(selectedName),
|
|
566
|
-
health: this.providerHealthTracker.get(selectedName),
|
|
567
|
-
account: this._accountRecords.get(selectedName),
|
|
568
|
-
})]
|
|
569
|
-
: [];
|
|
570
|
-
|
|
571
|
-
const resolved = resolvePrimaryScrollableSection(width, height, {
|
|
572
|
-
intro: INTRO,
|
|
573
|
-
footerLines: [footerHint],
|
|
574
|
-
palette,
|
|
575
|
-
beforeSections: [postureSection, ...chainSections],
|
|
576
|
-
section: {
|
|
577
|
-
title: 'Providers',
|
|
578
|
-
fixedLines: [buildProviderColumnHeader(width, C)],
|
|
579
|
-
scrollableLines: rows,
|
|
580
|
-
selectedIndex: this._selectedIndex,
|
|
581
|
-
scrollOffset: this._scrollOffset,
|
|
582
|
-
guardRows: 1,
|
|
583
|
-
minRows: 4,
|
|
584
|
-
appendWindowSummary: { dimColor: C.dim },
|
|
585
|
-
},
|
|
586
|
-
afterSections: selectedSections,
|
|
587
|
-
});
|
|
588
|
-
this._scrollOffset = resolved.scrollOffset;
|
|
589
|
-
|
|
590
|
-
return buildPanelWorkspace(width, height, {
|
|
591
|
-
title: 'Health',
|
|
592
|
-
intro: INTRO,
|
|
593
|
-
sections: [postureSection, ...chainSections, resolved.section, ...selectedSections],
|
|
594
|
-
footerLines: [footerHint],
|
|
595
|
-
palette,
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
private _renderRoutesView(
|
|
600
|
-
width: number,
|
|
601
|
-
height: number,
|
|
602
|
-
postureSection: PanelWorkspaceSection,
|
|
603
|
-
footerHint: Line,
|
|
604
|
-
palette: typeof DEFAULT_PANEL_PALETTE,
|
|
605
|
-
selectedName: string | undefined,
|
|
606
|
-
): Line[] {
|
|
607
|
-
const account = selectedName ? this._accountRecords.get(selectedName) : undefined;
|
|
608
|
-
const routeLines = buildRouteViewLines(width, C, palette, account);
|
|
609
|
-
|
|
610
|
-
const resolved = resolvePrimaryScrollableSection(width, height, {
|
|
611
|
-
intro: INTRO,
|
|
612
|
-
footerLines: [footerHint],
|
|
613
|
-
palette,
|
|
614
|
-
beforeSections: [postureSection],
|
|
615
|
-
section: {
|
|
616
|
-
title: `Auth Routes — ${selectedName ?? 'n/a'}`,
|
|
617
|
-
fixedLines: [buildRouteColumnHeader(width, C)],
|
|
618
|
-
scrollableLines: routeLines,
|
|
619
|
-
selectedIndex: 0,
|
|
620
|
-
scrollOffset: this._scrollOffset,
|
|
621
|
-
guardRows: 1,
|
|
622
|
-
minRows: 4,
|
|
623
|
-
appendWindowSummary: { dimColor: C.dim },
|
|
624
|
-
},
|
|
625
|
-
afterSections: [],
|
|
626
|
-
});
|
|
627
|
-
this._scrollOffset = resolved.scrollOffset;
|
|
628
|
-
|
|
629
|
-
return buildPanelWorkspace(width, height, {
|
|
630
|
-
title: 'Health',
|
|
631
|
-
intro: INTRO,
|
|
632
|
-
sections: [postureSection, resolved.section],
|
|
633
|
-
footerLines: [footerHint],
|
|
634
|
-
palette,
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
private _renderDomainsView(
|
|
639
|
-
width: number,
|
|
640
|
-
height: number,
|
|
641
|
-
postureSection: PanelWorkspaceSection,
|
|
642
|
-
footerHint: Line,
|
|
643
|
-
palette: typeof DEFAULT_PANEL_PALETTE,
|
|
644
|
-
): Line[] {
|
|
645
|
-
const domainLines = buildDomainLines(width, C, palette, this._collectDomainSummaries());
|
|
646
|
-
const maintenanceSection: PanelWorkspaceSection = {
|
|
647
|
-
title: 'Session Maintenance',
|
|
648
|
-
lines: buildMaintenanceLines(width, C, palette, this._evaluateMaintenance()),
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
const resolved = resolvePrimaryScrollableSection(width, height, {
|
|
652
|
-
intro: INTRO,
|
|
653
|
-
footerLines: [footerHint],
|
|
654
|
-
palette,
|
|
655
|
-
beforeSections: [postureSection],
|
|
656
|
-
section: {
|
|
657
|
-
title: 'Repair Domains',
|
|
658
|
-
fixedLines: [],
|
|
659
|
-
scrollableLines: domainLines,
|
|
660
|
-
selectedIndex: 0,
|
|
661
|
-
scrollOffset: this._scrollOffset,
|
|
662
|
-
guardRows: 1,
|
|
663
|
-
minRows: 4,
|
|
664
|
-
appendWindowSummary: { dimColor: C.dim },
|
|
665
|
-
},
|
|
666
|
-
afterSections: [maintenanceSection],
|
|
667
|
-
});
|
|
668
|
-
this._scrollOffset = resolved.scrollOffset;
|
|
669
|
-
|
|
670
|
-
return buildPanelWorkspace(width, height, {
|
|
671
|
-
title: 'Health',
|
|
672
|
-
intro: INTRO,
|
|
673
|
-
sections: [postureSection, resolved.section, maintenanceSection],
|
|
674
|
-
footerLines: [footerHint],
|
|
675
|
-
palette,
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
}
|