Add snapshot pagination for persisted realtime history (#61480)

## What changed

Add experimental `thread/realtime/list` reads independent of turn pagination or a live runtime. Support session, observation-time, and event-ID filters, with ordering by observation time or committed position.

Keep cursor pagination within a fixed snapshot and expose positions for catching up on events committed later. Return `unsupported`, `pending`, or `ready` coverage so clients can distinguish unavailable history from events awaiting indexing. Limit fork reads to the child's own realtime history.

## Testing

Add SQLite tests for snapshot stability, late-event catch-up, cursor validation, and coverage tracking. Extend app-server tests to cover filtering, exact event lookup, and fork isolation.

GitOrigin-RevId: 8158df53f10d948ede4911654aa8adbc7297b258
This commit is contained in:
Zahan Malkani
2026-11-14 07:09:26 +00:00
committed by copyberry
parent 5943d7acdf
commit 05229d1874
25 changed files with 1124 additions and 42 deletions
@@ -6415,6 +6415,12 @@ class ThreadRealtimeClosedNotification(BaseModel):
thread_id: Annotated[str, Field(alias="threadId")]
class ThreadRealtimeCoverage(Enum):
unsupported = "unsupported"
pending = "pending"
ready = "ready"
class ThreadRealtimeErrorNotification(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
@@ -6538,6 +6544,11 @@ class ThreadRealtimeItemTranscriptDeltaNotification(BaseModel):
thread_id: Annotated[str, Field(alias="threadId")]
class ThreadRealtimeOrder(Enum):
observed_at = "observedAt"
position = "position"
class ThreadRealtimeOutputAudioDeltaNotification(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
@@ -12927,6 +12938,14 @@ class ThreadItemsListResponse(BaseModel):
] = None
class ThreadRealtimeEntry(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
item: ThreadRealtimeItem
position: Annotated[int, Field(ge=0)]
class ItemThreadTimelineEntry(BaseModel):
model_config = ConfigDict(
populate_by_name=True,