diff --git a/src/providers/gemini.rs b/src/providers/gemini.rs index c03bf28f..44ad7231 100644 --- a/src/providers/gemini.rs +++ b/src/providers/gemini.rs @@ -74,8 +74,6 @@ struct GeminiInlineData { struct GeminiFunctionCall { name: String, args: Value, - #[serde(skip_serializing_if = "Option::is_none", rename = "thought_signature")] - thought_signature: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -264,8 +262,15 @@ impl GeminiProvider { .unwrap_or_default(); let name = msg.name.clone().or_else(|| msg.tool_call_id.clone()).unwrap_or_else(|| "unknown_function".to_string()); - let response_value = serde_json::from_str::(&text_content) + + // Gemini API requires 'response' to be a JSON object (google.protobuf.Struct). + // If it is an array or primitive, wrap it in an object. + let mut response_value = serde_json::from_str::(&text_content) .unwrap_or_else(|_| serde_json::json!({ "result": text_content })); + + if !response_value.is_object() { + response_value = serde_json::json!({ "result": response_value }); + } parts.push(GeminiPart { text: None, @@ -328,7 +333,6 @@ impl GeminiProvider { function_call: Some(GeminiFunctionCall { name: tc.function.name.clone(), args, - thought_signature: thought_signature.clone(), }), function_response: None, thought: None, @@ -537,10 +541,9 @@ impl GeminiProvider { .filter(|p| p.function_call.is_some()) .map(|p| { let fc = p.function_call.as_ref().unwrap(); - // CAPTURE: Try extracting thought_signature from multiple possible locations + // CAPTURE: Try extracting thought_signature from sibling fields let id = p.thought_signature_camel.clone() .or_else(|| p.thought_signature_snake.clone()) - .or_else(|| fc.thought_signature.clone()) .unwrap_or_else(|| format!("call_{}", Uuid::new_v4().simple())); ToolCall { @@ -886,10 +889,9 @@ impl super::Provider for GeminiProvider { if let Some(fc) = &p.function_call { let tool_call_idx = p_idx as u32; - // Attempt to find a signature in any possible field + // Attempt to find a signature in sibling fields let signature = p.thought_signature_camel.clone() - .or_else(|| p.thought_signature_snake.clone()) - .or_else(|| fc.thought_signature.clone()); + .or_else(|| p.thought_signature_snake.clone()); // Ensure the ID remains stable for this tool call index. // If we found a real signature now, we update it; otherwise use the existing or new random ID.