From c19aeea32561be272bc60fb541b8cefba8639f52 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Nov 2025 00:49:59 +0000 Subject: [PATCH] Clarify regex vs literal text in search result messages (#1757) * Initial plan * Improve presentation of regex-based searches in agent mode - Updated FindTextInFilesTool to indicate "regex" vs "text" in search messages - Updated Claude grep tool formatter to show "Searched for regex" - Added test for literal text search message format - Updated existing test to match new regex message format Co-authored-by: roblourens <323878+roblourens@users.noreply.github.com> * Make regex/text keywords localizable via l10n - Moved 'regex' and 'text' keywords inside l10n.t() calls - This allows localization system to translate or keep terms as appropriate per language - Addresses localization concern about whether 'regex' should be localized Co-authored-by: roblourens <323878+roblourens@users.noreply.github.com> * Refactor nested ternary operators into helper method - Extract message generation logic into getResultMessage helper - Improves code readability and maintainability - All tests passing Co-authored-by: roblourens <323878+roblourens@users.noreply.github.com> * Update ChatSessionContentProvider test snapshot - Updated snapshot to reflect new grep message format - Changed from "Searched text for" to "Searched for regex" - All tests now passing (8/8) Co-authored-by: roblourens <323878+roblourens@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: roblourens <323878+roblourens@users.noreply.github.com> --- .../claude/common/toolInvocationFormatter.ts | 2 +- ...udeChatSessionContentProvider.spec.ts.snap | 2 +- .../tools/node/findTextInFilesTool.tsx | 28 +++++++++++++++---- .../node/test/findTextInFilesTool.spec.tsx | 10 ++++++- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/extensions/copilot/src/extension/agents/claude/common/toolInvocationFormatter.ts b/extensions/copilot/src/extension/agents/claude/common/toolInvocationFormatter.ts index 3bf1cc7bc19..4926d6003d8 100644 --- a/extensions/copilot/src/extension/agents/claude/common/toolInvocationFormatter.ts +++ b/extensions/copilot/src/extension/agents/claude/common/toolInvocationFormatter.ts @@ -75,7 +75,7 @@ function formatGlobInvocation(invocation: ChatToolInvocationPart, toolUse: Anthr function formatGrepInvocation(invocation: ChatToolInvocationPart, toolUse: Anthropic.ToolUseBlock): void { const pattern: string = (toolUse.input as any)?.pattern ?? ''; - invocation.invocationMessage = new MarkdownString(l10n.t("Searched text for `{0}`", pattern)); + invocation.invocationMessage = new MarkdownString(l10n.t("Searched for regex `{0}`", pattern)); } function formatLSInvocation(invocation: ChatToolInvocationPart, toolUse: Anthropic.ToolUseBlock): void { diff --git a/extensions/copilot/src/extension/chatSessions/vscode-node/test/__snapshots__/claudeChatSessionContentProvider.spec.ts.snap b/extensions/copilot/src/extension/chatSessions/vscode-node/test/__snapshots__/claudeChatSessionContentProvider.spec.ts.snap index 5d18ae78079..883c5212460 100644 --- a/extensions/copilot/src/extension/chatSessions/vscode-node/test/__snapshots__/claudeChatSessionContentProvider.spec.ts.snap +++ b/extensions/copilot/src/extension/chatSessions/vscode-node/test/__snapshots__/claudeChatSessionContentProvider.spec.ts.snap @@ -30,7 +30,7 @@ exports[`ChatSessionContentProvider > loads real fixture file with tool invocati { "parts": [ { - "invocationMessage": "Searched text for \`ClaudeAgentManager\`", + "invocationMessage": "Searched for regex \`ClaudeAgentManager\`", "isError": undefined, "toolCallId": "toolu_01FqdrDGdxXUWRRLziM7gS2R", "toolName": "Grep", diff --git a/extensions/copilot/src/extension/tools/node/findTextInFilesTool.tsx b/extensions/copilot/src/extension/tools/node/findTextInFilesTool.tsx index 3fa737f6a96..84064f56f5b 100644 --- a/extensions/copilot/src/extension/tools/node/findTextInFilesTool.tsx +++ b/extensions/copilot/src/extension/tools/node/findTextInFilesTool.tsx @@ -95,16 +95,28 @@ export class FindTextInFilesTool implements ICopilotTool, token: vscode.CancellationToken): vscode.ProviderResult { + const isRegExp = options.input.isRegexp ?? true; + const query = this.formatQueryString(options.input); return { - invocationMessage: new MarkdownString(l10n.t`Searching text for ${this.formatQueryString(options.input)}`), + invocationMessage: isRegExp ? + new MarkdownString(l10n.t`Searching for regex ${query}`) : + new MarkdownString(l10n.t`Searching for text ${query}`), }; } diff --git a/extensions/copilot/src/extension/tools/node/test/findTextInFilesTool.spec.tsx b/extensions/copilot/src/extension/tools/node/test/findTextInFilesTool.spec.tsx index a89458b4fe1..e2df02420ea 100644 --- a/extensions/copilot/src/extension/tools/node/test/findTextInFilesTool.spec.tsx +++ b/extensions/copilot/src/extension/tools/node/test/findTextInFilesTool.spec.tsx @@ -89,7 +89,15 @@ suite('FindTextInFiles', () => { const tool = accessor.get(IInstantiationService).createInstance(FindTextInFilesTool); const prepared = await tool.prepareInvocation({ input: { query: 'hello `world`' }, }, CancellationToken.None); - expect((prepared?.invocationMessage as any as MarkdownString).value).toMatchInlineSnapshot(`"Searching text for \`\` hello \`world\` \`\`"`); + expect((prepared?.invocationMessage as any as MarkdownString).value).toMatchInlineSnapshot(`"Searching for regex \`\` hello \`world\` \`\`"`); + }); + + test('prepares invocation message with text for literal search', async () => { + setup(new RelativePattern(URI.file(workspaceFolder), ''), false); + + const tool = accessor.get(IInstantiationService).createInstance(FindTextInFilesTool); + const prepared = await tool.prepareInvocation({ input: { query: 'hello', isRegexp: false }, }, CancellationToken.None); + expect((prepared?.invocationMessage as any as MarkdownString).value).toMatchInlineSnapshot(`"Searching for text \`hello\`"`); }); test('retries with plain text when regex yields no results', async () => {