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 @@ -21,6 +21,7 @@ export const toolNames = [
"apply_diff",
"insert_content",
"search_and_replace",
"apply_patch",
"search_files",
"list_files",
"list_code_definition_names",
Expand Down
16 changes: 16 additions & 0 deletions src/core/assistant-message/NativeToolCallParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,14 @@ export class NativeToolCallParser {
}
break

case "apply_patch":
if (partialArgs.patch !== undefined) {
nativeArgs = {
patch: partialArgs.patch,
}
}
break

// Add other tools as needed
default:
break
Expand Down Expand Up @@ -768,6 +776,14 @@ export class NativeToolCallParser {
}
break

case "apply_patch":
if (args.patch !== undefined) {
nativeArgs = {
patch: args.patch,
} as NativeArgsFor<TName>
}
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 { writeToFileTool } from "../tools/WriteToFileTool"
import { applyDiffTool } from "../tools/MultiApplyDiffTool"
import { insertContentTool } from "../tools/InsertContentTool"
import { searchAndReplaceTool } from "../tools/SearchAndReplaceTool"
import { applyPatchTool } from "../tools/ApplyPatchTool"
import { listCodeDefinitionNamesTool } from "../tools/ListCodeDefinitionNamesTool"
import { searchFilesTool } from "../tools/SearchFilesTool"
import { browserActionTool } from "../tools/BrowserActionTool"
Expand Down Expand Up @@ -382,6 +383,8 @@ export async function presentAssistantMessage(cline: Task) {
return `[${block.name} for '${block.params.path}']`
case "search_and_replace":
return `[${block.name} for '${block.params.path}']`
case "apply_patch":
return `[${block.name}]`
case "list_files":
return `[${block.name} for '${block.params.path}']`
case "list_code_definition_names":
Expand Down Expand Up @@ -828,6 +831,16 @@ export async function presentAssistantMessage(cline: Task) {
toolProtocol,
})
break
case "apply_patch":
await checkpointSaveAndMark(cline)
await applyPatchTool.handle(cline, block as ToolUse<"apply_patch">, {
askApproval,
handleError,
pushToolResult,
removeClosingTag,
toolProtocol,
})
break
case "read_file":
// Check if this model should use the simplified single-file read tool
// Only use simplified tool for XML protocol - native protocol works with standard tool
Expand Down
61 changes: 61 additions & 0 deletions src/core/prompts/tools/native-tools/apply_patch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type OpenAI from "openai"

const apply_patch_DESCRIPTION = `Apply patches to files using a stripped-down, file-oriented diff format. This tool supports creating new files, deleting files, and updating existing files with precise changes.

The patch format uses a simple, human-readable structure:

*** Begin Patch
[ one or more file sections ]
*** End Patch

Each file section starts with one of three headers:
- *** Add File: <path> - Create a new file. Every following line is a + line (the initial contents).
- *** Delete File: <path> - Remove an existing file. Nothing follows.
- *** Update File: <path> - Patch an existing file in place.

For Update File operations:
- May be immediately followed by *** Move to: <new path> if you want to rename the file.
- Then one or more "hunks", each introduced by @@ (optionally followed by context like a class or function name).
- Within a hunk each line starts with:
- ' ' (space) for context lines (unchanged)
- '-' for lines to remove
- '+' for lines to add

Context guidelines:
- Show 3 lines of code above and below each change.
- Use @@ with a class/function name if 3 lines of context is insufficient to uniquely identify the location.
- Multiple @@ statements can be used for deeply nested code.

Example patch:
*** Begin Patch
*** Add File: hello.txt
+Hello world
*** Update File: src/app.py
*** Move to: src/main.py
@@ def greet():
-print("Hi")
+print("Hello, world!")
*** Delete File: obsolete.txt
*** End Patch`

const apply_patch = {
type: "function",
function: {
name: "apply_patch",
description: apply_patch_DESCRIPTION,
parameters: {
type: "object",
properties: {
patch: {
type: "string",
description:
"The complete patch text in the apply_patch format, starting with '*** Begin Patch' and ending with '*** End Patch'.",
},
},
required: ["patch"],
additionalProperties: false,
},
},
} satisfies OpenAI.Chat.ChatCompletionTool

export default apply_patch
2 changes: 2 additions & 0 deletions src/core/prompts/tools/native-tools/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type OpenAI from "openai"
import accessMcpResource from "./access_mcp_resource"
import { apply_diff } from "./apply_diff"
import applyPatch from "./apply_patch"
import askFollowupQuestion from "./ask_followup_question"
import attemptCompletion from "./attempt_completion"
import browserAction from "./browser_action"
Expand Down Expand Up @@ -33,6 +34,7 @@ export function getNativeTools(partialReadsEnabled: boolean = true): OpenAI.Chat
return [
accessMcpResource,
apply_diff,
applyPatch,
askFollowupQuestion,
attemptCompletion,
browserAction,
Expand Down
Loading
Loading