Skip to content

Commit 7b87ba2

Browse files
Copilotroblourens
andauthored
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>
1 parent 9f0637d commit 7b87ba2

File tree

4 files changed

+33
-9
lines changed

4 files changed

+33
-9
lines changed

src/extension/agents/claude/common/toolInvocationFormatter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ function formatGlobInvocation(invocation: ChatToolInvocationPart, toolUse: Anthr
7575

7676
function formatGrepInvocation(invocation: ChatToolInvocationPart, toolUse: Anthropic.ToolUseBlock): void {
7777
const pattern: string = (toolUse.input as any)?.pattern ?? '';
78-
invocation.invocationMessage = new MarkdownString(l10n.t("Searched text for `{0}`", pattern));
78+
invocation.invocationMessage = new MarkdownString(l10n.t("Searched for regex `{0}`", pattern));
7979
}
8080

8181
function formatLSInvocation(invocation: ChatToolInvocationPart, toolUse: Anthropic.ToolUseBlock): void {

src/extension/chatSessions/vscode-node/test/__snapshots__/claudeChatSessionContentProvider.spec.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ exports[`ChatSessionContentProvider > loads real fixture file with tool invocati
3030
{
3131
"parts": [
3232
{
33-
"invocationMessage": "Searched text for \`ClaudeAgentManager\`",
33+
"invocationMessage": "Searched for regex \`ClaudeAgentManager\`",
3434
"isError": undefined,
3535
"toolCallId": "toolu_01FqdrDGdxXUWRRLziM7gS2R",
3636
"toolName": "Grep",

src/extension/tools/node/findTextInFilesTool.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,28 @@ export class FindTextInFilesTool implements ICopilotTool<IFindTextInFilesToolPar
9595
return [];
9696
}).slice(0, maxResults);
9797
const query = this.formatQueryString(options.input);
98-
result.toolResultMessage = textMatches.length === 0 ?
99-
new MarkdownString(l10n.t`Searched text for ${query}, no results`) :
100-
textMatches.length === 1 ?
101-
new MarkdownString(l10n.t`Searched text for ${query}, 1 result`) :
102-
new MarkdownString(l10n.t`Searched text for ${query}, ${textMatches.length} results`);
98+
result.toolResultMessage = this.getResultMessage(isRegExp, query, textMatches.length);
10399

104100
result.toolResultDetails = textMatches;
105101
return result;
106102
}
107103

104+
private getResultMessage(isRegExp: boolean, query: string, count: number): MarkdownString {
105+
if (count === 0) {
106+
return isRegExp
107+
? new MarkdownString(l10n.t`Searched for regex ${query}, no results`)
108+
: new MarkdownString(l10n.t`Searched for text ${query}, no results`);
109+
} else if (count === 1) {
110+
return isRegExp
111+
? new MarkdownString(l10n.t`Searched for regex ${query}, 1 result`)
112+
: new MarkdownString(l10n.t`Searched for text ${query}, 1 result`);
113+
} else {
114+
return isRegExp
115+
? new MarkdownString(l10n.t`Searched for regex ${query}, ${count} results`)
116+
: new MarkdownString(l10n.t`Searched for text ${query}, ${count} results`);
117+
}
118+
}
119+
108120
private isValidRegex(pattern: string): boolean {
109121
try {
110122
new RegExp(pattern);
@@ -138,8 +150,12 @@ export class FindTextInFilesTool implements ICopilotTool<IFindTextInFilesToolPar
138150
}
139151

140152
prepareInvocation(options: vscode.LanguageModelToolInvocationPrepareOptions<IFindTextInFilesToolParams>, token: vscode.CancellationToken): vscode.ProviderResult<vscode.PreparedToolInvocation> {
153+
const isRegExp = options.input.isRegexp ?? true;
154+
const query = this.formatQueryString(options.input);
141155
return {
142-
invocationMessage: new MarkdownString(l10n.t`Searching text for ${this.formatQueryString(options.input)}`),
156+
invocationMessage: isRegExp ?
157+
new MarkdownString(l10n.t`Searching for regex ${query}`) :
158+
new MarkdownString(l10n.t`Searching for text ${query}`),
143159
};
144160
}
145161

src/extension/tools/node/test/findTextInFilesTool.spec.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,15 @@ suite('FindTextInFiles', () => {
8989

9090
const tool = accessor.get(IInstantiationService).createInstance(FindTextInFilesTool);
9191
const prepared = await tool.prepareInvocation({ input: { query: 'hello `world`' }, }, CancellationToken.None);
92-
expect((prepared?.invocationMessage as any as MarkdownString).value).toMatchInlineSnapshot(`"Searching text for \`\` hello \`world\` \`\`"`);
92+
expect((prepared?.invocationMessage as any as MarkdownString).value).toMatchInlineSnapshot(`"Searching for regex \`\` hello \`world\` \`\`"`);
93+
});
94+
95+
test('prepares invocation message with text for literal search', async () => {
96+
setup(new RelativePattern(URI.file(workspaceFolder), ''), false);
97+
98+
const tool = accessor.get(IInstantiationService).createInstance(FindTextInFilesTool);
99+
const prepared = await tool.prepareInvocation({ input: { query: 'hello', isRegexp: false }, }, CancellationToken.None);
100+
expect((prepared?.invocationMessage as any as MarkdownString).value).toMatchInlineSnapshot(`"Searching for text \`hello\`"`);
93101
});
94102

95103
test('retries with plain text when regex yields no results', async () => {

0 commit comments

Comments
 (0)