diff --git a/src/query.ts b/src/query.ts index 07e8b6fae..2bf9a757e 100644 --- a/src/query.ts +++ b/src/query.ts @@ -124,13 +124,25 @@ function* yieldMissingToolResultBlocks( assistantMessages: AssistantMessage[], errorMessage: string, ) { - for (const assistantMessage of assistantMessages) { + // Filter out duplicate tool use blocks within the same message to prevent duplicate tool results + const uniqueAssistantMessages = assistantMessages.map(assistantMessage => { + const content = assistantMessage.message.content + const uniqueContent = content.filter((item, index, self) => { + if (item.type !== 'tool_use') return true + return index === self.findIndex(other => + other.type === 'tool_use' && other.id === item.id + ) + }) + return { ...assistantMessage, message: { ...assistantMessage.message, content: uniqueContent } } + }) + + for (const assistantMessage of uniqueAssistantMessages) { // Extract all tool use blocks from this assistant message const toolUseBlocks = assistantMessage.message.content.filter( content => content.type === 'tool_use', ) as ToolUseBlock[] - // Emit an interruption message for each tool use + // Emit an interruption message for each unique tool use for (const toolUse of toolUseBlocks) { yield createUserMessage({ content: [ diff --git a/src/services/tools/StreamingToolExecutor.ts b/src/services/tools/StreamingToolExecutor.ts index c4f06a961..f142cf2fd 100644 --- a/src/services/tools/StreamingToolExecutor.ts +++ b/src/services/tools/StreamingToolExecutor.ts @@ -74,6 +74,12 @@ export class StreamingToolExecutor { * Add a tool to the execution queue. Will start executing immediately if conditions allow. */ addTool(block: ToolUseBlock, assistantMessage: AssistantMessage): void { + // Prevent duplicate tool additions - if a tool with this ID already exists, skip it. + // This can happen when provider disconnects/reconnects and resends the same tool_use block. + if (this.tools.some(t => t.id === block.id)) { + return + } + const toolDefinition = findToolByName(this.toolDefinitions, block.name) if (!toolDefinition) { this.tools.push({