mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
chore: hide voice button when no voice backend configured (not deployed)
This commit is contained in:
@@ -15,8 +15,8 @@ describe('listConfiguredVoiceBackends', () => {
|
|||||||
expect(backends).toEqual(['elevenlabs', 'gemini-live', 'qwen-realtime'])
|
expect(backends).toEqual(['elevenlabs', 'gemini-live', 'qwen-realtime'])
|
||||||
})
|
})
|
||||||
|
|
||||||
test('falls back to elevenlabs when no keys configured', () => {
|
test('returns empty when no keys configured', () => {
|
||||||
expect(listConfiguredVoiceBackends({})).toEqual(['elevenlabs'])
|
expect(listConfiguredVoiceBackends({})).toEqual([])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -37,6 +37,10 @@ describe('resolveHubVoiceBackend', () => {
|
|||||||
})
|
})
|
||||||
expect(backend).toBe('elevenlabs')
|
expect(backend).toBe('elevenlabs')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('returns null when no backends configured', () => {
|
||||||
|
expect(resolveHubVoiceBackend({})).toBeNull()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('resolveEffectiveVoiceBackend', () => {
|
describe('resolveEffectiveVoiceBackend', () => {
|
||||||
@@ -50,4 +54,8 @@ describe('resolveEffectiveVoiceBackend', () => {
|
|||||||
expect(resolveEffectiveVoiceBackend(configured, 'gemini-live', null)).toBe('gemini-live')
|
expect(resolveEffectiveVoiceBackend(configured, 'gemini-live', null)).toBe('gemini-live')
|
||||||
expect(resolveEffectiveVoiceBackend(configured, 'gemini-live', 'qwen-realtime')).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
@@ -260,25 +260,31 @@ export function listConfiguredVoiceBackends(env: VoiceBackendEnv): VoiceBackendT
|
|||||||
if (env.DASHSCOPE_API_KEY?.trim() || env.QWEN_API_KEY?.trim()) {
|
if (env.DASHSCOPE_API_KEY?.trim() || env.QWEN_API_KEY?.trim()) {
|
||||||
backends.push('qwen-realtime')
|
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. */
|
/** Hub default from VOICE_BACKEND when configured, else first available backend. null when none configured. */
|
||||||
export function resolveHubVoiceBackend(env: VoiceBackendEnv): VoiceBackendType {
|
export function resolveHubVoiceBackend(env: VoiceBackendEnv): VoiceBackendType | null {
|
||||||
const configured = listConfiguredVoiceBackends(env)
|
const configured = listConfiguredVoiceBackends(env)
|
||||||
|
if (configured.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
const raw = env.VOICE_BACKEND
|
const raw = env.VOICE_BACKEND
|
||||||
const fromEnv = VOICE_BACKEND_VALUES.includes(raw as VoiceBackendType)
|
const fromEnv = VOICE_BACKEND_VALUES.includes(raw as VoiceBackendType)
|
||||||
? (raw as VoiceBackendType)
|
? (raw as VoiceBackendType)
|
||||||
: DEFAULT_VOICE_BACKEND
|
: 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. */
|
/** User preference wins when valid; otherwise hub default. */
|
||||||
export function resolveEffectiveVoiceBackend(
|
export function resolveEffectiveVoiceBackend(
|
||||||
configured: readonly VoiceBackendType[],
|
configured: readonly VoiceBackendType[],
|
||||||
hubDefault: VoiceBackendType,
|
hubDefault: VoiceBackendType | null,
|
||||||
storedPreference: string | null | undefined
|
storedPreference: string | null | undefined
|
||||||
): VoiceBackendType {
|
): VoiceBackendType | null {
|
||||||
|
if (configured.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
storedPreference
|
storedPreference
|
||||||
&& VOICE_BACKEND_VALUES.includes(storedPreference as VoiceBackendType)
|
&& VOICE_BACKEND_VALUES.includes(storedPreference as VoiceBackendType)
|
||||||
@@ -286,10 +292,10 @@ export function resolveEffectiveVoiceBackend(
|
|||||||
) {
|
) {
|
||||||
return storedPreference as VoiceBackendType
|
return storedPreference as VoiceBackendType
|
||||||
}
|
}
|
||||||
if (configured.includes(hubDefault)) {
|
if (hubDefault && configured.includes(hubDefault)) {
|
||||||
return hubDefault
|
return hubDefault
|
||||||
}
|
}
|
||||||
return configured[0] ?? hubDefault
|
return configured[0] ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GEMINI_LIVE_MODEL = 'gemini-2.5-flash-native-audio-latest'
|
export const GEMINI_LIVE_MODEL = 'gemini-2.5-flash-native-audio-latest'
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ export async function fetchQwenToken(api: ApiClient): Promise<QwenTokenResponse>
|
|||||||
|
|
||||||
export interface VoiceBackendResponse {
|
export interface VoiceBackendResponse {
|
||||||
/** Hub default (VOICE_BACKEND env, validated against configured backends). */
|
/** Hub default (VOICE_BACKEND env, validated against configured backends). */
|
||||||
backend: VoiceBackendType
|
backend: VoiceBackendType | null
|
||||||
/** Backends with API keys configured on the hub. */
|
/** Backends with API keys configured on the hub. */
|
||||||
backends: VoiceBackendType[]
|
backends: VoiceBackendType[]
|
||||||
}
|
}
|
||||||
@@ -229,12 +229,12 @@ function isVoiceBackendType(value: string): value is VoiceBackendType {
|
|||||||
export async function fetchVoiceBackend(api: ApiClient): Promise<VoiceBackendResponse> {
|
export async function fetchVoiceBackend(api: ApiClient): Promise<VoiceBackendResponse> {
|
||||||
const result = await api.fetchVoiceBackend()
|
const result = await api.fetchVoiceBackend()
|
||||||
const { backend } = result
|
const { backend } = result
|
||||||
if (!isVoiceBackendType(backend)) {
|
if (backend !== null && !isVoiceBackendType(backend)) {
|
||||||
throw new Error(`Unrecognised voice backend: ${backend}`)
|
throw new Error(`Unrecognised voice backend: ${backend}`)
|
||||||
}
|
}
|
||||||
const rawBackends = Array.isArray(result.backends) ? result.backends : [backend]
|
const rawBackends = Array.isArray(result.backends) ? result.backends : backend !== null ? [backend] : []
|
||||||
const backends = rawBackends.filter(isVoiceBackendType)
|
const backends = rawBackends.filter(isVoiceBackendType)
|
||||||
if (backends.length === 0) {
|
if (backend !== null && backends.length === 0) {
|
||||||
backends.push(backend)
|
backends.push(backend)
|
||||||
}
|
}
|
||||||
return { backend, backends }
|
return { backend, backends }
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ export function writeStoredVoiceBackendPreference(backend: VoiceBackendType): vo
|
|||||||
|
|
||||||
export function resolveSelectedVoiceBackend(
|
export function resolveSelectedVoiceBackend(
|
||||||
configured: readonly VoiceBackendType[],
|
configured: readonly VoiceBackendType[],
|
||||||
hubDefault: VoiceBackendType
|
hubDefault: VoiceBackendType | null
|
||||||
): VoiceBackendType {
|
): VoiceBackendType | null {
|
||||||
return resolveEffectiveVoiceBackend(
|
return resolveEffectiveVoiceBackend(
|
||||||
configured,
|
configured,
|
||||||
hubDefault,
|
hubDefault,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export function useVoiceSettings() {
|
|||||||
setConfiguredBackends(response.backends)
|
setConfiguredBackends(response.backends)
|
||||||
const selected = resolveSelectedVoiceBackend(response.backends, response.backend)
|
const selected = resolveSelectedVoiceBackend(response.backends, response.backend)
|
||||||
setBackendState(selected)
|
setBackendState(selected)
|
||||||
setVoiceIdState(readStoredVoiceSelection(selected))
|
setVoiceIdState(selected ? readStoredVoiceSelection(selected) : null)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
if (cancelled) return
|
if (cancelled) return
|
||||||
setConfiguredBackends(['elevenlabs'])
|
setConfiguredBackends(['elevenlabs'])
|
||||||
|
|||||||
Reference in New Issue
Block a user