@mycadet/assistant 0.12.10 → 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 +10 -10
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
- package/node_modules/@mycadet/ces-client/src/http-credentials.ts +18 -1
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
- package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
- package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
- package/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
- 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 +41 -5
- 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/llm.ts +3 -5
- 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__/conversation-query-routes.test.ts +13 -11
- package/src/runtime/routes/__tests__/tts-routes.test.ts +2 -6
- package/src/runtime/routes/conversation-query-routes.ts +0 -96
- 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
|
@@ -58,72 +58,6 @@ function seedProviderKeys(record: Record<string, string>): void {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
// -- Cadet Cloud availability mock --------------------------------------
|
|
62
|
-
|
|
63
|
-
let mockCadetAvailable = false;
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Arguments the cloud batch adapter was called with. The cloud path has
|
|
67
|
-
* no constructor to spy on (the cloud connection is the credential), so
|
|
68
|
-
* the language it forwards is observable only at the transcribe call.
|
|
69
|
-
*/
|
|
70
|
-
const cadetCloudTranscribeCalls: Array<{
|
|
71
|
-
mimeType: string;
|
|
72
|
-
language: string | undefined;
|
|
73
|
-
}> = [];
|
|
74
|
-
|
|
75
|
-
mock.module("../cadet-cloud.js", () => ({
|
|
76
|
-
cadetCloudSpeechAvailable: async () => mockCadetAvailable,
|
|
77
|
-
cadetCloudTranscribe: async (
|
|
78
|
-
_audio: Buffer,
|
|
79
|
-
mimeType: string,
|
|
80
|
-
_signal?: AbortSignal,
|
|
81
|
-
language?: string,
|
|
82
|
-
) => {
|
|
83
|
-
cadetCloudTranscribeCalls.push({ mimeType, language });
|
|
84
|
-
return { text: "" };
|
|
85
|
-
},
|
|
86
|
-
sttErrorFromCloudSpeech: (failure: unknown) => new Error(String(failure)),
|
|
87
|
-
}));
|
|
88
|
-
|
|
89
|
-
const cadetStreamCtorCalls: Array<{ connection: unknown; options: unknown }> =
|
|
90
|
-
[];
|
|
91
|
-
let mockTunnelConnection: {
|
|
92
|
-
wsBaseUrl: string;
|
|
93
|
-
httpBaseUrl: string;
|
|
94
|
-
mintServiceToken: () => string;
|
|
95
|
-
} | null = null;
|
|
96
|
-
|
|
97
|
-
mock.module("../cadet-speech-relay-connection.js", () => ({
|
|
98
|
-
resolveSpeechRelayConnection: async () => mockTunnelConnection,
|
|
99
|
-
}));
|
|
100
|
-
|
|
101
|
-
mock.module("../cadet-cloud-realtime.js", () => ({
|
|
102
|
-
CadetManagedRealtimeTranscriber: class {
|
|
103
|
-
readonly providerId = "cadet";
|
|
104
|
-
readonly boundaryId = "daemon-streaming";
|
|
105
|
-
constructor(connection: unknown, options: unknown) {
|
|
106
|
-
cadetStreamCtorCalls.push({ connection, options });
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
}));
|
|
110
|
-
|
|
111
|
-
/** Constructor calls for the cloud Flux transcriber (`cadet-flux`). */
|
|
112
|
-
const cadetFluxStreamCtorCalls: Array<{
|
|
113
|
-
connection: unknown;
|
|
114
|
-
options: unknown;
|
|
115
|
-
}> = [];
|
|
116
|
-
|
|
117
|
-
mock.module("../cadet-cloud-flux-realtime.js", () => ({
|
|
118
|
-
CadetManagedFluxRealtimeTranscriber: class {
|
|
119
|
-
readonly providerId = "cadet-flux";
|
|
120
|
-
readonly boundaryId = "daemon-streaming";
|
|
121
|
-
constructor(connection: unknown, options: unknown) {
|
|
122
|
-
cadetFluxStreamCtorCalls.push({ connection, options });
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
}));
|
|
126
|
-
|
|
127
61
|
// -- Streaming adapter mocks ----------------------------------------------
|
|
128
62
|
|
|
129
63
|
/**
|
|
@@ -212,7 +146,6 @@ mock.module("../xai-realtime.js", () => ({
|
|
|
212
146
|
const {
|
|
213
147
|
effectiveSttLanguage,
|
|
214
148
|
resolveBatchTranscriber,
|
|
215
|
-
sttCredentialGapReason,
|
|
216
149
|
resolveConversationStreamingSttCapability,
|
|
217
150
|
resolveStreamingTranscriber,
|
|
218
151
|
resolveTelephonySttCapability,
|
|
@@ -588,14 +521,11 @@ describe("telephony capability catalog alignment", () => {
|
|
|
588
521
|
/**
|
|
589
522
|
* Providers that deliberately sit out telephony (`telephonyMode: "none"`).
|
|
590
523
|
* `deepgram-flux` is a streaming-only spike, and telephony is out of its
|
|
591
|
-
* scope.
|
|
592
|
-
*
|
|
593
|
-
* nova-3 concept. Nothing reroutes a call to another provider, so opting
|
|
594
|
-
* out here means a Flux-configured assistant does not transcribe calls.
|
|
524
|
+
* scope. Nothing reroutes a call to another provider, so opting out here
|
|
525
|
+
* means a Flux-configured assistant does not transcribe calls.
|
|
595
526
|
*/
|
|
596
527
|
const TELEPHONY_OPT_OUT: ReadonlySet<SttProviderId> = new Set([
|
|
597
528
|
"deepgram-flux",
|
|
598
|
-
"cadet-flux",
|
|
599
529
|
]);
|
|
600
530
|
|
|
601
531
|
test("deepgram catalog entry has realtime-ws telephonyMode", () => {
|
|
@@ -650,7 +580,6 @@ describe("telephony capability catalog alignment", () => {
|
|
|
650
580
|
test("telephony opt-out providers resolve as unsupported", async () => {
|
|
651
581
|
for (const id of TELEPHONY_OPT_OUT) {
|
|
652
582
|
const entry = getProviderEntry(id);
|
|
653
|
-
mockCadetAvailable = false;
|
|
654
583
|
seedProviderKeys({ [entry!.credentialProvider]: `test-key-${id}` });
|
|
655
584
|
applyConfig({ provider: id });
|
|
656
585
|
|
|
@@ -681,8 +610,6 @@ describe("telephony capability catalog alignment", () => {
|
|
|
681
610
|
deepgram: "deepgram",
|
|
682
611
|
"google-gemini": "gemini",
|
|
683
612
|
xai: "xai",
|
|
684
|
-
// cadet's credential is the cloud connection, mocked below.
|
|
685
|
-
cadet: "cadet",
|
|
686
613
|
};
|
|
687
614
|
|
|
688
615
|
for (const id of listProviderIds()) {
|
|
@@ -692,8 +619,7 @@ describe("telephony capability catalog alignment", () => {
|
|
|
692
619
|
const credKey = credentialMap[id];
|
|
693
620
|
expect(credKey).toBeDefined();
|
|
694
621
|
|
|
695
|
-
|
|
696
|
-
seedProviderKeys(id === "cadet" ? {} : { [credKey]: `test-key-${id}` });
|
|
622
|
+
seedProviderKeys({ [credKey]: `test-key-${id}` });
|
|
697
623
|
applyConfig({ provider: id });
|
|
698
624
|
|
|
699
625
|
const result = await resolveTelephonySttCapability();
|
|
@@ -1125,214 +1051,12 @@ describe("resolveStreamingTranscriber diarize preference", () => {
|
|
|
1125
1051
|
});
|
|
1126
1052
|
});
|
|
1127
1053
|
|
|
1128
|
-
describe("cadet-flux managed resolution", () => {
|
|
1129
|
-
beforeEach(() => {
|
|
1130
|
-
mockCadetAvailable = false;
|
|
1131
|
-
mockTunnelConnection = {
|
|
1132
|
-
wsBaseUrl: "ws://gateway.test",
|
|
1133
|
-
httpBaseUrl: "http://gateway.test",
|
|
1134
|
-
mintServiceToken: () => "vk-test",
|
|
1135
|
-
};
|
|
1136
|
-
cadetFluxStreamCtorCalls.length = 0;
|
|
1137
|
-
});
|
|
1138
|
-
|
|
1139
|
-
test("streaming resolver constructs the cloud Flux adapter over the same relay connection", async () => {
|
|
1140
|
-
mockCadetAvailable = true;
|
|
1141
|
-
applyConfig({ provider: "cadet-flux", language: "es" });
|
|
1142
|
-
|
|
1143
|
-
const transcriber = await resolveStreamingTranscriber({
|
|
1144
|
-
sampleRate: 16000,
|
|
1145
|
-
});
|
|
1146
|
-
|
|
1147
|
-
expect(transcriber?.providerId).toBe("cadet-flux");
|
|
1148
|
-
expect(cadetFluxStreamCtorCalls).toEqual([
|
|
1149
|
-
{
|
|
1150
|
-
connection: mockTunnelConnection,
|
|
1151
|
-
// The relay picks flux-general-en vs flux-general-multi from the
|
|
1152
|
-
// language, so forwarding it is the only lever over the model.
|
|
1153
|
-
options: { sampleRate: 16000, language: "es" },
|
|
1154
|
-
},
|
|
1155
|
-
]);
|
|
1156
|
-
});
|
|
1157
|
-
|
|
1158
|
-
test("an unset language reaches the relay as code-switching, not English", async () => {
|
|
1159
|
-
// The relay resolves an absent language to flux-general-en, so unset
|
|
1160
|
-
// would be a silent English pin on non-English speech.
|
|
1161
|
-
mockCadetAvailable = true;
|
|
1162
|
-
applyConfig({ provider: "cadet-flux" });
|
|
1163
|
-
|
|
1164
|
-
await resolveStreamingTranscriber({ sampleRate: 16000 });
|
|
1165
|
-
|
|
1166
|
-
expect(
|
|
1167
|
-
(cadetFluxStreamCtorCalls[0]?.options as { language?: string })?.language,
|
|
1168
|
-
).toBe("multi");
|
|
1169
|
-
});
|
|
1170
|
-
|
|
1171
|
-
test("resolves null without a cloud connection", async () => {
|
|
1172
|
-
// The credential is the cloud connection, not a stored API key.
|
|
1173
|
-
mockCadetAvailable = false;
|
|
1174
|
-
applyConfig({ provider: "cadet-flux" });
|
|
1175
|
-
|
|
1176
|
-
expect(await resolveStreamingTranscriber({ sampleRate: 16000 })).toBeNull();
|
|
1177
|
-
expect(cadetFluxStreamCtorCalls).toHaveLength(0);
|
|
1178
|
-
});
|
|
1179
|
-
|
|
1180
|
-
test("has no batch boundary, like BYOK Flux", async () => {
|
|
1181
|
-
mockCadetAvailable = true;
|
|
1182
|
-
applyConfig({ provider: "cadet-flux" });
|
|
1183
|
-
|
|
1184
|
-
await expect(resolveBatchTranscriber()).rejects.toThrow(SttError);
|
|
1185
|
-
});
|
|
1186
|
-
|
|
1187
|
-
test("refuses a language Flux has no model for, like BYOK Flux", async () => {
|
|
1188
|
-
// The relay rejects the dial for a language outside Flux's roster, which
|
|
1189
|
-
// reaches the caller as an unexplained param error. Refusing here names
|
|
1190
|
-
// the reason where it can be read.
|
|
1191
|
-
mockCadetAvailable = true;
|
|
1192
|
-
applyConfig({ provider: "cadet-flux", language: "ko" });
|
|
1193
|
-
|
|
1194
|
-
expect(await resolveStreamingTranscriber({ sampleRate: 16000 })).toBeNull();
|
|
1195
|
-
expect(cadetFluxStreamCtorCalls).toHaveLength(0);
|
|
1196
|
-
});
|
|
1197
|
-
|
|
1198
|
-
test("serves a language that is on the Flux roster", async () => {
|
|
1199
|
-
mockCadetAvailable = true;
|
|
1200
|
-
applyConfig({ provider: "cadet-flux", language: "hi" });
|
|
1201
|
-
|
|
1202
|
-
const transcriber = await resolveStreamingTranscriber({
|
|
1203
|
-
sampleRate: 16000,
|
|
1204
|
-
});
|
|
1205
|
-
|
|
1206
|
-
expect(transcriber?.providerId).toBe("cadet-flux");
|
|
1207
|
-
});
|
|
1208
|
-
});
|
|
1209
|
-
|
|
1210
|
-
describe("cadet managed resolution", () => {
|
|
1211
|
-
beforeEach(() => {
|
|
1212
|
-
mockCadetAvailable = false;
|
|
1213
|
-
mockTunnelConnection = null;
|
|
1214
|
-
cadetStreamCtorCalls.length = 0;
|
|
1215
|
-
});
|
|
1216
|
-
|
|
1217
|
-
test("the cadet provider resolves the batch transcriber when the cloud connection exists", async () => {
|
|
1218
|
-
mockCadetAvailable = true;
|
|
1219
|
-
applyConfig({ provider: "cadet" });
|
|
1220
|
-
|
|
1221
|
-
const transcriber = await resolveBatchTranscriber();
|
|
1222
|
-
expect(transcriber?.providerId).toBe("cadet");
|
|
1223
|
-
});
|
|
1224
|
-
|
|
1225
|
-
test("the cadet provider resolves null without a cloud connection", async () => {
|
|
1226
|
-
mockCadetAvailable = false;
|
|
1227
|
-
applyConfig({ provider: "cadet" });
|
|
1228
|
-
|
|
1229
|
-
expect(await resolveBatchTranscriber()).toBeNull();
|
|
1230
|
-
});
|
|
1231
|
-
|
|
1232
|
-
test("the cadet provider wins over a stored BYOK key", async () => {
|
|
1233
|
-
mockCadetAvailable = true;
|
|
1234
|
-
seedProviderKeys({ deepgram: "dg-key" });
|
|
1235
|
-
applyConfig({ provider: "cadet" });
|
|
1236
|
-
|
|
1237
|
-
const capability = await resolveConversationStreamingSttCapability();
|
|
1238
|
-
expect(capability.status).toBe("supported");
|
|
1239
|
-
if (capability.status === "supported") {
|
|
1240
|
-
expect(capability.providerId).toBe("cadet");
|
|
1241
|
-
expect(capability.streamingMode).toBe("realtime-ws");
|
|
1242
|
-
}
|
|
1243
|
-
});
|
|
1244
|
-
|
|
1245
|
-
test("streaming resolver constructs the cadet adapter with the tunnel connection and sample rate", async () => {
|
|
1246
|
-
mockCadetAvailable = true;
|
|
1247
|
-
mockTunnelConnection = {
|
|
1248
|
-
wsBaseUrl: "ws://gateway.test",
|
|
1249
|
-
httpBaseUrl: "http://gateway.test",
|
|
1250
|
-
mintServiceToken: () => "vk-test",
|
|
1251
|
-
};
|
|
1252
|
-
applyConfig({ provider: "cadet" });
|
|
1253
|
-
|
|
1254
|
-
const transcriber = await resolveStreamingTranscriber({
|
|
1255
|
-
sampleRate: 24000,
|
|
1256
|
-
});
|
|
1257
|
-
expect(transcriber?.providerId).toBe("cadet");
|
|
1258
|
-
expect(cadetStreamCtorCalls).toEqual([
|
|
1259
|
-
{
|
|
1260
|
-
connection: mockTunnelConnection,
|
|
1261
|
-
// No language is configured here, so the cloud default rides along
|
|
1262
|
-
// with the connection plumbing this test is about.
|
|
1263
|
-
options: { sampleRate: 24000, language: "multi" },
|
|
1264
|
-
},
|
|
1265
|
-
]);
|
|
1266
|
-
});
|
|
1267
|
-
|
|
1268
|
-
test("streaming resolver returns null when the cloud connection is unavailable", async () => {
|
|
1269
|
-
mockCadetAvailable = false;
|
|
1270
|
-
mockTunnelConnection = {
|
|
1271
|
-
wsBaseUrl: "ws://gateway.test",
|
|
1272
|
-
httpBaseUrl: "http://gateway.test",
|
|
1273
|
-
mintServiceToken: () => "vk-test",
|
|
1274
|
-
};
|
|
1275
|
-
applyConfig({ provider: "cadet" });
|
|
1276
|
-
|
|
1277
|
-
expect(await resolveStreamingTranscriber({ sampleRate: 16000 })).toBeNull();
|
|
1278
|
-
expect(cadetStreamCtorCalls).toHaveLength(0);
|
|
1279
|
-
});
|
|
1280
|
-
|
|
1281
|
-
test("streaming resolver returns null when the tunnel connection is missing", async () => {
|
|
1282
|
-
mockCadetAvailable = true;
|
|
1283
|
-
mockTunnelConnection = null;
|
|
1284
|
-
applyConfig({ provider: "cadet" });
|
|
1285
|
-
|
|
1286
|
-
expect(await resolveStreamingTranscriber({ sampleRate: 16000 })).toBeNull();
|
|
1287
|
-
expect(cadetStreamCtorCalls).toHaveLength(0);
|
|
1288
|
-
});
|
|
1289
|
-
|
|
1290
|
-
test("conversation streaming capability reports missing credentials without a connection", async () => {
|
|
1291
|
-
mockCadetAvailable = false;
|
|
1292
|
-
applyConfig({ provider: "cadet" });
|
|
1293
|
-
|
|
1294
|
-
const capability = await resolveConversationStreamingSttCapability();
|
|
1295
|
-
expect(capability.status).toBe("missing-credentials");
|
|
1296
|
-
if (capability.status === "missing-credentials") {
|
|
1297
|
-
// Connection-based gap copy: the fix is connecting the account,
|
|
1298
|
-
// not entering an API key.
|
|
1299
|
-
expect(capability.reason).toContain("cloud connect");
|
|
1300
|
-
expect(capability.reason).not.toContain("API key");
|
|
1301
|
-
}
|
|
1302
|
-
});
|
|
1303
|
-
});
|
|
1304
|
-
|
|
1305
1054
|
describe("resolveStreamingTranscriber language plumbing", () => {
|
|
1306
1055
|
beforeEach(() => {
|
|
1307
|
-
mockCadetAvailable = false;
|
|
1308
|
-
mockTunnelConnection = null;
|
|
1309
1056
|
deepgramCtorCalls.length = 0;
|
|
1310
1057
|
geminiCtorCalls.length = 0;
|
|
1311
1058
|
whisperCtorCalls.length = 0;
|
|
1312
1059
|
xaiCtorCalls.length = 0;
|
|
1313
|
-
cadetStreamCtorCalls.length = 0;
|
|
1314
|
-
});
|
|
1315
|
-
|
|
1316
|
-
test("managed sessions forward services.stt.language to the relay adapter", async () => {
|
|
1317
|
-
// The cloud path is why this plumbing exists: tunnel allowlists
|
|
1318
|
-
// `language` and pins nova-3, so "multi" reaches Deepgram's
|
|
1319
|
-
// code-switching mode without any platform-side change.
|
|
1320
|
-
mockCadetAvailable = true;
|
|
1321
|
-
mockTunnelConnection = {
|
|
1322
|
-
wsBaseUrl: "ws://gateway.test",
|
|
1323
|
-
httpBaseUrl: "http://gateway.test",
|
|
1324
|
-
mintServiceToken: () => "vk-test",
|
|
1325
|
-
};
|
|
1326
|
-
applyConfig({ provider: "cadet", language: "multi" });
|
|
1327
|
-
|
|
1328
|
-
await resolveStreamingTranscriber({ sampleRate: 24000 });
|
|
1329
|
-
|
|
1330
|
-
expect(cadetStreamCtorCalls).toEqual([
|
|
1331
|
-
{
|
|
1332
|
-
connection: mockTunnelConnection,
|
|
1333
|
-
options: { sampleRate: 24000, language: "multi" },
|
|
1334
|
-
},
|
|
1335
|
-
]);
|
|
1336
1060
|
});
|
|
1337
1061
|
|
|
1338
1062
|
test("BYOK Deepgram sessions with 'multi' pin nova-3 alongside the language", async () => {
|
|
@@ -1410,27 +1134,6 @@ describe("resolveStreamingTranscriber language plumbing", () => {
|
|
|
1410
1134
|
});
|
|
1411
1135
|
});
|
|
1412
1136
|
|
|
1413
|
-
test("no configured language falls to multilingual on the cloud relay", async () => {
|
|
1414
|
-
// The relay dials Deepgram server-side, so it inherits the same English
|
|
1415
|
-
// default and needs the same fill-in.
|
|
1416
|
-
mockCadetAvailable = true;
|
|
1417
|
-
mockTunnelConnection = {
|
|
1418
|
-
wsBaseUrl: "ws://gateway.test",
|
|
1419
|
-
httpBaseUrl: "http://gateway.test",
|
|
1420
|
-
mintServiceToken: () => "vk-test",
|
|
1421
|
-
};
|
|
1422
|
-
applyConfig({ provider: "cadet" });
|
|
1423
|
-
|
|
1424
|
-
await resolveStreamingTranscriber({ sampleRate: 24000 });
|
|
1425
|
-
|
|
1426
|
-
expect(cadetStreamCtorCalls).toEqual([
|
|
1427
|
-
{
|
|
1428
|
-
connection: mockTunnelConnection,
|
|
1429
|
-
options: { sampleRate: 24000, language: "multi" },
|
|
1430
|
-
},
|
|
1431
|
-
]);
|
|
1432
|
-
});
|
|
1433
|
-
|
|
1434
1137
|
test("an explicitly configured language still wins over the default", async () => {
|
|
1435
1138
|
// The default only fills the unset case: someone who picked Tamil (off
|
|
1436
1139
|
// the code-switching roster entirely) must keep it.
|
|
@@ -1521,40 +1224,6 @@ describe("resolveStreamingTranscriber language plumbing", () => {
|
|
|
1521
1224
|
});
|
|
1522
1225
|
});
|
|
1523
1226
|
|
|
1524
|
-
test("managed batch forwards the configured language to the cloud", async () => {
|
|
1525
|
-
// The cloud proxy passes it to Deepgram server-side, so a cloud
|
|
1526
|
-
// voice note decodes in the same language the live session does.
|
|
1527
|
-
cadetCloudTranscribeCalls.length = 0;
|
|
1528
|
-
mockCadetAvailable = true;
|
|
1529
|
-
applyConfig({ provider: "cadet", language: "ta" });
|
|
1530
|
-
|
|
1531
|
-
const transcriber = await resolveBatchTranscriber();
|
|
1532
|
-
await transcriber!.transcribe({
|
|
1533
|
-
audio: Buffer.from("fake-audio"),
|
|
1534
|
-
mimeType: "audio/ogg",
|
|
1535
|
-
});
|
|
1536
|
-
|
|
1537
|
-
expect(cadetCloudTranscribeCalls).toHaveLength(1);
|
|
1538
|
-
expect(cadetCloudTranscribeCalls[0]?.language).toBe("ta");
|
|
1539
|
-
});
|
|
1540
|
-
|
|
1541
|
-
test("managed batch falls to multilingual when no language is configured", async () => {
|
|
1542
|
-
// The gap this closes: cloud voice notes used to decode as English no
|
|
1543
|
-
// matter what the user had chosen, because nothing was forwarded.
|
|
1544
|
-
cadetCloudTranscribeCalls.length = 0;
|
|
1545
|
-
mockCadetAvailable = true;
|
|
1546
|
-
applyConfig({ provider: "cadet" });
|
|
1547
|
-
|
|
1548
|
-
const transcriber = await resolveBatchTranscriber();
|
|
1549
|
-
await transcriber!.transcribe({
|
|
1550
|
-
audio: Buffer.from("fake-audio"),
|
|
1551
|
-
mimeType: "audio/ogg",
|
|
1552
|
-
});
|
|
1553
|
-
|
|
1554
|
-
expect(cadetCloudTranscribeCalls).toHaveLength(1);
|
|
1555
|
-
expect(cadetCloudTranscribeCalls[0]?.language).toBe("multi");
|
|
1556
|
-
});
|
|
1557
|
-
|
|
1558
1227
|
test("batch resolution falls to multilingual when no language is configured", async () => {
|
|
1559
1228
|
// Dictation and voice notes ride the batch path, and they read the same
|
|
1560
1229
|
// config the live session does. A user whose spoken language works in
|
|
@@ -1609,10 +1278,6 @@ describe("streaming capability matches the streaming factory", () => {
|
|
|
1609
1278
|
"google-gemini": "gemini",
|
|
1610
1279
|
"openai-whisper": "openai",
|
|
1611
1280
|
xai: "xai",
|
|
1612
|
-
// cadet's credential is the cloud connection, mocked below.
|
|
1613
|
-
cadet: "cadet",
|
|
1614
|
-
// Cloud Flux rides the same platform connection.
|
|
1615
|
-
"cadet-flux": "cadet",
|
|
1616
1281
|
};
|
|
1617
1282
|
|
|
1618
1283
|
/** The exact list both user-facing error strings advertise. */
|
|
@@ -1625,24 +1290,11 @@ describe("streaming capability matches the streaming factory", () => {
|
|
|
1625
1290
|
function seedCredentialsFor(id: SttProviderId): void {
|
|
1626
1291
|
const credential = STREAMING_CREDENTIAL[id];
|
|
1627
1292
|
expect(credential).toBeDefined();
|
|
1628
|
-
|
|
1629
|
-
// than a stored API key, and both dial through the same relay.
|
|
1630
|
-
const managed = id === "cadet" || id === "cadet-flux";
|
|
1631
|
-
mockCadetAvailable = managed;
|
|
1632
|
-
mockTunnelConnection = managed
|
|
1633
|
-
? {
|
|
1634
|
-
wsBaseUrl: "ws://gateway.test",
|
|
1635
|
-
httpBaseUrl: "http://gateway.test",
|
|
1636
|
-
mintServiceToken: () => "vk-test",
|
|
1637
|
-
}
|
|
1638
|
-
: null;
|
|
1639
|
-
seedProviderKeys(managed ? {} : { [credential!]: `key-${id}` });
|
|
1293
|
+
seedProviderKeys({ [credential!]: `key-${id}` });
|
|
1640
1294
|
applyConfig({ provider: id });
|
|
1641
1295
|
}
|
|
1642
1296
|
|
|
1643
1297
|
beforeEach(() => {
|
|
1644
|
-
mockCadetAvailable = false;
|
|
1645
|
-
mockTunnelConnection = null;
|
|
1646
1298
|
loggerWarnings.length = 0;
|
|
1647
1299
|
});
|
|
1648
1300
|
|
|
@@ -1668,8 +1320,6 @@ describe("streaming capability matches the streaming factory", () => {
|
|
|
1668
1320
|
test("every advertised provider reports missing credentials AND builds nothing without them", async () => {
|
|
1669
1321
|
for (const id of advertisedStreamingProviders()) {
|
|
1670
1322
|
secureKeys.clear(); // the supported-loop above seeded these same providers
|
|
1671
|
-
mockCadetAvailable = false;
|
|
1672
|
-
mockTunnelConnection = null;
|
|
1673
1323
|
applyConfig({ provider: id });
|
|
1674
1324
|
|
|
1675
1325
|
const capability = await resolveConversationStreamingSttCapability();
|
|
@@ -1685,8 +1335,6 @@ describe("streaming capability matches the streaming factory", () => {
|
|
|
1685
1335
|
|
|
1686
1336
|
describe("deepgram-flux streaming resolution", () => {
|
|
1687
1337
|
beforeEach(() => {
|
|
1688
|
-
mockCadetAvailable = false;
|
|
1689
|
-
mockTunnelConnection = null;
|
|
1690
1338
|
loggerWarnings.length = 0;
|
|
1691
1339
|
});
|
|
1692
1340
|
|
|
@@ -1770,8 +1418,6 @@ describe("deepgram-flux streaming resolution", () => {
|
|
|
1770
1418
|
|
|
1771
1419
|
describe("deepgram-flux batch resolution", () => {
|
|
1772
1420
|
beforeEach(() => {
|
|
1773
|
-
mockCadetAvailable = false;
|
|
1774
|
-
mockTunnelConnection = null;
|
|
1775
1421
|
loggerWarnings.length = 0;
|
|
1776
1422
|
});
|
|
1777
1423
|
|
|
@@ -1822,20 +1468,11 @@ describe("deepgram-flux batch resolution", () => {
|
|
|
1822
1468
|
});
|
|
1823
1469
|
});
|
|
1824
1470
|
|
|
1825
|
-
describe("sttCredentialGapReason", () => {
|
|
1826
|
-
test("cadet gets connection copy; API-key providers keep key copy", () => {
|
|
1827
|
-
expect(sttCredentialGapReason("cadet")).toContain("cloud connect");
|
|
1828
|
-
expect(sttCredentialGapReason("cadet")).not.toContain("API key");
|
|
1829
|
-
expect(sttCredentialGapReason("deepgram")).toContain("API key");
|
|
1830
|
-
});
|
|
1831
|
-
});
|
|
1832
|
-
|
|
1833
1471
|
describe("effectiveSttLanguage", () => {
|
|
1834
1472
|
test("fills the unset case only where unset would mean English", () => {
|
|
1835
|
-
// Deepgram
|
|
1836
|
-
//
|
|
1473
|
+
// Deepgram decodes language-less audio as English, so leaving it unset
|
|
1474
|
+
// is a silent pin rather than a neutral state.
|
|
1837
1475
|
expect(effectiveSttLanguage("deepgram", undefined)).toBe("multi");
|
|
1838
|
-
expect(effectiveSttLanguage("cadet", undefined)).toBe("multi");
|
|
1839
1476
|
// Everyone else detects natively from the audio; filling in a ten-language
|
|
1840
1477
|
// roster would narrow what they can already do.
|
|
1841
1478
|
expect(effectiveSttLanguage("xai", undefined)).toBeUndefined();
|
|
@@ -1847,7 +1484,6 @@ describe("effectiveSttLanguage", () => {
|
|
|
1847
1484
|
// The default decides what happens when nobody has chosen, nothing more.
|
|
1848
1485
|
expect(effectiveSttLanguage("deepgram", "ta")).toBe("ta");
|
|
1849
1486
|
expect(effectiveSttLanguage("deepgram", "en")).toBe("en");
|
|
1850
|
-
expect(effectiveSttLanguage("cadet", "multi")).toBe("multi");
|
|
1851
1487
|
expect(effectiveSttLanguage("xai", "hi")).toBe("hi");
|
|
1852
1488
|
});
|
|
1853
1489
|
});
|
|
@@ -1881,8 +1517,6 @@ describe("the multilingual default reaches configs with no stt block", () => {
|
|
|
1881
1517
|
|
|
1882
1518
|
describe("services.stt.roles selection", () => {
|
|
1883
1519
|
beforeEach(() => {
|
|
1884
|
-
mockCadetAvailable = false;
|
|
1885
|
-
mockTunnelConnection = null;
|
|
1886
1520
|
seedProviderKeys({ deepgram: "dg-key", openai: "oai-key" });
|
|
1887
1521
|
deepgramCtorCalls.length = 0;
|
|
1888
1522
|
whisperCtorCalls.length = 0;
|
|
@@ -222,9 +222,8 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
|
|
|
222
222
|
supportsDiarization: false,
|
|
223
223
|
// "no picker", not native detection: this entry pins the English Flux
|
|
224
224
|
// model and sends no language parameter, so audio in another language
|
|
225
|
-
// transcribes as English. Flux itself has a multilingual model;
|
|
226
|
-
//
|
|
227
|
-
// the model to follow the selection.
|
|
225
|
+
// transcribes as English. Flux itself has a multilingual model; a BYOK
|
|
226
|
+
// picker would need the model to follow the selection.
|
|
228
227
|
languageSelection: "auto",
|
|
229
228
|
credentialsGuide: DEEPGRAM_CREDENTIALS_GUIDE,
|
|
230
229
|
},
|
|
@@ -284,64 +283,6 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
|
|
|
284
283
|
},
|
|
285
284
|
},
|
|
286
285
|
],
|
|
287
|
-
[
|
|
288
|
-
"cadet",
|
|
289
|
-
{
|
|
290
|
-
id: "cadet",
|
|
291
|
-
baseModelFamily: "nova-3",
|
|
292
|
-
displayName: "Cadet",
|
|
293
|
-
subtitle:
|
|
294
|
-
"Speech-to-text through your Cadet account — billed to Cadet credits, no separate API key needed.",
|
|
295
|
-
setupMode: "connection",
|
|
296
|
-
setupHint: "Connect your Cadet account to enable managed transcription.",
|
|
297
|
-
// Legacy credential-service key (persisted identity rows).
|
|
298
|
-
credentialProvider: "cadet",
|
|
299
|
-
supportedBoundaries: new Set<SttBoundaryId>([
|
|
300
|
-
"daemon-batch",
|
|
301
|
-
"daemon-streaming",
|
|
302
|
-
]),
|
|
303
|
-
telephonyMode: "realtime-ws",
|
|
304
|
-
conversationStreamingMode: "realtime-ws",
|
|
305
|
-
turnDetection: "none",
|
|
306
|
-
supportsDiarization: false,
|
|
307
|
-
// The relay dials Deepgram nova-3 server-side, which takes an explicit
|
|
308
|
-
// language parameter.
|
|
309
|
-
languageSelection: "manual",
|
|
310
|
-
},
|
|
311
|
-
],
|
|
312
|
-
[
|
|
313
|
-
"cadet-flux",
|
|
314
|
-
{
|
|
315
|
-
id: "cadet-flux",
|
|
316
|
-
variantOf: "cadet",
|
|
317
|
-
variantModel: "flux",
|
|
318
|
-
displayName: "Cadet (Flux)",
|
|
319
|
-
subtitle:
|
|
320
|
-
"Conversational speech-to-text with model-native turn detection, through your Cadet account. No separate API key needed.",
|
|
321
|
-
setupMode: "connection",
|
|
322
|
-
setupHint: "Connect your Cadet account to enable managed transcription.",
|
|
323
|
-
// Shared with `cadet`: the cloud connection is the credential, and
|
|
324
|
-
// Flux is a different endpoint on the same relay, not a second account.
|
|
325
|
-
credentialProvider: "cadet",
|
|
326
|
-
// Streaming only, same as the BYOK Flux entry: Flux has no batch
|
|
327
|
-
// endpoint, and the relay exposes none.
|
|
328
|
-
supportedBoundaries: new Set<SttBoundaryId>(["daemon-streaming"]),
|
|
329
|
-
// The relay maps `Finalize` onto Flux's `CloseStream`, which ends the
|
|
330
|
-
// session rather than flushing it, and telephony's utterance-boundary
|
|
331
|
-
// finals are a nova-3 concept. Calls stay on `cadet`.
|
|
332
|
-
telephonyMode: "none",
|
|
333
|
-
conversationStreamingMode: "realtime-ws",
|
|
334
|
-
// The relay is dialed with `contract=flux`, so Flux's turn lifecycle
|
|
335
|
-
// events arrive intact and a live-voice session may let them commit
|
|
336
|
-
// the turn. Without that opt-in the relay translates them away and
|
|
337
|
-
// this would be false.
|
|
338
|
-
turnDetection: "provider",
|
|
339
|
-
supportsDiarization: false,
|
|
340
|
-
// The relay selects `flux-general-en` or `flux-general-multi` from the
|
|
341
|
-
// language it is sent, so unlike BYOK Flux the picker is meaningful.
|
|
342
|
-
languageSelection: "manual",
|
|
343
|
-
},
|
|
344
|
-
],
|
|
345
286
|
[
|
|
346
287
|
"xai",
|
|
347
288
|
{
|
|
@@ -499,18 +440,6 @@ export function supportsDiarization(id: SttProviderId): boolean {
|
|
|
499
440
|
* provider, so a new turn-detecting provider is a catalog entry rather than a
|
|
500
441
|
* session change.
|
|
501
442
|
*/
|
|
502
|
-
/**
|
|
503
|
-
* Whether a provider authenticates with the Cadet Cloud connection rather
|
|
504
|
-
* than a stored API key.
|
|
505
|
-
*
|
|
506
|
-
* Derived from the catalog rather than a hand-kept id list: every check that
|
|
507
|
-
* gates cloud speech reads this, so adding a cloud provider cannot leave
|
|
508
|
-
* one of them behind on a stale literal.
|
|
509
|
-
*/
|
|
510
|
-
export function isCloudSttProvider(id: SttProviderId): boolean {
|
|
511
|
-
return CATALOG.get(id)?.credentialProvider === "cadet";
|
|
512
|
-
}
|
|
513
|
-
|
|
514
443
|
/**
|
|
515
444
|
* The catalog row a configured provider plus model family resolves to.
|
|
516
445
|
*
|