From 2495ff253c26ff7cd665d2870b19ba5c65a07ecc Mon Sep 17 00:00:00 2001 From: Luan Vu Date: Tue, 10 Mar 2026 18:45:09 +0700 Subject: [PATCH] fix(ui): wire allowEmpty for embedding provider select (#112) The `allowEmpty` prop on `ProviderModelSelect` was defined but the Select dropdown still auto-selected the first provider when the value was empty, and there was no way to reset back to empty (auto-detect). - Map empty provider to a sentinel so Radix Select can represent it - Show an "(auto)" option in the dropdown when `allowEmpty` is set - Pass `allowEmpty` from both embedding config callers - Skip clearing the model on provider change in allowEmpty mode to avoid a stale-closure bug where the second setState overwrites the provider update Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com> --- .../src/components/shared/provider-model-select.tsx | 13 +++++++++++-- .../agent-detail/config-sections/memory-section.tsx | 1 + .../pages/config/sections/ai-defaults-section.tsx | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/ui/web/src/components/shared/provider-model-select.tsx b/ui/web/src/components/shared/provider-model-select.tsx index 736218be..065ab2be 100644 --- a/ui/web/src/components/shared/provider-model-select.tsx +++ b/ui/web/src/components/shared/provider-model-select.tsx @@ -97,7 +97,13 @@ export function ProviderModelSelect({ const handleProviderChange = (v: string) => { onProviderChange(v); - onModelChange(""); + // Only clear model when NOT in allowEmpty mode. + // In allowEmpty mode (embedding config), both callbacks update the same + // parent state object — calling onModelChange("") with a stale closure + // would overwrite the provider change we just made. + if (!allowEmpty) { + onModelChange(""); + } }; const handleVerify = async () => { @@ -110,11 +116,14 @@ export function ProviderModelSelect({
{providerLabel ?? t("provider")} {enabledProviders.length > 0 ? ( - handleProviderChange(v === "__empty__" ? "" : v)}> + {allowEmpty && ( + {providerPlaceholder || "(auto)"} + )} {enabledProviders.map((p) => ( {p.display_name || p.name} diff --git a/ui/web/src/pages/agents/agent-detail/config-sections/memory-section.tsx b/ui/web/src/pages/agents/agent-detail/config-sections/memory-section.tsx index f8a6b71e..001d9e1c 100644 --- a/ui/web/src/pages/agents/agent-detail/config-sections/memory-section.tsx +++ b/ui/web/src/pages/agents/agent-detail/config-sections/memory-section.tsx @@ -40,6 +40,7 @@ export function MemorySection({ enabled, value, onToggle, onChange }: MemorySect modelTip="Embedding model name (e.g. text-embedding-3-small). Must be supported by the provider." providerPlaceholder="(auto)" modelPlaceholder="text-embedding-3-small" + allowEmpty />
diff --git a/ui/web/src/pages/config/sections/ai-defaults-section.tsx b/ui/web/src/pages/config/sections/ai-defaults-section.tsx index 10ed7c5d..1b893ae6 100644 --- a/ui/web/src/pages/config/sections/ai-defaults-section.tsx +++ b/ui/web/src/pages/config/sections/ai-defaults-section.tsx @@ -183,6 +183,7 @@ export function AiDefaultsSection({ data, onSave, saving }: Props) { modelTip={t("agents.memory.embeddingModelTip")} providerPlaceholder="(auto)" modelPlaceholder="text-embedding-3-small" + allowEmpty />
updateNested("memory", { max_results: Number(v) })} placeholder="6" />