@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.
- package/CHANGELOG.md +130 -127
- package/README.md +32 -14
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +2 -2
- package/src/cli/ensure-goodvibes-gitignore.ts +32 -0
- package/src/cli/entrypoint.ts +2 -0
- 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 +58 -0
- package/src/core/focus-tracker.ts +41 -0
- package/src/core/long-task-notifier.ts +33 -6
- package/src/core/stream-event-wiring.ts +104 -2
- package/src/core/stream-stall-watchdog.ts +41 -17
- 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 +126 -8
- package/src/input/command-registry.ts +54 -1
- package/src/input/commands/checkpoint-runtime.ts +280 -0
- package/src/input/commands/codebase-runtime.ts +192 -0
- package/src/input/commands/diff-runtime.ts +61 -30
- 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-content.ts +12 -0
- package/src/input/commands/session-workflow.ts +19 -1
- package/src/input/commands/settings-sync-runtime.ts +1 -1
- package/src/input/commands/share-runtime.ts +9 -2
- 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-content-actions.ts +22 -8
- package/src/input/handler-feed-routes.ts +107 -7
- package/src/input/handler-feed.ts +49 -13
- package/src/input/handler-interactions.ts +3 -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 +3 -6
- package/src/input/handler-ui-state.ts +10 -22
- package/src/input/handler.ts +10 -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 +41 -44
- package/src/panels/agent-inspector-shared.ts +35 -11
- package/src/panels/base-panel.ts +22 -1
- package/src/panels/builtin/agent.ts +21 -107
- package/src/panels/builtin/development.ts +16 -62
- 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 +63 -14
- package/src/panels/diff-panel.ts +123 -60
- 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/git-panel.ts +9 -9
- package/src/panels/index.ts +7 -31
- package/src/panels/local-auth-panel.ts +10 -0
- 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/scrollable-list-panel.ts +9 -0
- package/src/panels/skills-panel.ts +7 -51
- package/src/panels/token-budget-panel.ts +5 -3
- package/src/panels/types.ts +26 -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/shell-surface.ts +8 -1
- package/src/renderer/turn-injection.ts +114 -0
- package/src/renderer/ui-factory.ts +91 -7
- package/src/runtime/bootstrap-command-context.ts +24 -1
- package/src/runtime/bootstrap-command-parts.ts +36 -7
- package/src/runtime/bootstrap-core.ts +19 -4
- package/src/runtime/bootstrap-hook-bridge.ts +5 -0
- package/src/runtime/bootstrap-shell.ts +41 -17
- 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 -233
- package/src/panels/communication-panel.ts +0 -256
- package/src/panels/control-plane-panel.ts +0 -470
- package/src/panels/debug-panel.ts +0 -609
- package/src/panels/docs-panel.ts +0 -375
- package/src/panels/eval-panel.ts +0 -627
- package/src/panels/file-explorer-panel.ts +0 -664
- 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 -506
- 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 -557
- 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 -721
- package/src/panels/provider-health-panel.ts +0 -678
- package/src/panels/provider-health-tracker.ts +0 -306
- package/src/panels/provider-health-views.ts +0 -560
- 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 -487
- 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 -530
- package/src/panels/worktree-panel.ts +0 -360
- package/src/panels/wrfc-panel.ts +0 -790
- package/src/renderer/agent-detail-modal.ts +0 -465
- package/src/renderer/live-tail-modal.ts +0 -156
- package/src/renderer/process-modal.ts +0 -656
- package/src/renderer/qr-renderer.ts +0 -120
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
|
-
import
|
|
2
|
+
import { readBudgetAlertUsd, BUDGET_ALERT_USD_DEFAULT } from '../export/cost-utils.ts';
|
|
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';
|
|
5
6
|
import type { RuntimeEventBus } from '@/runtime/index.ts';
|
|
@@ -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,15 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
92
87
|
completeModelSelectionSideEffect,
|
|
93
88
|
} = options;
|
|
94
89
|
|
|
95
|
-
|
|
90
|
+
// W0.9: after any resume seam replays historical messages into `conversation`,
|
|
91
|
+
// the freshly-constructed `orchestrator` still has its zeroed default usage
|
|
92
|
+
// (SDK gap — Orchestrator.usage is never persisted/reseeded). Recompute it
|
|
93
|
+
// from the replayed history so the footer doesn't show Input: 0 post-resume.
|
|
94
|
+
const hydrateSessionUsage = (): void => {
|
|
95
|
+
const { usage, lastInputTokens } = sumConversationUsage(conversation.getMessageSnapshot());
|
|
96
|
+
orchestrator.usage = usage;
|
|
97
|
+
orchestrator.lastInputTokens = lastInputTokens;
|
|
98
|
+
};
|
|
96
99
|
const resumeSession = createResumeSessionHandler({
|
|
97
100
|
runtimeBus,
|
|
98
101
|
runtime,
|
|
@@ -107,6 +110,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
107
110
|
configManager,
|
|
108
111
|
providerRegistry: services.providerRegistry,
|
|
109
112
|
homeDirectory: services.homeDirectory,
|
|
113
|
+
hydrateSessionUsage,
|
|
110
114
|
});
|
|
111
115
|
|
|
112
116
|
const foundationClients = createRuntimeFoundationClients({
|
|
@@ -128,16 +132,22 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
128
132
|
runtimeBus,
|
|
129
133
|
});
|
|
130
134
|
|
|
131
|
-
const openAgentDetailRef: { fn: (agentId: string) => void } = { fn: (_agentId: string) => {} };
|
|
132
|
-
|
|
133
135
|
// WO-139: initial cost-budget alert threshold (USD; 0/unset = disabled).
|
|
134
136
|
// Once the session starts, the real control surface is the CostTrackerPanel
|
|
135
137
|
// itself — the in-panel 'b' key and /cost budget <usd> both call
|
|
136
|
-
// 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.
|
|
137
144
|
const parsedBudgetThreshold = Number(process.env.GOODVIBES_COST_BUDGET_USD);
|
|
138
145
|
const initialCostBudgetThreshold = Number.isFinite(parsedBudgetThreshold) && parsedBudgetThreshold > 0
|
|
139
146
|
? parsedBudgetThreshold
|
|
140
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
|
+
}
|
|
141
151
|
|
|
142
152
|
let commandContextRef: CommandContext | null = null;
|
|
143
153
|
registerBuiltinPanels(services.panelManager, {
|
|
@@ -172,7 +182,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
172
182
|
componentHealthMonitor: services.componentHealthMonitor,
|
|
173
183
|
worktreeRegistry: services.worktreeRegistry,
|
|
174
184
|
sandboxSessionRegistry: services.sandboxSessionRegistry,
|
|
175
|
-
systemMessagesPanel,
|
|
176
185
|
memoryRegistry: services.memoryRegistry,
|
|
177
186
|
uiServices,
|
|
178
187
|
pluginManager: services.pluginManager,
|
|
@@ -180,7 +189,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
180
189
|
hookActivityTracker: services.hookActivityTracker,
|
|
181
190
|
hookWorkbench: services.hookWorkbench,
|
|
182
191
|
mcpRegistry: services.mcpRegistry,
|
|
183
|
-
openAgentDetail: (agentId: string) => openAgentDetailRef.fn(agentId),
|
|
184
192
|
daemonHomeDir: join(services.homeDirectory, '.goodvibes', 'daemon'),
|
|
185
193
|
opsApi,
|
|
186
194
|
planRuntime,
|
|
@@ -193,7 +201,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
193
201
|
|
|
194
202
|
const systemMessageRouter = createSystemMessageRouter(
|
|
195
203
|
conversation,
|
|
196
|
-
systemMessagesPanel,
|
|
197
204
|
(kind) => {
|
|
198
205
|
const ui = getConfigSnapshot(configManager).ui;
|
|
199
206
|
if (kind === 'wrfc') return ui.wrfcMessages;
|
|
@@ -223,6 +230,9 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
223
230
|
mcpRegistry: services.mcpRegistry,
|
|
224
231
|
voiceProviderRegistry: services.voiceProviders,
|
|
225
232
|
voiceService: services.voiceService,
|
|
233
|
+
webSearchService: services.webSearchService,
|
|
234
|
+
mediaProviders: services.mediaProviders,
|
|
235
|
+
artifactStore: services.artifactStore,
|
|
226
236
|
forensicsRegistry,
|
|
227
237
|
policyRuntimeState,
|
|
228
238
|
readModels: uiServices.readModels,
|
|
@@ -230,6 +240,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
230
240
|
remoteRuntime,
|
|
231
241
|
planRuntime,
|
|
232
242
|
fileUndoManager: services.fileUndoManager,
|
|
243
|
+
workspaceCheckpointManager: services.workspaceCheckpointManager,
|
|
233
244
|
memoryRegistry: services.memoryRegistry,
|
|
234
245
|
integrationHelpers: services.integrationHelpers,
|
|
235
246
|
automationManager: services.automationManager,
|
|
@@ -258,6 +269,11 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
258
269
|
sessionMemoryStore: services.sessionMemoryStore,
|
|
259
270
|
sessionLineageTracker: services.sessionLineageTracker,
|
|
260
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(),
|
|
261
277
|
changeTracker: services.sessionChangeTracker,
|
|
262
278
|
planManager: services.planManager,
|
|
263
279
|
adaptivePlanner: services.adaptivePlanner,
|
|
@@ -282,6 +298,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
282
298
|
},
|
|
283
299
|
completeModelSelectionSideEffect,
|
|
284
300
|
componentHealthMonitor: services.componentHealthMonitor,
|
|
301
|
+
hydrateSessionUsage,
|
|
285
302
|
});
|
|
286
303
|
commandContextRef = commandContext;
|
|
287
304
|
|
|
@@ -291,6 +308,16 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
291
308
|
lastGitInfoRef.value = info;
|
|
292
309
|
requestRender();
|
|
293
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
|
+
});
|
|
294
321
|
|
|
295
322
|
const saveHistory = configManager.get('behavior.saveHistory') as boolean;
|
|
296
323
|
const inputHistory = new InputHistory({
|
|
@@ -305,8 +332,5 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
305
332
|
lastGitInfoRef,
|
|
306
333
|
inputHistory,
|
|
307
334
|
systemMessageRouter,
|
|
308
|
-
setOpenAgentDetail: (fn: (agentId: string) => void) => {
|
|
309
|
-
openAgentDetailRef.fn = fn;
|
|
310
|
-
},
|
|
311
335
|
};
|
|
312
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
|
};
|
package/src/runtime/services.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { FocusTracker } from '../core/focus-tracker.ts';
|
|
3
|
+
import { ConfigManager, ServiceRegistry, SubscriptionManager, ToolLLM } from '@pellux/goodvibes-sdk/platform/config';
|
|
3
4
|
import { SecretsManager } from '../config/secrets.ts';
|
|
4
|
-
import { ServiceRegistry } from '@pellux/goodvibes-sdk/platform/config';
|
|
5
|
-
import { SubscriptionManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
6
5
|
import { AutomationDeliveryManager, AutomationManager, AutomationRouteStore } from '@pellux/goodvibes-sdk/platform/automation';
|
|
7
|
-
import { ChannelPluginRegistry, ChannelPolicyManager, RouteBindingManager, SurfaceRegistry } from '@pellux/goodvibes-sdk/platform/channels';
|
|
8
|
-
import { ChannelDeliveryRouter } from '@pellux/goodvibes-sdk/platform/channels';
|
|
6
|
+
import { ChannelDeliveryRouter, ChannelPluginRegistry, ChannelPolicyManager, RouteBindingManager, SurfaceRegistry } from '@pellux/goodvibes-sdk/platform/channels';
|
|
9
7
|
import { ApprovalBroker, GatewayMethodCatalog, SharedSessionBroker } from '@pellux/goodvibes-sdk/platform/control-plane';
|
|
10
8
|
import { WatcherRegistry } from '@pellux/goodvibes-sdk/platform/watchers';
|
|
11
9
|
import { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
|
|
@@ -23,16 +21,10 @@ import {
|
|
|
23
21
|
} from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
24
22
|
import { MediaProviderRegistry, ensureBuiltinMediaProviders } from '@pellux/goodvibes-sdk/platform/media';
|
|
25
23
|
import { MultimodalService } from '@pellux/goodvibes-sdk/platform/multimodal';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import { ArchetypeLoader } from '@pellux/goodvibes-sdk/platform/agents';
|
|
31
|
-
import { ProcessManager } from '@pellux/goodvibes-sdk/platform/tools';
|
|
32
|
-
import { ModeManager } from '@pellux/goodvibes-sdk/platform/state';
|
|
33
|
-
import { FileUndoManager } from '@pellux/goodvibes-sdk/platform/state';
|
|
34
|
-
import { MemoryRegistry } from '@pellux/goodvibes-sdk/platform/state';
|
|
35
|
-
import { MemoryStore } from '@pellux/goodvibes-sdk/platform/state';
|
|
24
|
+
import { AgentMessageBus, AgentOrchestrator, ArchetypeLoader, WrfcController } from '@pellux/goodvibes-sdk/platform/agents';
|
|
25
|
+
import { AgentManager, OverflowHandler, ProcessManager, createWorkflowServices, type WorkflowServices } from '@pellux/goodvibes-sdk/platform/tools';
|
|
26
|
+
import { FileStateCache, FileUndoManager, MemoryEmbeddingProviderRegistry, MemoryRegistry, MemoryStore, ModeManager, ProjectIndex, type CodeIndexStore } from '@pellux/goodvibes-sdk/platform/state';
|
|
27
|
+
import { WorkspaceCheckpointManager } from '@pellux/goodvibes-sdk/platform/workspace';
|
|
36
28
|
import type { RuntimeEventBus } from '@/runtime/index.ts';
|
|
37
29
|
import { createDomainDispatch } from './store/index.ts';
|
|
38
30
|
import type { DomainDispatch, RuntimeStore } from './store/index.ts';
|
|
@@ -41,40 +33,20 @@ import { RemoteRunnerRegistry, RemoteSupervisor } from '@/runtime/index.ts';
|
|
|
41
33
|
import { IntegrationHelperService } from '@/runtime/index.ts';
|
|
42
34
|
import { VoiceProviderRegistry, VoiceService, ensureBuiltinVoiceProviders } from '@pellux/goodvibes-sdk/platform/voice';
|
|
43
35
|
import { WebSearchProviderRegistry, WebSearchService } from '@pellux/goodvibes-sdk/platform/web-search';
|
|
44
|
-
import { MemoryEmbeddingProviderRegistry } from '@pellux/goodvibes-sdk/platform/state';
|
|
45
36
|
import { PanelManager } from '../panels/panel-manager.ts';
|
|
46
37
|
import { HookActivityTracker } from '@pellux/goodvibes-sdk/platform/hooks';
|
|
47
38
|
import { HookDispatcher, createHookWorkbench, type HookWorkbench } from '@pellux/goodvibes-sdk/platform/hooks';
|
|
48
39
|
import { PluginManager } from '@pellux/goodvibes-sdk/platform/plugins';
|
|
49
40
|
import { BookmarkManager } from '@pellux/goodvibes-sdk/platform/bookmarks';
|
|
50
41
|
import { ProfileManager } from '@pellux/goodvibes-sdk/platform/profiles';
|
|
51
|
-
import { SessionManager } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
52
|
-
import {
|
|
53
|
-
import { ApiTokenAuditor } from '@pellux/goodvibes-sdk/platform/security';
|
|
54
|
-
import { UserAuthManager } from '@pellux/goodvibes-sdk/platform/security';
|
|
42
|
+
import { SessionManager, CrossSessionTaskRegistry, SessionChangeTracker } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
43
|
+
import { ApiTokenAuditor, UserAuthManager } from '@pellux/goodvibes-sdk/platform/security';
|
|
55
44
|
import { WebhookNotifier } from '@pellux/goodvibes-sdk/platform/integrations';
|
|
56
45
|
import { McpRegistry } from '@pellux/goodvibes-sdk/platform/mcp';
|
|
57
|
-
import {
|
|
58
|
-
import { ProviderOptimizer } from '@pellux/goodvibes-sdk/platform/providers';
|
|
59
|
-
import { ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
60
|
-
import type { ModelDefinition } from '@pellux/goodvibes-sdk/platform/providers';
|
|
61
|
-
import { ProviderCapabilityRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
62
|
-
import { CacheHitTracker } from '@pellux/goodvibes-sdk/platform/providers';
|
|
63
|
-
import { FavoritesStore } from '@pellux/goodvibes-sdk/platform/providers';
|
|
64
|
-
import { BenchmarkStore } from '@pellux/goodvibes-sdk/platform/providers';
|
|
65
|
-
import { ModelLimitsService } from '@pellux/goodvibes-sdk/platform/providers';
|
|
66
|
-
import { inferFallbackContextWindow } from '@pellux/goodvibes-sdk/platform/providers';
|
|
46
|
+
import { BenchmarkStore, CacheHitTracker, FavoritesStore, inferFallbackContextWindow, type ModelDefinition, ModelLimitsService, ProviderCapabilityRegistry, ProviderOptimizer, ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
67
47
|
import { KeybindingsManager } from '../input/keybindings.ts';
|
|
68
|
-
import { SessionMemoryStore } from '@pellux/goodvibes-sdk/platform/core';
|
|
69
|
-
import { SessionLineageTracker } from '@pellux/goodvibes-sdk/platform/core';
|
|
70
|
-
import { SessionChangeTracker } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
71
|
-
import { ExecutionPlanManager } from '@pellux/goodvibes-sdk/platform/core';
|
|
72
|
-
import { AdaptivePlanner } from '@pellux/goodvibes-sdk/platform/core';
|
|
73
|
-
import { FileStateCache } from '@pellux/goodvibes-sdk/platform/state';
|
|
74
|
-
import { ProjectIndex } from '@pellux/goodvibes-sdk/platform/state';
|
|
48
|
+
import { AdaptivePlanner, DeterministicReplayEngine, ExecutionPlanManager, SessionLineageTracker, SessionMemoryStore } from '@pellux/goodvibes-sdk/platform/core';
|
|
75
49
|
import { IdempotencyStore } from '@/runtime/index.ts';
|
|
76
|
-
import { OverflowHandler } from '@pellux/goodvibes-sdk/platform/tools';
|
|
77
|
-
import { ToolLLM } from '@pellux/goodvibes-sdk/platform/config';
|
|
78
50
|
import { ComponentHealthMonitor } from '@/runtime/index.ts';
|
|
79
51
|
import { WorktreeRegistry } from '@/runtime/index.ts';
|
|
80
52
|
import { SandboxSessionRegistry } from '@/runtime/index.ts';
|
|
@@ -83,10 +55,10 @@ import { isFeatureFlagEnabled } from './surface-feature-flags.ts';
|
|
|
83
55
|
import type { FeatureFlagManager } from '@/runtime/index.ts';
|
|
84
56
|
import { createFeatureFlagManager } from '@/runtime/index.ts';
|
|
85
57
|
import { PolicyRuntimeState } from '@/runtime/index.ts';
|
|
86
|
-
import {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
} from '
|
|
58
|
+
import { createProcessRegistry, type ProcessRegistry } from '@pellux/goodvibes-sdk/platform/runtime/fleet';
|
|
59
|
+
import { calcSessionCost, isModelPriced } from '../export/cost-utils.ts';
|
|
60
|
+
import { createWorkstreamServices, type OrchestrationEngine, type WorkstreamCommandService } from './workstream-services.ts';
|
|
61
|
+
import { codeIndexDbPath, createCodeIndexServices } from './code-index-services.ts';
|
|
90
62
|
import { WorkPlanStore } from '../work-plans/work-plan-store.ts';
|
|
91
63
|
import {
|
|
92
64
|
registerDaemonHandlers,
|
|
@@ -221,6 +193,8 @@ export interface RuntimeServices {
|
|
|
221
193
|
readonly worktreeRegistry: WorktreeRegistry;
|
|
222
194
|
readonly sandboxSessionRegistry: SandboxSessionRegistry;
|
|
223
195
|
readonly webhookNotifier: WebhookNotifier;
|
|
196
|
+
/** Terminal focus tracker (W2.3) — fed by input/handler-feed.ts, read by the alert notifiers in core/. */
|
|
197
|
+
readonly focusTracker: FocusTracker;
|
|
224
198
|
readonly replayEngine: DeterministicReplayEngine;
|
|
225
199
|
readonly providerOptimizer: ProviderOptimizer;
|
|
226
200
|
readonly providerCapabilityRegistry: ProviderCapabilityRegistry;
|
|
@@ -248,8 +222,16 @@ export interface RuntimeServices {
|
|
|
248
222
|
readonly agentOrchestrator: AgentOrchestrator;
|
|
249
223
|
readonly wrfcController: WrfcController;
|
|
250
224
|
readonly processManager: ProcessManager;
|
|
225
|
+
/** Wave 4 (wo703): the phase/work-item orchestration engine — see runtime/workstream-services.ts. */
|
|
226
|
+
readonly orchestrationEngine: OrchestrationEngine;
|
|
227
|
+
readonly workstreamCommands: WorkstreamCommandService;
|
|
228
|
+
/** Wave 5 (wo804): the repo source-tree code index — see runtime/code-index-services.ts. */
|
|
229
|
+
readonly codeIndexStore: CodeIndexStore;
|
|
230
|
+
/** W2.1/W2.2: unified live process registry (agents, WRFC chains, workflows, watchers, background processes) backing the Fleet panel. */
|
|
231
|
+
readonly processRegistry: ProcessRegistry;
|
|
251
232
|
readonly modeManager: ModeManager;
|
|
252
233
|
readonly fileUndoManager: FileUndoManager;
|
|
234
|
+
readonly workspaceCheckpointManager: WorkspaceCheckpointManager;
|
|
253
235
|
readonly integrationHelpers: IntegrationHelperService;
|
|
254
236
|
/**
|
|
255
237
|
* Re-root path-bound stores (MemoryStore, ProjectIndex) to a new working directory.
|
|
@@ -272,6 +254,9 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
272
254
|
const runtimeDispatch = createDomainDispatch(options.runtimeStore);
|
|
273
255
|
const gatewayMethods = new GatewayMethodCatalog();
|
|
274
256
|
const panelManager = new PanelManager();
|
|
257
|
+
// W6.1 (the purge): MIGRATE-TO-MODAL surface + redirect registration moved to
|
|
258
|
+
// registerBuiltinPanels (builtin-panels.ts), where the panels' resolved deps
|
|
259
|
+
// are available for the surfaces to close over.
|
|
275
260
|
const keybindingsManager = new KeybindingsManager({
|
|
276
261
|
configPath: shellPaths.resolveUserPath('tui', 'keybindings.json'),
|
|
277
262
|
});
|
|
@@ -352,6 +337,10 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
352
337
|
executor: agentOrchestrator,
|
|
353
338
|
configManager,
|
|
354
339
|
});
|
|
340
|
+
agentOrchestrator.setConversationSink({ // Wave-3 Part C6 bridge (mirrors the SDK's own createRuntimeServices)
|
|
341
|
+
register: (agentId, source) => agentManager.registerConversationSource(agentId, source),
|
|
342
|
+
release: (agentId) => agentManager.releaseConversationSource(agentId),
|
|
343
|
+
});
|
|
355
344
|
agentManager.setRuntimeBus(options.runtimeBus);
|
|
356
345
|
const wrfcController = new WrfcController(options.runtimeBus, agentMessageBus, {
|
|
357
346
|
agentManager,
|
|
@@ -580,6 +569,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
580
569
|
const componentHealthMonitor = new ComponentHealthMonitor();
|
|
581
570
|
const worktreeRegistry = new WorktreeRegistry(workingDirectory);
|
|
582
571
|
const webhookNotifier = new WebhookNotifier();
|
|
572
|
+
const focusTracker = new FocusTracker();
|
|
583
573
|
const replayEngine = new DeterministicReplayEngine(workingDirectory);
|
|
584
574
|
const providerOptimizer = new ProviderOptimizer(
|
|
585
575
|
providerRegistry,
|
|
@@ -603,8 +593,57 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
603
593
|
artifactStore,
|
|
604
594
|
});
|
|
605
595
|
const processManager = new ProcessManager();
|
|
596
|
+
// Wave 4 (wo703): the phase/work-item orchestration engine, constructed
|
|
597
|
+
// before the process registry so its fleet nodes (workstream/phase/
|
|
598
|
+
// work-item) can be folded in below via the registry's optional
|
|
599
|
+
// orchestrationEngine dep.
|
|
600
|
+
const { orchestrationEngine, workstreamCommands } = createWorkstreamServices({
|
|
601
|
+
agentManager, configManager, adaptivePlanner, runtimeBus: options.runtimeBus, projectRoot: workingDirectory,
|
|
602
|
+
});
|
|
603
|
+
// Wave 5 (wo804): repo source-tree code index, sharing memoryEmbeddingRegistry
|
|
604
|
+
// with MemoryStore above. Auto-build is config-gated (default off) — see
|
|
605
|
+
// code-index-services.ts's header doc.
|
|
606
|
+
const { codeIndexStore } = createCodeIndexServices({ workingDirectory, configManager, memoryEmbeddingRegistry });
|
|
607
|
+
// W2.1/W2.2: one shared process registry aggregating the managers above —
|
|
608
|
+
// the Fleet panel (panels/fleet-read-model.ts) is its first consumer.
|
|
609
|
+
// Constructed once here (not per-consumer) so the coalesced tick and the
|
|
610
|
+
// agent-activity side-table are shared, not duplicated.
|
|
611
|
+
const processRegistry = createProcessRegistry({
|
|
612
|
+
agentManager,
|
|
613
|
+
wrfcController,
|
|
614
|
+
orchestrationEngine, // Wave 4 (wo703): folds workstream/phase/work-item nodes into the fleet
|
|
615
|
+
codeIndexService: codeIndexStore, // Wave 5 (wo804): folds a single 'code-index' node into the fleet
|
|
616
|
+
processManager,
|
|
617
|
+
watcherRegistry,
|
|
618
|
+
workflow,
|
|
619
|
+
approvalBroker,
|
|
620
|
+
sessionBroker,
|
|
621
|
+
messageBus: agentMessageBus, // Wave-3: backs steer()/`steerable` (wo612 builds the composer UI on top)
|
|
622
|
+
automationManager, // Wave 6 (wo-F item d4): folds /schedule AutomationJobs into the fleet as 'schedule' nodes
|
|
623
|
+
runtimeBus: options.runtimeBus,
|
|
624
|
+
// Honest pricing: never fabricate a cost for an unrecognized model.
|
|
625
|
+
priceUsage: (model, usage) => {
|
|
626
|
+
const modelId = model ?? 'unknown';
|
|
627
|
+
if (!isModelPriced(modelId)) return null;
|
|
628
|
+
return calcSessionCost(usage.inputTokens, usage.outputTokens, usage.cacheReadTokens, usage.cacheWriteTokens, modelId);
|
|
629
|
+
},
|
|
630
|
+
});
|
|
606
631
|
const modeManager = new ModeManager();
|
|
607
632
|
const fileUndoManager = new FileUndoManager();
|
|
633
|
+
const workspaceCheckpointManager = new WorkspaceCheckpointManager({
|
|
634
|
+
workspaceRoot: workingDirectory,
|
|
635
|
+
runtimeBus: options.runtimeBus,
|
|
636
|
+
});
|
|
637
|
+
// Fire-and-forget: subscriptions go live immediately if init() succeeds.
|
|
638
|
+
// If it rejects, WorkspaceCheckpointManager caches that rejection on
|
|
639
|
+
// `initPromise` and never clears it, so every later call (create/list/
|
|
640
|
+
// diff/restore — each awaits init() first) re-throws the same error
|
|
641
|
+
// forever: checkpointing becomes entirely unavailable for the rest of the
|
|
642
|
+
// session, not "degraded to manual-only". The `.catch(() => {})` here only
|
|
643
|
+
// exists to prevent an unhandled rejection at startup; the checkpoint
|
|
644
|
+
// commands (checkpoint-runtime.ts) are what actually catch and report the
|
|
645
|
+
// failure to the user, on first use.
|
|
646
|
+
void workspaceCheckpointManager.init().catch(() => {});
|
|
608
647
|
const integrationHelpers = new IntegrationHelperService({
|
|
609
648
|
workingDirectory,
|
|
610
649
|
homeDirectory,
|
|
@@ -709,6 +748,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
709
748
|
worktreeRegistry,
|
|
710
749
|
sandboxSessionRegistry,
|
|
711
750
|
webhookNotifier,
|
|
751
|
+
focusTracker,
|
|
712
752
|
replayEngine,
|
|
713
753
|
providerOptimizer,
|
|
714
754
|
providerCapabilityRegistry,
|
|
@@ -736,12 +776,20 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
736
776
|
agentOrchestrator,
|
|
737
777
|
wrfcController,
|
|
738
778
|
processManager,
|
|
779
|
+
orchestrationEngine,
|
|
780
|
+
workstreamCommands,
|
|
781
|
+
codeIndexStore,
|
|
782
|
+
processRegistry,
|
|
739
783
|
modeManager,
|
|
740
784
|
fileUndoManager,
|
|
785
|
+
workspaceCheckpointManager,
|
|
741
786
|
integrationHelpers,
|
|
742
787
|
async rerootStores(newWorkingDir: string): Promise<void> {
|
|
743
788
|
const newMemoryDbPath = join(newWorkingDir, '.goodvibes', 'tui', 'memory.sqlite');
|
|
744
789
|
await memoryStore.reroot(newMemoryDbPath);
|
|
790
|
+
// Wave 5 (wo804) risk #7: the code index must follow memory to the new
|
|
791
|
+
// tree, or it keeps pointing at the old working directory.
|
|
792
|
+
await codeIndexStore.reroot(newWorkingDir, codeIndexDbPath(newWorkingDir));
|
|
745
793
|
await projectIndex.reroot(newWorkingDir);
|
|
746
794
|
},
|
|
747
795
|
};
|