Fix AI chat not reacting to provider/model changes

- Mark transport dirty instead of resetting chat on settings change
- Rebuild Chat with new transport while preserving message history
- Watch apiKey and customBaseURL changes in addition to model/provider
- Fix provider select z-index inside settings popover (z-52 + isolate)
- Prevent popover dismiss when interacting with select dropdown
This commit is contained in:
Anton A S 2026-03-11 01:23:36 +03:00
parent ba4333d798
commit 82f586ac73
4 changed files with 32 additions and 13 deletions

View file

@ -32,10 +32,8 @@ function scrollToBottom() {
watch(messages, scrollToBottom, { deep: true })
function handleSubmit(text: string) {
if (!chat.value) {
const c = ensureChat()
if (c) chat.value = markRaw(c)
}
const c = ensureChat()
if (c) chat.value = markRaw(c)
chat.value?.sendMessage({ text }).catch(() => {
/* user-facing error handled by UI */
})

View file

@ -41,7 +41,7 @@ const { triggerClass, itemClass, testId } = defineProps<{
<SelectContent
position="popper"
:side-offset="4"
:class="selectContent({ radius: 'lg', padding: 'md' })"
:class="selectContent({ radius: 'lg', padding: 'md', class: 'isolate z-[52]' })"
>
<SelectViewport>
<SelectItem

View file

@ -78,7 +78,16 @@ function clearKey() {
:collision-padding="16"
:avoid-collisions="true"
class="isolate z-[51] w-64 rounded-lg border border-border bg-panel p-3 shadow-lg"
@interact-outside="save"
@interact-outside="
(e: Event) => {
const target = e.target as HTMLElement | null
if (target?.closest('[role=listbox], [data-reka-popper-content-wrapper]')) {
e.preventDefault()
return
}
save()
}
"
>
<div class="flex flex-col gap-2.5">
<h3 class="text-[11px] font-semibold text-surface">AI Provider</h3>

View file

@ -64,17 +64,25 @@ const isConfigured = computed(() => {
return true
})
let transportDirty = false
function markTransportDirty() {
transportDirty = true
}
watch(providerID, (id) => {
const def = AI_PROVIDERS.find((p) => p.id === id)
if (def?.defaultModel) {
modelID.value = def.defaultModel
}
resetChat()
markTransportDirty()
})
watch(modelID, () => resetChat())
watch(customModelID, () => resetChat())
watch(customAPIType, () => resetChat())
watch(modelID, markTransportDirty)
watch(customModelID, markTransportDirty)
watch(customAPIType, markTransportDirty)
watch(apiKey, markTransportDirty)
watch(customBaseURL, markTransportDirty)
function setAPIKey(key: string) {
apiKey.value = key
@ -170,15 +178,19 @@ function createTransport() {
function ensureChat(): Chat<UIMessage> | null {
if (!isConfigured.value) return null
if (!chat) {
chat = new Chat<UIMessage>({
transport: createTransport()
})
chat = new Chat<UIMessage>({ transport: createTransport() })
transportDirty = false
} else if (transportDirty) {
const messages = chat.messages
chat = new Chat<UIMessage>({ transport: createTransport(), messages })
transportDirty = false
}
return chat
}
function resetChat() {
chat = null
transportDirty = false
}
if (typeof window !== 'undefined') {