@pellux/goodvibes-tui 1.0.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 (209) hide show
  1. package/CHANGELOG.md +130 -127
  2. package/README.md +32 -14
  3. package/docs/foundation-artifacts/operator-contract.json +1 -1
  4. package/package.json +2 -2
  5. package/src/cli/ensure-goodvibes-gitignore.ts +32 -0
  6. package/src/cli/entrypoint.ts +2 -0
  7. package/src/core/alert-gating.ts +67 -0
  8. package/src/core/approval-alert.ts +72 -0
  9. package/src/core/budget-breach-notifier.ts +106 -0
  10. package/src/core/conversation-rendering.ts +19 -0
  11. package/src/core/conversation.ts +58 -0
  12. package/src/core/focus-tracker.ts +41 -0
  13. package/src/core/long-task-notifier.ts +33 -6
  14. package/src/core/stream-event-wiring.ts +104 -2
  15. package/src/core/stream-stall-watchdog.ts +41 -17
  16. package/src/core/system-message-router.ts +37 -51
  17. package/src/core/turn-cancellation.ts +20 -0
  18. package/src/core/turn-event-wiring.ts +64 -3
  19. package/src/export/cost-utils.ts +126 -8
  20. package/src/input/command-registry.ts +54 -1
  21. package/src/input/commands/checkpoint-runtime.ts +280 -0
  22. package/src/input/commands/codebase-runtime.ts +192 -0
  23. package/src/input/commands/diff-runtime.ts +61 -30
  24. package/src/input/commands/eval.ts +1 -1
  25. package/src/input/commands/health-runtime.ts +1 -1
  26. package/src/input/commands/image-runtime.ts +112 -0
  27. package/src/input/commands/intelligence-runtime.ts +11 -1
  28. package/src/input/commands/local-auth-runtime.ts +4 -1
  29. package/src/input/commands/local-runtime.ts +9 -3
  30. package/src/input/commands/marketplace-runtime.ts +2 -2
  31. package/src/input/commands/memory.ts +6 -1
  32. package/src/input/commands/operator-panel-runtime.ts +40 -24
  33. package/src/input/commands/planning-runtime.ts +26 -3
  34. package/src/input/commands/platform-sandbox-runtime.ts +1 -6
  35. package/src/input/commands/plugin-runtime.ts +2 -2
  36. package/src/input/commands/policy-dispatch.ts +21 -0
  37. package/src/input/commands/provider-accounts-runtime.ts +1 -1
  38. package/src/input/commands/qrcode-runtime.ts +3 -3
  39. package/src/input/commands/recall-review.ts +35 -0
  40. package/src/input/commands/remote-runtime.ts +3 -3
  41. package/src/input/commands/runtime-services.ts +54 -13
  42. package/src/input/commands/services-runtime.ts +1 -1
  43. package/src/input/commands/session-content.ts +12 -0
  44. package/src/input/commands/session-workflow.ts +19 -1
  45. package/src/input/commands/settings-sync-runtime.ts +1 -1
  46. package/src/input/commands/share-runtime.ts +9 -2
  47. package/src/input/commands/shell-core.ts +15 -7
  48. package/src/input/commands/skills-runtime.ts +2 -8
  49. package/src/input/commands/subscription-runtime.ts +2 -2
  50. package/src/input/commands/test-runtime.ts +277 -0
  51. package/src/input/commands/websearch-runtime.ts +101 -0
  52. package/src/input/commands/work-plan-runtime.ts +36 -10
  53. package/src/input/commands/workstream-runtime.ts +338 -0
  54. package/src/input/commands.ts +12 -0
  55. package/src/input/config-modal-types.ts +161 -0
  56. package/src/input/config-modal.ts +377 -0
  57. package/src/input/feed-context-factory.ts +7 -8
  58. package/src/input/handler-command-route.ts +27 -17
  59. package/src/input/handler-content-actions.ts +22 -8
  60. package/src/input/handler-feed-routes.ts +107 -7
  61. package/src/input/handler-feed.ts +49 -13
  62. package/src/input/handler-interactions.ts +3 -3
  63. package/src/input/handler-modal-routes.ts +65 -0
  64. package/src/input/handler-modal-stack.ts +3 -5
  65. package/src/input/handler-modal-token-routes.ts +16 -49
  66. package/src/input/handler-picker-routes.ts +11 -94
  67. package/src/input/handler-shortcuts.ts +24 -14
  68. package/src/input/handler-types.ts +3 -6
  69. package/src/input/handler-ui-state.ts +10 -22
  70. package/src/input/handler.ts +10 -28
  71. package/src/input/keybindings.ts +22 -8
  72. package/src/input/model-picker-types.ts +24 -6
  73. package/src/input/model-picker.ts +58 -0
  74. package/src/input/panel-integration-actions.ts +9 -170
  75. package/src/input/settings-modal-data.ts +95 -0
  76. package/src/input/settings-modal-mutations.ts +6 -4
  77. package/src/main.ts +41 -44
  78. package/src/panels/agent-inspector-shared.ts +35 -11
  79. package/src/panels/base-panel.ts +22 -1
  80. package/src/panels/builtin/agent.ts +21 -107
  81. package/src/panels/builtin/development.ts +16 -62
  82. package/src/panels/builtin/knowledge.ts +8 -32
  83. package/src/panels/builtin/operations.ts +84 -428
  84. package/src/panels/builtin/session.ts +21 -112
  85. package/src/panels/builtin/shared.ts +9 -43
  86. package/src/panels/builtin-modals.ts +218 -0
  87. package/src/panels/builtin-panels.ts +5 -0
  88. package/src/panels/cost-tracker-panel.ts +63 -14
  89. package/src/panels/diff-panel.ts +123 -60
  90. package/src/panels/eval-registry.ts +60 -0
  91. package/src/panels/fleet-panel.ts +800 -0
  92. package/src/panels/fleet-read-model.ts +477 -0
  93. package/src/panels/fleet-steer.ts +92 -0
  94. package/src/panels/fleet-stop.ts +125 -0
  95. package/src/panels/fleet-tabs.ts +230 -0
  96. package/src/panels/fleet-transcript.ts +356 -0
  97. package/src/panels/git-panel.ts +9 -9
  98. package/src/panels/index.ts +7 -31
  99. package/src/panels/local-auth-panel.ts +10 -0
  100. package/src/panels/modals/hooks-modal.ts +187 -0
  101. package/src/panels/modals/keybindings-modal.ts +151 -0
  102. package/src/panels/modals/knowledge-modal.ts +158 -0
  103. package/src/panels/modals/local-auth-modal.ts +132 -0
  104. package/src/panels/modals/marketplace-modal.ts +218 -0
  105. package/src/panels/modals/memory-modal.ts +180 -0
  106. package/src/panels/modals/modal-surface-helpers.ts +54 -0
  107. package/src/panels/modals/modal-theme.ts +36 -0
  108. package/src/panels/modals/pairing-modal.ts +144 -0
  109. package/src/panels/modals/planning-modal.ts +282 -0
  110. package/src/panels/modals/plugins-modal.ts +174 -0
  111. package/src/panels/modals/policy-modal.ts +256 -0
  112. package/src/panels/modals/provider-health-modal.ts +136 -0
  113. package/src/panels/modals/remote-modal.ts +115 -0
  114. package/src/panels/modals/sandbox-modal.ts +150 -0
  115. package/src/panels/modals/security-modal.ts +217 -0
  116. package/src/panels/modals/services-modal.ts +179 -0
  117. package/src/panels/modals/settings-sync-modal.ts +142 -0
  118. package/src/panels/modals/skills-modal.ts +189 -0
  119. package/src/panels/modals/subscription-modal.ts +172 -0
  120. package/src/panels/modals/work-plan-modal.ts +149 -0
  121. package/src/panels/panel-confirm-overlay.ts +72 -0
  122. package/src/panels/panel-manager.ts +108 -5
  123. package/src/panels/project-planning-answer-actions.ts +4 -2
  124. package/src/panels/scrollable-list-panel.ts +9 -0
  125. package/src/panels/skills-panel.ts +7 -51
  126. package/src/panels/token-budget-panel.ts +5 -3
  127. package/src/panels/types.ts +26 -0
  128. package/src/permissions/hunk-selection.ts +179 -0
  129. package/src/permissions/prompt.ts +60 -4
  130. package/src/renderer/compaction-history-modal.ts +19 -3
  131. package/src/renderer/compaction-preview.ts +13 -2
  132. package/src/renderer/compaction-quality.ts +100 -0
  133. package/src/renderer/config-modal.ts +81 -0
  134. package/src/renderer/conversation-overlays.ts +10 -17
  135. package/src/renderer/fleet-tab-strip.ts +56 -0
  136. package/src/renderer/footer-tips.ts +10 -2
  137. package/src/renderer/git-status.ts +40 -0
  138. package/src/renderer/help-overlay.ts +2 -2
  139. package/src/renderer/model-workspace.ts +44 -1
  140. package/src/renderer/panel-workspace-bar.ts +8 -2
  141. package/src/renderer/shell-surface.ts +8 -1
  142. package/src/renderer/turn-injection.ts +114 -0
  143. package/src/renderer/ui-factory.ts +91 -7
  144. package/src/runtime/bootstrap-command-context.ts +24 -1
  145. package/src/runtime/bootstrap-command-parts.ts +36 -7
  146. package/src/runtime/bootstrap-core.ts +19 -4
  147. package/src/runtime/bootstrap-hook-bridge.ts +5 -0
  148. package/src/runtime/bootstrap-shell.ts +41 -17
  149. package/src/runtime/bootstrap.ts +11 -17
  150. package/src/runtime/code-index-services.ts +112 -0
  151. package/src/runtime/orchestrator-core-services.ts +49 -0
  152. package/src/runtime/process-lifecycle.ts +3 -1
  153. package/src/runtime/services.ts +91 -43
  154. package/src/runtime/ui-services.ts +8 -0
  155. package/src/runtime/workstream-services.ts +195 -0
  156. package/src/shell/blocking-input.ts +22 -1
  157. package/src/shell/ui-openers.ts +129 -17
  158. package/src/utils/format-duration.ts +8 -18
  159. package/src/utils/splash-lines.ts +1 -1
  160. package/src/version.ts +1 -1
  161. package/src/panels/agent-inspector-panel.ts +0 -786
  162. package/src/panels/approval-panel.ts +0 -252
  163. package/src/panels/automation-control-panel.ts +0 -479
  164. package/src/panels/cockpit-panel.ts +0 -481
  165. package/src/panels/cockpit-read-model.ts +0 -233
  166. package/src/panels/communication-panel.ts +0 -256
  167. package/src/panels/control-plane-panel.ts +0 -470
  168. package/src/panels/debug-panel.ts +0 -609
  169. package/src/panels/docs-panel.ts +0 -375
  170. package/src/panels/eval-panel.ts +0 -627
  171. package/src/panels/file-explorer-panel.ts +0 -664
  172. package/src/panels/file-preview-panel.ts +0 -517
  173. package/src/panels/hooks-panel.ts +0 -401
  174. package/src/panels/incident-review-panel.ts +0 -406
  175. package/src/panels/intelligence-panel.ts +0 -383
  176. package/src/panels/knowledge-graph-panel.ts +0 -506
  177. package/src/panels/marketplace-panel.ts +0 -399
  178. package/src/panels/memory-panel.ts +0 -558
  179. package/src/panels/ops-control-panel.ts +0 -329
  180. package/src/panels/ops-strategy-panel.ts +0 -321
  181. package/src/panels/orchestration-panel.ts +0 -465
  182. package/src/panels/panel-list-panel.ts +0 -557
  183. package/src/panels/plan-dashboard-panel.ts +0 -707
  184. package/src/panels/policy-panel.ts +0 -517
  185. package/src/panels/project-planning-panel.ts +0 -721
  186. package/src/panels/provider-health-panel.ts +0 -678
  187. package/src/panels/provider-health-tracker.ts +0 -306
  188. package/src/panels/provider-health-views.ts +0 -560
  189. package/src/panels/qr-panel.ts +0 -280
  190. package/src/panels/remote-panel.ts +0 -534
  191. package/src/panels/routes-panel.ts +0 -241
  192. package/src/panels/sandbox-panel.ts +0 -456
  193. package/src/panels/security-panel.ts +0 -447
  194. package/src/panels/services-panel.ts +0 -329
  195. package/src/panels/session-browser-panel.ts +0 -487
  196. package/src/panels/settings-sync-panel.ts +0 -398
  197. package/src/panels/subscription-panel.ts +0 -342
  198. package/src/panels/symbol-outline-panel.ts +0 -619
  199. package/src/panels/system-messages-panel.ts +0 -364
  200. package/src/panels/tasks-panel.ts +0 -608
  201. package/src/panels/thinking-panel.ts +0 -333
  202. package/src/panels/tool-inspector-panel.ts +0 -537
  203. package/src/panels/work-plan-panel.ts +0 -530
  204. package/src/panels/worktree-panel.ts +0 -360
  205. package/src/panels/wrfc-panel.ts +0 -790
  206. package/src/renderer/agent-detail-modal.ts +0 -465
  207. package/src/renderer/live-tail-modal.ts +0 -156
  208. package/src/renderer/process-modal.ts +0 -656
  209. 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
- }