mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: sanitize tool_use_id in tool_result blocks to match API history (#11131)
Tool IDs from providers like Gemini/OpenRouter contain special characters (e.g., 'functions.read_file:0') that are sanitized when saving tool_use blocks to API history. However, tool_result blocks were using the original unsanitized IDs, causing ToolResultIdMismatchError. This fix ensures tool_result blocks use sanitizeToolUseId() to match the sanitized tool_use IDs in conversation history. Fixes EXT-711
This commit is contained in:
parent
fa93109b76
commit
3400499917
2 changed files with 16 additions and 7 deletions
|
|
@ -40,6 +40,7 @@ import { isValidToolName, validateToolUse } from "../tools/validateToolUse"
|
|||
import { codebaseSearchTool } from "../tools/CodebaseSearchTool"
|
||||
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
import { sanitizeToolUseId } from "../../utils/tool-id"
|
||||
|
||||
/**
|
||||
* Processes and presents assistant message content to the user interface.
|
||||
|
|
@ -118,7 +119,7 @@ export async function presentAssistantMessage(cline: Task) {
|
|||
if (toolCallId) {
|
||||
cline.pushToolResultToUserContent({
|
||||
type: "tool_result",
|
||||
tool_use_id: toolCallId,
|
||||
tool_use_id: sanitizeToolUseId(toolCallId),
|
||||
content: errorMessage,
|
||||
is_error: true,
|
||||
})
|
||||
|
|
@ -169,7 +170,7 @@ export async function presentAssistantMessage(cline: Task) {
|
|||
if (toolCallId) {
|
||||
cline.pushToolResultToUserContent({
|
||||
type: "tool_result",
|
||||
tool_use_id: toolCallId,
|
||||
tool_use_id: sanitizeToolUseId(toolCallId),
|
||||
content: resultContent,
|
||||
})
|
||||
|
||||
|
|
@ -410,7 +411,7 @@ export async function presentAssistantMessage(cline: Task) {
|
|||
|
||||
cline.pushToolResultToUserContent({
|
||||
type: "tool_result",
|
||||
tool_use_id: toolCallId,
|
||||
tool_use_id: sanitizeToolUseId(toolCallId),
|
||||
content: errorMessage,
|
||||
is_error: true,
|
||||
})
|
||||
|
|
@ -447,7 +448,7 @@ export async function presentAssistantMessage(cline: Task) {
|
|||
// continue gracefully.
|
||||
cline.pushToolResultToUserContent({
|
||||
type: "tool_result",
|
||||
tool_use_id: toolCallId,
|
||||
tool_use_id: sanitizeToolUseId(toolCallId),
|
||||
content: formatResponse.toolError(errorMessage),
|
||||
is_error: true,
|
||||
})
|
||||
|
|
@ -493,7 +494,7 @@ export async function presentAssistantMessage(cline: Task) {
|
|||
|
||||
cline.pushToolResultToUserContent({
|
||||
type: "tool_result",
|
||||
tool_use_id: toolCallId,
|
||||
tool_use_id: sanitizeToolUseId(toolCallId),
|
||||
content: resultContent,
|
||||
})
|
||||
|
||||
|
|
@ -644,7 +645,7 @@ export async function presentAssistantMessage(cline: Task) {
|
|||
// Push tool_result directly without setting didAlreadyUseTool
|
||||
cline.pushToolResultToUserContent({
|
||||
type: "tool_result",
|
||||
tool_use_id: toolCallId,
|
||||
tool_use_id: sanitizeToolUseId(toolCallId),
|
||||
content: typeof errorContent === "string" ? errorContent : "(validation error)",
|
||||
is_error: true,
|
||||
})
|
||||
|
|
@ -947,7 +948,7 @@ export async function presentAssistantMessage(cline: Task) {
|
|||
// This prevents the stream from being interrupted with "Response interrupted by tool use result"
|
||||
cline.pushToolResultToUserContent({
|
||||
type: "tool_result",
|
||||
tool_use_id: toolCallId,
|
||||
tool_use_id: sanitizeToolUseId(toolCallId),
|
||||
content: formatResponse.toolError(errorMessage),
|
||||
is_error: true,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@ describe("sanitizeToolUseId", () => {
|
|||
it("should replace multiple invalid characters", () => {
|
||||
expect(sanitizeToolUseId("mcp.server:tool/name")).toBe("mcp_server_tool_name")
|
||||
})
|
||||
|
||||
it("should sanitize Gemini/OpenRouter function call IDs with dots and colons", () => {
|
||||
// This is the exact pattern seen in PostHog errors where tool_result IDs
|
||||
// didn't match tool_use IDs due to missing sanitization
|
||||
expect(sanitizeToolUseId("functions.read_file:0")).toBe("functions_read_file_0")
|
||||
expect(sanitizeToolUseId("functions.write_to_file:1")).toBe("functions_write_to_file_1")
|
||||
expect(sanitizeToolUseId("read_file:0")).toBe("read_file_0")
|
||||
})
|
||||
})
|
||||
|
||||
describe("real-world MCP tool use ID patterns", () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue