@@ -8,10 +8,10 @@ import { useAudioContext } from '@proj-airi/stage-ui/stores/audio'
88import { useHearingSpeechInputPipeline , useHearingStore } from ' @proj-airi/stage-ui/stores/modules/hearing'
99import { useProvidersStore } from ' @proj-airi/stage-ui/stores/providers'
1010import { useSettingsAudioDevice } from ' @proj-airi/stage-ui/stores/settings'
11- import { Button , FieldCheckbox , FieldRange , FieldSelect } from ' @proj-airi/ui'
11+ import { Button , FieldCheckbox , FieldInput , FieldRange , FieldSelect } from ' @proj-airi/ui'
1212import { until } from ' @vueuse/core'
1313import { storeToRefs } from ' pinia'
14- import { computed , onUnmounted , ref , watch } from ' vue'
14+ import { computed , onMounted , onUnmounted , ref , watch } from ' vue'
1515import { useI18n } from ' vue-i18n'
1616
1717const { t } = useI18n ()
@@ -222,8 +222,29 @@ const speakingIndicatorClass = computed(() => {
222222 }
223223})
224224
225- function updateCustomModelName(value : string ) {
226- activeCustomModelName .value = value
225+ function updateCustomModelName(value : string | undefined ) {
226+ const modelValue = value || ' '
227+ activeCustomModelName .value = modelValue
228+ activeTranscriptionModel .value = modelValue
229+ }
230+
231+ // Sync OpenAI Compatible model from provider config
232+ function syncOpenAICompatibleSettings() {
233+ if (activeTranscriptionProvider .value !== ' openai-compatible-audio-transcription' )
234+ return
235+
236+ const providerConfig = providersStore .getProviderConfig (activeTranscriptionProvider .value )
237+ // Always sync model from provider config (override any existing value from previous provider)
238+ if (providerConfig ?.model ) {
239+ activeTranscriptionModel .value = providerConfig .model as string
240+ updateCustomModelName (providerConfig .model as string )
241+ }
242+ else {
243+ // If no model in provider config, use default
244+ const defaultModel = ' whisper-1'
245+ activeTranscriptionModel .value = defaultModel
246+ updateCustomModelName (defaultModel )
247+ }
227248}
228249
229250onStopRecord (async (recording ) => {
@@ -427,6 +448,7 @@ watch(activeTranscriptionProvider, async (provider) => {
427448 return
428449
429450 await hearingStore .loadModelsForProvider (provider )
451+ syncOpenAICompatibleSettings ()
430452
431453 // Auto-select first model for Web Speech API if no model is selected
432454 if (provider === ' browser-web-speech-api' && ! activeTranscriptionModel .value ) {
@@ -438,6 +460,11 @@ watch(activeTranscriptionProvider, async (provider) => {
438460 }
439461}, { immediate: true })
440462
463+ onMounted (async () => {
464+ // Audio devices are loaded on demand when user requests them
465+ syncOpenAICompatibleSettings ()
466+ })
467+
441468onUnmounted (() => {
442469 stopSTTTest ()
443470 stopAudioMonitoring ()
@@ -537,19 +564,25 @@ onUnmounted(() => {
537564 </div >
538565
539566 <!-- Model selection section -->
540- <div v-if =" activeTranscriptionProvider && supportsModelListing " >
567+ <div v-if =" activeTranscriptionProvider" >
541568 <div flex =" ~ col gap-4" >
542569 <div >
543570 <h2 class =" text-lg md:text-2xl" >
544571 {{ t('settings.pages.modules.consciousness.sections.section.provider-model-selection.title') }}
545572 </h2 >
546573 <div text =" neutral-400 dark:neutral-400" >
547- <span >{{ t('settings.pages.modules.consciousness.sections.section.provider-model-selection.subtitle') }}</span >
574+ <!-- Show different description based on whether provider supports model listing and has models -->
575+ <span v-if =" supportsModelListing && providerModels.length > 0" >
576+ {{ t('settings.pages.modules.consciousness.sections.section.provider-model-selection.subtitle') }}
577+ </span >
578+ <span v-else >
579+ Enter the transcription model to use (e.g., 'whisper-1', 'gpt-4o-transcribe')
580+ </span >
548581 </div >
549582 </div >
550583
551584 <!-- Loading state -->
552- <div v-if =" isLoadingActiveProviderModels" class =" flex items-center justify-center py-4" >
585+ <div v-if =" isLoadingActiveProviderModels && supportsModelListing " class =" flex items-center justify-center py-4" >
553586 <div class =" mr-2 animate-spin" >
554587 <div i-solar:spinner-line-duotone text-xl />
555588 </div >
@@ -558,14 +591,26 @@ onUnmounted(() => {
558591
559592 <!-- Error state -->
560593 <ErrorContainer
561- v-else-if =" activeProviderModelError"
594+ v-else-if =" activeProviderModelError && supportsModelListing "
562595 :title =" t('settings.pages.modules.consciousness.sections.section.provider-model-selection.error')"
563596 :error =" activeProviderModelError"
564597 />
565598
566- <!-- No models available -->
599+ <!-- Manual input for providers without model listing or when no models are available -->
600+ <div
601+ v-else-if =" !supportsModelListing || (activeTranscriptionProvider === 'openai-compatible-audio-transcription' && providerModels.length === 0 && !isLoadingActiveProviderModels)"
602+ class =" mt-2"
603+ >
604+ <FieldInput
605+ :model-value =" activeTranscriptionModel || activeCustomModelName || ''"
606+ placeholder =" whisper-1"
607+ @update:model-value =" updateCustomModelName"
608+ />
609+ </div >
610+
611+ <!-- No models available (for other providers with model listing but no models) -->
567612 <Alert
568- v-else-if =" providerModels.length === 0 && !isLoadingActiveProviderModels"
613+ v-else-if =" providerModels.length === 0 && !isLoadingActiveProviderModels && supportsModelListing "
569614 type =" warning"
570615 >
571616 <template #title >
@@ -576,8 +621,8 @@ onUnmounted(() => {
576621 </template >
577622 </Alert >
578623
579- <!-- Using the new RadioCardManySelect component -->
580- <template v-else-if =" providerModels .length > 0 " >
624+ <!-- Using the new RadioCardManySelect component for providers with models -->
625+ <template v-else-if =" providerModels .length > 0 && supportsModelListing " >
581626 <RadioCardManySelect
582627 v-model =" activeTranscriptionModel"
583628 v-model:search-query =" transcriptionModelSearchQuery"
0 commit comments