Merge branch 'aether-rust-pioneer' of https://github.com/fawney19/Aether into codex/codex-image-progress-heartbeat

# Conflicts:
#	frontend/src/features/usage/components/__tests__/HorizontalRequestTimeline.spec.ts
This commit is contained in:
Entropy.Xu
2026-05-09 01:26:44 +08:00
90 changed files with 8542 additions and 1252 deletions

View File

@@ -58,6 +58,17 @@ pub use crate::formats::openai::shared::{
pub use crate::formats::shared::error_body::{
build_core_error_body_for_client_format, is_core_error_finalize_kind, LocalCoreSyncErrorKind,
};
pub use crate::formats::shared::image_bridge::{
build_gemini_image_request_body_from_openai_image_request,
build_gemini_image_response_from_openai_image_response,
build_gemini_image_response_from_openai_responses_image_response,
build_openai_image_provider_body_from_response_stream_sync_body,
build_openai_image_request_body_from_gemini_image_request,
build_openai_image_response_from_gemini_response,
build_openai_image_response_from_response_stream_sync_body, gemini_request_is_image_generation,
resolve_requested_gemini_image_model_for_request, GeminiImageRequestForOpenAi,
OpenAiImageRequestForGemini,
};
pub use crate::formats::shared::model_directives::{
apply_model_directive_mapping_patch, apply_model_directive_overrides_from_model,
apply_model_directive_overrides_from_request, claude_model_uses_adaptive_effort,

View File

@@ -368,6 +368,7 @@ pub fn maybe_build_openai_image_sync_finalize_product(
report_kind: &str,
status_code: u16,
report_context: Option<&Value>,
body_json: Option<&Value>,
body_base64: Option<&str>,
) -> Result<Option<OpenAiImageSyncFinalizeProduct>, AiSurfaceFinalizeError> {
if report_kind != OPENAI_IMAGE_SYNC_FINALIZE_REPORT_KIND || status_code >= 400 {
@@ -384,6 +385,45 @@ pub fn maybe_build_openai_image_sync_finalize_product(
{
return Ok(None);
}
let provider_api_format = report_context
.get("provider_api_format")
.and_then(Value::as_str)
.map(str::trim)
.unwrap_or_default();
if provider_api_format == "gemini:generate_content" {
let Some(provider_body_json) = body_json else {
return Ok(None);
};
let Some(client_body_json) =
crate::formats::shared::image_bridge::build_openai_image_response_from_gemini_response(
provider_body_json,
Some(report_context),
)
else {
return Ok(None);
};
return Ok(Some(OpenAiImageSyncFinalizeProduct {
client_body_json,
provider_body_json: provider_body_json.clone(),
}));
}
if provider_api_format != "openai:image" {
return Ok(None);
}
if let Some(provider_body_json) = body_json {
if provider_body_json.get("output").is_some() && provider_body_json.get("data").is_none() {
let Some(client_body_json) = crate::formats::shared::image_bridge::build_openai_image_response_from_response_stream_sync_body(
provider_body_json,
Some(report_context),
) else {
return Ok(None);
};
return Ok(Some(OpenAiImageSyncFinalizeProduct {
client_body_json,
provider_body_json: provider_body_json.clone(),
}));
}
}
let Some(body_base64) = body_base64 else {
return Ok(None);
};
@@ -689,6 +729,7 @@ mod tests {
"openai_image_sync_finalize",
200,
Some(&report_context),
None,
Some(&body_base64),
)
.expect("finalize should succeed")

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,7 @@ use std::fmt;
pub mod error_body;
pub mod family;
pub mod image_bridge;
pub mod model_directives;
pub mod passthrough;
pub mod request;

View File

@@ -595,6 +595,17 @@ pub fn maybe_build_standard_cross_format_sync_product(
let provider_api_format = provider_api_format.trim().to_ascii_lowercase();
let client_api_format = client_api_format.trim().to_ascii_lowercase();
if provider_api_format == "openai:image" && client_api_format == "gemini:generate_content" {
let client_body_json = crate::formats::shared::image_bridge::build_gemini_image_response_from_openai_responses_image_response(
&provider_body_json,
Some(report_context),
)?;
return Some(StandardCrossFormatSyncProduct {
client_body_json,
provider_body_json,
});
}
let client_body_json = if is_standard_chat_finalize_kind(report_kind) {
sync_chat_response_conversion_kind(&provider_api_format, &client_api_format)?;
convert_standard_chat_response(

View File

@@ -27,7 +27,12 @@ pub fn maybe_bridge_standard_sync_json_to_stream(
) -> Result<Option<SyncToStreamBridgeOutcome>, AiSurfaceFinalizeError> {
let provider_api_format = normalize_api_format(provider_api_format);
let client_api_format = normalize_api_format(client_api_format);
if provider_api_format == "openai:image" && client_api_format == "openai:image" {
if client_api_format == "openai:image"
&& matches!(
provider_api_format.as_str(),
"openai:image" | "gemini:generate_content"
)
{
return maybe_bridge_openai_image_sync_json_to_stream(provider_body_json, report_context);
}
if !is_standard_api_format(provider_api_format.as_str())
@@ -67,6 +72,36 @@ fn maybe_bridge_openai_image_sync_json_to_stream(
provider_body_json: &Value,
report_context: Option<&Value>,
) -> Result<Option<SyncToStreamBridgeOutcome>, AiSurfaceFinalizeError> {
let provider_api_format = report_context
.and_then(|value| value.get("provider_api_format"))
.and_then(Value::as_str)
.map(str::trim)
.unwrap_or("openai:image");
let owned_response;
let provider_body_json = if provider_api_format == "gemini:generate_content" {
let Some(converted) =
crate::formats::shared::image_bridge::build_openai_image_response_from_gemini_response(
provider_body_json,
report_context,
)
else {
return Ok(None);
};
owned_response = converted;
&owned_response
} else if provider_body_json.get("output").is_some() && provider_body_json.get("data").is_none()
{
let Some(converted) = crate::formats::shared::image_bridge::build_openai_image_response_from_response_stream_sync_body(
provider_body_json,
report_context,
) else {
return Ok(None);
};
owned_response = converted;
&owned_response
} else {
provider_body_json
};
let Some(response) = provider_body_json.as_object() else {
return Ok(None);
};