Commit 5629d2b
committed
fix(sdk): drop session-stream auto-reconnect after explicit disconnect
`StandardSessionStreamManager#ensureTailConnected` re-subscribes the SSE
tail in `.finally` whenever handlers or once-waiters remain on the key.
That's the right move for unexpected tail crashes, but wrong when
`session.in.wait()` calls `disconnectStream` to suspend the run via a
waitpoint: the run-level `stopInput.on(...)` registered at the top of
the `chat.agent` loop keeps the handlers set non-empty, so during the
suspend window the tail silently resurrects, the next user message
arrives at S2, the tail dispatches it, `stopSub`'s "kind === stop"
filter rejects it, the data falls into the buffer, the waitpoint
*also* delivers the same record, the SDK resumes, and on the next
turn's `messagesInput.on(...)` registration the buffer drain re-fires
the handler — `pendingMessages` ends up holding a duplicate of the
just-consumed message and the loop runs an extra LLM turn with
identical content.
Track explicit teardown via `explicitlyDisconnected: Set<string>`.
`disconnectStream` adds the key, `.finally` bails when set, `on()` /
`once()` clear it so future re-attaches reconnect normally. Honors
`wait()`'s expectation that explicit disconnect ⇒ no records buffered
or delivered until a fresh `on()`/`once()`, while preserving
auto-reconnect for legitimate failures (network drops, etc.).
Verified end-to-end against a `chat.agent` reproduction that
previously fired three turns per submitted message after suspend; with
the fix exactly one turn per message, single LLM call, single
persisted assistant reply.
Trivial: `wait()` extracts `nextSeq` to a local for readability.1 parent d221490 commit 5629d2b
2 files changed
Lines changed: 32 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
39 | 45 | | |
40 | 46 | | |
41 | 47 | | |
| |||
58 | 64 | | |
59 | 65 | | |
60 | 66 | | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
61 | 70 | | |
62 | 71 | | |
63 | 72 | | |
| |||
85 | 94 | | |
86 | 95 | | |
87 | 96 | | |
| 97 | + | |
88 | 98 | | |
89 | 99 | | |
90 | 100 | | |
| |||
168 | 178 | | |
169 | 179 | | |
170 | 180 | | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
171 | 187 | | |
172 | 188 | | |
173 | 189 | | |
| |||
223 | 239 | | |
224 | 240 | | |
225 | 241 | | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
226 | 256 | | |
227 | 257 | | |
228 | 258 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
617 | 617 | | |
618 | 618 | | |
619 | 619 | | |
620 | | - | |
| 620 | + | |
| 621 | + | |
621 | 622 | | |
622 | 623 | | |
623 | 624 | | |
| |||
0 commit comments