diff --git a/web/src/app/home/components/models-dialog/component/provider-form/ProviderForm.tsx b/web/src/app/home/components/models-dialog/component/provider-form/ProviderForm.tsx index 97655cebb..7cbc0f7e7 100644 --- a/web/src/app/home/components/models-dialog/component/provider-form/ProviderForm.tsx +++ b/web/src/app/home/components/models-dialog/component/provider-form/ProviderForm.tsx @@ -42,6 +42,7 @@ interface ProviderFormProps { providerId?: string; initialValues?: ProviderFormInitialValues; onValuesChange?: (values: ProviderFormInitialValues) => void; + submitButtonText?: string; onFormSubmit: (providerUuid?: string) => void; onFormCancel: () => void; } @@ -50,6 +51,7 @@ export default function ProviderForm({ providerId, initialValues, onValuesChange, + submitButtonText, onFormSubmit, onFormCancel, }: ProviderFormProps) { @@ -399,7 +401,7 @@ export default function ProviderForm({ /> - + diff --git a/web/src/app/wizard/page.tsx b/web/src/app/wizard/page.tsx index 979845c8d..fb3e13389 100644 --- a/web/src/app/wizard/page.tsx +++ b/web/src/app/wizard/page.tsx @@ -51,6 +51,7 @@ import { getAdapterDocUrl } from '@/app/infra/entities/adapter-docs'; import i18n from 'i18next'; import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; import { Card, CardContent, @@ -1151,6 +1152,9 @@ function WizardModelScan({ ); const [adding, setAdding] = useState(false); const [scanDone, setScanDone] = useState(false); + const [searchQuery, setSearchQuery] = useState(''); + const [manualModelName, setManualModelName] = useState(''); + const [manualAdding, setManualAdding] = useState(false); // Auto-scan on mount useEffect(() => { @@ -1178,6 +1182,12 @@ function WizardModelScan({ }; }, [providerUuid]); + const filteredModels = searchQuery + ? scannedModels.filter((m) => + m.name.toLowerCase().includes(searchQuery.toLowerCase()), + ) + : scannedModels; + const toggleModel = (name: string) => { setSelectedModels((prev) => { const next = new Set(prev); @@ -1214,6 +1224,29 @@ function WizardModelScan({ } }; + const handleManualAdd = async () => { + const name = manualModelName.trim(); + if (!providerUuid || !name) return; + setManualAdding(true); + try { + await httpClient.createProviderLLMModel({ + name, + provider_uuid: providerUuid, + abilities: ['llm'], + reasoning_config: { level: 'provider_default' }, + context_length: null, + extra_args: {}, + } as never); + toast.success(t('wizard.provider.modelsAdded', { count: 1 })); + setManualModelName(''); + onModelsAdded(); + } catch { + toast.error(t('wizard.provider.modelsAddError')); + } finally { + setManualAdding(false); + } + }; + return (
@@ -1233,55 +1266,101 @@ function WizardModelScan({
)} - {!scanning && scanDone && scannedModels.length === 0 && ( -
-

{t('wizard.provider.noModelsFound')}

-
- )} - - {!scanning && scannedModels.length > 0 && ( + {!scanning && scanDone && ( <> -
- {scannedModels.map((model) => ( -