From 7974d2ba5cce794a68ab916cf51f2dbfd084107b Mon Sep 17 00:00:00 2001 From: zhangyapu1 Date: Mon, 1 Jun 2026 10:47:46 +0800 Subject: [PATCH] fix: extract primary key when multiple API keys are configured When multiple API keys are stored as comma-separated string (e.g., "key1,key2"), the model fetcher and aionrs agent now extract the first valid key instead of passing the entire string as a single API key. - Add primary_key() helper in fetchers.rs to extract first valid key - Use primary_key in fetch_for_platform for all platform fetchers - Extract first valid key in aionrs agent initialization --- .../src/manager/aionrs/agent.rs | 13 ++++++++++- .../src/model_fetcher/fetchers.rs | 22 ++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/crates/aionui-ai-agent/src/manager/aionrs/agent.rs b/crates/aionui-ai-agent/src/manager/aionrs/agent.rs index 3cf27f01..38ef078f 100644 --- a/crates/aionui-ai-agent/src/manager/aionrs/agent.rs +++ b/crates/aionui-ai-agent/src/manager/aionrs/agent.rs @@ -66,7 +66,18 @@ impl AionrsAgentManager { let cli_args = CliArgs { provider: Some(config_extra.provider.clone()), - api_key: Some(config_extra.api_key.clone()), + // When multiple keys are stored as comma-separated string, + // use the first valid key for the aionrs engine. + // Full key rotation on failure is handled at a higher layer. + api_key: Some( + config_extra + .api_key + .split([',', '\n']) + .map(|s| s.trim()) + .find(|s| !s.is_empty()) + .unwrap_or(&config_extra.api_key) + .to_owned(), + ), base_url: config_extra.base_url.clone(), model: Some(config_extra.model.clone()), max_tokens: Some(config_extra.max_tokens), diff --git a/crates/aionui-system/src/model_fetcher/fetchers.rs b/crates/aionui-system/src/model_fetcher/fetchers.rs index 3a82e16a..aced8206 100644 --- a/crates/aionui-system/src/model_fetcher/fetchers.rs +++ b/crates/aionui-system/src/model_fetcher/fetchers.rs @@ -9,20 +9,32 @@ use super::FetchConfig; const REQUEST_TIMEOUT: Duration = Duration::from_secs(30); +/// Extract the first API key from a potentially comma/newline-separated string. +/// If the input contains multiple keys (e.g., "key1,key2"), only the first one +/// is used for fetching the model list. +fn primary_key(api_key: &str) -> &str { + api_key + .split([',', '\n']) + .map(|s| s.trim()) + .find(|s| !s.is_empty()) + .unwrap_or(api_key) +} + /// Dispatch to the appropriate platform-specific fetcher. pub(crate) async fn fetch_for_platform( client: &reqwest::Client, config: &FetchConfig, ) -> Result, AppError> { + let key = primary_key(&config.api_key); match config.platform.as_str() { - "anthropic" | "claude" => fetch_anthropic(client, &config.base_url, &config.api_key).await, - "gemini" => fetch_gemini(client, &config.base_url, &config.api_key).await, + "anthropic" | "claude" => fetch_anthropic(client, &config.base_url, key).await, + "gemini" => fetch_gemini(client, &config.base_url, key).await, "bedrock" => fetch_bedrock(config).await, "vertex-ai" => Ok(vertex_ai_models()), - "new-api" => fetch_new_api(client, &config.base_url, &config.api_key).await, + "new-api" => fetch_new_api(client, &config.base_url, key).await, "minimax" => Ok(minimax_models()), - "dashscope-coding" => fetch_dashscope_coding(client, &config.base_url, &config.api_key).await, - _ => fetch_openai_compatible(client, &config.base_url, &config.api_key).await, + "dashscope-coding" => fetch_dashscope_coding(client, &config.base_url, key).await, + _ => fetch_openai_compatible(client, &config.base_url, key).await, } }