Add Patch tool (opt-in apply-patch editing)#27
Merged
Merged
Conversation
Port of Codex's apply-patch format (codex-rs/apply-patch) to TypeScript, providing fuzzy multi-hunk, multi-file editing alongside the existing Write and Edit tools. - Add Patch tool with parser, 4-tier fuzzy seek, and apply logic - Extend Sandbox interface with deleteFile() and rename() methods - Implement in all sandboxes (Local, Vercel, E2B) and MockSandbox Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Patch overlaps with Edit and can confuse smaller models when both are present in the default toolset. Move it behind a `patch?: true | ToolConfig` flag mirroring the askUser pattern, before any 0.x consumers depend on it being default.
Add a `shellQuote` helper and use it in VercelSandbox for `readDir`,
`fileExists`, `isDirectory`, `deleteFile`, and `rename`. Prevents shell
injection through paths that contain quotes, spaces, or other special
characters.
Also relax the `Sandbox` interface: `deleteFile` and `rename` are now
optional. Built-in sandboxes still implement them, but custom sandboxes
can omit them and callers can fall back to `exec("rm -- ...")` /
`exec("mv -- ...")`.
Previously, applying a multi-hunk patch could leave the workspace in a
half-applied state if a later hunk failed: earlier hunks had already
been written. Now the tool parses every hunk, derives all new contents,
and validates paths and context-line matches before touching disk. If
any hunk fails validation the patch is rejected as a whole and no
files are modified.
Also handle sandboxes that don't implement `deleteFile` or `rename`
(now optional on the Sandbox interface) by falling back to safely
quoted `exec("rm -- …")` / `exec("mv -- …")`.
Add a folder-scoped AGENTS.md (with CLAUDE.md symlink) describing the
parser/applier/seek-sequence layout and the format-as-LLM-contract
caveat.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Biome's auto-fix removed the leading `!` on `result` and `r2` but kept `messages!`, breaking the chain since `prepareStep` returns `... | undefined`. Narrow with an explicit guard instead.
Refactor patch application and sequence search for performance and safety, add documentation clarification, and extend tests. applyReplacements now builds segments instead of splicing/spreading large arrays to avoid V8 argument limits and handle empty replacements efficiently. seekSequence precomputes trimmed/normalized pattern variants to avoid repeated work. Added default Patch hint to tool guidance and clarified Sandbox behavior in AGENTS.md (deleteFile optional; moves implemented as write+delete). Tests updated to assert guidance presence and to cover large insert hunks that would previously hit argument limits.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new Patch tool that applies edits in OpenAI Codex's
apply-patchformat — multi-hunk, multi-file, with fuzzy context-line matching and add/delete/rename support. ComplementsEdit(single-string find/replace) for larger refactors where one round-trip per edit is wasteful.Opt-in, not default. Edit and Patch overlap, and including both by default tends to confuse smaller models. Enable explicitly:
What's in this PR
codex-rs/apply-patch. Tool description and patch-format string are part of the LLM contract.shellQuotehelper used inVercelSandboxforreadDir/fileExists/isDirectory/deleteFile/rename, eliminating injection through paths with quotes or special characters.deleteFileandrenameare now optional on theSandboxinterface. Built-in sandboxes still implement them; custom sandboxes can omit them and Patch falls back to safely quotedexec("rm -- …")/exec("mv -- …").src/tools/patch/AGENTS.md(and CLAUDE.md symlink) covering parser/applier layout and the format-as-LLM-contract caveat.Test plan
bun run typecheckclean for changed filesbun run check(Biome) cleanbun run test— 638 passing, 27 skipped (no new failures)tests/tools/patch.test.ts— 63 tests covering parser, chunk grammar, seek-sequence, Unicode normalization, applier, atomicity, and the tool integration pathtests/sandbox/shell-quote.test.ts— 8 teststests/tools/index.test.ts— confirms Patch is not in defaults and is added whenpatch: true/patch: { ... }examples/basic.tswith a real model