From d5c34c58736fb2ad1eb8fdd2a42011085844e228 Mon Sep 17 00:00:00 2001 From: egenvall Date: Sat, 21 Feb 2026 10:40:09 +0100 Subject: [PATCH] Avoid requiring static API key for OAuth Login --- src/llm/manager.rs | 28 +++++++++++++++++++++++++++- src/llm/model.rs | 21 ++++++++++----------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/llm/manager.rs b/src/llm/manager.rs index 06698930f..4022d2c4d 100644 --- a/src/llm/manager.rs +++ b/src/llm/manager.rs @@ -9,7 +9,7 @@ //! `get_api_key()` calls read the new values lock-free. use crate::auth::OAuthCredentials; -use crate::config::{LlmConfig, ProviderConfig}; +use crate::config::{ApiType, LlmConfig, ProviderConfig}; use crate::error::{LlmError, Result}; use anyhow::Context as _; @@ -143,6 +143,32 @@ impl LlmManager { } } + /// Resolve the Anthropic provider config, preferring OAuth credentials. + /// + /// If a static provider exists in config, returns it with the API key + /// overridden by the OAuth token when available. If no static provider + /// exists but OAuth credentials are present, builds a provider from + /// the OAuth token alone. + pub async fn get_anthropic_provider(&self) -> Result { + let token = self.get_anthropic_token().await?; + let static_provider = self.get_provider("anthropic").ok(); + + match (static_provider, token) { + (Some(mut provider), Some(token)) => { + provider.api_key = token; + Ok(provider) + } + (Some(provider), None) => Ok(provider), + (None, Some(token)) => Ok(ProviderConfig { + api_type: ApiType::Anthropic, + base_url: "https://api.anthropic.com".to_string(), + api_key: token, + name: None, + }), + (None, None) => Err(LlmError::UnknownProvider("anthropic".to_string()).into()), + } + } + /// Get the appropriate API key for a provider. pub fn get_api_key(&self, provider_id: &str) -> Result { let provider = self.get_provider(provider_id)?; diff --git a/src/llm/model.rs b/src/llm/model.rs index 4b44f0289..8f82342ea 100644 --- a/src/llm/model.rs +++ b/src/llm/model.rs @@ -76,17 +76,16 @@ impl SpacebotModel { .map(|(provider, _)| provider) .unwrap_or("anthropic"); - let mut provider_config = self - .llm_manager - .get_provider(provider_id) - .map_err(|e| CompletionError::ProviderError(e.to_string()))?; - - // For Anthropic, prefer OAuth token from auth.json over static config key - if provider_id == "anthropic" { - if let Ok(Some(token)) = self.llm_manager.get_anthropic_token().await { - provider_config.api_key = token; - } - } + let mut provider_config = if provider_id == "anthropic" { + self.llm_manager + .get_anthropic_provider() + .await + .map_err(|e| CompletionError::ProviderError(e.to_string()))? + } else { + self.llm_manager + .get_provider(provider_id) + .map_err(|e| CompletionError::ProviderError(e.to_string()))? + }; if provider_id == "zai-coding-plan" || provider_id == "zhipu" { let display_name = if provider_id == "zhipu" {