fix: 添加 IFlow provider 对 OpenAI 格式的支持

- 在 provider_calls.rs 中实现 IFlowOAuth 和 IFlowCookie 的处理逻辑
- 修复 deepseek-chat 模型请求返回 400 Bad Request 的问题
- 支持 IFlow 的 token 缓存和自动刷新机制
This commit is contained in:
Chiron
2026-01-10 11:19:01 +08:00
parent d67ca77a5f
commit f36bc02124
+139 -4
View File
@@ -59,7 +59,8 @@ use crate::models::anthropic::AnthropicMessagesRequest;
use crate::models::openai::ChatCompletionRequest;
use crate::models::provider_pool_model::{CredentialData, ProviderCredential};
use crate::providers::{
AntigravityProvider, ClaudeCustomProvider, KiroProvider, OpenAICustomProvider, VertexProvider,
AntigravityProvider, ClaudeCustomProvider, IFlowProvider, KiroProvider, OpenAICustomProvider,
VertexProvider,
};
use crate::server::AppState;
use crate::server_utils::{
@@ -1919,11 +1920,145 @@ pub async fn call_provider_openai(
.into_response()
}
}
// IFlow 凭证类型 - 支持 OpenAI 格式
CredentialData::IFlowOAuth { creds_file_path } => {
let db = match &state.db {
Some(db) => db,
None => {
return (
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({"error": {"message": "Database not available"}})),
)
.into_response();
}
};
// 获取缓存的 token
let token = match state
.token_cache
.get_valid_token(db, &credential.uuid)
.await
{
Ok(t) => t,
Err(e) => {
tracing::warn!("[POOL] IFlow token cache miss, loading from source: {}", e);
let mut iflow = IFlowProvider::new();
if let Err(e) = iflow.load_credentials_from_path(creds_file_path).await {
let _ = state.pool_service.mark_unhealthy(
db,
&credential.uuid,
Some(&format!("Failed to load IFlow credentials: {}", e)),
);
return (
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({"error": {"message": format!("Failed to load IFlow credentials: {}", e)}})),
)
.into_response();
}
if let Err(e) = iflow.ensure_valid_token().await {
let _ = state.pool_service.mark_unhealthy(
db,
&credential.uuid,
Some(&format!("IFlow token refresh failed: {}", e)),
);
return (
StatusCode::UNAUTHORIZED,
Json(serde_json::json!({"error": {"message": format!("IFlow token refresh failed: {}", e)}})),
)
.into_response();
}
iflow.credentials.access_token.unwrap_or_default()
}
};
let mut iflow = IFlowProvider::new();
iflow.credentials.access_token = Some(token);
let request_json = serde_json::to_value(request).unwrap_or_default();
match iflow.call_api(&request_json).await {
Ok(response) => {
let status = response.status();
let headers = response.headers().clone();
match response.bytes().await {
Ok(body) => {
let mut response_builder = Response::builder().status(status);
for (key, value) in headers.iter() {
response_builder = response_builder.header(key, value);
}
response_builder.body(Body::from(body)).unwrap_or_else(|_| {
(StatusCode::INTERNAL_SERVER_ERROR, "Failed to build response").into_response()
})
}
Err(e) => {
tracing::error!("[IFlow] Failed to read response body: {}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({"error": {"message": format!("Failed to read IFlow response: {}", e)}})),
)
.into_response()
}
}
}
Err(e) => {
tracing::error!("[IFlow] API call failed: {}", e);
(
StatusCode::BAD_GATEWAY,
Json(serde_json::json!({"error": {"message": format!("IFlow API call failed: {}", e)}})),
)
.into_response()
}
}
}
CredentialData::IFlowCookie { creds_file_path } => {
let mut iflow = IFlowProvider::new();
if let Err(e) = iflow.load_credentials_from_path(creds_file_path).await {
return (
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({"error": {"message": format!("Failed to load IFlow credentials: {}", e)}})),
)
.into_response();
}
let request_json = serde_json::to_value(request).unwrap_or_default();
match iflow.call_api(&request_json).await {
Ok(response) => {
let status = response.status();
let headers = response.headers().clone();
match response.bytes().await {
Ok(body) => {
let mut response_builder = Response::builder().status(status);
for (key, value) in headers.iter() {
response_builder = response_builder.header(key, value);
}
response_builder.body(Body::from(body)).unwrap_or_else(|_| {
(StatusCode::INTERNAL_SERVER_ERROR, "Failed to build response").into_response()
})
}
Err(e) => {
tracing::error!("[IFlow] Failed to read response body: {}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({"error": {"message": format!("Failed to read IFlow response: {}", e)}})),
)
.into_response()
}
}
}
Err(e) => {
tracing::error!("[IFlow] API call failed: {}", e);
(
StatusCode::BAD_GATEWAY,
Json(serde_json::json!({"error": {"message": format!("IFlow API call failed: {}", e)}})),
)
.into_response()
}
}
}
// 新增的凭证类型暂不支持 OpenAI 格式
CredentialData::CodexOAuth { .. }
| CredentialData::ClaudeOAuth { .. }
| CredentialData::IFlowOAuth { .. }
| CredentialData::IFlowCookie { .. } => {
| CredentialData::ClaudeOAuth { .. } => {
(
StatusCode::BAD_REQUEST,
Json(serde_json::json!({"error": {"message": "This credential type does not support OpenAI format yet"}})),