From 412386b48901435304eb8392a3afa812e42601af Mon Sep 17 00:00:00 2001 From: shivammittal274 <56757235+shivammittal274@users.noreply.github.com> Date: Thu, 9 Apr 2026 02:40:38 +0530 Subject: [PATCH] fix: ensure custom model entry is always visible in model selector (#662) The merged PR (#661) injected custom entries into filteredModels, but cmdk auto-scrolls to its first selected CommandItem, pushing the custom entry out of view. Fix by using forceMount on a separate CommandGroup and resetting scroll to top on every keystroke via requestAnimationFrame. --- .../app/ai-settings/NewProviderDialog.tsx | 51 +++++++++++++++---- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/packages/browseros-agent/apps/agent/entrypoints/app/ai-settings/NewProviderDialog.tsx b/packages/browseros-agent/apps/agent/entrypoints/app/ai-settings/NewProviderDialog.tsx index 2a2d358fb..7dfd7b476 100644 --- a/packages/browseros-agent/apps/agent/entrypoints/app/ai-settings/NewProviderDialog.tsx +++ b/packages/browseros-agent/apps/agent/entrypoints/app/ai-settings/NewProviderDialog.tsx @@ -8,7 +8,7 @@ import { Loader2, XCircle, } from 'lucide-react' -import { type FC, useEffect, useMemo, useState } from 'react' +import { type FC, useEffect, useMemo, useRef, useState } from 'react' import { useForm } from 'react-hook-form' import { z } from 'zod/v3' import { Button } from '@/components/ui/button' @@ -223,6 +223,7 @@ export const NewProviderDialog: FC = ({ const [testResult, setTestResult] = useState(null) const [modelPickerOpen, setModelPickerOpen] = useState(false) const [modelSearch, setModelSearch] = useState('') + const modelListRef = useRef(null) const { supports } = useCapabilities() const { baseUrl: agentServerUrl } = useAgentServerUrl() const kimiLaunch = useKimiLaunch() @@ -305,14 +306,12 @@ export const NewProviderDialog: FC = ({ [modelInfoList], ) - const filteredModels = useMemo(() => { - if (!modelSearch) return modelInfoList - const fuzzyResults = modelFuse.search(modelSearch).map((r) => r.item) - const hasExactMatch = fuzzyResults.some((m) => m.modelId === modelSearch) - if (hasExactMatch) return fuzzyResults - const customEntry = { modelId: modelSearch, contextLength: 0 } - return [customEntry, ...fuzzyResults] - }, [modelSearch, modelFuse, modelInfoList]) + const filteredModels = modelSearch + ? modelFuse.search(modelSearch).map((r) => r.item) + : modelInfoList + + const showCustomEntry = + modelSearch && !filteredModels.some((m) => m.modelId === modelSearch) // Handle provider type change (user-initiated via Select) const handleTypeChange = (newType: ProviderType) => { @@ -899,7 +898,12 @@ export const NewProviderDialog: FC = ({ { + setModelSearch(v) + requestAnimationFrame(() => { + modelListRef.current?.scrollTo(0, 0) + }) + }} onKeyDown={(e) => { if (e.key === 'Enter' && modelSearch) { e.preventDefault() @@ -917,11 +921,36 @@ export const NewProviderDialog: FC = ({ } }} /> - + No models found. Press Enter to use " {modelSearch}" + {showCustomEntry && ( + + { + form.setValue('modelId', modelSearch) + track(MODEL_SELECTED_EVENT, { + provider_type: watchedType, + model_id: modelSearch, + is_custom_model: true, + }) + setModelPickerOpen(false) + setModelSearch('') + }} + > + + {modelSearch} + + {field.value === modelSearch && ( + + )} + + + )} {filteredModels.length > 0 && ( {filteredModels.map((model) => (