fix(google): Fix 400 Bad Request error with Gemini 3 thought signatures (#6035)

Signed-off-by: rabi <ramishra@redhat.com>
This commit is contained in:
Rabi Mishra
2025-12-17 19:08:46 +05:30
committed by GitHub
parent b401222b89
commit fc8a4b4adf
9 changed files with 273 additions and 57 deletions
+28 -14
View File
@@ -536,7 +536,7 @@ mod tests {
let tool_request = ToolRequest {
id: "test-id".to_string(),
tool_call: Ok(tool_call),
thought_signature: None,
metadata: None,
};
let result = tool_request_to_markdown(&tool_request, true);
@@ -560,7 +560,7 @@ mod tests {
let tool_request = ToolRequest {
id: "test-id".to_string(),
tool_call: Ok(tool_call),
thought_signature: None,
metadata: None,
};
let result = tool_request_to_markdown(&tool_request, true);
@@ -580,6 +580,7 @@ mod tests {
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "test-id".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -605,6 +606,7 @@ mod tests {
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "test-id".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -698,7 +700,7 @@ mod tests {
let tool_request = ToolRequest {
id: "shell-cat".to_string(),
tool_call: Ok(tool_call),
thought_signature: None,
metadata: None,
};
let python_code = r#"#!/usr/bin/env python3
@@ -716,6 +718,7 @@ if __name__ == "__main__":
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "shell-cat".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -750,7 +753,7 @@ if __name__ == "__main__":
let tool_request = ToolRequest {
id: "git-status".to_string(),
tool_call: Ok(git_status_call),
thought_signature: None,
metadata: None,
};
let git_output = " M src/main.rs\n?? temp.txt\n A new_feature.rs";
@@ -762,6 +765,7 @@ if __name__ == "__main__":
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "git-status".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -794,7 +798,7 @@ if __name__ == "__main__":
let _tool_request = ToolRequest {
id: "cargo-build".to_string(),
tool_call: Ok(cargo_build_call),
thought_signature: None,
metadata: None,
};
let build_output = r#" Compiling goose-cli v0.1.0 (/Users/user/goose)
@@ -816,6 +820,7 @@ warning: unused variable `x`
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "cargo-build".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -844,7 +849,7 @@ warning: unused variable `x`
let _tool_request = ToolRequest {
id: "curl-api".to_string(),
tool_call: Ok(curl_call),
thought_signature: None,
metadata: None,
};
let api_response = r#"{
@@ -868,6 +873,7 @@ warning: unused variable `x`
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "curl-api".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -898,7 +904,7 @@ warning: unused variable `x`
let tool_request = ToolRequest {
id: "editor-write".to_string(),
tool_call: Ok(editor_call),
thought_signature: None,
metadata: None,
};
let text_content = TextContent {
@@ -909,6 +915,7 @@ warning: unused variable `x`
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "editor-write".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -944,7 +951,7 @@ warning: unused variable `x`
let _tool_request = ToolRequest {
id: "editor-view".to_string(),
tool_call: Ok(editor_call),
thought_signature: None,
metadata: None,
};
let python_code = r#"import os
@@ -971,6 +978,7 @@ def process_data(data: List[Dict]) -> List[Dict]:
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "editor-view".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -999,7 +1007,7 @@ def process_data(data: List[Dict]) -> List[Dict]:
let _tool_request = ToolRequest {
id: "shell-error".to_string(),
tool_call: Ok(error_call),
thought_signature: None,
metadata: None,
};
let error_output = r#"python: can't open file 'nonexistent_script.py': [Errno 2] No such file or directory
@@ -1013,6 +1021,7 @@ Command failed with exit code 2"#;
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "shell-error".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -1040,7 +1049,7 @@ Command failed with exit code 2"#;
let tool_request = ToolRequest {
id: "script-exec".to_string(),
tool_call: Ok(script_call),
thought_signature: None,
metadata: None,
};
let script_output = r#"Python 3.11.5 (main, Aug 24 2023, 15:18:16) [Clang 14.0.3 ]
@@ -1058,6 +1067,7 @@ Command failed with exit code 2"#;
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "script-exec".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -1092,7 +1102,7 @@ Command failed with exit code 2"#;
let _tool_request = ToolRequest {
id: "multi-cmd".to_string(),
tool_call: Ok(multi_call),
thought_signature: None,
metadata: None,
};
let multi_output = r#"total 24
@@ -1110,6 +1120,7 @@ drwx------ 3 user staff 96 Dec 6 16:20 com.apple.launchd.abc
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "multi-cmd".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -1142,7 +1153,7 @@ drwx------ 3 user staff 96 Dec 6 16:20 com.apple.launchd.abc
let tool_request = ToolRequest {
id: "grep-search".to_string(),
tool_call: Ok(grep_call),
thought_signature: None,
metadata: None,
};
let grep_output = r#"src/main.rs:15:async fn process_request(req: Request) -> Result<Response> {
@@ -1158,6 +1169,7 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "grep-search".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -1191,7 +1203,7 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
let _tool_request = ToolRequest {
id: "json-test".to_string(),
tool_call: Ok(tool_call),
thought_signature: None,
metadata: None,
};
let json_output = r#"{"status": "success", "data": {"count": 42}}"#;
@@ -1203,6 +1215,7 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "json-test".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
@@ -1231,7 +1244,7 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
let tool_request = ToolRequest {
id: "npm-install".to_string(),
tool_call: Ok(npm_call),
thought_signature: None,
metadata: None,
};
let npm_output = r#"added 57 packages, and audited 58 packages in 3s
@@ -1249,6 +1262,7 @@ found 0 vulnerabilities"#;
annotations: None,
};
let tool_response = ToolResponse {
metadata: None,
id: "npm-install".to_string(),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],