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