Skip to content

Commit 73d2c5c

Browse files
committed
Disable XML parser when native tool protocol is enabled
- Make assistantMessageParser optional (undefined for native protocol) - Only initialize parser when toolProtocol is 'xml' - Add conditional checks before calling parser methods - Handle native protocol text chunks separately from XML parsing This prevents unnecessary XML parsing when using native tool calls, which come as structured tool_call chunks instead of XML text.
1 parent 1b19646 commit 73d2c5c

File tree

1 file changed

+51
-24
lines changed

1 file changed

+51
-24
lines changed

src/core/task/Task.ts

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
300300
didRejectTool = false
301301
didAlreadyUseTool = false
302302
didCompleteReadingStream = false
303-
assistantMessageParser: AssistantMessageParser
303+
assistantMessageParser?: AssistantMessageParser
304304

305305
// Token Usage Cache
306306
private tokenUsageSnapshot?: TokenUsage
@@ -405,8 +405,10 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
405405
TelemetryService.instance.captureTaskCreated(this.taskId)
406406
}
407407

408-
// Initialize the assistant message parser.
409-
this.assistantMessageParser = new AssistantMessageParser()
408+
// Initialize the assistant message parser only for XML protocol.
409+
// For native protocol, tool calls come as tool_call chunks, not XML.
410+
const toolProtocol = vscode.workspace.getConfiguration(Package.name).get<ToolProtocol>("toolProtocol", "xml")
411+
this.assistantMessageParser = toolProtocol === "xml" ? new AssistantMessageParser() : undefined
410412

411413
this.messageQueueService = new MessageQueueService()
412414

@@ -1995,7 +1997,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
19951997
this.didAlreadyUseTool = false
19961998
this.presentAssistantMessageLocked = false
19971999
this.presentAssistantMessageHasPendingUpdates = false
1998-
this.assistantMessageParser.reset()
2000+
this.assistantMessageParser?.reset()
19992001

20002002
await this.diffViewProvider.reset()
20012003

@@ -2081,18 +2083,41 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
20812083
case "text": {
20822084
assistantMessage += chunk.text
20832085

2084-
// Parse raw assistant message chunk into content blocks.
2085-
const prevLength = this.assistantMessageContent.length
2086-
this.assistantMessageContent = this.assistantMessageParser.processChunk(chunk.text)
2086+
if (this.assistantMessageParser) {
2087+
// XML protocol: Parse raw assistant message chunk into content blocks
2088+
const prevLength = this.assistantMessageContent.length
2089+
this.assistantMessageContent = this.assistantMessageParser.processChunk(chunk.text)
20872090

2088-
if (this.assistantMessageContent.length > prevLength) {
2089-
// New content we need to present, reset to
2090-
// false in case previous content set this to true.
2091-
this.userMessageContentReady = false
2092-
}
2091+
if (this.assistantMessageContent.length > prevLength) {
2092+
// New content we need to present, reset to
2093+
// false in case previous content set this to true.
2094+
this.userMessageContentReady = false
2095+
}
20932096

2094-
// Present content to user.
2095-
presentAssistantMessage(this)
2097+
// Present content to user.
2098+
presentAssistantMessage(this)
2099+
} else {
2100+
// Native protocol: Text chunks are plain text, not XML tool calls
2101+
// Create or update a text content block directly
2102+
const lastBlock =
2103+
this.assistantMessageContent[this.assistantMessageContent.length - 1]
2104+
2105+
if (lastBlock?.type === "text" && lastBlock.partial) {
2106+
// Update existing partial text block
2107+
lastBlock.content = assistantMessage
2108+
} else {
2109+
// Create new text block
2110+
this.assistantMessageContent.push({
2111+
type: "text",
2112+
content: assistantMessage,
2113+
partial: true,
2114+
})
2115+
this.userMessageContentReady = false
2116+
}
2117+
2118+
// Present content to user
2119+
presentAssistantMessage(this)
2120+
}
20962121
break
20972122
}
20982123
}
@@ -2383,16 +2408,18 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
23832408
// Can't just do this b/c a tool could be in the middle of executing.
23842409
// this.assistantMessageContent.forEach((e) => (e.partial = false))
23852410

2386-
// Now that the stream is complete, finalize any remaining partial content blocks
2387-
this.assistantMessageParser.finalizeContentBlocks()
2411+
// Now that the stream is complete, finalize any remaining partial content blocks (XML protocol only)
2412+
if (this.assistantMessageParser) {
2413+
this.assistantMessageParser.finalizeContentBlocks()
23882414

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")
2392-
const parsedBlocks = this.assistantMessageParser.getContentBlocks()
2415+
// Preserve tool_use blocks that were added via native protocol (not parsed from text)
2416+
// These come from tool_call chunks and are added directly to assistantMessageContent
2417+
const nativeToolBlocks = this.assistantMessageContent.filter((block) => block.type === "tool_use")
2418+
const parsedBlocks = this.assistantMessageParser.getContentBlocks()
23932419

2394-
// Merge: parser blocks + native tool blocks that aren't in parser
2395-
this.assistantMessageContent = [...parsedBlocks, ...nativeToolBlocks]
2420+
// Merge: parser blocks + native tool blocks that aren't in parser
2421+
this.assistantMessageContent = [...parsedBlocks, ...nativeToolBlocks]
2422+
}
23962423

23972424
if (partialBlocks.length > 0) {
23982425
// If there is content to update then it will complete and
@@ -2425,8 +2452,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
24252452
await this.saveClineMessages()
24262453
await this.providerRef.deref()?.postStateToWebview()
24272454

2428-
// Reset parser after each complete conversation round
2429-
this.assistantMessageParser.reset()
2455+
// Reset parser after each complete conversation round (XML protocol only)
2456+
this.assistantMessageParser?.reset()
24302457

24312458
// Now add to apiConversationHistory.
24322459
// Need to save assistant responses to file before proceeding to

0 commit comments

Comments
 (0)