@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.
Files changed (194) hide show
  1. package/CHANGELOG.md +85 -21
  2. package/README.md +20 -11
  3. package/docs/foundation-artifacts/operator-contract.json +1 -1
  4. package/package.json +2 -2
  5. package/src/core/alert-gating.ts +67 -0
  6. package/src/core/approval-alert.ts +72 -0
  7. package/src/core/budget-breach-notifier.ts +106 -0
  8. package/src/core/conversation-rendering.ts +19 -0
  9. package/src/core/conversation.ts +18 -0
  10. package/src/core/focus-tracker.ts +41 -0
  11. package/src/core/long-task-notifier.ts +33 -6
  12. package/src/core/system-message-router.ts +37 -51
  13. package/src/core/turn-cancellation.ts +20 -0
  14. package/src/core/turn-event-wiring.ts +64 -3
  15. package/src/export/cost-utils.ts +36 -0
  16. package/src/input/command-registry.ts +38 -1
  17. package/src/input/commands/checkpoint-runtime.ts +280 -0
  18. package/src/input/commands/codebase-runtime.ts +192 -0
  19. package/src/input/commands/eval.ts +1 -1
  20. package/src/input/commands/health-runtime.ts +1 -1
  21. package/src/input/commands/image-runtime.ts +112 -0
  22. package/src/input/commands/intelligence-runtime.ts +11 -1
  23. package/src/input/commands/local-auth-runtime.ts +4 -1
  24. package/src/input/commands/local-runtime.ts +9 -3
  25. package/src/input/commands/marketplace-runtime.ts +2 -2
  26. package/src/input/commands/memory.ts +6 -1
  27. package/src/input/commands/operator-panel-runtime.ts +40 -24
  28. package/src/input/commands/planning-runtime.ts +26 -3
  29. package/src/input/commands/platform-sandbox-runtime.ts +1 -6
  30. package/src/input/commands/plugin-runtime.ts +2 -2
  31. package/src/input/commands/policy-dispatch.ts +21 -0
  32. package/src/input/commands/provider-accounts-runtime.ts +1 -1
  33. package/src/input/commands/qrcode-runtime.ts +3 -3
  34. package/src/input/commands/recall-review.ts +35 -0
  35. package/src/input/commands/remote-runtime.ts +3 -3
  36. package/src/input/commands/runtime-services.ts +54 -13
  37. package/src/input/commands/services-runtime.ts +1 -1
  38. package/src/input/commands/session-workflow.ts +16 -1
  39. package/src/input/commands/settings-sync-runtime.ts +1 -1
  40. package/src/input/commands/shell-core.ts +15 -7
  41. package/src/input/commands/skills-runtime.ts +2 -8
  42. package/src/input/commands/subscription-runtime.ts +2 -2
  43. package/src/input/commands/test-runtime.ts +277 -0
  44. package/src/input/commands/websearch-runtime.ts +101 -0
  45. package/src/input/commands/work-plan-runtime.ts +36 -10
  46. package/src/input/commands/workstream-runtime.ts +338 -0
  47. package/src/input/commands.ts +12 -0
  48. package/src/input/config-modal-types.ts +161 -0
  49. package/src/input/config-modal.ts +377 -0
  50. package/src/input/feed-context-factory.ts +7 -8
  51. package/src/input/handler-command-route.ts +27 -17
  52. package/src/input/handler-feed-routes.ts +61 -23
  53. package/src/input/handler-feed.ts +47 -23
  54. package/src/input/handler-interactions.ts +1 -3
  55. package/src/input/handler-modal-routes.ts +65 -0
  56. package/src/input/handler-modal-stack.ts +3 -5
  57. package/src/input/handler-modal-token-routes.ts +16 -49
  58. package/src/input/handler-picker-routes.ts +11 -94
  59. package/src/input/handler-shortcuts.ts +24 -14
  60. package/src/input/handler-types.ts +2 -6
  61. package/src/input/handler-ui-state.ts +10 -22
  62. package/src/input/handler.ts +6 -28
  63. package/src/input/keybindings.ts +22 -8
  64. package/src/input/model-picker-types.ts +24 -6
  65. package/src/input/model-picker.ts +58 -0
  66. package/src/input/panel-integration-actions.ts +9 -170
  67. package/src/input/settings-modal-data.ts +95 -0
  68. package/src/input/settings-modal-mutations.ts +6 -4
  69. package/src/main.ts +24 -27
  70. package/src/panels/agent-inspector-shared.ts +2 -1
  71. package/src/panels/base-panel.ts +22 -1
  72. package/src/panels/builtin/agent.ts +21 -107
  73. package/src/panels/builtin/development.ts +15 -61
  74. package/src/panels/builtin/knowledge.ts +8 -32
  75. package/src/panels/builtin/operations.ts +84 -428
  76. package/src/panels/builtin/session.ts +21 -112
  77. package/src/panels/builtin/shared.ts +9 -43
  78. package/src/panels/builtin-modals.ts +218 -0
  79. package/src/panels/builtin-panels.ts +5 -0
  80. package/src/panels/cost-tracker-panel.ts +36 -10
  81. package/src/panels/diff-panel.ts +12 -43
  82. package/src/panels/eval-registry.ts +60 -0
  83. package/src/panels/fleet-panel.ts +800 -0
  84. package/src/panels/fleet-read-model.ts +477 -0
  85. package/src/panels/fleet-steer.ts +92 -0
  86. package/src/panels/fleet-stop.ts +125 -0
  87. package/src/panels/fleet-tabs.ts +230 -0
  88. package/src/panels/fleet-transcript.ts +356 -0
  89. package/src/panels/index.ts +7 -31
  90. package/src/panels/modals/hooks-modal.ts +187 -0
  91. package/src/panels/modals/keybindings-modal.ts +151 -0
  92. package/src/panels/modals/knowledge-modal.ts +158 -0
  93. package/src/panels/modals/local-auth-modal.ts +132 -0
  94. package/src/panels/modals/marketplace-modal.ts +218 -0
  95. package/src/panels/modals/memory-modal.ts +180 -0
  96. package/src/panels/modals/modal-surface-helpers.ts +54 -0
  97. package/src/panels/modals/modal-theme.ts +36 -0
  98. package/src/panels/modals/pairing-modal.ts +144 -0
  99. package/src/panels/modals/planning-modal.ts +282 -0
  100. package/src/panels/modals/plugins-modal.ts +174 -0
  101. package/src/panels/modals/policy-modal.ts +256 -0
  102. package/src/panels/modals/provider-health-modal.ts +136 -0
  103. package/src/panels/modals/remote-modal.ts +115 -0
  104. package/src/panels/modals/sandbox-modal.ts +150 -0
  105. package/src/panels/modals/security-modal.ts +217 -0
  106. package/src/panels/modals/services-modal.ts +179 -0
  107. package/src/panels/modals/settings-sync-modal.ts +142 -0
  108. package/src/panels/modals/skills-modal.ts +189 -0
  109. package/src/panels/modals/subscription-modal.ts +172 -0
  110. package/src/panels/modals/work-plan-modal.ts +149 -0
  111. package/src/panels/panel-confirm-overlay.ts +72 -0
  112. package/src/panels/panel-manager.ts +108 -5
  113. package/src/panels/project-planning-answer-actions.ts +4 -2
  114. package/src/panels/skills-panel.ts +7 -51
  115. package/src/panels/types.ts +13 -0
  116. package/src/permissions/hunk-selection.ts +179 -0
  117. package/src/permissions/prompt.ts +60 -4
  118. package/src/renderer/compaction-history-modal.ts +19 -3
  119. package/src/renderer/compaction-preview.ts +13 -2
  120. package/src/renderer/compaction-quality.ts +100 -0
  121. package/src/renderer/config-modal.ts +81 -0
  122. package/src/renderer/conversation-overlays.ts +10 -17
  123. package/src/renderer/fleet-tab-strip.ts +56 -0
  124. package/src/renderer/footer-tips.ts +10 -2
  125. package/src/renderer/git-status.ts +40 -0
  126. package/src/renderer/help-overlay.ts +2 -2
  127. package/src/renderer/model-workspace.ts +44 -1
  128. package/src/renderer/panel-workspace-bar.ts +8 -2
  129. package/src/renderer/turn-injection.ts +114 -0
  130. package/src/runtime/bootstrap-command-context.ts +21 -1
  131. package/src/runtime/bootstrap-command-parts.ts +34 -7
  132. package/src/runtime/bootstrap-core.ts +14 -4
  133. package/src/runtime/bootstrap-shell.ts +29 -16
  134. package/src/runtime/bootstrap.ts +11 -17
  135. package/src/runtime/code-index-services.ts +112 -0
  136. package/src/runtime/orchestrator-core-services.ts +49 -0
  137. package/src/runtime/process-lifecycle.ts +3 -1
  138. package/src/runtime/services.ts +91 -43
  139. package/src/runtime/ui-services.ts +8 -0
  140. package/src/runtime/workstream-services.ts +195 -0
  141. package/src/shell/blocking-input.ts +22 -1
  142. package/src/shell/ui-openers.ts +129 -17
  143. package/src/utils/format-duration.ts +8 -18
  144. package/src/utils/splash-lines.ts +1 -1
  145. package/src/version.ts +1 -1
  146. package/src/panels/agent-inspector-panel.ts +0 -786
  147. package/src/panels/approval-panel.ts +0 -252
  148. package/src/panels/automation-control-panel.ts +0 -479
  149. package/src/panels/cockpit-panel.ts +0 -481
  150. package/src/panels/cockpit-read-model.ts +0 -238
  151. package/src/panels/communication-panel.ts +0 -256
  152. package/src/panels/control-plane-panel.ts +0 -470
  153. package/src/panels/debug-panel.ts +0 -615
  154. package/src/panels/docs-panel.ts +0 -384
  155. package/src/panels/eval-panel.ts +0 -627
  156. package/src/panels/file-explorer-panel.ts +0 -673
  157. package/src/panels/file-preview-panel.ts +0 -517
  158. package/src/panels/hooks-panel.ts +0 -401
  159. package/src/panels/incident-review-panel.ts +0 -406
  160. package/src/panels/intelligence-panel.ts +0 -383
  161. package/src/panels/knowledge-graph-panel.ts +0 -515
  162. package/src/panels/marketplace-panel.ts +0 -399
  163. package/src/panels/memory-panel.ts +0 -558
  164. package/src/panels/ops-control-panel.ts +0 -329
  165. package/src/panels/ops-strategy-panel.ts +0 -321
  166. package/src/panels/orchestration-panel.ts +0 -465
  167. package/src/panels/panel-list-panel.ts +0 -566
  168. package/src/panels/plan-dashboard-panel.ts +0 -707
  169. package/src/panels/policy-panel.ts +0 -517
  170. package/src/panels/project-planning-panel.ts +0 -731
  171. package/src/panels/provider-health-panel.ts +0 -678
  172. package/src/panels/provider-health-tracker.ts +0 -310
  173. package/src/panels/provider-health-views.ts +0 -567
  174. package/src/panels/qr-panel.ts +0 -280
  175. package/src/panels/remote-panel.ts +0 -534
  176. package/src/panels/routes-panel.ts +0 -241
  177. package/src/panels/sandbox-panel.ts +0 -456
  178. package/src/panels/security-panel.ts +0 -447
  179. package/src/panels/services-panel.ts +0 -329
  180. package/src/panels/session-browser-panel.ts +0 -496
  181. package/src/panels/settings-sync-panel.ts +0 -398
  182. package/src/panels/subscription-panel.ts +0 -342
  183. package/src/panels/symbol-outline-panel.ts +0 -619
  184. package/src/panels/system-messages-panel.ts +0 -364
  185. package/src/panels/tasks-panel.ts +0 -608
  186. package/src/panels/thinking-panel.ts +0 -333
  187. package/src/panels/tool-inspector-panel.ts +0 -537
  188. package/src/panels/work-plan-panel.ts +0 -540
  189. package/src/panels/worktree-panel.ts +0 -360
  190. package/src/panels/wrfc-panel.ts +0 -790
  191. package/src/renderer/agent-detail-modal.ts +0 -466
  192. package/src/renderer/live-tail-modal.ts +0 -156
  193. package/src/renderer/process-modal.ts +0 -671
  194. package/src/renderer/qr-renderer.ts +0 -120
@@ -1,241 +0,0 @@
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 type { PanelIntegrationContext } from './types.ts';
5
- import { SessionBrowserPanel } from './session-browser-panel.ts';
6
- import type { UiReadModel, UiRoutesSnapshot } from '../runtime/ui-read-models.ts';
7
- import { truncateDisplay } from '../utils/terminal-width.ts';
8
- import {
9
- buildDetailBlock,
10
- buildEmptyState,
11
- buildKeyValueLine,
12
- buildKeyboardHints,
13
- buildPanelLine,
14
- buildPanelWorkspace,
15
- buildStatusPill,
16
- DEFAULT_PANEL_PALETTE,
17
- type PanelPalette,
18
- } from './polish.ts';
19
-
20
- // Base chrome only — title band, state colors, and text tokens all come
21
- // straight from DEFAULT_PANEL_PALETTE (WO-002).
22
- const C = DEFAULT_PANEL_PALETTE;
23
-
24
- function formatTime(value?: number): string {
25
- if (!value) return 'n/a';
26
- return new Date(value).toLocaleString();
27
- }
28
-
29
- type RouteBinding = UiRoutesSnapshot['bindings'][number];
30
-
31
- // Set by handleInput (enter/c) and consumed on the very next
32
- // handlePanelIntegrationAction dispatch of that same key — handleInput has
33
- // no access to the panelManager.
34
- type PendingRouteAction =
35
- | { readonly kind: 'open-session'; readonly sessionId: string }
36
- | { readonly kind: 'open-communication' };
37
-
38
- export class RoutesPanel extends ScrollableListPanel<RouteBinding> {
39
- private readonly readModel?: UiReadModel<UiRoutesSnapshot>;
40
- private readonly unsub: (() => void) | null;
41
- private pendingAction: PendingRouteAction | null = null;
42
-
43
- public constructor(readModel?: UiReadModel<UiRoutesSnapshot>) {
44
- super('routes', 'Routes', 'R', 'runtime-ops');
45
- this.showSelectionGutter = true; // I5: non-color selection affordance
46
- this.filterEnabled = true;
47
- this.filterLabel = 'Filter routes';
48
- this.readModel = readModel;
49
- this.unsub = readModel ? readModel.subscribe(() => this.markDirty()) : null;
50
- }
51
-
52
- public override handleInput(key: string): boolean {
53
- if (!this.filterActive) {
54
- // Enter jumps to the session browser focused on this binding's session
55
- // — a direct panel jump instead of a printed slash-command signpost.
56
- if (key === 'enter' || key === 'return') {
57
- const selected = this.getSelectedItem();
58
- if (selected?.sessionId) {
59
- this.pendingAction = { kind: 'open-session', sessionId: selected.sessionId };
60
- return true;
61
- }
62
- return false;
63
- }
64
- // c opens the communication panel to inspect routed message flow.
65
- if (key === 'c') {
66
- this.pendingAction = { kind: 'open-communication' };
67
- return true;
68
- }
69
- }
70
- return super.handleInput(key);
71
- }
72
-
73
- public handlePanelIntegrationAction(_key: string, ctx: PanelIntegrationContext): boolean {
74
- if (!this.pendingAction) return false;
75
- const action = this.pendingAction;
76
- this.pendingAction = null;
77
- if (action.kind === 'open-communication') {
78
- ctx.panelManager.open('communication');
79
- return true;
80
- }
81
- const panel = ctx.panelManager.open('sessions');
82
- if (panel instanceof SessionBrowserPanel) {
83
- panel.focusSession(action.sessionId);
84
- }
85
- return true;
86
- }
87
-
88
- protected override filterMatches(binding: RouteBinding, q: string): boolean {
89
- return binding.surfaceKind.toLowerCase().includes(q)
90
- || (binding.title ?? '').toLowerCase().includes(q)
91
- || binding.externalId.toLowerCase().includes(q)
92
- || (binding.sessionId ?? '').toLowerCase().includes(q)
93
- || (binding.runId ?? '').toLowerCase().includes(q);
94
- }
95
-
96
- public override onDestroy(): void {
97
- this.unsub?.();
98
- }
99
-
100
- protected override getPalette(): PanelPalette {
101
- return C;
102
- }
103
-
104
- protected getItems(): readonly RouteBinding[] {
105
- if (!this.readModel) return [];
106
- return this.readModel.getSnapshot().bindings;
107
- }
108
-
109
- protected renderItem(binding: RouteBinding, _index: number, selected: boolean, width: number): Line {
110
- const bg = selected ? C.selectBg : undefined;
111
- return buildPanelLine(width, [
112
- [' ', C.label, bg],
113
- [binding.surfaceKind.padEnd(9), C.info, bg],
114
- [` ${truncateDisplay(binding.title ?? binding.externalId, 22).padEnd(22)}`, C.value, bg],
115
- ...buildStatusPill(binding.sessionId ? 'good' : 'warn', ` ${truncateDisplay(binding.sessionId ?? binding.runId ?? 'unbound', 18).padEnd(18)}`, { bg }),
116
- [` ${truncateDisplay(formatTime(binding.lastSeenAt), Math.max(0, width - 54))}`, C.dim, bg],
117
- ]);
118
- }
119
-
120
- protected override getEmptyStateMessage(): string {
121
- return ' No route bindings recorded.';
122
- }
123
-
124
- protected override getEmptyStateActions(): Array<{ command: string; summary: string }> {
125
- return [
126
- { command: '/schedule list', summary: 'run jobs and triggers that create route bindings' },
127
- { command: '/communication', summary: 'inspect routed communication once a surface is active' },
128
- ];
129
- }
130
-
131
- public render(width: number, height: number): Line[] {
132
- const intro = 'External route bindings that preserve thread, session, and reply context across Slack, Discord, ntfy, webhook, web, and TUI surfaces.';
133
-
134
- if (!this.readModel) {
135
- const workspace = buildPanelWorkspace(width, height, {
136
- title: 'Route Bindings',
137
- intro,
138
- sections: [{
139
- lines: buildEmptyState(
140
- width,
141
- ' Runtime store not wired.',
142
- 'This panel needs the shared runtime store to inspect omnichannel route bindings.',
143
- [{ command: '/communication', summary: 'review communication posture while route state is unavailable' }],
144
- C,
145
- ),
146
- }],
147
- palette: C,
148
- });
149
- while (workspace.length < height) workspace.push(createEmptyLine(width));
150
- return workspace;
151
- }
152
-
153
- const snapshot = this.readModel.getSnapshot();
154
- const bindings = this.getItems();
155
- const surfaceEntries = Object.entries(snapshot.bindingIdsBySurface)
156
- .filter(([, ids]) => ids.length > 0)
157
- .sort((a, b) => b[1].length - a[1].length || a[0].localeCompare(b[0]));
158
-
159
- const headerLines: Line[] = [
160
- buildKeyValueLine(width, [
161
- { label: 'bindings', value: String(snapshot.totalBindings), valueColor: snapshot.totalBindings > 0 ? C.info : C.dim },
162
- { label: 'active', value: String(snapshot.activeBindingIds.length), valueColor: snapshot.activeBindingIds.length > 0 ? C.good : C.dim },
163
- { label: 'resolved', value: String(snapshot.totalResolved), valueColor: snapshot.totalResolved > 0 ? C.good : C.dim },
164
- { label: 'failures', value: String(snapshot.totalFailures), valueColor: snapshot.totalFailures > 0 ? C.bad : C.dim },
165
- ], C),
166
- ];
167
-
168
- if (bindings.length === 0) {
169
- return this.renderList(width, height, {
170
- title: 'Route Bindings',
171
- header: headerLines,
172
- emptyMessage: ' No route bindings recorded.',
173
- });
174
- }
175
-
176
- this.clampSelection();
177
- // Detail must describe the row the (possibly filtered) list highlights —
178
- // getItems() would desync under an applied filter, and a filter that
179
- // matches nothing leaves no selection at all.
180
- const selected = this.getSelectedItem();
181
-
182
- const detailRows: Line[] = selected ? [
183
- buildPanelLine(width, [
184
- [' Binding: ', C.label],
185
- [selected.id, C.value],
186
- [' Surface: ', C.label],
187
- [selected.surfaceKind, C.info],
188
- ]),
189
- buildPanelLine(width, [
190
- [' External: ', C.label],
191
- [truncateDisplay(selected.externalId, 28), C.value],
192
- [' Kind: ', C.label],
193
- [selected.kind, C.dim],
194
- ]),
195
- buildPanelLine(width, [
196
- [' Session: ', C.label],
197
- [selected.sessionId ?? 'n/a', C.value],
198
- [' Run: ', C.label],
199
- [selected.runId ?? 'n/a', C.dim],
200
- ]),
201
- buildPanelLine(width, [
202
- [' Channel: ', C.label],
203
- [selected.channelId ?? 'n/a', C.dim],
204
- [' Thread: ', C.label],
205
- [selected.threadId ?? 'n/a', C.dim],
206
- ]),
207
- buildPanelLine(width, [
208
- [' Last seen: ', C.label],
209
- [formatTime(selected.lastSeenAt), C.dim],
210
- ]),
211
- ] : [];
212
-
213
- if (selected && surfaceEntries.length > 0) {
214
- detailRows.push(
215
- ...surfaceEntries.slice(0, 4).map(([surface, ids]) => buildPanelLine(width, [
216
- [' ', C.label],
217
- [surface.padEnd(10), C.info],
218
- [` ${String(ids.length)} binding(s)`, C.value],
219
- ])),
220
- );
221
- }
222
-
223
- const hints = this.filterActive
224
- ? [{ keys: 'type', label: 'filter' }, { keys: 'Enter', label: 'apply' }, { keys: 'Esc', label: 'clear' }]
225
- : [
226
- { keys: 'Up/Down', label: 'move' },
227
- ...(selected?.sessionId ? [{ keys: 'Enter', label: 'open session' }] : []),
228
- { keys: 'c', label: 'communication' },
229
- { keys: '/', label: 'filter' },
230
- ];
231
-
232
- return this.renderList(width, height, {
233
- title: 'Route Bindings',
234
- header: headerLines,
235
- footer: [
236
- ...(selected ? buildDetailBlock(width, `Binding · ${selected.surfaceKind}`, detailRows, C) : []),
237
- buildKeyboardHints(width, hints, C),
238
- ],
239
- });
240
- }
241
- }