fix(gemini): resolve 400 errors by strictly adhering to JSON schema
- Remove from as it is rejected by the API inside . - Ensure is always a JSON object (google.protobuf.Struct), wrapping non-object tool results in . - Update extraction logic to only look for in sibling fields.
This commit is contained in:
@@ -74,8 +74,6 @@ struct GeminiInlineData {
|
|||||||
struct GeminiFunctionCall {
|
struct GeminiFunctionCall {
|
||||||
name: String,
|
name: String,
|
||||||
args: Value,
|
args: Value,
|
||||||
#[serde(skip_serializing_if = "Option::is_none", rename = "thought_signature")]
|
|
||||||
thought_signature: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@@ -264,8 +262,15 @@ impl GeminiProvider {
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let name = msg.name.clone().or_else(|| msg.tool_call_id.clone()).unwrap_or_else(|| "unknown_function".to_string());
|
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::<Value>(&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::<Value>(&text_content)
|
||||||
.unwrap_or_else(|_| serde_json::json!({ "result": 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 {
|
parts.push(GeminiPart {
|
||||||
text: None,
|
text: None,
|
||||||
@@ -328,7 +333,6 @@ impl GeminiProvider {
|
|||||||
function_call: Some(GeminiFunctionCall {
|
function_call: Some(GeminiFunctionCall {
|
||||||
name: tc.function.name.clone(),
|
name: tc.function.name.clone(),
|
||||||
args,
|
args,
|
||||||
thought_signature: thought_signature.clone(),
|
|
||||||
}),
|
}),
|
||||||
function_response: None,
|
function_response: None,
|
||||||
thought: None,
|
thought: None,
|
||||||
@@ -537,10 +541,9 @@ impl GeminiProvider {
|
|||||||
.filter(|p| p.function_call.is_some())
|
.filter(|p| p.function_call.is_some())
|
||||||
.map(|p| {
|
.map(|p| {
|
||||||
let fc = p.function_call.as_ref().unwrap();
|
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()
|
let id = p.thought_signature_camel.clone()
|
||||||
.or_else(|| p.thought_signature_snake.clone())
|
.or_else(|| p.thought_signature_snake.clone())
|
||||||
.or_else(|| fc.thought_signature.clone())
|
|
||||||
.unwrap_or_else(|| format!("call_{}", Uuid::new_v4().simple()));
|
.unwrap_or_else(|| format!("call_{}", Uuid::new_v4().simple()));
|
||||||
|
|
||||||
ToolCall {
|
ToolCall {
|
||||||
@@ -886,10 +889,9 @@ impl super::Provider for GeminiProvider {
|
|||||||
if let Some(fc) = &p.function_call {
|
if let Some(fc) = &p.function_call {
|
||||||
let tool_call_idx = p_idx as u32;
|
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()
|
let signature = p.thought_signature_camel.clone()
|
||||||
.or_else(|| p.thought_signature_snake.clone())
|
.or_else(|| p.thought_signature_snake.clone());
|
||||||
.or_else(|| fc.thought_signature.clone());
|
|
||||||
|
|
||||||
// Ensure the ID remains stable for this tool call index.
|
// 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.
|
// If we found a real signature now, we update it; otherwise use the existing or new random ID.
|
||||||
|
|||||||
Reference in New Issue
Block a user