diff --git a/src-tauri/src/proxy/forwarder.rs b/src-tauri/src/proxy/forwarder.rs index 5e562265b..60b1db9a2 100644 --- a/src-tauri/src/proxy/forwarder.rs +++ b/src-tauri/src/proxy/forwarder.rs @@ -176,14 +176,24 @@ impl RequestForwarder { let mut last_provider = None; let mut attempted_providers = 0usize; + // 单 Provider 场景下跳过熔断器检查(故障转移关闭时) + let bypass_circuit_breaker = providers.len() == 1; + // 依次尝试每个供应商 for provider in providers.iter() { // 发起请求前先获取熔断器放行许可(HalfOpen 会占用探测名额) - let permit = self - .router - .allow_provider_request(&provider.id, app_type_str) - .await; - if !permit.allowed { + // 单 Provider 场景下跳过此检查,避免熔断器阻塞所有请求 + let (allowed, used_half_open_permit) = if bypass_circuit_breaker { + (true, false) + } else { + let permit = self + .router + .allow_provider_request(&provider.id, app_type_str) + .await; + (permit.allowed, permit.used_half_open_permit) + }; + + if !allowed { log::debug!( "[{}] Provider {} 熔断器拒绝本次请求,跳过", app_type_str, @@ -192,8 +202,6 @@ impl RequestForwarder { continue; } - let used_half_open_permit = permit.used_half_open_permit; - attempted_providers += 1; log::info!( @@ -435,10 +443,23 @@ impl RequestForwarder { serde_json::to_string_pretty(body).unwrap_or_else(|_| body.to_string()) ); + // 应用模型映射(独立于格式转换) + let (mapped_body, _original_model, mapped_model) = + super::model_mapper::apply_model_mapping(body.clone(), provider); + + if let Some(ref mapped) = mapped_model { + log::info!( + "[{}] >>> 模型映射后的请求 JSON:\n{}", + adapter.name(), + serde_json::to_string_pretty(&mapped_body).unwrap_or_default() + ); + log::info!("[{}] 模型已映射到: {}", adapter.name(), mapped); + } + // 转换请求体(如果需要) let request_body = if needs_transform { log::info!("[{}] 转换请求格式 (Anthropic → OpenAI)", adapter.name()); - let transformed = adapter.transform_request(body.clone(), provider)?; + let transformed = adapter.transform_request(mapped_body, provider)?; log::info!( "[{}] >>> 转换后的请求 JSON:\n{}", adapter.name(), @@ -446,7 +467,7 @@ impl RequestForwarder { ); transformed } else { - body.clone() + mapped_body }; log::info!( diff --git a/src-tauri/src/proxy/provider_router.rs b/src-tauri/src/proxy/provider_router.rs index 04eead5f3..dbd1ee008 100644 --- a/src-tauri/src/proxy/provider_router.rs +++ b/src-tauri/src/proxy/provider_router.rs @@ -91,29 +91,19 @@ impl ProviderRouter { } } } else { - // 故障转移关闭:仅使用当前供应商 - log::info!("[{app_type}] Failover disabled, using current provider only"); + // 故障转移关闭:仅使用当前供应商,跳过熔断器检查 + // 原因:单 Provider 场景下,熔断器打开会导致所有请求失败,用户体验差 + log::info!("[{app_type}] Failover disabled, using current provider only (circuit breaker bypassed)"); if let Some(current_id) = self.db.get_current_provider(app_type)? { if let Some(current) = self.db.get_provider_by_id(¤t_id, app_type)? { - let circuit_key = format!("{}:{}", app_type, current.id); - let breaker = self.get_or_create_circuit_breaker(&circuit_key).await; - - if breaker.is_available().await { - log::info!( - "[{}] Current provider available: {} ({})", - app_type, - current.name, - current.id - ); - result.push(current); - } else { - log::warn!( - "[{}] Current provider {} circuit breaker open", - app_type, - current.name - ); - } + log::info!( + "[{}] Current provider: {} ({})", + app_type, + current.name, + current.id + ); + result.push(current); } } }