fix(stage-pages): allow clearing OpenAI-compatible speech model field (#1644)

This commit is contained in:
Lulu
2026-04-13 13:55:00 +08:00
committed by GitHub
parent 1ca3a72394
commit bc94ba480b
@@ -27,6 +27,7 @@ const defaultVoiceSettings = {
// Get provider metadata
const providerId = 'openai-compatible-audio-speech'
const defaultModel = 'tts-1'
const defaultVoice = 'alloy'
// Initialize speed from provider config or default
const speed = ref<number>(
@@ -35,9 +36,12 @@ const speed = ref<number>(
|| defaultVoiceSettings.speed,
)
// Model selection
// Model selection (store raw string; empty string is valid while editing — default is applied only at API call)
const model = computed({
get: () => providers.value[providerId]?.model as string | undefined || defaultModel,
get: () => {
const raw = providers.value[providerId]?.model as string | undefined | null
return raw ?? ''
},
set: (value) => {
if (!providers.value[providerId])
providers.value[providerId] = {}
@@ -46,7 +50,10 @@ const model = computed({
})
const voice = computed({
get: () => providers.value[providerId]?.voice || 'alloy',
get: () => {
const raw = providers.value[providerId]?.voice as string | undefined | null
return raw ?? ''
},
set: (value) => {
if (!providers.value[providerId])
providers.value[providerId] = {}
@@ -66,19 +73,19 @@ watch(
if (Math.abs(speed.value - newSpeed) > 0.001) // Use small epsilon for float comparison
speed.value = newSpeed
// Sync model if it was reset
if (!config.model && model.value !== defaultModel)
// Sync model if property was cleared externally (undefined/null), not when user sets empty string
if (config.model == null && model.value !== defaultModel)
model.value = defaultModel
// Sync voice if it was reset
if (!config.voice && voice.value !== 'alloy')
voice.value = 'alloy'
// Sync voice if property was cleared externally (undefined/null), not when user sets empty string
if (config.voice == null && voice.value !== defaultVoice)
voice.value = defaultVoice
}
else {
// Provider config was reset, reset our local refs to defaults
speed.value = defaultVoiceSettings.speed
model.value = defaultModel
voice.value = 'alloy'
voice.value = defaultVoice
}
},
{ deep: true, immediate: true },
@@ -89,16 +96,10 @@ const apiKeyConfigured = computed(() => !!providers.value[providerId]?.apiKey)
// Ensure provider config is initialized on mount
onMounted(() => {
if (!providers.value[providerId]) {
providers.value[providerId] = {}
}
// Initialize model and voice if they don't exist
if (!providers.value[providerId].model) {
providers.value[providerId].model = defaultModel
}
if (!providers.value[providerId].voice) {
providers.value[providerId].voice = 'alloy'
}
providers.value[providerId] ??= {}
// Defaults only when unset (null/undefined); empty strings are kept intentionally
providers.value[providerId].model ??= defaultModel
providers.value[providerId].voice ??= defaultVoice
})
// Generate speech with OpenAI-compatible parameters
@@ -118,7 +119,7 @@ async function handleGenerateSpeech(input: string, voiceId: string, _useSSML: bo
provider,
modelToUse,
input,
voiceId || (voice.value as string),
voiceId || voice.value || defaultVoice,
{
...providerConfig,
...defaultVoiceSettings,
@@ -133,22 +134,6 @@ watch(speed, async () => {
providers.value[providerId].speed = speed.value
})
watch(model, () => {
// Ensure provider config exists
if (!providers.value[providerId])
providers.value[providerId] = {}
// Save model to provider config (this persists to localStorage automatically)
providers.value[providerId].model = model.value
})
watch(voice, () => {
// Ensure provider config exists
if (!providers.value[providerId])
providers.value[providerId] = {}
// Save voice to provider config (this persists to localStorage automatically)
providers.value[providerId].voice = voice.value
})
// Use the composable to get validation logic and state
const {
isValidating,