From baa62885ebfe8577ffdd63fbec1b33cd932d6902 Mon Sep 17 00:00:00 2001 From: Vishnuvardhan Reddy Date: Thu, 26 Feb 2026 12:03:35 +0000 Subject: [PATCH] fix(providers): add fallback support at provider creation time Previously, CreateProvider would fail immediately if the primary model couldn't create a provider (e.g., antigravity model with no OAuth credentials), even when model_fallbacks were configured in agents.defaults. This change makes CreateProvider try each model in the fallback list when the primary fails, allowing graceful degradation when OAuth credentials expire or are missing. Fixes the issue where users with gemini-flash as default model but no antigravity credentials would get an error instead of falling back to other configured models. The fallback chain during Chat() calls remains unchanged and continues to work as before. This fix ensures provider creation itself respects the configured fallbacks. --- pkg/providers/legacy_provider.go | 56 +++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/pkg/providers/legacy_provider.go b/pkg/providers/legacy_provider.go index 23f137538..090452e9c 100644 --- a/pkg/providers/legacy_provider.go +++ b/pkg/providers/legacy_provider.go @@ -28,22 +28,46 @@ func CreateProvider(cfg *config.Config) (LLMProvider, string, error) { return nil, "", fmt.Errorf("no providers configured. Please add entries to model_list in your config") } - // Get model config from model_list - modelCfg, err := cfg.GetModelConfig(model) - if err != nil { - return nil, "", fmt.Errorf("model %q not found in model_list: %w", model, err) + // Collect models to try: primary first, then fallbacks + modelsToTry := []string{model} + modelsToTry = append(modelsToTry, cfg.Agents.Defaults.ModelFallbacks...) + + var lastErr error + for i, modelName := range modelsToTry { + // Get model config from model_list + modelCfg, err := cfg.GetModelConfig(modelName) + if err != nil { + lastErr = fmt.Errorf("model %q not found in model_list: %w", modelName, err) + if i == len(modelsToTry)-1 { + return nil, "", lastErr + } + continue + } + + // Inject global workspace if not set in model config + if modelCfg.Workspace == "" { + modelCfg.Workspace = cfg.WorkspacePath() + } + + // Use factory to create provider + provider, modelID, err := CreateProviderFromConfig(modelCfg) + if err != nil { + lastErr = fmt.Errorf("failed to create provider for model %q: %w", modelName, err) + // If this is the last model, return the error + if i == len(modelsToTry)-1 { + return nil, "", fmt.Errorf("all provider creation attempts failed. Last error: %w", lastErr) + } + // Otherwise, try the next fallback model + continue + } + + // Success! Return the provider + if modelName != model { + // Log that we're using a fallback model + return provider, modelID, nil + } + return provider, modelID, nil } - // Inject global workspace if not set in model config - if modelCfg.Workspace == "" { - modelCfg.Workspace = cfg.WorkspacePath() - } - - // Use factory to create provider - provider, modelID, err := CreateProviderFromConfig(modelCfg) - if err != nil { - return nil, "", fmt.Errorf("failed to create provider for model %q: %w", model, err) - } - - return provider, modelID, nil + return nil, "", lastErr }