@@ -654,40 +654,55 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
654654 this . emit ( RooCodeEventName . Message , { action : "updated" , message } )
655655
656656 // Telemetry capture remains unchanged below
657-
658657 const shouldCaptureMessage = message . partial !== true && CloudService . isEnabled ( )
659-
660658 if ( shouldCaptureMessage ) {
661659 CloudService . instance . captureEvent ( {
662660 event : TelemetryEventName . TASK_MESSAGE ,
663661 properties : { taskId : this . taskId , message } ,
664662 } )
665663 }
666664
667- // If provider is unavailable, or panel is hidden, skip UI delta updates.
668- // The UI will resync on next visibility or full state push.
669- if ( ! provider || ( typeof ( provider as any ) . isVisible === "function" && ! ( provider as any ) . isVisible ( ) ) ) {
670- return
671- }
672-
673665 // Batch UI updates within a short window to avoid overwhelming the webview
674666 const ts = ( message as any ) ?. ts as number | undefined
675667 if ( typeof ts === "number" ) {
676668 this . messageUpdateBuffer . set ( ts , message )
677669 } else {
678- // Fallback: no timestamp, just send immediately
670+ // Fallback: no timestamp - only send if panel is visible and provider exists
671+ if ( ! provider || ! provider . isVisible ( ) ) {
672+ // Drop non-essential delta; UI will resync on next visibility/state push
673+ return
674+ }
679675 await provider . postMessageToWebview ( { type : "messageUpdated" , clineMessage : message } )
680676 return
681677 }
682678
683679 if ( ! this . messageUpdateTimer ) {
684680 this . messageUpdateTimer = setTimeout ( async ( ) => {
685681 try {
686- const batch = Array . from ( this . messageUpdateBuffer . values ( ) )
687- this . messageUpdateBuffer . clear ( )
682+ // Atomically swap buffers so new arrivals during flush aren't lost
683+ const batchMap = this . messageUpdateBuffer
684+ this . messageUpdateBuffer = new Map ( )
688685 this . messageUpdateTimer = undefined
686+
687+ const batch = Array . from ( batchMap . values ( ) )
688+
689+ const providerNow = this . providerRef . deref ( )
690+ if ( ! providerNow ) {
691+ console . warn (
692+ `[Task#updateClineMessage] Dropping ${ batch . length } messageUpdated deltas: provider unavailable` ,
693+ )
694+ return
695+ }
696+ if ( ! providerNow . isVisible ( ) ) {
697+ // Drop deltas while hidden; UI will receive a full state sync on visibility
698+ console . debug (
699+ `[Task#updateClineMessage] Dropping ${ batch . length } messageUpdated deltas while hidden` ,
700+ )
701+ return
702+ }
703+
689704 for ( const m of batch ) {
690- await provider . postMessageToWebview ( { type : "messageUpdated" , clineMessage : m } )
705+ await providerNow . postMessageToWebview ( { type : "messageUpdated" , clineMessage : m } )
691706 }
692707 } catch ( e ) {
693708 console . error ( "[Task#updateClineMessage] Failed to flush message updates:" , e )
0 commit comments