You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(core,sdk): resume session.in via seq cursor on turn-complete header
Replaces the wall-clock dedup cutoff on session.in with a seq-based
resume cursor carried on each turn-complete control record as a
`session-in-event-id` sibling header. On worker boot the cursor is
read off .out's latest turn-complete and seeds .in's SSE subscription
so already-processed user messages aren't replayed from S2.
The timestamp model had a narrow race: the snapshot's lastOutTimestamp
was Date.now() sampled after turn-complete landed on S2, so a user
message arriving between turn-complete and snapshot-write could be
silently filtered as "old" on the next worker boot. Seq numbers are
unique, total-ordered, and stamped by S2, so the same cutoff now
falls out without any clock involved.
The sessionStreams manager grows a second cursor (lastDispatchedSeqNum)
distinct from the existing received cursor. It advances only when a
record is delivered to a once()/wait() consumer or shifted off the
buffer into one. The agent persists it on turn-complete and seeds it
back at the next worker's boot before any .in SSE subscribe opens.
lastOutTimestamp is gone from the snapshot; the rescan is O(1 turn)
since .out is bounded.
Also bundles four small PR-review fixes:
- runStream SSEStreamPart doc had the trigger-control vs
S2-command-record marker reversed
- agentChat removed a redundant reader.releaseLock() before a
recursive return that the finally block already covers
- sessions surfaces onControl on SessionSubscribeOptions so consumers
of the raw .out.read() API see header-form control records
- chatSnapshot drops the now-unused lastOutTimestamp field
0 commit comments