"""Keyset cursor helpers for thread listings (SPEC ยง9.1: cursor = last_message_at,id).""" from __future__ import annotations import base64 import datetime as dt import uuid def encode_cursor(last_message_at: dt.datetime, thread_id: uuid.UUID) -> str: raw = f"{last_message_at.isoformat()}|{thread_id}" return base64.urlsafe_b64encode(raw.encode()).decode() def decode_cursor(cursor: str | None) -> tuple[dt.datetime, uuid.UUID] | None: if not cursor: return None try: raw = base64.urlsafe_b64decode(cursor.encode()).decode() date_str, id_str = raw.split("|", 1) return dt.datetime.fromisoformat(date_str), uuid.UUID(id_str) except (ValueError, TypeError): return None