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
{{ message }}
Repository navigation
Transcript state on the Project singleton is not isolated per SDK context #2267
Project is a process-wide singleton, but the session id it is appending for is
context-scoped (AsyncLocalStorage). With two SDK sessions overlapping in one
process, records can be written to the wrong session's transcript file.
This was found by CodeRabbit during review of #2253 and is split out here
deliberately: #2253 fixes the sequential case and does not claim to make
overlapping turns safe. Filing it so the remaining hazard is not carried
silently by that PR.
Mechanism
recordTranscript() resolves the session id from the SDK context, so inside
session A's context it returns A.
Project.appendEntry() compares its sessionId argument with getSessionId(). When they differ it resolves the file per session via getExistingSessionFile(sessionId), which is safe. When they match it writes
to the cached this.sessionFile.
switchSession() emits a process-wide signal that clears that cached pointer,
and the next resolution fills it from whichever session asked.
So if session B switches while a turn in session A is still in flight, A's isCurrentSession check passes — the id really is A in A's context — and the
append lands in the file B resolved. The record is lost from A's transcript and
resuming A misses it.
Scope of a fix
The transcript state on Project has to become context-scoped, both fields:
sessionFile — the cached path;
pendingEntries — the buffer.
Both, and not one: resetSessionFile() drops pendingEntries along with the
path, and simply preserving that buffer across a switch would be worse than the
bug. Those entries belong to the session that buffered them, so carrying them
forward would flush them into the next session's file. Doing this properly means
flushing them to their own session on the way out.
That is a change to a singleton a lot of call sites reach through, and it wants
its own concurrency tests, which is why it is not folded into #2253.
Activity