@pellux/goodvibes-tui 0.28.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 +101 -0
- package/README.md +1 -1
- package/package.json +1 -1
- 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-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/keybindings.ts +48 -8
- package/src/input/panel-integration-actions.ts +107 -1
- package/src/main.ts +5 -1
- 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/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 +203 -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 +309 -128
- 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/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 +21 -7
- package/src/renderer/overlay-box.ts +16 -10
- package/src/renderer/process-indicator.ts +3 -1
- package/src/renderer/progress.ts +5 -4
- 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/theme.ts +60 -3
- package/src/renderer/ui-factory.ts +41 -30
- 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/shell/ui-openers.ts +14 -22
- package/src/utils/format-duration.ts +2 -2
- 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 -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/runtime/diagnostics/panels/panel-resources.ts +0 -118
- package/src/runtime/diagnostics/panels/policy.ts +0 -177
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Line } from '../types/grid.ts';
|
|
2
2
|
import { ScrollableListPanel } from './scrollable-list-panel.ts';
|
|
3
|
+
import type { PanelIntegrationContext } from './types.ts';
|
|
3
4
|
import {
|
|
4
5
|
buildBodyText,
|
|
5
6
|
buildDetailBlock,
|
|
@@ -15,10 +16,18 @@ import { truncateDisplay } from '../utils/terminal-width.ts';
|
|
|
15
16
|
import type { PolicyRuntimeState, PermissionAuditEntry } from '@/runtime/index.ts';
|
|
16
17
|
import { buildPermissionRuleSuggestions } from '@/runtime/index.ts';
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
19
|
+
// Splits a computed '/command arg1 arg2' string into the { name, args } shape
|
|
20
|
+
// ctx.executeCommand expects — same leading-slash-stripping approach used by
|
|
21
|
+
// remote-panel.ts / session-browser-panel.ts for their own dispatched commands.
|
|
22
|
+
function parseCommand(command: string): { name: string; args: string[] } | null {
|
|
23
|
+
const parts = command.replace(/^\//, '').split(/\s+/).filter(Boolean);
|
|
24
|
+
const [name, ...args] = parts;
|
|
25
|
+
return name ? { name, args } : null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Base chrome only — title band comes straight from DEFAULT_PANEL_PALETTE
|
|
29
|
+
// (WO-002).
|
|
30
|
+
const C = DEFAULT_PANEL_PALETTE;
|
|
22
31
|
|
|
23
32
|
// Reference catalog of approval lanes and where each one is reviewed. Used to
|
|
24
33
|
// resolve the next-step command for a live request and as a fallback reference
|
|
@@ -71,13 +80,45 @@ function fmtAgo(ts: number): string {
|
|
|
71
80
|
|
|
72
81
|
export class ApprovalPanel extends ScrollableListPanel<PermissionAuditEntry> {
|
|
73
82
|
private readonly policyRuntimeState: Pick<PolicyRuntimeState, 'getSnapshot'>;
|
|
83
|
+
// p / 1-3 = dispatch '/policy simulate' or a rule-suggestion command via the
|
|
84
|
+
// handleInput -> handlePanelIntegrationAction bridge (handleInput has no
|
|
85
|
+
// ctx.executeCommand — same pattern as remote-panel.ts / session-browser-panel.ts).
|
|
86
|
+
private pendingCommand: { name: string; args: string[] } | null = null;
|
|
74
87
|
|
|
75
88
|
public constructor(policyRuntimeState: Pick<PolicyRuntimeState, 'getSnapshot'>) {
|
|
76
|
-
super('approval', 'Approval', 'A', '
|
|
89
|
+
super('approval', 'Approval', 'A', 'security-policy');
|
|
77
90
|
this.showSelectionGutter = true; // I5: non-color selection affordance
|
|
78
91
|
this.policyRuntimeState = policyRuntimeState;
|
|
79
92
|
}
|
|
80
93
|
|
|
94
|
+
private getRuleSuggestions() {
|
|
95
|
+
const audit = this.policyRuntimeState.getSnapshot().recentPermissionAudit;
|
|
96
|
+
return buildPermissionRuleSuggestions(audit).slice(0, 3);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
override handleInput(key: string): boolean {
|
|
100
|
+
if (key === 'p') {
|
|
101
|
+
this.pendingCommand = parseCommand('/policy simulate');
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
if (key === '1' || key === '2' || key === '3') {
|
|
105
|
+
const suggestion = this.getRuleSuggestions()[Number(key) - 1];
|
|
106
|
+
if (!suggestion) return false;
|
|
107
|
+
this.pendingCommand = parseCommand(suggestion.command);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return super.handleInput(key);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Drains `pendingCommand` (set by 'p' or '1'/'2'/'3') via the ctx.executeCommand bridge. */
|
|
114
|
+
handlePanelIntegrationAction(_key: string, ctx: PanelIntegrationContext): boolean {
|
|
115
|
+
if (!this.pendingCommand) return false;
|
|
116
|
+
const { name, args } = this.pendingCommand;
|
|
117
|
+
this.pendingCommand = null;
|
|
118
|
+
void ctx.executeCommand?.(name, args);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
81
122
|
protected override getPalette() { return C; }
|
|
82
123
|
protected override getEmptyStateMessage() { return ' No approval pressure right now.'; }
|
|
83
124
|
protected override getEmptyStateActions() {
|
|
@@ -112,8 +153,7 @@ export class ApprovalPanel extends ScrollableListPanel<PermissionAuditEntry> {
|
|
|
112
153
|
|
|
113
154
|
/** Next-step review command for the currently selected request (if any). */
|
|
114
155
|
public getSelectedCommand(): string | null {
|
|
115
|
-
const
|
|
116
|
-
const selected = items[this.selectedIndex];
|
|
156
|
+
const selected = this.getSelectedItem();
|
|
117
157
|
return selected ? reviewFor(selected).command : null;
|
|
118
158
|
}
|
|
119
159
|
|
|
@@ -124,8 +164,7 @@ export class ApprovalPanel extends ScrollableListPanel<PermissionAuditEntry> {
|
|
|
124
164
|
const denialCount = audit.filter((e) => e.approved === false).length;
|
|
125
165
|
const pendingCount = audit.filter((e) => e.approved === undefined).length;
|
|
126
166
|
|
|
127
|
-
const
|
|
128
|
-
const selected = items[this.selectedIndex] ?? null;
|
|
167
|
+
const selected = this.getSelectedItem() ?? null;
|
|
129
168
|
|
|
130
169
|
// ---- Posture summary (severity + counts first) ----
|
|
131
170
|
const headerLines: Line[] = [
|
|
@@ -139,7 +178,10 @@ export class ApprovalPanel extends ScrollableListPanel<PermissionAuditEntry> {
|
|
|
139
178
|
]),
|
|
140
179
|
pendingCount > 0
|
|
141
180
|
? buildPanelLine(width, [[` ${pendingCount} request${pendingCount !== 1 ? 's' : ''} awaiting a decision — select one to see its review path.`, C.warn]])
|
|
142
|
-
:
|
|
181
|
+
: buildPanelLine(width, [
|
|
182
|
+
[' p ', C.info],
|
|
183
|
+
['/policy simulate — preview which requests a scoped rule change would auto-approve', C.dim],
|
|
184
|
+
]),
|
|
143
185
|
];
|
|
144
186
|
|
|
145
187
|
// ---- Detail block for the selected request ----
|
|
@@ -162,18 +204,25 @@ export class ApprovalPanel extends ScrollableListPanel<PermissionAuditEntry> {
|
|
|
162
204
|
...(selected.reasons[0]
|
|
163
205
|
? buildBodyText(width, `why prompted: ${selected.reasons[0]}`, C, C.dim)
|
|
164
206
|
: buildBodyText(width, `why prompted: ${review.why}`, C, C.dim)),
|
|
165
|
-
|
|
207
|
+
// WO-160: dropped the printed `review.command` guidance line here —
|
|
208
|
+
// Enter is already wired by the shell to dispatch that exact command
|
|
209
|
+
// (see onSelect below and the "Enter: review (<command>)" footer
|
|
210
|
+
// hint), so restating it as a signpost was a pure action substitute.
|
|
166
211
|
], C));
|
|
167
212
|
}
|
|
168
213
|
|
|
169
|
-
// ---- Durable-rule suggestions from repeated denials ----
|
|
214
|
+
// ---- Durable-rule suggestions from repeated denials (dispatchable via 1/2/3) ----
|
|
215
|
+
const suggestions = this.getRuleSuggestions();
|
|
170
216
|
const ruleSuggestionLines: Line[] = [];
|
|
171
|
-
|
|
172
|
-
ruleSuggestionLines.push(buildPanelLine(width, [
|
|
217
|
+
suggestions.forEach((suggestion, index) => {
|
|
218
|
+
ruleSuggestionLines.push(buildPanelLine(width, [
|
|
219
|
+
[` ${index + 1}) `, C.info],
|
|
220
|
+
[truncateDisplay(suggestion.summary, Math.max(0, width - 8)), C.info],
|
|
221
|
+
]));
|
|
173
222
|
ruleSuggestionLines.push(buildGuidanceLine(width, suggestion.command, suggestion.reason, C));
|
|
174
|
-
}
|
|
223
|
+
});
|
|
175
224
|
if (ruleSuggestionLines.length > 0) {
|
|
176
|
-
ruleSuggestionLines.unshift(buildPanelLine(width, [[' Suggested durable rules', C.label]]));
|
|
225
|
+
ruleSuggestionLines.unshift(buildPanelLine(width, [[' Suggested durable rules (press 1/2/3 to apply)', C.label]]));
|
|
177
226
|
}
|
|
178
227
|
|
|
179
228
|
// ---- Context-aware footer: only show review key when a request is selected ----
|
|
@@ -187,6 +236,8 @@ export class ApprovalPanel extends ScrollableListPanel<PermissionAuditEntry> {
|
|
|
187
236
|
{ keys: '↑/↓', label: 'select' },
|
|
188
237
|
{ keys: 'g/G', label: 'top/bottom' },
|
|
189
238
|
];
|
|
239
|
+
if (suggestions.length > 0) hints.push({ keys: '1-3', label: 'apply rule suggestion' });
|
|
240
|
+
if (pendingCount === 0) hints.push({ keys: 'p', label: 'policy simulate' });
|
|
190
241
|
|
|
191
242
|
return this.renderList(width, height, {
|
|
192
243
|
title: 'Approval Control Room',
|