Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/types/src/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const toolNames = [
"write_to_file",
"apply_diff",
"search_and_replace",
"search_replace",
"apply_patch",
"search_files",
"list_files",
Expand Down
28 changes: 28 additions & 0 deletions src/core/assistant-message/NativeToolCallParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,20 @@ export class NativeToolCallParser {
}
break

case "search_replace":
if (
partialArgs.file_path !== undefined ||
partialArgs.old_string !== undefined ||
partialArgs.new_string !== undefined
) {
nativeArgs = {
file_path: partialArgs.file_path,
old_string: partialArgs.old_string,
new_string: partialArgs.new_string,
}
}
break

// Add other tools as needed
default:
break
Expand Down Expand Up @@ -742,6 +756,20 @@ export class NativeToolCallParser {
}
break

case "search_replace":
if (
args.file_path !== undefined &&
args.old_string !== undefined &&
args.new_string !== undefined
) {
nativeArgs = {
file_path: args.file_path,
old_string: args.old_string,
new_string: args.new_string,
} as NativeArgsFor<TName>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@roomote Remove this type override.

Note: We need to later look into typing for nativeArgs in general.

Copy link
Contributor

@roomote roomote bot Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixaroo Clock   See task on Roo Cloud

Fixed the reported issue. Since PR #9918 was already merged, created follow-up PR #9922 with the fix. All local checks passed.

View commit | View follow-up PR | Revert commit

}
break

default:
break
}
Expand Down
13 changes: 13 additions & 0 deletions src/core/assistant-message/presentAssistantMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { shouldUseSingleFileRead, TOOL_PROTOCOL } from "@roo-code/types"
import { writeToFileTool } from "../tools/WriteToFileTool"
import { applyDiffTool } from "../tools/MultiApplyDiffTool"
import { searchAndReplaceTool } from "../tools/SearchAndReplaceTool"
import { searchReplaceTool } from "../tools/SearchReplaceTool"
import { applyPatchTool } from "../tools/ApplyPatchTool"
import { listCodeDefinitionNamesTool } from "../tools/ListCodeDefinitionNamesTool"
import { searchFilesTool } from "../tools/SearchFilesTool"
Expand Down Expand Up @@ -385,6 +386,8 @@ export async function presentAssistantMessage(cline: Task) {
}]`
case "search_and_replace":
return `[${block.name} for '${block.params.path}']`
case "search_replace":
return `[${block.name} for '${block.params.file_path}']`
case "apply_patch":
return `[${block.name}]`
case "list_files":
Expand Down Expand Up @@ -835,6 +838,16 @@ export async function presentAssistantMessage(cline: Task) {
toolProtocol,
})
break
case "search_replace":
await checkpointSaveAndMark(cline)
await searchReplaceTool.handle(cline, block as ToolUse<"search_replace">, {
askApproval,
handleError,
pushToolResult,
removeClosingTag,
toolProtocol,
})
break
case "apply_patch":
await checkpointSaveAndMark(cline)
await applyPatchTool.handle(cline, block as ToolUse<"apply_patch">, {
Expand Down
2 changes: 2 additions & 0 deletions src/core/prompts/tools/native-tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import newTask from "./new_task"
import { createReadFileTool } from "./read_file"
import runSlashCommand from "./run_slash_command"
import searchAndReplace from "./search_and_replace"
import searchReplace from "./search_replace"
import searchFiles from "./search_files"
import switchMode from "./switch_mode"
import updateTodoList from "./update_todo_list"
Expand Down Expand Up @@ -47,6 +48,7 @@ export function getNativeTools(partialReadsEnabled: boolean = true): OpenAI.Chat
createReadFileTool(partialReadsEnabled),
runSlashCommand,
searchAndReplace,
searchReplace,
searchFiles,
switchMode,
updateTodoList,
Expand Down
51 changes: 51 additions & 0 deletions src/core/prompts/tools/native-tools/search_replace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type OpenAI from "openai"

const SEARCH_REPLACE_DESCRIPTION = `Use this tool to propose a search and replace operation on an existing file.

The tool will replace ONE occurrence of old_string with new_string in the specified file.

CRITICAL REQUIREMENTS FOR USING THIS TOOL:

1. UNIQUENESS: The old_string MUST uniquely identify the specific instance you want to change. This means:
- Include AT LEAST 3-5 lines of context BEFORE the change point
- Include AT LEAST 3-5 lines of context AFTER the change point
- Include all whitespace, indentation, and surrounding code exactly as it appears in the file

2. SINGLE INSTANCE: This tool can only change ONE instance at a time. If you need to change multiple instances:
- Make separate calls to this tool for each instance
- Each call must uniquely identify its specific instance using extensive context

3. VERIFICATION: Before using this tool:
- If multiple instances exist, gather enough context to uniquely identify each one
- Plan separate tool calls for each instance`

const search_replace = {
type: "function",
function: {
name: "search_replace",
description: SEARCH_REPLACE_DESCRIPTION,
parameters: {
type: "object",
properties: {
file_path: {
type: "string",
description:
"The path to the file you want to search and replace in. You can use either a relative path in the workspace or an absolute path. If an absolute path is provided, it will be preserved as is.",
},
old_string: {
type: "string",
description:
"The text to replace (must be unique within the file, and must match the file contents exactly, including all whitespace and indentation)",
},
new_string: {
type: "string",
description: "The edited text to replace the old_string (must be different from the old_string)",
},
},
required: ["file_path", "old_string", "new_string"],
additionalProperties: false,
},
},
} satisfies OpenAI.Chat.ChatCompletionTool

export default search_replace
Loading
Loading