@@ -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