Improve custom provider creation experience (#7541)

This commit is contained in:
David Katz
2026-03-02 13:16:22 -05:00
committed by GitHub
parent 568ec98821
commit 858c1b6919
5 changed files with 44 additions and 12 deletions
+1 -1
View File
@@ -179,7 +179,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
return providersData;
} catch (error) {
console.error('Failed to fetch providers:', error);
return [];
return providersListRef.current;
}
}
return providersListRef.current;
@@ -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,
};
}
});
@@ -104,7 +104,9 @@ export const SwitchModelModal = ({
const [provider, setProvider] = useState<string | null>(
initialProvider || currentProvider || null
);
const [model, setModel] = useState<string>(currentModel || '');
const [model, setModel] = useState<string>(
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<boolean>(false);
const [userClearedModel, setUserClearedModel] = useState(false);
const [providerErrors, setProviderErrors] = useState<Record<string, string>>({});
const [providerWarnings, setProviderWarnings] = useState<Record<string, string>>({});
const [thinkingLevel, setThinkingLevel] = useState<string>('low');
const [claudeThinkingType, setClaudeThinkingType] = useState<string>('disabled');
const [claudeThinkingEffort, setClaudeThinkingEffort] = useState<string>('high');
@@ -301,8 +304,12 @@ export const SwitchModelModal = ({
options: { value: string; label: string; provider: string; providerType: ProviderType }[];
}[] = [];
const errorMap: Record<string, string> = {};
const warningMap: Record<string, string> = {};
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 && (
<div className="text-red-500 text-sm mt-1">{validationErrors.model}</div>
)}
{provider && providerWarnings[provider] && (
<div className="rounded-md bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 p-3 mt-2">
<div className="text-sm text-yellow-700 dark:text-yellow-300">
{providerWarnings[provider]}
</div>
</div>
)}
</div>
) : (
<div className="flex flex-col gap-2">
@@ -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]
@@ -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]);