Merge remote-tracking branch 'origin/pr/424' into aether-rust-pioneer

# Conflicts:
#	crates/aether-provider-transport/src/vertex/auth.rs
#	crates/aether-provider-transport/src/vertex/mod.rs
#	crates/aether-provider-transport/src/vertex/policy.rs
This commit is contained in:
fawney19
2026-05-11 00:19:04 +08:00
2 changed files with 128 additions and 1 deletions

View File

@@ -208,6 +208,14 @@ pub fn build_same_format_provider_request_body(
) {
return None;
}
if matches!(input.family, SameFormatProviderFamily::Gemini)
&& aether_ai_formats::api_format_alias_matches(
input.provider_api_format,
"gemini:generate_content",
)
{
strip_gemini_function_response_ids(&mut provider_request_body);
}
let require_body_stream_field = input.force_body_stream_field
|| input
.body_json
@@ -222,6 +230,28 @@ pub fn build_same_format_provider_request_body(
Some(provider_request_body)
}
fn strip_gemini_function_response_ids(value: &mut Value) {
match value {
Value::Object(object) => {
for key in ["functionResponse", "function_response"] {
if let Some(function_response) = object.get_mut(key).and_then(Value::as_object_mut)
{
function_response.remove("id");
}
}
for child in object.values_mut() {
strip_gemini_function_response_ids(child);
}
}
Value::Array(items) => {
for item in items {
strip_gemini_function_response_ids(item);
}
}
_ => {}
}
}
pub fn build_same_format_provider_upstream_url(
transport: &GatewayProviderTransportSnapshot,
params: SameFormatProviderUpstreamUrlParams<'_>,
@@ -788,6 +818,66 @@ mod tests {
assert!(body.get("stream").is_none());
}
#[test]
fn same_format_gemini_body_strips_function_response_id_for_upstream() {
let body = build_same_format_provider_request_body(SameFormatProviderRequestBodyInput {
body_json: &json!({
"contents": [
{
"role": "user",
"parts": [
{
"functionResponse": {
"id": "call_123",
"name": "lookup",
"response": {
"result": {
"id": "keep_result_id",
"ok": true
}
}
}
},
{
"function_response": {
"id": "call_456",
"name": "lookup_snake",
"response": {"ok": true}
}
}
]
}
],
"stream": true
}),
mapped_model: "gemini-upstream",
client_api_format: "gemini:generate_content",
provider_api_format: "gemini:generate_content",
source_model: None,
family: SameFormatProviderFamily::Gemini,
body_rules: None,
request_headers: None,
upstream_is_stream: true,
force_body_stream_field: false,
kiro_auth_config: None,
is_claude_code: false,
enable_model_directives: false,
})
.expect("body should build");
let function_response = &body["contents"][0]["parts"][0]["functionResponse"];
assert!(function_response.get("id").is_none());
assert_eq!(function_response["name"], "lookup");
assert_eq!(
function_response["response"]["result"]["id"],
"keep_result_id"
);
let function_response = &body["contents"][0]["parts"][1]["function_response"];
assert!(function_response.get("id").is_none());
assert_eq!(function_response["name"], "lookup_snake");
}
#[test]
fn same_format_stream_policy_wins_after_body_rules() {
let body_rules = json!([