Skip to content

Commit 80b2984

Browse files
authored
improve search and replace tool (#2764)
* Refactor search and replace tool * feat(search-replace): enhance search/replace tool UI and messaging Refactor search/replace tool message structure for better consistency Add dedicated UI component for displaying search/replace operations Add i18n support for search/replace operations in all supported languages Improve partial tool handling in searchAndReplaceTool * Remove search_and_replace experiment and related references
1 parent 61e23cc commit 80b2984

File tree

33 files changed

+875
-356
lines changed

33 files changed

+875
-356
lines changed

evals/packages/types/src/roo-code-defaults.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ export const rooCodeDefaults: RooCodeSettings = {
5656
diffEnabled: true,
5757
fuzzyMatchThreshold: 1.0,
5858
experiments: {
59-
search_and_replace: false,
6059
insert_content: false,
6160
powerSteering: false,
6261
},

evals/packages/types/src/roo-code.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ export type CustomSupportPrompts = z.infer<typeof customSupportPromptsSchema>
271271
* ExperimentId
272272
*/
273273

274-
export const experimentIds = ["search_and_replace", "insert_content", "powerSteering"] as const
274+
export const experimentIds = ["insert_content", "powerSteering"] as const
275275

276276
export const experimentIdsSchema = z.enum(experimentIds)
277277

@@ -282,7 +282,6 @@ export type ExperimentId = z.infer<typeof experimentIdsSchema>
282282
*/
283283

284284
const experimentsSchema = z.object({
285-
search_and_replace: z.boolean(),
286285
insert_content: z.boolean(),
287286
powerSteering: z.boolean(),
288287
})

src/core/prompts/__tests__/__snapshots__/system.test.ts.snap

Lines changed: 514 additions & 97 deletions
Large diffs are not rendered by default.

src/core/prompts/__tests__/system.test.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ describe("SYSTEM_PROMPT", () => {
171171
beforeEach(() => {
172172
// Reset experiments before each test to ensure they're disabled by default
173173
experiments = {
174-
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: false,
175174
[EXPERIMENT_IDS.INSERT_BLOCK]: false,
176175
}
177176
})
@@ -482,7 +481,6 @@ describe("SYSTEM_PROMPT", () => {
482481
it("should disable experimental tools by default", async () => {
483482
// Set experiments to explicitly disable experimental tools
484483
const experimentsConfig = {
485-
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: false,
486484
[EXPERIMENT_IDS.INSERT_BLOCK]: false,
487485
}
488486

@@ -508,15 +506,13 @@ describe("SYSTEM_PROMPT", () => {
508506
// Check that experimental tool sections are not included
509507
const toolSections = prompt.split("\n## ").slice(1)
510508
const toolNames = toolSections.map((section) => section.split("\n")[0].trim())
511-
expect(toolNames).not.toContain("search_and_replace")
512509
expect(toolNames).not.toContain("insert_content")
513510
expect(prompt).toMatchSnapshot()
514511
})
515512

516513
it("should enable experimental tools when explicitly enabled", async () => {
517514
// Set experiments for testing experimental features
518515
const experimentsEnabled = {
519-
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: true,
520516
[EXPERIMENT_IDS.INSERT_BLOCK]: true,
521517
}
522518

@@ -544,15 +540,13 @@ describe("SYSTEM_PROMPT", () => {
544540
const toolNames = toolSections.map((section) => section.split("\n")[0].trim())
545541

546542
// Verify experimental tools are included in the prompt when enabled
547-
expect(toolNames).toContain("search_and_replace")
548543
expect(toolNames).toContain("insert_content")
549544
expect(prompt).toMatchSnapshot()
550545
})
551546

552547
it("should selectively enable experimental tools", async () => {
553548
// Set experiments for testing selective enabling
554549
const experimentsSelective = {
555-
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: true,
556550
[EXPERIMENT_IDS.INSERT_BLOCK]: false,
557551
}
558552

@@ -580,14 +574,12 @@ describe("SYSTEM_PROMPT", () => {
580574
const toolNames = toolSections.map((section) => section.split("\n")[0].trim())
581575

582576
// Verify only enabled experimental tools are included
583-
expect(toolNames).toContain("search_and_replace")
584577
expect(toolNames).not.toContain("insert_content")
585578
expect(prompt).toMatchSnapshot()
586579
})
587580

588581
it("should list all available editing tools in base instruction", async () => {
589582
const experiments = {
590-
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: true,
591583
[EXPERIMENT_IDS.INSERT_BLOCK]: true,
592584
}
593585

@@ -615,7 +607,6 @@ describe("SYSTEM_PROMPT", () => {
615607
})
616608
it("should provide detailed instructions for each enabled tool", async () => {
617609
const experiments = {
618-
[EXPERIMENT_IDS.SEARCH_AND_REPLACE]: true,
619610
[EXPERIMENT_IDS.INSERT_BLOCK]: true,
620611
}
621612

@@ -640,7 +631,6 @@ describe("SYSTEM_PROMPT", () => {
640631
"You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files.",
641632
)
642633
expect(prompt).toContain("The insert_content tool adds lines of text to files")
643-
expect(prompt).toContain("The search_and_replace tool finds and replaces text or regex in files")
644634
})
645635
})
646636

src/core/prompts/sections/rules.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ function getEditingInstructions(diffStrategy?: DiffStrategy, experiments?: Recor
1919
if (experiments?.["insert_content"]) {
2020
availableTools.push("insert_content (for adding lines to existing files)")
2121
}
22-
if (experiments?.["search_and_replace"]) {
23-
availableTools.push("search_and_replace (for finding and replacing individual pieces of text)")
24-
}
22+
23+
availableTools.push("search_and_replace (for finding and replacing individual pieces of text)")
2524

2625
// Base editing instruction mentioning all available tools
2726
if (availableTools.length > 1) {
@@ -38,11 +37,9 @@ function getEditingInstructions(diffStrategy?: DiffStrategy, experiments?: Recor
3837
)
3938
}
4039

41-
if (experiments?.["search_and_replace"]) {
42-
instructions.push(
43-
"- The search_and_replace tool finds and replaces text or regex in files. This tool allows you to search for a specific regex pattern or text and replace it with another value. Be cautious when using this tool to ensure you are replacing the correct text. It can support multiple operations at once.",
44-
)
45-
}
40+
instructions.push(
41+
"- The search_and_replace tool finds and replaces text or regex in files. This tool allows you to search for a specific regex pattern or text and replace it with another value. Be cautious when using this tool to ensure you are replacing the correct text. It can support multiple operations at once.",
42+
)
4643

4744
if (availableTools.length > 1) {
4845
instructions.push(

src/core/prompts/tools/search-and-replace.ts

Lines changed: 28 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,38 @@ import { ToolArgs } from "./types"
22

33
export function getSearchAndReplaceDescription(args: ToolArgs): string {
44
return `## search_and_replace
5-
Description: Request to perform search and replace operations on a file. Each operation can specify a search pattern (string or regex) and replacement text, with optional line range restrictions and regex flags. Shows a diff preview before applying changes.
6-
Parameters:
7-
- path: (required) The path of the file to modify (relative to the current workspace directory ${args.cwd.toPosix()})
8-
- operations: (required) A JSON array of search/replace operations. Each operation is an object with:
9-
* search: (required) The text or pattern to search for
10-
* replace: (required) The text to replace matches with. If multiple lines need to be replaced, use "\n" for newlines
11-
* start_line: (optional) Starting line number for restricted replacement
12-
* end_line: (optional) Ending line number for restricted replacement
13-
* use_regex: (optional) Whether to treat search as a regex pattern
14-
* ignore_case: (optional) Whether to ignore case when matching
15-
* regex_flags: (optional) Additional regex flags when use_regex is true
16-
Usage:
17-
<search_and_replace>
18-
<path>File path here</path>
19-
<operations>[
20-
{
21-
"search": "text to find",
22-
"replace": "replacement text",
23-
"start_line": 1,
24-
"end_line": 10
25-
}
26-
]</operations>
27-
</search_and_replace>
28-
Example: Replace "foo" with "bar" in lines 1-10 of example.ts
5+
Description: Request to perform a search and replace operation on a file. Supports both literal text and regex patterns. Shows a diff preview before applying changes.
6+
7+
Required Parameters:
8+
- path: The path of the file to modify (relative to the current workspace directory ${args.cwd.toPosix()})
9+
- search: The text or pattern to search for
10+
- replace: The text to replace matches with
11+
12+
Optional Parameters:
13+
- start_line: Starting line number for restricted replacement (1-based)
14+
- end_line: Ending line number for restricted replacement (1-based)
15+
- use_regex: Set to "true" to treat search as a regex pattern (default: false)
16+
- ignore_case: Set to "true" to ignore case when matching (default: false)
17+
18+
Notes:
19+
- When use_regex is true, the search parameter is treated as a regular expression pattern
20+
- When ignore_case is true, the search is case-insensitive regardless of regex mode
21+
22+
Examples:
23+
24+
1. Simple text replacement:
2925
<search_and_replace>
3026
<path>example.ts</path>
31-
<operations>[
32-
{
33-
"search": "foo",
34-
"replace": "bar",
35-
"start_line": 1,
36-
"end_line": 10
37-
}
38-
]</operations>
27+
<search>oldText</search>
28+
<replace>newText</replace>
3929
</search_and_replace>
40-
Example: Replace all occurrences of "old" with "new" using regex
30+
31+
2. Case-insensitive regex pattern:
4132
<search_and_replace>
4233
<path>example.ts</path>
43-
<operations>[
44-
{
45-
"search": "old\\w+",
46-
"replace": "new$&",
47-
"use_regex": true,
48-
"ignore_case": true
49-
}
50-
]</operations>
34+
<search>old\w+</search>
35+
<replace>new$&</replace>
36+
<use_regex>true</use_regex>
37+
<ignore_case>true</ignore_case>
5138
</search_and_replace>`
5239
}

0 commit comments

Comments
 (0)