migrate ai format conversion to responses adapters

This commit is contained in:
fawney19
2026-04-26 23:59:53 +08:00
parent e36fb8c07a
commit 5b914aa78c
183 changed files with 13539 additions and 3401 deletions
@@ -90,10 +90,10 @@ pub(super) async fn maybe_handle(
let endpoint = match normalized_provider_type.as_str() {
"codex" => endpoints.into_iter().find(|endpoint| {
endpoint.is_active
&& endpoint
.api_format
.trim()
.eq_ignore_ascii_case("openai:cli")
&& matches!(
endpoint.api_format.trim().to_ascii_lowercase().as_str(),
"openai:responses" | "openai:cli"
)
}),
"antigravity" => endpoints.into_iter().find(|endpoint| {
endpoint.is_active
@@ -122,7 +122,7 @@ pub(super) async fn maybe_handle(
let Some(endpoint) = endpoint else {
let detail = match normalized_provider_type.as_str() {
"codex" => "找不到有效的 openai:cli 端点",
"codex" => "找不到有效的 openai:responses 端点",
"antigravity" => "找不到有效的 gemini:chat/gemini:cli 端点",
"kiro" => "找不到有效的 Kiro 端点",
_ => "找不到有效端点",
@@ -227,10 +227,10 @@ pub(super) async fn handle_admin_provider_oauth_complete_key(
.await?;
if let Some(endpoint) = endpoints.into_iter().find(|endpoint| {
endpoint.is_active
&& endpoint
.api_format
.trim()
.eq_ignore_ascii_case("openai:cli")
&& matches!(
endpoint.api_format.trim().to_ascii_lowercase().as_str(),
"openai:responses" | "openai:cli"
)
}) {
let refreshed_key = state
.read_provider_catalog_keys_by_ids(std::slice::from_ref(&key_id))
@@ -93,8 +93,8 @@ pub(super) async fn execute_codex_quota_plan(
body_ref: None,
},
stream: false,
client_api_format: "openai:cli".to_string(),
provider_api_format: "openai:cli".to_string(),
client_api_format: "openai:responses".to_string(),
provider_api_format: "openai:responses".to_string(),
model_name: Some("codex-wham-usage".to_string()),
proxy,
tls_profile: state.resolve_transport_tls_profile(transport),
@@ -19,10 +19,10 @@ pub(crate) fn provider_oauth_runtime_endpoint_for_provider(
.iter()
.find(|endpoint| {
endpoint.is_active
&& endpoint
.api_format
.trim()
.eq_ignore_ascii_case("openai:cli")
&& matches!(
endpoint.api_format.trim().to_ascii_lowercase().as_str(),
"openai:responses" | "openai:cli"
)
})
.cloned(),
"antigravity" => endpoints
@@ -22,7 +22,6 @@ use crate::provider_transport::kiro::{
build_kiro_provider_request_body, supports_local_kiro_request_transport_with_network,
KiroProviderHeadersInput, KIRO_ENVELOPE_NAME,
};
use crate::provider_transport::url::build_openai_cli_url;
use crate::usage::GatewaySyncReportRequest;
use crate::{AppState, GatewayError};
use aether_admin::provider::pool as admin_provider_pool_pure;
@@ -282,10 +281,19 @@ fn provider_query_key_supports_endpoint(
return true;
}
let formats = provider_key_configured_api_formats(key);
let endpoint_api_format = provider_query_normalize_api_format_alias(endpoint_api_format);
formats.is_empty()
|| formats
.iter()
.any(|value| value.eq_ignore_ascii_case(endpoint_api_format))
.any(|value| provider_query_normalize_api_format_alias(value) == endpoint_api_format)
}
fn provider_query_normalize_api_format_alias(value: &str) -> String {
match value.trim().to_ascii_lowercase().as_str() {
"openai:cli" => "openai:responses".to_string(),
"openai:compact" => "openai:responses:compact".to_string(),
other => other.to_string(),
}
}
fn provider_query_transport_supports_standard_test_execution(
@@ -297,7 +305,7 @@ fn provider_query_transport_supports_standard_test_execution(
"openai:chat" => {
crate::provider_transport::policy::supports_local_openai_chat_transport(transport)
}
"openai:cli" => {
"openai:responses" | "openai:cli" => {
crate::provider_transport::policy::supports_local_standard_transport_with_network(
transport, api_format,
)
@@ -977,7 +985,7 @@ async fn provider_query_execute_standard_test_candidate(
}
provider_request_body
}
"openai:cli" => {
"openai:responses" | "openai:cli" => {
let Some(mut provider_request_body) =
crate::ai_pipeline::build_cross_format_openai_chat_request_body(
&request_body,
@@ -1001,14 +1009,14 @@ async fn provider_query_execute_standard_test_candidate(
format!("Provider request body rules rejected {provider_api_format}"),
));
}
crate::ai_pipeline::apply_codex_openai_cli_special_body_edits(
crate::ai_pipeline::apply_codex_openai_responses_special_body_edits(
&mut provider_request_body,
transport.provider.provider_type.as_str(),
provider_api_format,
transport.endpoint.body_rules.as_ref(),
Some(candidate.key.id.as_str()),
);
crate::ai_pipeline::apply_openai_compact_special_body_edits(
crate::ai_pipeline::apply_openai_responses_compact_special_body_edits(
&mut provider_request_body,
provider_api_format,
);
@@ -1030,12 +1038,12 @@ async fn provider_query_execute_standard_test_candidate(
None
};
let oauth_auth = match provider_api_format {
"openai:chat" | "openai:cli" | "claude:chat" | "claude:cli" | "gemini:chat"
| "gemini:cli" => state.resolve_local_oauth_header_auth(&transport).await?,
"openai:chat" | "openai:responses" | "openai:cli" | "claude:chat" | "claude:cli"
| "gemini:chat" | "gemini:cli" => state.resolve_local_oauth_header_auth(&transport).await?,
_ => None,
};
let auth = match provider_api_format {
"openai:chat" | "openai:cli" => {
"openai:chat" | "openai:responses" | "openai:cli" => {
crate::provider_transport::auth::resolve_local_openai_bearer_auth(&transport)
.or(oauth_auth)
}
@@ -1096,7 +1104,7 @@ async fn provider_query_execute_standard_test_candidate(
Some("application/json"),
)
}
"openai:cli" => {
"openai:responses" | "openai:cli" => {
crate::provider_transport::auth::build_complete_passthrough_headers_with_auth(
&parts.headers,
auth_header.as_deref().unwrap_or_default(),
@@ -1150,8 +1158,11 @@ async fn provider_query_execute_standard_test_candidate(
response_body: None,
});
}
if provider_api_format == "openai:cli" {
crate::ai_pipeline::apply_codex_openai_cli_special_headers(
if matches!(
provider_api_format.trim().to_ascii_lowercase().as_str(),
"openai:responses" | "openai:cli"
) {
crate::ai_pipeline::apply_codex_openai_responses_special_headers(
&mut request_headers,
&provider_request_body,
&parts.headers,
@@ -1254,7 +1265,10 @@ fn provider_query_prefers_chat_standard_test_api_format(api_format: &str) -> boo
}
fn provider_query_supports_cli_standard_test_api_format(api_format: &str) -> bool {
matches!(api_format, "openai:cli" | "claude:cli" | "gemini:cli")
matches!(
api_format,
"openai:responses" | "openai:cli" | "claude:cli" | "gemini:cli"
)
}
async fn build_admin_provider_query_kiro_failover_response(
@@ -328,11 +328,8 @@ fn resolve_fixed_provider_endpoint_template<'a>(
}
template.endpoints.iter().find(|item| {
item.api_format
.eq_ignore_ascii_case(updated_endpoint.api_format.trim())
|| item
.api_format
.eq_ignore_ascii_case(existing_endpoint.api_format.trim())
api_format_matches(item.api_format, updated_endpoint.api_format.trim())
|| api_format_matches(item.api_format, existing_endpoint.api_format.trim())
})
}
@@ -349,6 +346,19 @@ fn endpoint_matches_fixed_provider_template(
.api_format
.trim()
.eq_ignore_ascii_case(endpoint_template.api_format)
|| api_format_matches(&endpoint.api_format, endpoint_template.api_format)
}
fn normalize_api_format_alias(value: &str) -> String {
match value.trim().to_ascii_lowercase().as_str() {
"openai:cli" => "openai:responses".to_string(),
"openai:compact" => "openai:responses:compact".to_string(),
other => other.to_string(),
}
}
fn api_format_matches(left: &str, right: &str) -> bool {
normalize_api_format_alias(left) == normalize_api_format_alias(right)
}
fn fixed_provider_endpoint_metadata(
@@ -312,7 +312,16 @@ impl<'a> AdminAppState<'a> {
)?;
let provider_type = provider.provider_type.trim().to_ascii_lowercase();
if provider_type == "codex" && existing_endpoint.api_format == "openai:cli" {
if provider_type == "codex"
&& matches!(
existing_endpoint
.api_format
.trim()
.to_ascii_lowercase()
.as_str(),
"openai:responses" | "openai:cli"
)
{
let has_config_in_payload = fields.contains("config");
let config_payload = if has_config_in_payload {
updated
@@ -334,7 +343,7 @@ impl<'a> AdminAppState<'a> {
&& requested.is_some()
&& !admin_requested_force_stream(requested.expect("checked above"))
{
return Err("Codex OpenAI CLI 端点固定为强制流式,不允许修改".to_string());
return Err("Codex OpenAI Responses 端点固定为强制流式,不允许修改".to_string());
}
config.remove("upstreamStreamPolicy");
config.remove("upstream_stream");