@pellux/goodvibes-tui 1.1.0 → 1.7.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 +20 -11
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +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/conversation-rendering.ts +19 -0
- 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/system-message-router.ts +37 -51
- package/src/core/turn-cancellation.ts +20 -0
- package/src/core/turn-event-wiring.ts +64 -3
- package/src/export/cost-utils.ts +36 -0
- package/src/input/command-registry.ts +38 -1
- package/src/input/commands/checkpoint-runtime.ts +280 -0
- package/src/input/commands/codebase-runtime.ts +192 -0
- package/src/input/commands/eval.ts +1 -1
- package/src/input/commands/health-runtime.ts +1 -1
- 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 +6 -1
- package/src/input/commands/operator-panel-runtime.ts +40 -24
- package/src/input/commands/planning-runtime.ts +26 -3
- 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 +3 -3
- package/src/input/commands/recall-review.ts +35 -0
- 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-workflow.ts +16 -1
- package/src/input/commands/settings-sync-runtime.ts +1 -1
- package/src/input/commands/shell-core.ts +15 -7
- 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 +338 -0
- package/src/input/commands.ts +12 -0
- package/src/input/config-modal-types.ts +161 -0
- package/src/input/config-modal.ts +377 -0
- package/src/input/feed-context-factory.ts +7 -8
- package/src/input/handler-command-route.ts +27 -17
- package/src/input/handler-feed-routes.ts +61 -23
- package/src/input/handler-feed.ts +47 -23
- package/src/input/handler-interactions.ts +1 -3
- package/src/input/handler-modal-routes.ts +65 -0
- package/src/input/handler-modal-stack.ts +3 -5
- package/src/input/handler-modal-token-routes.ts +16 -49
- package/src/input/handler-picker-routes.ts +11 -94
- package/src/input/handler-shortcuts.ts +24 -14
- package/src/input/handler-types.ts +2 -6
- package/src/input/handler-ui-state.ts +10 -22
- package/src/input/handler.ts +6 -28
- package/src/input/keybindings.ts +22 -8
- package/src/input/model-picker-types.ts +24 -6
- package/src/input/model-picker.ts +58 -0
- package/src/input/panel-integration-actions.ts +9 -170
- package/src/input/settings-modal-data.ts +95 -0
- package/src/input/settings-modal-mutations.ts +6 -4
- package/src/main.ts +24 -27
- 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 +9 -43
- 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-panel.ts +800 -0
- package/src/panels/fleet-read-model.ts +477 -0
- package/src/panels/fleet-steer.ts +92 -0
- package/src/panels/fleet-stop.ts +125 -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 +151 -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 +36 -0
- package/src/panels/modals/pairing-modal.ts +144 -0
- package/src/panels/modals/planning-modal.ts +282 -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 +149 -0
- package/src/panels/panel-confirm-overlay.ts +72 -0
- package/src/panels/panel-manager.ts +108 -5
- package/src/panels/project-planning-answer-actions.ts +4 -2
- package/src/panels/skills-panel.ts +7 -51
- package/src/panels/types.ts +13 -0
- package/src/permissions/hunk-selection.ts +179 -0
- package/src/permissions/prompt.ts +60 -4
- 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/config-modal.ts +81 -0
- package/src/renderer/conversation-overlays.ts +10 -17
- package/src/renderer/fleet-tab-strip.ts +56 -0
- package/src/renderer/footer-tips.ts +10 -2
- package/src/renderer/git-status.ts +40 -0
- package/src/renderer/help-overlay.ts +2 -2
- package/src/renderer/model-workspace.ts +44 -1
- package/src/renderer/panel-workspace-bar.ts +8 -2
- package/src/renderer/turn-injection.ts +114 -0
- package/src/runtime/bootstrap-command-context.ts +21 -1
- package/src/runtime/bootstrap-command-parts.ts +34 -7
- package/src/runtime/bootstrap-core.ts +14 -4
- package/src/runtime/bootstrap-shell.ts +29 -16
- package/src/runtime/bootstrap.ts +11 -17
- package/src/runtime/code-index-services.ts +112 -0
- package/src/runtime/orchestrator-core-services.ts +49 -0
- package/src/runtime/process-lifecycle.ts +3 -1
- package/src/runtime/services.ts +91 -43
- package/src/runtime/ui-services.ts +8 -0
- package/src/runtime/workstream-services.ts +195 -0
- package/src/shell/blocking-input.ts +22 -1
- package/src/shell/ui-openers.ts +129 -17
- package/src/utils/format-duration.ts +8 -18
- package/src/utils/splash-lines.ts +1 -1
- 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,364 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SystemMessagesPanel — displays operational system messages routed away
|
|
3
|
-
* from the main conversation.
|
|
4
|
-
*
|
|
5
|
-
* Migrated (Wave B2): extends ScrollableListPanel<SystemMessageEntry>.
|
|
6
|
-
* Navigation (up/down/j/k/pageup/pagedown/g/G) is handled by the base class.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { ScrollableListPanel } from './scrollable-list-panel.ts';
|
|
10
|
-
import { createEmptyLine, type Line } from '../types/grid.ts';
|
|
11
|
-
import type { ComponentHealthMonitor } from '../runtime/perf/panel-health-monitor.ts';
|
|
12
|
-
import {
|
|
13
|
-
buildBodyText,
|
|
14
|
-
buildEmptyState,
|
|
15
|
-
buildGuidanceLine,
|
|
16
|
-
buildKeyValueLine,
|
|
17
|
-
buildKeyboardHints,
|
|
18
|
-
buildPanelListRow,
|
|
19
|
-
buildPanelLine,
|
|
20
|
-
buildStatusBadge,
|
|
21
|
-
buildSummaryBlock,
|
|
22
|
-
buildPanelWorkspace,
|
|
23
|
-
resolvePrimaryScrollableSection,
|
|
24
|
-
DEFAULT_PANEL_PALETTE,
|
|
25
|
-
extendPalette,
|
|
26
|
-
type PanelPalette,
|
|
27
|
-
type PanelWorkspaceSection,
|
|
28
|
-
} from './polish.ts';
|
|
29
|
-
import { type ConfirmState, handleConfirmInput, renderConfirmLines } from './confirm-state.ts';
|
|
30
|
-
import { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
31
|
-
|
|
32
|
-
const MAX_MESSAGES = 500;
|
|
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).
|
|
46
|
-
const C = extendPalette(DEFAULT_PANEL_PALETTE, {
|
|
47
|
-
high: '#fbbf24',
|
|
48
|
-
low: '#9ca3af',
|
|
49
|
-
ts: '#6b7280',
|
|
50
|
-
} as const);
|
|
51
|
-
|
|
52
|
-
export type SystemMessagePriority = 'high' | 'low';
|
|
53
|
-
|
|
54
|
-
export interface SystemMessageEntry {
|
|
55
|
-
ts: number;
|
|
56
|
-
text: string;
|
|
57
|
-
priority: SystemMessagePriority;
|
|
58
|
-
}
|
|
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
|
-
|
|
64
|
-
function fmtTime(ts: number): string {
|
|
65
|
-
const d = new Date(ts);
|
|
66
|
-
const hh = String(d.getHours()).padStart(2, '0');
|
|
67
|
-
const mm = String(d.getMinutes()).padStart(2, '0');
|
|
68
|
-
const ss = String(d.getSeconds()).padStart(2, '0');
|
|
69
|
-
return `${hh}:${mm}:${ss}`;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export class SystemMessagesPanel extends ScrollableListPanel<SystemMessageEntry> {
|
|
73
|
-
private _messages: SystemMessageEntry[] = [];
|
|
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;
|
|
79
|
-
|
|
80
|
-
constructor(configManager: ConfigManager, componentHealthMonitor?: ComponentHealthMonitor) {
|
|
81
|
-
super('system-messages', 'System Messages', '▥', 'runtime-ops', componentHealthMonitor);
|
|
82
|
-
this.configManager = configManager;
|
|
83
|
-
this.filterEnabled = true;
|
|
84
|
-
this.filterLabel = 'Filter messages';
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
protected override filterMatches(entry: SystemMessageEntry, q: string): boolean {
|
|
88
|
-
return entry.text.toLowerCase().includes(q) || entry.priority.toLowerCase().includes(q);
|
|
89
|
-
}
|
|
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
|
-
|
|
98
|
-
// ---------------------------------------------------------------------------
|
|
99
|
-
// ScrollableListPanel contract
|
|
100
|
-
// ---------------------------------------------------------------------------
|
|
101
|
-
|
|
102
|
-
protected getItems(): readonly SystemMessageEntry[] {
|
|
103
|
-
return this._messages;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
protected renderItem(
|
|
107
|
-
entry: SystemMessageEntry,
|
|
108
|
-
index: number,
|
|
109
|
-
selected: boolean,
|
|
110
|
-
width: number,
|
|
111
|
-
): Line {
|
|
112
|
-
const preview = entry.text.replace(/\s+/g, ' ').trim();
|
|
113
|
-
return buildPanelListRow(width, [
|
|
114
|
-
{ text: `${fmtTime(entry.ts)} `, fg: C.ts },
|
|
115
|
-
{
|
|
116
|
-
text: `${(entry.priority === 'high' ? 'HIGH' : 'LOW').padEnd(4)} `,
|
|
117
|
-
fg: entry.priority === 'high' ? C.high : C.low,
|
|
118
|
-
bold: entry.priority === 'high',
|
|
119
|
-
},
|
|
120
|
-
{ text: preview, fg: C.value },
|
|
121
|
-
], C, {
|
|
122
|
-
selected,
|
|
123
|
-
marker: entry.priority === 'high' ? '!' : '\u00b7',
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
protected override getPalette(): PanelPalette {
|
|
128
|
-
return C;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
protected override getEmptyStateMessage(): string {
|
|
132
|
-
return ' No system messages yet.';
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
|
-
// Public API
|
|
137
|
-
// ---------------------------------------------------------------------------
|
|
138
|
-
|
|
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;
|
|
146
|
-
this._messages.push({ ts: Date.now(), text, priority });
|
|
147
|
-
if (this._messages.length > MAX_MESSAGES) {
|
|
148
|
-
this._messages.shift();
|
|
149
|
-
if (this.selectedIndex > 0) this.selectedIndex--;
|
|
150
|
-
}
|
|
151
|
-
if (wasAtTail) {
|
|
152
|
-
const visibleAfter = this.getVisibleItems();
|
|
153
|
-
this.selectedIndex = Math.max(0, visibleAfter.length - 1);
|
|
154
|
-
}
|
|
155
|
-
this.markDirty();
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
get count(): number {
|
|
159
|
-
return this._messages.length;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
getMessages(): readonly SystemMessageEntry[] {
|
|
163
|
-
return this._messages;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// ---------------------------------------------------------------------------
|
|
167
|
-
// Input
|
|
168
|
-
// ---------------------------------------------------------------------------
|
|
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
|
-
|
|
221
|
-
// ---------------------------------------------------------------------------
|
|
222
|
-
// Render — multi-section layout (posture + list + detail)
|
|
223
|
-
// ---------------------------------------------------------------------------
|
|
224
|
-
|
|
225
|
-
// Context-aware footer: navigation keys plus filter keys that reflect the
|
|
226
|
-
// current filter state (active typing / applied query / inactive).
|
|
227
|
-
private footerHints(): Array<{ keys: string; label: string }> {
|
|
228
|
-
const hints: Array<{ keys: string; label: string }> = [
|
|
229
|
-
{ keys: 'j/k', label: 'scroll' },
|
|
230
|
-
{ keys: 'g/G', label: 'jump' },
|
|
231
|
-
{ keys: 'p', label: 'priority' },
|
|
232
|
-
];
|
|
233
|
-
if (this.filterActive) {
|
|
234
|
-
hints.push({ keys: 'Esc', label: 'clear filter' });
|
|
235
|
-
} else if (this.filterQuery) {
|
|
236
|
-
hints.push({ keys: '/', label: 'edit filter' }, { keys: 'Esc', label: 'clear filter' });
|
|
237
|
-
} else {
|
|
238
|
-
hints.push({ keys: '/', label: 'filter' });
|
|
239
|
-
if (this._messages.length > 0) hints.push({ keys: 'c', label: 'clear' });
|
|
240
|
-
}
|
|
241
|
-
return hints;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
override render(width: number, height: number): Line[] {
|
|
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
|
-
|
|
257
|
-
const intro = 'Operational system traffic routed out of the main conversation to reduce noise and keep runtime status reviewable.';
|
|
258
|
-
|
|
259
|
-
if (this._messages.length === 0) {
|
|
260
|
-
this.needsRender = false;
|
|
261
|
-
const lines = buildPanelWorkspace(width, height, {
|
|
262
|
-
title: 'System Messages',
|
|
263
|
-
intro,
|
|
264
|
-
sections: [{
|
|
265
|
-
lines: buildEmptyState(
|
|
266
|
-
width,
|
|
267
|
-
this.getEmptyStateMessage(),
|
|
268
|
-
'Model switches, scan notices, provider/system state, and other operational updates will appear here once the runtime starts emitting them.',
|
|
269
|
-
[
|
|
270
|
-
{ command: '/help', summary: 'review command and workflow surfaces' },
|
|
271
|
-
{ command: '/cockpit', summary: 'open the unified runtime control room' },
|
|
272
|
-
],
|
|
273
|
-
C,
|
|
274
|
-
),
|
|
275
|
-
}],
|
|
276
|
-
footerLines: [
|
|
277
|
-
buildPanelLine(width, [[' Low-priority system traffic lands here by default. Routing is configurable via /settings.', C.dim]]),
|
|
278
|
-
],
|
|
279
|
-
palette: C,
|
|
280
|
-
});
|
|
281
|
-
return lines;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
const highCount = this._messages.filter((entry) => entry.priority === 'high').length;
|
|
285
|
-
const lowCount = this._messages.length - highCount;
|
|
286
|
-
this.selectedIndex = Math.min(this.selectedIndex, this._messages.length - 1);
|
|
287
|
-
const ui = this.configManager.getRaw().ui;
|
|
288
|
-
const latest = this._messages[this._messages.length - 1];
|
|
289
|
-
const postureLines = [
|
|
290
|
-
// Severity + recency first: high-priority count leads, newest message age follows.
|
|
291
|
-
buildPanelLine(width, [
|
|
292
|
-
[' ', C.label],
|
|
293
|
-
...buildStatusBadge(highCount > 0 ? 'failed' : 'completed', 'high', { count: highCount }),
|
|
294
|
-
[' ', C.dim],
|
|
295
|
-
...buildStatusBadge('review', 'low', { count: lowCount }),
|
|
296
|
-
...(latest ? ([[' newest ', C.label], [`${fmtTime(latest.ts)}`, C.value]] as Array<[string, string]>) : []),
|
|
297
|
-
]),
|
|
298
|
-
buildKeyValueLine(width, [
|
|
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 },
|
|
302
|
-
], C),
|
|
303
|
-
buildGuidanceLine(width, '/settings', 'review the full settings surface (routing is also toggleable in-panel with s/o/w)', C),
|
|
304
|
-
];
|
|
305
|
-
|
|
306
|
-
const visible = this.getVisibleItems();
|
|
307
|
-
this.selectedIndex = Math.max(0, Math.min(this.selectedIndex, visible.length - 1));
|
|
308
|
-
const selected = this.getSelectedItem();
|
|
309
|
-
const noMatchReason = this.filterQuery.trim()
|
|
310
|
-
? `"${this.filterQuery.trim()}"${this.priorityFilter ? ` + priority:${this.priorityFilter}` : ''}`
|
|
311
|
-
: `priority:${this.priorityFilter}`;
|
|
312
|
-
const messageRows: Line[] = visible.length > 0
|
|
313
|
-
? visible.map((entry, index) => this.renderItem(entry, index, index === this.selectedIndex, width))
|
|
314
|
-
: [buildPanelLine(width, [[` No messages match ${noMatchReason} (Esc to clear filter, p to reset priority)`, C.dim]])];
|
|
315
|
-
|
|
316
|
-
const filterSection: PanelWorkspaceSection = { lines: [this.buildFilterLine(width)] };
|
|
317
|
-
const postureSection: PanelWorkspaceSection = { lines: buildSummaryBlock(width, 'System posture', postureLines, C) };
|
|
318
|
-
const detailSection: PanelWorkspaceSection = selected
|
|
319
|
-
? {
|
|
320
|
-
title: 'Selected Message',
|
|
321
|
-
lines: [
|
|
322
|
-
buildPanelLine(width, [
|
|
323
|
-
[' Time ', C.label],
|
|
324
|
-
[fmtTime(selected.ts), C.value],
|
|
325
|
-
[' Priority ', C.label],
|
|
326
|
-
[selected.priority, selected.priority === 'high' ? C.high : C.low],
|
|
327
|
-
]),
|
|
328
|
-
...buildBodyText(width, selected.text, C, C.value),
|
|
329
|
-
],
|
|
330
|
-
}
|
|
331
|
-
: { title: 'Selected Message', lines: [] };
|
|
332
|
-
const messagesSection = resolvePrimaryScrollableSection(width, height, {
|
|
333
|
-
intro,
|
|
334
|
-
palette: C,
|
|
335
|
-
beforeSections: [filterSection, postureSection],
|
|
336
|
-
section: {
|
|
337
|
-
title: 'Timeline',
|
|
338
|
-
scrollableLines: messageRows,
|
|
339
|
-
selectedIndex: this.selectedIndex,
|
|
340
|
-
scrollOffset: this.scrollStart,
|
|
341
|
-
minRows: 4,
|
|
342
|
-
appendWindowSummary: { dimColor: C.ts },
|
|
343
|
-
},
|
|
344
|
-
afterSections: [detailSection],
|
|
345
|
-
});
|
|
346
|
-
this.scrollStart = messagesSection.scrollOffset;
|
|
347
|
-
const sections: PanelWorkspaceSection[] = [
|
|
348
|
-
filterSection,
|
|
349
|
-
postureSection,
|
|
350
|
-
messagesSection.section,
|
|
351
|
-
detailSection,
|
|
352
|
-
];
|
|
353
|
-
this.needsRender = false;
|
|
354
|
-
const lines = buildPanelWorkspace(width, height, {
|
|
355
|
-
title: 'System Messages',
|
|
356
|
-
intro,
|
|
357
|
-
sections,
|
|
358
|
-
footerLines: [buildKeyboardHints(width, this.footerHints(), C)],
|
|
359
|
-
palette: C,
|
|
360
|
-
});
|
|
361
|
-
return lines;
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
}
|