Claude: replace module-level file read states with per-loop per-session state class. fixes #3571

This commit is contained in:
LZDQ
2026-05-01 19:15:07 +08:00
committed by Xubin Ren
parent 6891a7a4d4
commit 58ae2d5b7e
7 changed files with 214 additions and 108 deletions
+8 -4
View File
@@ -27,12 +27,16 @@ class TestEditReadTracking:
"""edit_file should warn when file hasn't been read first."""
@pytest.fixture()
def read_tool(self, tmp_path):
return ReadFileTool(workspace=tmp_path)
def file_states(self):
return file_state.FileStates()
@pytest.fixture()
def edit_tool(self, tmp_path):
return EditFileTool(workspace=tmp_path)
def read_tool(self, tmp_path, file_states):
return ReadFileTool(workspace=tmp_path, file_states=file_states)
@pytest.fixture()
def edit_tool(self, tmp_path, file_states):
return EditFileTool(workspace=tmp_path, file_states=file_states)
@pytest.mark.asyncio
async def test_edit_warns_if_file_not_read_first(self, edit_tool, tmp_path):
+31
View File
@@ -97,6 +97,37 @@ class TestReadDedup:
assert isinstance(second, list)
# ---------------------------------------------------------------------------
# Cross-session isolation (issue #3571)
# ---------------------------------------------------------------------------
# Each session must keep its own read cache. When session A reads a file,
# session B reading the same file must still receive the full content, not
# the "[File unchanged since last read]" dedup stub. The stub is only valid
# within the session that first cached the read.
class TestReadDedupSessionIsolation:
@pytest.mark.asyncio
async def test_separate_sessions_do_not_share_dedup_state(self, tmp_path):
f = tmp_path / "shared.txt"
f.write_text("\n".join(f"line {i}" for i in range(10)), encoding="utf-8")
session_a_tool = ReadFileTool(workspace=tmp_path)
session_b_tool = ReadFileTool(workspace=tmp_path)
first = await session_a_tool.execute(path=str(f))
assert "line 0" in first
# Session B has never read this file before — it must see the full
# content, not the dedup stub from session A.
second = await session_b_tool.execute(path=str(f))
assert "unchanged" not in second.lower(), (
"Session B should not inherit session A's read-dedup state. "
f"Got: {second!r}"
)
assert "line 0" in second
# ---------------------------------------------------------------------------
# PDF support
# ---------------------------------------------------------------------------