Watch
1
0
Fork
You've already forked souveraine
0

fix: preserve the full reply (not the streamed partial) on surface-drop

Revises the prior fix: the model's reply is already complete in
final_content before the paced stream loop, so truncating to
needlessly dropped the unstreamed tail. On SSE receiver-drop, stop
streaming but commit the FULL reply (interrupt flag skips the pointless
N+1 and marks the turn); the surface recovers the whole reply on resume.
This commit is contained in:
Fimeg 2026-07-30 15:22:12 -04:00
commit 4caca36859

View file

@ -473,17 +473,21 @@ pub(crate) async fn run_turn(
send_res = tx.send(Ok(BackendEvent::Token(s.clone()))) => {
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.
// disconnected mid-stream). The model's reply is
// already complete in `final_content` — only the
// paced live-stream was cut, so do NOT truncate
// to `streamed`. Stop streaming to the dead
// receiver and let the turn commit the FULL
// reply below; treating it as an interrupt also
// skips the now-pointless N+1 pass and lands a
// small marker so the next turn knows the live
// tail was missed. Returning early here used to
// orphan the turn entirely — no commit — leaving
// a user→user gap so the next turn could not link
// to the past, and the model answered as if from
// nowhere ("whatever it was…"). The surface
// recovers the whole reply on its next resume.
interrupted = true;
final_content = streamed;
break;
}
dispatcher.emit_segment(&s);