@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
|
@@ -16,6 +16,7 @@ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
|
16
16
|
import type { ForensicsRegistry } from '@/runtime/index.ts';
|
|
17
17
|
import type { PolicyRuntimeState } from '@/runtime/index.ts';
|
|
18
18
|
import type { FileUndoManager } from '@pellux/goodvibes-sdk/platform/state';
|
|
19
|
+
import type { WorkspaceCheckpointManager } from '@pellux/goodvibes-sdk/platform/workspace';
|
|
19
20
|
import type { McpRegistry } from '@pellux/goodvibes-sdk/platform/mcp';
|
|
20
21
|
import type { MemoryRegistry } from '@pellux/goodvibes-sdk/platform/state';
|
|
21
22
|
import type { IntegrationHelperService } from '@/runtime/index.ts';
|
|
@@ -61,6 +62,10 @@ export type CreateBootstrapCommandContextOptions = {
|
|
|
61
62
|
mcpRegistry: McpRegistry;
|
|
62
63
|
voiceProviderRegistry?: VoiceProviderRegistry;
|
|
63
64
|
voiceService?: VoiceService;
|
|
65
|
+
/** B31: direct-command consumers (`/search`, `/image`) of already-constructed RuntimeServices. */
|
|
66
|
+
webSearchService?: import('@pellux/goodvibes-sdk/platform/web-search').WebSearchService;
|
|
67
|
+
mediaProviders?: import('@pellux/goodvibes-sdk/platform/media').MediaProviderRegistry;
|
|
68
|
+
artifactStore?: import('@pellux/goodvibes-sdk/platform/artifacts').ArtifactStore;
|
|
64
69
|
forensicsRegistry: ForensicsRegistry;
|
|
65
70
|
policyRuntimeState: PolicyRuntimeState;
|
|
66
71
|
readModels: UiReadModels;
|
|
@@ -68,6 +73,7 @@ export type CreateBootstrapCommandContextOptions = {
|
|
|
68
73
|
remoteRuntime?: RemoteCommandService;
|
|
69
74
|
planRuntime?: PlanRuntimeService;
|
|
70
75
|
fileUndoManager: FileUndoManager;
|
|
76
|
+
workspaceCheckpointManager?: WorkspaceCheckpointManager;
|
|
71
77
|
memoryRegistry?: MemoryRegistry;
|
|
72
78
|
integrationHelpers?: IntegrationHelperService;
|
|
73
79
|
automationManager?: ShellAutomationManagerRuntimeService;
|
|
@@ -115,6 +121,9 @@ export type CreateBootstrapCommandContextOptions = {
|
|
|
115
121
|
wrfcController?: import('@pellux/goodvibes-sdk/platform/agents').WrfcController;
|
|
116
122
|
componentHealthMonitor: import('@/runtime/index.ts').ComponentHealthMonitor;
|
|
117
123
|
hydrateSessionUsage?: () => void;
|
|
124
|
+
workstreamEngine?: import('./workstream-services.ts').WorkstreamCommandService;
|
|
125
|
+
codeIndexStore?: import('@pellux/goodvibes-sdk/platform/state').CodeIndexStore;
|
|
126
|
+
getMainSessionTurnInjections?: () => readonly import('../renderer/turn-injection.ts').TurnInjectionEntry[];
|
|
118
127
|
};
|
|
119
128
|
|
|
120
129
|
export function createBootstrapCommandContext(
|
|
@@ -132,6 +141,9 @@ export function createBootstrapCommandContext(
|
|
|
132
141
|
mcpRegistry,
|
|
133
142
|
voiceProviderRegistry,
|
|
134
143
|
voiceService,
|
|
144
|
+
webSearchService,
|
|
145
|
+
mediaProviders,
|
|
146
|
+
artifactStore,
|
|
135
147
|
forensicsRegistry,
|
|
136
148
|
policyRuntimeState,
|
|
137
149
|
readModels,
|
|
@@ -139,6 +151,7 @@ export function createBootstrapCommandContext(
|
|
|
139
151
|
remoteRuntime,
|
|
140
152
|
planRuntime,
|
|
141
153
|
fileUndoManager,
|
|
154
|
+
workspaceCheckpointManager,
|
|
142
155
|
memoryRegistry,
|
|
143
156
|
integrationHelpers,
|
|
144
157
|
automationManager,
|
|
@@ -169,6 +182,9 @@ export function createBootstrapCommandContext(
|
|
|
169
182
|
wrfcController,
|
|
170
183
|
changeTracker,
|
|
171
184
|
hydrateSessionUsage,
|
|
185
|
+
workstreamEngine,
|
|
186
|
+
codeIndexStore,
|
|
187
|
+
getMainSessionTurnInjections,
|
|
172
188
|
planManager,
|
|
173
189
|
adaptivePlanner,
|
|
174
190
|
sessionOrchestration,
|
|
@@ -226,6 +242,9 @@ export function createBootstrapCommandContext(
|
|
|
226
242
|
wrfcController,
|
|
227
243
|
changeTracker,
|
|
228
244
|
hydrateSessionUsage,
|
|
245
|
+
workstreamEngine,
|
|
246
|
+
codeIndexStore,
|
|
247
|
+
getMainSessionTurnInjections,
|
|
229
248
|
});
|
|
230
249
|
const provider = createBootstrapCommandProviderSection({
|
|
231
250
|
providerRegistry,
|
|
@@ -236,6 +255,7 @@ export function createBootstrapCommandContext(
|
|
|
236
255
|
const workspace = createBootstrapCommandWorkspaceSection({
|
|
237
256
|
keybindingsManager,
|
|
238
257
|
fileUndoManager,
|
|
258
|
+
workspaceCheckpointManager,
|
|
239
259
|
panelManager,
|
|
240
260
|
profileManager,
|
|
241
261
|
bookmarkManager,
|
|
@@ -243,7 +263,7 @@ export function createBootstrapCommandContext(
|
|
|
243
263
|
projectPlanningProjectId,
|
|
244
264
|
workPlanStore,
|
|
245
265
|
}, shellServices);
|
|
246
|
-
const platform = createBootstrapCommandPlatformSection({ configManager, voiceProviderRegistry, voiceService }, shellServices);
|
|
266
|
+
const platform = createBootstrapCommandPlatformSection({ configManager, voiceProviderRegistry, voiceService, webSearchService, mediaProviders, artifactStore }, shellServices);
|
|
247
267
|
const extensions = createBootstrapCommandExtensionsSection({
|
|
248
268
|
toolRegistry,
|
|
249
269
|
mcpRegistry,
|
|
@@ -16,7 +16,8 @@ import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/pe
|
|
|
16
16
|
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
17
17
|
import type { ForensicsRegistry } from '@/runtime/index.ts';
|
|
18
18
|
import type { PolicyRuntimeState } from '@/runtime/index.ts';
|
|
19
|
-
import type { FileUndoManager } from '@pellux/goodvibes-sdk/platform/state';
|
|
19
|
+
import type { CodeIndexStore, FileUndoManager } from '@pellux/goodvibes-sdk/platform/state';
|
|
20
|
+
import type { WorkspaceCheckpointManager } from '@pellux/goodvibes-sdk/platform/workspace';
|
|
20
21
|
import type { McpRegistry } from '@pellux/goodvibes-sdk/platform/mcp';
|
|
21
22
|
import type { MemoryRegistry } from '@pellux/goodvibes-sdk/platform/state';
|
|
22
23
|
import type { IntegrationHelperService } from '@/runtime/index.ts';
|
|
@@ -79,11 +80,16 @@ export interface BootstrapCommandSectionOptions {
|
|
|
79
80
|
readonly mcpRegistry: McpRegistry;
|
|
80
81
|
readonly voiceProviderRegistry?: VoiceProviderRegistry;
|
|
81
82
|
readonly voiceService?: VoiceService;
|
|
83
|
+
/** B31: direct-command consumers (`/search`, `/image`) of already-constructed RuntimeServices. */
|
|
84
|
+
readonly webSearchService?: import('@pellux/goodvibes-sdk/platform/web-search').WebSearchService;
|
|
85
|
+
readonly mediaProviders?: import('@pellux/goodvibes-sdk/platform/media').MediaProviderRegistry;
|
|
86
|
+
readonly artifactStore?: import('@pellux/goodvibes-sdk/platform/artifacts').ArtifactStore;
|
|
82
87
|
readonly forensicsRegistry: ForensicsRegistry;
|
|
83
88
|
readonly policyRuntimeState: PolicyRuntimeState;
|
|
84
89
|
readonly readModels: UiReadModels;
|
|
85
90
|
readonly shellPaths: ShellPathService;
|
|
86
91
|
readonly fileUndoManager: FileUndoManager;
|
|
92
|
+
readonly workspaceCheckpointManager?: WorkspaceCheckpointManager;
|
|
87
93
|
readonly memoryRegistry?: MemoryRegistry;
|
|
88
94
|
readonly integrationHelpers?: IntegrationHelperService;
|
|
89
95
|
readonly knowledgeService?: KnowledgeService;
|
|
@@ -110,6 +116,9 @@ export interface BootstrapCommandSectionOptions {
|
|
|
110
116
|
readonly wrfcController?: import('@pellux/goodvibes-sdk/platform/agents').WrfcController;
|
|
111
117
|
readonly changeTracker?: import('@pellux/goodvibes-sdk/platform/sessions').SessionChangeTracker;
|
|
112
118
|
readonly hydrateSessionUsage?: () => void;
|
|
119
|
+
readonly workstreamEngine?: import('./workstream-services.ts').WorkstreamCommandService;
|
|
120
|
+
readonly codeIndexStore?: CodeIndexStore;
|
|
121
|
+
readonly getMainSessionTurnInjections?: () => readonly import('../renderer/turn-injection.ts').TurnInjectionEntry[];
|
|
113
122
|
readonly agentManager?: ShellAgentManagerService;
|
|
114
123
|
readonly modeManager?: ShellModeManagerService;
|
|
115
124
|
readonly automationManager?: ShellAutomationManagerRuntimeService;
|
|
@@ -182,8 +191,15 @@ export function createBootstrapCommandActions(
|
|
|
182
191
|
} = options;
|
|
183
192
|
|
|
184
193
|
const showPanel = (panelId: string, pane?: 'top' | 'bottom') => {
|
|
194
|
+
// W6.1 (the purge): a MIGRATE-TO-MODAL id resolves to a modal, not a panel.
|
|
195
|
+
// panelManager.open() fires the injected openModal callback and returns a
|
|
196
|
+
// no-op sentinel — so skip panelManager.show() (which would reveal an empty
|
|
197
|
+
// panel workspace behind the modal) when this id redirects. Keeps every
|
|
198
|
+
// showPanel-based front-door (openHooksPanel/openSecurityPanel/… and the
|
|
199
|
+
// migrated command runtimes) opening the modal cleanly.
|
|
200
|
+
const redirected = panelManager.getModalRedirect(panelId) !== undefined;
|
|
185
201
|
panelManager.open(panelId, pane);
|
|
186
|
-
panelManager.show();
|
|
202
|
+
if (!redirected) panelManager.show();
|
|
187
203
|
requestRender();
|
|
188
204
|
};
|
|
189
205
|
|
|
@@ -279,11 +295,15 @@ export function createBootstrapCommandActions(
|
|
|
279
295
|
openMemoryPanel: () => {
|
|
280
296
|
showPanel('memory');
|
|
281
297
|
},
|
|
298
|
+
// W6.1: remote/subscription migrated to config-modal surfaces. open() hits
|
|
299
|
+
// the modal redirect and invokes the openModal callback — do NOT go through
|
|
300
|
+
// showPanel here, which would additionally reveal + focus an (empty) panel
|
|
301
|
+
// workspace behind the fullscreen modal.
|
|
282
302
|
openRemotePanel: () => {
|
|
283
|
-
|
|
303
|
+
panelManager.open('remote');
|
|
284
304
|
},
|
|
285
305
|
openSubscriptionPanel: () => {
|
|
286
|
-
|
|
306
|
+
panelManager.open('subscription');
|
|
287
307
|
},
|
|
288
308
|
openLocalAuthMaskedEntry: (kind, username) => {
|
|
289
309
|
showPanel('local-auth');
|
|
@@ -301,7 +321,7 @@ export function createBootstrapCommandActions(
|
|
|
301
321
|
export function createBootstrapCommandSessionSection(
|
|
302
322
|
options: Pick<
|
|
303
323
|
BootstrapCommandSectionOptions,
|
|
304
|
-
'conversation' | 'runtime' | 'sessionManager' | 'sessionMemoryStore' | 'sessionLineageTracker' | 'wrfcController' | 'changeTracker' | 'hydrateSessionUsage'
|
|
324
|
+
'conversation' | 'runtime' | 'sessionManager' | 'sessionMemoryStore' | 'sessionLineageTracker' | 'wrfcController' | 'changeTracker' | 'hydrateSessionUsage' | 'workstreamEngine' | 'codeIndexStore' | 'getMainSessionTurnInjections'
|
|
305
325
|
>,
|
|
306
326
|
): BootstrapCommandSessionSection {
|
|
307
327
|
return {
|
|
@@ -313,6 +333,9 @@ export function createBootstrapCommandSessionSection(
|
|
|
313
333
|
wrfcController: options.wrfcController,
|
|
314
334
|
changeTracker: options.changeTracker,
|
|
315
335
|
hydrateSessionUsage: options.hydrateSessionUsage,
|
|
336
|
+
workstreamEngine: options.workstreamEngine,
|
|
337
|
+
codeIndexStore: options.codeIndexStore,
|
|
338
|
+
getMainSessionTurnInjections: options.getMainSessionTurnInjections,
|
|
316
339
|
};
|
|
317
340
|
}
|
|
318
341
|
|
|
@@ -333,7 +356,7 @@ export function createBootstrapCommandProviderSection(
|
|
|
333
356
|
export function createBootstrapCommandWorkspaceSection(
|
|
334
357
|
options: Pick<
|
|
335
358
|
BootstrapCommandSectionOptions,
|
|
336
|
-
'keybindingsManager' | 'fileUndoManager' | 'panelManager' | 'profileManager' | 'bookmarkManager'
|
|
359
|
+
'keybindingsManager' | 'fileUndoManager' | 'workspaceCheckpointManager' | 'panelManager' | 'profileManager' | 'bookmarkManager'
|
|
337
360
|
| 'projectPlanningService' | 'projectPlanningProjectId' | 'workPlanStore'
|
|
338
361
|
>,
|
|
339
362
|
shellServices: BootstrapCommandShellServices,
|
|
@@ -341,6 +364,7 @@ export function createBootstrapCommandWorkspaceSection(
|
|
|
341
364
|
return {
|
|
342
365
|
keybindingsManager: options.keybindingsManager,
|
|
343
366
|
fileUndoManager: options.fileUndoManager,
|
|
367
|
+
workspaceCheckpointManager: options.workspaceCheckpointManager,
|
|
344
368
|
panelManager: options.panelManager,
|
|
345
369
|
profileManager: options.profileManager,
|
|
346
370
|
bookmarkManager: options.bookmarkManager,
|
|
@@ -354,7 +378,7 @@ export function createBootstrapCommandWorkspaceSection(
|
|
|
354
378
|
export function createBootstrapCommandPlatformSection(
|
|
355
379
|
options: Pick<
|
|
356
380
|
BootstrapCommandSectionOptions,
|
|
357
|
-
'configManager' | 'voiceProviderRegistry' | 'voiceService'
|
|
381
|
+
'configManager' | 'voiceProviderRegistry' | 'voiceService' | 'webSearchService' | 'mediaProviders' | 'artifactStore'
|
|
358
382
|
>,
|
|
359
383
|
shellServices: BootstrapCommandShellServices,
|
|
360
384
|
): BootstrapCommandPlatformSection {
|
|
@@ -363,6 +387,9 @@ export function createBootstrapCommandPlatformSection(
|
|
|
363
387
|
configManager: options.configManager,
|
|
364
388
|
voiceProviderRegistry: options.voiceProviderRegistry,
|
|
365
389
|
voiceService: options.voiceService,
|
|
390
|
+
webSearchService: options.webSearchService,
|
|
391
|
+
mediaProviders: options.mediaProviders,
|
|
392
|
+
artifactStore: options.artifactStore,
|
|
366
393
|
...shellServices.platform,
|
|
367
394
|
};
|
|
368
395
|
}
|
|
@@ -7,7 +7,6 @@ import { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
|
7
7
|
import { registerAllTools } from '@pellux/goodvibes-sdk/platform/tools';
|
|
8
8
|
import { PermissionManager, createPermissionConfigReader } from '@pellux/goodvibes-sdk/platform/permissions';
|
|
9
9
|
import { Notifier } from '@pellux/goodvibes-sdk/platform/integrations';
|
|
10
|
-
import { WebhookNotifier } from '@pellux/goodvibes-sdk/platform/integrations';
|
|
11
10
|
import { Compositor } from '../renderer/compositor.ts';
|
|
12
11
|
import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions';
|
|
13
12
|
import type { SystemMessageRouter } from '../core/system-message-router.ts';
|
|
@@ -33,7 +32,7 @@ import { createUiRuntimeServices, type UiRuntimeServices } from './ui-services.t
|
|
|
33
32
|
import { join } from 'node:path';
|
|
34
33
|
import { installWrfcAgentToolGuard } from '../tools/wrfc-agent-guard.ts';
|
|
35
34
|
import { createWrfcPersistence, type WrfcPersistence } from './wrfc-persistence.ts';
|
|
36
|
-
import type { SystemMessagePriority } from '../
|
|
35
|
+
import type { SystemMessagePriority } from '../core/system-message-router.ts';
|
|
37
36
|
|
|
38
37
|
// ---------------------------------------------------------------------------
|
|
39
38
|
// Pre-router buffer
|
|
@@ -637,10 +636,20 @@ export async function initializeBootstrapCore(
|
|
|
637
636
|
|
|
638
637
|
providerRegistry.startWatching(runtimeBus);
|
|
639
638
|
|
|
639
|
+
// W2.3: attach the SAME WebhookNotifier instance that `/notify add|remove|clear`
|
|
640
|
+
// (notify-runtime.ts) keeps live via ctx.services.webhookNotifier, rather than
|
|
641
|
+
// constructing a second, boot-time-only instance here. Before this fix, a
|
|
642
|
+
// webhook URL added mid-session reached long-task notifications (which read
|
|
643
|
+
// ctx.services.webhookNotifier directly) but never reached this instance's
|
|
644
|
+
// AGENT_FAILED/WORKFLOW_CHAIN_FAILED/WORKFLOW_CHAIN_PASSED runtime-bus
|
|
645
|
+
// listeners until restart — and if the session started with zero URLs
|
|
646
|
+
// configured, attachToRuntimeBus was never even called, so those listeners
|
|
647
|
+
// never existed at all for the rest of the session. Always attaching
|
|
648
|
+
// (regardless of initial URL count) and seeding the shared instance fixes
|
|
649
|
+
// both: `send()` is already a safe no-op with zero URLs configured.
|
|
640
650
|
const webhookUrls = (configManager.getCategory('notifications') as { webhookUrls?: string[] }).webhookUrls ?? [];
|
|
641
651
|
if (webhookUrls.length > 0) {
|
|
642
|
-
|
|
643
|
-
webhookNotifier.attachToRuntimeBus(runtimeBus);
|
|
652
|
+
services.webhookNotifier.setUrls(webhookUrls);
|
|
644
653
|
domainDispatch.syncIntegration({
|
|
645
654
|
id: 'webhooks',
|
|
646
655
|
displayName: 'Webhooks',
|
|
@@ -652,6 +661,7 @@ export async function initializeBootstrapCore(
|
|
|
652
661
|
meta: { urlCount: webhookUrls.length },
|
|
653
662
|
}, 'bootstrap.webhooks');
|
|
654
663
|
}
|
|
664
|
+
services.webhookNotifier.attachToRuntimeBus(runtimeBus);
|
|
655
665
|
|
|
656
666
|
const notifier = await Notifier.fromConfig(services.serviceRegistry);
|
|
657
667
|
const queueStatuses = notifier.getQueueStatus();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
|
+
import { readBudgetAlertUsd, BUDGET_ALERT_USD_DEFAULT } from '../export/cost-utils.ts';
|
|
2
3
|
import { sumConversationUsage, type ConversationManager } from '../core/conversation';
|
|
3
4
|
import type { Orchestrator } from '../core/orchestrator';
|
|
4
5
|
import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
@@ -15,7 +16,6 @@ import { GitStatusProvider } from '../renderer/git-status.ts';
|
|
|
15
16
|
import type { GitHeaderInfo } from '../renderer/git-status.ts';
|
|
16
17
|
import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions';
|
|
17
18
|
import { registerBuiltinPanels } from '../panels/builtin-panels.ts';
|
|
18
|
-
import { SystemMessagesPanel } from '../panels/system-messages-panel.ts';
|
|
19
19
|
import { createSystemMessageRouter, type SystemMessageRouter } from '../core/system-message-router.ts';
|
|
20
20
|
import { getConfigSnapshot } from '../config/index.ts';
|
|
21
21
|
import { createBootstrapCommandContext } from './bootstrap-command-context.ts';
|
|
@@ -40,11 +40,6 @@ export interface BootstrapShellState {
|
|
|
40
40
|
readonly lastGitInfoRef: { value: GitHeaderInfo | undefined };
|
|
41
41
|
readonly inputHistory: InputHistory;
|
|
42
42
|
readonly systemMessageRouter: SystemMessageRouter;
|
|
43
|
-
/**
|
|
44
|
-
* Wire the agent detail modal opener after InputHandler is constructed.
|
|
45
|
-
* Call with `(id) => input.agentDetailModal.open(id)` from main.ts.
|
|
46
|
-
*/
|
|
47
|
-
readonly setOpenAgentDetail: (fn: (agentId: string) => void) => void;
|
|
48
43
|
}
|
|
49
44
|
|
|
50
45
|
export interface BootstrapShellOptions {
|
|
@@ -92,7 +87,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
92
87
|
completeModelSelectionSideEffect,
|
|
93
88
|
} = options;
|
|
94
89
|
|
|
95
|
-
const systemMessagesPanel = new SystemMessagesPanel(configManager, services.componentHealthMonitor);
|
|
96
90
|
// W0.9: after any resume seam replays historical messages into `conversation`,
|
|
97
91
|
// the freshly-constructed `orchestrator` still has its zeroed default usage
|
|
98
92
|
// (SDK gap — Orchestrator.usage is never persisted/reseeded). Recompute it
|
|
@@ -138,16 +132,22 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
138
132
|
runtimeBus,
|
|
139
133
|
});
|
|
140
134
|
|
|
141
|
-
const openAgentDetailRef: { fn: (agentId: string) => void } = { fn: (_agentId: string) => {} };
|
|
142
|
-
|
|
143
135
|
// WO-139: initial cost-budget alert threshold (USD; 0/unset = disabled).
|
|
144
136
|
// Once the session starts, the real control surface is the CostTrackerPanel
|
|
145
137
|
// itself — the in-panel 'b' key and /cost budget <usd> both call
|
|
146
|
-
// CostTrackerPanel.setBudgetThreshold() directly on the live panel instance
|
|
138
|
+
// CostTrackerPanel.setBudgetThreshold() directly on the live panel instance,
|
|
139
|
+
// which (W2.3) now writes through to the behavior.budgetAlertUsd config key
|
|
140
|
+
// so the background budget-breach notifier reads the same value. The env
|
|
141
|
+
// var remains a first-run convenience only: it seeds the config key when
|
|
142
|
+
// that key has never been set, so it doesn't silently override a value the
|
|
143
|
+
// user has already configured in a prior session.
|
|
147
144
|
const parsedBudgetThreshold = Number(process.env.GOODVIBES_COST_BUDGET_USD);
|
|
148
145
|
const initialCostBudgetThreshold = Number.isFinite(parsedBudgetThreshold) && parsedBudgetThreshold > 0
|
|
149
146
|
? parsedBudgetThreshold
|
|
150
147
|
: 0;
|
|
148
|
+
if (initialCostBudgetThreshold > 0 && readBudgetAlertUsd((k) => configManager.get(k as Parameters<typeof configManager.get>[0])) === BUDGET_ALERT_USD_DEFAULT) {
|
|
149
|
+
configManager.set('behavior.budgetAlertUsd' as Parameters<typeof configManager.set>[0], initialCostBudgetThreshold as never);
|
|
150
|
+
}
|
|
151
151
|
|
|
152
152
|
let commandContextRef: CommandContext | null = null;
|
|
153
153
|
registerBuiltinPanels(services.panelManager, {
|
|
@@ -182,7 +182,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
182
182
|
componentHealthMonitor: services.componentHealthMonitor,
|
|
183
183
|
worktreeRegistry: services.worktreeRegistry,
|
|
184
184
|
sandboxSessionRegistry: services.sandboxSessionRegistry,
|
|
185
|
-
systemMessagesPanel,
|
|
186
185
|
memoryRegistry: services.memoryRegistry,
|
|
187
186
|
uiServices,
|
|
188
187
|
pluginManager: services.pluginManager,
|
|
@@ -190,7 +189,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
190
189
|
hookActivityTracker: services.hookActivityTracker,
|
|
191
190
|
hookWorkbench: services.hookWorkbench,
|
|
192
191
|
mcpRegistry: services.mcpRegistry,
|
|
193
|
-
openAgentDetail: (agentId: string) => openAgentDetailRef.fn(agentId),
|
|
194
192
|
daemonHomeDir: join(services.homeDirectory, '.goodvibes', 'daemon'),
|
|
195
193
|
opsApi,
|
|
196
194
|
planRuntime,
|
|
@@ -203,7 +201,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
203
201
|
|
|
204
202
|
const systemMessageRouter = createSystemMessageRouter(
|
|
205
203
|
conversation,
|
|
206
|
-
systemMessagesPanel,
|
|
207
204
|
(kind) => {
|
|
208
205
|
const ui = getConfigSnapshot(configManager).ui;
|
|
209
206
|
if (kind === 'wrfc') return ui.wrfcMessages;
|
|
@@ -233,6 +230,9 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
233
230
|
mcpRegistry: services.mcpRegistry,
|
|
234
231
|
voiceProviderRegistry: services.voiceProviders,
|
|
235
232
|
voiceService: services.voiceService,
|
|
233
|
+
webSearchService: services.webSearchService,
|
|
234
|
+
mediaProviders: services.mediaProviders,
|
|
235
|
+
artifactStore: services.artifactStore,
|
|
236
236
|
forensicsRegistry,
|
|
237
237
|
policyRuntimeState,
|
|
238
238
|
readModels: uiServices.readModels,
|
|
@@ -240,6 +240,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
240
240
|
remoteRuntime,
|
|
241
241
|
planRuntime,
|
|
242
242
|
fileUndoManager: services.fileUndoManager,
|
|
243
|
+
workspaceCheckpointManager: services.workspaceCheckpointManager,
|
|
243
244
|
memoryRegistry: services.memoryRegistry,
|
|
244
245
|
integrationHelpers: services.integrationHelpers,
|
|
245
246
|
automationManager: services.automationManager,
|
|
@@ -268,6 +269,11 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
268
269
|
sessionMemoryStore: services.sessionMemoryStore,
|
|
269
270
|
sessionLineageTracker: services.sessionLineageTracker,
|
|
270
271
|
wrfcController: services.wrfcController,
|
|
272
|
+
workstreamEngine: services.workstreamCommands,
|
|
273
|
+
codeIndexStore: services.codeIndexStore,
|
|
274
|
+
// Wave 5 (wo805): expose the MAIN session's per-turn passive-injection ring
|
|
275
|
+
// so `/recall injections` (no agent id) renders it — see recall-review.ts.
|
|
276
|
+
getMainSessionTurnInjections: () => orchestrator.getTurnInjections(),
|
|
271
277
|
changeTracker: services.sessionChangeTracker,
|
|
272
278
|
planManager: services.planManager,
|
|
273
279
|
adaptivePlanner: services.adaptivePlanner,
|
|
@@ -302,6 +308,16 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
302
308
|
lastGitInfoRef.value = info;
|
|
303
309
|
requestRender();
|
|
304
310
|
}).catch(() => { /* non-fatal */ });
|
|
311
|
+
// W1.6 FIX 2: the header's git segment otherwise only refreshes on
|
|
312
|
+
// TURN_COMPLETED/TOOL_SUCCEEDED/TOOL_FAILED (see turn-event-wiring.ts's
|
|
313
|
+
// refreshGit()) — if the user runs `git init` externally and never submits
|
|
314
|
+
// another turn, the header stays stuck on the startup-time fallback
|
|
315
|
+
// indefinitely. Poll at the same 5s cadence GitPanel already uses for its
|
|
316
|
+
// own self-poll (git-panel.ts) so the two mechanisms are cadence-consistent.
|
|
317
|
+
gitStatusProvider.startPolling(5_000, (info) => {
|
|
318
|
+
lastGitInfoRef.value = info;
|
|
319
|
+
requestRender();
|
|
320
|
+
});
|
|
305
321
|
|
|
306
322
|
const saveHistory = configManager.get('behavior.saveHistory') as boolean;
|
|
307
323
|
const inputHistory = new InputHistory({
|
|
@@ -316,8 +332,5 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
316
332
|
lastGitInfoRef,
|
|
317
333
|
inputHistory,
|
|
318
334
|
systemMessageRouter,
|
|
319
|
-
setOpenAgentDetail: (fn: (agentId: string) => void) => {
|
|
320
|
-
openAgentDetailRef.fn = fn;
|
|
321
|
-
},
|
|
322
335
|
};
|
|
323
336
|
}
|
package/src/runtime/bootstrap.ts
CHANGED
|
@@ -42,6 +42,7 @@ import type { UiRuntimeServices } from './ui-services.ts';
|
|
|
42
42
|
import { createDeferredStartupCoordinator } from '@/runtime/index.ts';
|
|
43
43
|
import { initializeBootstrapCore } from './bootstrap-core.ts';
|
|
44
44
|
import { createBootstrapShell } from './bootstrap-shell.ts';
|
|
45
|
+
import { buildSharedOrchestratorCoreServices } from './orchestrator-core-services.ts';
|
|
45
46
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
46
47
|
import { DaemonServer } from '@pellux/goodvibes-sdk/platform/daemon';
|
|
47
48
|
import { HttpListener } from '@pellux/goodvibes-sdk/platform/daemon';
|
|
@@ -110,19 +111,15 @@ export type BootstrapContext = RuntimeContext & {
|
|
|
110
111
|
/** Command registry used by InputHandler. main.ts needs this to wire input. */
|
|
111
112
|
commandRegistry: import('../input/command-registry.ts').CommandRegistry;
|
|
112
113
|
/**
|
|
113
|
-
* System message router instantiated at startup, wired to conversation
|
|
114
|
+
* System message router instantiated at startup, wired to conversation.
|
|
114
115
|
*
|
|
115
116
|
* @remarks
|
|
116
117
|
* Route operational messages through this rather than calling
|
|
117
|
-
* conversation.addSystemMessage() directly so
|
|
118
|
-
*
|
|
118
|
+
* conversation.addSystemMessage() directly so routing-target config
|
|
119
|
+
* (panel/conversation/both) and the forced-inline critical prefixes stay
|
|
120
|
+
* centralized in one place.
|
|
119
121
|
*/
|
|
120
122
|
systemMessageRouter: SystemMessageRouter;
|
|
121
|
-
/**
|
|
122
|
-
* Wire the agent detail modal opener after InputHandler is constructed in main.ts.
|
|
123
|
-
* Call with `(id) => input.agentDetailModal.open(id)` once the InputHandler is ready.
|
|
124
|
-
*/
|
|
125
|
-
setOpenAgentDetail: (fn: (agentId: string) => void) => void;
|
|
126
123
|
};
|
|
127
124
|
|
|
128
125
|
// ── Bootstrap function ────────────────────────────────────────────────────
|
|
@@ -235,15 +232,11 @@ export async function bootstrapRuntime(
|
|
|
235
232
|
logger.debug('companion handleUserInput safety catch', { error: String(err) });
|
|
236
233
|
});
|
|
237
234
|
};
|
|
235
|
+
// Shared payload (single source of truth, includes wo805's memoryRegistry —
|
|
236
|
+
// see orchestrator-core-services.ts) plus this site's cacheHitTracker.
|
|
238
237
|
orchestrator.setCoreServices({
|
|
239
|
-
configManager,
|
|
240
|
-
providerRegistry,
|
|
238
|
+
...buildSharedOrchestratorCoreServices({ services, configManager, providerRegistry }),
|
|
241
239
|
cacheHitTracker: services.cacheHitTracker,
|
|
242
|
-
planManager: services.planManager,
|
|
243
|
-
adaptivePlanner: services.adaptivePlanner,
|
|
244
|
-
sessionMemoryStore: services.sessionMemoryStore,
|
|
245
|
-
sessionLineageTracker: services.sessionLineageTracker,
|
|
246
|
-
idempotencyStore: services.idempotencyStore,
|
|
247
240
|
});
|
|
248
241
|
conversation.setSessionLineageTracker(services.sessionLineageTracker);
|
|
249
242
|
|
|
@@ -297,7 +290,9 @@ export async function bootstrapRuntime(
|
|
|
297
290
|
const gitStatusProvider = shell.gitStatusProvider;
|
|
298
291
|
const inputHistory = shell.inputHistory;
|
|
299
292
|
const lastGitInfoRef = shell.lastGitInfoRef;
|
|
300
|
-
|
|
293
|
+
// W1.6 FIX 2: dispose the header's live-repo-state poll (git-status.ts
|
|
294
|
+
// startPolling) on shutdown, same pattern as acpTaskSyncInterval above.
|
|
295
|
+
bootstrapUnsubs.push(() => gitStatusProvider.stopPolling());
|
|
301
296
|
const pluginCommandRegistry = {
|
|
302
297
|
register(command: {
|
|
303
298
|
readonly name: string;
|
|
@@ -628,7 +623,6 @@ export async function bootstrapRuntime(
|
|
|
628
623
|
_getConfiguredProviderIds: () => services.providerRegistry.getConfiguredProviderIds(),
|
|
629
624
|
commandRegistry,
|
|
630
625
|
systemMessageRouter,
|
|
631
|
-
setOpenAgentDetail,
|
|
632
626
|
shutdown: async (sessionData) => {
|
|
633
627
|
// Clear bootstrap-owned subscriptions
|
|
634
628
|
bootstrapUnsubs.forEach(fn => fn());
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// code-index-services.ts — Wave 5 (wo804, W5.3 Stage A TUI wiring)
|
|
3
|
+
//
|
|
4
|
+
// Constructs the TUI's repo source-tree code index: CodeIndexStore
|
|
5
|
+
// (@pellux/goodvibes-sdk/platform/state, landed on SDK main as wo802/W5.3
|
|
6
|
+
// Stage A). Extracted into its own module rather than built inline in
|
|
7
|
+
// services.ts: services.ts sits at the architecture check's 800-line cap
|
|
8
|
+
// (scripts/check-architecture.ts), so any new service gets its own
|
|
9
|
+
// construction module and a single wiring call there (mirrors
|
|
10
|
+
// createWorkstreamServices's one-function-bundle shape).
|
|
11
|
+
//
|
|
12
|
+
// Schema-initialized eagerly (mirrors memoryStore: construction + init()
|
|
13
|
+
// happen unconditionally so the store is queryable — /codebase status, the
|
|
14
|
+
// fleet node — even before any build has ever run). The actual walk/chunk/
|
|
15
|
+
// embed build is NEVER auto-triggered by default: the hundreds of existing
|
|
16
|
+
// test fixtures (and every headless invocation) construct RuntimeServices
|
|
17
|
+
// without asking for a full source-tree walk, and init() alone never runs
|
|
18
|
+
// one (mirrors the SDK's own RuntimeServices wiring in
|
|
19
|
+
// platform/runtime/services.ts, which gates its equivalent scheduleBuild()
|
|
20
|
+
// call behind an explicit autoStartCodeIndex option).
|
|
21
|
+
//
|
|
22
|
+
// REALITY-WINS DIVERGENCE from the SDK's own shape: the SDK's
|
|
23
|
+
// RuntimeServicesOptions exposes autoStartCodeIndex as a constructor-time
|
|
24
|
+
// boolean because that call site is a library entrypoint threaded by each
|
|
25
|
+
// embedder. This TUI's createRuntimeServices has no such per-call knob —
|
|
26
|
+
// auto-start is decided from a TUI-local config key instead
|
|
27
|
+
// (CODE_INDEX_ENABLED_CONFIG_KEY, default OFF), so every construction path
|
|
28
|
+
// (interactive main.ts, the daemon, and every test fixture) shares one
|
|
29
|
+
// honest, user-visible on/off switch rather than needing to thread a new
|
|
30
|
+
// boolean through every call site. With it off (the default), `/codebase
|
|
31
|
+
// build` is the explicit, visible trigger — exactly the shape wo804's brief
|
|
32
|
+
// asks for.
|
|
33
|
+
//
|
|
34
|
+
// Shares memoryEmbeddingRegistry with MemoryStore (constructed in
|
|
35
|
+
// services.ts) so code + memory retrieval use one embedding provider and one
|
|
36
|
+
// dimensionality, per the SDK design doc (code-index-store.ts's constructor
|
|
37
|
+
// takes the SAME MemoryEmbeddingProviderRegistry instance memory uses).
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
import { join } from 'node:path';
|
|
41
|
+
import { CodeIndexStore } from '@pellux/goodvibes-sdk/platform/state';
|
|
42
|
+
import type { MemoryEmbeddingProviderRegistry } from '@pellux/goodvibes-sdk/platform/state';
|
|
43
|
+
import type { ConfigKey, ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
44
|
+
import { readBooleanConfig } from '../core/alert-gating.ts';
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* TUI-local synthetic config key (not yet in the SDK's ConfigKey union) that
|
|
48
|
+
* gates the code index's auto-build on construction. Default OFF — see this
|
|
49
|
+
* module's header doc. Surfaced in /config via a synthetic entry
|
|
50
|
+
* (settings-modal-data.ts) exactly like behavior.notifyAfterSeconds.
|
|
51
|
+
*/
|
|
52
|
+
export const CODE_INDEX_ENABLED_CONFIG_KEY = 'storage.codeIndexEnabled';
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Honest, generous bounds passed EXPLICITLY to CodeIndexStore (values equal
|
|
56
|
+
* to its own internal defaults) so /codebase status and the settings
|
|
57
|
+
* description can state them in one place without reaching into store
|
|
58
|
+
* internals or duplicating magic numbers.
|
|
59
|
+
*/
|
|
60
|
+
export const CODE_INDEX_MAX_FILES = 5000;
|
|
61
|
+
export const CODE_INDEX_MAX_FILE_BYTES = 512 * 1024;
|
|
62
|
+
export const CODE_INDEX_MAX_TOTAL_BYTES = 256 * 1024 * 1024;
|
|
63
|
+
|
|
64
|
+
export interface CodeIndexServicesDeps {
|
|
65
|
+
readonly workingDirectory: string;
|
|
66
|
+
readonly configManager: Pick<ConfigManager, 'get'>;
|
|
67
|
+
readonly memoryEmbeddingRegistry: MemoryEmbeddingProviderRegistry;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface CodeIndexServices {
|
|
71
|
+
readonly codeIndexStore: CodeIndexStore;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Absolute path to the TUI's code-index sqlite file, sibling to memory.sqlite under .goodvibes/tui/. */
|
|
75
|
+
export function codeIndexDbPath(workingDirectory: string): string {
|
|
76
|
+
return join(workingDirectory, '.goodvibes', 'tui', 'code-index.sqlite');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Whether the code index's initial build should auto-start on construction.
|
|
81
|
+
* Exported so /codebase status and the settings modal read the exact same
|
|
82
|
+
* config key + default this module decides auto-start from.
|
|
83
|
+
*/
|
|
84
|
+
export function isCodeIndexAutoStartEnabled(configManager: Pick<ConfigManager, 'get'>): boolean {
|
|
85
|
+
return readBooleanConfig(
|
|
86
|
+
(key) => configManager.get(key as ConfigKey),
|
|
87
|
+
CODE_INDEX_ENABLED_CONFIG_KEY,
|
|
88
|
+
false,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Constructs the TUI's CodeIndexStore. Schema-init runs unconditionally
|
|
94
|
+
* (init() never throws — it degrades to an honest `available: false` +
|
|
95
|
+
* recorded error on failure, mirrored by CodeIndexStats/describeDegradation);
|
|
96
|
+
* the initial full build only fires when isCodeIndexAutoStartEnabled() is
|
|
97
|
+
* true, via the SAME fire-and-forget scheduleBuild() an explicit
|
|
98
|
+
* `/codebase build` invocation uses.
|
|
99
|
+
*/
|
|
100
|
+
export function createCodeIndexServices(deps: CodeIndexServicesDeps): CodeIndexServices {
|
|
101
|
+
const codeIndexStore = new CodeIndexStore(
|
|
102
|
+
deps.workingDirectory,
|
|
103
|
+
codeIndexDbPath(deps.workingDirectory),
|
|
104
|
+
deps.memoryEmbeddingRegistry,
|
|
105
|
+
{ maxFiles: CODE_INDEX_MAX_FILES, maxFileBytes: CODE_INDEX_MAX_FILE_BYTES, maxTotalBytes: CODE_INDEX_MAX_TOTAL_BYTES },
|
|
106
|
+
);
|
|
107
|
+
codeIndexStore.init();
|
|
108
|
+
if (isCodeIndexAutoStartEnabled(deps.configManager)) {
|
|
109
|
+
codeIndexStore.scheduleBuild();
|
|
110
|
+
}
|
|
111
|
+
return { codeIndexStore };
|
|
112
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { OrchestratorCoreServices } from '@pellux/goodvibes-sdk/platform/core';
|
|
2
|
+
import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
3
|
+
import type { ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
4
|
+
import type { RuntimeServices } from './services.ts';
|
|
5
|
+
|
|
6
|
+
/** The slice of the runtime services bag the shared orchestrator payload draws from. */
|
|
7
|
+
export type OrchestratorCoreServicesSource = Pick<
|
|
8
|
+
RuntimeServices,
|
|
9
|
+
| 'planManager'
|
|
10
|
+
| 'adaptivePlanner'
|
|
11
|
+
| 'sessionMemoryStore'
|
|
12
|
+
| 'sessionLineageTracker'
|
|
13
|
+
| 'idempotencyStore'
|
|
14
|
+
| 'memoryRegistry'
|
|
15
|
+
>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The single source of truth for the `Orchestrator.setCoreServices()` payload
|
|
19
|
+
* fields shared by BOTH call sites (runtime/bootstrap.ts and main.ts). Each
|
|
20
|
+
* site spreads this and adds its own site-specific extras (bootstrap:
|
|
21
|
+
* cacheHitTracker; main: favoritesStore) — setCoreServices() merges, so the
|
|
22
|
+
* later main.ts call only overlays, never erases.
|
|
23
|
+
*
|
|
24
|
+
* Wave-5 (wo805) BLOCKER regression guard: `memoryRegistry` here is what turns
|
|
25
|
+
* on per-turn passive knowledge injection for the MAIN interactive session —
|
|
26
|
+
* the SDK turn loop hard-gates on `coreServices.memoryRegistry` (undefined is
|
|
27
|
+
* a silent no-op: Orchestrator.getTurnInjections() stays empty forever and
|
|
28
|
+
* `/recall injections` renders a misleading empty state). Both call sites once
|
|
29
|
+
* omitted it independently; routing them through this one function (with
|
|
30
|
+
* src/test/runtime/orchestrator-core-services.test.ts pinning the field) is
|
|
31
|
+
* what keeps that from regressing.
|
|
32
|
+
*/
|
|
33
|
+
export function buildSharedOrchestratorCoreServices(input: {
|
|
34
|
+
readonly services: OrchestratorCoreServicesSource;
|
|
35
|
+
readonly configManager: ConfigManager;
|
|
36
|
+
readonly providerRegistry: ProviderRegistry;
|
|
37
|
+
}): OrchestratorCoreServices {
|
|
38
|
+
const { services, configManager, providerRegistry } = input;
|
|
39
|
+
return {
|
|
40
|
+
configManager,
|
|
41
|
+
providerRegistry,
|
|
42
|
+
planManager: services.planManager,
|
|
43
|
+
adaptivePlanner: services.adaptivePlanner,
|
|
44
|
+
sessionMemoryStore: services.sessionMemoryStore,
|
|
45
|
+
sessionLineageTracker: services.sessionLineageTracker,
|
|
46
|
+
idempotencyStore: services.idempotencyStore,
|
|
47
|
+
memoryRegistry: services.memoryRegistry,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -34,6 +34,8 @@ export interface ProcessLifecycleAnsi {
|
|
|
34
34
|
readonly KEYBOARD_EXT_DISABLE: string;
|
|
35
35
|
readonly MOUSE_DISABLE: string;
|
|
36
36
|
readonly CURSOR_SHOW: string;
|
|
37
|
+
/** Disables terminal focus-event reporting (DECSET ?1004l) — see main.ts FOCUS_ENABLE. */
|
|
38
|
+
readonly FOCUS_DISABLE: string;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
export interface ProcessLifecycleDeps {
|
|
@@ -128,7 +130,7 @@ export function installProcessLifecycle(deps: ProcessLifecycleDeps): ProcessLife
|
|
|
128
130
|
if (terminalRestored) return;
|
|
129
131
|
terminalRestored = true;
|
|
130
132
|
const exitScreen = noAltScreen ? ansi.CLEAR_SCREEN : ansi.CLEAR_SCREEN + ansi.ALT_SCREEN_EXIT;
|
|
131
|
-
allowTerminalWrite(() => stdout.write(ansi.PASTE_DISABLE + ansi.KEYBOARD_EXT_DISABLE + ansi.MOUSE_DISABLE + ansi.CURSOR_SHOW + exitScreen));
|
|
133
|
+
allowTerminalWrite(() => stdout.write(ansi.PASTE_DISABLE + ansi.KEYBOARD_EXT_DISABLE + ansi.MOUSE_DISABLE + ansi.FOCUS_DISABLE + ansi.CURSOR_SHOW + exitScreen));
|
|
132
134
|
getTerminalOutputGuard().dispose();
|
|
133
135
|
try { stdin.setRawMode(false); } catch { /* stdin may not be a TTY */ }
|
|
134
136
|
};
|