From d9bb11ef313f9b4d6737af2d7d41457b7af5cdab Mon Sep 17 00:00:00 2001 From: Justin Chen <54879025+justschen@users.noreply.github.com> Date: Thu, 29 Jan 2026 16:48:46 -0800 Subject: [PATCH] associate spinner text with tool call or reasoning block (#291762) * associate spinner text with tool call or reasoning block * address some comments, removed a loading title --- .../chatThinkingContentPart.ts | 74 ++++++++++++++----- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingContentPart.ts b/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingContentPart.ts index cd47bd2f2aa..ce9c70c41d7 100644 --- a/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingContentPart.ts +++ b/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingContentPart.ts @@ -108,15 +108,32 @@ interface ILazyThinkingItem { type ILazyItem = ILazyToolItem | ILazyThinkingItem; const THINKING_SCROLL_MAX_HEIGHT = 200; -const workingMessages = [ - localize('chat.thinking.working.1', 'Thinking...'), - localize('chat.thinking.working.2', 'Processing...'), - localize('chat.thinking.working.3', 'Analyzing...'), - localize('chat.thinking.working.4', 'Computing...'), - localize('chat.thinking.working.5', 'Loading...'), - localize('chat.thinking.working.6', 'Reasoning...'), - localize('chat.thinking.working.7', 'Evaluating...'), - localize('chat.thinking.working.8', 'Preparing...'), +const enum WorkingMessageCategory { + Thinking = 'thinking', + Terminal = 'terminal', + Tool = 'tool' +} + +const thinkingMessages = [ + localize('chat.thinking.thinking.1', 'Thinking...'), + localize('chat.thinking.thinking.2', 'Reasoning...'), + localize('chat.thinking.thinking.3', 'Considering...'), + localize('chat.thinking.thinking.4', 'Analyzing...'), + localize('chat.thinking.thinking.5', 'Evaluating...'), +]; + +const terminalMessages = [ + localize('chat.thinking.terminal.1', 'Executing...'), + localize('chat.thinking.terminal.2', 'Running...'), + localize('chat.thinking.terminal.3', 'Processing...'), +]; + +const toolMessages = [ + localize('chat.thinking.tool.1', 'Processing...'), + localize('chat.thinking.tool.2', 'Preparing...'), + localize('chat.thinking.tool.3', 'Loading...'), + localize('chat.thinking.tool.4', 'Analyzing...'), + localize('chat.thinking.tool.5', 'Evaluating...'), ]; export class ChatThinkingContentPart extends ChatCollapsibleContentPart implements IChatContentPart { @@ -147,7 +164,7 @@ export class ChatThinkingContentPart extends ChatCollapsibleContentPart implemen private hasExpandedOnce: boolean = false; private workingSpinnerElement: HTMLElement | undefined; private workingSpinnerLabel: HTMLElement | undefined; - private availableWorkingMessages: string[] = [...workingMessages]; + private availableMessagesByCategory = new Map(); private readonly toolWrappersByCallId = new Map(); private readonly toolDisposables = this._register(new DisposableMap()); private pendingRemovals: { toolCallId: string; toolLabel: string }[] = []; @@ -155,12 +172,25 @@ export class ChatThinkingContentPart extends ChatCollapsibleContentPart implemen private mutationObserverDisposable: IDisposable | undefined; private isUpdatingDimensions: boolean = false; - private getRandomWorkingMessage(): string { - if (this.availableWorkingMessages.length === 0) { - this.availableWorkingMessages = [...workingMessages]; + private getRandomWorkingMessage(category: WorkingMessageCategory = WorkingMessageCategory.Tool): string { + let pool = this.availableMessagesByCategory.get(category); + if (!pool || pool.length === 0) { + switch (category) { + case WorkingMessageCategory.Thinking: + pool = [...thinkingMessages]; + break; + case WorkingMessageCategory.Terminal: + pool = [...terminalMessages]; + break; + case WorkingMessageCategory.Tool: + default: + pool = [...toolMessages]; + break; + } + this.availableMessagesByCategory.set(category, pool); } - const index = Math.floor(Math.random() * this.availableWorkingMessages.length); - return this.availableWorkingMessages.splice(index, 1)[0]; + const index = Math.floor(Math.random() * pool.length); + return pool.splice(index, 1)[0]; } constructor( @@ -298,7 +328,7 @@ export class ChatThinkingContentPart extends ChatCollapsibleContentPart implemen const spinnerIcon = createThinkingIcon(ThemeIcon.modify(Codicon.loading, 'spin')); this.workingSpinnerElement.appendChild(spinnerIcon); this.workingSpinnerLabel = $('span.chat-thinking-spinner-label'); - this.workingSpinnerLabel.textContent = this.getRandomWorkingMessage(); + this.workingSpinnerLabel.textContent = this.getRandomWorkingMessage(WorkingMessageCategory.Thinking); this.workingSpinnerElement.appendChild(this.workingSpinnerLabel); this.wrapper.appendChild(this.workingSpinnerElement); } @@ -905,9 +935,11 @@ export class ChatThinkingContentPart extends ChatCollapsibleContentPart implemen this.trackToolMetadata(toolInvocationId, toolInvocationOrMarkdown); this.appendedItemCount++; - // get random title + // get random message based on tool type if (this.workingSpinnerLabel) { - this.workingSpinnerLabel.textContent = this.getRandomWorkingMessage(); + const isTerminalTool = toolInvocationOrMarkdown && (toolInvocationOrMarkdown.kind === 'toolInvocation' || toolInvocationOrMarkdown.kind === 'toolInvocationSerialized') && toolInvocationOrMarkdown.toolSpecificData?.kind === 'terminal'; + const category = isTerminalTool ? WorkingMessageCategory.Terminal : WorkingMessageCategory.Tool; + this.workingSpinnerLabel.textContent = this.getRandomWorkingMessage(category); } // If expanded or has been expanded once, render immediately @@ -1208,7 +1240,9 @@ export class ChatThinkingContentPart extends ChatCollapsibleContentPart implemen } if (this.workingSpinnerLabel) { - this.workingSpinnerLabel.textContent = this.getRandomWorkingMessage(); + const isTerminalTool = item.toolInvocationOrMarkdown && (item.toolInvocationOrMarkdown.kind === 'toolInvocation' || item.toolInvocationOrMarkdown.kind === 'toolInvocationSerialized') && item.toolInvocationOrMarkdown.toolSpecificData?.kind === 'terminal'; + const category = isTerminalTool ? WorkingMessageCategory.Terminal : WorkingMessageCategory.Tool; + this.workingSpinnerLabel.textContent = this.getRandomWorkingMessage(category); } // Handle tool items @@ -1259,7 +1293,7 @@ export class ChatThinkingContentPart extends ChatCollapsibleContentPart implemen } if (this.workingSpinnerLabel) { - this.workingSpinnerLabel.textContent = this.getRandomWorkingMessage(); + this.workingSpinnerLabel.textContent = this.getRandomWorkingMessage(WorkingMessageCategory.Thinking); } } this.updateDropdownClickability();