Skip to content

Commit 93c6d97

Browse files
authored
Fix duplicate tool blocks causing 'tool has already been used' error (#9275)
1 parent 1b19646 commit 93c6d97

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

src/core/task/Task.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
isIdleAsk,
3636
isInteractiveAsk,
3737
isResumableAsk,
38+
isNativeProtocol,
3839
QueuedMessage,
3940
DEFAULT_CONSECUTIVE_MISTAKE_LIMIT,
4041
DEFAULT_CHECKPOINT_TIMEOUT_SECONDS,
@@ -60,7 +61,7 @@ import { ClineApiReqCancelReason, ClineApiReqInfo } from "../../shared/Extension
6061
import { getApiMetrics, hasTokenUsageChanged } from "../../shared/getApiMetrics"
6162
import { ClineAskResponse } from "../../shared/WebviewMessage"
6263
import { defaultModeSlug, getModeBySlug, getGroupName } from "../../shared/modes"
63-
import { DiffStrategy } from "../../shared/tools"
64+
import { DiffStrategy, type ToolUse } from "../../shared/tools"
6465
import { EXPERIMENT_IDS, experiments } from "../../shared/experiments"
6566
import { getModelMaxOutputTokens } from "../../shared/api"
6667

@@ -2386,13 +2387,26 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
23862387
// Now that the stream is complete, finalize any remaining partial content blocks
23872388
this.assistantMessageParser.finalizeContentBlocks()
23882389

2389-
// Preserve tool_use blocks that were added via native protocol (not parsed from text)
2390-
// These come from tool_call chunks and are added directly to assistantMessageContent
2391-
const nativeToolBlocks = this.assistantMessageContent.filter((block) => block.type === "tool_use")
23922390
const parsedBlocks = this.assistantMessageParser.getContentBlocks()
23932391

2394-
// Merge: parser blocks + native tool blocks that aren't in parser
2395-
this.assistantMessageContent = [...parsedBlocks, ...nativeToolBlocks]
2392+
// Check if we're using native protocol
2393+
const toolProtocol = vscode.workspace
2394+
.getConfiguration(Package.name)
2395+
.get<ToolProtocol>("toolProtocol", "xml")
2396+
const isNative = isNativeProtocol(toolProtocol)
2397+
2398+
if (isNative) {
2399+
// For native protocol: Preserve tool_use blocks that were added via tool_call chunks
2400+
// These are added directly to assistantMessageContent and have an 'id' property
2401+
const nativeToolBlocks = this.assistantMessageContent.filter(
2402+
(block): block is ToolUse<any> => block.type === "tool_use" && (block as any).id !== undefined,
2403+
)
2404+
// Merge: parser blocks (text) + native tool blocks (tools with IDs)
2405+
this.assistantMessageContent = [...parsedBlocks, ...nativeToolBlocks]
2406+
} else {
2407+
// For XML protocol: Use only parsed blocks (includes both text and tool_use parsed from XML)
2408+
this.assistantMessageContent = parsedBlocks
2409+
}
23962410

23972411
if (partialBlocks.length > 0) {
23982412
// If there is content to update then it will complete and

0 commit comments

Comments
 (0)