Files
OmniRoute/tests/unit/audio-nested-model-credential-fallback.test.ts
Ravi Tharuma 6003612000 fix(audio): fall back nested STT models when the prefix provider has no credentials (#10584)
* fix(audio): fall back nested STT models when the prefix provider has no credentials

Bare ids such as deepgram/nova-3 prefix-match the native provider and 400
when that key is missing, even if OpenRouter lists the same model. Retry
the gateway and mention qualified catalog ids in the error.

Closes #10583

* test(audio): scope whisper-1 fallback test to a 2-provider registry

nanogpt was added to AUDIO_TRANSCRIPTION_PROVIDERS (already merged,
unrelated to this fix) with a bare "whisper-1" model id, which now
intercepts findAlternateAudioProvider's first candidate before the
qualified-alias branch this test exists to cover. Scope the test to a
local {openai, openrouter} registry subset so it deterministically
exercises the qualified `${provider}/${model}` fallback regardless of
future providers that also list a bare "whisper-1" id.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-08-18 10:52:48 -03:00

73 lines
2.8 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
const {
parseTranscriptionModel,
AUDIO_TRANSCRIPTION_PROVIDERS,
audioModelAliasCandidates,
findAlternateAudioProvider,
listAlternateAudioModelIds,
missingAudioProviderCredentialsMessage,
} = await import("../../open-sse/config/audioRegistry.ts");
test("parseTranscriptionModel prefix-matches native Deepgram for deepgram/nova-3", () => {
assert.deepEqual(parseTranscriptionModel("deepgram/nova-3"), {
provider: "deepgram",
model: "nova-3",
});
});
test("parseTranscriptionModel keeps OpenRouter when the id is qualified", () => {
assert.deepEqual(parseTranscriptionModel("openrouter/deepgram/nova-3"), {
provider: "openrouter",
model: "deepgram/nova-3",
});
});
test("findAlternateAudioProvider maps native Deepgram nova-3 to OpenRouter", () => {
const candidates = audioModelAliasCandidates("deepgram/nova-3", "deepgram", "nova-3");
const alternate = findAlternateAudioProvider(
AUDIO_TRANSCRIPTION_PROVIDERS,
"deepgram",
candidates
);
assert.ok(alternate);
assert.equal(alternate?.provider, "openrouter");
assert.equal(alternate?.model, "deepgram/nova-3");
});
test("findAlternateAudioProvider maps bare whisper-1 to OpenRouter when OpenAI has no creds", () => {
// Scoped to a 2-provider registry (rather than the live, growing
// AUDIO_TRANSCRIPTION_PROVIDERS) so this stays a deterministic test of the
// *qualified*-alias fallback branch (`${failedProvider}/${resolvedModel}`)
// regardless of future providers that also list a bare "whisper-1" id
// (e.g. nanogpt) and would otherwise intercept on the first candidate.
const scopedRegistry = {
openai: AUDIO_TRANSCRIPTION_PROVIDERS.openai,
openrouter: AUDIO_TRANSCRIPTION_PROVIDERS.openrouter,
};
const candidates = audioModelAliasCandidates("whisper-1", "openai", "whisper-1");
const alternate = findAlternateAudioProvider(scopedRegistry, "openai", candidates);
assert.ok(alternate);
assert.equal(alternate?.provider, "openrouter");
assert.equal(alternate?.model, "openai/whisper-1");
});
test("findAlternateAudioProvider returns null when no other provider lists the model", () => {
const alternate = findAlternateAudioProvider(AUDIO_TRANSCRIPTION_PROVIDERS, "assemblyai", [
"universal-3-pro",
"assemblyai/universal-3-pro",
]);
assert.equal(alternate, null);
});
test("missing-credential error lists qualified catalog aliases", () => {
const candidates = audioModelAliasCandidates("deepgram/nova-3", "deepgram", "nova-3");
const ids = listAlternateAudioModelIds(AUDIO_TRANSCRIPTION_PROVIDERS, "deepgram", candidates);
assert.ok(ids.includes("openrouter/deepgram/nova-3"));
assert.match(
missingAudioProviderCredentialsMessage("deepgram", ids),
/No credentials for provider: deepgram.*openrouter\/deepgram\/nova-3/
);
});