merge
This commit is contained in:
@@ -222,6 +222,16 @@ impl GeminiProvider {
|
|||||||
let mut contents: Vec<GeminiContent> = Vec::new();
|
let mut contents: Vec<GeminiContent> = Vec::new();
|
||||||
let mut system_parts = Vec::new();
|
let mut system_parts = Vec::new();
|
||||||
|
|
||||||
|
// PRE-PASS: Build tool_id -> function_name mapping for tool responses
|
||||||
|
let mut tool_id_to_name = std::collections::HashMap::new();
|
||||||
|
for msg in &messages {
|
||||||
|
if let Some(tool_calls) = &msg.tool_calls {
|
||||||
|
for tc in tool_calls {
|
||||||
|
tool_id_to_name.insert(tc.id.clone(), tc.function.name.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for msg in messages {
|
for msg in messages {
|
||||||
if msg.role == "system" {
|
if msg.role == "system" {
|
||||||
for part in msg.content {
|
for part in msg.content {
|
||||||
@@ -261,7 +271,14 @@ 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());
|
// RESOLVE: Use msg.name if present, otherwise look up by tool_call_id
|
||||||
|
let name = msg.name.clone()
|
||||||
|
.or_else(|| {
|
||||||
|
msg.tool_call_id.as_ref()
|
||||||
|
.and_then(|id| tool_id_to_name.get(id).cloned())
|
||||||
|
})
|
||||||
|
.or_else(|| msg.tool_call_id.clone())
|
||||||
|
.unwrap_or_else(|| "unknown_function".to_string());
|
||||||
|
|
||||||
// Gemini API requires 'response' to be a JSON object (google.protobuf.Struct).
|
// Gemini API requires 'response' to be a JSON object (google.protobuf.Struct).
|
||||||
// If it is an array or primitive, wrap it in an object.
|
// If it is an array or primitive, wrap it in an object.
|
||||||
@@ -322,10 +339,13 @@ impl GeminiProvider {
|
|||||||
let args = serde_json::from_str::<Value>(&tc.function.arguments)
|
let args = serde_json::from_str::<Value>(&tc.function.arguments)
|
||||||
.unwrap_or_else(|_| serde_json::json!({}));
|
.unwrap_or_else(|_| serde_json::json!({}));
|
||||||
|
|
||||||
// RESTORE: Use tc.id as thought_signature.
|
// RESTORE: Only use tc.id as thought_signature if it's NOT a synthetic ID.
|
||||||
// Gemini 3 models require this field for any function call in the history.
|
// Synthetic IDs (starting with 'call_') cause 400 errors as they are not valid Base64 for the TYPE_BYTES field.
|
||||||
// We include it regardless of format to ensure the model has context.
|
let thought_signature = if tc.id.starts_with("call_") {
|
||||||
let thought_signature = Some(tc.id.clone());
|
None
|
||||||
|
} else {
|
||||||
|
Some(tc.id.clone())
|
||||||
|
};
|
||||||
|
|
||||||
parts.push(GeminiPart {
|
parts.push(GeminiPart {
|
||||||
text: None,
|
text: None,
|
||||||
|
|||||||
Reference in New Issue
Block a user