MCPcopy Create free account
hub / github.com/Zoo-Code-Org/Zoo-Code / validateAndFixToolResultIds

Function validateAndFixToolResultIds

src/core/task/validateToolResultIds.ts:50–234  ·  view source on GitHub ↗
(
	userMessage: Anthropic.MessageParam,
	apiConversationHistory: Anthropic.MessageParam[],
)

Source from the content-addressed store, hash-verified

48 * @returns The validated user message with corrected tool_use_ids and any missing tool_results added
49 */
50export function validateAndFixToolResultIds(
51 userMessage: Anthropic.MessageParam,
52 apiConversationHistory: Anthropic.MessageParam[],
53): Anthropic.MessageParam {
54 // Only process user messages with array content
55 if (userMessage.role !== "user" || !Array.isArray(userMessage.content)) {
56 return userMessage
57 }
58
59 // Find the previous assistant message from conversation history
60 const prevAssistantIdx = findLastIndex(apiConversationHistory, (msg) => msg.role === "assistant")
61 if (prevAssistantIdx === -1) {
62 return userMessage
63 }
64
65 const previousAssistantMessage = apiConversationHistory[prevAssistantIdx]
66
67 // Get tool_use blocks from the assistant message
68 const assistantContent = previousAssistantMessage.content
69 if (!Array.isArray(assistantContent)) {
70 return userMessage
71 }
72
73 const toolUseBlocks = assistantContent.filter((block): block is Anthropic.ToolUseBlock => block.type === "tool_use")
74
75 // No tool_use blocks to match against - no validation needed
76 if (toolUseBlocks.length === 0) {
77 return userMessage
78 }
79
80 // Find tool_result blocks in the user message
81 let toolResults = userMessage.content.filter(
82 (block): block is Anthropic.ToolResultBlockParam => block.type === "tool_result",
83 )
84
85 // Deduplicate tool_result blocks to prevent API protocol violations (GitHub #10465)
86 // This serves as a safety net for any potential race conditions that could generate
87 // duplicate tool_results with the same tool_use_id. The root cause (approval feedback
88 // creating duplicate results) has been fixed in presentAssistantMessage.ts, but this
89 // deduplication remains as a defensive measure for unknown edge cases.
90 const seenToolResultIds = new Set<string>()
91 const deduplicatedContent = userMessage.content.filter((block) => {
92 if (block.type !== "tool_result") {
93 return true
94 }
95 if (seenToolResultIds.has(block.tool_use_id)) {
96 return false // Duplicate - filter out
97 }
98 seenToolResultIds.add(block.tool_use_id)
99 return true
100 })
101
102 userMessage = {
103 ...userMessage,
104 content: deduplicatedContent,
105 }
106
107 toolResults = deduplicatedContent.filter(

Calls 4

findLastIndexFunction · 0.90
hasMethod · 0.65
captureExceptionMethod · 0.65
hasInstanceMethod · 0.45

Tested by

no test coverage detected