@vellumai/assistant 0.11.4-staging.1 → 0.11.4-staging.3
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/AGENTS.md +8 -2
- package/ARCHITECTURE.md +2 -0
- package/docs/architecture/memory.md +15 -0
- package/docs/browser-use-architecture-phase2.md +128 -56
- package/docs/flux-turn-detection-spike.md +11 -6
- package/knip.json +3 -0
- package/openapi.yaml +135 -75
- package/package.json +1 -1
- package/scripts/write-plugin-api-shim.ts +10 -0
- package/src/__tests__/app-control-flow.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +2 -2
- package/src/__tests__/assistant-feature-flag-guard.test.ts +25 -3
- package/src/__tests__/byok-default-profile-ensure.test.ts +15 -0
- package/src/__tests__/channel-setup-panel-ack.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +8 -10
- package/src/__tests__/conversation-agent-loop.test.ts +4 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +112 -0
- package/src/__tests__/conversation-notifiers-provenance.test.ts +1 -1
- package/src/__tests__/conversation-queue.test.ts +99 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +9 -9
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
- package/src/__tests__/conversation-slash-queue.test.ts +3 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +21 -14
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +1 -1
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/document-sync-tags.test.ts +0 -75
- package/src/__tests__/gateway-only-guard.test.ts +2 -5
- package/src/__tests__/http-user-message-parity.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +49 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -0
- package/src/__tests__/media-generate-image.test.ts +131 -21
- package/src/__tests__/memory-retrieval-hook.test.ts +94 -2
- package/src/__tests__/plugin-api-webhook-url.test.ts +10 -7
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +7 -3
- package/src/__tests__/proxy-approval-callback.test.ts +1 -0
- package/src/__tests__/qdrant-manager.test.ts +14 -1
- package/src/__tests__/run-due-schedules.test.ts +21 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +187 -18
- package/src/__tests__/schedule-routes.test.ts +23 -0
- package/src/__tests__/schedule-store.test.ts +17 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +3 -3
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/subagent-fork-prompt-role.test.ts +1 -1
- package/src/__tests__/subagent-spawn-and-await.test.ts +4 -7
- package/src/__tests__/subagent-tool-gate-mode.test.ts +1 -1
- package/src/__tests__/subagent-tools.test.ts +81 -101
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +1 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
- package/src/__tests__/ui-shape-teaching.test.ts +33 -0
- package/src/__tests__/ui-visual-surface.test.ts +1 -1
- package/src/__tests__/ui-voice-picker-surface.test.ts +128 -0
- package/src/__tests__/ui-work-result-surface.test.ts +1 -1
- package/src/__tests__/voice-config-update.test.ts +40 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +5 -3
- package/src/__tests__/voice-session-bridge.test.ts +85 -29
- package/src/__tests__/workspace-migration-146-repair-retired-fireworks-deepseek-flash-model-id.test.ts +235 -0
- package/src/acp/session-manager.ts +8 -1
- package/src/api/surfaces.ts +12 -3
- package/src/calls/__tests__/voice-session-bridge.test.ts +21 -10
- package/src/calls/__tests__/voice-triage-escalate.test.ts +8 -0
- package/src/calls/call-controller.ts +16 -7
- package/src/calls/voice-session-bridge.ts +44 -25
- package/src/calls/voice-triage-escalate.ts +1 -0
- package/src/cli/bundled-modules.ts +29 -0
- package/src/cli/commands/db/repair.ts +4 -8
- package/src/cli/commands/domain.ts +6 -3
- package/src/cli/commands/email.ts +6 -3
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/plugins.ts +85 -36
- package/src/cli/commands/schedules.ts +35 -1
- package/src/cli/lib/bundled-marketplace.json +1 -1
- package/src/config/__tests__/balanced-model-experiment.test.ts +278 -0
- package/src/config/assistant-feature-flags.ts +36 -15
- package/src/config/balanced-model-experiment.ts +35 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +5 -4
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +101 -0
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.test.ts +65 -0
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +7 -1
- package/src/config/bundled-skills/settings/tools/shared.ts +16 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +9 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -12
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -4
- package/src/config/call-site-defaults.ts +7 -0
- package/src/config/default-profile-catalog.ts +97 -5
- package/src/config/feature-flag-registry.json +11 -11
- package/src/config/skills.ts +9 -2
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
- package/src/daemon/conversation-agent-loop.ts +14 -13
- package/src/daemon/conversation-notifiers.ts +11 -9
- package/src/daemon/conversation-store.ts +4 -4
- package/src/daemon/conversation-surfaces.ts +54 -18
- package/src/daemon/conversation-tool-setup.ts +2 -4
- package/src/daemon/conversation.ts +81 -44
- package/src/daemon/doordash-steps.ts +2 -2
- package/src/daemon/lifecycle.ts +14 -1
- package/src/daemon/process-message.ts +0 -23
- package/src/daemon/windows-compiled-entry.ts +4 -0
- package/src/documents/document-store.ts +5 -235
- package/src/hooks/types.ts +5 -0
- package/src/ipc/gateway-flag-listener.ts +17 -3
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +118 -0
- package/src/live-voice/live-voice-manager.ts +16 -3
- package/src/live-voice/live-voice-session.ts +63 -9
- package/src/live-voice/windows-compiled-live-voice.ts +4 -0
- package/src/monitoring/control.ts +1 -0
- package/src/monitoring/db-integrity-sample.ts +4 -5
- package/src/permissions/prompter.ts +1 -5
- package/src/persistence/conversation-queries.ts +66 -16
- package/src/persistence/embeddings/qdrant-manager.ts +84 -49
- package/src/persistence/migrations/360-add-document-workspace-path.ts +5 -14
- package/src/persistence/schema/documents.ts +4 -4
- package/src/plugin-api/constants.ts +8 -0
- package/src/plugin-api/index.ts +5 -1
- package/src/plugin-api/vision-support.test.ts +1 -1
- package/src/plugin-api/webhook-url.ts +13 -11
- package/src/plugins/defaults/main.ts +6 -7
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +77 -0
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +24 -6
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +53 -5
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +4 -4
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +66 -1
- package/src/plugins/defaults/memory/v3/injector.ts +8 -0
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +23 -9
- package/src/plugins/defaults/memory/worker-control.ts +1 -0
- package/src/plugins/defaults/worker-entrypoints.ts +3 -0
- package/src/plugins/mtime-cache.ts +17 -0
- package/src/prompts/templates/system-sections.ts +0 -7
- package/src/providers/__tests__/context-overflow-error.test.ts +24 -0
- package/src/providers/__tests__/retry-callsite.test.ts +20 -0
- package/src/providers/model-catalog.ts +3 -3
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +16 -7
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +11 -6
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +9 -49
- package/src/routes/control.ts +1 -0
- package/src/routes/route-host-client.ts +1 -0
- package/src/runtime/AGENTS.md +16 -17
- package/src/runtime/agent-wake.ts +15 -12
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +170 -1
- package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +215 -0
- package/src/runtime/routes/conversation-list-routes.ts +54 -22
- package/src/runtime/routes/conversation-management-routes.ts +2 -3
- package/src/runtime/routes/conversation-routes.ts +11 -13
- package/src/runtime/routes/documents-routes.ts +3 -222
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +2 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -2
- package/src/runtime/routes/playground/reset-circuit.ts +1 -1
- package/src/runtime/routes/schedule-routes.ts +94 -7
- package/src/runtime/routes/workspace-routes.ts +0 -9
- package/src/runtime/routes/workspace-utils.ts +3 -13
- package/src/runtime/services/conversation-serializer.ts +7 -2
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +68 -5
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +81 -0
- package/src/schedule/plugin-schedule-availability.ts +58 -0
- package/src/schedule/plugin-schedule-declarations.ts +23 -27
- package/src/schedule/plugin-schedule-reconciler.ts +12 -3
- package/src/schedule/schedule-store.ts +5 -1
- package/src/schedule/scheduler.ts +9 -4
- package/src/schedule/worker-control.ts +1 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +26 -15
- package/src/subagent/consult-context.ts +11 -11
- package/src/subagent/consult-prompt.ts +26 -35
- package/src/subagent/manager.ts +20 -37
- package/src/subagent/notify.ts +7 -1
- package/src/subagent/types.ts +8 -6
- package/src/tools/acp/spawn.ts +6 -4
- package/src/tools/skills/scaffold-managed.ts +25 -7
- package/src/tools/subagent/spawn.ts +28 -88
- package/src/tools/ui-surface/surface-shape-docs.ts +12 -1
- package/src/tts/__tests__/reasoning-tag-filter.test.ts +15 -0
- package/src/tts/reasoning-tag-filter.ts +11 -32
- package/src/util/__tests__/worker-process-command.test.ts +37 -0
- package/src/util/logger.ts +16 -0
- package/src/util/think-tag-stream.ts +95 -0
- package/src/util/worker-process.ts +37 -4
- package/src/windows-compiled-cli.ts +32 -0
- package/src/windows-compiled-entry.ts +4 -0
- package/src/windows-compiled-logger.ts +6 -0
- package/src/windows-compiled-worker-entry.ts +29 -0
- package/src/workspace/byok-default-profile-ensure.ts +15 -6
- package/src/workspace/migrations/146-repair-retired-fireworks-deepseek-flash-model-id.ts +195 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/document-workspace-file.test.ts +0 -467
- package/src/subagent/__tests__/consult-transcript.test.ts +0 -184
- package/src/subagent/consult-transcript.ts +0 -90
|
@@ -72,6 +72,7 @@ mock.module("../../persistence/conversation-crud.js", () => ({
|
|
|
72
72
|
|
|
73
73
|
import { setConfig } from "../../__tests__/helpers/set-config.js";
|
|
74
74
|
import { ABORT_WATCHDOG_MS } from "../../daemon/abort-watchdog.js";
|
|
75
|
+
import { VOICE_ESCALATION_CONTINUATION_MESSAGE_KIND } from "../../plugin-api/constants.js";
|
|
75
76
|
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
76
77
|
import {
|
|
77
78
|
CALL_OPENING_MARKER,
|
|
@@ -125,7 +126,7 @@ interface FakeConversation {
|
|
|
125
126
|
metadata?: Record<string, unknown>;
|
|
126
127
|
}) => Promise<{ id: string }>;
|
|
127
128
|
workingDir: string;
|
|
128
|
-
|
|
129
|
+
addEventObserver: (observer: unknown) => () => void;
|
|
129
130
|
handleConfirmationResponse: (
|
|
130
131
|
requestId: string,
|
|
131
132
|
decision: string,
|
|
@@ -191,13 +192,15 @@ function makeFakeConversation(opts: {
|
|
|
191
192
|
opts.onPersist?.(persistCount);
|
|
192
193
|
return { id: `msg-${persistCount}` };
|
|
193
194
|
},
|
|
194
|
-
// The install
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
195
|
+
// The install / reset pair marks a turn taking ownership of the
|
|
196
|
+
// conversation (observer registered) vs a turn's cleanup releasing it
|
|
197
|
+
// (the returned disposer invoked).
|
|
198
|
+
addEventObserver: (observer) => {
|
|
199
|
+
opts.events?.push("client:install");
|
|
200
|
+
clientCallback = observer as (msg: unknown) => Promise<void>;
|
|
201
|
+
return () => {
|
|
202
|
+
opts.events?.push("client:reset");
|
|
203
|
+
};
|
|
201
204
|
},
|
|
202
205
|
handleConfirmationResponse: (requestId, decision) => {
|
|
203
206
|
confirmationDecisions.push({ requestId, decision });
|
|
@@ -213,7 +216,7 @@ function makeFakeConversation(opts: {
|
|
|
213
216
|
conversation,
|
|
214
217
|
waitForIdleCalls,
|
|
215
218
|
confirmationDecisions,
|
|
216
|
-
/** Deliver an event the way the conversation would, to the installed
|
|
219
|
+
/** Deliver an event the way the conversation would, to the installed observer. */
|
|
217
220
|
emitToClient: async (msg: unknown) => {
|
|
218
221
|
await clientCallback?.(msg);
|
|
219
222
|
},
|
|
@@ -360,6 +363,10 @@ describe("startVoiceTurn escalation-continuation persistence", () => {
|
|
|
360
363
|
// not merely echo-suppressed live.
|
|
361
364
|
const fake = makeFakeConversation({ processing: false });
|
|
362
365
|
fakeConversation = fake.conversation;
|
|
366
|
+
let runOptions: Record<string, unknown> | undefined;
|
|
367
|
+
fake.conversation.runAgentLoop = async (...args: unknown[]) => {
|
|
368
|
+
runOptions = args[2] as Record<string, unknown>;
|
|
369
|
+
};
|
|
363
370
|
|
|
364
371
|
await startVoiceTurn({
|
|
365
372
|
...makeTurnOptions(),
|
|
@@ -372,7 +379,11 @@ describe("startVoiceTurn escalation-continuation persistence", () => {
|
|
|
372
379
|
expect(fake.lastPersistOpts()?.metadata).toEqual({
|
|
373
380
|
voiceSessionTurn: true,
|
|
374
381
|
hidden: true,
|
|
382
|
+
messageKind: VOICE_ESCALATION_CONTINUATION_MESSAGE_KIND,
|
|
375
383
|
});
|
|
384
|
+
expect(runOptions?.messageKind).toBe(
|
|
385
|
+
VOICE_ESCALATION_CONTINUATION_MESSAGE_KIND,
|
|
386
|
+
);
|
|
376
387
|
});
|
|
377
388
|
|
|
378
389
|
test("the opener prompt is persisted un-hidden (unchanged)", async () => {
|
|
@@ -967,7 +978,7 @@ describe("startVoiceTurn prior-turn teardown barrier", () => {
|
|
|
967
978
|
expect(events).toEqual(["persist", "client:install"]);
|
|
968
979
|
|
|
969
980
|
// Turn 2 arrives during the teardown window: it must not persist or
|
|
970
|
-
// install its
|
|
981
|
+
// install its event observer until turn 1's cleanup has run.
|
|
971
982
|
const turn2 = startVoiceTurn(
|
|
972
983
|
makeTurnOptions(undefined, "conv-teardown-order"),
|
|
973
984
|
);
|
|
@@ -85,6 +85,14 @@ describe("front-door decision rule", () => {
|
|
|
85
85
|
expect(rule.toLowerCase()).toContain("tool");
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
test("escalates when an answer needs personal memory absent from context", () => {
|
|
89
|
+
expect(rule.toLowerCase()).toContain("saved personal fact");
|
|
90
|
+
expect(rule.toLowerCase()).toContain("escalate rather than guessing");
|
|
91
|
+
expect(rule.toLowerCase()).toContain(
|
|
92
|
+
"personal context that is already present is yours to use directly",
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
88
96
|
test("demands a silent decision — no narrated reasoning in spoken output", () => {
|
|
89
97
|
// Regression: a weak front-door model narrated its triage deliberation
|
|
90
98
|
// aloud ("Context is complete — Alex paused...") before the bridge.
|
|
@@ -730,8 +730,10 @@ export class CallController {
|
|
|
730
730
|
let ttsBuffer = "";
|
|
731
731
|
let fullResponseText = "";
|
|
732
732
|
// Reasoning models can inline <think> spans in the content stream when a
|
|
733
|
-
// profile has not opted into parseThinkTags
|
|
734
|
-
//
|
|
733
|
+
// profile has not opted into parseThinkTags. Neither the spoken path nor
|
|
734
|
+
// the post-turn consumers of fullResponseText (transcripts,
|
|
735
|
+
// assistant_spoke, END_CALL/ASK_GUARDIAN detection) may see them: both
|
|
736
|
+
// are fed only filtered text.
|
|
735
737
|
const reasoningFilter = createReasoningTagFilter();
|
|
736
738
|
|
|
737
739
|
// Synthesized path: text is split at speakable boundaries as it streams
|
|
@@ -935,8 +937,13 @@ export class CallController {
|
|
|
935
937
|
if (!this.isCurrentRun(runVersion)) {
|
|
936
938
|
return;
|
|
937
939
|
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
+
// One filter feeds both consumers: the spoken stream and the text
|
|
941
|
+
// used for transcripts, assistant_spoke, and END_CALL/ASK_GUARDIAN
|
|
942
|
+
// marker detection. A control marker inside a reasoning span must
|
|
943
|
+
// never trigger a real action the caller did not hear.
|
|
944
|
+
const speakable = reasoningFilter.push(text);
|
|
945
|
+
fullResponseText += speakable;
|
|
946
|
+
ttsBuffer += speakable;
|
|
940
947
|
ttsBuffer = stripInternalSpeechMarkers(ttsBuffer);
|
|
941
948
|
flushSafeText();
|
|
942
949
|
};
|
|
@@ -1015,9 +1022,11 @@ export class CallController {
|
|
|
1015
1022
|
return fullResponseText;
|
|
1016
1023
|
}
|
|
1017
1024
|
|
|
1018
|
-
// Final sweep: release any held-back partial tag
|
|
1019
|
-
// remaining control markers from the buffer.
|
|
1020
|
-
|
|
1025
|
+
// Final sweep: release any held-back partial tag to both consumers,
|
|
1026
|
+
// then strip any remaining control markers from the buffer.
|
|
1027
|
+
const filterTail = reasoningFilter.flush();
|
|
1028
|
+
fullResponseText += filterTail;
|
|
1029
|
+
ttsBuffer += filterTail;
|
|
1021
1030
|
ttsBuffer = stripInternalSpeechMarkers(ttsBuffer);
|
|
1022
1031
|
if (ttsBuffer.length > 0) {
|
|
1023
1032
|
emitSafeChunk(ttsBuffer);
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
recordConversationPersistedSeq,
|
|
35
35
|
updateMessageContent,
|
|
36
36
|
} from "../persistence/conversation-crud.js";
|
|
37
|
+
import { VOICE_ESCALATION_CONTINUATION_MESSAGE_KIND } from "../plugin-api/constants.js";
|
|
37
38
|
import { pinnedListeningLanguage } from "../providers/speech-to-text/provider-catalog.js";
|
|
38
39
|
import type { ContentBlock } from "../providers/types.js";
|
|
39
40
|
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
@@ -783,11 +784,13 @@ export async function startVoiceTurn(
|
|
|
783
784
|
// model wakes, but they are not user speech and must not render as a live
|
|
784
785
|
// user bubble. Their echo is suppressed below (parity with
|
|
785
786
|
// `isEchoSuppressedUserMessage` on the text path).
|
|
787
|
+
const isEscalationContinuation =
|
|
788
|
+
opts.content === ESCALATION_CONTINUATION_CONTENT;
|
|
786
789
|
const isSyntheticVoicePrompt =
|
|
787
790
|
opts.hiddenSyntheticPrompt === true ||
|
|
788
791
|
opts.content === CALL_OPENING_MARKER ||
|
|
789
792
|
opts.content === CALL_VERIFICATION_COMPLETE_MARKER ||
|
|
790
|
-
|
|
793
|
+
isEscalationContinuation;
|
|
791
794
|
|
|
792
795
|
// The escalation-continuation prompt is a pure internal instruction ("give
|
|
793
796
|
// the full answer now"), not a real utterance and not the sort of scaffolding
|
|
@@ -799,8 +802,7 @@ export async function startVoiceTurn(
|
|
|
799
802
|
// affects client display. A caller whose prompt text is not a fixed sentinel
|
|
800
803
|
// opts into the same treatment with `hiddenSyntheticPrompt`.
|
|
801
804
|
const isHiddenSyntheticPrompt =
|
|
802
|
-
opts.hiddenSyntheticPrompt === true ||
|
|
803
|
-
opts.content === ESCALATION_CONTINUATION_CONTENT;
|
|
805
|
+
opts.hiddenSyntheticPrompt === true || isEscalationContinuation;
|
|
804
806
|
|
|
805
807
|
// Build the call-control protocol prompt so the model knows how to emit
|
|
806
808
|
// control markers (ASK_GUARDIAN, END_CALL, etc.) and recognize opener turns.
|
|
@@ -934,10 +936,10 @@ export async function startVoiceTurn(
|
|
|
934
936
|
// failed while no concurrent turn held the lock). Paths where this turn
|
|
935
937
|
// LOST the conversation to a concurrent winner must use `restoreTurnState`
|
|
936
938
|
// instead — this reset-to-defaults would clobber the winner's live state.
|
|
937
|
-
// The
|
|
938
|
-
// (
|
|
939
|
-
//
|
|
940
|
-
let
|
|
939
|
+
// The approval observer is only detached when this turn installed it
|
|
940
|
+
// (`detachApprovalObserver` is set); otherwise cleanup would detach an
|
|
941
|
+
// observer installed by a prior turn.
|
|
942
|
+
let detachApprovalObserver: (() => void) | undefined;
|
|
941
943
|
/**
|
|
942
944
|
* Confirmations this voice turn left pending for the user to answer, and the
|
|
943
945
|
* timers that stop them waiting forever.
|
|
@@ -976,11 +978,10 @@ export async function startVoiceTurn(
|
|
|
976
978
|
conversation.setVoiceCallControlPrompt(null);
|
|
977
979
|
conversation.callSessionId = undefined;
|
|
978
980
|
conversation.forcePromptSideEffects = false;
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
}
|
|
981
|
+
// Detach so the stale closure doesn't act on events from future turns on
|
|
982
|
+
// the same conversation.
|
|
983
|
+
detachApprovalObserver?.();
|
|
984
|
+
detachApprovalObserver = undefined;
|
|
984
985
|
};
|
|
985
986
|
|
|
986
987
|
const requestId = uuidv7();
|
|
@@ -994,6 +995,9 @@ export async function startVoiceTurn(
|
|
|
994
995
|
// `isVoiceSessionUserMessage` for why the channel fields cannot carry it.
|
|
995
996
|
voiceSessionTurn: true,
|
|
996
997
|
...(isHiddenSyntheticPrompt ? { hidden: true } : {}),
|
|
998
|
+
...(isEscalationContinuation
|
|
999
|
+
? { messageKind: VOICE_ESCALATION_CONTINUATION_MESSAGE_KIND }
|
|
1000
|
+
: {}),
|
|
997
1001
|
...(opts.voiceTelemetry
|
|
998
1002
|
? {
|
|
999
1003
|
// Projected onto `TurnTelemetryEvent.client` by
|
|
@@ -1245,24 +1249,25 @@ export async function startVoiceTurn(
|
|
|
1245
1249
|
publishConversationMessagesChanged(opts.conversationId);
|
|
1246
1250
|
}
|
|
1247
1251
|
|
|
1248
|
-
//
|
|
1249
|
-
//
|
|
1252
|
+
// Observe confirmation_request and secret_request events so voice can
|
|
1253
|
+
// auto-deny/auto-allow/auto-resolve them (there is no interactive UI on a
|
|
1254
|
+
// call). Delivery is not this observer's job: the conversation's sink has
|
|
1255
|
+
// already put each event on the wire before the observer sees it, which is
|
|
1256
|
+
// what keeps a resolution's `interaction_resolved` after the request it
|
|
1257
|
+
// answers.
|
|
1250
1258
|
let lastError: string | null = null;
|
|
1251
|
-
|
|
1259
|
+
const handleVoiceEvent = async (msg: AssistantEvent): Promise<void> => {
|
|
1252
1260
|
// The user (or anything else) answered: stop the fallback from firing on a
|
|
1253
1261
|
// request that is already decided.
|
|
1254
1262
|
if (msg.type === "interaction_resolved") {
|
|
1255
1263
|
settleVoiceApproval(msg.requestId);
|
|
1256
1264
|
}
|
|
1257
1265
|
if (msg.type === "confirmation_request") {
|
|
1258
|
-
//
|
|
1259
|
-
//
|
|
1260
|
-
//
|
|
1261
|
-
//
|
|
1262
|
-
//
|
|
1263
|
-
// before `confirmation_request` on the wire, leaving an orphaned card
|
|
1264
|
-
// whose Allow/Deny buttons 404.
|
|
1265
|
-
broadcastMessage(msg);
|
|
1266
|
+
// The request is already on the wire (the sink delivered it before this
|
|
1267
|
+
// observer ran), so a resolution below lands after it: attached clients
|
|
1268
|
+
// (e.g. the web app behind a live-voice room) clear their approval card
|
|
1269
|
+
// only on `interaction_resolved`, and the reverse order would leave an
|
|
1270
|
+
// orphaned card whose Allow/Deny buttons 404.
|
|
1266
1271
|
if (!isGuardian) {
|
|
1267
1272
|
// Non-guardian voice callers have no interactive approval UI.
|
|
1268
1273
|
// The pre-exec gate (tool-approval-handler.ts) handles grant
|
|
@@ -1420,9 +1425,15 @@ export async function startVoiceTurn(
|
|
|
1420
1425
|
conversation.handleSecretResponse(msg.requestId, undefined, "store");
|
|
1421
1426
|
return;
|
|
1422
1427
|
}
|
|
1423
|
-
|
|
1428
|
+
};
|
|
1429
|
+
detachApprovalObserver = conversation.addEventObserver((msg) => {
|
|
1430
|
+
handleVoiceEvent(msg).catch((err) => {
|
|
1431
|
+
log.warn(
|
|
1432
|
+
{ turnId, eventType: msg.type, err },
|
|
1433
|
+
"Voice approval observer failed",
|
|
1434
|
+
);
|
|
1435
|
+
});
|
|
1424
1436
|
});
|
|
1425
|
-
clientCallbackInstalled = true;
|
|
1426
1437
|
|
|
1427
1438
|
// Registered before the agent loop starts so the NEXT turn on this
|
|
1428
1439
|
// conversation waits for this turn's `finally { cleanup() }` — not just
|
|
@@ -1709,11 +1720,19 @@ export async function startVoiceTurn(
|
|
|
1709
1720
|
// ordinary call-agent resolution.
|
|
1710
1721
|
callSite:
|
|
1711
1722
|
opts.routingLeg === "front-door" ? "voiceFrontDoor" : "callAgent",
|
|
1723
|
+
// A caller is on the line, so the turn is interactive: approval prompts
|
|
1724
|
+
// must be raised rather than pre-denied, because the approval observer
|
|
1725
|
+
// above is what decides them (auto-resolve for a non-guardian caller,
|
|
1726
|
+
// a real card the guardian can answer).
|
|
1727
|
+
isInteractive: true,
|
|
1712
1728
|
// The escalation-continuation prompt is a transcript-suppressed machine
|
|
1713
1729
|
// signal (persisted `hidden`), so flag the turn to match — keeps
|
|
1714
1730
|
// prompt-as-user-speech consumers (e.g. title generation) from treating
|
|
1715
1731
|
// it as user speech.
|
|
1716
1732
|
...(isHiddenSyntheticPrompt ? { isHiddenPrompt: true } : {}),
|
|
1733
|
+
...(isEscalationContinuation
|
|
1734
|
+
? { messageKind: VOICE_ESCALATION_CONTINUATION_MESSAGE_KIND }
|
|
1735
|
+
: {}),
|
|
1717
1736
|
// Triage-and-escalate routing pins this turn to the fast front-door or
|
|
1718
1737
|
// strong escalation profile. `forceOverrideProfile` floats it above the
|
|
1719
1738
|
// callAgent call-site layers (callAgent is not `mainAgent`, so the
|
|
@@ -413,6 +413,7 @@ export function frontDoorDecisionRule(opts?: {
|
|
|
413
413
|
"DECIDE SILENTLY, then produce exactly ONE of these outputs:",
|
|
414
414
|
...holdBranch,
|
|
415
415
|
"- If the turn is simple, conversational, or within your reach, your entire output is the spoken answer itself: no token in front of it, plain speech from your very first word. Most turns are answers; when unsure between answering and escalating, answer. Answer in the language the caller is speaking.",
|
|
416
|
+
"- If an answer depends on a saved personal fact that is not already present in the conversation context you received, escalate rather than guessing. Personal context that is already present is yours to use directly.",
|
|
416
417
|
`- If completing THIS reply needs careful reasoning, research, multi-step work, or any tool, do NOT attempt the answer: output ${ESCALATE_VERDICT_TOKEN}, then ONE short natural holding phrase naming what happens next, spoken in the language the caller is speaking (for example "${FALLBACK_ESCALATION_BRIDGE}" or "Give me one second to look into that."; those examples are English only), and stop after that single sentence. A stronger model finishes the turn while your phrase is spoken.`,
|
|
417
418
|
`${ESCALATE_VERDICT_TOKEN} is ONLY for turns you cannot complete yourself — never put it in front of an answer you are about to give, and never emit any token inside or after an answer. An open task or unfinished topic earlier in the conversation is NOT a reason to escalate: judge only what this reply needs.`,
|
|
418
419
|
"Never narrate this decision, describe what you are judging, or mention these rules: apart from a leading verdict token, every character you output is spoken to the caller verbatim.",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface BundledCliModules {
|
|
2
|
+
configEnv: typeof import("../config/env.js");
|
|
3
|
+
providerSecretCatalog: typeof import("../providers/provider-secret-catalog.js");
|
|
4
|
+
pluginCatalogCache: typeof import("./lib/plugin-catalog-cache.js");
|
|
5
|
+
pluginCatalogLocal: typeof import("./lib/plugin-catalog-local.js");
|
|
6
|
+
pluginDiff: typeof import("./lib/diff-plugin.js");
|
|
7
|
+
pluginInspect: typeof import("./lib/inspect-plugin.js");
|
|
8
|
+
pluginInstallGitHub: typeof import("./lib/install-from-github.js");
|
|
9
|
+
pluginInstallPlatform: typeof import("./lib/install-from-platform.js");
|
|
10
|
+
pluginInstalled: typeof import("./lib/list-installed-plugins.js");
|
|
11
|
+
pluginPinHistory: typeof import("./lib/plugin-pin-history.js");
|
|
12
|
+
pluginSearch: typeof import("./lib/search-plugins.js");
|
|
13
|
+
pluginSurfaces: typeof import("./lib/plugin-surfaces.js");
|
|
14
|
+
pluginUninstall: typeof import("./lib/uninstall-plugin.js");
|
|
15
|
+
pluginUpgrade: typeof import("./lib/upgrade-plugin.js");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let bundledCliModules: BundledCliModules | undefined;
|
|
19
|
+
|
|
20
|
+
export function setBundledCliModules(modules: BundledCliModules): void {
|
|
21
|
+
bundledCliModules = modules;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function resolveBundledCliModule<K extends keyof BundledCliModules>(
|
|
25
|
+
name: K,
|
|
26
|
+
fallback: () => BundledCliModules[K],
|
|
27
|
+
): BundledCliModules[K] {
|
|
28
|
+
return bundledCliModules?.[name] ?? fallback();
|
|
29
|
+
}
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { existsSync } from "node:fs";
|
|
18
|
-
import { createRequire } from "node:module";
|
|
19
18
|
|
|
20
19
|
import type { Command } from "commander";
|
|
21
20
|
|
|
@@ -27,8 +26,6 @@ import { integrityCheckStep } from "./repair-step-integrity.js";
|
|
|
27
26
|
import type { RepairReport, RepairStep, StepResult } from "./repair-steps.js";
|
|
28
27
|
import { formatDurationMs, runRepairSteps } from "./repair-steps.js";
|
|
29
28
|
|
|
30
|
-
const loadModule = createRequire(import.meta.url);
|
|
31
|
-
|
|
32
29
|
// ---------------------------------------------------------------------------
|
|
33
30
|
// Step sequence
|
|
34
31
|
// ---------------------------------------------------------------------------
|
|
@@ -38,10 +35,9 @@ const loadModule = createRequire(import.meta.url);
|
|
|
38
35
|
* structural damage surfaces early. Resolved lazily because the backfill
|
|
39
36
|
* step pulls the DB graph.
|
|
40
37
|
*/
|
|
41
|
-
function repairSteps(): RepairStep[] {
|
|
42
|
-
const { conversationBackfillStep } =
|
|
43
|
-
"./repair-step-conversation-backfill.js"
|
|
44
|
-
) as typeof import("./repair-step-conversation-backfill.js");
|
|
38
|
+
async function repairSteps(): Promise<RepairStep[]> {
|
|
39
|
+
const { conversationBackfillStep } =
|
|
40
|
+
await import("./repair-step-conversation-backfill.js");
|
|
45
41
|
return [integrityCheckStep, conversationBackfillStep];
|
|
46
42
|
}
|
|
47
43
|
|
|
@@ -128,7 +124,7 @@ export function registerDbRepair(parent: Command): void {
|
|
|
128
124
|
|
|
129
125
|
const report = await runRepairSteps(
|
|
130
126
|
{ dbPath },
|
|
131
|
-
repairSteps(),
|
|
127
|
+
await repairSteps(),
|
|
132
128
|
isJson
|
|
133
129
|
? {}
|
|
134
130
|
: {
|
|
@@ -3,6 +3,7 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import type { Command } from "commander";
|
|
4
4
|
|
|
5
5
|
import { cliIpcCall, exitFromIpcResult } from "../../ipc/cli-client.js";
|
|
6
|
+
import { resolveBundledCliModule } from "../bundled-modules.js";
|
|
6
7
|
import { applyCommandHelp, subcommand } from "../lib/cli-command-help.js";
|
|
7
8
|
import { registerCommand } from "../lib/register-command.js";
|
|
8
9
|
import { getCliLogger } from "../logger.js";
|
|
@@ -19,9 +20,11 @@ const log = getCliLogger("domain");
|
|
|
19
20
|
* synchronously, so there is no place to await a module load.
|
|
20
21
|
*/
|
|
21
22
|
function envDomains(): { apexDomain: string; baseDomain: string } {
|
|
22
|
-
const { getApexDomain, getAssistantDomain } =
|
|
23
|
-
"
|
|
24
|
-
|
|
23
|
+
const { getApexDomain, getAssistantDomain } = resolveBundledCliModule(
|
|
24
|
+
"configEnv",
|
|
25
|
+
() =>
|
|
26
|
+
loadModule("../../config/env.js") as typeof import("../../config/env.js"),
|
|
27
|
+
);
|
|
25
28
|
return { apexDomain: getApexDomain(), baseDomain: getAssistantDomain() };
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from "../../ipc/cli-client.js";
|
|
17
17
|
import { guessMimeType } from "../../util/mime-type.js";
|
|
18
18
|
import { readStdinSync } from "../../util/read-stdin.js";
|
|
19
|
+
import { resolveBundledCliModule } from "../bundled-modules.js";
|
|
19
20
|
import { applyCommandHelp, subcommand } from "../lib/cli-command-help.js";
|
|
20
21
|
import { registerCommand } from "../lib/register-command.js";
|
|
21
22
|
import { getCliLogger } from "../logger.js";
|
|
@@ -60,9 +61,11 @@ function handleEmailIpcError(
|
|
|
60
61
|
* synchronously, so there is no place to await a module load.
|
|
61
62
|
*/
|
|
62
63
|
function assistantDomain(): string {
|
|
63
|
-
const { getAssistantDomain } =
|
|
64
|
-
"
|
|
65
|
-
|
|
64
|
+
const { getAssistantDomain } = resolveBundledCliModule(
|
|
65
|
+
"configEnv",
|
|
66
|
+
() =>
|
|
67
|
+
loadModule("../../config/env.js") as typeof import("../../config/env.js"),
|
|
68
|
+
);
|
|
66
69
|
return getAssistantDomain();
|
|
67
70
|
}
|
|
68
71
|
|
package/src/cli/commands/keys.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
|
|
3
3
|
import type { Command } from "commander";
|
|
4
4
|
|
|
5
|
+
import { resolveBundledCliModule } from "../bundled-modules.js";
|
|
5
6
|
import { applyCommandHelp, subcommand } from "../lib/cli-command-help.js";
|
|
6
7
|
import { registerCommand } from "../lib/register-command.js";
|
|
7
8
|
import { log } from "../logger.js";
|
|
@@ -16,9 +17,13 @@ const loadModule = createRequire(import.meta.url);
|
|
|
16
17
|
* callbacks synchronously, so there is no place to await a module load.
|
|
17
18
|
*/
|
|
18
19
|
function apiKeyProviders(): readonly string[] {
|
|
19
|
-
const { API_KEY_PROVIDERS } =
|
|
20
|
-
"
|
|
21
|
-
|
|
20
|
+
const { API_KEY_PROVIDERS } = resolveBundledCliModule(
|
|
21
|
+
"providerSecretCatalog",
|
|
22
|
+
() =>
|
|
23
|
+
loadModule(
|
|
24
|
+
"../../providers/provider-secret-catalog.js",
|
|
25
|
+
) as typeof import("../../providers/provider-secret-catalog.js"),
|
|
26
|
+
);
|
|
22
27
|
return API_KEY_PROVIDERS;
|
|
23
28
|
}
|
|
24
29
|
|
|
@@ -15,6 +15,7 @@ import { cliIpcCall } from "../../ipc/cli-client.js";
|
|
|
15
15
|
import { stripAnsiAndControlChars } from "../../util/ansi.js";
|
|
16
16
|
import { getWorkspacePluginsDir } from "../../util/platform.js";
|
|
17
17
|
import { truncate } from "../../util/truncate.js";
|
|
18
|
+
import { resolveBundledCliModule } from "../bundled-modules.js";
|
|
18
19
|
import { yellow } from "../lib/cli-colors.js";
|
|
19
20
|
import { applyCommandHelp, subcommand } from "../lib/cli-command-help.js";
|
|
20
21
|
import { confirmPrompt } from "../lib/confirm-prompt.js";
|
|
@@ -61,64 +62,112 @@ const loadModule = createRequire(import.meta.url);
|
|
|
61
62
|
/** Lazy accessors: each getter loads its implementation module on first use. */
|
|
62
63
|
const libs = {
|
|
63
64
|
get catalogCache() {
|
|
64
|
-
return
|
|
65
|
-
"
|
|
66
|
-
|
|
65
|
+
return resolveBundledCliModule(
|
|
66
|
+
"pluginCatalogCache",
|
|
67
|
+
() =>
|
|
68
|
+
loadModule(
|
|
69
|
+
"../lib/plugin-catalog-cache.js",
|
|
70
|
+
) as typeof import("../lib/plugin-catalog-cache.js"),
|
|
71
|
+
);
|
|
67
72
|
},
|
|
68
73
|
get catalogLocal() {
|
|
69
|
-
return
|
|
70
|
-
"
|
|
71
|
-
|
|
74
|
+
return resolveBundledCliModule(
|
|
75
|
+
"pluginCatalogLocal",
|
|
76
|
+
() =>
|
|
77
|
+
loadModule(
|
|
78
|
+
"../lib/plugin-catalog-local.js",
|
|
79
|
+
) as typeof import("../lib/plugin-catalog-local.js"),
|
|
80
|
+
);
|
|
72
81
|
},
|
|
73
82
|
get diff() {
|
|
74
|
-
return
|
|
75
|
-
"
|
|
76
|
-
|
|
83
|
+
return resolveBundledCliModule(
|
|
84
|
+
"pluginDiff",
|
|
85
|
+
() =>
|
|
86
|
+
loadModule(
|
|
87
|
+
"../lib/diff-plugin.js",
|
|
88
|
+
) as typeof import("../lib/diff-plugin.js"),
|
|
89
|
+
);
|
|
77
90
|
},
|
|
78
91
|
get inspect() {
|
|
79
|
-
return
|
|
80
|
-
"
|
|
81
|
-
|
|
92
|
+
return resolveBundledCliModule(
|
|
93
|
+
"pluginInspect",
|
|
94
|
+
() =>
|
|
95
|
+
loadModule(
|
|
96
|
+
"../lib/inspect-plugin.js",
|
|
97
|
+
) as typeof import("../lib/inspect-plugin.js"),
|
|
98
|
+
);
|
|
82
99
|
},
|
|
83
100
|
get installGitHub() {
|
|
84
|
-
return
|
|
85
|
-
"
|
|
86
|
-
|
|
101
|
+
return resolveBundledCliModule(
|
|
102
|
+
"pluginInstallGitHub",
|
|
103
|
+
() =>
|
|
104
|
+
loadModule(
|
|
105
|
+
"../lib/install-from-github.js",
|
|
106
|
+
) as typeof import("../lib/install-from-github.js"),
|
|
107
|
+
);
|
|
87
108
|
},
|
|
88
109
|
get installPlatform() {
|
|
89
|
-
return
|
|
90
|
-
"
|
|
91
|
-
|
|
110
|
+
return resolveBundledCliModule(
|
|
111
|
+
"pluginInstallPlatform",
|
|
112
|
+
() =>
|
|
113
|
+
loadModule(
|
|
114
|
+
"../lib/install-from-platform.js",
|
|
115
|
+
) as typeof import("../lib/install-from-platform.js"),
|
|
116
|
+
);
|
|
92
117
|
},
|
|
93
118
|
get installed() {
|
|
94
|
-
return
|
|
95
|
-
"
|
|
96
|
-
|
|
119
|
+
return resolveBundledCliModule(
|
|
120
|
+
"pluginInstalled",
|
|
121
|
+
() =>
|
|
122
|
+
loadModule(
|
|
123
|
+
"../lib/list-installed-plugins.js",
|
|
124
|
+
) as typeof import("../lib/list-installed-plugins.js"),
|
|
125
|
+
);
|
|
97
126
|
},
|
|
98
127
|
get pinHistory() {
|
|
99
|
-
return
|
|
100
|
-
"
|
|
101
|
-
|
|
128
|
+
return resolveBundledCliModule(
|
|
129
|
+
"pluginPinHistory",
|
|
130
|
+
() =>
|
|
131
|
+
loadModule(
|
|
132
|
+
"../lib/plugin-pin-history.js",
|
|
133
|
+
) as typeof import("../lib/plugin-pin-history.js"),
|
|
134
|
+
);
|
|
102
135
|
},
|
|
103
136
|
get search() {
|
|
104
|
-
return
|
|
105
|
-
"
|
|
106
|
-
|
|
137
|
+
return resolveBundledCliModule(
|
|
138
|
+
"pluginSearch",
|
|
139
|
+
() =>
|
|
140
|
+
loadModule(
|
|
141
|
+
"../lib/search-plugins.js",
|
|
142
|
+
) as typeof import("../lib/search-plugins.js"),
|
|
143
|
+
);
|
|
107
144
|
},
|
|
108
145
|
get surfaces() {
|
|
109
|
-
return
|
|
110
|
-
"
|
|
111
|
-
|
|
146
|
+
return resolveBundledCliModule(
|
|
147
|
+
"pluginSurfaces",
|
|
148
|
+
() =>
|
|
149
|
+
loadModule(
|
|
150
|
+
"../lib/plugin-surfaces.js",
|
|
151
|
+
) as typeof import("../lib/plugin-surfaces.js"),
|
|
152
|
+
);
|
|
112
153
|
},
|
|
113
154
|
get uninstall() {
|
|
114
|
-
return
|
|
115
|
-
"
|
|
116
|
-
|
|
155
|
+
return resolveBundledCliModule(
|
|
156
|
+
"pluginUninstall",
|
|
157
|
+
() =>
|
|
158
|
+
loadModule(
|
|
159
|
+
"../lib/uninstall-plugin.js",
|
|
160
|
+
) as typeof import("../lib/uninstall-plugin.js"),
|
|
161
|
+
);
|
|
117
162
|
},
|
|
118
163
|
get upgrade() {
|
|
119
|
-
return
|
|
120
|
-
"
|
|
121
|
-
|
|
164
|
+
return resolveBundledCliModule(
|
|
165
|
+
"pluginUpgrade",
|
|
166
|
+
() =>
|
|
167
|
+
loadModule(
|
|
168
|
+
"../lib/upgrade-plugin.js",
|
|
169
|
+
) as typeof import("../lib/upgrade-plugin.js"),
|
|
170
|
+
);
|
|
122
171
|
},
|
|
123
172
|
};
|
|
124
173
|
|