From f7e4334bee75f42b9cba5ebb04cec9ddc2ed15c0 Mon Sep 17 00:00:00 2001 From: whit3rabbit Date: Fri, 27 Mar 2026 22:52:36 -0500 Subject: [PATCH] fix: apply Gemini tool schema sanitizer to OpenAI-format chat_completions path --- crates/proxy/src/server/chat_completions.rs | 42 +++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/crates/proxy/src/server/chat_completions.rs b/crates/proxy/src/server/chat_completions.rs index 590664e..4fe95f1 100644 --- a/crates/proxy/src/server/chat_completions.rs +++ b/crates/proxy/src/server/chat_completions.rs @@ -196,6 +196,27 @@ pub(crate) async fn chat_completions( &effective.backend, &mut openai_req, ); + // Gemini/Vertex rejects standard JSON Schema keywords; sanitize tool schemas. + if matches!( + effective.backend, + BackendClient::GeminiOpenAI(_) | BackendClient::Vertex(_) + ) { + if let Some(tools) = openai_req.tools.take() { + openai_req.tools = Some( + tools + .into_iter() + .map(|mut t| { + if let Some(params) = t.function.parameters.take() { + t.function.parameters = Some( + mapping::tools_map::sanitize_schema_for_gemini(params), + ); + } + t + }) + .collect(), + ); + } + } if effective.omit_stream_options { openai_req.stream_options = None; } @@ -393,6 +414,27 @@ async fn chat_completions_stream( // Translate to OpenAI format for the backend let mut openai_req = mapping::message_map::anthropic_to_openai_request(&anthropic_req); super::routes::inject_gemini_thinking(&anthropic_req, &effective.backend, &mut openai_req); + // Gemini/Vertex rejects standard JSON Schema keywords; sanitize tool schemas. + if matches!( + effective.backend, + BackendClient::GeminiOpenAI(_) | BackendClient::Vertex(_) + ) { + if let Some(tools) = openai_req.tools.take() { + openai_req.tools = Some( + tools + .into_iter() + .map(|mut t| { + if let Some(params) = t.function.parameters.take() { + t.function.parameters = Some( + mapping::tools_map::sanitize_schema_for_gemini(params), + ); + } + t + }) + .collect(), + ); + } + } openai_req.model = mapped_model_resolved; openai_req.stream = Some(true); if !effective.omit_stream_options {