fix: strip $schema and unsupported JSON Schema fields from tool params

Google's Gemini API rejects $schema, additionalProperties, $ref,
$defs, default, examples, and title in tool parameter schemas.
OpenCode/MCP tools include these standard JSON Schema fields.
Now recursively stripped during OpenAI→Gemini tool conversion.
This commit is contained in:
Nikketryhard
2026-02-15 00:18:32 -06:00
parent 7c44729ace
commit 40c6379ca1

View File

@@ -474,7 +474,8 @@ pub fn openai_tools_to_gemini(tools: &[Value]) -> Vec<Value> {
"description": func["description"],
});
if let Some(params) = func.get("parameters") {
decl["parameters"] = uppercase_types(params.clone());
let cleaned = clean_schema_for_gemini(uppercase_types(params.clone()));
decl["parameters"] = cleaned;
}
Some(decl)
})
@@ -487,6 +488,41 @@ pub fn openai_tools_to_gemini(tools: &[Value]) -> Vec<Value> {
vec![serde_json::json!({"functionDeclarations": declarations})]
}
/// Recursively strip JSON Schema fields that Google's Gemini API doesn't accept.
/// Known unsupported: $schema, additionalProperties, $ref, $defs, default, examples
fn clean_schema_for_gemini(mut val: Value) -> Value {
const STRIP_KEYS: &[&str] = &[
"$schema",
"additionalProperties",
"$ref",
"$defs",
"default",
"examples",
"title",
];
match &mut val {
Value::Object(map) => {
for key in STRIP_KEYS {
map.remove(*key);
}
let keys: Vec<String> = map.keys().cloned().collect();
for key in keys {
if let Some(v) = map.remove(&key) {
map.insert(key, clean_schema_for_gemini(v));
}
}
}
Value::Array(arr) => {
for v in arr.iter_mut() {
*v = clean_schema_for_gemini(std::mem::take(v));
}
}
_ => {}
}
val
}
/// Convert OpenAI tool_choice to Gemini toolConfig format.
///
/// OpenAI: "auto" | "required" | "none" | {"type":"function","function":{"name":"X"}}