@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.
Files changed (118) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/README.md +1 -1
  3. package/package.json +1 -1
  4. package/src/input/commands/cost-runtime.ts +49 -0
  5. package/src/input/commands/operator-runtime.ts +5 -1
  6. package/src/input/commands.ts +2 -0
  7. package/src/input/handler-feed-routes.ts +12 -35
  8. package/src/input/handler-feed.ts +4 -8
  9. package/src/input/handler-shortcuts.ts +51 -0
  10. package/src/input/handler.ts +43 -6
  11. package/src/input/keybindings.ts +48 -8
  12. package/src/input/panel-integration-actions.ts +107 -1
  13. package/src/main.ts +5 -1
  14. package/src/panels/agent-inspector-panel.ts +125 -36
  15. package/src/panels/agent-inspector-shared.ts +144 -0
  16. package/src/panels/approval-panel.ts +67 -16
  17. package/src/panels/automation-control-panel.ts +368 -124
  18. package/src/panels/builtin/agent.ts +28 -37
  19. package/src/panels/builtin/development.ts +40 -32
  20. package/src/panels/builtin/knowledge.ts +15 -6
  21. package/src/panels/builtin/operations.ts +178 -117
  22. package/src/panels/builtin/session.ts +35 -9
  23. package/src/panels/builtin/shared.ts +98 -6
  24. package/src/panels/cockpit-panel.ts +232 -73
  25. package/src/panels/communication-panel.ts +58 -20
  26. package/src/panels/confirm-state.ts +8 -1
  27. package/src/panels/control-plane-panel.ts +351 -118
  28. package/src/panels/cost-tracker-panel.ts +165 -7
  29. package/src/panels/debug-panel.ts +312 -159
  30. package/src/panels/diff-panel.ts +203 -57
  31. package/src/panels/docs-panel.ts +152 -66
  32. package/src/panels/eval-panel.ts +220 -42
  33. package/src/panels/file-explorer-panel.ts +202 -122
  34. package/src/panels/file-preview-panel.ts +132 -57
  35. package/src/panels/git-panel.ts +309 -128
  36. package/src/panels/hooks-panel.ts +150 -22
  37. package/src/panels/incident-review-panel.ts +223 -35
  38. package/src/panels/index.ts +0 -4
  39. package/src/panels/intelligence-panel.ts +212 -86
  40. package/src/panels/knowledge-graph-panel.ts +461 -101
  41. package/src/panels/local-auth-panel.ts +240 -28
  42. package/src/panels/marketplace-panel.ts +193 -26
  43. package/src/panels/memory-panel.ts +78 -77
  44. package/src/panels/ops-control-panel.ts +146 -29
  45. package/src/panels/ops-strategy-panel.ts +72 -4
  46. package/src/panels/orchestration-panel.ts +231 -69
  47. package/src/panels/panel-list-panel.ts +154 -131
  48. package/src/panels/panel-manager.ts +97 -9
  49. package/src/panels/plan-dashboard-panel.ts +333 -17
  50. package/src/panels/plugins-panel.ts +184 -29
  51. package/src/panels/policy-panel.ts +210 -38
  52. package/src/panels/polish-core.ts +7 -2
  53. package/src/panels/polish.ts +23 -4
  54. package/src/panels/project-planning-answer-actions.ts +134 -0
  55. package/src/panels/project-planning-panel.ts +62 -113
  56. package/src/panels/provider-health-panel.ts +434 -518
  57. package/src/panels/provider-health-routes.ts +203 -0
  58. package/src/panels/provider-health-tracker.ts +194 -6
  59. package/src/panels/provider-health-views.ts +560 -0
  60. package/src/panels/qr-panel.ts +116 -30
  61. package/src/panels/remote-panel.ts +114 -36
  62. package/src/panels/routes-panel.ts +63 -22
  63. package/src/panels/sandbox-panel.ts +174 -42
  64. package/src/panels/scrollable-list-panel.ts +19 -135
  65. package/src/panels/security-panel.ts +133 -33
  66. package/src/panels/services-panel.ts +116 -64
  67. package/src/panels/session-browser-panel.ts +73 -2
  68. package/src/panels/session-maintenance.ts +4 -122
  69. package/src/panels/settings-sync-panel.ts +335 -72
  70. package/src/panels/skills-panel.ts +157 -89
  71. package/src/panels/subscription-panel.ts +86 -33
  72. package/src/panels/symbol-outline-panel.ts +248 -108
  73. package/src/panels/system-messages-panel.ts +114 -13
  74. package/src/panels/tasks-panel.ts +326 -139
  75. package/src/panels/thinking-panel.ts +43 -10
  76. package/src/panels/token-budget-panel.ts +194 -18
  77. package/src/panels/tool-inspector-panel.ts +144 -34
  78. package/src/panels/types.ts +40 -4
  79. package/src/panels/work-plan-panel.ts +280 -17
  80. package/src/panels/worktree-panel.ts +175 -42
  81. package/src/panels/wrfc-panel.ts +116 -24
  82. package/src/renderer/conversation-overlays.ts +25 -11
  83. package/src/renderer/footer-tips.ts +41 -0
  84. package/src/renderer/fullscreen-primitives.ts +22 -16
  85. package/src/renderer/help-overlay.ts +91 -14
  86. package/src/renderer/hint-grammar.ts +52 -0
  87. package/src/renderer/layout.ts +7 -7
  88. package/src/renderer/modal-factory.ts +23 -15
  89. package/src/renderer/model-picker-overlay.ts +21 -7
  90. package/src/renderer/overlay-box.ts +16 -10
  91. package/src/renderer/process-indicator.ts +3 -1
  92. package/src/renderer/progress.ts +5 -4
  93. package/src/renderer/search-overlay.ts +27 -6
  94. package/src/renderer/session-picker-modal.ts +6 -4
  95. package/src/renderer/settings-modal.ts +70 -10
  96. package/src/renderer/shell-surface.ts +41 -15
  97. package/src/renderer/status-glyphs.ts +11 -9
  98. package/src/renderer/theme.ts +60 -3
  99. package/src/renderer/ui-factory.ts +41 -30
  100. package/src/renderer/ui-primitives.ts +23 -2
  101. package/src/runtime/bootstrap-shell.ts +35 -18
  102. package/src/runtime/diagnostics/panels/index.ts +0 -3
  103. package/src/shell/ui-openers.ts +14 -22
  104. package/src/utils/format-duration.ts +2 -2
  105. package/src/utils/splash-lines.ts +44 -3
  106. package/src/version.ts +1 -1
  107. package/src/work-plans/work-plan-store.ts +13 -0
  108. package/src/panels/agent-logs-panel.ts +0 -635
  109. package/src/panels/agent-logs-shared.ts +0 -129
  110. package/src/panels/context-visualizer-panel.ts +0 -238
  111. package/src/panels/forensics-panel.ts +0 -378
  112. package/src/panels/provider-account-snapshot.ts +0 -259
  113. package/src/panels/provider-accounts-panel.ts +0 -255
  114. package/src/panels/provider-stats-panel.ts +0 -391
  115. package/src/panels/schedule-panel.ts +0 -365
  116. package/src/panels/watchers-panel.ts +0 -213
  117. package/src/runtime/diagnostics/panels/panel-resources.ts +0 -118
  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
- const C = {
19
- ...DEFAULT_PANEL_PALETTE,
20
- headerBg: '#111827',
21
- } as const;
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', 'monitoring');
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 items = this.getVisibleItems();
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 items = this.getVisibleItems();
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
- : buildGuidanceLine(width, '/policy simulate', 'preview which requests a scoped rule change would auto-approve', C),
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
- buildGuidanceLine(width, review.command, `review and decide the ${laneOf(selected)} request`, C),
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
- for (const suggestion of buildPermissionRuleSuggestions(audit).slice(0, 3)) {
172
- ruleSuggestionLines.push(buildPanelLine(width, [[` ${truncateDisplay(suggestion.summary, Math.max(0, width - 4))}`, C.info]]));
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',