@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
|
@@ -5,19 +5,26 @@
|
|
|
5
5
|
* Delivery is resolved from the message KIND ('system' | 'wrfc' |
|
|
6
6
|
* 'operational'), which maps to a configurable routing target
|
|
7
7
|
* (ui.systemMessages / ui.wrfcMessages / ui.operationalMessages, each
|
|
8
|
-
* 'panel' | 'conversation' | 'both'). resolveSystemMessageDelivery() turns
|
|
9
|
-
* target — plus whether a panel is attached — into a { toPanel,
|
|
10
|
-
* decision.
|
|
11
|
-
* not by itself decide conversation delivery.
|
|
8
|
+
* 'panel' | 'conversation' | 'both'). resolveSystemMessageDelivery() turns
|
|
9
|
+
* that target — plus whether a panel is attached — into a { toPanel,
|
|
10
|
+
* toConversation } decision.
|
|
12
11
|
*
|
|
13
|
-
*
|
|
14
|
-
* (
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* W6.1 (the purge): the SystemMessagesPanel this router used to optionally
|
|
13
|
+
* push into was DELETE-disposition (no surviving human surface — a picker
|
|
14
|
+
* over the old panel registry, not something worth a dedicated console) and
|
|
15
|
+
* has been removed entirely, so this router now always resolves with
|
|
16
|
+
* `hasPanel = false`. Per resolveSystemMessageDelivery's own contract that
|
|
17
|
+
* means EVERY kind/target combination (including 'panel'-only) falls back
|
|
18
|
+
* to `toConversation: true` — nothing this router routes can vanish; it all
|
|
19
|
+
* reaches conversation.addTypedSystemMessage(), which the transcript
|
|
20
|
+
* renders as a navigable system line. This is deliberate, not a regression:
|
|
21
|
+
* operational chatter that used to be tucked away in a rarely-opened panel
|
|
22
|
+
* now surfaces inline, same as the messages that were already forced there
|
|
23
|
+
* (see FORCE_CONVERSATION_PREFIXES below).
|
|
17
24
|
*
|
|
18
25
|
* Usage:
|
|
19
26
|
* ```ts
|
|
20
|
-
* const router = createSystemMessageRouter(conversation
|
|
27
|
+
* const router = createSystemMessageRouter(conversation);
|
|
21
28
|
* router.routeSystemMessage('[Provider] anthropic registered', 'low');
|
|
22
29
|
* router.routeSystemMessage('[Session] Saved session abc123', 'high');
|
|
23
30
|
* ```
|
|
@@ -33,7 +40,6 @@
|
|
|
33
40
|
*/
|
|
34
41
|
|
|
35
42
|
import type { ConversationManager } from './conversation';
|
|
36
|
-
import type { SystemMessagesPanel, SystemMessagePriority } from '../panels/system-messages-panel.ts';
|
|
37
43
|
import {
|
|
38
44
|
classifySystemMessageKind,
|
|
39
45
|
classifySystemMessagePriority,
|
|
@@ -48,13 +54,15 @@ export type {
|
|
|
48
54
|
SystemMessageTarget,
|
|
49
55
|
} from '@/runtime/index.ts';
|
|
50
56
|
|
|
57
|
+
/** Panel emphasis level. Panel delivery was removed in W6.1 (see file doc); kept as the priority vocabulary for callers and for the SDK's delivery-resolution signature. */
|
|
58
|
+
export type SystemMessagePriority = 'high' | 'low';
|
|
59
|
+
|
|
51
60
|
/**
|
|
52
61
|
* Message categories that are operationally critical enough that the user must
|
|
53
62
|
* see them inline in the main conversation, regardless of the configured
|
|
54
|
-
* routing target
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* failed over, or the context was compacted.
|
|
63
|
+
* routing target. Errors, provider failovers, and compaction/context notices
|
|
64
|
+
* fall here: a user should never have to go hunting to discover that a turn
|
|
65
|
+
* errored, a provider failed over, or the context was compacted.
|
|
58
66
|
*
|
|
59
67
|
* Detection is by the stable message prefix tag, mirroring how the SDK
|
|
60
68
|
* classifiers key off message content. This deliberately does NOT force every
|
|
@@ -72,13 +80,12 @@ function mustReachConversation(message: string): boolean {
|
|
|
72
80
|
// ---------------------------------------------------------------------------
|
|
73
81
|
|
|
74
82
|
/**
|
|
75
|
-
* Routes system messages to the conversation
|
|
76
|
-
*
|
|
83
|
+
* Routes system messages to the conversation based on priority level and
|
|
84
|
+
* configured target. See file doc for the W6.1 panel removal.
|
|
77
85
|
*/
|
|
78
86
|
export class SystemMessageRouter {
|
|
79
87
|
constructor(
|
|
80
88
|
private readonly conversation: ConversationManager,
|
|
81
|
-
private panel: SystemMessagesPanel | null,
|
|
82
89
|
private readonly getTargetForKind: (kind: SystemMessageKind) => SystemMessageTarget = defaultSystemMessageTarget,
|
|
83
90
|
) {}
|
|
84
91
|
|
|
@@ -87,28 +94,26 @@ export class SystemMessageRouter {
|
|
|
87
94
|
/**
|
|
88
95
|
* Route a system message.
|
|
89
96
|
*
|
|
90
|
-
* Delivery is resolved from the kind and its configured target
|
|
91
|
-
*
|
|
92
|
-
*
|
|
97
|
+
* Delivery is resolved from the kind and its configured target. Critical
|
|
98
|
+
* notices (errors/failover/compaction, see FORCE_CONVERSATION_PREFIXES)
|
|
99
|
+
* are additionally forced into the conversation.
|
|
93
100
|
*
|
|
94
101
|
* @param message - Message text.
|
|
95
|
-
* @param priority - 'high' | 'low'
|
|
102
|
+
* @param priority - 'high' | 'low' (kept for callers; no longer changes
|
|
103
|
+
* delivery now that there is no panel to emphasize on).
|
|
96
104
|
* @param kind - Classification kind ('system' | 'wrfc' | 'operational');
|
|
97
105
|
* used to resolve routing target and conversation navigability.
|
|
98
106
|
*/
|
|
99
107
|
routeTypedSystemMessage(
|
|
100
108
|
message: string,
|
|
101
|
-
|
|
109
|
+
_priority: SystemMessagePriority,
|
|
102
110
|
kind: SystemMessageKind,
|
|
103
111
|
): void {
|
|
104
112
|
const target = this.getTargetForKind(kind);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// Critical notices (errors, failover, compaction) must surface inline even
|
|
110
|
-
// when the configured target is panel-only — otherwise a user without the
|
|
111
|
-
// SystemMessagesPanel open would never see them.
|
|
113
|
+
// hasPanel is always false post-W6.1 — resolveSystemMessageDelivery's own
|
|
114
|
+
// contract means every target ('panel' | 'conversation' | 'both')
|
|
115
|
+
// resolves toConversation: true in that case (see file doc).
|
|
116
|
+
const delivery = resolveSystemMessageDelivery(target, false);
|
|
112
117
|
const toConversation = delivery.toConversation || mustReachConversation(message);
|
|
113
118
|
if (toConversation) {
|
|
114
119
|
// addTypedSystemMessage threads the kind into the conversation so the
|
|
@@ -153,21 +158,6 @@ export class SystemMessageRouter {
|
|
|
153
158
|
wrfc(message: string, priority: SystemMessagePriority = 'high'): void {
|
|
154
159
|
this.routeTypedSystemMessage(message, priority, 'wrfc');
|
|
155
160
|
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Returns the current panel reference.
|
|
159
|
-
*/
|
|
160
|
-
getPanel(): SystemMessagesPanel | null {
|
|
161
|
-
return this.panel;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Replace the panel reference after construction (late binding).
|
|
166
|
-
* Pass null to detach the panel.
|
|
167
|
-
*/
|
|
168
|
-
setPanel(panel: SystemMessagesPanel | null): void {
|
|
169
|
-
this.panel = panel;
|
|
170
|
-
}
|
|
171
161
|
}
|
|
172
162
|
|
|
173
163
|
// ---------------------------------------------------------------------------
|
|
@@ -175,17 +165,13 @@ export class SystemMessageRouter {
|
|
|
175
165
|
// ---------------------------------------------------------------------------
|
|
176
166
|
|
|
177
167
|
/**
|
|
178
|
-
* Create a SystemMessageRouter wired to the given conversation
|
|
168
|
+
* Create a SystemMessageRouter wired to the given conversation.
|
|
179
169
|
*
|
|
180
|
-
* @param conversation - The ConversationManager
|
|
181
|
-
* @param panel - The SystemMessagesPanel for all messages. Can be null
|
|
182
|
-
* (router still works; messages to panel are silently
|
|
183
|
-
* dropped until a panel is available).
|
|
170
|
+
* @param conversation - The ConversationManager all routed messages reach.
|
|
184
171
|
*/
|
|
185
172
|
export function createSystemMessageRouter(
|
|
186
173
|
conversation: ConversationManager,
|
|
187
|
-
panel: SystemMessagesPanel | null = null,
|
|
188
174
|
getTargetForKind: (kind: SystemMessageKind) => SystemMessageTarget = defaultSystemMessageTarget,
|
|
189
175
|
): SystemMessageRouter {
|
|
190
|
-
return new SystemMessageRouter(conversation,
|
|
176
|
+
return new SystemMessageRouter(conversation, getTargetForKind);
|
|
191
177
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Orchestrator } from './orchestrator';
|
|
2
|
+
import type { SpokenTurnRuntime } from '../audio/spoken-turn-wiring.ts';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Builds the shared "cancel the active turn" action: stops any in-flight
|
|
6
|
+
* spoken output, then aborts the orchestrator's turn if one is actively
|
|
7
|
+
* streaming. Extracted from main.ts so the file can stay under its 800-line
|
|
8
|
+
* cap while still wiring `commandContext.isGenerating` (see W1.6 FIX 1).
|
|
9
|
+
*/
|
|
10
|
+
export function createCancelGeneration(
|
|
11
|
+
orchestrator: Orchestrator,
|
|
12
|
+
spokenTurns: Pick<SpokenTurnRuntime, 'stop'>,
|
|
13
|
+
): () => void {
|
|
14
|
+
return () => {
|
|
15
|
+
spokenTurns.stop('Spoken output stopped.');
|
|
16
|
+
if (orchestrator.isThinking) {
|
|
17
|
+
orchestrator.abort();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -6,7 +6,12 @@ import type { HookDispatcher, HookPhase, HookCategory, HookEventPath } from '@pe
|
|
|
6
6
|
import type { ConversationManager } from './conversation.ts';
|
|
7
7
|
import { journalPathFor, openTranscriptJournal, type TranscriptJournal } from './transcript-journal.ts';
|
|
8
8
|
import type { WebhookNotifier } from '@pellux/goodvibes-sdk/platform/integrations';
|
|
9
|
+
import { notifyCompletion } from '@pellux/goodvibes-sdk/platform/utils';
|
|
9
10
|
import { maybeNotifyLongTask, readNotifyAfterSeconds, type LongTaskStatus } from './long-task-notifier.ts';
|
|
11
|
+
import type { FocusTracker } from './focus-tracker.ts';
|
|
12
|
+
import { shouldFireAlert, FORCE_NOTIFY_DURATION_MS } from './alert-gating.ts';
|
|
13
|
+
import { createBudgetBreachNotifier, type BudgetBreachNotifier } from './budget-breach-notifier.ts';
|
|
14
|
+
import { readBudgetAlertUsd } from '../export/cost-utils.ts';
|
|
10
15
|
|
|
11
16
|
/** Infer the options param of persistConversation to pick up SessionManager correctly. */
|
|
12
17
|
type PersistOptions = NonNullable<Parameters<typeof persistConversation>[5]>;
|
|
@@ -14,11 +19,13 @@ type PersistOptions = NonNullable<Parameters<typeof persistConversation>[5]>;
|
|
|
14
19
|
/** Minimal orchestrator surface required by turn-event wiring. */
|
|
15
20
|
interface TurnOrchestrator {
|
|
16
21
|
readonly lastInputTokens: number;
|
|
22
|
+
/** Cumulative session usage — same object CostTrackerPanel reads, used here for budget-breach checks. */
|
|
23
|
+
readonly usage: { readonly input: number; readonly output: number; readonly cacheRead: number; readonly cacheWrite: number };
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
/** Minimal provider registry surface required by turn-event wiring. */
|
|
20
27
|
interface TurnProviderRegistry {
|
|
21
|
-
getCurrentModel(): { readonly contextWindow: number };
|
|
28
|
+
getCurrentModel(): { readonly contextWindow: number; readonly id?: string };
|
|
22
29
|
getContextWindowForModel(model: { readonly contextWindow: number }): number;
|
|
23
30
|
}
|
|
24
31
|
|
|
@@ -57,6 +64,16 @@ export interface WireTurnEventHandlersOptions {
|
|
|
57
64
|
* when absent.
|
|
58
65
|
*/
|
|
59
66
|
readonly webhookNotifier?: WebhookNotifier | null;
|
|
67
|
+
/**
|
|
68
|
+
* Terminal focus tracker (W2.3). Gates the long-task, budget-breach, and
|
|
69
|
+
* agent/chain-failure desktop alerts wired in this module — see
|
|
70
|
+
* alert-gating.ts. Optional; when absent, none of the new W2.3 alert
|
|
71
|
+
* behavior is gated by focus (long-task keeps its pre-W2.3 always-fire
|
|
72
|
+
* behavior, and budget-breach/failure alerts are skipped entirely, since
|
|
73
|
+
* they are new-in-W2.3 and have no pre-existing unconditional-fire path
|
|
74
|
+
* to fall back to).
|
|
75
|
+
*/
|
|
76
|
+
readonly focusTracker?: Pick<FocusTracker, 'shouldAlertWhenUnfocused'> | null;
|
|
60
77
|
/**
|
|
61
78
|
* Minimal test seam: injectable clock for controlling Date.now() in tests.
|
|
62
79
|
* Defaults to the real Date.now when absent.
|
|
@@ -94,13 +111,14 @@ export function wireTurnEventHandlers(
|
|
|
94
111
|
options: WireTurnEventHandlersOptions,
|
|
95
112
|
): WireTurnEventHandlersResult {
|
|
96
113
|
const {
|
|
97
|
-
events, conversation, runtime, configManager, hookDispatcher,
|
|
114
|
+
events, conversation, runtime, configManager, hookDispatcher, orchestrator, providerRegistry,
|
|
98
115
|
workingDir, homeDirectory, sessionManager, gitStatusProvider,
|
|
99
|
-
lastGitInfoRef, buildSessionContinuityHints, render, webhookNotifier,
|
|
116
|
+
lastGitInfoRef, buildSessionContinuityHints, render, webhookNotifier, focusTracker,
|
|
100
117
|
_clock = Date.now,
|
|
101
118
|
} = options;
|
|
102
119
|
|
|
103
120
|
const unsubs: Array<() => void> = [];
|
|
121
|
+
const configGet = (k: string): unknown => configManager.get(k as Parameters<typeof configManager.get>[0]);
|
|
104
122
|
|
|
105
123
|
// Create the per-session transcript journal. Path mirrors recovery-file
|
|
106
124
|
// convention (homeDirectory-scoped). Created lazily on first append.
|
|
@@ -112,6 +130,13 @@ export function wireTurnEventHandlers(
|
|
|
112
130
|
// Track turn start time for long-task notification threshold.
|
|
113
131
|
let turnStartTime: number | null = null;
|
|
114
132
|
|
|
133
|
+
// Budget-breach edge-trigger checker (W2.3) — one instance per session,
|
|
134
|
+
// piggybacking on the same TURN_COMPLETED handler as the long-task
|
|
135
|
+
// notification below rather than adding a second TURN_COMPLETED subscription.
|
|
136
|
+
const budgetBreachNotifier: BudgetBreachNotifier | null = focusTracker
|
|
137
|
+
? createBudgetBreachNotifier({ focusTracker, configGet, webhookNotifier: webhookNotifier ?? null, sessionId: runtime.sessionId })
|
|
138
|
+
: null;
|
|
139
|
+
|
|
115
140
|
const refreshGit = (): void => {
|
|
116
141
|
gitStatusProvider.refresh().then((info) => { lastGitInfoRef.value = info; render(); }).catch(() => { /* non-fatal */ });
|
|
117
142
|
};
|
|
@@ -140,7 +165,15 @@ export function wireTurnEventHandlers(
|
|
|
140
165
|
sessionId: runtime.sessionId,
|
|
141
166
|
thresholdSeconds: notifyThreshold,
|
|
142
167
|
webhookNotifier: webhookNotifier ?? null,
|
|
168
|
+
focusTracker,
|
|
169
|
+
configGet,
|
|
143
170
|
});
|
|
171
|
+
// Budget-breach alert (W2.3): edge-triggered, piggybacks on this same
|
|
172
|
+
// TURN_COMPLETED handler rather than a second subscription.
|
|
173
|
+
if (budgetBreachNotifier) {
|
|
174
|
+
const sessionModel = providerRegistry.getCurrentModel().id ?? 'unknown';
|
|
175
|
+
budgetBreachNotifier.check(orchestrator.usage, sessionModel, readBudgetAlertUsd(configGet));
|
|
176
|
+
}
|
|
144
177
|
// Auto-save after every LLM turn so kills don't lose the session
|
|
145
178
|
try {
|
|
146
179
|
const snapshot = conversation.toJSON() as { messages: Array<import('./conversation.ts').ConversationMessageSnapshot>; timestamp?: number };
|
|
@@ -180,5 +213,33 @@ export function wireTurnEventHandlers(
|
|
|
180
213
|
refreshGit();
|
|
181
214
|
}));
|
|
182
215
|
|
|
216
|
+
// Agent/chain-failure desktop alerts (W2.3). The SDK's WebhookNotifier and
|
|
217
|
+
// Notifier already fire webhook/Slack/Discord notifications for these two
|
|
218
|
+
// events unconditionally (attachToRuntimeBus in the SDK's
|
|
219
|
+
// platform/integrations — pre-existing, not focus-gated: an out-of-band
|
|
220
|
+
// push to another device is useful regardless of terminal focus). What was
|
|
221
|
+
// missing was a desktop notification, gated by focus like the other three
|
|
222
|
+
// alert classes — that's the only thing added here, to avoid double-firing
|
|
223
|
+
// a webhook that's already covered.
|
|
224
|
+
if (focusTracker) {
|
|
225
|
+
unsubs.push(events.agents.on('AGENT_FAILED', (payload) => {
|
|
226
|
+
if (!shouldFireAlert(focusTracker, configGet, 'behavior.notifyOnAgentFailure')) return;
|
|
227
|
+
try {
|
|
228
|
+
notifyCompletion('GoodVibes — agent failed', `agent ${payload.agentId.slice(0, 8)} failed: ${payload.error}`, FORCE_NOTIFY_DURATION_MS);
|
|
229
|
+
} catch (err) {
|
|
230
|
+
logger.debug('turn-event-wiring: agent-failure notify error', { error: String(err) });
|
|
231
|
+
}
|
|
232
|
+
}));
|
|
233
|
+
unsubs.push(events.workflows.on('WORKFLOW_CHAIN_FAILED', (payload) => {
|
|
234
|
+
if (!shouldFireAlert(focusTracker, configGet, 'behavior.notifyOnChainFailure')) return;
|
|
235
|
+
const kindLabel = payload.failureKind === 'transport' ? 'transient transport error' : payload.reason;
|
|
236
|
+
try {
|
|
237
|
+
notifyCompletion('GoodVibes — WRFC chain failed', `chain ${payload.chainId.slice(0, 12)} failed: ${kindLabel}`, FORCE_NOTIFY_DURATION_MS);
|
|
238
|
+
} catch (err) {
|
|
239
|
+
logger.debug('turn-event-wiring: chain-failure notify error', { error: String(err) });
|
|
240
|
+
}
|
|
241
|
+
}));
|
|
242
|
+
}
|
|
243
|
+
|
|
183
244
|
return { refreshGit, unsubs, transcriptJournal };
|
|
184
245
|
}
|
package/src/export/cost-utils.ts
CHANGED
|
@@ -1,13 +1,38 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// cost-utils — canonical pricing source for token cost calculations (consumed by CostTrackerPanel and share-runtime)
|
|
3
|
+
//
|
|
4
|
+
// Pricing resolution order (resolvePricing):
|
|
5
|
+
// 1. `:free` suffix (OpenRouter free-tier convention) — always priced at $0.
|
|
6
|
+
// 2. The live SDK model catalog, when a source has been wired via
|
|
7
|
+
// setPricingSource() (bootstrap-core.ts wires ProviderRegistry.getRawCatalogModels()
|
|
8
|
+
// once catalog init completes) — exact id match, then prefix/substring.
|
|
9
|
+
// 3. STATIC_FALLBACK_PRICING — a small hand-maintained safety net for common
|
|
10
|
+
// frontier models, used when the catalog has no source wired (e.g. tests)
|
|
11
|
+
// or hasn't matched (catalog not yet loaded, or a model this net covers
|
|
12
|
+
// that the catalog happens to miss).
|
|
13
|
+
// 4. Unpriced: the model is genuinely unknown to every source above. This is
|
|
14
|
+
// reported explicitly via `priced: false` so consumers can render an
|
|
15
|
+
// honest "unpriced" state instead of a silent $0.
|
|
3
16
|
// ---------------------------------------------------------------------------
|
|
4
17
|
|
|
18
|
+
import type { CatalogModel } from '@pellux/goodvibes-sdk/platform/providers';
|
|
19
|
+
|
|
5
20
|
export interface ModelPricing {
|
|
6
21
|
input: number;
|
|
7
22
|
output: number;
|
|
8
23
|
}
|
|
9
24
|
|
|
10
|
-
|
|
25
|
+
/** Result of a pricing lookup: the resolved (possibly zero) price, and whether it's real. */
|
|
26
|
+
export interface PricingResult {
|
|
27
|
+
pricing: ModelPricing;
|
|
28
|
+
/** False when no source (catalog or static fallback) recognized the model — the zero pricing is a placeholder, not a real price. */
|
|
29
|
+
priced: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Hand-maintained safety net, used only when the live catalog has no source
|
|
33
|
+
// wired or does not recognize the model. NOT the primary pricing source —
|
|
34
|
+
// see resolvePricing() below.
|
|
35
|
+
const STATIC_FALLBACK_PRICING: Record<string, ModelPricing> = {
|
|
11
36
|
// Free tier
|
|
12
37
|
'openrouter/free': { input: 0, output: 0 },
|
|
13
38
|
|
|
@@ -34,17 +59,71 @@ const MODEL_PRICING: Record<string, ModelPricing> = {
|
|
|
34
59
|
'gemini-2.5-pro': { input: 1.25, output: 5 },
|
|
35
60
|
};
|
|
36
61
|
|
|
62
|
+
// Module-level injection point. Kept as a bare singleton (not threaded through
|
|
63
|
+
// call sites) because the 9 existing consumers are pure functions with no
|
|
64
|
+
// ProviderRegistry in scope; see WO-315 brief for the tradeoff. Tests that
|
|
65
|
+
// never call setPricingSource() fall through to the static-fallback path,
|
|
66
|
+
// which keeps them isolated from catalog state by default.
|
|
67
|
+
let pricingSource: (() => readonly CatalogModel[]) | null = null;
|
|
68
|
+
|
|
69
|
+
/** Wire (or clear, with null) the live catalog as the primary pricing source. */
|
|
70
|
+
export function setPricingSource(source: (() => readonly CatalogModel[]) | null): void {
|
|
71
|
+
pricingSource = source;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function findInCatalog(modelId: string, models: readonly CatalogModel[]): ModelPricing | null {
|
|
75
|
+
const exact = models.find((m) => m.id === modelId);
|
|
76
|
+
if (exact) return exact.tier === 'free' ? { input: 0, output: 0 } : exact.pricing;
|
|
77
|
+
for (const m of models) {
|
|
78
|
+
if (modelId.startsWith(m.id) || modelId.includes(m.id)) {
|
|
79
|
+
return m.tier === 'free' ? { input: 0, output: 0 } : m.pricing;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function findInStaticFallback(modelId: string): ModelPricing | null {
|
|
86
|
+
const exact = STATIC_FALLBACK_PRICING[modelId];
|
|
87
|
+
if (exact) return exact;
|
|
88
|
+
for (const [key, pricing] of Object.entries(STATIC_FALLBACK_PRICING)) {
|
|
89
|
+
if (modelId.startsWith(key) || modelId.includes(key)) return pricing;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* resolvePricing — resolve USD-per-1M-token pricing for a model ID, and
|
|
96
|
+
* whether that pricing is real (vs. an unpriced placeholder). See the module
|
|
97
|
+
* header for the full resolution order.
|
|
98
|
+
*/
|
|
99
|
+
export function resolvePricing(modelId: string): PricingResult {
|
|
100
|
+
if (modelId.endsWith(':free')) return { pricing: { input: 0, output: 0 }, priced: true };
|
|
101
|
+
|
|
102
|
+
const models = pricingSource?.() ?? [];
|
|
103
|
+
const catalogHit = findInCatalog(modelId, models);
|
|
104
|
+
if (catalogHit) return { pricing: catalogHit, priced: true };
|
|
105
|
+
|
|
106
|
+
const fallbackHit = findInStaticFallback(modelId);
|
|
107
|
+
if (fallbackHit) return { pricing: fallbackHit, priced: true };
|
|
108
|
+
|
|
109
|
+
// Genuinely unknown — no source recognizes this model. Report honestly
|
|
110
|
+
// rather than collapsing into the same zero a free model would return.
|
|
111
|
+
return { pricing: { input: 0, output: 0 }, priced: false };
|
|
112
|
+
}
|
|
113
|
+
|
|
37
114
|
/**
|
|
38
115
|
* getPricing — resolve USD-per-1M-token pricing for a model ID.
|
|
39
|
-
*
|
|
116
|
+
* Back-compat wrapper over resolvePricing(); returns zero for both genuinely
|
|
117
|
+
* free and genuinely unknown models (use resolvePricing/isModelPriced to
|
|
118
|
+
* distinguish the two).
|
|
40
119
|
*/
|
|
41
120
|
export function getPricing(modelId: string): ModelPricing {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return
|
|
121
|
+
return resolvePricing(modelId).pricing;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** True when `modelId` resolves to a real price (free or paid), false when it's an unpriced placeholder. */
|
|
125
|
+
export function isModelPriced(modelId: string): boolean {
|
|
126
|
+
return resolvePricing(modelId).priced;
|
|
48
127
|
}
|
|
49
128
|
|
|
50
129
|
/**
|
|
@@ -56,6 +135,9 @@ export function getPricing(modelId: string): ModelPricing {
|
|
|
56
135
|
* cacheRead — cumulative cache-read tokens
|
|
57
136
|
* cacheWrite — cumulative cache-write tokens
|
|
58
137
|
* modelId — registry model identifier
|
|
138
|
+
*
|
|
139
|
+
* Unpriced models contribute 0 to the total (same as before this WO) — only
|
|
140
|
+
* the display layer distinguishes "genuinely free/priced" from "unpriced".
|
|
59
141
|
*/
|
|
60
142
|
export function calcSessionCost(
|
|
61
143
|
inputTokens: number,
|
|
@@ -69,3 +151,39 @@ export function calcSessionCost(
|
|
|
69
151
|
const billableInput = inputTokens + cacheRead + cacheWrite;
|
|
70
152
|
return (billableInput * pricing.input + outputTokens * pricing.output) / 1_000_000;
|
|
71
153
|
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* computeBudgetBreach — pure predicate shared by CostTrackerPanel's render-time
|
|
157
|
+
* "OVER BUDGET" flag and the background budget-breach notifier
|
|
158
|
+
* (core/budget-breach-notifier.ts), so both agree on exactly one definition
|
|
159
|
+
* of "over budget". `budgetThreshold <= 0` means no budget is configured
|
|
160
|
+
* (disabled), which can never be breached.
|
|
161
|
+
*/
|
|
162
|
+
export function computeBudgetBreach(sessionCost: number, budgetThreshold: number): boolean {
|
|
163
|
+
return budgetThreshold > 0 && sessionCost > budgetThreshold;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Read/write access to the `behavior.budgetAlertUsd` TUI-local config key. Plain
|
|
167
|
+
* callbacks (rather than a ConfigManager reference) so callers can pass a
|
|
168
|
+
* generic-key-cast wrapper without this module depending on the SDK config types. */
|
|
169
|
+
export interface BudgetAlertConfigAccess {
|
|
170
|
+
readonly get: (key: string) => unknown;
|
|
171
|
+
readonly set: (key: string, value: unknown) => void;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Default for the `behavior.budgetAlertUsd` synthetic setting: 0 = no budget configured. */
|
|
175
|
+
export const BUDGET_ALERT_USD_DEFAULT = 0;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* readBudgetAlertUsd — read the session cost-budget alert threshold (USD) from
|
|
179
|
+
* config. This is the single source of truth CostTrackerPanel and the
|
|
180
|
+
* background budget-breach notifier (core/budget-breach-notifier.ts) both
|
|
181
|
+
* read, so a threshold set via the panel's 'b' key is immediately visible to
|
|
182
|
+
* the notifier and vice versa. Falls back to BUDGET_ALERT_USD_DEFAULT (off)
|
|
183
|
+
* when the key is absent or invalid.
|
|
184
|
+
*/
|
|
185
|
+
export function readBudgetAlertUsd(configGet: (key: string) => unknown): number {
|
|
186
|
+
const raw = configGet('behavior.budgetAlertUsd');
|
|
187
|
+
const parsed = typeof raw === 'number' ? raw : Number(raw);
|
|
188
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : BUDGET_ALERT_USD_DEFAULT;
|
|
189
|
+
}
|
|
@@ -7,6 +7,7 @@ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
|
7
7
|
import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions';
|
|
8
8
|
import type { SelectionItem, SelectionResult, SelectionAction } from './selection-modal.ts';
|
|
9
9
|
import type { FileUndoManager } from '@pellux/goodvibes-sdk/platform/state';
|
|
10
|
+
import type { WorkspaceCheckpointManager } from '@pellux/goodvibes-sdk/platform/workspace';
|
|
10
11
|
import type { PanelManager } from '../panels/panel-manager.ts';
|
|
11
12
|
import type { KeybindingsManager } from './keybindings.ts';
|
|
12
13
|
import type { OnboardingWizardMode } from './onboarding/onboarding-wizard.ts';
|
|
@@ -68,6 +69,9 @@ export interface CommandUiActions {
|
|
|
68
69
|
};
|
|
69
70
|
executeCommand?: (name: string, args: string[]) => Promise<boolean>;
|
|
70
71
|
cancelGeneration?: () => void;
|
|
72
|
+
/** True while an LLM turn is actively streaming. Used to give Escape
|
|
73
|
+
* cancel-turn precedence over a focused panel's own escape handling. */
|
|
74
|
+
isGenerating?: () => boolean;
|
|
71
75
|
completeModelSelection?: (selection: {
|
|
72
76
|
model: { id: string; provider: string; displayName: string; registryKey: string };
|
|
73
77
|
effort: string;
|
|
@@ -75,9 +79,25 @@ export interface CommandUiActions {
|
|
|
75
79
|
/** Which config target to write the selected model to. Defaults to 'main'. */
|
|
76
80
|
target?: import('./model-picker.ts').ModelPickerTarget;
|
|
77
81
|
}) => void;
|
|
82
|
+
/**
|
|
83
|
+
* Commit an embedding-provider selection from the model picker's
|
|
84
|
+
* 'embeddingProvider' mode (the 'embeddings' target). Deliberately separate
|
|
85
|
+
* from completeModelSelection — embedding providers are not
|
|
86
|
+
* ModelDefinition-shaped, so routing them through the same commit path
|
|
87
|
+
* would require fabricating a fake model object.
|
|
88
|
+
*/
|
|
89
|
+
completeEmbeddingProviderSelection?: (providerId: string) => void;
|
|
78
90
|
clearScreen?: () => void;
|
|
79
91
|
activatePlan?: (planId: string, task: string) => void;
|
|
80
92
|
requestPermission?: PermissionRequestHandler;
|
|
93
|
+
/**
|
|
94
|
+
* Force a full-screen repaint on the next frame (reuses Compositor.resetDiff(),
|
|
95
|
+
* the same call resize/bootstrap already use). Defense-in-depth for command
|
|
96
|
+
* handlers whose spawned subprocess may have written to the real tty (e.g. a
|
|
97
|
+
* stderr-capture regression) — nulls the diff buffers so the next composite()
|
|
98
|
+
* repaints over any stray output instead of leaving it until an unrelated resize.
|
|
99
|
+
*/
|
|
100
|
+
requestFullRepaint?: () => void;
|
|
81
101
|
}
|
|
82
102
|
|
|
83
103
|
export interface CommandShellUiOpeners {
|
|
@@ -99,6 +119,13 @@ export interface CommandShellUiOpeners {
|
|
|
99
119
|
callback: (result: SelectionResult | null) => void,
|
|
100
120
|
) => void;
|
|
101
121
|
openSettingsModal?: (target?: string) => void;
|
|
122
|
+
/**
|
|
123
|
+
* Open a MIGRATE-TO-MODAL surface by name (W6.1 purge skeleton — WO-A/B
|
|
124
|
+
* command runtimes call this instead of openCommandPanel once their panel
|
|
125
|
+
* is converted to a ModalFactory config). Threaded from ui-openers.ts the
|
|
126
|
+
* same way openSettingsModal is.
|
|
127
|
+
*/
|
|
128
|
+
openModal?: (name: string) => void;
|
|
102
129
|
openSessionPicker?: () => void;
|
|
103
130
|
openProfilePicker?: () => void;
|
|
104
131
|
openShortcutsOverlay?: () => void;
|
|
@@ -141,6 +168,26 @@ export interface CommandSessionServices {
|
|
|
141
168
|
readonly sessionLineageTracker?: import('@pellux/goodvibes-sdk/platform/core').SessionLineageTracker;
|
|
142
169
|
readonly wrfcController?: import('@pellux/goodvibes-sdk/platform/agents').WrfcController;
|
|
143
170
|
readonly changeTracker?: import('@pellux/goodvibes-sdk/platform/sessions').SessionChangeTracker;
|
|
171
|
+
/**
|
|
172
|
+
* Recompute the Orchestrator's session-wide usage totals from the
|
|
173
|
+
* conversation's current message history. Call after a session resume
|
|
174
|
+
* replays historical messages, before the next render, so the footer's
|
|
175
|
+
* token counter reflects the resumed session's real usage instead of a
|
|
176
|
+
* fresh Orchestrator's zeroed default (W0.9).
|
|
177
|
+
*/
|
|
178
|
+
readonly hydrateSessionUsage?: () => void;
|
|
179
|
+
/** Wave 4 (wo703): the orchestration engine's command-facing facade — see runtime/workstream-services.ts. */
|
|
180
|
+
readonly workstreamEngine?: import('../runtime/workstream-services.ts').WorkstreamCommandService;
|
|
181
|
+
/** Wave 5 (wo804): the repo source-tree code index — see runtime/code-index-services.ts. */
|
|
182
|
+
readonly codeIndexStore?: import('@pellux/goodvibes-sdk/platform/state').CodeIndexStore;
|
|
183
|
+
/**
|
|
184
|
+
* Wave 5 (wo805): the MAIN interactive session's per-turn passive-injection
|
|
185
|
+
* honesty ring — `Orchestrator.getTurnInjections()`, the main-session
|
|
186
|
+
* counterpart to `AgentRecord.turnInjections` (wo801). `/recall injections`
|
|
187
|
+
* with no agent id reads this. Optional so command contexts built without an
|
|
188
|
+
* orchestrator (headless, tests) fall back to the honest empty state.
|
|
189
|
+
*/
|
|
190
|
+
readonly getMainSessionTurnInjections?: () => readonly import('../renderer/turn-injection.ts').TurnInjectionEntry[];
|
|
144
191
|
}
|
|
145
192
|
|
|
146
193
|
export interface CommandProviderServices {
|
|
@@ -157,6 +204,7 @@ export interface CommandProviderServices {
|
|
|
157
204
|
export interface CommandWorkspaceUiServices {
|
|
158
205
|
keybindingsManager?: KeybindingsManager;
|
|
159
206
|
fileUndoManager?: FileUndoManager;
|
|
207
|
+
workspaceCheckpointManager?: WorkspaceCheckpointManager;
|
|
160
208
|
panelManager?: PanelManager;
|
|
161
209
|
profileManager?: import('@pellux/goodvibes-sdk/platform/profiles').ProfileManager;
|
|
162
210
|
bookmarkManager?: import('@pellux/goodvibes-sdk/platform/bookmarks').BookmarkManager;
|
|
@@ -174,6 +222,11 @@ export interface CommandPlatformConfigServices {
|
|
|
174
222
|
readonly configManager: ConfigManager;
|
|
175
223
|
readonly voiceProviderRegistry?: VoiceProviderRegistry;
|
|
176
224
|
readonly voiceService?: VoiceService;
|
|
225
|
+
/** Direct-command consumer (`/search`) alongside the existing agent-tool consumer. */
|
|
226
|
+
readonly webSearchService?: import('@pellux/goodvibes-sdk/platform/web-search').WebSearchService;
|
|
227
|
+
/** Direct-command consumer (`/image`) — first production caller of `.generate()`. */
|
|
228
|
+
readonly mediaProviders?: import('@pellux/goodvibes-sdk/platform/media').MediaProviderRegistry;
|
|
229
|
+
readonly artifactStore?: import('@pellux/goodvibes-sdk/platform/artifacts').ArtifactStore;
|
|
177
230
|
}
|
|
178
231
|
|
|
179
232
|
export interface CommandPlatformServices
|
|
@@ -186,7 +239,7 @@ export interface CommandOpsServices
|
|
|
186
239
|
export interface CommandExtensionRegistryServices {
|
|
187
240
|
readonly toolRegistry: ToolRegistry;
|
|
188
241
|
readonly mcpRegistry: McpRegistry;
|
|
189
|
-
readonly evalRegistry?: import('../panels/eval-
|
|
242
|
+
readonly evalRegistry?: import('../panels/eval-registry.ts').EvalRegistry;
|
|
190
243
|
}
|
|
191
244
|
|
|
192
245
|
export interface CommandExtensionServices
|