@pellux/goodvibes-tui 0.18.12 → 0.18.17
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 +172 -0
- package/README.md +1 -1
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +3 -2
- package/src/config/index.ts +1 -138
- package/src/core/conversation-rendering.ts +3 -3
- package/src/core/conversation.ts +176 -423
- package/src/core/history.ts +45 -0
- package/src/core/orchestrator.ts +3 -735
- package/src/core/system-message-router.ts +19 -58
- package/src/daemon/cli.ts +82 -6
- package/src/input/command-registry.ts +2 -0
- package/src/input/commands/control-room-runtime.ts +1 -1
- package/src/input/commands/health-runtime.ts +1 -1
- package/src/input/commands/local-setup-review.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +1 -1
- package/src/input/commands/qrcode-runtime.ts +20 -0
- package/src/input/commands/subscription-runtime.ts +1 -1
- package/src/input/commands.ts +2 -0
- package/src/input/handler-content-actions.ts +2 -2
- package/src/input/handler-feed.ts +7 -1
- package/src/input/handler-modal-routes.ts +19 -2
- package/src/input/handler-modal-token-routes.ts +4 -1
- package/src/input/handler-picker-routes.ts +4 -2
- package/src/input/handler-ui-state.ts +1 -1
- package/src/input/handler.ts +1 -1
- package/src/input/model-picker.ts +11 -0
- package/src/input/search.ts +1 -1
- package/src/input/selection.ts +2 -2
- package/src/input/settings-modal.ts +31 -3
- package/src/main.ts +1 -1
- package/src/panels/agent-inspector-panel.ts +3 -3
- package/src/panels/agent-logs-panel.ts +26 -27
- package/src/panels/approval-panel.ts +2 -2
- package/src/panels/automation-control-panel.ts +3 -3
- package/src/panels/base-panel.ts +14 -14
- package/src/panels/builtin/operations.ts +1 -1
- package/src/panels/builtin/session.ts +67 -1
- package/src/panels/builtin/shared.ts +4 -4
- package/src/panels/cockpit-panel.ts +2 -2
- package/src/panels/communication-panel.ts +3 -3
- package/src/panels/context-visualizer-panel.ts +2 -2
- package/src/panels/control-plane-panel.ts +3 -3
- package/src/panels/cost-tracker-panel.ts +3 -3
- package/src/panels/debug-panel.ts +2 -2
- package/src/panels/diff-panel.ts +2 -2
- package/src/panels/docs-panel.ts +1 -1
- package/src/panels/eval-panel.ts +2 -2
- package/src/panels/file-explorer-panel.ts +3 -3
- package/src/panels/file-preview-panel.ts +3 -3
- package/src/panels/forensics-panel.ts +2 -2
- package/src/panels/git-panel.ts +1 -1
- package/src/panels/hooks-panel.ts +3 -3
- package/src/panels/incident-review-panel.ts +1 -1
- package/src/panels/intelligence-panel.ts +2 -2
- package/src/panels/knowledge-panel.ts +1 -1
- package/src/panels/local-auth-panel.ts +2 -2
- package/src/panels/marketplace-panel.ts +1 -1
- package/src/panels/mcp-panel.ts +3 -3
- package/src/panels/memory-panel.ts +1 -1
- package/src/panels/ops-control-panel.ts +3 -3
- package/src/panels/ops-strategy-panel.ts +2 -2
- package/src/panels/orchestration-panel.ts +2 -2
- package/src/panels/panel-list-panel.ts +6 -6
- package/src/panels/plan-dashboard-panel.ts +1 -1
- package/src/panels/plugins-panel.ts +2 -2
- package/src/panels/policy-panel.ts +2 -2
- package/src/panels/polish.ts +3 -3
- package/src/panels/provider-account-snapshot.ts +1 -1
- package/src/panels/provider-accounts-panel.ts +25 -29
- package/src/panels/provider-health-panel.ts +2 -2
- package/src/panels/provider-stats-panel.ts +3 -3
- package/src/panels/qr-panel.ts +182 -0
- package/src/panels/remote-panel.ts +3 -3
- package/src/panels/routes-panel.ts +3 -3
- package/src/panels/sandbox-panel.ts +2 -2
- package/src/panels/schedule-panel.ts +1 -1
- package/src/panels/scrollable-list-panel.ts +407 -0
- package/src/panels/security-panel.ts +2 -2
- package/src/panels/services-panel.ts +3 -3
- package/src/panels/session-browser-panel.ts +2 -2
- package/src/panels/settings-sync-panel.ts +2 -2
- package/src/panels/skills-panel.ts +6 -6
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/symbol-outline-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +4 -4
- package/src/panels/tasks-panel.ts +2 -2
- package/src/panels/thinking-panel.ts +3 -3
- package/src/panels/token-budget-panel.ts +1 -1
- package/src/panels/tool-inspector-panel.ts +3 -3
- package/src/panels/types.ts +5 -5
- package/src/panels/watchers-panel.ts +3 -3
- package/src/panels/welcome-panel.ts +1 -1
- package/src/panels/worktree-panel.ts +22 -21
- package/src/panels/wrfc-panel.ts +3 -3
- package/src/permissions/prompt.ts +3 -22
- package/src/plugins/loader.ts +15 -304
- package/src/renderer/agent-detail-modal.ts +1 -1
- package/src/renderer/autocomplete-overlay.ts +2 -2
- package/src/renderer/bookmark-modal.ts +1 -1
- package/src/renderer/bottom-bar.ts +2 -2
- package/src/renderer/buffer.ts +1 -1
- package/src/renderer/code-block.ts +2 -2
- package/src/renderer/compositor.ts +2 -2
- package/src/renderer/context-inspector.ts +1 -1
- package/src/renderer/conversation-layout.ts +2 -2
- package/src/renderer/conversation-overlays.ts +1 -1
- package/src/renderer/conversation-surface.ts +2 -2
- package/src/renderer/diff-view.ts +2 -2
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +2 -2
- package/src/renderer/file-tree.ts +2 -2
- package/src/renderer/help-overlay.ts +1 -1
- package/src/renderer/history-search-overlay.ts +2 -2
- package/src/renderer/live-tail-modal.ts +1 -1
- package/src/renderer/markdown.ts +2 -2
- package/src/renderer/modal-factory.ts +3 -3
- package/src/renderer/model-picker-overlay.ts +2 -2
- package/src/renderer/overlay-box.ts +2 -2
- package/src/renderer/panel-composite.ts +1 -1
- package/src/renderer/panel-picker-overlay.ts +2 -2
- package/src/renderer/panel-tab-bar.ts +1 -1
- package/src/renderer/panel-workspace-bar.ts +1 -1
- package/src/renderer/process-indicator.ts +2 -2
- package/src/renderer/process-modal.ts +1 -1
- package/src/renderer/profile-picker-modal.ts +2 -2
- package/src/renderer/progress.ts +2 -2
- package/src/renderer/qr-renderer.ts +117 -0
- package/src/renderer/search-overlay.ts +2 -2
- package/src/renderer/selection-modal-overlay.ts +2 -2
- package/src/renderer/session-picker-modal.ts +2 -2
- package/src/renderer/settings-modal-helpers.ts +122 -0
- package/src/renderer/settings-modal.ts +149 -113
- package/src/renderer/shell-surface.ts +1 -1
- package/src/renderer/system-message.ts +1 -1
- package/src/renderer/tab-strip.ts +2 -2
- package/src/renderer/text-layout.ts +1 -1
- package/src/renderer/thinking.ts +1 -1
- package/src/renderer/tool-call.ts +2 -2
- package/src/renderer/ui-factory.ts +2 -2
- package/src/runtime/bootstrap-command-context.ts +5 -6
- package/src/runtime/bootstrap-command-parts.ts +32 -18
- package/src/runtime/bootstrap-core.ts +3 -2
- package/src/runtime/bootstrap-hook-bridge.ts +15 -174
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +7 -2
- package/src/runtime/context.ts +4 -20
- package/src/runtime/diagnostics/panels/index.ts +6 -6
- package/src/runtime/diagnostics/panels/ops.ts +1 -1
- package/src/runtime/diagnostics/panels/panel-resources.ts +118 -0
- package/src/runtime/perf/panel-contracts.ts +32 -0
- package/src/runtime/perf/panel-health-monitor.ts +18 -0
- package/src/runtime/services.ts +5 -5
- package/src/runtime/store/domains/domain-read-matrix.ts +0 -2
- package/src/runtime/store/selectors/index.ts +11 -6
- package/src/runtime/store/state.ts +12 -4
- package/src/runtime/ui-events.ts +1 -0
- package/src/runtime/ui-read-model-helpers.ts +1 -32
- package/src/runtime/ui-read-models-observability-maintenance.ts +1 -81
- package/src/runtime/ui-read-models-observability-options.ts +1 -5
- package/src/runtime/ui-read-models-observability-remote.ts +1 -73
- package/src/runtime/ui-read-models-observability-security.ts +1 -172
- package/src/runtime/ui-read-models-observability-system.ts +1 -217
- package/src/runtime/ui-read-models-observability.ts +1 -59
- package/src/runtime/ui-service-queries.ts +1 -114
- package/src/runtime/ui-services.ts +1 -1
- package/src/shell/ui-openers.ts +1 -1
- package/src/tools/index.ts +1 -186
- package/src/types/grid.ts +48 -0
- package/src/utils/clipboard.ts +21 -0
- package/src/utils/splash-lines.ts +1 -1
- package/src/utils/terminal-width.ts +185 -0
- package/src/version.ts +1 -1
- package/src/config/service-registry.ts +0 -1
- package/src/config/subscription-providers.ts +0 -127
- package/src/daemon/facade-composition.ts +0 -398
- package/src/daemon/facade.ts +0 -638
- package/src/daemon/surface-policy.ts +0 -60
- package/src/daemon/types.ts +0 -191
- package/src/runtime/diagnostics/actions.ts +0 -776
- package/src/runtime/diagnostics/index.ts +0 -99
- package/src/runtime/diagnostics/panels/agents.ts +0 -252
- package/src/runtime/diagnostics/panels/events.ts +0 -188
- package/src/runtime/diagnostics/panels/health.ts +0 -242
- package/src/runtime/diagnostics/panels/tasks.ts +0 -251
- package/src/runtime/diagnostics/panels/tool-calls.ts +0 -267
- package/src/runtime/diagnostics/provider.ts +0 -262
- package/src/runtime/store/domains/conversation.ts +0 -181
- package/src/runtime/store/domains/permissions.ts +0 -143
- package/src/runtime/store/helpers/reducers/conversation.ts +0 -228
- package/src/runtime/store/helpers/reducers/lifecycle.ts +0 -440
- package/src/runtime/store/helpers/reducers/shared.ts +0 -60
- package/src/runtime/store/helpers/reducers/sync.ts +0 -555
- package/src/runtime/store/helpers/reducers.ts +0 -30
- package/src/runtime/ui-read-models-core.ts +0 -95
- package/src/runtime/ui-read-models-operations.ts +0 -203
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* MemoryPanel — project memory substrate TUI panel.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { Line } from '
|
|
5
|
+
import type { Line } from '../types/grid.ts';
|
|
6
6
|
import type { MemoryRegistry } from '@pellux/goodvibes-sdk/platform/state/memory-store';
|
|
7
7
|
import type { MemoryRecord, MemoryClass } from '@pellux/goodvibes-sdk/platform/state/memory-store';
|
|
8
8
|
import { BasePanel } from './base-panel.ts';
|
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
* Requires the `operator-control-plane` feature flag to be enabled.
|
|
8
8
|
* Open via Ctrl+O keybind or `/ops view` command.
|
|
9
9
|
*/
|
|
10
|
-
import type { Line } from '
|
|
10
|
+
import type { Line } from '../types/grid.ts';
|
|
11
11
|
import type { OpsEvent } from '@pellux/goodvibes-sdk/platform/runtime/events/index';
|
|
12
|
-
import type { UiEventFeed } from '
|
|
12
|
+
import type { UiEventFeed } from '../runtime/ui-events.ts';
|
|
13
13
|
import type { OpsAuditEntry } from '../runtime/diagnostics/panels/ops.ts';
|
|
14
14
|
import { OpsPanel } from '../runtime/diagnostics/panels/ops.ts';
|
|
15
15
|
import { BasePanel } from './base-panel.ts';
|
|
16
|
-
import { createEmptyLine } from '
|
|
16
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
17
17
|
import {
|
|
18
18
|
buildEmptyState,
|
|
19
19
|
buildPanelLine,
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { BasePanel } from './base-panel.ts';
|
|
11
|
-
import type { Line } from '
|
|
11
|
+
import type { Line } from '../types/grid.ts';
|
|
12
12
|
import type { PlannerDecision, ExecutionStrategy } from '@pellux/goodvibes-sdk/platform/core/adaptive-planner';
|
|
13
13
|
import type { PlannerEvent } from '@pellux/goodvibes-sdk/platform/runtime/events/index';
|
|
14
|
-
import type { UiEventFeed } from '
|
|
14
|
+
import type { UiEventFeed } from '../runtime/ui-events.ts';
|
|
15
15
|
import type { OpsStrategyQuery } from '../runtime/ui-service-queries.ts';
|
|
16
16
|
import {
|
|
17
17
|
buildEmptyState,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Line } from '
|
|
2
|
-
import { createEmptyLine } from '
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
3
3
|
import { BasePanel } from './base-panel.ts';
|
|
4
4
|
import type { UiOrchestrationSnapshot, UiReadModel } from '../runtime/ui-read-models.ts';
|
|
5
5
|
import {
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Open via /panel list.
|
|
14
14
|
*/
|
|
15
|
-
import type { Line, Cell } from '
|
|
15
|
+
import type { Line, Cell } from '../types/grid.ts';
|
|
16
16
|
import type { PanelCategory, PanelRegistration } from './types.ts';
|
|
17
17
|
import { BasePanel } from './base-panel.ts';
|
|
18
18
|
import type { PanelManager } from './panel-manager.ts';
|
|
19
|
-
import type {
|
|
20
|
-
import { createEmptyLine } from '
|
|
19
|
+
import type { ComponentHealthMonitor } from '../runtime/perf/panel-health-monitor.ts';
|
|
20
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
21
21
|
import {
|
|
22
22
|
buildEmptyState,
|
|
23
23
|
buildKeyValueLine,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
resolvePrimaryScrollableSection,
|
|
31
31
|
type PanelWorkspaceSection,
|
|
32
32
|
} from './polish.ts';
|
|
33
|
-
import { truncateDisplay } from '
|
|
33
|
+
import { truncateDisplay } from '../utils/terminal-width.ts';
|
|
34
34
|
import { wrapWithHangingIndent } from '../renderer/text-layout.ts';
|
|
35
35
|
import {
|
|
36
36
|
getPanelSearchFocusTransition,
|
|
@@ -112,9 +112,9 @@ export class PanelListPanel extends BasePanel {
|
|
|
112
112
|
|
|
113
113
|
public constructor(
|
|
114
114
|
private readonly panelManager: PanelManager,
|
|
115
|
-
|
|
115
|
+
componentHealthMonitor?: ComponentHealthMonitor,
|
|
116
116
|
) {
|
|
117
|
-
super('panel-list', 'Panel List', 'L', 'session',
|
|
117
|
+
super('panel-list', 'Panel List', 'L', 'session', componentHealthMonitor);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
public override onActivate(): void {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Line } from '
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
2
|
import type { ExecutionPlan, PlanItem, PlanItemStatus } from '@pellux/goodvibes-sdk/platform/core/execution-plan';
|
|
3
3
|
import { BasePanel } from './base-panel.ts';
|
|
4
4
|
import type { PlanDashboardQuery } from '../runtime/ui-service-queries.ts';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Line } from '
|
|
2
|
-
import { createEmptyLine } from '
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
3
3
|
import { BasePanel } from './base-panel.ts';
|
|
4
4
|
import type { PluginManagerObserver, PluginStatus } from '@pellux/goodvibes-sdk/platform/plugins/manager';
|
|
5
5
|
import {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Line } from '
|
|
2
|
-
import { createEmptyLine } from '
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
3
3
|
import { BasePanel } from './base-panel.ts';
|
|
4
4
|
import type { PolicyRuntimeState } from '@pellux/goodvibes-sdk/platform/runtime/permissions/policy-runtime';
|
|
5
5
|
import type { PolicyPanelSnapshot } from '../runtime/diagnostics/panels/policy.ts';
|
package/src/panels/polish.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Line } from '
|
|
2
|
-
import { createEmptyLine, createStyledCell } from '
|
|
3
|
-
import { getDisplayWidth, wrapText } from '
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine, createStyledCell } from '../types/grid.ts';
|
|
3
|
+
import { getDisplayWidth, wrapText } from '../utils/terminal-width.ts';
|
|
4
4
|
import { getSurfaceContentRows, getTrackedVisibleWindow, getVisibleWindow, type VisibleWindow } from '../renderer/surface-layout.ts';
|
|
5
5
|
import { GLYPHS, UI_TONES } from '../renderer/ui-primitives.ts';
|
|
6
6
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { listBuiltinSubscriptionProviders } from '
|
|
1
|
+
import { listBuiltinSubscriptionProviders } from '@pellux/goodvibes-sdk/platform/config/subscription-providers';
|
|
2
2
|
import type {
|
|
3
3
|
ProviderAccountInspectionQuery,
|
|
4
4
|
} from '../runtime/ui-service-queries.ts';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Line } from '
|
|
2
|
-
import { createEmptyLine } from '
|
|
3
|
-
import {
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
3
|
+
import { ScrollableListPanel } from './scrollable-list-panel.ts';
|
|
4
4
|
import {
|
|
5
5
|
buildDetailBlock,
|
|
6
6
|
buildEmptyState,
|
|
@@ -29,11 +29,9 @@ const C = {
|
|
|
29
29
|
selectBg: '#1e293b',
|
|
30
30
|
} as const;
|
|
31
31
|
|
|
32
|
-
export class ProviderAccountsPanel extends
|
|
32
|
+
export class ProviderAccountsPanel extends ScrollableListPanel<ProviderAccountRecord> {
|
|
33
33
|
private records: ProviderAccountRecord[] = [];
|
|
34
34
|
private loading = false;
|
|
35
|
-
private selectedIndex = 0;
|
|
36
|
-
private scrollOffset = 0;
|
|
37
35
|
private readonly providerAccounts: ProviderAccountSnapshotQuery;
|
|
38
36
|
|
|
39
37
|
public constructor(deps: ProviderAccountsPanelDeps) {
|
|
@@ -47,22 +45,26 @@ export class ProviderAccountsPanel extends BasePanel {
|
|
|
47
45
|
if (!this.loading) void this.refresh();
|
|
48
46
|
}
|
|
49
47
|
|
|
48
|
+
protected getItems(): readonly ProviderAccountRecord[] {
|
|
49
|
+
return this.records;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
protected renderItem(item: ProviderAccountRecord, _index: number, selected: boolean, width: number): Line {
|
|
53
|
+
return buildPanelListRow(width, [
|
|
54
|
+
{ text: item.providerId.padEnd(16), fg: item.active ? C.good : C.value },
|
|
55
|
+
{ text: ` ${item.activeRoute.padEnd(14)}`, fg: item.activeRoute === 'subscription' ? C.info : item.activeRoute === 'api-key' ? C.warn : item.activeRoute === 'service-oauth' ? C.value : C.dim },
|
|
56
|
+
{ text: ` models=${String(item.modelCount).padEnd(4)}`, fg: C.dim },
|
|
57
|
+
{ text: ` ${item.authFreshness.padEnd(10)}`, fg: item.authFreshness === 'expired' ? C.bad : item.authFreshness === 'expiring' || item.authFreshness === 'pending' ? C.warn : C.dim },
|
|
58
|
+
{ text: ` issues=${String(item.issues.length).padEnd(2)}`, fg: item.issues.length > 0 ? C.bad : C.good },
|
|
59
|
+
], C, { selected });
|
|
60
|
+
}
|
|
61
|
+
|
|
50
62
|
public handleInput(key: string): boolean {
|
|
51
63
|
if (key === 'r') {
|
|
52
64
|
void this.refresh();
|
|
53
65
|
return true;
|
|
54
66
|
}
|
|
55
|
-
|
|
56
|
-
this.selectedIndex = Math.max(0, this.selectedIndex - 1);
|
|
57
|
-
this.markDirty();
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
if (key === 'down' || key === 'j') {
|
|
61
|
-
this.selectedIndex = Math.min(Math.max(0, this.records.length - 1), this.selectedIndex + 1);
|
|
62
|
-
this.markDirty();
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
67
|
+
return super.handleInput(key);
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
private async refresh(): Promise<void> {
|
|
@@ -70,7 +72,7 @@ export class ProviderAccountsPanel extends BasePanel {
|
|
|
70
72
|
this.markDirty();
|
|
71
73
|
const snapshot = await this.buildSnapshot();
|
|
72
74
|
this.records = [...snapshot.providers];
|
|
73
|
-
this.
|
|
75
|
+
this.clampSelection();
|
|
74
76
|
this.loading = false;
|
|
75
77
|
this.markDirty();
|
|
76
78
|
}
|
|
@@ -177,15 +179,9 @@ export class ProviderAccountsPanel extends BasePanel {
|
|
|
177
179
|
}
|
|
178
180
|
const postureSection: PanelWorkspaceSection = { lines: buildSummaryBlock(width, 'Provider posture', postureLines, C) };
|
|
179
181
|
const detailsSection: PanelWorkspaceSection = { lines: buildDetailBlock(width, 'Selected provider', detailRows, C) };
|
|
180
|
-
const rawProviderLines: Line[] = this.records.map((record, absolute) =>
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
{ text: ` ${record.activeRoute.padEnd(14)}`, fg: record.activeRoute === 'subscription' ? C.info : record.activeRoute === 'api-key' ? C.warn : record.activeRoute === 'service-oauth' ? C.value : C.dim },
|
|
184
|
-
{ text: ` models=${String(record.modelCount).padEnd(4)}`, fg: C.dim },
|
|
185
|
-
{ text: ` ${record.authFreshness.padEnd(10)}`, fg: record.authFreshness === 'expired' ? C.bad : record.authFreshness === 'expiring' || record.authFreshness === 'pending' ? C.warn : C.dim },
|
|
186
|
-
{ text: ` issues=${String(record.issues.length).padEnd(2)}`, fg: record.issues.length > 0 ? C.bad : C.good },
|
|
187
|
-
], C, { selected: absolute === this.selectedIndex });
|
|
188
|
-
});
|
|
182
|
+
const rawProviderLines: Line[] = this.records.map((record, absolute) =>
|
|
183
|
+
this.renderItem(record, absolute, absolute === this.selectedIndex, width),
|
|
184
|
+
);
|
|
189
185
|
const resolvedProvidersSection = resolvePrimaryScrollableSection(width, height, {
|
|
190
186
|
intro,
|
|
191
187
|
footerLines,
|
|
@@ -195,14 +191,14 @@ export class ProviderAccountsPanel extends BasePanel {
|
|
|
195
191
|
title: 'Providers',
|
|
196
192
|
scrollableLines: rawProviderLines,
|
|
197
193
|
selectedIndex: this.selectedIndex,
|
|
198
|
-
scrollOffset: this.
|
|
194
|
+
scrollOffset: this.scrollStart,
|
|
199
195
|
guardRows: 1,
|
|
200
196
|
minRows: 4,
|
|
201
197
|
appendWindowSummary: { dimColor: C.dim },
|
|
202
198
|
},
|
|
203
199
|
afterSections: [detailsSection],
|
|
204
200
|
});
|
|
205
|
-
this.
|
|
201
|
+
this.scrollStart = resolvedProvidersSection.scrollOffset;
|
|
206
202
|
const sections: PanelWorkspaceSection[] = [
|
|
207
203
|
postureSection,
|
|
208
204
|
resolvedProvidersSection.section,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config/manager';
|
|
2
2
|
import { BasePanel } from './base-panel.ts';
|
|
3
|
-
import { createEmptyLine, createStyledCell, type Line } from '
|
|
3
|
+
import { createEmptyLine, createStyledCell, type Line } from '../types/grid.ts';
|
|
4
4
|
import type { ProviderAuthRouteDescriptor } from '@pellux/goodvibes-sdk/platform/providers/interface';
|
|
5
5
|
import type { ProviderEvent, TurnEvent } from '@pellux/goodvibes-sdk/platform/runtime/events/index';
|
|
6
|
-
import type { UiEventFeed } from '
|
|
6
|
+
import type { UiEventFeed } from '../runtime/ui-events.ts';
|
|
7
7
|
import {
|
|
8
8
|
type ProviderRuntimeInspectionQuery,
|
|
9
9
|
} from '../runtime/ui-service-queries.ts';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BasePanel } from './base-panel.ts';
|
|
2
|
-
import type { Line } from '
|
|
2
|
+
import type { Line } from '../types/grid.ts';
|
|
3
3
|
import type { ProviderEvent, TurnEvent } from '@pellux/goodvibes-sdk/platform/runtime/events/index';
|
|
4
|
-
import type { UiEventFeed } from '
|
|
4
|
+
import type { UiEventFeed } from '../runtime/ui-events.ts';
|
|
5
5
|
import type { UiProvidersSnapshot, UiReadModel } from '../runtime/ui-read-models.ts';
|
|
6
6
|
import {
|
|
7
7
|
buildEmptyState,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
DEFAULT_PANEL_PALETTE,
|
|
12
12
|
type PanelWorkspaceSection,
|
|
13
13
|
} from './polish.ts';
|
|
14
|
-
import { truncateDisplay } from '
|
|
14
|
+
import { truncateDisplay } from '../utils/terminal-width.ts';
|
|
15
15
|
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
// Constants
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
3
|
+
import { BasePanel } from './base-panel.ts';
|
|
4
|
+
import {
|
|
5
|
+
buildPanelLine,
|
|
6
|
+
DEFAULT_PANEL_PALETTE,
|
|
7
|
+
} from './polish.ts';
|
|
8
|
+
import { renderQrMatrix, generateQrMatrix } from '../renderer/qr-renderer.ts';
|
|
9
|
+
import { encodeConnectionPayload } from '@pellux/goodvibes-sdk/platform/pairing/index';
|
|
10
|
+
|
|
11
|
+
const C = {
|
|
12
|
+
...DEFAULT_PANEL_PALETTE,
|
|
13
|
+
url: '#38bdf8',
|
|
14
|
+
token: '#a78bfa',
|
|
15
|
+
hint: '#64748b',
|
|
16
|
+
qrFg: '#000000',
|
|
17
|
+
qrBg: '#ffffff',
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Connection info passed to the QR panel.
|
|
22
|
+
* Populated at construction; updated when the token is regenerated.
|
|
23
|
+
*/
|
|
24
|
+
export interface QrPanelConnectionInfo {
|
|
25
|
+
/** Full connection URL (e.g. http://192.168.1.x:3141) */
|
|
26
|
+
readonly url: string;
|
|
27
|
+
/** Auth token */
|
|
28
|
+
readonly token: string;
|
|
29
|
+
/** Username associated with the companion session */
|
|
30
|
+
readonly username: string;
|
|
31
|
+
/** Bootstrap password for companion authentication */
|
|
32
|
+
readonly password?: string;
|
|
33
|
+
/** SDK/surface version (defaults to '0.0.0' if omitted) */
|
|
34
|
+
readonly version?: string;
|
|
35
|
+
/** Surface identifier (defaults to 'tui' if omitted) */
|
|
36
|
+
readonly surface?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Callback used by the panel to regenerate the companion token.
|
|
41
|
+
* Returns updated connection info.
|
|
42
|
+
*/
|
|
43
|
+
export type RegenerateTokenFn = () => QrPanelConnectionInfo;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Callback used by the panel to copy text to the clipboard.
|
|
47
|
+
*/
|
|
48
|
+
export type CopyToClipboardFn = (text: string) => void;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* QrPanel - displays a QR code for companion app pairing.
|
|
52
|
+
*
|
|
53
|
+
* Shows connection URL, truncated token, and username above the QR code.
|
|
54
|
+
* Supports `r` to regenerate the token and `c` to copy the token.
|
|
55
|
+
*
|
|
56
|
+
* QR matrix generation uses the SDK's `generateQrMatrix` via `encodeConnectionPayload`.
|
|
57
|
+
*/
|
|
58
|
+
export class QrPanel extends BasePanel {
|
|
59
|
+
private connectionInfo: QrPanelConnectionInfo;
|
|
60
|
+
private readonly regenerateToken: RegenerateTokenFn | undefined;
|
|
61
|
+
private readonly copyToClipboard: CopyToClipboardFn | undefined;
|
|
62
|
+
private lastStatus = '';
|
|
63
|
+
|
|
64
|
+
public constructor(
|
|
65
|
+
connectionInfo: QrPanelConnectionInfo,
|
|
66
|
+
regenerateToken?: RegenerateTokenFn,
|
|
67
|
+
copyToClipboard?: CopyToClipboardFn,
|
|
68
|
+
) {
|
|
69
|
+
super('qr-code', 'QR Code', 'Q', 'session');
|
|
70
|
+
this.connectionInfo = connectionInfo;
|
|
71
|
+
this.regenerateToken = regenerateToken;
|
|
72
|
+
this.copyToClipboard = copyToClipboard;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public handleInput(key: string): boolean {
|
|
76
|
+
if (key === 'r') {
|
|
77
|
+
if (this.regenerateToken) {
|
|
78
|
+
this.connectionInfo = this.regenerateToken();
|
|
79
|
+
this.lastStatus = 'Token regenerated.';
|
|
80
|
+
} else {
|
|
81
|
+
this.lastStatus = 'Regeneration not available.';
|
|
82
|
+
}
|
|
83
|
+
this.markDirty();
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
if (key === 'c') {
|
|
87
|
+
if (this.copyToClipboard) {
|
|
88
|
+
this.copyToClipboard(this.connectionInfo.token);
|
|
89
|
+
this.lastStatus = 'Token copied to clipboard.';
|
|
90
|
+
} else {
|
|
91
|
+
this.lastStatus = 'Clipboard not available.';
|
|
92
|
+
}
|
|
93
|
+
this.markDirty();
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public render(width: number, height: number): Line[] {
|
|
100
|
+
this.needsRender = false;
|
|
101
|
+
const lines: Line[] = [];
|
|
102
|
+
|
|
103
|
+
const { url, token, username, password } = this.connectionInfo;
|
|
104
|
+
|
|
105
|
+
// ── Connection info header ─────────────────────────────────────────────
|
|
106
|
+
lines.push(createEmptyLine(width));
|
|
107
|
+
lines.push(
|
|
108
|
+
buildPanelLine(width, [
|
|
109
|
+
[' URL ', C.label],
|
|
110
|
+
[url.slice(0, Math.max(0, width - 12)), C.url],
|
|
111
|
+
]),
|
|
112
|
+
);
|
|
113
|
+
lines.push(
|
|
114
|
+
buildPanelLine(width, [
|
|
115
|
+
[' Token ', C.label],
|
|
116
|
+
[token, C.token],
|
|
117
|
+
]),
|
|
118
|
+
);
|
|
119
|
+
lines.push(
|
|
120
|
+
buildPanelLine(width, [
|
|
121
|
+
[' Username ', C.label],
|
|
122
|
+
[username.slice(0, Math.max(0, width - 12)), C.value],
|
|
123
|
+
]),
|
|
124
|
+
);
|
|
125
|
+
if (password !== undefined) {
|
|
126
|
+
lines.push(
|
|
127
|
+
buildPanelLine(width, [
|
|
128
|
+
[' Password ', C.label],
|
|
129
|
+
[password, C.value],
|
|
130
|
+
]),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
lines.push(createEmptyLine(width));
|
|
134
|
+
|
|
135
|
+
// ── QR code ────────────────────────────────────────────────────────────
|
|
136
|
+
const payload = encodeConnectionPayload({
|
|
137
|
+
url: this.connectionInfo.url,
|
|
138
|
+
token: this.connectionInfo.token,
|
|
139
|
+
username: this.connectionInfo.username,
|
|
140
|
+
...(this.connectionInfo.password !== undefined ? { password: this.connectionInfo.password } : {}),
|
|
141
|
+
version: this.connectionInfo.version ?? '0.0.0',
|
|
142
|
+
surface: this.connectionInfo.surface ?? 'tui',
|
|
143
|
+
});
|
|
144
|
+
const matrix = generateQrMatrix(payload);
|
|
145
|
+
const qrLines = renderQrMatrix(matrix.modules, width, { fg: C.qrFg, bg: C.qrBg });
|
|
146
|
+
for (const qrLine of qrLines) {
|
|
147
|
+
lines.push(qrLine);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
lines.push(createEmptyLine(width));
|
|
151
|
+
|
|
152
|
+
// ── Status message (ephemeral) ─────────────────────────────────────────
|
|
153
|
+
if (this.lastStatus) {
|
|
154
|
+
lines.push(
|
|
155
|
+
buildPanelLine(width, [
|
|
156
|
+
[` ${this.lastStatus} `, C.hint],
|
|
157
|
+
]),
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ── Hints ──────────────────────────────────────────────────────────────
|
|
162
|
+
const hintsLine = buildPanelLine(width, [
|
|
163
|
+
[' r ', C.hint],
|
|
164
|
+
['regenerate ', C.dim],
|
|
165
|
+
[' c ', C.hint],
|
|
166
|
+
['copy token', C.dim],
|
|
167
|
+
]);
|
|
168
|
+
|
|
169
|
+
// Push hints at the bottom if we have room, otherwise append after QR
|
|
170
|
+
const remaining = height - lines.length;
|
|
171
|
+
if (remaining > 2) {
|
|
172
|
+
// Fill with empty lines to push hints toward bottom
|
|
173
|
+
const fillCount = Math.max(0, remaining - 2);
|
|
174
|
+
for (let i = 0; i < fillCount; i++) {
|
|
175
|
+
lines.push(createEmptyLine(width));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
lines.push(hintsLine);
|
|
179
|
+
|
|
180
|
+
return lines;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Line } from '
|
|
2
|
-
import { createEmptyLine } from '
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
3
3
|
import { BasePanel } from './base-panel.ts';
|
|
4
4
|
import type { UiReadModel, UiRemoteSnapshot } from '../runtime/ui-read-models.ts';
|
|
5
5
|
import {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
resolvePrimaryScrollableSection,
|
|
15
15
|
type PanelWorkspaceSection,
|
|
16
16
|
} from './polish.ts';
|
|
17
|
-
import { truncateDisplay } from '
|
|
17
|
+
import { truncateDisplay } from '../utils/terminal-width.ts';
|
|
18
18
|
import { getTrackedVisibleWindow } from '../renderer/surface-layout.ts';
|
|
19
19
|
|
|
20
20
|
const C = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Line } from '
|
|
2
|
-
import { createEmptyLine } from '
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
3
3
|
import { BasePanel } from './base-panel.ts';
|
|
4
4
|
import type { UiReadModel, UiRoutesSnapshot } from '../runtime/ui-read-models.ts';
|
|
5
|
-
import { truncateDisplay } from '
|
|
5
|
+
import { truncateDisplay } from '../utils/terminal-width.ts';
|
|
6
6
|
import {
|
|
7
7
|
buildEmptyState,
|
|
8
8
|
buildGuidanceLine,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Line } from '
|
|
2
|
-
import { createEmptyLine } from '
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
3
3
|
import { BasePanel } from './base-panel.ts';
|
|
4
4
|
import { ConfigManager } from '@pellux/goodvibes-sdk/platform/config/manager';
|
|
5
5
|
import { buildSandboxReview, listSandboxPresets, listSandboxProfiles } from '@pellux/goodvibes-sdk/platform/runtime/sandbox/manager';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BasePanel } from './base-panel.ts';
|
|
2
|
-
import { type Line } from '
|
|
2
|
+
import { type Line } from '../types/grid.ts';
|
|
3
3
|
import type { AutomationManager } from '@pellux/goodvibes-sdk/platform/automation/index';
|
|
4
4
|
import type { AutomationJob } from '@pellux/goodvibes-sdk/platform/automation/jobs';
|
|
5
5
|
import type { AutomationRun } from '@pellux/goodvibes-sdk/platform/automation/runs';
|