@pellux/goodvibes-tui 0.27.0 → 0.29.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 +124 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/core/context-usage.ts +53 -0
- package/src/core/conversation.ts +4 -6
- package/src/core/session-recovery.ts +2 -0
- package/src/core/turn-event-wiring.ts +1 -0
- package/src/input/commands/cost-runtime.ts +49 -0
- package/src/input/commands/eval.ts +4 -3
- package/src/input/commands/operator-runtime.ts +5 -1
- package/src/input/commands.ts +2 -0
- package/src/input/handler-feed-routes.ts +60 -26
- package/src/input/handler-feed.ts +17 -8
- package/src/input/handler-picker-routes.ts +18 -13
- package/src/input/handler-shortcuts.ts +51 -0
- package/src/input/handler-ui-state.ts +4 -0
- package/src/input/handler.ts +43 -6
- package/src/input/keybindings.ts +53 -8
- package/src/input/model-picker.ts +5 -0
- package/src/input/panel-integration-actions.ts +117 -1
- package/src/main.ts +5 -2
- package/src/panels/agent-inspector-panel.ts +139 -45
- package/src/panels/agent-inspector-shared.ts +147 -3
- package/src/panels/approval-panel.ts +204 -102
- package/src/panels/automation-control-panel.ts +370 -103
- package/src/panels/base-panel.ts +26 -2
- package/src/panels/builtin/agent.ts +28 -37
- package/src/panels/builtin/development.ts +40 -32
- package/src/panels/builtin/knowledge.ts +15 -6
- package/src/panels/builtin/operations.ts +178 -117
- package/src/panels/builtin/session.ts +35 -9
- package/src/panels/builtin/shared.ts +98 -6
- package/src/panels/cockpit-panel.ts +253 -75
- package/src/panels/cockpit-read-model.ts +2 -1
- package/src/panels/communication-panel.ts +159 -56
- package/src/panels/confirm-state.ts +8 -1
- package/src/panels/control-plane-panel.ts +354 -95
- package/src/panels/cost-tracker-panel.ts +243 -57
- package/src/panels/debug-panel.ts +347 -159
- package/src/panels/diff-panel.ts +257 -82
- package/src/panels/docs-panel.ts +166 -64
- package/src/panels/eval-panel.ts +336 -109
- package/src/panels/expandable-list-panel.ts +189 -0
- package/src/panels/file-explorer-panel.ts +238 -159
- package/src/panels/file-preview-panel.ts +141 -59
- package/src/panels/git-panel.ts +360 -191
- package/src/panels/hooks-panel.ts +181 -19
- package/src/panels/incident-review-panel.ts +252 -43
- package/src/panels/index.ts +0 -4
- package/src/panels/intelligence-panel.ts +310 -103
- package/src/panels/knowledge-graph-panel.ts +480 -58
- package/src/panels/local-auth-panel.ts +251 -33
- package/src/panels/marketplace-panel.ts +219 -33
- package/src/panels/memory-panel.ts +83 -81
- package/src/panels/ops-control-panel.ts +211 -32
- package/src/panels/ops-strategy-panel.ts +131 -45
- package/src/panels/orchestration-panel.ts +259 -67
- package/src/panels/panel-list-panel.ts +184 -136
- package/src/panels/panel-manager.ts +120 -13
- package/src/panels/plan-dashboard-panel.ts +507 -74
- package/src/panels/plugins-panel.ts +227 -34
- package/src/panels/policy-panel.ts +264 -55
- package/src/panels/polish-core.ts +162 -0
- package/src/panels/polish-tables.ts +258 -0
- package/src/panels/polish.ts +67 -149
- package/src/panels/project-planning-answer-actions.ts +134 -0
- package/src/panels/project-planning-panel.ts +84 -113
- package/src/panels/provider-health-panel.ts +438 -480
- package/src/panels/provider-health-routes.ts +203 -0
- package/src/panels/provider-health-tracker.ts +194 -6
- package/src/panels/provider-health-views.ts +560 -0
- package/src/panels/qr-panel.ts +136 -38
- package/src/panels/remote-panel.ts +123 -38
- package/src/panels/routes-panel.ts +87 -24
- package/src/panels/sandbox-panel.ts +232 -65
- package/src/panels/scrollable-list-panel.ts +143 -145
- package/src/panels/security-panel.ts +204 -52
- package/src/panels/services-panel.ts +174 -76
- package/src/panels/session-browser-panel.ts +101 -6
- package/src/panels/session-maintenance.ts +4 -122
- package/src/panels/settings-sync-panel.ts +346 -68
- package/src/panels/skills-panel.ts +157 -89
- package/src/panels/subscription-panel.ts +105 -34
- package/src/panels/symbol-outline-panel.ts +287 -154
- package/src/panels/system-messages-panel.ts +172 -38
- package/src/panels/tasks-panel.ts +348 -134
- package/src/panels/thinking-panel.ts +66 -32
- package/src/panels/token-budget-panel.ts +233 -46
- package/src/panels/tool-inspector-panel.ts +170 -54
- package/src/panels/types.ts +65 -4
- package/src/panels/work-plan-panel.ts +393 -39
- package/src/panels/worktree-panel.ts +239 -61
- package/src/panels/wrfc-panel-format.ts +133 -0
- package/src/panels/wrfc-panel.ts +146 -150
- package/src/renderer/compaction-preview.ts +2 -1
- package/src/renderer/compositor.ts +46 -43
- package/src/renderer/conversation-overlays.ts +25 -11
- package/src/renderer/footer-tips.ts +41 -0
- package/src/renderer/fullscreen-primitives.ts +22 -16
- package/src/renderer/help-overlay.ts +91 -14
- package/src/renderer/hint-grammar.ts +52 -0
- package/src/renderer/layout.ts +7 -7
- package/src/renderer/modal-factory.ts +23 -15
- package/src/renderer/model-picker-overlay.ts +30 -11
- package/src/renderer/model-workspace.ts +2 -3
- package/src/renderer/overlay-box.ts +16 -10
- package/src/renderer/panel-composite.ts +7 -20
- package/src/renderer/panel-workspace-bar.ts +14 -8
- package/src/renderer/process-indicator.ts +3 -1
- package/src/renderer/progress.ts +8 -6
- package/src/renderer/search-overlay.ts +27 -6
- package/src/renderer/session-picker-modal.ts +6 -4
- package/src/renderer/settings-modal.ts +70 -10
- package/src/renderer/shell-surface.ts +41 -15
- package/src/renderer/status-glyphs.ts +11 -9
- package/src/renderer/tab-strip.ts +148 -34
- package/src/renderer/theme.ts +60 -3
- package/src/renderer/ui-factory.ts +45 -36
- package/src/renderer/ui-primitives.ts +23 -2
- package/src/runtime/bootstrap-shell.ts +35 -18
- package/src/runtime/diagnostics/panels/index.ts +0 -3
- package/src/runtime/ui/model-picker/health-enrichment.ts +3 -0
- package/src/runtime/ui/model-picker/types.ts +4 -0
- package/src/shell/ui-openers.ts +14 -22
- package/src/utils/format-duration.ts +55 -0
- package/src/utils/format-number.ts +71 -0
- package/src/utils/splash-lines.ts +44 -3
- package/src/version.ts +1 -1
- package/src/work-plans/work-plan-store.ts +13 -0
- package/src/panels/agent-logs-panel.ts +0 -666
- package/src/panels/agent-logs-shared.ts +0 -129
- package/src/panels/context-visualizer-panel.ts +0 -214
- package/src/panels/forensics-panel.ts +0 -364
- package/src/panels/panel-picker.ts +0 -106
- package/src/panels/provider-account-snapshot.ts +0 -259
- package/src/panels/provider-accounts-panel.ts +0 -218
- package/src/panels/provider-stats-panel.ts +0 -366
- package/src/panels/schedule-panel.ts +0 -342
- package/src/panels/watchers-panel.ts +0 -193
- package/src/renderer/panel-picker-overlay.ts +0 -202
- package/src/renderer/panel-tab-bar.ts +0 -69
- package/src/runtime/diagnostics/panels/panel-resources.ts +0 -118
- package/src/runtime/diagnostics/panels/policy.ts +0 -177
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type { Line } from '../types/grid.ts';
|
|
2
|
+
import { createEmptyLine } from '../types/grid.ts';
|
|
3
|
+
import { ScrollableListPanel } from './scrollable-list-panel.ts';
|
|
4
|
+
import {
|
|
5
|
+
buildKeyboardHints,
|
|
6
|
+
buildPanelWorkspace,
|
|
7
|
+
resolveScrollablePanelSection,
|
|
8
|
+
} from './polish.ts';
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// ExpandableListPanel<T>
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A list panel with a built-in master → detail drill-down.
|
|
16
|
+
*
|
|
17
|
+
* Encapsulates the collapse/expand + detail-view pattern that was previously
|
|
18
|
+
* hand-rolled in git, tool-inspector, agent-inspector, approval, and wrfc
|
|
19
|
+
* panels: a scrollable list where pressing Enter/→ on a row opens a scrollable
|
|
20
|
+
* detail view for that item, and Esc/← returns to the list.
|
|
21
|
+
*
|
|
22
|
+
* Subclasses implement (in addition to the `ScrollableListPanel` contract):
|
|
23
|
+
* - `getDetailLines(item, width)` — the detail body for the expanded item.
|
|
24
|
+
*
|
|
25
|
+
* Optionally override:
|
|
26
|
+
* - `getDetailTitle(item)` — detail-view title (defaults to `this.name`).
|
|
27
|
+
* - `getListHints()` / `getDetailHints()` — footer keyboard hints per mode.
|
|
28
|
+
* - `renderListView(width, height)` — the list-mode body (defaults to
|
|
29
|
+
* `renderList` with the list hints footer).
|
|
30
|
+
*
|
|
31
|
+
* Do NOT override `render()`; it dispatches between list and detail modes.
|
|
32
|
+
*/
|
|
33
|
+
export abstract class ExpandableListPanel<T> extends ScrollableListPanel<T> {
|
|
34
|
+
/** The item currently expanded into the detail view, or null in list mode. */
|
|
35
|
+
protected expandedItem: T | null = null;
|
|
36
|
+
/** First visible row of the detail view. */
|
|
37
|
+
protected detailScroll = 0;
|
|
38
|
+
|
|
39
|
+
/** Render the detail body lines for an expanded item. */
|
|
40
|
+
protected abstract getDetailLines(item: T, width: number): readonly Line[];
|
|
41
|
+
|
|
42
|
+
/** Title shown above the detail view. */
|
|
43
|
+
protected getDetailTitle(_item: T): string {
|
|
44
|
+
return this.name;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Keyboard hints shown in list mode. */
|
|
48
|
+
protected getListHints(): ReadonlyArray<{ keys: string; label: string }> {
|
|
49
|
+
return [
|
|
50
|
+
{ keys: '↑/↓', label: 'move' },
|
|
51
|
+
{ keys: 'Enter', label: 'open' },
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Keyboard hints shown in detail mode. */
|
|
56
|
+
protected getDetailHints(): ReadonlyArray<{ keys: string; label: string }> {
|
|
57
|
+
return [
|
|
58
|
+
{ keys: '↑/↓', label: 'scroll' },
|
|
59
|
+
{ keys: 'Esc', label: 'back' },
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
protected isExpanded(): boolean {
|
|
64
|
+
return this.expandedItem !== null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Expand the currently selected item into the detail view. */
|
|
68
|
+
protected expandSelected(): void {
|
|
69
|
+
const items = this.getItems();
|
|
70
|
+
const item = items[this.selectedIndex];
|
|
71
|
+
if (item === undefined) return;
|
|
72
|
+
this.expandedItem = item;
|
|
73
|
+
this.detailScroll = 0;
|
|
74
|
+
this.needsRender = true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Collapse the detail view back to the list. */
|
|
78
|
+
protected collapse(): void {
|
|
79
|
+
if (this.expandedItem === null) return;
|
|
80
|
+
this.expandedItem = null;
|
|
81
|
+
this.detailScroll = 0;
|
|
82
|
+
this.needsRender = true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// -------------------------------------------------------------------------
|
|
86
|
+
// Input
|
|
87
|
+
// -------------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
handleInput(key: string): boolean {
|
|
90
|
+
if (this.expandedItem !== null) {
|
|
91
|
+
// Detail mode: scroll the detail body; Esc/← collapses.
|
|
92
|
+
if (this.lastError !== null) this.clearError();
|
|
93
|
+
switch (key) {
|
|
94
|
+
case 'escape':
|
|
95
|
+
case 'left':
|
|
96
|
+
case 'h':
|
|
97
|
+
this.collapse();
|
|
98
|
+
return true;
|
|
99
|
+
case 'up':
|
|
100
|
+
case 'k':
|
|
101
|
+
this.detailScroll = Math.max(0, this.detailScroll - 1);
|
|
102
|
+
this.needsRender = true;
|
|
103
|
+
return true;
|
|
104
|
+
case 'down':
|
|
105
|
+
case 'j':
|
|
106
|
+
this.detailScroll += 1;
|
|
107
|
+
this.needsRender = true;
|
|
108
|
+
return true;
|
|
109
|
+
case 'pageup':
|
|
110
|
+
this.detailScroll = Math.max(0, this.detailScroll - this.getPageSize());
|
|
111
|
+
this.needsRender = true;
|
|
112
|
+
return true;
|
|
113
|
+
case 'pagedown':
|
|
114
|
+
this.detailScroll += this.getPageSize();
|
|
115
|
+
this.needsRender = true;
|
|
116
|
+
return true;
|
|
117
|
+
case 'home':
|
|
118
|
+
case 'g':
|
|
119
|
+
this.detailScroll = 0;
|
|
120
|
+
this.needsRender = true;
|
|
121
|
+
return true;
|
|
122
|
+
default:
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// List mode: Enter/→ expands; everything else is list navigation.
|
|
128
|
+
if (key === 'enter' || key === 'return' || key === 'right' || key === 'l') {
|
|
129
|
+
if (this.getItems().length === 0) return false;
|
|
130
|
+
this.expandSelected();
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
return super.handleInput(key);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
handleScroll(deltaRows: number): boolean {
|
|
137
|
+
if (this.expandedItem !== null) {
|
|
138
|
+
const rows = Math.trunc(deltaRows);
|
|
139
|
+
if (rows === 0) return false;
|
|
140
|
+
this.detailScroll = Math.max(0, this.detailScroll + rows);
|
|
141
|
+
this.needsRender = true;
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
return super.handleScroll(deltaRows);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// -------------------------------------------------------------------------
|
|
148
|
+
// Render
|
|
149
|
+
// -------------------------------------------------------------------------
|
|
150
|
+
|
|
151
|
+
render(width: number, height: number): Line[] {
|
|
152
|
+
if (this.expandedItem !== null) {
|
|
153
|
+
return this.renderDetailView(width, height, this.expandedItem);
|
|
154
|
+
}
|
|
155
|
+
return this.renderListView(width, height);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** List-mode body. Override for a custom header; defaults to renderList. */
|
|
159
|
+
protected renderListView(width: number, height: number): Line[] {
|
|
160
|
+
return this.renderList(width, height, { hints: this.getListHints() });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Detail-mode body — scrollable detail lines + standardized chrome. */
|
|
164
|
+
protected renderDetailView(width: number, height: number, item: T): Line[] {
|
|
165
|
+
this.needsRender = false;
|
|
166
|
+
const palette = this.getPalette();
|
|
167
|
+
const detailLines = [...this.getDetailLines(item, width)];
|
|
168
|
+
const footer = buildKeyboardHints(width, this.getDetailHints(), palette);
|
|
169
|
+
|
|
170
|
+
const resolved = resolveScrollablePanelSection(width, height, {
|
|
171
|
+
palette,
|
|
172
|
+
afterSections: [{ lines: [footer] }],
|
|
173
|
+
section: {
|
|
174
|
+
scrollableLines: detailLines,
|
|
175
|
+
scrollOffset: this.detailScroll,
|
|
176
|
+
appendWindowSummary: detailLines.length > 5 ? { dimColor: palette.dim } : undefined,
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
this.detailScroll = resolved.scrollOffset;
|
|
180
|
+
|
|
181
|
+
const lines = buildPanelWorkspace(width, height, {
|
|
182
|
+
title: this.getDetailTitle(item),
|
|
183
|
+
sections: [resolved.section, { lines: [footer] }],
|
|
184
|
+
palette,
|
|
185
|
+
});
|
|
186
|
+
while (lines.length < height) lines.push(createEmptyLine(width));
|
|
187
|
+
return lines.slice(0, height);
|
|
188
|
+
}
|
|
189
|
+
}
|