refactor(apply_patch): remove deprecated patch mode, keep edits-only
Drop the legacy unified-diff patch parameter and all related parsing/ generation logic (_parse_patch, _generate_patch, _apply_hunks, etc.). The tool now accepts only the structured `edits` array, eliminating the intermediate diff-string round-trip. Also update file_edit_events tracking and tests to work exclusively with edits. Benchmark (zhipu glm-5.1, edits mode): 15/15 cases passed.
This commit is contained in:
@@ -89,23 +89,18 @@ def test_apply_patch_prepares_trackers_for_each_touched_file(tmp_path: Path) ->
|
||||
delete_me = tmp_path / "src" / "delete_me.py"
|
||||
delete_me.write_text("gone\n", encoding="utf-8")
|
||||
|
||||
patch = """*** Begin Patch
|
||||
*** Add File: src/new.py
|
||||
+fresh
|
||||
*** Update File: src/existing.py
|
||||
@@
|
||||
-old
|
||||
+new
|
||||
keep
|
||||
*** Delete File: src/delete_me.py
|
||||
*** End Patch"""
|
||||
edits = [
|
||||
{"path": "src/new.py", "action": "add", "new_text": "fresh"},
|
||||
{"path": "src/existing.py", "action": "replace", "old_text": "old", "new_text": "new"},
|
||||
{"path": "src/delete_me.py", "action": "delete", "old_text": "gone\n"},
|
||||
]
|
||||
|
||||
trackers = prepare_file_edit_trackers(
|
||||
call_id="call-patch",
|
||||
tool_name="apply_patch",
|
||||
tool=None,
|
||||
workspace=tmp_path,
|
||||
params={"patch": patch},
|
||||
params={"edits": edits},
|
||||
)
|
||||
|
||||
assert [tracker.display_path for tracker in trackers] == [
|
||||
@@ -118,7 +113,7 @@ def test_apply_patch_prepares_trackers_for_each_touched_file(tmp_path: Path) ->
|
||||
existing.write_text("new\nkeep\n", encoding="utf-8")
|
||||
delete_me.unlink()
|
||||
|
||||
events = [build_file_edit_end_event(tracker, {"patch": patch}) for tracker in trackers]
|
||||
events = [build_file_edit_end_event(tracker, {"edits": edits}) for tracker in trackers]
|
||||
by_path = {event["path"]: event for event in events}
|
||||
assert (by_path["src/new.py"]["added"], by_path["src/new.py"]["deleted"]) == (1, 0)
|
||||
assert (by_path["src/existing.py"]["added"], by_path["src/existing.py"]["deleted"]) == (1, 1)
|
||||
@@ -135,12 +130,9 @@ def test_apply_patch_dry_run_does_not_prepare_file_edit_trackers(tmp_path: Path)
|
||||
workspace=tmp_path,
|
||||
params={
|
||||
"dry_run": True,
|
||||
"patch": """*** Begin Patch
|
||||
*** Update File: file.txt
|
||||
@@
|
||||
-old
|
||||
+new
|
||||
*** End Patch""",
|
||||
"edits": [
|
||||
{"path": "file.txt", "action": "replace", "old_text": "old", "new_text": "new"}
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
@@ -221,14 +213,8 @@ def test_streaming_apply_patch_tracker_emits_live_counts_per_file(tmp_path: Path
|
||||
"call_id": "call-patch",
|
||||
"name": "apply_patch",
|
||||
"arguments_delta": (
|
||||
'{"patch":"*** Begin Patch\\n'
|
||||
'*** Update File: src/existing.py\\n'
|
||||
'@@\\n'
|
||||
'-old\\n'
|
||||
'+new\\n'
|
||||
' keep\\n'
|
||||
'*** Add File: src/new.py\\n'
|
||||
'+fresh\\n'
|
||||
'{"edits":[{"path":"src/existing.py","action":"replace","old_text":"old","new_text":"new"}'
|
||||
',{"path":"src/new.py","action":"add","new_text":"fresh"}]}'
|
||||
),
|
||||
})
|
||||
|
||||
@@ -255,9 +241,7 @@ def test_streaming_apply_patch_tracker_skips_dry_run(tmp_path: Path) -> None:
|
||||
"call_id": "call-patch",
|
||||
"name": "apply_patch",
|
||||
"arguments_delta": (
|
||||
'{"dry_run":true,"patch":"*** Begin Patch\\n'
|
||||
'*** Add File: dry.md\\n'
|
||||
'+preview\\n'
|
||||
'{"dry_run":true,"edits":[{"path":"dry.md","action":"add","new_text":"preview"}]}'
|
||||
),
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user