mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
fix(web): hide the voice button when no voice backend is configured (#1317)
* chore: hide voice button when no voice backend configured (not deployed) * fix(hub,web): handle unavailable voice backends via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> --------- Co-authored-by: HAPI <noreply@hapi.run>
This commit is contained in:
@@ -38,8 +38,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([])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -67,6 +67,10 @@ describe('resolveHubVoiceBackend', () => {
|
||||
})
|
||||
expect(backend).toBe('elevenlabs')
|
||||
})
|
||||
|
||||
test('returns null when no backends configured', () => {
|
||||
expect(resolveHubVoiceBackend({})).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('resolveEffectiveVoiceBackend', () => {
|
||||
@@ -80,4 +84,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
@@ -310,25 +310,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)
|
||||
@@ -336,10 +342,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'
|
||||
|
||||
Reference in New Issue
Block a user