mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
Improve custom provider creation experience (#7541)
This commit is contained in:
@@ -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]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user