import json from api import models from api import streaming class FakeSession: def __init__(self): self.session_id = "new_session" self.parent_session_id = "original_parent" self.pre_compression_snapshot = False self.pinned = True self.active_stream_id = "live-stream" self.pending_user_message = "current prompt" self.pending_attachments = [{"name": "file.txt"}] self.pending_started_at = 123.0 self.messages = [{"role": "user", "content": "current prompt"}] self.saved_payload = None def save(self, *, touch_updated_at=True, skip_index=False): self.saved_payload = { "session_id": self.session_id, "parent_session_id": self.parent_session_id, "pre_compression_snapshot": self.pre_compression_snapshot, "pinned": self.pinned, "active_stream_id": self.active_stream_id, "pending_user_message": self.pending_user_message, "pending_attachments": list(self.pending_attachments), "pending_started_at": self.pending_started_at, "touch_updated_at": touch_updated_at, "skip_index": skip_index, } path = streaming.SESSION_DIR / f"{self.session_id}.json" path.write_text(json.dumps(self.saved_payload), encoding="utf-8") def test_preserve_pre_compression_snapshot_clears_runtime_fields_while_restoring_continuation_state(tmp_path, monkeypatch): monkeypatch.setattr(streaming, "SESSION_DIR", tmp_path) (tmp_path / "old_session.json").write_text(json.dumps({"messages": []}), encoding="utf-8") session = FakeSession() streaming._preserve_pre_compression_snapshot(session, "old_session") assert session.saved_payload == { "session_id": "old_session", "parent_session_id": "original_parent", "pre_compression_snapshot": True, "pinned": False, "active_stream_id": None, "pending_user_message": None, "pending_attachments": [], "pending_started_at": None, "touch_updated_at": False, "skip_index": False, } assert session.session_id == "new_session" assert session.pre_compression_snapshot is False assert session.pinned is True assert session.active_stream_id == "live-stream" assert session.pending_user_message == "current prompt" assert session.pending_attachments == [{"name": "file.txt"}] assert session.pending_started_at == 123.0 saved = json.loads((tmp_path / "old_session.json").read_text(encoding="utf-8")) assert saved["pre_compression_snapshot"] is True assert saved["pinned"] is False assert saved["active_stream_id"] is None assert saved["pending_user_message"] is None assert saved["pending_attachments"] == [] assert saved["pending_started_at"] is None def test_preserve_pre_compression_snapshot_load_and_mark_branch_clears_runtime_fields(tmp_path, monkeypatch): monkeypatch.setattr(streaming, "SESSION_DIR", tmp_path) monkeypatch.setattr(models, "SESSION_DIR", tmp_path) old_payload = { "session_id": "old_session", "title": "Archived parent", "messages": [ {"role": "user", "content": "older prompt"}, {"role": "assistant", "content": "older answer"}, {"role": "user", "content": "newer prompt already on disk"}, ], "pre_compression_snapshot": True, "pinned": True, "active_stream_id": "stale-stream", "pending_user_message": "stale prompt", "pending_attachments": [{"name": "stale.txt"}], "pending_started_at": 12345, } (tmp_path / "old_session.json").write_text(json.dumps(old_payload), encoding="utf-8") session = FakeSession() session.messages = [{"role": "user", "content": "current prompt"}] streaming._preserve_pre_compression_snapshot(session, "old_session") saved = json.loads((tmp_path / "old_session.json").read_text(encoding="utf-8")) assert saved["messages"] == old_payload["messages"] assert saved["pre_compression_snapshot"] is True assert saved["pinned"] is False assert saved["active_stream_id"] is None assert saved["pending_user_message"] is None assert saved["pending_attachments"] == [] assert saved["pending_started_at"] is None def test_preserve_pre_compression_snapshot_does_not_leave_continuation_marked_as_snapshot(tmp_path, monkeypatch): """A continuation loaded from an old snapshot must not remain hidden.""" monkeypatch.setattr(streaming, "SESSION_DIR", tmp_path) (tmp_path / "old_session.json").write_text(json.dumps({"messages": []}), encoding="utf-8") session = FakeSession() session.pre_compression_snapshot = True streaming._preserve_pre_compression_snapshot(session, "old_session") # The helper archives the parent and restores the incoming object state. # The streaming compression path must clear this before saving the child. assert session.pre_compression_snapshot is True session.pre_compression_snapshot = False session.save(touch_updated_at=False) continuation = json.loads((tmp_path / "new_session.json").read_text(encoding="utf-8")) assert continuation["pre_compression_snapshot"] is False