Skip to content

Add Patch tool (opt-in apply-patch editing)#27

Merged
jbreite merged 11 commits into
mainfrom
add-patch-tool
May 5, 2026
Merged

Add Patch tool (opt-in apply-patch editing)#27
jbreite merged 11 commits into
mainfrom
add-patch-tool

Conversation

@jbreite
Copy link
Copy Markdown
Owner

@jbreite jbreite commented May 2, 2026

Summary

Adds a new Patch tool that applies edits in OpenAI Codex's apply-patch format — multi-hunk, multi-file, with fuzzy context-line matching and add/delete/rename support. Complements Edit (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:

const { tools } = await createAgentTools(sandbox, { patch: true });
// or with config: { patch: { allowedPaths: ["/workspace"] } }

What's in this PR

  • Patch tool — parser, applier, seek-sequence with Unicode normalization, all faithfully ported from codex-rs/apply-patch. Tool description and patch-format string are part of the LLM contract.
  • Atomic application — multi-hunk patches now pre-flight-validate every hunk (paths + context-line matches + derived contents) before touching disk. A failure in hunk 3 no longer leaves hunks 1–2 half-applied.
  • Sandbox hardening — new shellQuote helper used in VercelSandbox for readDir / fileExists / isDirectory / deleteFile / rename, eliminating injection through paths with quotes or special characters.
  • Optional sandbox methodsdeleteFile and rename are now optional on the Sandbox interface. Built-in sandboxes still implement them; custom sandboxes can omit them and Patch falls back to safely quoted exec("rm -- …") / exec("mv -- …").
  • Folder docssrc/tools/patch/AGENTS.md (and CLAUDE.md symlink) covering parser/applier layout and the format-as-LLM-contract caveat.

Test plan

  • bun run typecheck clean for changed files
  • bun run check (Biome) clean
  • bun 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 path
  • tests/sandbox/shell-quote.test.ts — 8 tests
  • tests/tools/index.test.ts — confirms Patch is not in defaults and is added when patch: true/patch: { ... }
  • Manual smoke test via examples/basic.ts with a real model

jbreite and others added 6 commits March 1, 2026 20:39
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.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bashkit-docs Ready Ready Preview, Comment May 5, 2026 0:05am

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.
jbreite added 3 commits May 5, 2026 07:42
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.
@jbreite jbreite merged commit e5481d3 into main May 5, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant