diff --git a/ui/desktop/src/components/ConfigContext.tsx b/ui/desktop/src/components/ConfigContext.tsx index 6c169e26f2..05b823b0a3 100644 --- a/ui/desktop/src/components/ConfigContext.tsx +++ b/ui/desktop/src/components/ConfigContext.tsx @@ -179,7 +179,7 @@ export const ConfigProvider: React.FC = ({ children }) => { return providersData; } catch (error) { console.error('Failed to fetch providers:', error); - return []; + return providersListRef.current; } } return providersListRef.current; diff --git a/ui/desktop/src/components/settings/models/modelInterface.ts b/ui/desktop/src/components/settings/models/modelInterface.ts index 0be12e2244..a8ee79bec6 100644 --- a/ui/desktop/src/components/settings/models/modelInterface.ts +++ b/ui/desktop/src/components/settings/models/modelInterface.ts @@ -47,6 +47,7 @@ export interface ProviderModelsResult { provider: ProviderDetails; models: string[] | null; error: string | null; + warning: string | null; } export async function fetchModelsForProviders( @@ -61,7 +62,7 @@ export async function fetchModelsForProviders( const downloadedModels = allModels .filter((m) => m.status.state === 'Downloaded') .map((m) => m.id); - return { provider: p, models: downloadedModels, error: null }; + return { provider: p, models: downloadedModels, error: null, warning: null }; } const response = await getProviderModels({ @@ -69,14 +70,29 @@ export async function fetchModelsForProviders( throwOnError: true, }); const models = response.data || []; - return { provider: p, models, error: null }; + return { provider: p, models, error: null, warning: null }; } catch (e: unknown) { + // For custom providers, fall back to the configured model list + if (p.provider_type === 'Custom') { + const fallbackModels = p.metadata.known_models.map((m) => m.name); + if (fallbackModels.length > 0) { + console.warn(`Failed to fetch models for ${p.name}:`, getErrorMessage(e)); + return { + provider: p, + models: fallbackModels, + error: null, + warning: `Could not fetch models from provider — showing configured models instead.`, + }; + } + } + const errMsg = getErrorMessage(e); const errorMessage = `Failed to fetch models for ${p.name}${errMsg ? `: ${errMsg}` : ''}`; return { provider: p, models: null, error: errorMessage, + warning: null, }; } }); diff --git a/ui/desktop/src/components/settings/models/subcomponents/SwitchModelModal.tsx b/ui/desktop/src/components/settings/models/subcomponents/SwitchModelModal.tsx index dda23fc6eb..3bd5bc17d7 100644 --- a/ui/desktop/src/components/settings/models/subcomponents/SwitchModelModal.tsx +++ b/ui/desktop/src/components/settings/models/subcomponents/SwitchModelModal.tsx @@ -104,7 +104,9 @@ export const SwitchModelModal = ({ const [provider, setProvider] = useState( initialProvider || currentProvider || null ); - const [model, setModel] = useState(currentModel || ''); + const [model, setModel] = useState( + initialProvider && initialProvider !== currentProvider ? '' : currentModel || '' + ); const [isCustomModel, setIsCustomModel] = useState(false); const [validationErrors, setValidationErrors] = useState({ provider: '', @@ -118,6 +120,7 @@ export const SwitchModelModal = ({ const [loadingModels, setLoadingModels] = useState(false); const [userClearedModel, setUserClearedModel] = useState(false); const [providerErrors, setProviderErrors] = useState>({}); + const [providerWarnings, setProviderWarnings] = useState>({}); const [thinkingLevel, setThinkingLevel] = useState('low'); const [claudeThinkingType, setClaudeThinkingType] = useState('disabled'); const [claudeThinkingEffort, setClaudeThinkingEffort] = useState('high'); @@ -301,8 +304,12 @@ export const SwitchModelModal = ({ options: { value: string; label: string; provider: string; providerType: ProviderType }[]; }[] = []; const errorMap: Record = {}; + const warningMap: Record = {}; - results.forEach(({ provider: p, models, error }) => { + results.forEach(({ provider: p, models, error, warning }) => { + if (warning) { + warningMap[p.name] = warning; + } if (error) { errorMap[p.name] = error; return; @@ -336,8 +343,9 @@ export const SwitchModelModal = ({ } }); - // Save provider errors to state + // Save provider errors and warnings to state setProviderErrors(errorMap); + setProviderWarnings(warningMap); setModelOptions(groupedOptions); setOriginalModelOptions(groupedOptions); @@ -684,6 +692,13 @@ export const SwitchModelModal = ({ {attemptedSubmit && validationErrors.model && (
{validationErrors.model}
)} + {provider && providerWarnings[provider] && ( +
+
+ {providerWarnings[provider]} +
+
+ )} ) : (
diff --git a/ui/desktop/src/components/settings/providers/ProviderGrid.tsx b/ui/desktop/src/components/settings/providers/ProviderGrid.tsx index b7b3d5ad3c..834d0bfee1 100644 --- a/ui/desktop/src/components/settings/providers/ProviderGrid.tsx +++ b/ui/desktop/src/components/settings/providers/ProviderGrid.tsx @@ -196,11 +196,13 @@ function ProviderCards({ const handleCreateCustomProvider = useCallback( async (data: UpdateCustomProviderRequest) => { const { createCustomProvider } = await import('../../../api'); - await createCustomProvider({ body: data, throwOnError: true }); + const result = await createCustomProvider({ body: data, throwOnError: true }); + const providerId = result.data?.replace('Custom provider added - ID: ', '') || null; setShowCustomProviderModal(false); if (refreshProviders) { - refreshProviders(); + await refreshProviders(); } + setSwitchModelProvider(providerId); setShowSwitchModelModal(true); }, [refreshProviders] diff --git a/ui/desktop/src/components/settings/providers/ProviderSettingsPage.tsx b/ui/desktop/src/components/settings/providers/ProviderSettingsPage.tsx index aaad639ffe..989460906f 100644 --- a/ui/desktop/src/components/settings/providers/ProviderSettingsPage.tsx +++ b/ui/desktop/src/components/settings/providers/ProviderSettingsPage.tsx @@ -50,11 +50,10 @@ export default function ProviderSettings({ }, []); // Intentionally not including loadProviders in deps to prevent reloading // This function will be passed to ProviderGrid for manual refreshes after config changes - const refreshProviders = useCallback(() => { + const refreshProviders = useCallback(async () => { if (initialLoadDone.current) { - getProviders(true).then((result) => { - if (result) setProviders(result); - }); + const result = await getProviders(true); + if (result) setProviders(result); } }, [getProviders]);