import { createDeepgramProvider, createGatewayProvider, createGroqProvider, createOpenAiProvider, createSttProviders, type SttProviderInput, type SttProviderOptions, } from './providers.ts' function assert(condition: boolean, message: string): asserts condition { if (!condition) throw new Error(message) } function assertEquals(actual: unknown, expected: unknown, message: string): void { const a = JSON.stringify(actual) const e = JSON.stringify(expected) if (a !== e) throw new Error(`${message}: expected ${e}, got ${a}`) } const INPUT: SttProviderInput = { audio: new Blob([new Uint8Array(8_000)], { type: 'audio/ogg' }), fileName: 'audio.ogg', contentType: 'audio/ogg', languageCode: 'ko', hints: { keyterms: ['D3RO'], prompt: 'D3RO' }, } const INTERNAL_URL = 'https://nas.internal.example/api/stt/internal/transcribe' function options(fetchImpl: typeof fetch, logs: Array> = []): SttProviderOptions { return { fetchImpl, logger: { warn: (_message, meta) => logs.push(meta) } } } function respond(status: number, body: unknown): typeof fetch { return () => Promise.resolve( new Response(typeof body === 'string' ? body : JSON.stringify(body), { status }), ) } Deno.test('a 2xx empty transcript is no_speech for every provider, never a failure', async () => { const cases = [ createGatewayProvider({ url: 'https://gw.example', token: 't', hasDirectFallback: true }, options(respond(200, { text: '' }))), createGroqProvider('k', options(respond(200, { text: ' ' }))), createOpenAiProvider('k', options(respond(200, { text: '' }))), createDeepgramProvider('k', options(respond(200, { results: { channels: [{ alternatives: [{ transcript: '', confidence: 0 }] }] }, }))), ] for (const provider of cases) { assertEquals(await provider.transcribe(INPUT), { kind: 'no_speech' }, `${provider.id} empty transcript`) } }) Deno.test('a 2xx transcript is normalized into an ok result', async () => { const groq = createGroqProvider('k', options(respond(200, { text: ' 안녕 ', language: 'korean', duration: 2 }))) assertEquals(await groq.transcribe(INPUT), { kind: 'ok', result: { transcript: '안녕', confidence: 0.98, language_code: 'ko', duration_seconds: 2, provider: 'groq' }, }, 'groq result') const deepgram = createDeepgramProvider('k', options(respond(200, { metadata: { duration: 3 }, results: { channels: [{ detected_language: 'en', alternatives: [{ transcript: 'hi', confidence: 0.9 }] }] }, }))) assertEquals(await deepgram.transcribe(INPUT), { kind: 'ok', result: { transcript: 'hi', confidence: 0.9, language_code: 'en', duration_seconds: 3, provider: 'deepgram' }, }, 'deepgram result') }) Deno.test('a network error leaks neither the message nor the internal gateway URL', async () => { const logs: Array> = [] const throwing: typeof fetch = () => Promise.reject(new TypeError(`error sending request for url (${INTERNAL_URL}): connection refused`)) const gateway = createGatewayProvider( { url: 'https://nas.internal.example', token: 't', hasDirectFallback: true }, options(throwing, logs), ) const outcome = await gateway.transcribe(INPUT) assertEquals(outcome, { kind: 'retryable', failure: 'network_error', billed: false, unavailable: false }, 'fixed code') assert(!JSON.stringify(outcome).includes('nas.internal'), 'internal host must not reach the outcome') assert(String(logs[0]?.message).includes('nas.internal'), 'raw message stays in the server log') }) Deno.test('timeouts, http failures and gateway 503 map to fixed codes', async () => { const timeout: typeof fetch = () => Promise.reject(new DOMException('signal timed out', 'TimeoutError')) assertEquals( await createOpenAiProvider('k', options(timeout)).transcribe(INPUT), { kind: 'retryable', failure: 'timeout', billed: false, unavailable: false }, 'timeout', ) assertEquals( await createGroqProvider('k', options(respond(429, { error: { message: 'org-SECRET' } }))).transcribe(INPUT), { kind: 'retryable', failure: 'http_429', billed: false, unavailable: false }, '429', ) const gateway = createGatewayProvider({ url: 'https://gw.example', token: 't', hasDirectFallback: false }, options(respond(503, 'down'))) assertEquals( await gateway.transcribe(INPUT), { kind: 'retryable', failure: 'http_503', billed: false, unavailable: true }, 'gateway 503 is unavailable', ) assertEquals( await createGroqProvider('k', options(respond(503, 'down'))).transcribe(INPUT), { kind: 'retryable', failure: 'http_503', billed: false, unavailable: false }, 'direct provider 503 is a failure', ) }) Deno.test('a malformed 2xx body is a billed invalid_response', async () => { for (const body of ['not json {', { nope: true }, { text: 'hi', language: 'korean', duration: 'long' }]) { assertEquals( await createOpenAiProvider('k', options(respond(200, body))).transcribe(INPUT), { kind: 'retryable', failure: 'invalid_response', billed: true, unavailable: false }, `malformed body ${JSON.stringify(body)}`, ) } }) Deno.test('a misconfigured gateway URL is reported as misconfigured without calling fetch', async () => { let called = false const gateway = createGatewayProvider( { url: 'http://public.example', token: 't', hasDirectFallback: true }, options(() => { called = true return Promise.resolve(new Response('{}')) }), ) assertEquals( await gateway.transcribe(INPUT), { kind: 'retryable', failure: 'misconfigured', billed: false, unavailable: false }, 'public http gateway rejected', ) assert(!called, 'gateway token never sent over public http') }) Deno.test('gateway uses the dedicated token header on the canonical internal URL', async () => { const seen: Array<{ url: string; headers: HeadersInit | undefined }> = [] const capture = ((url: string | URL | Request, init?: { headers?: HeadersInit }) => { seen.push({ url: String(url), headers: init?.headers }) return Promise.resolve(new Response(JSON.stringify({ text: 'hi', language: 'ko' }))) }) as typeof fetch const gateway = createGatewayProvider({ url: 'https://gw.example/ignored', token: 'gw-token', hasDirectFallback: true }, options(capture)) const outcome = await gateway.transcribe(INPUT) assertEquals(outcome.kind, 'ok', 'gateway success') assertEquals(seen, [{ url: 'https://gw.example/api/stt/internal/transcribe', headers: { 'X-D3RO-STT-Gateway-Token': 'gw-token' }, }], 'canonical URL and header, no user JWT') }) Deno.test('provider chain keeps the gateway → groq → openai → deepgram order and skips unconfigured ones', () => { const fetchImpl = respond(200, { text: 'x' }) const all = createSttProviders({ gatewayUrl: 'https://gw.example', gatewayToken: 't', groqKey: 'g', openaiKey: 'o', deepgramKey: 'd', }, options(fetchImpl)) assertEquals(all.map((p) => p.id), ['gateway', 'groq', 'openai', 'deepgram'], 'full order') const noToken = createSttProviders({ gatewayUrl: 'https://gw.example', gatewayToken: '', groqKey: '', openaiKey: 'o', deepgramKey: '', }, options(fetchImpl)) assertEquals(noToken.map((p) => p.id), ['openai'], 'gateway is skipped without its own token') })