fix(litellm): add graceful fallback when model fetch fails

- Add options to retry with different API key or base URL
- Allow manual model entry as fallback
- Option to return to provider selection instead of crashing
- Show helpful error context about why fetch might have failed

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Charles-Henri ROBICHE 2026-01-29 10:14:07 +01:00
parent 629c25c0e4
commit 6faae80ad4
No known key found for this signature in database

View File

@ -765,11 +765,76 @@ export async function applyAuthChoiceApiProviders(
maxTokens = modelInfo.maxOutputTokens;
}
} else {
// No models available from LiteLLM - fail with error
throw new Error(
"Could not fetch models from LiteLLM. Please ensure your LiteLLM server is running " +
`at ${normalizedBaseUrl} and accessible, or provide the model via --litellm-model flag.`,
// No models available from LiteLLM - offer manual entry or retry
await params.prompter.note(
[
"Could not fetch models from LiteLLM server.",
`Server: ${normalizedBaseUrl}`,
"",
"This could be due to:",
" • Invalid API key",
" • Server not accessible",
" • Network connectivity issues",
].join("\n"),
"Model fetch failed",
);
const action = await params.prompter.select({
message: "How would you like to proceed?",
options: [
{ value: "retry-apikey", label: "Re-enter API key" },
{ value: "retry-baseurl", label: "Re-enter base URL" },
{ value: "manual", label: "Enter model name manually" },
{ value: "cancel", label: "Go back to provider selection" },
],
});
if (action === "cancel") {
return null; // Return null to go back to provider selection
}
if (action === "retry-apikey") {
// Re-prompt for API key
const key = await params.prompter.text({
message: "Enter LiteLLM API key",
validate: validateApiKeyInput,
});
apiKey = normalizeApiKeyInput(String(key));
await setLitellmApiKey(apiKey, params.agentDir);
// Retry the entire LiteLLM flow by returning null and letting the caller retry
throw new Error("Please try the LiteLLM setup again with the new API key");
}
if (action === "retry-baseurl") {
throw new Error("Please restart the setup and provide the correct base URL");
}
// Manual model entry
const modelInput = await params.prompter.text({
message: "Enter model name (as configured in your LiteLLM server)",
placeholder: "e.g., gpt-4, claude-opus-4-5, etc.",
validate: (value) => {
if (!value?.trim()) return "Model name is required";
return undefined;
},
});
normalizedModelId = String(modelInput).trim();
// Prompt for context window since we couldn't auto-detect it
const contextInput = await params.prompter.text({
message: "Enter context window size (tokens) - optional",
placeholder: "e.g., 200000 for Claude Opus 4.5",
validate: (value) => {
if (!value?.trim()) return undefined; // Optional
const num = Number.parseInt(value, 10);
if (Number.isNaN(num) || num <= 0) return "Must be a positive number";
return undefined;
},
});
if (contextInput && String(contextInput).trim()) {
contextWindow = Number.parseInt(String(contextInput).trim(), 10);
}
}
// Strip litellm/ prefix if the API returned it (avoid litellm/litellm/model)