@pellux/goodvibes-tui 0.28.0 → 1.0.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 +133 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/core/conversation-line-cache.ts +432 -0
- package/src/core/conversation-rendering.ts +11 -3
- package/src/core/conversation.ts +50 -4
- package/src/input/commands/cost-runtime.ts +49 -0
- package/src/input/commands/operator-runtime.ts +5 -1
- package/src/input/commands.ts +2 -0
- package/src/input/handler-content-actions.ts +8 -3
- package/src/input/handler-feed-routes.ts +12 -35
- package/src/input/handler-feed.ts +4 -8
- package/src/input/handler-shortcuts.ts +51 -0
- package/src/input/handler.ts +43 -6
- package/src/input/input-history.ts +17 -4
- package/src/input/keybindings.ts +48 -8
- package/src/input/panel-integration-actions.ts +107 -1
- package/src/main.ts +19 -11
- package/src/panels/agent-inspector-panel.ts +125 -36
- package/src/panels/agent-inspector-shared.ts +144 -0
- package/src/panels/approval-panel.ts +67 -16
- package/src/panels/automation-control-panel.ts +368 -124
- package/src/panels/base-panel.ts +1 -1
- 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 +232 -73
- package/src/panels/communication-panel.ts +58 -20
- package/src/panels/confirm-state.ts +8 -1
- package/src/panels/control-plane-panel.ts +351 -118
- package/src/panels/cost-tracker-panel.ts +165 -7
- package/src/panels/debug-panel.ts +312 -159
- package/src/panels/diff-panel.ts +209 -57
- package/src/panels/docs-panel.ts +152 -66
- package/src/panels/eval-panel.ts +220 -42
- package/src/panels/file-explorer-panel.ts +202 -122
- package/src/panels/file-preview-panel.ts +132 -57
- package/src/panels/git-panel.ts +310 -129
- package/src/panels/hooks-panel.ts +150 -22
- package/src/panels/incident-review-panel.ts +223 -35
- package/src/panels/index.ts +0 -4
- package/src/panels/intelligence-panel.ts +212 -86
- package/src/panels/knowledge-graph-panel.ts +461 -101
- package/src/panels/local-auth-panel.ts +240 -28
- package/src/panels/marketplace-panel.ts +193 -26
- package/src/panels/memory-panel.ts +78 -77
- package/src/panels/ops-control-panel.ts +146 -29
- package/src/panels/ops-strategy-panel.ts +72 -4
- package/src/panels/orchestration-panel.ts +231 -69
- package/src/panels/panel-list-panel.ts +154 -131
- package/src/panels/panel-manager.ts +97 -9
- package/src/panels/plan-dashboard-panel.ts +333 -17
- package/src/panels/plugins-panel.ts +184 -29
- package/src/panels/policy-panel.ts +210 -38
- package/src/panels/polish-core.ts +7 -2
- package/src/panels/polish.ts +23 -4
- package/src/panels/project-planning-answer-actions.ts +134 -0
- package/src/panels/project-planning-panel.ts +62 -113
- package/src/panels/provider-health-panel.ts +434 -518
- 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 +116 -30
- package/src/panels/remote-panel.ts +114 -36
- package/src/panels/routes-panel.ts +63 -22
- package/src/panels/sandbox-panel.ts +174 -42
- package/src/panels/scrollable-list-panel.ts +19 -135
- package/src/panels/security-panel.ts +133 -33
- package/src/panels/services-panel.ts +116 -64
- package/src/panels/session-browser-panel.ts +73 -2
- package/src/panels/session-maintenance.ts +4 -122
- package/src/panels/settings-sync-panel.ts +335 -72
- package/src/panels/skills-panel.ts +157 -89
- package/src/panels/subscription-panel.ts +86 -33
- package/src/panels/symbol-outline-panel.ts +248 -108
- package/src/panels/system-messages-panel.ts +114 -13
- package/src/panels/tasks-panel.ts +326 -139
- package/src/panels/thinking-panel.ts +43 -10
- package/src/panels/token-budget-panel.ts +194 -18
- package/src/panels/tool-inspector-panel.ts +144 -34
- package/src/panels/types.ts +40 -4
- package/src/panels/work-plan-panel.ts +280 -17
- package/src/panels/worktree-panel.ts +175 -42
- package/src/panels/wrfc-panel.ts +116 -24
- package/src/renderer/agent-detail-modal.ts +37 -8
- package/src/renderer/code-block.ts +58 -28
- package/src/renderer/context-inspector.ts +3 -6
- package/src/renderer/conversation-overlays.ts +25 -11
- package/src/renderer/conversation-surface.ts +1 -21
- package/src/renderer/diff-view.ts +6 -4
- package/src/renderer/footer-tips.ts +41 -0
- package/src/renderer/fullscreen-primitives.ts +23 -17
- package/src/renderer/fullscreen-workspace.ts +2 -7
- package/src/renderer/help-overlay.ts +91 -14
- package/src/renderer/hint-grammar.ts +52 -0
- package/src/renderer/history-search-overlay.ts +10 -16
- package/src/renderer/layout.ts +7 -7
- package/src/renderer/markdown.ts +9 -1
- package/src/renderer/modal-factory.ts +23 -15
- package/src/renderer/model-picker-overlay.ts +8 -485
- package/src/renderer/model-workspace.ts +9 -24
- package/src/renderer/overlay-box.ts +23 -19
- package/src/renderer/process-indicator.ts +15 -25
- package/src/renderer/profile-picker-modal.ts +13 -14
- package/src/renderer/prompt-content-width.ts +16 -0
- package/src/renderer/search-overlay.ts +27 -6
- package/src/renderer/selection-modal-overlay.ts +3 -1
- package/src/renderer/semantic-diff.ts +1 -1
- package/src/renderer/session-picker-modal.ts +6 -4
- package/src/renderer/settings-modal-helpers.ts +10 -34
- package/src/renderer/settings-modal.ts +70 -10
- package/src/renderer/shell-surface.ts +54 -15
- package/src/renderer/status-glyphs.ts +11 -9
- package/src/renderer/surface-layout.ts +0 -12
- package/src/renderer/term-caps.ts +1 -1
- package/src/renderer/theme.ts +60 -3
- package/src/renderer/tool-call.ts +6 -20
- package/src/renderer/ui-factory.ts +48 -37
- package/src/renderer/ui-primitives.ts +41 -3
- package/src/runtime/bootstrap-shell.ts +35 -18
- package/src/runtime/diagnostics/panels/index.ts +0 -3
- package/src/runtime/render-scheduler.ts +80 -0
- package/src/shell/ui-openers.ts +14 -22
- package/src/utils/format-duration.ts +2 -2
- package/src/utils/splash-lines.ts +54 -5
- package/src/version.ts +1 -1
- package/src/work-plans/work-plan-store.ts +13 -0
- package/src/panels/agent-logs-panel.ts +0 -635
- package/src/panels/agent-logs-shared.ts +0 -129
- package/src/panels/context-visualizer-panel.ts +0 -238
- package/src/panels/forensics-panel.ts +0 -378
- package/src/panels/provider-account-snapshot.ts +0 -259
- package/src/panels/provider-accounts-panel.ts +0 -255
- package/src/panels/provider-stats-panel.ts +0 -391
- package/src/panels/schedule-panel.ts +0 -365
- package/src/panels/watchers-panel.ts +0 -213
- package/src/renderer/file-tree.ts +0 -153
- package/src/renderer/progress.ts +0 -99
- package/src/renderer/status-token.ts +0 -67
- package/src/runtime/diagnostics/panels/panel-resources.ts +0 -118
- package/src/runtime/diagnostics/panels/policy.ts +0 -177
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { ScrollableListPanel } from './scrollable-list-panel.ts';
|
|
10
|
-
import type
|
|
10
|
+
import { createEmptyLine, type Line } from '../types/grid.ts';
|
|
11
11
|
import type { ComponentHealthMonitor } from '../runtime/perf/panel-health-monitor.ts';
|
|
12
12
|
import {
|
|
13
13
|
buildBodyText,
|
|
@@ -26,13 +26,24 @@ import {
|
|
|
26
26
|
type PanelPalette,
|
|
27
27
|
type PanelWorkspaceSection,
|
|
28
28
|
} from './polish.ts';
|
|
29
|
+
import { type ConfirmState, handleConfirmInput, renderConfirmLines } from './confirm-state.ts';
|
|
29
30
|
import { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
30
31
|
|
|
31
32
|
const MAX_MESSAGES = 500;
|
|
32
33
|
|
|
34
|
+
// UI message-routing targets (ui.systemMessages / ui.operationalMessages /
|
|
35
|
+
// ui.wrfcMessages) all share the same enum. Cycled in-panel by s/o/w and
|
|
36
|
+
// persisted via ConfigManager.set (WO-137).
|
|
37
|
+
type RouteTarget = 'panel' | 'conversation' | 'both';
|
|
38
|
+
const ROUTE_CYCLE: readonly RouteTarget[] = ['panel', 'conversation', 'both'];
|
|
39
|
+
function nextRoute(current: string): RouteTarget {
|
|
40
|
+
const idx = ROUTE_CYCLE.indexOf(current as RouteTarget);
|
|
41
|
+
return ROUTE_CYCLE[(idx + 1 + ROUTE_CYCLE.length) % ROUTE_CYCLE.length]!;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Domain accents only; the title band comes straight from
|
|
45
|
+
// DEFAULT_PANEL_PALETTE (WO-002).
|
|
33
46
|
const C = extendPalette(DEFAULT_PANEL_PALETTE, {
|
|
34
|
-
header: '#00ffff',
|
|
35
|
-
headerBg: '#0f172a',
|
|
36
47
|
high: '#fbbf24',
|
|
37
48
|
low: '#9ca3af',
|
|
38
49
|
ts: '#6b7280',
|
|
@@ -46,6 +57,10 @@ export interface SystemMessageEntry {
|
|
|
46
57
|
priority: SystemMessagePriority;
|
|
47
58
|
}
|
|
48
59
|
|
|
60
|
+
// One-key priority cycle (all -> high -> low -> all), applied on top of the
|
|
61
|
+
// existing text filter rather than replacing it.
|
|
62
|
+
const PRIORITY_CYCLE: ReadonlyArray<'' | SystemMessagePriority> = ['', 'high', 'low'];
|
|
63
|
+
|
|
49
64
|
function fmtTime(ts: number): string {
|
|
50
65
|
const d = new Date(ts);
|
|
51
66
|
const hh = String(d.getHours()).padStart(2, '0');
|
|
@@ -57,9 +72,13 @@ function fmtTime(ts: number): string {
|
|
|
57
72
|
export class SystemMessagesPanel extends ScrollableListPanel<SystemMessageEntry> {
|
|
58
73
|
private _messages: SystemMessageEntry[] = [];
|
|
59
74
|
private readonly configManager: ConfigManager;
|
|
75
|
+
/** '' = all priorities; set via the one-key priority cycle ('p'). */
|
|
76
|
+
private priorityFilter: '' | SystemMessagePriority = '';
|
|
77
|
+
/** c=clear backlog confirmation. */
|
|
78
|
+
private confirmClear: ConfirmState<'clear'> | null = null;
|
|
60
79
|
|
|
61
80
|
constructor(configManager: ConfigManager, componentHealthMonitor?: ComponentHealthMonitor) {
|
|
62
|
-
super('system-messages', 'System Messages', '
|
|
81
|
+
super('system-messages', 'System Messages', '▥', 'runtime-ops', componentHealthMonitor);
|
|
63
82
|
this.configManager = configManager;
|
|
64
83
|
this.filterEnabled = true;
|
|
65
84
|
this.filterLabel = 'Filter messages';
|
|
@@ -69,6 +88,13 @@ export class SystemMessagesPanel extends ScrollableListPanel<SystemMessageEntry>
|
|
|
69
88
|
return entry.text.toLowerCase().includes(q) || entry.priority.toLowerCase().includes(q);
|
|
70
89
|
}
|
|
71
90
|
|
|
91
|
+
/** Text filter (base class) combined with the priority cycle filter. */
|
|
92
|
+
protected override getVisibleItems(): readonly SystemMessageEntry[] {
|
|
93
|
+
const base = super.getVisibleItems();
|
|
94
|
+
if (!this.priorityFilter) return base;
|
|
95
|
+
return base.filter((entry) => entry.priority === this.priorityFilter);
|
|
96
|
+
}
|
|
97
|
+
|
|
72
98
|
// ---------------------------------------------------------------------------
|
|
73
99
|
// ScrollableListPanel contract
|
|
74
100
|
// ---------------------------------------------------------------------------
|
|
@@ -111,13 +137,21 @@ export class SystemMessagesPanel extends ScrollableListPanel<SystemMessageEntry>
|
|
|
111
137
|
// ---------------------------------------------------------------------------
|
|
112
138
|
|
|
113
139
|
push(text: string, priority: SystemMessagePriority): void {
|
|
140
|
+
// Follow-mode: only auto-jump to the new message when the selection was
|
|
141
|
+
// already at the tail of what's currently visible. Otherwise the user is
|
|
142
|
+
// reviewing history and a new low-priority message shouldn't yank the
|
|
143
|
+
// cursor out from under them.
|
|
144
|
+
const visibleBefore = this.getVisibleItems();
|
|
145
|
+
const wasAtTail = visibleBefore.length === 0 || this.selectedIndex >= visibleBefore.length - 1;
|
|
114
146
|
this._messages.push({ ts: Date.now(), text, priority });
|
|
115
147
|
if (this._messages.length > MAX_MESSAGES) {
|
|
116
148
|
this._messages.shift();
|
|
117
149
|
if (this.selectedIndex > 0) this.selectedIndex--;
|
|
118
150
|
}
|
|
119
|
-
|
|
120
|
-
|
|
151
|
+
if (wasAtTail) {
|
|
152
|
+
const visibleAfter = this.getVisibleItems();
|
|
153
|
+
this.selectedIndex = Math.max(0, visibleAfter.length - 1);
|
|
154
|
+
}
|
|
121
155
|
this.markDirty();
|
|
122
156
|
}
|
|
123
157
|
|
|
@@ -130,9 +164,60 @@ export class SystemMessagesPanel extends ScrollableListPanel<SystemMessageEntry>
|
|
|
130
164
|
}
|
|
131
165
|
|
|
132
166
|
// ---------------------------------------------------------------------------
|
|
133
|
-
// Input
|
|
167
|
+
// Input
|
|
134
168
|
// ---------------------------------------------------------------------------
|
|
135
169
|
|
|
170
|
+
override handleInput(key: string): boolean {
|
|
171
|
+
const confirmResult = handleConfirmInput(this.confirmClear, key);
|
|
172
|
+
if (confirmResult === 'confirmed') {
|
|
173
|
+
this.confirmClear = null;
|
|
174
|
+
this._messages = [];
|
|
175
|
+
this.selectedIndex = 0;
|
|
176
|
+
this.markDirty();
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
if (confirmResult === 'cancelled') {
|
|
180
|
+
this.confirmClear = null;
|
|
181
|
+
this.markDirty();
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
if (confirmResult === 'absorbed') return true;
|
|
185
|
+
|
|
186
|
+
if (!this.filterActive && key === 'p') {
|
|
187
|
+
const idx = PRIORITY_CYCLE.indexOf(this.priorityFilter);
|
|
188
|
+
this.priorityFilter = PRIORITY_CYCLE[(idx + 1) % PRIORITY_CYCLE.length]!;
|
|
189
|
+
this.selectedIndex = 0;
|
|
190
|
+
this.markDirty();
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
if (!this.filterActive && key === 's') {
|
|
194
|
+
const ui = this.configManager.getRaw().ui;
|
|
195
|
+
this.configManager.set('ui.systemMessages', nextRoute(ui.systemMessages));
|
|
196
|
+
this.markDirty();
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
if (!this.filterActive && key === 'o') {
|
|
200
|
+
const ui = this.configManager.getRaw().ui;
|
|
201
|
+
this.configManager.set('ui.operationalMessages', nextRoute(ui.operationalMessages));
|
|
202
|
+
this.markDirty();
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
if (!this.filterActive && key === 'w') {
|
|
206
|
+
const ui = this.configManager.getRaw().ui;
|
|
207
|
+
this.configManager.set('ui.wrfcMessages', nextRoute(ui.wrfcMessages));
|
|
208
|
+
this.markDirty();
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
if (!this.filterActive && key === 'c') {
|
|
212
|
+
if (this._messages.length === 0) return false;
|
|
213
|
+
this.confirmClear = { subject: 'clear', label: `${this._messages.length} system message(s)`, verb: 'Clear' };
|
|
214
|
+
this.markDirty();
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return super.handleInput(key);
|
|
219
|
+
}
|
|
220
|
+
|
|
136
221
|
// ---------------------------------------------------------------------------
|
|
137
222
|
// Render — multi-section layout (posture + list + detail)
|
|
138
223
|
// ---------------------------------------------------------------------------
|
|
@@ -143,6 +228,7 @@ export class SystemMessagesPanel extends ScrollableListPanel<SystemMessageEntry>
|
|
|
143
228
|
const hints: Array<{ keys: string; label: string }> = [
|
|
144
229
|
{ keys: 'j/k', label: 'scroll' },
|
|
145
230
|
{ keys: 'g/G', label: 'jump' },
|
|
231
|
+
{ keys: 'p', label: 'priority' },
|
|
146
232
|
];
|
|
147
233
|
if (this.filterActive) {
|
|
148
234
|
hints.push({ keys: 'Esc', label: 'clear filter' });
|
|
@@ -150,12 +236,24 @@ export class SystemMessagesPanel extends ScrollableListPanel<SystemMessageEntry>
|
|
|
150
236
|
hints.push({ keys: '/', label: 'edit filter' }, { keys: 'Esc', label: 'clear filter' });
|
|
151
237
|
} else {
|
|
152
238
|
hints.push({ keys: '/', label: 'filter' });
|
|
239
|
+
if (this._messages.length > 0) hints.push({ keys: 'c', label: 'clear' });
|
|
153
240
|
}
|
|
154
241
|
return hints;
|
|
155
242
|
}
|
|
156
243
|
|
|
157
244
|
override render(width: number, height: number): Line[] {
|
|
158
245
|
return this.trackedRender(() => {
|
|
246
|
+
if (this.confirmClear) {
|
|
247
|
+
this.needsRender = false;
|
|
248
|
+
const lines = buildPanelWorkspace(width, height, {
|
|
249
|
+
title: 'System Messages',
|
|
250
|
+
sections: [{ title: 'Confirmation', lines: renderConfirmLines(width, this.confirmClear) }],
|
|
251
|
+
palette: C,
|
|
252
|
+
});
|
|
253
|
+
while (lines.length < height) lines.push(createEmptyLine(width));
|
|
254
|
+
return lines.slice(0, height);
|
|
255
|
+
}
|
|
256
|
+
|
|
159
257
|
const intro = 'Operational system traffic routed out of the main conversation to reduce noise and keep runtime status reviewable.';
|
|
160
258
|
|
|
161
259
|
if (this._messages.length === 0) {
|
|
@@ -198,19 +296,22 @@ export class SystemMessagesPanel extends ScrollableListPanel<SystemMessageEntry>
|
|
|
198
296
|
...(latest ? ([[' newest ', C.label], [`${fmtTime(latest.ts)}`, C.value]] as Array<[string, string]>) : []),
|
|
199
297
|
]),
|
|
200
298
|
buildKeyValueLine(width, [
|
|
201
|
-
{ label: 'system route', value: ui.systemMessages, valueColor: C.info },
|
|
202
|
-
{ label: 'ops route', value: ui.operationalMessages, valueColor: C.info },
|
|
203
|
-
{ label: 'wrfc route', value: ui.wrfcMessages, valueColor: C.info },
|
|
299
|
+
{ label: 'system route (s)', value: ui.systemMessages, valueColor: C.info },
|
|
300
|
+
{ label: 'ops route (o)', value: ui.operationalMessages, valueColor: C.info },
|
|
301
|
+
{ label: 'wrfc route (w)', value: ui.wrfcMessages, valueColor: C.info },
|
|
204
302
|
], C),
|
|
205
|
-
buildGuidanceLine(width, '/settings', '
|
|
303
|
+
buildGuidanceLine(width, '/settings', 'review the full settings surface (routing is also toggleable in-panel with s/o/w)', C),
|
|
206
304
|
];
|
|
207
305
|
|
|
208
306
|
const visible = this.getVisibleItems();
|
|
209
307
|
this.selectedIndex = Math.max(0, Math.min(this.selectedIndex, visible.length - 1));
|
|
210
|
-
const selected =
|
|
308
|
+
const selected = this.getSelectedItem();
|
|
309
|
+
const noMatchReason = this.filterQuery.trim()
|
|
310
|
+
? `"${this.filterQuery.trim()}"${this.priorityFilter ? ` + priority:${this.priorityFilter}` : ''}`
|
|
311
|
+
: `priority:${this.priorityFilter}`;
|
|
211
312
|
const messageRows: Line[] = visible.length > 0
|
|
212
313
|
? visible.map((entry, index) => this.renderItem(entry, index, index === this.selectedIndex, width))
|
|
213
|
-
: [buildPanelLine(width, [[` No messages match
|
|
314
|
+
: [buildPanelLine(width, [[` No messages match ${noMatchReason} (Esc to clear filter, p to reset priority)`, C.dim]])];
|
|
214
315
|
|
|
215
316
|
const filterSection: PanelWorkspaceSection = { lines: [this.buildFilterLine(width)] };
|
|
216
317
|
const postureSection: PanelWorkspaceSection = { lines: buildSummaryBlock(width, 'System posture', postureLines, C) };
|