Skip to content

feat(agent): add fuzzy whitespace matching to edit_files tool#22446

Merged
kylecarbs merged 2 commits intomainfrom
kylecarbs/fuzzy-whitespace-edit
Feb 28, 2026
Merged

feat(agent): add fuzzy whitespace matching to edit_files tool#22446
kylecarbs merged 2 commits intomainfrom
kylecarbs/fuzzy-whitespace-edit

Conversation

@kylecarbs
Copy link
Copy Markdown
Member

Inspired by openai/codex's apply_patch implementation, this changes the edit_files search-and-replace to use a cascading match strategy when the exact search string isn't found:

  1. Exact substring match (byte-for-byte) — existing behavior, unchanged
  2. Line-by-line match ignoring trailing whitespace — handles trailing spaces/tabs the LLM omits
  3. Line-by-line match ignoring all leading/trailing whitespace — handles tabs-vs-spaces and wrong indentation depth

Problem

When the chat agent uses edit_files, it generates a search string that must match the file content exactly. LLMs frequently get whitespace wrong:

  • Emitting spaces when the file uses tabs (or vice versa)
  • Getting the indentation depth wrong by one or more levels
  • Omitting trailing whitespace that exists in the file

When this happens, the edit silently does nothing, and the agent falls into a retry loop using cat -A to diagnose the exact whitespace characters.

Solution

Adopted the same cascading fuzzy match strategy that openai/codex uses in seek_sequence.rs:

  • Pass 1: exact match (existing behavior)
  • Pass 2: TrimRight each line before comparing (trailing whitespace tolerance)
  • Pass 3: TrimSpace each line before comparing (full indentation tolerance)

When a fuzzy match is found, the matched lines in the original file are replaced with the replacement text. This preserves surrounding content exactly.

Changes

  • agent/agentfiles/files.go: Replaced icholy/replace streaming transformer with in-memory fuzzyReplace + helper functions (seekLines, spliceLines)
  • agent/agentfiles/files_test.go: Added 6 new test cases covering trailing whitespace, tabs-vs-spaces, different indent depths, exact match preference, no-match behavior, and mixed whitespace multiline edits
  • Removed icholy/replace dependency from go.mod/go.sum

Inspired by openai/codex's apply_patch implementation, this changes the
edit_files search-and-replace to use a cascading match strategy when the
exact search string isn't found:

1. Exact substring match (byte-for-byte) - existing behavior
2. Line-by-line match ignoring trailing whitespace
3. Line-by-line match ignoring all leading/trailing whitespace
   (indentation-tolerant)

This fixes the common issue where the LLM generates a search string with
spaces but the file uses tabs (or vice versa), or gets the indentation
depth wrong. Previously these edits would silently fail, forcing the
agent into retry loops with cat -A to diagnose whitespace.

The icholy/replace streaming transformer dependency is removed in favor
of reading the file into memory and applying replacements directly.
@kylecarbs kylecarbs merged commit 5945feb into main Feb 28, 2026
24 checks passed
@kylecarbs kylecarbs deleted the kylecarbs/fuzzy-whitespace-edit branch February 28, 2026 22:03
@github-actions github-actions bot locked and limited conversation to collaborators Feb 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant