From a7c692dae8ce61db38f0a590fb8915f5a3af3ea6 Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Tue, 3 Mar 2026 10:59:50 -0500 Subject: [PATCH] fix(streaming): terminate SSE with [DONE] and keep-alives --- src/server/mod.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/server/mod.rs b/src/server/mod.rs index a89f0996..16d3bae3 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -6,6 +6,7 @@ use axum::{ routing::{get, post}, }; use futures::stream::StreamExt; +use std::time::Duration; use sqlx; use std::sync::Arc; use tracing::{info, warn}; @@ -279,7 +280,21 @@ async fn chat_completions( } }); - Ok(Sse::new(sse_stream).into_response()) + // Many OpenAI-compatible clients expect a terminal [DONE] marker. + // Emit it when the upstream stream ends to avoid clients treating + // the response as incomplete. + let done = futures::stream::once(async { Ok(Event::default().data("[DONE]")) }); + let out = sse_stream.chain(done); + + Ok( + Sse::new(out) + .keep_alive( + axum::response::sse::KeepAlive::new() + .interval(Duration::from_secs(15)) + .text(": keep-alive"), + ) + .into_response(), + ) } Err(e) => { // Record provider failure