Skip to content

Conversation

@tlongwell-block
Copy link
Collaborator

@tlongwell-block tlongwell-block commented Sep 4, 2025

Adds support for applying unified diffs (both single-file and multi-file) through the text editor's str_replace command. This enhancement reduces token usage when making multi-line edits by up to 90%.

Why This Matters

Previously, multi-line edits required sending the entire old and new content as parameters, consuming substantial tokens. With diff support, only the changes are transmitted, dramatically reducing token usage for large edits.

What's New

Core Features

  • Unified diff support: Apply standard git-style unified diffs to files
  • Multi-file operations: Handle multiple file changes in a single operation
  • Fuzzy matching: Intelligently applies patches even with minor context differences
  • Token efficiency: Reduces token consumption by up to 90% for multi-line edits

Implementation

Text Editor Enhancement

  • New diff parameter: Optional parameter added to TextEditorParams for the str_replace command
  • Diff parsing: Uses mpatch crate (v0.2.0) for robust diff parsing and application
  • Markdown support: Automatically handles diffs wrapped in markdown code blocks
  • Atomic operations: Multi-file changes are all-or-nothing with automatic rollback on failure

Safety & Validation

  • Path traversal protection: Validates all file paths to prevent directory traversal attacks
  • Symlink detection: Blocks operations on symbolic links for security
  • Size limits:
    • Maximum diff size: 1MB
    • Maximum files per diff: 100
  • File history tracking: Maintains history for undo operations

Architecture

The feature is built with a modular, functional approach:

Key Components

  • apply_diff(): Main entry point that coordinates the diff application process
  • validate_path_safety(): Ensures all file operations are secure
  • apply_single_patch(): Handles individual file patches with fuzzy matching
  • DiffResults: Tracks statistics about the applied changes

Processing Flow

  1. Validate diff size and content
  2. Parse patches from the unified diff format
  3. Apply each patch with fuzzy matching for resilience
  4. Track all changes in file history
  5. Generate a summary of modifications

Benefits

  • Massive token savings: Up to 90% reduction for multi-line edits
  • Git compatibility: Works seamlessly with git-generated diffs
  • Robust error handling: Clear feedback when patches cannot be applied
  • Undo support: All diff operations can be rolled back
  • Atomic multi-file changes: Ensures consistency across multiple files

Usage Example

Instead of:

{
  "command": "str_replace",
  "old_str": "// 50 lines of old code...",
  "new_str": "// 50 lines of new code..."
}

Now you can use:

{
  "command": "str_replace",
  "diff": "--- a/file.rs\n+++ b/file.rs\n@@ -10,3 +10,3 @@\n-old line\n+new line"
}

Testing

Comprehensive test suite includes:

  • Single and multi-file diff application
  • File creation, modification, and deletion operations
  • Context validation with fuzzy matching
  • Undo functionality after diff operations
  • Security validations (path traversal, symlinks)
  • Edge cases (empty files, wrong line numbers, context mismatches)

All tests pass successfully.

@michaelneale
Copy link
Collaborator

seems nice - not sure if we have this AND replace_all (maybe....). curious how performance is

@tlongwell-block tlongwell-block marked this pull request as ready for review September 5, 2025 14:16
tlongwell-block and others added 5 commits September 5, 2025 13:25
* main:
  docs: social channels (#4552)
  feat: simplify navigation, make reload work (#4498)
  docs: new recipe warning (#4545)
  Add AGENTS.md for AI coding assistant support (#4539)
  docs: non-interactive compact now (#4543)
  fixed css classes and added some accessibility fixes (#4492)
  feat(acp): Read files (#4531)
  Add YouTube Short to Auto Visualiser Tutorial (#4536)
  Fix/settings page (#4520)
  update to RMCP 0.6.2 (#4523)
Copy link
Collaborator

@michaelneale michaelneale left a comment

Choose a reason for hiding this comment

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

I think this is ok, I wasn't able to trigger it to use a diff, it would happily use str_replace when it made sense, but that is probably ok. I did try to tell it to make a diff, it did, but it didn't work (probably as it was contrived). Any tips on how to see this out? just has to be day to day?

Seems a nicely focussed change and improvement. Main concern is how it works with lower end models, but the prompt doesn't really change much so should be ok.

@michaelneale michaelneale self-assigned this Sep 8, 2025
@tlongwell-block
Copy link
Collaborator Author

@michaelneale yeah, it is reluctant to use it. The old/new str is more intuitive for it, I think.

But, in my testing, sonnet handled the diff format for multiple files (going up to 10) really well. I'm not sure if I should use stronger language here to encourage using diff editing more, because it is pretty aggressive already.

@michaelneale
Copy link
Collaborator

@tlongwell-block I would leave it as is, and consider (while cracked open) adding in replace_all in this one omnibus PR and then we can get it in? covers all bases then.

@tlongwell-block tlongwell-block merged commit 4eff96f into main Sep 9, 2025
11 checks passed
@tlongwell-block tlongwell-block deleted the feat/unified-diff-support branch September 9, 2025 16:55
@alexhancock alexhancock mentioned this pull request Sep 9, 2025
katzdave added a commit that referenced this pull request Sep 10, 2025
…data

* 'main' of github.com:block/goose:
  refactor: add new recipe dependency updater (#4596)
  chore: fix nightly builds to have tags (#4595)
  feat: Import file contents from recipe 'file' input type parameter (#4558)
  also adding this change to the api key send for recipes (#4587)
  Fix local (working directory) recipes storage (#4588)
  fix: don't redact tool calls (#4589)
  Prompt injection detection (simplified - only pattern matching) (#4237)
  feat: add streaming support to Tetrate Agent Router Service provider (#4477)
  docs: goosehints updates (#4581)
  Iand/recipe scanner updates (#4584)
  patching recipe scanning workflows for permissions changes (#4579)
  fix: onboarding endpoints send token secret (#4575)
  Fix : Google AI schema validation by adding missing array items fields (#4569)
  Add unified diff support to text editor (#4522)
michaelneale added a commit that referenced this pull request Sep 10, 2025
* main: (29 commits)
  docs: update built-in extensions list and fix link (#4601)
  Add Message Metadata for Visibility Control (#4538)
  Remove deprecated Claude 3.5 models (#4590)
  Remove unused loadRecipe function (#4599)
  Send the secret with decodeRecipe (#4597)
  fix markdown links overflowing content and hide agent link previews (#4585)
  refactor: add new recipe dependency updater (#4596)
  chore: fix nightly builds to have tags (#4595)
  feat: Import file contents from recipe 'file' input type parameter (#4558)
  also adding this change to the api key send for recipes (#4587)
  Fix local (working directory) recipes storage (#4588)
  fix: don't redact tool calls (#4589)
  Prompt injection detection (simplified - only pattern matching) (#4237)
  feat: add streaming support to Tetrate Agent Router Service provider (#4477)
  docs: goosehints updates (#4581)
  Iand/recipe scanner updates (#4584)
  patching recipe scanning workflows for permissions changes (#4579)
  fix: onboarding endpoints send token secret (#4575)
  Fix : Google AI schema validation by adding missing array items fields (#4569)
  Add unified diff support to text editor (#4522)
  ...
michaelneale added a commit that referenced this pull request Sep 10, 2025
* main: (30 commits)
  docs: update built-in extensions list and fix link (#4601)
  Add Message Metadata for Visibility Control (#4538)
  Remove deprecated Claude 3.5 models (#4590)
  Remove unused loadRecipe function (#4599)
  Send the secret with decodeRecipe (#4597)
  fix markdown links overflowing content and hide agent link previews (#4585)
  refactor: add new recipe dependency updater (#4596)
  chore: fix nightly builds to have tags (#4595)
  feat: Import file contents from recipe 'file' input type parameter (#4558)
  also adding this change to the api key send for recipes (#4587)
  Fix local (working directory) recipes storage (#4588)
  fix: don't redact tool calls (#4589)
  Prompt injection detection (simplified - only pattern matching) (#4237)
  feat: add streaming support to Tetrate Agent Router Service provider (#4477)
  docs: goosehints updates (#4581)
  Iand/recipe scanner updates (#4584)
  patching recipe scanning workflows for permissions changes (#4579)
  fix: onboarding endpoints send token secret (#4575)
  Fix : Google AI schema validation by adding missing array items fields (#4569)
  Add unified diff support to text editor (#4522)
  ...
thebristolsound pushed a commit to thebristolsound/goose that referenced this pull request Sep 11, 2025
Co-authored-by: Michael Neale <[email protected]>
Signed-off-by: Matt Donovan <[email protected]>
@understood-the-assignment
Copy link
Contributor

Claude 3.7 Sonnet seems to be having a lot of trouble with this new tool for me.

It tries to:

path: ~/a/b/c/d/e/f/g/s/i/transmogrification/transmogrify.py
command: str_replace
diff: --- a/src/initech/transmogrification/transmogrify.py
+++ b/src/initech/transmogrification/transmogrify.py
@@ -127,7 +127,7 @@ ....
 ...patch follows ...

-32603: Mcp error: -32603: File '/home/user/a/b/c/d/e/f/g/src/initech/transmogrification/src/initech/transmogrification/transmogrify.py' not found and patch doesn't create it

i.e. it puts the full path in the path parameter and then a relative path in the diff header.

IMHO Goose should stop trying to invent clever new variations of tools that are completely different from what the common models out there are trained on. We should try to mimic the prompts and tools that Claude Code, Gemini CLI, and OpenAI Codex are providing to their respective models.

HikaruEgashira pushed a commit to HikaruEgashira/goose that referenced this pull request Oct 3, 2025
Co-authored-by: Michael Neale <[email protected]>
Signed-off-by: HikaruEgashira <[email protected]>
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.

5 participants