Skip to content

Commit e898ef6

Browse files
authored
fix serialized finished tool calls showing up in thinking (#307200)
1 parent 54b695e commit e898ef6

3 files changed

Lines changed: 23 additions & 4 deletions

File tree

src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingContentPart.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ export class ChatThinkingContentPart extends ChatCollapsibleContentPart implemen
844844
* and the thinking part was only created to hold that tool.
845845
*/
846846
public isEffectivelyEmpty(): boolean {
847+
this.processPendingRemovals();
847848
if (this.toolInvocationCount > 0 || this.lazyItems.length > 0 || this.hookCount > 0) {
848849
return false;
849850
}
@@ -1562,6 +1563,12 @@ ${this.hookCount > 0 ? `EXAMPLES WITH BLOCKED CONTENT (from hooks):
15621563
// Render external image pills for serialized (already-completed) tool invocations
15631564
if (toolInvocationOrMarkdown.kind === 'toolInvocationSerialized') {
15641565
this.updateExternalResourceParts(toolInvocationOrMarkdown);
1566+
1567+
// Queue hidden serialized tools for removal immediately.
1568+
if (IChatToolInvocation.isEffectivelyHidden(toolInvocationOrMarkdown)) {
1569+
this.pendingRemovals.push({ toolCallId: toolInvocationOrMarkdown.toolCallId, toolLabel: toolCallLabel });
1570+
this.schedulePendingRemovalsFlush();
1571+
}
15651572
}
15661573

15671574
// track state for live/still streaming tools, excluding serialized tools

src/vs/workbench/contrib/chat/browser/widget/chatListRenderer.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,7 +1057,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
10571057
!lastPart ||
10581058
lastPart.kind === 'references' ||
10591059
(lastPart.kind === 'markdownContent' && !moreContentAvailable && this.hasBeenCaughtUpLongEnough(element)) ||
1060-
((lastPart.kind === 'toolInvocation' || lastPart.kind === 'toolInvocationSerialized') && (IChatToolInvocation.isComplete(lastPart) || lastPart.presentation === 'hidden')) ||
1060+
((lastPart.kind === 'toolInvocation' || lastPart.kind === 'toolInvocationSerialized') && (IChatToolInvocation.isComplete(lastPart) || IChatToolInvocation.isEffectivelyHidden(lastPart))) ||
10611061
((lastPart.kind === 'textEditGroup' || lastPart.kind === 'notebookEditGroup') && lastPart.done && !partsToRender.some(part => part.kind === 'toolInvocation' && !IChatToolInvocation.isComplete(part))) ||
10621062
(lastPart.kind === 'progressTask' && lastPart.deferred.isSettled) ||
10631063
lastPart.kind === 'mcpServersStarting' ||
@@ -1969,7 +1969,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
19691969
const lastThinking = this.getLastThinkingPart(templateData.renderedParts);
19701970

19711971
// create thinking part if it doesn't exist yet
1972-
if (!lastThinking && toolInvocation.presentation !== 'hidden' && this.shouldPinPart(toolInvocation, context.element) && collapsedToolsMode === CollapsedToolsDisplayMode.Always) {
1972+
if (!lastThinking && !IChatToolInvocation.isEffectivelyHidden(toolInvocation) && this.shouldPinPart(toolInvocation, context.element) && collapsedToolsMode === CollapsedToolsDisplayMode.Always) {
19731973
const thinkingPart = this.renderThinkingPart({
19741974
kind: 'thinking',
19751975
}, context, templateData);
@@ -1985,7 +1985,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
19851985
}
19861986

19871987
if (this.shouldPinPart(toolInvocation, context.element)) {
1988-
if (lastThinking && toolInvocation.presentation !== 'hidden') {
1988+
if (lastThinking && !IChatToolInvocation.isEffectivelyHidden(toolInvocation)) {
19891989
// Append using factory - thinking part decides whether to render lazily
19901990
toolInvocation.isAttachedToThinking = true;
19911991
lastThinking.appendItem(createToolPart, toolInvocation.toolId, toolInvocation, templateData.value);
@@ -2001,7 +2001,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
20012001

20022002
// Check for subagent grouping before creating tool part - subagent part handles lazy creation
20032003
const subagentId = getSubagentId(toolInvocation);
2004-
if (subagentId && isResponseVM(context.element) && toolInvocation.presentation !== 'hidden') {
2004+
if (subagentId && isResponseVM(context.element) && !IChatToolInvocation.isEffectivelyHidden(toolInvocation)) {
20052005
return this.handleSubagentToolGrouping(toolInvocation, subagentId, context, templateData, codeBlockStartIndex);
20062006
}
20072007

@@ -2143,6 +2143,8 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
21432143
return;
21442144
}
21452145

2146+
this.finalizeCurrentThinkingPart(context, templateData);
2147+
21462148
const taskPart = this.instantiationService.createInstance(ChatTaskContentPart, task, this._contentReferencesListPool, this.chatContentMarkdownRenderer, context);
21472149
return taskPart;
21482150
}

src/vs/workbench/contrib/chat/common/chatService/chatService.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,16 @@ export namespace IChatToolInvocation {
818818
return state.type === StateKind.Completed || state.type === StateKind.Cancelled;
819819
}
820820

821+
export function isEffectivelyHidden(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): boolean {
822+
if (invocation.presentation === 'hidden') {
823+
return true;
824+
}
825+
if (invocation.presentation === 'hiddenAfterComplete' && isComplete(invocation, reader)) {
826+
return true;
827+
}
828+
return false;
829+
}
830+
821831
export function isStreaming(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): boolean {
822832
if (invocation.kind === 'toolInvocationSerialized') {
823833
return false;

0 commit comments

Comments
 (0)