mirror of
https://github.com/aiclientproxy/proxycast.git
synced 2026-09-24 23:10:56 +08:00
fix: 添加 IFlow provider 对 OpenAI 格式的支持
- 在 provider_calls.rs 中实现 IFlowOAuth 和 IFlowCookie 的处理逻辑 - 修复 deepseek-chat 模型请求返回 400 Bad Request 的问题 - 支持 IFlow 的 token 缓存和自动刷新机制
This commit is contained in:
@@ -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"}})),
|
||||
|
||||
Reference in New Issue
Block a user