@pellux/goodvibes-tui 1.1.0 → 1.9.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 +28 -18
- package/docs/foundation-artifacts/operator-contract.json +4045 -1763
- package/package.json +2 -2
- package/src/audio/spoken-turn-controller.ts +12 -2
- package/src/audio/spoken-turn-wiring.ts +2 -1
- package/src/cli/help.ts +8 -1
- package/src/cli/service-posture.ts +2 -1
- package/src/cli/status.ts +2 -1
- package/src/cli/surface-command.ts +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/composer-state.ts +11 -3
- package/src/core/conversation-line-cache.ts +27 -3
- package/src/core/conversation-rendering.ts +90 -14
- 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/stream-event-wiring.ts +20 -1
- package/src/core/system-message-noise.ts +87 -0
- package/src/core/system-message-router.ts +104 -51
- package/src/core/turn-cancellation.ts +25 -0
- package/src/core/turn-event-wiring.ts +72 -3
- package/src/daemon/cli.ts +29 -2
- package/src/daemon/handlers/register.ts +8 -1
- package/src/daemon/service-commands.ts +329 -0
- package/src/export/cost-utils.ts +36 -0
- package/src/input/autocomplete.ts +27 -1
- package/src/input/command-registry.ts +84 -5
- package/src/input/commands/checkpoint-runtime.ts +280 -0
- package/src/input/commands/codebase-runtime.ts +232 -0
- package/src/input/commands/config.ts +43 -3
- package/src/input/commands/eval.ts +1 -1
- package/src/input/commands/health-runtime.ts +10 -2
- 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 +73 -35
- package/src/input/commands/operator-panel-runtime.ts +71 -31
- package/src/input/commands/planning-runtime.ts +116 -4
- 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 +26 -6
- package/src/input/commands/recall-review.ts +35 -0
- package/src/input/commands/remote-runtime-setup.ts +5 -3
- 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 +20 -9
- package/src/input/commands/session-workflow.ts +16 -1
- package/src/input/commands/settings-sync-runtime.ts +16 -4
- package/src/input/commands/shell-core.ts +25 -8
- 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 +488 -0
- package/src/input/commands.ts +12 -0
- package/src/input/config-modal-types.ts +175 -0
- package/src/input/config-modal.ts +592 -0
- package/src/input/feed-context-factory.ts +10 -8
- package/src/input/handler-command-route.ts +37 -20
- package/src/input/handler-content-actions.ts +17 -2
- package/src/input/handler-feed-routes.ts +74 -114
- package/src/input/handler-feed.ts +79 -27
- package/src/input/handler-interactions.ts +1 -3
- package/src/input/handler-modal-routes.ts +136 -6
- package/src/input/handler-modal-stack.ts +14 -7
- package/src/input/handler-modal-token-routes.ts +16 -49
- package/src/input/handler-onboarding-daemon-adopt.ts +149 -0
- package/src/input/handler-onboarding.ts +71 -59
- package/src/input/handler-picker-routes.ts +26 -102
- package/src/input/handler-shortcuts.ts +74 -14
- package/src/input/handler-types.ts +2 -6
- package/src/input/handler-ui-state.ts +10 -22
- package/src/input/handler.ts +12 -29
- package/src/input/keybindings.ts +23 -8
- package/src/input/model-picker-types.ts +24 -6
- package/src/input/model-picker.ts +77 -2
- package/src/input/onboarding/onboarding-runtime-status.ts +10 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +8 -1
- package/src/input/onboarding/onboarding-wizard-constants.ts +4 -1
- package/src/input/onboarding/onboarding-wizard-network-adopt.ts +136 -0
- package/src/input/onboarding/onboarding-wizard-steps.ts +9 -6
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/panel-integration-actions.ts +9 -170
- package/src/input/panel-mouse-geometry.ts +97 -0
- package/src/input/panel-paste-flood-guard.ts +86 -0
- package/src/input/selection-modal.ts +11 -0
- package/src/input/session-picker-modal.ts +44 -4
- package/src/input/settings-modal-data.ts +146 -2
- package/src/input/settings-modal-mutations.ts +6 -4
- package/src/input/settings-modal-types.ts +4 -2
- package/src/main.ts +49 -51
- 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 +18 -46
- 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-deep-link.ts +31 -0
- package/src/panels/fleet-panel-format.ts +62 -0
- package/src/panels/fleet-panel-worktree-detail.ts +48 -0
- package/src/panels/fleet-panel.ts +758 -0
- package/src/panels/fleet-read-model.ts +520 -0
- package/src/panels/fleet-steer.ts +125 -0
- package/src/panels/fleet-stop.ts +153 -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 +166 -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 +42 -0
- package/src/panels/modals/pairing-modal.ts +163 -0
- package/src/panels/modals/planning-modal.ts +304 -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 +177 -0
- package/src/panels/panel-confirm-overlay.ts +72 -0
- package/src/panels/panel-manager.ts +123 -9
- package/src/panels/polish-core.ts +38 -25
- package/src/panels/project-planning-answer-actions.ts +8 -11
- package/src/panels/skills-panel.ts +7 -51
- package/src/panels/types.ts +37 -0
- package/src/permissions/hunk-selection.ts +179 -0
- package/src/permissions/prompt.ts +216 -13
- package/src/renderer/autocomplete-overlay.ts +28 -2
- 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/compositor.ts +2 -3
- package/src/renderer/config-modal.ts +95 -0
- package/src/renderer/conversation-overlays.ts +10 -17
- package/src/renderer/fleet-tab-strip.ts +56 -0
- package/src/renderer/footer-tips.ts +15 -3
- package/src/renderer/fullscreen-primitives.ts +32 -22
- package/src/renderer/git-status.ts +43 -1
- package/src/renderer/help-overlay.ts +2 -2
- package/src/renderer/layout.ts +0 -4
- package/src/renderer/markdown.ts +7 -3
- package/src/renderer/modal-factory.ts +25 -20
- package/src/renderer/model-workspace.ts +62 -4
- package/src/renderer/overlay-box.ts +21 -17
- package/src/renderer/panel-workspace-bar.ts +8 -2
- package/src/renderer/process-indicator.ts +14 -3
- package/src/renderer/selection-modal-overlay.ts +6 -1
- package/src/renderer/session-picker-modal.ts +196 -3
- package/src/renderer/settings-modal-helpers.ts +2 -0
- package/src/renderer/settings-modal.ts +7 -0
- package/src/renderer/shell-surface.ts +8 -1
- package/src/renderer/status-glyphs.ts +14 -15
- package/src/renderer/system-message.ts +15 -3
- package/src/renderer/terminal-bg-probe.ts +339 -0
- package/src/renderer/terminal-escapes.ts +20 -0
- package/src/renderer/theme-mode-config.ts +67 -0
- package/src/renderer/theme.ts +91 -1
- package/src/renderer/thinking.ts +11 -3
- package/src/renderer/tool-call.ts +15 -9
- package/src/renderer/tool-result-summary.ts +148 -0
- package/src/renderer/turn-injection.ts +133 -0
- package/src/renderer/ui-factory.ts +154 -85
- package/src/renderer/ui-primitives.ts +30 -129
- package/src/runtime/bootstrap-command-context.ts +27 -1
- package/src/runtime/bootstrap-command-parts.ts +41 -10
- package/src/runtime/bootstrap-core.ts +47 -15
- package/src/runtime/bootstrap-hook-bridge.ts +7 -0
- package/src/runtime/bootstrap-shell.ts +48 -17
- package/src/runtime/bootstrap.ts +129 -22
- package/src/runtime/code-index-services.ts +135 -0
- package/src/runtime/legacy-daemon-migration.ts +516 -0
- package/src/runtime/memory-fold.ts +26 -0
- package/src/runtime/onboarding/derivation.ts +7 -2
- package/src/runtime/onboarding/snapshot.ts +27 -1
- package/src/runtime/onboarding/types.ts +31 -1
- package/src/runtime/operator-token-cleanup.ts +82 -1
- package/src/runtime/orchestrator-core-services.ts +59 -0
- package/src/runtime/process-lifecycle.ts +3 -1
- package/src/runtime/resume-notice.ts +209 -0
- package/src/runtime/services.ts +98 -46
- package/src/runtime/session-inbound-inputs.ts +252 -0
- package/src/runtime/session-spine-transport.ts +64 -0
- package/src/runtime/terminal-output-guard.ts +15 -8
- package/src/runtime/ui-services.ts +27 -3
- package/src/runtime/workstream-services.ts +327 -0
- package/src/runtime/wrfc-persistence.ts +124 -17
- package/src/shell/blocking-input.ts +68 -4
- package/src/shell/recovery-input-helpers.ts +170 -1
- package/src/shell/ui-openers.ts +171 -26
- package/src/utils/format-duration.ts +8 -18
- package/src/utils/splash-lines.ts +1 -1
- package/src/utils/terminal-width.ts +52 -0
- 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,11 @@ 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
|
+
codeIndexReindexScheduler?: import('@pellux/goodvibes-sdk/platform/state').CodeIndexReindexScheduler;
|
|
127
|
+
isPassiveCodeInjectionFlagEnabled?: () => boolean;
|
|
128
|
+
getMainSessionTurnInjections?: () => readonly import('../renderer/turn-injection.ts').TurnInjectionEntry[];
|
|
118
129
|
};
|
|
119
130
|
|
|
120
131
|
export function createBootstrapCommandContext(
|
|
@@ -132,6 +143,9 @@ export function createBootstrapCommandContext(
|
|
|
132
143
|
mcpRegistry,
|
|
133
144
|
voiceProviderRegistry,
|
|
134
145
|
voiceService,
|
|
146
|
+
webSearchService,
|
|
147
|
+
mediaProviders,
|
|
148
|
+
artifactStore,
|
|
135
149
|
forensicsRegistry,
|
|
136
150
|
policyRuntimeState,
|
|
137
151
|
readModels,
|
|
@@ -139,6 +153,7 @@ export function createBootstrapCommandContext(
|
|
|
139
153
|
remoteRuntime,
|
|
140
154
|
planRuntime,
|
|
141
155
|
fileUndoManager,
|
|
156
|
+
workspaceCheckpointManager,
|
|
142
157
|
memoryRegistry,
|
|
143
158
|
integrationHelpers,
|
|
144
159
|
automationManager,
|
|
@@ -169,6 +184,11 @@ export function createBootstrapCommandContext(
|
|
|
169
184
|
wrfcController,
|
|
170
185
|
changeTracker,
|
|
171
186
|
hydrateSessionUsage,
|
|
187
|
+
workstreamEngine,
|
|
188
|
+
codeIndexStore,
|
|
189
|
+
codeIndexReindexScheduler,
|
|
190
|
+
isPassiveCodeInjectionFlagEnabled,
|
|
191
|
+
getMainSessionTurnInjections,
|
|
172
192
|
planManager,
|
|
173
193
|
adaptivePlanner,
|
|
174
194
|
sessionOrchestration,
|
|
@@ -226,6 +246,11 @@ export function createBootstrapCommandContext(
|
|
|
226
246
|
wrfcController,
|
|
227
247
|
changeTracker,
|
|
228
248
|
hydrateSessionUsage,
|
|
249
|
+
workstreamEngine,
|
|
250
|
+
codeIndexStore,
|
|
251
|
+
codeIndexReindexScheduler,
|
|
252
|
+
isPassiveCodeInjectionFlagEnabled,
|
|
253
|
+
getMainSessionTurnInjections,
|
|
229
254
|
});
|
|
230
255
|
const provider = createBootstrapCommandProviderSection({
|
|
231
256
|
providerRegistry,
|
|
@@ -236,6 +261,7 @@ export function createBootstrapCommandContext(
|
|
|
236
261
|
const workspace = createBootstrapCommandWorkspaceSection({
|
|
237
262
|
keybindingsManager,
|
|
238
263
|
fileUndoManager,
|
|
264
|
+
workspaceCheckpointManager,
|
|
239
265
|
panelManager,
|
|
240
266
|
profileManager,
|
|
241
267
|
bookmarkManager,
|
|
@@ -243,7 +269,7 @@ export function createBootstrapCommandContext(
|
|
|
243
269
|
projectPlanningProjectId,
|
|
244
270
|
workPlanStore,
|
|
245
271
|
}, shellServices);
|
|
246
|
-
const platform = createBootstrapCommandPlatformSection({ configManager, voiceProviderRegistry, voiceService }, shellServices);
|
|
272
|
+
const platform = createBootstrapCommandPlatformSection({ configManager, voiceProviderRegistry, voiceService, webSearchService, mediaProviders, artifactStore }, shellServices);
|
|
247
273
|
const extensions = createBootstrapCommandExtensionsSection({
|
|
248
274
|
toolRegistry,
|
|
249
275
|
mcpRegistry,
|
|
@@ -5,7 +5,7 @@ import type { ConversationManager } from '../core/conversation';
|
|
|
5
5
|
import type { KnowledgeApi } from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
6
6
|
import type { HookApi } from '@pellux/goodvibes-sdk/platform/hooks';
|
|
7
7
|
import type { McpApi } from '@pellux/goodvibes-sdk/platform/mcp';
|
|
8
|
-
import type { PanelManager } from '../panels/panel-manager.ts';
|
|
8
|
+
import type { PanelManager, PanelDeepLinkTarget } from '../panels/panel-manager.ts';
|
|
9
9
|
import type { ProviderApi } from '@pellux/goodvibes-sdk/platform/providers';
|
|
10
10
|
import type { OpsApi } from '@/runtime/index.ts';
|
|
11
11
|
import type { MutableRuntimeState } from '@/runtime/index.ts';
|
|
@@ -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,11 @@ 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 codeIndexReindexScheduler?: import('@pellux/goodvibes-sdk/platform/state').CodeIndexReindexScheduler;
|
|
122
|
+
readonly isPassiveCodeInjectionFlagEnabled?: () => boolean;
|
|
123
|
+
readonly getMainSessionTurnInjections?: () => readonly import('../renderer/turn-injection.ts').TurnInjectionEntry[];
|
|
113
124
|
readonly agentManager?: ShellAgentManagerService;
|
|
114
125
|
readonly modeManager?: ShellModeManagerService;
|
|
115
126
|
readonly automationManager?: ShellAutomationManagerRuntimeService;
|
|
@@ -181,9 +192,16 @@ export function createBootstrapCommandActions(
|
|
|
181
192
|
localUserAuthManager,
|
|
182
193
|
} = options;
|
|
183
194
|
|
|
184
|
-
const showPanel = (panelId: string, pane?: 'top' | 'bottom') => {
|
|
185
|
-
|
|
186
|
-
panelManager.
|
|
195
|
+
const showPanel = (panelId: string, pane?: 'top' | 'bottom', target?: PanelDeepLinkTarget) => {
|
|
196
|
+
// W6.1 (the purge): a MIGRATE-TO-MODAL id resolves to a modal, not a panel.
|
|
197
|
+
// panelManager.open() fires the injected openModal callback and returns a
|
|
198
|
+
// no-op sentinel — so skip panelManager.show() (which would reveal an empty
|
|
199
|
+
// panel workspace behind the modal) when this id redirects. Keeps every
|
|
200
|
+
// showPanel-based front-door (openHooksPanel/openSecurityPanel/… and the
|
|
201
|
+
// migrated command runtimes) opening the modal cleanly.
|
|
202
|
+
const redirected = panelManager.getModalRedirect(panelId) !== undefined;
|
|
203
|
+
panelManager.open(panelId, pane, target);
|
|
204
|
+
if (!redirected) panelManager.show();
|
|
187
205
|
requestRender();
|
|
188
206
|
};
|
|
189
207
|
|
|
@@ -279,11 +297,15 @@ export function createBootstrapCommandActions(
|
|
|
279
297
|
openMemoryPanel: () => {
|
|
280
298
|
showPanel('memory');
|
|
281
299
|
},
|
|
300
|
+
// W6.1: remote/subscription migrated to config-modal surfaces. open() hits
|
|
301
|
+
// the modal redirect and invokes the openModal callback — do NOT go through
|
|
302
|
+
// showPanel here, which would additionally reveal + focus an (empty) panel
|
|
303
|
+
// workspace behind the fullscreen modal.
|
|
282
304
|
openRemotePanel: () => {
|
|
283
|
-
|
|
305
|
+
panelManager.open('remote');
|
|
284
306
|
},
|
|
285
307
|
openSubscriptionPanel: () => {
|
|
286
|
-
|
|
308
|
+
panelManager.open('subscription');
|
|
287
309
|
},
|
|
288
310
|
openLocalAuthMaskedEntry: (kind, username) => {
|
|
289
311
|
showPanel('local-auth');
|
|
@@ -301,7 +323,7 @@ export function createBootstrapCommandActions(
|
|
|
301
323
|
export function createBootstrapCommandSessionSection(
|
|
302
324
|
options: Pick<
|
|
303
325
|
BootstrapCommandSectionOptions,
|
|
304
|
-
'conversation' | 'runtime' | 'sessionManager' | 'sessionMemoryStore' | 'sessionLineageTracker' | 'wrfcController' | 'changeTracker' | 'hydrateSessionUsage'
|
|
326
|
+
'conversation' | 'runtime' | 'sessionManager' | 'sessionMemoryStore' | 'sessionLineageTracker' | 'wrfcController' | 'changeTracker' | 'hydrateSessionUsage' | 'workstreamEngine' | 'codeIndexStore' | 'codeIndexReindexScheduler' | 'isPassiveCodeInjectionFlagEnabled' | 'getMainSessionTurnInjections'
|
|
305
327
|
>,
|
|
306
328
|
): BootstrapCommandSessionSection {
|
|
307
329
|
return {
|
|
@@ -313,6 +335,11 @@ export function createBootstrapCommandSessionSection(
|
|
|
313
335
|
wrfcController: options.wrfcController,
|
|
314
336
|
changeTracker: options.changeTracker,
|
|
315
337
|
hydrateSessionUsage: options.hydrateSessionUsage,
|
|
338
|
+
workstreamEngine: options.workstreamEngine,
|
|
339
|
+
codeIndexStore: options.codeIndexStore,
|
|
340
|
+
codeIndexReindexScheduler: options.codeIndexReindexScheduler,
|
|
341
|
+
isPassiveCodeInjectionFlagEnabled: options.isPassiveCodeInjectionFlagEnabled,
|
|
342
|
+
getMainSessionTurnInjections: options.getMainSessionTurnInjections,
|
|
316
343
|
};
|
|
317
344
|
}
|
|
318
345
|
|
|
@@ -333,7 +360,7 @@ export function createBootstrapCommandProviderSection(
|
|
|
333
360
|
export function createBootstrapCommandWorkspaceSection(
|
|
334
361
|
options: Pick<
|
|
335
362
|
BootstrapCommandSectionOptions,
|
|
336
|
-
'keybindingsManager' | 'fileUndoManager' | 'panelManager' | 'profileManager' | 'bookmarkManager'
|
|
363
|
+
'keybindingsManager' | 'fileUndoManager' | 'workspaceCheckpointManager' | 'panelManager' | 'profileManager' | 'bookmarkManager'
|
|
337
364
|
| 'projectPlanningService' | 'projectPlanningProjectId' | 'workPlanStore'
|
|
338
365
|
>,
|
|
339
366
|
shellServices: BootstrapCommandShellServices,
|
|
@@ -341,6 +368,7 @@ export function createBootstrapCommandWorkspaceSection(
|
|
|
341
368
|
return {
|
|
342
369
|
keybindingsManager: options.keybindingsManager,
|
|
343
370
|
fileUndoManager: options.fileUndoManager,
|
|
371
|
+
workspaceCheckpointManager: options.workspaceCheckpointManager,
|
|
344
372
|
panelManager: options.panelManager,
|
|
345
373
|
profileManager: options.profileManager,
|
|
346
374
|
bookmarkManager: options.bookmarkManager,
|
|
@@ -354,7 +382,7 @@ export function createBootstrapCommandWorkspaceSection(
|
|
|
354
382
|
export function createBootstrapCommandPlatformSection(
|
|
355
383
|
options: Pick<
|
|
356
384
|
BootstrapCommandSectionOptions,
|
|
357
|
-
'configManager' | 'voiceProviderRegistry' | 'voiceService'
|
|
385
|
+
'configManager' | 'voiceProviderRegistry' | 'voiceService' | 'webSearchService' | 'mediaProviders' | 'artifactStore'
|
|
358
386
|
>,
|
|
359
387
|
shellServices: BootstrapCommandShellServices,
|
|
360
388
|
): BootstrapCommandPlatformSection {
|
|
@@ -363,6 +391,9 @@ export function createBootstrapCommandPlatformSection(
|
|
|
363
391
|
configManager: options.configManager,
|
|
364
392
|
voiceProviderRegistry: options.voiceProviderRegistry,
|
|
365
393
|
voiceService: options.voiceService,
|
|
394
|
+
webSearchService: options.webSearchService,
|
|
395
|
+
mediaProviders: options.mediaProviders,
|
|
396
|
+
artifactStore: options.artifactStore,
|
|
366
397
|
...shellServices.platform,
|
|
367
398
|
};
|
|
368
399
|
}
|
|
@@ -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,9 @@ 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';
|
|
36
|
+
import { SessionSpineClient, SessionUnionCache, TUI_SPINE_PARTICIPANT } from '@pellux/goodvibes-sdk/platform/runtime/session-spine';
|
|
37
|
+
import { SessionInboundInputPoller, createBootstrapInboundInputPoller } from './session-inbound-inputs.ts';
|
|
37
38
|
|
|
38
39
|
// ---------------------------------------------------------------------------
|
|
39
40
|
// Pre-router buffer
|
|
@@ -115,6 +116,12 @@ export interface BootstrapCoreState {
|
|
|
115
116
|
readonly requestRender: () => void;
|
|
116
117
|
readonly setRenderRequest: (fn: () => void) => void;
|
|
117
118
|
readonly runtimeSessionIdRef: { value: string };
|
|
119
|
+
/** Cross-surface identity mirror; permanently dormant for embedded/local-only (docs/decisions/2026-07-06-session-spine-mode-branch-is-permanent.md), activated by bootstrap.ts only for an adopted 'external' daemon. */
|
|
120
|
+
readonly sessionSpine: SessionSpineClient;
|
|
121
|
+
/** D3: inbound steer/follow-up delivery; dormant until bootstrap.ts activates it. */
|
|
122
|
+
readonly sessionInboundInputs: SessionInboundInputPoller;
|
|
123
|
+
/** Cache-backed read facade; bootstrap.ts drives its mode (embedded/external/local-only) from the same HostServiceMode as the spine above. */
|
|
124
|
+
readonly sessionUnionCache: SessionUnionCache;
|
|
118
125
|
/**
|
|
119
126
|
* WRFC chain persistence — call `rehydrate()` once after the SystemMessageRouter
|
|
120
127
|
* is wired so interrupted chains from a previous process are surfaced to the operator.
|
|
@@ -128,17 +135,8 @@ export type CompanionMessagePayload = Extract<SessionEvent, { type: 'COMPANION_M
|
|
|
128
135
|
// Operator narration of inbound channel events
|
|
129
136
|
// ---------------------------------------------------------------------------
|
|
130
137
|
|
|
131
|
-
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* When an external surface (GitHub, Slack, ntfy, etc.) triggers an agent turn,
|
|
135
|
-
* this function produces a human-readable system message so the operator can
|
|
136
|
-
* observe which event caused the turn. Returns null for internal/companion
|
|
137
|
-
* sources that do not need operator narration.
|
|
138
|
-
*
|
|
139
|
-
* @param event - The normalized inbound event descriptor.
|
|
140
|
-
* @returns A narration string, or null if no narration is appropriate.
|
|
141
|
-
*/
|
|
138
|
+
/** Narrate an inbound channel event (GitHub, Slack, ntfy, etc.) that triggered an
|
|
139
|
+
* agent turn, via the SystemMessageRouter — null for internal/companion sources. */
|
|
142
140
|
export function narrateInboundEvent(event: {
|
|
143
141
|
source: string;
|
|
144
142
|
metadata: Readonly<Record<string, unknown>> | undefined;
|
|
@@ -294,6 +292,12 @@ export async function initializeBootstrapCore(
|
|
|
294
292
|
surfaceRegistry,
|
|
295
293
|
watcherRegistry,
|
|
296
294
|
} = services;
|
|
295
|
+
// Permanently dormant for embedded/local-only (nothing to mirror to); bootstrap.ts activates it only for an adopted 'external' daemon.
|
|
296
|
+
const sessionSpine = new SessionSpineClient({ participant: TUI_SPINE_PARTICIPANT, recordKind: 'tui' });
|
|
297
|
+
// Cache-backed read facade over the local broker (passthrough until bootstrap.ts marks it
|
|
298
|
+
// embedded, or activates the adopted-daemon wire union for 'external').
|
|
299
|
+
// selfSessionIds keeps local authoritative for our own wire-mirrored session even when local/wire ids diverge (D-TUI-1).
|
|
300
|
+
const sessionUnionCache = new SessionUnionCache({ local: sharedSessionBroker, selfSessionIds: () => sessionSpine.mirroredSessionIds });
|
|
297
301
|
|
|
298
302
|
routeBindings.attachRuntime({ runtimeBus, runtimeStore: store });
|
|
299
303
|
surfaceRegistry.attachRuntime(store);
|
|
@@ -325,6 +329,7 @@ export async function initializeBootstrapCore(
|
|
|
325
329
|
const uiServices = createUiRuntimeServices(services, {
|
|
326
330
|
forensicsRegistry,
|
|
327
331
|
getControlPlaneRecentEvents,
|
|
332
|
+
sessionUnionCache,
|
|
328
333
|
});
|
|
329
334
|
|
|
330
335
|
const conversation = new ConversationManager(() => {
|
|
@@ -428,6 +433,10 @@ export async function initializeBootstrapCore(
|
|
|
428
433
|
} catch (err) {
|
|
429
434
|
logger.error('Render threw; next requestRender will reschedule', { error: String(err) });
|
|
430
435
|
}
|
|
436
|
+
// Debounced spine heartbeat on turn/render activity (no-op while dormant, i.e.
|
|
437
|
+
// embedded/local-only): a cheap synchronous no-op unless its own internal window has
|
|
438
|
+
// elapsed (at most one wire call per heartbeatMinIntervalMs) — safe on the hot path.
|
|
439
|
+
sessionSpine.heartbeat(runtimeSessionIdRef.value);
|
|
431
440
|
};
|
|
432
441
|
const requestRender = (): void => {
|
|
433
442
|
if (renderScheduled) return;
|
|
@@ -635,12 +644,27 @@ export async function initializeBootstrapCore(
|
|
|
635
644
|
},
|
|
636
645
|
));
|
|
637
646
|
|
|
647
|
+
// D3: inbound steer delivery — see createBootstrapInboundInputPoller's doc comment.
|
|
648
|
+
const sessionInboundInputs = createBootstrapInboundInputPoller({
|
|
649
|
+
runtimeSessionIdRef, routeOrBuffer, orchestratorHandleUserInputRef, conversation, requestRender,
|
|
650
|
+
});
|
|
651
|
+
|
|
638
652
|
providerRegistry.startWatching(runtimeBus);
|
|
639
653
|
|
|
654
|
+
// W2.3: attach the SAME WebhookNotifier instance that `/notify add|remove|clear`
|
|
655
|
+
// (notify-runtime.ts) keeps live via ctx.services.webhookNotifier, rather than
|
|
656
|
+
// constructing a second, boot-time-only instance here. Before this fix, a
|
|
657
|
+
// webhook URL added mid-session reached long-task notifications (which read
|
|
658
|
+
// ctx.services.webhookNotifier directly) but never reached this instance's
|
|
659
|
+
// AGENT_FAILED/WORKFLOW_CHAIN_FAILED/WORKFLOW_CHAIN_PASSED runtime-bus
|
|
660
|
+
// listeners until restart — and if the session started with zero URLs
|
|
661
|
+
// configured, attachToRuntimeBus was never even called, so those listeners
|
|
662
|
+
// never existed at all for the rest of the session. Always attaching
|
|
663
|
+
// (regardless of initial URL count) and seeding the shared instance fixes
|
|
664
|
+
// both: `send()` is already a safe no-op with zero URLs configured.
|
|
640
665
|
const webhookUrls = (configManager.getCategory('notifications') as { webhookUrls?: string[] }).webhookUrls ?? [];
|
|
641
666
|
if (webhookUrls.length > 0) {
|
|
642
|
-
|
|
643
|
-
webhookNotifier.attachToRuntimeBus(runtimeBus);
|
|
667
|
+
services.webhookNotifier.setUrls(webhookUrls);
|
|
644
668
|
domainDispatch.syncIntegration({
|
|
645
669
|
id: 'webhooks',
|
|
646
670
|
displayName: 'Webhooks',
|
|
@@ -652,6 +676,7 @@ export async function initializeBootstrapCore(
|
|
|
652
676
|
meta: { urlCount: webhookUrls.length },
|
|
653
677
|
}, 'bootstrap.webhooks');
|
|
654
678
|
}
|
|
679
|
+
services.webhookNotifier.attachToRuntimeBus(runtimeBus);
|
|
655
680
|
|
|
656
681
|
const notifier = await Notifier.fromConfig(services.serviceRegistry);
|
|
657
682
|
const queueStatuses = notifier.getQueueStatus();
|
|
@@ -714,6 +739,10 @@ export async function initializeBootstrapCore(
|
|
|
714
739
|
lastSeenAt: Date.now(),
|
|
715
740
|
},
|
|
716
741
|
}).catch((err) => { logger.debug('session broker create session failed at bootstrap', { err }); });
|
|
742
|
+
// Fire-and-forget spine mirror — a permanent parallel-write posture alongside (never
|
|
743
|
+
// instead of) the still-authoritative local SharedSessionBroker above. Dormant/queued
|
|
744
|
+
// until bootstrap.ts's deferred task activates it for an adopted 'external' daemon.
|
|
745
|
+
sessionSpine.register({ sessionId: runtime.sessionId, project: services.workingDirectory, title: 'Terminal UI session' });
|
|
717
746
|
|
|
718
747
|
domainDispatch.syncSessionState({
|
|
719
748
|
id: userSessionId,
|
|
@@ -764,5 +793,8 @@ export async function initializeBootstrapCore(
|
|
|
764
793
|
},
|
|
765
794
|
runtimeSessionIdRef,
|
|
766
795
|
wrfcPersistence,
|
|
796
|
+
sessionSpine,
|
|
797
|
+
sessionInboundInputs,
|
|
798
|
+
sessionUnionCache,
|
|
767
799
|
};
|
|
768
800
|
}
|
|
@@ -9,6 +9,7 @@ import { HelperModel } from '@pellux/goodvibes-sdk/platform/config';
|
|
|
9
9
|
import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
10
10
|
import { formatReturnContextForDisplay, getReturnContextMode, maybeAssistReturnContextSummary } from '@/runtime/index.ts';
|
|
11
11
|
import type { SharedSessionBroker } from '@pellux/goodvibes-sdk/platform/control-plane';
|
|
12
|
+
import type { SessionSpineClient } from '@pellux/goodvibes-sdk/platform/runtime/session-spine';
|
|
12
13
|
import type { SessionManager } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
13
14
|
import type { PanelManager } from '../panels/panel-manager.ts';
|
|
14
15
|
import type { ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
@@ -22,6 +23,10 @@ export interface ResumeSessionOptions {
|
|
|
22
23
|
readonly requestRender: () => void;
|
|
23
24
|
readonly onSessionIdChanged?: (sessionId: string) => void;
|
|
24
25
|
readonly sharedSessionBroker: Pick<SharedSessionBroker, 'reopenSession'>;
|
|
26
|
+
/** S3c: fire-and-forget daemon-spine mirror. Reopen (not register) is the
|
|
27
|
+
* ONLY resume-time verb — see the SDK session-spine client.ts header doc. */
|
|
28
|
+
readonly sessionSpine: Pick<SessionSpineClient, 'reopen'>;
|
|
29
|
+
readonly project: string;
|
|
25
30
|
readonly writeLastSessionPointer: (sessionId: string) => void;
|
|
26
31
|
readonly hookDispatcher: HookDispatcher;
|
|
27
32
|
readonly sessionManager: SessionManager;
|
|
@@ -75,6 +80,8 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
|
|
|
75
80
|
if (meta?.provider) options.runtime.provider = meta.provider;
|
|
76
81
|
options.writeLastSessionPointer(sessionId);
|
|
77
82
|
void options.sharedSessionBroker.reopenSession(sessionId).catch((err) => { logger.debug('session broker reopen session failed', { err }); });
|
|
83
|
+
// S3c: fire-and-forget spine mirror (reopen:true — the user resume verb).
|
|
84
|
+
options.sessionSpine.reopen({ sessionId, project: options.project, title: options.conversation.title || meta.title });
|
|
78
85
|
options.conversation.log(`Resumed session: ${sessionId}`, { fg: '135' });
|
|
79
86
|
const reopenedPanels: string[] = [];
|
|
80
87
|
if (meta.returnContext?.openPanels?.length) {
|
|
@@ -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';
|
|
@@ -32,6 +32,7 @@ import type { PolicyRuntimeState } from '@/runtime/index.ts';
|
|
|
32
32
|
import type { TaskManager } from '@/runtime/index.ts';
|
|
33
33
|
import type { UiRuntimeServices } from './ui-services.ts';
|
|
34
34
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
35
|
+
import type { SessionSpineClient } from '@pellux/goodvibes-sdk/platform/runtime/session-spine';
|
|
35
36
|
|
|
36
37
|
export interface BootstrapShellState {
|
|
37
38
|
readonly commandRegistry: CommandRegistry;
|
|
@@ -40,11 +41,6 @@ export interface BootstrapShellState {
|
|
|
40
41
|
readonly lastGitInfoRef: { value: GitHeaderInfo | undefined };
|
|
41
42
|
readonly inputHistory: InputHistory;
|
|
42
43
|
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
44
|
}
|
|
49
45
|
|
|
50
46
|
export interface BootstrapShellOptions {
|
|
@@ -52,6 +48,8 @@ export interface BootstrapShellOptions {
|
|
|
52
48
|
readonly runtimeBus: RuntimeEventBus;
|
|
53
49
|
readonly runtimeStore: RuntimeStore;
|
|
54
50
|
readonly services: RuntimeServices;
|
|
51
|
+
/** S3c: dormant until bootstrap.ts activates it for an adopted 'external' daemon. */
|
|
52
|
+
readonly sessionSpine: SessionSpineClient;
|
|
55
53
|
readonly conversation: ConversationManager;
|
|
56
54
|
readonly runtime: MutableRuntimeState;
|
|
57
55
|
readonly orchestrator: Orchestrator;
|
|
@@ -75,6 +73,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
75
73
|
runtimeBus,
|
|
76
74
|
runtimeStore,
|
|
77
75
|
services,
|
|
76
|
+
sessionSpine,
|
|
78
77
|
conversation,
|
|
79
78
|
runtime,
|
|
80
79
|
orchestrator,
|
|
@@ -92,7 +91,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
92
91
|
completeModelSelectionSideEffect,
|
|
93
92
|
} = options;
|
|
94
93
|
|
|
95
|
-
const systemMessagesPanel = new SystemMessagesPanel(configManager, services.componentHealthMonitor);
|
|
96
94
|
// W0.9: after any resume seam replays historical messages into `conversation`,
|
|
97
95
|
// the freshly-constructed `orchestrator` still has its zeroed default usage
|
|
98
96
|
// (SDK gap — Orchestrator.usage is never persisted/reseeded). Recompute it
|
|
@@ -109,6 +107,8 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
109
107
|
requestRender,
|
|
110
108
|
onSessionIdChanged,
|
|
111
109
|
sharedSessionBroker: services.sessionBroker,
|
|
110
|
+
sessionSpine,
|
|
111
|
+
project: services.workingDirectory,
|
|
112
112
|
writeLastSessionPointer,
|
|
113
113
|
hookDispatcher: services.hookDispatcher,
|
|
114
114
|
sessionManager: services.sessionManager,
|
|
@@ -138,16 +138,22 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
138
138
|
runtimeBus,
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
-
const openAgentDetailRef: { fn: (agentId: string) => void } = { fn: (_agentId: string) => {} };
|
|
142
|
-
|
|
143
141
|
// WO-139: initial cost-budget alert threshold (USD; 0/unset = disabled).
|
|
144
142
|
// Once the session starts, the real control surface is the CostTrackerPanel
|
|
145
143
|
// itself — the in-panel 'b' key and /cost budget <usd> both call
|
|
146
|
-
// CostTrackerPanel.setBudgetThreshold() directly on the live panel instance
|
|
144
|
+
// CostTrackerPanel.setBudgetThreshold() directly on the live panel instance,
|
|
145
|
+
// which (W2.3) now writes through to the behavior.budgetAlertUsd config key
|
|
146
|
+
// so the background budget-breach notifier reads the same value. The env
|
|
147
|
+
// var remains a first-run convenience only: it seeds the config key when
|
|
148
|
+
// that key has never been set, so it doesn't silently override a value the
|
|
149
|
+
// user has already configured in a prior session.
|
|
147
150
|
const parsedBudgetThreshold = Number(process.env.GOODVIBES_COST_BUDGET_USD);
|
|
148
151
|
const initialCostBudgetThreshold = Number.isFinite(parsedBudgetThreshold) && parsedBudgetThreshold > 0
|
|
149
152
|
? parsedBudgetThreshold
|
|
150
153
|
: 0;
|
|
154
|
+
if (initialCostBudgetThreshold > 0 && readBudgetAlertUsd((k) => configManager.get(k as Parameters<typeof configManager.get>[0])) === BUDGET_ALERT_USD_DEFAULT) {
|
|
155
|
+
configManager.set('behavior.budgetAlertUsd' as Parameters<typeof configManager.set>[0], initialCostBudgetThreshold as never);
|
|
156
|
+
}
|
|
151
157
|
|
|
152
158
|
let commandContextRef: CommandContext | null = null;
|
|
153
159
|
registerBuiltinPanels(services.panelManager, {
|
|
@@ -175,14 +181,14 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
175
181
|
forensicsRegistry,
|
|
176
182
|
policyRuntimeState,
|
|
177
183
|
approvalBroker: services.approvalBroker,
|
|
178
|
-
|
|
184
|
+
// S3d: panels read the cross-surface union facade, not the raw local broker.
|
|
185
|
+
sessionBroker: uiServices.sessions.sessionBroker,
|
|
179
186
|
automationManager: services.automationManager,
|
|
180
187
|
getControlPlaneRecentEvents,
|
|
181
188
|
tokenAuditor: services.tokenAuditor,
|
|
182
189
|
componentHealthMonitor: services.componentHealthMonitor,
|
|
183
190
|
worktreeRegistry: services.worktreeRegistry,
|
|
184
191
|
sandboxSessionRegistry: services.sandboxSessionRegistry,
|
|
185
|
-
systemMessagesPanel,
|
|
186
192
|
memoryRegistry: services.memoryRegistry,
|
|
187
193
|
uiServices,
|
|
188
194
|
pluginManager: services.pluginManager,
|
|
@@ -190,7 +196,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
190
196
|
hookActivityTracker: services.hookActivityTracker,
|
|
191
197
|
hookWorkbench: services.hookWorkbench,
|
|
192
198
|
mcpRegistry: services.mcpRegistry,
|
|
193
|
-
openAgentDetail: (agentId: string) => openAgentDetailRef.fn(agentId),
|
|
194
199
|
daemonHomeDir: join(services.homeDirectory, '.goodvibes', 'daemon'),
|
|
195
200
|
opsApi,
|
|
196
201
|
planRuntime,
|
|
@@ -203,13 +208,21 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
203
208
|
|
|
204
209
|
const systemMessageRouter = createSystemMessageRouter(
|
|
205
210
|
conversation,
|
|
206
|
-
systemMessagesPanel,
|
|
207
211
|
(kind) => {
|
|
208
212
|
const ui = getConfigSnapshot(configManager).ui;
|
|
209
213
|
if (kind === 'wrfc') return ui.wrfcMessages;
|
|
210
214
|
if (kind === 'operational') return ui.operationalMessages;
|
|
211
215
|
return ui.systemMessages;
|
|
212
216
|
},
|
|
217
|
+
{
|
|
218
|
+
// Suppress stale WRFC replay re-notifications for chains that can no
|
|
219
|
+
// longer act — gone (killed/removed → getChain null) or terminal
|
|
220
|
+
// (passed/failed). (UX-B item 1c.)
|
|
221
|
+
isChainTerminal: (chainId) => {
|
|
222
|
+
const chain = services.wrfcController.getChain(chainId);
|
|
223
|
+
return chain === null || chain.state === 'passed' || chain.state === 'failed';
|
|
224
|
+
},
|
|
225
|
+
},
|
|
213
226
|
);
|
|
214
227
|
orchestrator.setSystemMessageRouter(systemMessageRouter);
|
|
215
228
|
|
|
@@ -233,6 +246,9 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
233
246
|
mcpRegistry: services.mcpRegistry,
|
|
234
247
|
voiceProviderRegistry: services.voiceProviders,
|
|
235
248
|
voiceService: services.voiceService,
|
|
249
|
+
webSearchService: services.webSearchService,
|
|
250
|
+
mediaProviders: services.mediaProviders,
|
|
251
|
+
artifactStore: services.artifactStore,
|
|
236
252
|
forensicsRegistry,
|
|
237
253
|
policyRuntimeState,
|
|
238
254
|
readModels: uiServices.readModels,
|
|
@@ -240,6 +256,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
240
256
|
remoteRuntime,
|
|
241
257
|
planRuntime,
|
|
242
258
|
fileUndoManager: services.fileUndoManager,
|
|
259
|
+
workspaceCheckpointManager: services.workspaceCheckpointManager,
|
|
243
260
|
memoryRegistry: services.memoryRegistry,
|
|
244
261
|
integrationHelpers: services.integrationHelpers,
|
|
245
262
|
automationManager: services.automationManager,
|
|
@@ -268,6 +285,13 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
268
285
|
sessionMemoryStore: services.sessionMemoryStore,
|
|
269
286
|
sessionLineageTracker: services.sessionLineageTracker,
|
|
270
287
|
wrfcController: services.wrfcController,
|
|
288
|
+
workstreamEngine: services.workstreamCommands,
|
|
289
|
+
codeIndexStore: services.codeIndexStore,
|
|
290
|
+
codeIndexReindexScheduler: services.codeIndexReindexScheduler,
|
|
291
|
+
isPassiveCodeInjectionFlagEnabled: () => services.featureFlags.isEnabled('agent-passive-code-injection'),
|
|
292
|
+
// Wave 5 (wo805): expose the MAIN session's per-turn passive-injection ring
|
|
293
|
+
// so `/recall injections` (no agent id) renders it — see recall-review.ts.
|
|
294
|
+
getMainSessionTurnInjections: () => orchestrator.getTurnInjections(),
|
|
271
295
|
changeTracker: services.sessionChangeTracker,
|
|
272
296
|
planManager: services.planManager,
|
|
273
297
|
adaptivePlanner: services.adaptivePlanner,
|
|
@@ -302,6 +326,16 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
302
326
|
lastGitInfoRef.value = info;
|
|
303
327
|
requestRender();
|
|
304
328
|
}).catch(() => { /* non-fatal */ });
|
|
329
|
+
// W1.6 FIX 2: the header's git segment otherwise only refreshes on
|
|
330
|
+
// TURN_COMPLETED/TOOL_SUCCEEDED/TOOL_FAILED (see turn-event-wiring.ts's
|
|
331
|
+
// refreshGit()) — if the user runs `git init` externally and never submits
|
|
332
|
+
// another turn, the header stays stuck on the startup-time fallback
|
|
333
|
+
// indefinitely. Poll at the same 5s cadence GitPanel already uses for its
|
|
334
|
+
// own self-poll (git-panel.ts) so the two mechanisms are cadence-consistent.
|
|
335
|
+
gitStatusProvider.startPolling(5_000, (info) => {
|
|
336
|
+
lastGitInfoRef.value = info;
|
|
337
|
+
requestRender();
|
|
338
|
+
});
|
|
305
339
|
|
|
306
340
|
const saveHistory = configManager.get('behavior.saveHistory') as boolean;
|
|
307
341
|
const inputHistory = new InputHistory({
|
|
@@ -316,8 +350,5 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
316
350
|
lastGitInfoRef,
|
|
317
351
|
inputHistory,
|
|
318
352
|
systemMessageRouter,
|
|
319
|
-
setOpenAgentDetail: (fn: (agentId: string) => void) => {
|
|
320
|
-
openAgentDetailRef.fn = fn;
|
|
321
|
-
},
|
|
322
353
|
};
|
|
323
354
|
}
|