diff --git a/tests/test_workstream_endpoints.py b/tests/test_workstream_endpoints.py index 1af21f90..ad5d78d9 100644 --- a/tests/test_workstream_endpoints.py +++ b/tests/test_workstream_endpoints.py @@ -1304,8 +1304,6 @@ class TestHistoryInteractive: ``cursor`` = the resolved boundary's event_id. The client opens its initial SSE with that cursor so the delta rebuilds the turn. """ - import json - ws_id = "ws-cursor" _inject_storage.register_workstream(ws_id, kind="interactive", user_id="test-user") _inject_storage.save_message(ws_id, "user", "kick off", event_id=10) @@ -1340,8 +1338,6 @@ class TestHistoryInteractive: rendered block) and returns ``cursor: null`` — the client connects fresh to the synthetic-snapshot floor, never leaving the turn unrenderable.""" - import json - ws_id = "ws-cursor-reload" _inject_storage.register_workstream(ws_id, kind="interactive", user_id="test-user") _inject_storage.save_message(ws_id, "user", "kick off", event_id=10) diff --git a/turnstone/core/session.py b/turnstone/core/session.py index b3205dc6..f099e7bd 100644 --- a/turnstone/core/session.py +++ b/turnstone/core/session.py @@ -2134,12 +2134,15 @@ class ChatSession: """Current per-ws SSE ring-buffer high-water mark for stamping saved messages with the ``Last-Event-ID`` resume cursor. - Returns ``getattr(self.ui, "_event_id", None)`` — ``None`` for - UIs without the counter (CLI / eval / placeholder), whose rows - then stay NULL and are treated by ``/history`` as "no - fast-forward cursor available" (the synthetic-snapshot floor). + ``None`` for UIs without an integer counter — CLI / eval / + placeholder UIs (no ``_event_id``), and test doubles whose + ``self.ui`` is a ``MagicMock`` (a non-int ``_event_id`` would + otherwise reach the INSERT and fail to bind). Those rows stay + NULL and are treated by ``/history`` as "no fast-forward cursor + available" (the synthetic-snapshot floor). """ - return getattr(self.ui, "_event_id", None) + eid = getattr(self.ui, "_event_id", None) + return eid if isinstance(eid, int) else None def _remaining_token_budget(self) -> int: """Estimate how many tokens are available for new content.