fix(gemini): final alignment of thought_signature nesting and naming
Some checks failed
CI / Check (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Formatting (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Release Build (push) Has been cancelled

This commit is contained in:
2026-03-05 16:56:15 +00:00
parent 5bbd5f77b9
commit f7f6768333

View File

@@ -57,8 +57,6 @@ struct GeminiPart {
function_response: Option<GeminiFunctionResponse>, function_response: Option<GeminiFunctionResponse>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
thought: Option<String>, thought: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
thought_signature: Option<String>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -72,6 +70,8 @@ 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)]
@@ -231,7 +231,6 @@ impl GeminiProvider {
function_call: None, function_call: None,
function_response: None, function_response: None,
thought: None, thought: None,
thought_signature: None,
}); });
} }
} }
@@ -271,7 +270,6 @@ impl GeminiProvider {
response: response_value, response: response_value,
}), }),
thought: None, thought: None,
thought_signature: None,
}); });
} else if msg.role == "assistant" { } else if msg.role == "assistant" {
// Assistant messages: handle text, thought (reasoning), and tool_calls // Assistant messages: handle text, thought (reasoning), and tool_calls
@@ -284,7 +282,6 @@ impl GeminiProvider {
function_call: None, function_call: None,
function_response: None, function_response: None,
thought: None, thought: None,
thought_signature: None,
}); });
} }
} }
@@ -299,7 +296,6 @@ impl GeminiProvider {
function_call: None, function_call: None,
function_response: None, function_response: None,
thought: Some(reasoning.clone()), thought: Some(reasoning.clone()),
thought_signature: None,
}); });
} }
} }
@@ -324,10 +320,10 @@ impl GeminiProvider {
function_call: Some(GeminiFunctionCall { function_call: Some(GeminiFunctionCall {
name: tc.function.name.clone(), name: tc.function.name.clone(),
args, args,
thought_signature,
}), }),
function_response: None, function_response: None,
thought: None, thought: None,
thought_signature,
}); });
} }
} }
@@ -343,7 +339,6 @@ impl GeminiProvider {
function_call: None, function_call: None,
function_response: None, function_response: None,
thought: None, thought: None,
thought_signature: None,
}); });
} }
} }
@@ -362,7 +357,6 @@ impl GeminiProvider {
function_call: None, function_call: None,
function_response: None, function_response: None,
thought: None, thought: None,
thought_signature: None,
}); });
} }
} }
@@ -398,7 +392,6 @@ impl GeminiProvider {
function_call: None, function_call: None,
function_response: None, function_response: None,
thought: None, thought: None,
thought_signature: None,
}], }],
}); });
} }
@@ -525,11 +518,10 @@ impl GeminiProvider {
fn extract_tool_calls(parts: &[GeminiPart]) -> Option<Vec<ToolCall>> { fn extract_tool_calls(parts: &[GeminiPart]) -> Option<Vec<ToolCall>> {
let calls: Vec<ToolCall> = parts let calls: Vec<ToolCall> = parts
.iter() .iter()
.filter(|p| p.function_call.is_some()) .filter_map(|p| p.function_call.as_ref())
.map(|p| { .map(|fc| {
let fc = p.function_call.as_ref().unwrap(); // CAPTURE: Use thought_signature from functionCall as the ID if available
// CAPTURE: Use thought_signature from Part as the ID if available let id = fc.thought_signature.clone().unwrap_or_else(|| format!("call_{}", Uuid::new_v4().simple()));
let id = p.thought_signature.clone().unwrap_or_else(|| format!("call_{}", Uuid::new_v4().simple()));
ToolCall { ToolCall {
id, id,
@@ -549,12 +541,11 @@ impl GeminiProvider {
fn extract_tool_call_deltas(parts: &[GeminiPart]) -> Option<Vec<ToolCallDelta>> { fn extract_tool_call_deltas(parts: &[GeminiPart]) -> Option<Vec<ToolCallDelta>> {
let deltas: Vec<ToolCallDelta> = parts let deltas: Vec<ToolCallDelta> = parts
.iter() .iter()
.filter_map(|p| p.function_call.as_ref())
.enumerate() .enumerate()
.filter(|(_, p)| p.function_call.is_some()) .map(|(i, fc)| {
.map(|(i, p)| { // CAPTURE: Use thought_signature from functionCall as the ID if available
let fc = p.function_call.as_ref().unwrap(); let id = fc.thought_signature.clone().unwrap_or_else(|| format!("call_{}", Uuid::new_v4().simple()));
// CAPTURE: Use thought_signature from Part as the ID if available
let id = p.thought_signature.clone().unwrap_or_else(|| format!("call_{}", Uuid::new_v4().simple()));
ToolCallDelta { ToolCallDelta {
index: i as u32, index: i as u32,