Watch
1
0
Fork
You've already forked souveraine
0

fix: commit partial reply when the SSE surface drops mid-stream

turn.rs streaming loop returned early on tx.send failure (receiver gone)
before the session commit, orphaning the turn: the assistant's partial
reply never landed, so the next turn's history snapshot read the user's
follow-up with no preceding reply -> a user->user gap. The model then
answered as if from nowhere (the 'whatever it was...' non-sequitur),
model-independent and intermittent. Commit the partial like an interrupt
instead, the way the cancel branch already does, so the thread links.
This commit is contained in:
Fimeg 2026-07-30 15:17:55 -04:00
commit 426dcf6363

View file

@ -471,7 +471,21 @@ pub(crate) async fn run_turn(
break; break;
} }
send_res = tx.send(Ok(BackendEvent::Token(s.clone()))) => { send_res = tx.send(Ok(BackendEvent::Token(s.clone()))) => {
if send_res.is_err() { return Ok(()); } if send_res.is_err() {
// The SSE receiver is gone (the surface
// disconnected mid-reply). Do NOT return early:
// that would skip the session commit below and
// orphan this turn, leaving a user→user gap so
// the next turn cannot link to the past — the
// model reads the follow-up with no preceding
// reply and answers as if from nowhere. Commit
// the partial text like an interrupt instead, so
// the conversation thread stays intact even when
// the surface vanishes.
interrupted = true;
final_content = streamed;
break;
}
dispatcher.emit_segment(&s); dispatcher.emit_segment(&s);
streamed.push_str(&s); streamed.push_str(&s);
} }