@@ -1169,8 +1169,10 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
11691169 private renderChatContentDiff ( partsToRender : ReadonlyArray < IChatRendererContent | null > , contentForThisTurn : ReadonlyArray < IChatRendererContent > , element : IChatResponseViewModel , elementIndex : number , templateData : IChatListItemTemplate ) : void {
11701170 const renderedParts = templateData . renderedParts ?? [ ] ;
11711171 templateData . renderedParts = renderedParts ;
1172+ const lastMarkdownIndex = partsToRender . findLastIndex ( part => part ?. kind === 'markdownContent' ) ;
11721173 partsToRender . forEach ( ( partToRender , contentIndex ) => {
11731174 const alreadyRenderedPart = templateData . renderedParts ?. [ contentIndex ] ;
1175+ const isFinalAnswerPart = partToRender ?. kind === 'markdownContent' && contentIndex === lastMarkdownIndex && element . isComplete ;
11741176
11751177 if ( ! partToRender ) {
11761178 // null=no change
@@ -1188,7 +1190,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
11881190 }
11891191 renderedParts [ contentIndex ] = alreadyRenderedPart ;
11901192 return ;
1191- } else if ( alreadyRenderedPart instanceof ChatThinkingContentPart && this . shouldPinPart ( partToRender , element ) ) {
1193+ } else if ( alreadyRenderedPart instanceof ChatThinkingContentPart && this . shouldPinPart ( partToRender , element ) && ! isFinalAnswerPart ) {
11921194 // keep existing thinking part if we are pinning it (combining tool calls into it)
11931195 renderedParts [ contentIndex ] = alreadyRenderedPart ;
11941196 return ;
@@ -1219,7 +1221,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
12191221
12201222 // combine tool invocations into thinking part if needed. render the tool, but do not replace the working spinner with the new part's dom node since it is already inside the thinking part.
12211223 const lastThinking = this . getLastThinkingPart ( renderedParts ) ;
1222- if ( lastThinking && ( partToRender . kind === 'toolInvocation' || partToRender . kind === 'toolInvocationSerialized' || partToRender . kind === 'markdownContent' || partToRender . kind === 'textEditGroup' || partToRender . kind === 'hook' ) && this . shouldPinPart ( partToRender , element ) ) {
1224+ if ( lastThinking && ( partToRender . kind === 'toolInvocation' || partToRender . kind === 'toolInvocationSerialized' || partToRender . kind === 'markdownContent' || partToRender . kind === 'textEditGroup' || partToRender . kind === 'hook' ) && this . shouldPinPart ( partToRender , element ) && ! isFinalAnswerPart ) {
12231225 const newPart = this . renderChatContentPart ( partToRender , templateData , context ) ;
12241226 if ( newPart ) {
12251227 renderedParts [ contentIndex ] = newPart ;
@@ -1379,9 +1381,17 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
13791381
13801382 private diff ( renderedParts : ReadonlyArray < IChatContentPart > , contentToRender : ReadonlyArray < IChatRendererContent > , element : ChatTreeItem ) : ReadonlyArray < IChatRendererContent | null > {
13811383 const diff : ( IChatRendererContent | null ) [ ] = [ ] ;
1384+ const elementIsComplete = isResponseVM ( element ) && element . isComplete ;
1385+ const lastMarkdownContentIndex = contentToRender . findLastIndex ( part => part . kind === 'markdownContent' ) ;
13821386 for ( let i = 0 ; i < contentToRender . length ; i ++ ) {
13831387 const content = contentToRender [ i ] ;
13841388 const renderedPart = renderedParts [ i ] ;
1389+ const isFinalAnswerPart = content . kind === 'markdownContent' && i === lastMarkdownContentIndex && elementIsComplete ;
1390+
1391+ if ( isFinalAnswerPart && this . isRenderedPartInsideThinking ( renderedPart ) ) {
1392+ diff . push ( content ) ;
1393+ continue ;
1394+ }
13851395
13861396 if ( ! renderedPart || ! renderedPart . hasSameContent ( content , contentToRender . slice ( i + 1 ) , element ) ) {
13871397 diff . push ( content ) ;
@@ -1394,6 +1404,13 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
13941404 return diff ;
13951405 }
13961406
1407+ private isRenderedPartInsideThinking ( renderedPart : IChatContentPart | undefined ) : boolean {
1408+ if ( ! renderedPart ?. domNode ) {
1409+ return false ;
1410+ }
1411+ return ! ! dom . findParentWithClass ( renderedPart . domNode , 'chat-thinking-box' ) ;
1412+ }
1413+
13971414 private hasCodeblockUri ( part : IChatRendererContent ) : boolean {
13981415 if ( part . kind !== 'markdownContent' ) {
13991416 return false ;
0 commit comments