const { test } = require('node:test'); const assert = require('node:assert/strict'); const ENV_KEYS = ['TTS_PROVIDER', 'LITELLM_API_BASE', 'LITELLM_API_KEY', 'ELEVENLABS_API_KEY', 'GOOGLE_VERTEX_PROJECT']; function withEnv(overrides, fn) { const previous = {}; ENV_KEYS.forEach((key) => { previous[key] = process.env[key]; delete process.env[key]; }); Object.entries(overrides).forEach(([key, value]) => { process.env[key] = value; }); try { return fn(); } finally { ENV_KEYS.forEach((key) => { if (previous[key] === undefined) delete process.env[key]; else process.env[key] = previous[key]; }); } } test('TTS provider defaults to LiteLLM when gateway is configured', () => { const ttsProvider = require('../src/utils/ttsProvider'); withEnv({ LITELLM_API_BASE: 'https://llm.example.com' }, () => { assert.equal(ttsProvider.getTTSEnvProvider(), 'auto'); assert.equal(ttsProvider.getTTSProvider(), 'litellm'); }); }); test('TTS provider respects explicit provider override', () => { const ttsProvider = require('../src/utils/ttsProvider'); withEnv({ TTS_PROVIDER: 'elevenlabs', LITELLM_API_BASE: 'https://llm.example.com' }, () => { assert.equal(ttsProvider.getTTSEnvProvider(), 'elevenlabs'); assert.equal(ttsProvider.getTTSProvider(), 'elevenlabs'); }); }); test('LiteLLM TTS voice list stays OpenAI-compatible', () => { const ttsProvider = require('../src/utils/ttsProvider'); assert.deepEqual(ttsProvider.getTTSVoiceLists().litellm, [ 'alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer', 'ash', 'sage', 'coral' ]); }); test('TTS model discovery keeps OpenAI speech models only', () => { const ttsProvider = require('../src/utils/ttsProvider'); assert.equal(ttsProvider.isOpenAITTSModel('openai/tts-1'), true); assert.equal(ttsProvider.isOpenAITTSModel('openai-tts-1-hd'), true); assert.equal(ttsProvider.isOpenAITTSModel('openai-gpt-4o-mini-tts'), true); assert.equal(ttsProvider.isOpenAITTSModel('mistral-voxtral-mini-tts'), false); assert.equal(ttsProvider.isOpenAITTSModel('vertex-gemini-2.5-flash-tts'), false); }); test('LiteLLM TTS model extraction filters gateway model objects', () => { const ttsProvider = require('../src/utils/ttsProvider'); assert.deepEqual(ttsProvider.getLiteLLMTTSModels([ { id: 'openai-tts-1' }, { id: 'mistral-voxtral-mini-tts' }, { id: 'openai-gpt-4o-mini-tts' }, { id: 'vertex-gemini-2.5-flash-tts' }, { id: 'gpt-4.1' } ]), ['openai-tts-1', 'openai-gpt-4o-mini-tts']); }); test('LiteLLM headers include optional content type without exposing key value', () => { const ttsProvider = require('../src/utils/ttsProvider'); withEnv({ LITELLM_API_KEY: 'secret-token' }, () => { assert.deepEqual(ttsProvider.getLiteLLMHeaders('application/json'), { 'Content-Type': 'application/json', Authorization: 'Bearer secret-token' }); }); });