@mycadet/assistant 0.12.11 → 0.13.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/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
- package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
- package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
- package/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
- package/openapi.yaml +2 -708
- package/package.json +2 -3
- package/scripts/sync-web-search-catalog.ts +1 -2
- package/src/__tests__/cloud-profile-guard.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +6 -38
- package/src/__tests__/conversation-queue.test.ts +45 -6
- package/src/__tests__/db-readiness-http-gate.test.ts +0 -6
- package/src/__tests__/persist-onboarding-artifacts.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +0 -51
- package/src/__tests__/provider-cloud-proxy-integration.test.ts +2 -110
- package/src/__tests__/run-due-schedules.test.ts +0 -4
- package/src/__tests__/schedule-store.test.ts +0 -12
- package/src/__tests__/stt-stream-session.test.ts +4 -4
- package/src/__tests__/telephony-tts-guard.test.ts +2 -50
- package/src/__tests__/voice-config-update.test.ts +12 -167
- package/src/__tests__/web-search-catalog-parity.test.ts +0 -2
- package/src/__tests__/workspace-migration-130-speech-mode-to-provider.test.ts +9 -7
- package/src/__tests__/workspace-migration-132-web-search-mode-to-provider.test.ts +6 -6
- package/src/calls/__tests__/voice-session-bridge.test.ts +1 -4
- package/src/calls/resolve-call-tts-provider.ts +6 -25
- package/src/calls/telephony-credential-preflight.ts +0 -10
- package/src/calls/telephony-tts-capability.ts +1 -17
- package/src/cli/commands/tts.ts +1 -2
- package/src/cli/index.help.ts +0 -2
- package/src/cli/program.ts +0 -2
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +4 -42
- package/src/config/schemas/__tests__/stt.test.ts +10 -14
- package/src/config/schemas/services.ts +5 -6
- package/src/config/schemas/stt.ts +1 -3
- package/src/config/schemas/tts.ts +1 -30
- package/src/daemon/daemon-readiness.ts +4 -29
- package/src/daemon/lifecycle.ts +0 -31
- package/src/daemon/providers-setup.ts +0 -8
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
- package/src/heartbeat/heartbeat-service.ts +1 -66
- package/src/ipc/__tests__/db-readiness-ipc-gate.test.ts +1 -9
- package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +0 -44
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +4 -6
- package/src/live-voice/__tests__/live-voice-stt.test.ts +1 -1
- package/src/live-voice/live-voice-credential-preflight.ts +9 -33
- package/src/live-voice/live-voice-session.ts +10 -6
- package/src/live-voice/live-voice-tts.ts +1 -8
- package/src/plugins/defaults/memory/worker.ts +3 -3
- package/src/prompts/persona-resolver.ts +0 -35
- package/src/providers/__tests__/search-provider-catalog.test.ts +5 -8
- package/src/providers/__tests__/voice-error-copy.test.ts +9 -10
- package/src/providers/search-provider-catalog.ts +7 -39
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +3 -47
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +6 -372
- package/src/providers/speech-to-text/provider-catalog.ts +2 -73
- package/src/providers/speech-to-text/resolve.ts +3 -120
- package/src/runtime/http-router-types.ts +1 -3
- package/src/runtime/http-server.ts +1 -1
- package/src/runtime/routes/__tests__/tts-routes.test.ts +2 -6
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +7 -7
- package/src/runtime/routes/index.ts +0 -4
- package/src/runtime/routes/live-voice-routes.test.ts +4 -11
- package/src/runtime/routes/live-voice-routes.ts +8 -11
- package/src/runtime/routes/secret-routes.ts +0 -6
- package/src/runtime/routes/tts-routes.ts +0 -38
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1 -7
- package/src/schedule/__tests__/worker-mcp-readiness.test.ts +0 -4
- package/src/schedule/schedule-store.ts +0 -7
- package/src/schedule/scheduler.ts +0 -5
- package/src/schedule/worker.ts +1 -1
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +2 -10
- package/src/stt/daemon-batch-transcriber.ts +4 -38
- package/src/stt/types.ts +1 -9
- package/src/tools/network/__tests__/web-search.test.ts +3 -250
- package/src/tools/network/web-search.ts +4 -165
- package/src/tts/__tests__/provider-resolution.test.ts +0 -5
- package/src/tts/provider-catalog.ts +0 -4
- package/src/tts/types.ts +0 -1
- package/src/__tests__/cloud-speech-defaults.test.ts +0 -330
- package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1708
- package/src/__tests__/migration-export-http.test.ts +0 -557
- package/src/__tests__/migration-export-streaming.test.ts +0 -350
- package/src/__tests__/migration-export-to-gcs.test.ts +0 -706
- package/src/__tests__/migration-import-commit-http.test.ts +0 -1176
- package/src/__tests__/migration-import-from-gcs.test.ts +0 -534
- package/src/__tests__/migration-import-from-path.test.ts +0 -324
- package/src/__tests__/migration-import-from-url.test.ts +0 -588
- package/src/__tests__/migration-import-preflight-http.test.ts +0 -739
- package/src/__tests__/migration-jobs-status.test.ts +0 -139
- package/src/__tests__/migration-parity-persistence.test.ts +0 -1891
- package/src/__tests__/migration-transport.test.ts +0 -1089
- package/src/__tests__/migration-validate-http.test.ts +0 -634
- package/src/__tests__/migration-wizard.test.ts +0 -1395
- package/src/__tests__/rebind-secrets-screen.test.ts +0 -876
- package/src/__tests__/sanitize-config-for-transfer.test.ts +0 -259
- package/src/__tests__/transfer-progress-screen.test.ts +0 -1217
- package/src/__tests__/validation-results-screen.test.ts +0 -1130
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -147
- package/src/background-wake/background-wake-routes.test.ts +0 -906
- package/src/background-wake/cloud-client.test.ts +0 -328
- package/src/background-wake/cloud-client.ts +0 -196
- package/src/background-wake/next-wake.test.ts +0 -335
- package/src/background-wake/next-wake.ts +0 -188
- package/src/background-wake/publisher.ts +0 -93
- package/src/background-wake/wake-intent-hooks.test.ts +0 -234
- package/src/cli/commands/__tests__/backup.test.ts +0 -363
- package/src/cli/commands/backup.help.ts +0 -180
- package/src/cli/commands/backup.ts +0 -398
- package/src/cloud/cloud-speech.test.ts +0 -335
- package/src/cloud/cloud-speech.ts +0 -300
- package/src/config/cloud-speech-defaults.ts +0 -300
- package/src/config/sanitize-for-transfer.ts +0 -111
- package/src/live-voice/__tests__/live-voice-cloud-speech-fallback.test.ts +0 -250
- package/src/providers/speech-to-text/__tests__/cadet-cloud-realtime.test.ts +0 -457
- package/src/providers/speech-to-text/__tests__/cadet-cloud.test.ts +0 -271
- package/src/providers/speech-to-text/__tests__/cadet-speech-relay-connection.test.ts +0 -126
- package/src/providers/speech-to-text/cadet-cloud-flux-realtime.ts +0 -309
- package/src/providers/speech-to-text/cadet-cloud-realtime.ts +0 -315
- package/src/providers/speech-to-text/cadet-cloud.ts +0 -108
- package/src/providers/speech-to-text/cadet-speech-relay-connection.ts +0 -176
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +0 -254
- package/src/runtime/migrations/__tests__/job-registry.test.ts +0 -346
- package/src/runtime/migrations/__tests__/origin-mode.test.ts +0 -62
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +0 -184
- package/src/runtime/migrations/__tests__/staged-import-path.test.ts +0 -110
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +0 -112
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +0 -285
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +0 -126
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +0 -253
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +0 -208
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +0 -485
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +0 -349
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +0 -196
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +0 -551
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +0 -428
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +0 -220
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +0 -1823
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +0 -598
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +0 -463
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -538
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +0 -515
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +0 -453
- package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +0 -319
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +0 -240
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +0 -473
- package/src/runtime/migrations/gcs-signed-url.ts +0 -190
- package/src/runtime/migrations/job-registry.ts +0 -297
- package/src/runtime/migrations/migration-transport.ts +0 -612
- package/src/runtime/migrations/migration-wizard.ts +0 -747
- package/src/runtime/migrations/origin-mode.ts +0 -42
- package/src/runtime/migrations/rebind-secrets-screen.ts +0 -412
- package/src/runtime/migrations/staged-import-path.ts +0 -116
- package/src/runtime/migrations/transfer-progress-screen.ts +0 -323
- package/src/runtime/migrations/validation-results-screen.ts +0 -469
- package/src/runtime/migrations/vbundle-builder.ts +0 -1382
- package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -405
- package/src/runtime/migrations/vbundle-import-policy.ts +0 -241
- package/src/runtime/migrations/vbundle-importer.ts +0 -826
- package/src/runtime/migrations/vbundle-metadata-merge.ts +0 -113
- package/src/runtime/migrations/vbundle-streaming-importer.ts +0 -2844
- package/src/runtime/migrations/vbundle-streaming-validator.ts +0 -426
- package/src/runtime/migrations/vbundle-tar-stream.ts +0 -244
- package/src/runtime/migrations/vbundle-validator.ts +0 -724
- package/src/runtime/routes/__tests__/migration-cadet-metadata-reconcile.test.ts +0 -227
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +0 -54
- package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +0 -70
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +0 -257
- package/src/runtime/routes/background-wake-routes.ts +0 -387
- package/src/runtime/routes/migration-routes.ts +0 -2584
- package/src/tools/network/__tests__/cloud-search-proxy.test.ts +0 -282
- package/src/tools/network/cloud-search-proxy.ts +0 -211
- package/src/tts/__tests__/cadet-provider.test.ts +0 -253
- package/src/tts/providers/cadet-provider.ts +0 -244
- package/src/types/tar-stream.d.ts +0 -66
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { afterEach, beforeEach, describe, expect,
|
|
4
|
-
|
|
5
|
-
import * as actualCloudSpeech from "../cloud/cloud-speech.js";
|
|
6
|
-
|
|
7
|
-
let mockCloudSpeechAvailable = false;
|
|
8
|
-
|
|
9
|
-
mock.module("../cloud/cloud-speech.js", () => ({
|
|
10
|
-
...actualCloudSpeech,
|
|
11
|
-
managedSpeechAvailable: async () => mockCloudSpeechAvailable,
|
|
12
|
-
}));
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
13
4
|
|
|
14
5
|
// ---------------------------------------------------------------------------
|
|
15
6
|
// Mocks — declared before imports that depend on platform/logger
|
|
@@ -71,7 +62,6 @@ beforeEach(() => {
|
|
|
71
62
|
ensureTestDir();
|
|
72
63
|
writeConfig({});
|
|
73
64
|
invalidateConfigCache();
|
|
74
|
-
mockCloudSpeechAvailable = false;
|
|
75
65
|
});
|
|
76
66
|
|
|
77
67
|
afterEach(() => {
|
|
@@ -144,18 +134,6 @@ describe("voice_config_update — tts_provider", () => {
|
|
|
144
134
|
expect(tts).not.toHaveProperty("mode");
|
|
145
135
|
});
|
|
146
136
|
|
|
147
|
-
test("tts_provider cadet persists when a cloud connection is available", async () => {
|
|
148
|
-
mockCloudSpeechAvailable = true;
|
|
149
|
-
|
|
150
|
-
const result = await run(
|
|
151
|
-
{ setting: "tts_provider", value: "cadet" },
|
|
152
|
-
makeContext(),
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
expect(result.isError).toBe(false);
|
|
156
|
-
expect((readConfig().services as any).tts.provider).toBe("cadet");
|
|
157
|
-
});
|
|
158
|
-
|
|
159
137
|
test("broadcasts ttsProvider to client", async () => {
|
|
160
138
|
const messages: any[] = [];
|
|
161
139
|
const ctx = makeContext({
|
|
@@ -220,130 +198,36 @@ describe("voice_config_update — tts_voice_id", () => {
|
|
|
220
198
|
// Tests: tts_voice_id targets the active provider's voice field
|
|
221
199
|
// ---------------------------------------------------------------------------
|
|
222
200
|
|
|
223
|
-
describe("voice_config_update — tts_voice_id
|
|
224
|
-
|
|
225
|
-
writeConfig({ services: { tts: { provider: "
|
|
201
|
+
describe("voice_config_update — tts_voice_id", () => {
|
|
202
|
+
test("writes the voice id and broadcasts the ttsVoiceId key", async () => {
|
|
203
|
+
writeConfig({ services: { tts: { provider: "elevenlabs" } } });
|
|
226
204
|
invalidateConfigCache();
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
test("writes a Deepgram Aura model id to services.tts.providers.cadet.model", async () => {
|
|
230
|
-
makeCadetActive();
|
|
231
|
-
|
|
232
|
-
const result = await run(
|
|
233
|
-
{ setting: "tts_voice_id", value: "aura-2-zeus-en" },
|
|
234
|
-
makeContext(),
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
expect(result.isError).toBe(false);
|
|
238
|
-
const config = readConfig();
|
|
239
|
-
expect((config.services as any)?.tts?.providers?.cadet?.model).toBe(
|
|
240
|
-
"aura-2-zeus-en",
|
|
241
|
-
);
|
|
242
|
-
// The ElevenLabs field is never touched when cadet is active.
|
|
243
|
-
expect(
|
|
244
|
-
(config.services as any)?.tts?.providers?.elevenlabs?.voiceId,
|
|
245
|
-
).toBeUndefined();
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
test("accepts an ElevenLabs voice id as a cloud model (managed serves ElevenLabs voices)", async () => {
|
|
249
|
-
makeCadetActive();
|
|
250
|
-
|
|
251
|
-
const result = await run(
|
|
252
|
-
{ setting: "tts_voice_id", value: "EXAVITQu4vr4xnSDxMaL" },
|
|
253
|
-
makeContext(),
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
expect(result.isError).toBe(false);
|
|
257
|
-
expect((readConfig().services as any)?.tts?.providers?.cadet?.model).toBe(
|
|
258
|
-
"EXAVITQu4vr4xnSDxMaL",
|
|
259
|
-
);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
test("does not broadcast the ElevenLabs ttsVoiceId key for a cloud voice", async () => {
|
|
263
|
-
makeCadetActive();
|
|
264
205
|
const messages: any[] = [];
|
|
265
206
|
const ctx = makeContext({
|
|
266
207
|
sendToClient: (msg: any) => messages.push(msg),
|
|
267
208
|
});
|
|
268
209
|
|
|
269
|
-
const result = await run(
|
|
270
|
-
{ setting: "tts_voice_id", value: "aura-2-zeus-en" },
|
|
271
|
-
ctx,
|
|
272
|
-
);
|
|
273
|
-
|
|
274
|
-
expect(result.isError).toBe(false);
|
|
275
|
-
expect(messages).toHaveLength(0);
|
|
276
|
-
expect(result.content).not.toContain("broadcast");
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
test("hints the inline picker for the next cloud voice change", async () => {
|
|
280
|
-
makeCadetActive();
|
|
281
|
-
|
|
282
|
-
const result = await run(
|
|
283
|
-
{ setting: "tts_voice_id", value: "aura-2-zeus-en" },
|
|
284
|
-
makeContext(),
|
|
285
|
-
);
|
|
210
|
+
const result = await run({ setting: "tts_voice_id", value: "abc123" }, ctx);
|
|
286
211
|
|
|
287
212
|
expect(result.isError).toBe(false);
|
|
288
|
-
expect(
|
|
289
|
-
expect(
|
|
290
|
-
|
|
291
|
-
);
|
|
213
|
+
expect(messages).toHaveLength(1);
|
|
214
|
+
expect(messages[0].key).toBe("ttsVoiceId");
|
|
215
|
+
expect(messages[0].value).toBe("abc123");
|
|
292
216
|
});
|
|
293
217
|
|
|
294
|
-
test("
|
|
218
|
+
test("rejects a value with characters invalid for any voice id", async () => {
|
|
295
219
|
writeConfig({ services: { tts: { provider: "elevenlabs" } } });
|
|
296
220
|
invalidateConfigCache();
|
|
297
221
|
|
|
298
|
-
const result = await run(
|
|
299
|
-
{ setting: "tts_voice_id", value: "abc123" },
|
|
300
|
-
makeContext(),
|
|
301
|
-
);
|
|
302
|
-
|
|
303
|
-
expect(result.isError).toBe(false);
|
|
304
|
-
expect(result.content).not.toContain("voice_picker");
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
test("does not hint the picker for a non-voice setting", async () => {
|
|
308
|
-
makeCadetActive();
|
|
309
|
-
|
|
310
|
-
const result = await run(
|
|
311
|
-
{ setting: "conversation_timeout", value: 30 },
|
|
312
|
-
makeContext(),
|
|
313
|
-
);
|
|
314
|
-
|
|
315
|
-
expect(result.isError).toBe(false);
|
|
316
|
-
expect(result.content).not.toContain("voice_picker");
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
test("rejects a value with characters invalid for any voice id", async () => {
|
|
320
|
-
makeCadetActive();
|
|
321
|
-
|
|
322
222
|
const result = await run(
|
|
323
223
|
{ setting: "tts_voice_id", value: "a british man" },
|
|
324
224
|
makeContext(),
|
|
325
225
|
);
|
|
326
226
|
|
|
327
227
|
expect(result.isError).toBe(true);
|
|
328
|
-
expect(
|
|
329
|
-
|
|
330
|
-
);
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
test("broadcasts the ElevenLabs ttsVoiceId key when elevenlabs is active", async () => {
|
|
334
|
-
writeConfig({ services: { tts: { provider: "elevenlabs" } } });
|
|
335
|
-
invalidateConfigCache();
|
|
336
|
-
const messages: any[] = [];
|
|
337
|
-
const ctx = makeContext({
|
|
338
|
-
sendToClient: (msg: any) => messages.push(msg),
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
const result = await run({ setting: "tts_voice_id", value: "abc123" }, ctx);
|
|
342
|
-
|
|
343
|
-
expect(result.isError).toBe(false);
|
|
344
|
-
expect(messages).toHaveLength(1);
|
|
345
|
-
expect(messages[0].key).toBe("ttsVoiceId");
|
|
346
|
-
expect(messages[0].value).toBe("abc123");
|
|
228
|
+
expect(
|
|
229
|
+
(readConfig().services as any)?.tts?.providers?.elevenlabs?.voiceId,
|
|
230
|
+
).toBeUndefined();
|
|
347
231
|
});
|
|
348
232
|
});
|
|
349
233
|
|
|
@@ -536,31 +420,6 @@ describe("voice_config_update — stt_provider", () => {
|
|
|
536
420
|
);
|
|
537
421
|
});
|
|
538
422
|
|
|
539
|
-
test("persists the cadet provider when a cloud connection is available", async () => {
|
|
540
|
-
mockCloudSpeechAvailable = true;
|
|
541
|
-
|
|
542
|
-
const result = await run(
|
|
543
|
-
{ setting: "stt_provider", value: "cadet" },
|
|
544
|
-
makeContext(),
|
|
545
|
-
);
|
|
546
|
-
|
|
547
|
-
expect(result.isError).toBe(false);
|
|
548
|
-
expect((readConfig().services as any)?.stt?.provider).toBe("cadet");
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
test("rejects the cadet provider without a cloud connection", async () => {
|
|
552
|
-
mockCloudSpeechAvailable = false;
|
|
553
|
-
|
|
554
|
-
const result = await run(
|
|
555
|
-
{ setting: "stt_provider", value: "cadet" },
|
|
556
|
-
makeContext(),
|
|
557
|
-
);
|
|
558
|
-
|
|
559
|
-
expect(result.isError).toBe(true);
|
|
560
|
-
expect(result.content).toContain("assistant cloud connect");
|
|
561
|
-
expect((readConfig().services as any)?.stt?.provider).toBeUndefined();
|
|
562
|
-
});
|
|
563
|
-
|
|
564
423
|
test("stt_model persists under the active provider", async () => {
|
|
565
424
|
// Flux stays reachable from this surface after ceasing to be a provider
|
|
566
425
|
// id: it is a model family on whichever provider is active.
|
|
@@ -916,22 +775,8 @@ describe("voice_config_update - stt_language", () => {
|
|
|
916
775
|
// ---------------------------------------------------------------------------
|
|
917
776
|
|
|
918
777
|
describe("voice_config_update — catalog-driven provider validation", () => {
|
|
919
|
-
test("rejects tts_provider cadet without a cloud connection", async () => {
|
|
920
|
-
mockCloudSpeechAvailable = false;
|
|
921
|
-
|
|
922
|
-
const result = await run(
|
|
923
|
-
{ setting: "tts_provider", value: "cadet" },
|
|
924
|
-
makeContext(),
|
|
925
|
-
);
|
|
926
|
-
|
|
927
|
-
expect(result.isError).toBe(true);
|
|
928
|
-
expect(result.content).toContain("assistant cloud connect");
|
|
929
|
-
expect((readConfig().services as any)?.tts?.provider).toBeUndefined();
|
|
930
|
-
});
|
|
931
|
-
|
|
932
778
|
test("accepts every provider ID in the catalog", async () => {
|
|
933
779
|
// The catalog includes cadet, which is gated on a cloud connection.
|
|
934
|
-
mockCloudSpeechAvailable = true;
|
|
935
780
|
const catalogIds = listCatalogProviderIds();
|
|
936
781
|
expect(catalogIds.length).toBeGreaterThanOrEqual(1);
|
|
937
782
|
|
|
@@ -23,7 +23,6 @@ interface JsonCatalogEntry {
|
|
|
23
23
|
id: string;
|
|
24
24
|
displayName: string;
|
|
25
25
|
displayNameLong?: string;
|
|
26
|
-
kind: "managed" | "byok";
|
|
27
26
|
apiKeyPrefix?: string;
|
|
28
27
|
envVar?: string;
|
|
29
28
|
secretKey?: string;
|
|
@@ -61,7 +60,6 @@ function entryToPlain(
|
|
|
61
60
|
if (entry.displayNameLong !== undefined) {
|
|
62
61
|
out.displayNameLong = entry.displayNameLong;
|
|
63
62
|
}
|
|
64
|
-
out.kind = entry.kind;
|
|
65
63
|
if (entry.apiKeyPrefix !== undefined) {
|
|
66
64
|
out.apiKeyPrefix = entry.apiKeyPrefix;
|
|
67
65
|
}
|
|
@@ -9,7 +9,6 @@ import { tmpdir } from "node:os";
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
11
11
|
|
|
12
|
-
import { AssistantConfigSchema } from "../config/schema.js";
|
|
13
12
|
import { speechModeToProviderMigration } from "../workspace/migrations/130-speech-mode-to-provider.js";
|
|
14
13
|
import { WORKSPACE_MIGRATIONS } from "../workspace/migrations/registry.js";
|
|
15
14
|
import { getLastWorkspaceMigrationId } from "../workspace/migrations/runner.js";
|
|
@@ -146,9 +145,10 @@ describe("130-speech-mode-to-provider", () => {
|
|
|
146
145
|
expect(() => speechModeToProviderMigration.run(workspaceDir)).not.toThrow();
|
|
147
146
|
});
|
|
148
147
|
|
|
149
|
-
// The migrated shape is
|
|
150
|
-
//
|
|
151
|
-
|
|
148
|
+
// The migrated shape is frozen (the migration never reruns), asserted raw:
|
|
149
|
+
// the current config schema no longer knows the cadet provider id, so a
|
|
150
|
+
// schema parse of a migrated cloud config is no longer a valid invariant.
|
|
151
|
+
test("migrated output folds managed mode into the cadet provider", () => {
|
|
152
152
|
writeConfig({
|
|
153
153
|
services: {
|
|
154
154
|
stt: { mode: "managed", provider: "deepgram", providers: {} },
|
|
@@ -157,10 +157,12 @@ describe("130-speech-mode-to-provider", () => {
|
|
|
157
157
|
});
|
|
158
158
|
|
|
159
159
|
speechModeToProviderMigration.run(workspaceDir);
|
|
160
|
-
const parsed = AssistantConfigSchema.parse(readConfig());
|
|
161
160
|
|
|
162
|
-
expect(
|
|
163
|
-
|
|
161
|
+
expect(services(readConfig()).stt).toEqual({
|
|
162
|
+
provider: "cadet",
|
|
163
|
+
providers: {},
|
|
164
|
+
});
|
|
165
|
+
expect(services(readConfig()).tts).toEqual({ provider: "cadet" });
|
|
164
166
|
});
|
|
165
167
|
|
|
166
168
|
describe("down", () => {
|
|
@@ -9,7 +9,6 @@ import { tmpdir } from "node:os";
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
11
11
|
|
|
12
|
-
import { AssistantConfigSchema } from "../config/schema.js";
|
|
13
12
|
import { WORKSPACE_MIGRATIONS } from "../workspace/migrations/registry.js";
|
|
14
13
|
import { getLastWorkspaceMigrationId } from "../workspace/migrations/runner.js";
|
|
15
14
|
|
|
@@ -163,17 +162,18 @@ describe("132-web-search-mode-to-provider", () => {
|
|
|
163
162
|
).not.toThrow();
|
|
164
163
|
});
|
|
165
164
|
|
|
166
|
-
// The migrated shape is
|
|
167
|
-
//
|
|
168
|
-
|
|
165
|
+
// The migrated shape is frozen (the migration never reruns), asserted raw:
|
|
166
|
+
// the current config schema no longer knows the cadet provider id, so a
|
|
167
|
+
// schema parse of a migrated cloud config is no longer a valid invariant —
|
|
168
|
+
// the config loader's recovery ladder owns any on-disk 'cadet' values.
|
|
169
|
+
test("migrated output folds managed mode into the cadet provider", () => {
|
|
169
170
|
writeConfig({
|
|
170
171
|
services: { "web-search": { mode: "managed", provider: "brave" } },
|
|
171
172
|
});
|
|
172
173
|
|
|
173
174
|
webSearchModeToProviderMigration.run(workspaceDir);
|
|
174
|
-
const parsed = AssistantConfigSchema.parse(readConfig());
|
|
175
175
|
|
|
176
|
-
expect(
|
|
176
|
+
expect(webSearch(readConfig())).toEqual({ provider: "cadet" });
|
|
177
177
|
});
|
|
178
178
|
|
|
179
179
|
describe("down", () => {
|
|
@@ -1091,16 +1091,13 @@ describe("default call protocol numbered rules", () => {
|
|
|
1091
1091
|
|
|
1092
1092
|
test("a monolingual listening language becomes the pre-speech fallback", () => {
|
|
1093
1093
|
// An assistant pinned to services.stt.language = "es" on a provider that
|
|
1094
|
-
// honors the pin (deepgram
|
|
1094
|
+
// honors the pin (deepgram) is already transcribing Spanish, so
|
|
1095
1095
|
// the opener must not default to English. The default test config runs
|
|
1096
1096
|
// the auto-detect branch ("multi"), so the pinned branch is covered at
|
|
1097
1097
|
// the fragment level.
|
|
1098
1098
|
expect(preSpeechLanguageRuleFragment("es", "deepgram")).toContain(
|
|
1099
1099
|
'configured listening language ("es")',
|
|
1100
1100
|
);
|
|
1101
|
-
expect(preSpeechLanguageRuleFragment("es", "cadet")).toContain(
|
|
1102
|
-
"default to English only when neither gives a language",
|
|
1103
|
-
);
|
|
1104
1101
|
for (const autoDetect of ["multi", "", " ", undefined]) {
|
|
1105
1102
|
expect(preSpeechLanguageRuleFragment(autoDetect, "deepgram")).toBe(
|
|
1106
1103
|
"use the language the Task context implies, if any; otherwise default to English",
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
* native-vs-synthesized strategy decision stay in one implementation.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { resolveEffectiveSpeechProviders } from "../config/cloud-speech-defaults.js";
|
|
11
10
|
import { getConfig } from "../config/loader.js";
|
|
12
11
|
import {
|
|
13
12
|
getCatalogProvider,
|
|
@@ -74,13 +73,6 @@ export interface ResolveCallTtsOptions {
|
|
|
74
73
|
/**
|
|
75
74
|
* Resolve the active TTS provider via the global provider abstraction.
|
|
76
75
|
*
|
|
77
|
-
* The provider is the effective one after cloud-speech defaulting
|
|
78
|
-
* ({@link resolveEffectiveSpeechProviders}): a configured BYOK provider
|
|
79
|
-
* whose credential does not resolve is stood in for by cloud speech
|
|
80
|
-
* while the cloud connection is usable, the same substitution live
|
|
81
|
-
* voice makes, so a fresh Cadet connection speaks on the phone with zero
|
|
82
|
-
* TTS configuration.
|
|
83
|
-
*
|
|
84
76
|
* The native-vs-synthesized decision is driven by the catalog's
|
|
85
77
|
* `callMode` field via {@link resolveCallStrategy}. Providers with
|
|
86
78
|
* `callMode: "synthesized-play"` have their audio streamed through the
|
|
@@ -185,25 +177,14 @@ export async function resolveCallTtsProvider(
|
|
|
185
177
|
}
|
|
186
178
|
|
|
187
179
|
/**
|
|
188
|
-
* The TTS provider the call actually uses
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* working BYOK provider, and the outer resolver's own fallback is the
|
|
192
|
-
* silent native path.
|
|
180
|
+
* The TTS provider the call actually uses — the configured one. Kept as a
|
|
181
|
+
* named seam because the outer resolver's own fallback is the silent
|
|
182
|
+
* native path when the config has no services.tts block.
|
|
193
183
|
*/
|
|
194
|
-
|
|
184
|
+
function effectiveTtsProviderId(
|
|
195
185
|
config: ReturnType<typeof getConfig>,
|
|
196
|
-
):
|
|
197
|
-
|
|
198
|
-
const { tts } = await resolveEffectiveSpeechProviders(config);
|
|
199
|
-
return tts;
|
|
200
|
-
} catch (err) {
|
|
201
|
-
log.warn(
|
|
202
|
-
{ err },
|
|
203
|
-
"Managed-speech defaulting failed for call TTS; keeping the configured provider",
|
|
204
|
-
);
|
|
205
|
-
return undefined;
|
|
206
|
-
}
|
|
186
|
+
): TtsProviderId | undefined {
|
|
187
|
+
return config.services.tts?.provider;
|
|
207
188
|
}
|
|
208
189
|
|
|
209
190
|
/**
|
|
@@ -140,16 +140,6 @@ function ttsGap(
|
|
|
140
140
|
clause: `an API key for the text-to-speech provider "${providerId}" (no fallback provider has usable credentials)`,
|
|
141
141
|
};
|
|
142
142
|
}
|
|
143
|
-
case "missing-cloud-connection": {
|
|
144
|
-
return {
|
|
145
|
-
gap: {
|
|
146
|
-
kind: "tts",
|
|
147
|
-
providerId,
|
|
148
|
-
reason: `Managed TTS has no usable Cadet Cloud connection and no playable fallback provider is available`,
|
|
149
|
-
},
|
|
150
|
-
clause: `a Cadet Cloud connection for cloud speech (run 'assistant cloud connect'; no fallback provider has usable credentials)`,
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
143
|
case "missing-fish-audio-reference-id": {
|
|
154
144
|
return {
|
|
155
145
|
gap: {
|
|
@@ -37,8 +37,7 @@ import { resolveTtsConfig } from "../tts/tts-config-resolver.js";
|
|
|
37
37
|
export type TelephonyTtsNotPlayableReason =
|
|
38
38
|
| "unsupported-format"
|
|
39
39
|
| "missing-credentials"
|
|
40
|
-
| "missing-fish-audio-reference-id"
|
|
41
|
-
| "missing-cloud-connection";
|
|
40
|
+
| "missing-fish-audio-reference-id";
|
|
42
41
|
|
|
43
42
|
/**
|
|
44
43
|
* Result of resolving whether a TTS provider is playable over the
|
|
@@ -113,21 +112,6 @@ export async function evaluateTelephonyTtsPlayability(
|
|
|
113
112
|
}
|
|
114
113
|
}
|
|
115
114
|
|
|
116
|
-
// The cadet secret alone doesn't prove usability: cloud speech also
|
|
117
|
-
// needs the cloud assistant identity, or synthesis fails before any
|
|
118
|
-
// request is made — with allowNativeFallback false, that would mean
|
|
119
|
-
// silent call failures instead of a BYOK fallback.
|
|
120
|
-
if (entry.id === "cadet") {
|
|
121
|
-
const { managedSpeechAvailable } = await import("../cloud/cloud-speech.js");
|
|
122
|
-
if (!(await managedSpeechAvailable())) {
|
|
123
|
-
return {
|
|
124
|
-
status: "not-playable",
|
|
125
|
-
providerId: entry.id,
|
|
126
|
-
reason: "missing-cloud-connection",
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
115
|
if (entry.id === "fish-audio" && !fishAudioReferenceIdConfigured()) {
|
|
132
116
|
return {
|
|
133
117
|
status: "not-playable",
|
package/src/cli/commands/tts.ts
CHANGED
|
@@ -222,8 +222,7 @@ export function registerTtsCommand(program: Command): void {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
// Read the active TTS provider so the voice lands on the field that
|
|
225
|
-
// provider actually reads.
|
|
226
|
-
// active provider is `cadet` is a silent no-op.
|
|
225
|
+
// provider actually reads.
|
|
227
226
|
const cfg = await cliIpcCall<{
|
|
228
227
|
services?: { tts?: { provider?: string } };
|
|
229
228
|
}>("config_get");
|
package/src/cli/index.help.ts
CHANGED
|
@@ -16,7 +16,6 @@ import { attachmentHelp } from "./commands/attachment.help.js";
|
|
|
16
16
|
import { auditHelp } from "./commands/audit.help.js";
|
|
17
17
|
import { authHelp } from "./commands/auth.help.js";
|
|
18
18
|
import { avatarHelp } from "./commands/avatar.help.js";
|
|
19
|
-
import { backupHelp } from "./commands/backup.help.js";
|
|
20
19
|
import { bashHelp } from "./commands/bash.help.js";
|
|
21
20
|
import { browserHelp } from "./commands/browser.help.js";
|
|
22
21
|
import { cacheHelp } from "./commands/cache.help.js";
|
|
@@ -67,7 +66,6 @@ export const CLI_COMMAND_HELP: readonly CliCommandHelp[] = [
|
|
|
67
66
|
auditHelp,
|
|
68
67
|
authHelp,
|
|
69
68
|
avatarHelp,
|
|
70
|
-
backupHelp,
|
|
71
69
|
bashHelp,
|
|
72
70
|
browserHelp,
|
|
73
71
|
cacheHelp,
|
package/src/cli/program.ts
CHANGED
|
@@ -10,7 +10,6 @@ import { registerAttachmentCommand } from "./commands/attachment.js";
|
|
|
10
10
|
import { registerAuditCommand } from "./commands/audit.js";
|
|
11
11
|
import { registerAuthCommand } from "./commands/auth.js";
|
|
12
12
|
import { registerAvatarCommand } from "./commands/avatar.js";
|
|
13
|
-
import { registerBackupCommand } from "./commands/backup.js";
|
|
14
13
|
import { registerBashCommand } from "./commands/bash.js";
|
|
15
14
|
import { registerBrowserCommand } from "./commands/browser.js";
|
|
16
15
|
import { registerCacheCommand } from "./commands/cache.js";
|
|
@@ -108,7 +107,6 @@ Examples:
|
|
|
108
107
|
registerAuditCommand(program);
|
|
109
108
|
registerAuthCommand(program);
|
|
110
109
|
registerAvatarCommand(program);
|
|
111
|
-
registerBackupCommand(program);
|
|
112
110
|
registerBashCommand(program);
|
|
113
111
|
registerBrowserCommand(program);
|
|
114
112
|
registerCacheCommand(program);
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import { managedSpeechAvailable } from "../../../../cloud/cloud-speech.js";
|
|
2
1
|
import { normalizeActivationKey } from "../../../../daemon/handlers/config-voice.js";
|
|
3
2
|
import {
|
|
4
3
|
DEEPGRAM_MULTI_LANGUAGE_CODES,
|
|
5
4
|
DEEPGRAM_NOVA3_MONOLINGUAL_CODES,
|
|
6
5
|
} from "../../../../providers/speech-to-text/deepgram.js";
|
|
7
|
-
import {
|
|
8
|
-
isCloudSttProvider,
|
|
9
|
-
listProviderModelFamilies,
|
|
10
|
-
} from "../../../../providers/speech-to-text/provider-catalog.js";
|
|
6
|
+
import { listProviderModelFamilies } from "../../../../providers/speech-to-text/provider-catalog.js";
|
|
11
7
|
import type { SttProviderId } from "../../../../stt/types.js";
|
|
12
8
|
import { throwIfCancelled } from "../../../../tools/shared/abort.js";
|
|
13
9
|
import type {
|
|
@@ -28,7 +24,6 @@ import {
|
|
|
28
24
|
normalizeSttProviderId,
|
|
29
25
|
VALID_STT_PROVIDERS,
|
|
30
26
|
} from "../../../schemas/stt.js";
|
|
31
|
-
import { voicePickerHint } from "./shared.js";
|
|
32
27
|
|
|
33
28
|
/**
|
|
34
29
|
* Valid voice config settings and their UserDefaults key mappings.
|
|
@@ -199,19 +194,6 @@ const STT_LANGUAGE_ALIASES: Record<
|
|
|
199
194
|
"code-switching": "multi",
|
|
200
195
|
};
|
|
201
196
|
|
|
202
|
-
/**
|
|
203
|
-
* Same steer `navigate_settings_tab` puts on the Voice tab, applied to the
|
|
204
|
-
* strongest competing affordance: this tool's description coaches the model to
|
|
205
|
-
* read the cloud catalog and set `tts_voice_id` itself, which is exactly the
|
|
206
|
-
* "assistant names voices in prose" outcome the inline picker exists to
|
|
207
|
-
* replace. Managed only, because that is the catalog the picker renders. The
|
|
208
|
-
* write still happens and the result stays non-error; this only redirects the
|
|
209
|
-
* next request.
|
|
210
|
-
*/
|
|
211
|
-
const MANAGED_VOICE_PICKER_HINT = voicePickerHint(
|
|
212
|
-
"which lets them hear and pick from the cloud catalog in the conversation. Set the id here only when the user named a specific voice.",
|
|
213
|
-
);
|
|
214
|
-
|
|
215
197
|
function validateSetting(
|
|
216
198
|
setting: string,
|
|
217
199
|
value: unknown,
|
|
@@ -469,24 +451,8 @@ export async function run(
|
|
|
469
451
|
return { content: `Error: ${validation.error}`, isError: true };
|
|
470
452
|
}
|
|
471
453
|
|
|
472
|
-
//
|
|
473
|
-
//
|
|
474
|
-
// than "cadet" on a disconnected assistant persists happily and then
|
|
475
|
-
// resolves no transcriber at all.
|
|
476
|
-
const wantsCloudSpeech =
|
|
477
|
-
(setting === "stt_provider" &&
|
|
478
|
-
isCloudSttProvider(validation.coerced as SttProviderId)) ||
|
|
479
|
-
(setting === "tts_provider" && validation.coerced === "cadet");
|
|
480
|
-
if (wantsCloudSpeech && !(await managedSpeechAvailable())) {
|
|
481
|
-
return {
|
|
482
|
-
content:
|
|
483
|
-
"Error: cloud speech requires a Cadet Cloud connection. Run 'assistant cloud connect' first.",
|
|
484
|
-
isError: true,
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// Recheck: the cloud-speech reachability probe above is an await, and the
|
|
489
|
-
// client broadcast and config write below are what the user would notice.
|
|
454
|
+
// Recheck: the reachability probe above is an await, and the client
|
|
455
|
+
// broadcast and config write below are what the user would notice.
|
|
490
456
|
throwIfCancelled(context);
|
|
491
457
|
|
|
492
458
|
const meta: VoiceSettingMeta = VOICE_SETTINGS[setting as VoiceSettingName];
|
|
@@ -618,14 +584,10 @@ export async function run(
|
|
|
618
584
|
AUTO_DETECT_STT_PROVIDERS.has(activeSttProviderId)
|
|
619
585
|
? ` Note: the configured STT provider (${activeSttProviderId}) auto-detects the spoken language natively and ignores this setting.`
|
|
620
586
|
: "";
|
|
621
|
-
const pickerNote =
|
|
622
|
-
setting === "tts_voice_id" && activeTtsProviderId === "cadet"
|
|
623
|
-
? ` ${MANAGED_VOICE_PICKER_HINT}`
|
|
624
|
-
: "";
|
|
625
587
|
return {
|
|
626
588
|
content: `${friendlyName} updated to ${JSON.stringify(
|
|
627
589
|
validation.coerced,
|
|
628
|
-
)}.${broadcastNote}${autoDetectNote}
|
|
590
|
+
)}.${broadcastNote}${autoDetectNote}`,
|
|
629
591
|
isError: false,
|
|
630
592
|
};
|
|
631
593
|
}
|
|
@@ -69,9 +69,9 @@ describe("SttServiceSchema", () => {
|
|
|
69
69
|
test("language defaults to multilingual rather than staying absent", () => {
|
|
70
70
|
// Every config carries a real language, so nothing downstream has to
|
|
71
71
|
// infer one from an absent key. Omitting the param entirely is not a
|
|
72
|
-
// neutral state on Deepgram
|
|
73
|
-
//
|
|
74
|
-
const parsed = SttServiceSchema.parse({ provider: "
|
|
72
|
+
// neutral state on Deepgram: it decodes as English, which is what this
|
|
73
|
+
// default exists to stop.
|
|
74
|
+
const parsed = SttServiceSchema.parse({ provider: "deepgram" });
|
|
75
75
|
expect(parsed.language).toBe("multi");
|
|
76
76
|
});
|
|
77
77
|
|
|
@@ -86,7 +86,8 @@ describe("SttServiceSchema", () => {
|
|
|
86
86
|
|
|
87
87
|
test("language round-trips a code and the multi code-switching mode", () => {
|
|
88
88
|
expect(
|
|
89
|
-
SttServiceSchema.parse({ provider: "
|
|
89
|
+
SttServiceSchema.parse({ provider: "deepgram", language: "multi" })
|
|
90
|
+
.language,
|
|
90
91
|
).toBe("multi");
|
|
91
92
|
expect(
|
|
92
93
|
SttServiceSchema.parse({ provider: "deepgram", language: "hi" }).language,
|
|
@@ -95,30 +96,25 @@ describe("SttServiceSchema", () => {
|
|
|
95
96
|
|
|
96
97
|
test("language is trimmed and rejects blank strings", () => {
|
|
97
98
|
expect(
|
|
98
|
-
SttServiceSchema.parse({ provider: "
|
|
99
|
+
SttServiceSchema.parse({ provider: "deepgram", language: " multi " })
|
|
99
100
|
.language,
|
|
100
101
|
).toBe("multi");
|
|
101
102
|
expect(() =>
|
|
102
|
-
SttServiceSchema.parse({ provider: "
|
|
103
|
+
SttServiceSchema.parse({ provider: "deepgram", language: " " }),
|
|
103
104
|
).toThrow(/must not be empty/);
|
|
104
105
|
});
|
|
105
106
|
});
|
|
106
107
|
|
|
107
|
-
describe("
|
|
108
|
-
test("accepts cadet as an ordinary provider choice", () => {
|
|
109
|
-
const parsed = SttServiceSchema.parse({ provider: "cadet" });
|
|
110
|
-
expect(parsed.provider).toBe("cadet");
|
|
111
|
-
});
|
|
112
|
-
|
|
108
|
+
describe("provider parsing", () => {
|
|
113
109
|
// Migration 130 folds mode into provider; a stale key must not resurrect
|
|
114
110
|
// the second axis or fail the parse.
|
|
115
111
|
test("ignores a legacy mode key", () => {
|
|
116
112
|
const parsed = SttServiceSchema.parse({
|
|
117
113
|
mode: "managed",
|
|
118
|
-
provider: "
|
|
114
|
+
provider: "deepgram",
|
|
119
115
|
});
|
|
120
116
|
expect(parsed).toEqual({
|
|
121
|
-
provider: "
|
|
117
|
+
provider: "deepgram",
|
|
122
118
|
language: "multi",
|
|
123
119
|
providers: {},
|
|
124
120
|
roles: {},
|
|
@@ -71,12 +71,11 @@ const ImageGenerationServiceSchema = z.object({
|
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
|
-
* Web-search carries no `mode`: `provider` is the only axis.
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* by an older client is stripped at parse.
|
|
74
|
+
* Web-search carries no `mode`: `provider` is the only axis.
|
|
75
|
+
* `"inference-provider-native"` prefers the inference model's own hosted
|
|
76
|
+
* search, falling back to the user's own keys; any other provider uses the
|
|
77
|
+
* user's own API key. A `mode` key sent by an older client is stripped at
|
|
78
|
+
* parse.
|
|
80
79
|
*/
|
|
81
80
|
const WebSearchServiceSchema = z.object({
|
|
82
81
|
provider: z
|