@@ -217,7 +217,11 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
217217 const [ checkpointWarning , setCheckpointWarning ] = useState <
218218 { type : "WAIT_TIMEOUT" | "INIT_TIMEOUT" ; timeout : number } | undefined
219219 > ( undefined )
220- const [ isCondensing , setIsCondensing ] = useState < boolean > ( false )
220+ const [ condensingTaskIds , setCondensingTaskIds ] = useState < Set < string > > ( ( ) => new Set ( ) )
221+ const isCondensing = useMemo (
222+ ( ) => ( currentTaskId ? condensingTaskIds . has ( currentTaskId ) : false ) ,
223+ [ currentTaskId , condensingTaskIds ] ,
224+ )
221225 const everVisibleMessagesTsRef = useRef < LRUCache < number , boolean > > (
222226 new LRUCache ( {
223227 max : 100 ,
@@ -226,7 +230,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
226230 )
227231 const autoApproveTimeoutRef = useRef < NodeJS . Timeout | null > ( null )
228232 const userRespondedRef = useRef < boolean > ( false )
229- const pendingPostCompactRef = useRef < { text : string ; images : string [ ] } | null > ( null )
233+ const pendingPostCompactRef = useRef < { taskId : string ; text : string ; images : string [ ] } | null > ( null )
230234 const [ currentFollowUpTs , setCurrentFollowUpTs ] = useState < number | null > ( null )
231235 const [ aggregatedCostsMap , setAggregatedCostsMap ] = useState <
232236 Map <
@@ -239,6 +243,23 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
239243 >
240244 > ( new Map ( ) )
241245
246+ const markTaskCondensing = useCallback ( ( taskId : string , condensing : boolean ) => {
247+ setCondensingTaskIds ( ( prev ) => {
248+ const currentlyCondensing = prev . has ( taskId )
249+ if ( currentlyCondensing === condensing ) {
250+ return prev
251+ }
252+
253+ const next = new Set ( prev )
254+ if ( condensing ) {
255+ next . add ( taskId )
256+ } else {
257+ next . delete ( taskId )
258+ }
259+ return next
260+ } )
261+ } , [ ] )
262+
242263 const clineAskRef = useRef ( clineAsk )
243264 useEffect ( ( ) => {
244265 clineAskRef . current = clineAsk
@@ -553,7 +574,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
553574 setExpandedRows ( { } )
554575 everVisibleMessagesTsRef . current . clear ( )
555576 setCurrentFollowUpTs ( null )
556- setIsCondensing ( false )
557577
558578 if ( autoApproveTimeoutRef . current ) {
559579 clearTimeout ( autoApproveTimeoutRef . current )
@@ -660,14 +680,14 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
660680
661681 const handleCondenseContext = useCallback (
662682 ( taskId : string ) => {
663- if ( isCondensing || sendingDisabled ) {
683+ if ( ! taskId || condensingTaskIds . has ( taskId ) || sendingDisabled ) {
664684 return
665685 }
666- setIsCondensing ( true )
686+ markTaskCondensing ( taskId , true )
667687 setSendingDisabled ( true )
668688 vscode . postMessage ( { type : "condenseTaskContextRequest" , text : taskId } )
669689 } ,
670- [ isCondensing , sendingDisabled ] ,
690+ [ condensingTaskIds , markTaskCondensing , sendingDisabled ] ,
671691 )
672692
673693 /**
@@ -689,18 +709,23 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
689709 // /compact-and <msg> condenses, then sends <msg> once condensing completes.
690710 const compactMatch = / ^ \/ c o m p a c t ( - a n d ) ? (?: \s + ( [ \s \S ] + ) ) ? $ / . exec ( text )
691711 if ( compactMatch ) {
692- const taskId = currentTaskItem ?. id
693- if ( ! taskId || messagesRef . current . length === 0 || isCondensing || sendingDisabled ) {
712+ const taskId = currentTaskId ?? currentTaskItem ?. id
713+ if (
714+ ! taskId ||
715+ messagesRef . current . length === 0 ||
716+ condensingTaskIds . has ( taskId ) ||
717+ sendingDisabled
718+ ) {
694719 // Nothing to condense, or a condense is already in flight.
695720 setInputValue ( "" )
696721 setSelectedImages ( [ ] )
697722 return
698723 }
699724 const followUp = ( compactMatch [ 2 ] ?? "" ) . trim ( )
700725 if ( compactMatch [ 1 ] && followUp ) {
701- pendingPostCompactRef . current = { text : followUp , images }
726+ pendingPostCompactRef . current = { taskId , text : followUp , images }
702727 }
703- setIsCondensing ( true )
728+ markTaskCondensing ( taskId , true )
704729 setSendingDisabled ( true )
705730 vscode . postMessage ( { type : "condenseTaskContextRequest" , text : taskId } )
706731 setInputValue ( "" )
@@ -794,6 +819,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
794819 sendingDisabled ,
795820 isStreaming ,
796821 isCondensing ,
822+ condensingTaskIds ,
823+ markTaskCondensing ,
797824 apiConfiguration ?. apiProvider ,
798825 submissionDisabled ,
799826 selectedDraftId ,
@@ -805,16 +832,27 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
805832 // After /compact-and completes, dispatch the follow-up message stashed
806833 // when the user submitted the command.
807834 useEffect ( ( ) => {
808- if ( isCondensing || sendingDisabled ) {
835+ const pending = pendingPostCompactRef . current
836+ if ( ! pending || condensingTaskIds . has ( pending . taskId ) ) {
809837 return
810838 }
811- const pending = pendingPostCompactRef . current
812- if ( ! pending ) {
839+
840+ if ( pending . taskId === currentTaskId && sendingDisabled ) {
813841 return
814842 }
815843 pendingPostCompactRef . current = null
816- handleSendMessage ( pending . text , pending . images )
817- } , [ isCondensing , sendingDisabled , handleSendMessage ] )
844+ if ( pending . taskId === currentTaskId ) {
845+ handleSendMessage ( pending . text , pending . images )
846+ } else {
847+ vscode . postMessage ( {
848+ type : "askResponse" ,
849+ askResponse : "messageResponse" ,
850+ text : pending . text ,
851+ images : pending . images ,
852+ taskId : pending . taskId ,
853+ } )
854+ }
855+ } , [ condensingTaskIds , currentTaskId , sendingDisabled , handleSendMessage ] )
818856
819857 const handleSetChatBoxMessage = useCallback (
820858 ( text : string , images : string [ ] ) => {
@@ -1083,24 +1121,19 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
10831121 }
10841122 break
10851123 case "condenseTaskContextStarted" :
1086- // Handle both manual and automatic condensation start
1087- // We don't check the task ID because:
1088- // 1. There can only be one active task at a time
1089- // 2. Task switching resets isCondensing to false (see useEffect with task?.ts dependency)
1090- // 3. For new tasks, currentTaskItem may not be populated yet due to async state updates
1124+ // Handle both manual and automatic condensation start.
10911125 if ( message . text ) {
1092- setIsCondensing ( true )
1126+ markTaskCondensing ( message . text , true )
10931127 // Note: sendingDisabled is only set for manual condensation via handleCondenseContext
10941128 // Automatic condensation doesn't disable sending since the task is already running
10951129 }
10961130 break
10971131 case "condenseTaskContextResponse" :
1098- // Same reasoning as above - we trust this is for the current task
10991132 if ( message . text ) {
1100- if ( isCondensing && sendingDisabled ) {
1133+ markTaskCondensing ( message . text , false )
1134+ if ( message . text === currentTaskId && sendingDisabled ) {
11011135 setSendingDisabled ( false )
11021136 }
1103- setIsCondensing ( false )
11041137 }
11051138 break
11061139 case "checkpointInitWarning" :
@@ -1124,10 +1157,11 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
11241157 // not using its value but its reference.
11251158 } ,
11261159 [
1127- isCondensing ,
11281160 isHidden ,
11291161 sendingDisabled ,
11301162 enableButtons ,
1163+ currentTaskId ,
1164+ markTaskCondensing ,
11311165 handleChatReset ,
11321166 handleSendMessage ,
11331167 handleSetChatBoxMessage ,
0 commit comments