chore: hide voice button when no voice backend configured (not deployed)

This commit is contained in:
2026-08-02 21:45:37 +08:00
parent 5b0cda9c01
commit fd457e0303
5 changed files with 31 additions and 17 deletions
+10 -2
View File
@@ -15,8 +15,8 @@ describe('listConfiguredVoiceBackends', () => {
expect(backends).toEqual(['elevenlabs', 'gemini-live', 'qwen-realtime'])
})
test('falls back to elevenlabs when no keys configured', () => {
expect(listConfiguredVoiceBackends({})).toEqual(['elevenlabs'])
test('returns empty when no keys configured', () => {
expect(listConfiguredVoiceBackends({})).toEqual([])
})
})
@@ -37,6 +37,10 @@ describe('resolveHubVoiceBackend', () => {
})
expect(backend).toBe('elevenlabs')
})
test('returns null when no backends configured', () => {
expect(resolveHubVoiceBackend({})).toBeNull()
})
})
describe('resolveEffectiveVoiceBackend', () => {
@@ -50,4 +54,8 @@ describe('resolveEffectiveVoiceBackend', () => {
expect(resolveEffectiveVoiceBackend(configured, 'gemini-live', null)).toBe('gemini-live')
expect(resolveEffectiveVoiceBackend(configured, 'gemini-live', 'qwen-realtime')).toBe('gemini-live')
})
test('returns null when no backends configured', () => {
expect(resolveEffectiveVoiceBackend([], null, null)).toBeNull()
})
})
+14 -8
View File
@@ -260,25 +260,31 @@ export function listConfiguredVoiceBackends(env: VoiceBackendEnv): VoiceBackendT
if (env.DASHSCOPE_API_KEY?.trim() || env.QWEN_API_KEY?.trim()) {
backends.push('qwen-realtime')
}
return backends.length > 0 ? backends : [DEFAULT_VOICE_BACKEND]
return backends
}
/** Hub default from VOICE_BACKEND when configured, else first available backend. */
export function resolveHubVoiceBackend(env: VoiceBackendEnv): VoiceBackendType {
/** Hub default from VOICE_BACKEND when configured, else first available backend. null when none configured. */
export function resolveHubVoiceBackend(env: VoiceBackendEnv): VoiceBackendType | null {
const configured = listConfiguredVoiceBackends(env)
if (configured.length === 0) {
return null
}
const raw = env.VOICE_BACKEND
const fromEnv = VOICE_BACKEND_VALUES.includes(raw as VoiceBackendType)
? (raw as VoiceBackendType)
: DEFAULT_VOICE_BACKEND
return configured.includes(fromEnv) ? fromEnv : (configured[0] ?? DEFAULT_VOICE_BACKEND)
return configured.includes(fromEnv) ? fromEnv : configured[0]!
}
/** User preference wins when valid; otherwise hub default. */
export function resolveEffectiveVoiceBackend(
configured: readonly VoiceBackendType[],
hubDefault: VoiceBackendType,
hubDefault: VoiceBackendType | null,
storedPreference: string | null | undefined
): VoiceBackendType {
): VoiceBackendType | null {
if (configured.length === 0) {
return null
}
if (
storedPreference
&& VOICE_BACKEND_VALUES.includes(storedPreference as VoiceBackendType)
@@ -286,10 +292,10 @@ export function resolveEffectiveVoiceBackend(
) {
return storedPreference as VoiceBackendType
}
if (configured.includes(hubDefault)) {
if (hubDefault && configured.includes(hubDefault)) {
return hubDefault
}
return configured[0] ?? hubDefault
return configured[0] ?? null
}
export const GEMINI_LIVE_MODEL = 'gemini-2.5-flash-native-audio-latest'