@@ -39,7 +39,7 @@ import { CloudService, ExtensionBridgeService } from "@roo-code/cloud"
3939
4040// api
4141import { ApiHandler , ApiHandlerCreateMessageMetadata , buildApiHandler } from "../../api"
42- import { ApiStream } from "../../api/transform/stream"
42+ import { ApiStream , GroundingSource } from "../../api/transform/stream"
4343
4444// shared
4545import { findLastIndex } from "../../shared/array"
@@ -1746,7 +1746,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
17461746 this . didFinishAbortingStream = true
17471747 }
17481748
1749- // Reset streaming state.
1749+ // Reset streaming state for each new API request
17501750 this . currentStreamingContentIndex = 0
17511751 this . currentStreamingDidCheckpoint = false
17521752 this . assistantMessageContent = [ ]
@@ -1767,6 +1767,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
17671767 const stream = this . attemptApiRequest ( )
17681768 let assistantMessage = ""
17691769 let reasoningMessage = ""
1770+ let pendingGroundingSources : GroundingSource [ ] = [ ]
17701771 this . isStreaming = true
17711772
17721773 try {
@@ -1793,6 +1794,13 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
17931794 cacheReadTokens += chunk . cacheReadTokens ?? 0
17941795 totalCost = chunk . totalCost
17951796 break
1797+ case "grounding" :
1798+ // Handle grounding sources separately from regular content
1799+ // to prevent state persistence issues - store them separately
1800+ if ( chunk . sources && chunk . sources . length > 0 ) {
1801+ pendingGroundingSources . push ( ...chunk . sources )
1802+ }
1803+ break
17961804 case "text" : {
17971805 assistantMessage += chunk . text
17981806
@@ -2086,9 +2094,30 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
20862094 let didEndLoop = false
20872095
20882096 if ( assistantMessage . length > 0 ) {
2097+ // Display grounding sources to the user if they exist
2098+ if ( pendingGroundingSources . length > 0 ) {
2099+ const citationLinks = pendingGroundingSources . map ( ( source , i ) => `[${ i + 1 } ](${ source . url } )` )
2100+ const sourcesText = `Sources: ${ citationLinks . join ( ", " ) } `
2101+
2102+ await this . say ( "text" , sourcesText , undefined , false , undefined , undefined , {
2103+ isNonInteractive : true ,
2104+ } )
2105+ }
2106+
2107+ // Strip grounding sources from assistant message before persisting to API history
2108+ // This prevents state persistence issues while maintaining user experience
2109+ let cleanAssistantMessage = assistantMessage
2110+ if ( pendingGroundingSources . length > 0 ) {
2111+ // Remove any grounding source references that might have been integrated into the message
2112+ cleanAssistantMessage = assistantMessage
2113+ . replace ( / \[ \d + \] \s + [ ^ : \n ] + : \s + h t t p s ? : \/ \/ [ ^ \s \n ] + / g, "" )
2114+ . replace ( / S o u r c e s ? : \s * [ \s \S ] * ?(? = \n \n | \n $ | $ ) / g, "" )
2115+ . trim ( )
2116+ }
2117+
20892118 await this . addToApiConversationHistory ( {
20902119 role : "assistant" ,
2091- content : [ { type : "text" , text : assistantMessage } ] ,
2120+ content : [ { type : "text" , text : cleanAssistantMessage } ] ,
20922121 } )
20932122
20942123 TelemetryService . instance . captureConversationMessage ( this . taskId , "assistant" )
0 commit comments