fix(streaming): skip non-file-edit tools in apply_final_call_ids to prevent id corruption

apply_final_call_ids iterated over all final tool calls, including
non-file-edit tools like read_file. The greedy path-match in
matches_final_tool_call could overwrite a correct unique id with a
stale one from a different streaming state, producing duplicate
tool_use ids that poison the persisted session.

Guard the loop with is_file_edit_tool() so only tracked file-edit
tools (write_file, edit_file, apply_patch) are subject to canonical
id remapping. Non-file-edit tools keep their authoritative id from
get_final_message().

Fixes #4595
This commit is contained in:
axelray-dev
2026-06-30 15:21:02 +08:00
committed by Xubin Ren
parent 8df100203c
commit 070aed8ade
2 changed files with 38 additions and 0 deletions
+3
View File
@@ -529,6 +529,9 @@ class StreamingFileEditTracker:
"""Keep final start/end events keyed to any earlier streamed placeholder."""
used_canonicals: set[str] = set()
for tool_call in final_tool_calls:
name = getattr(tool_call, "name", None)
if not is_file_edit_tool(name):
continue
canonical = self.canonical_call_id_for(tool_call)
if canonical and canonical not in used_canonicals:
try: