Codex Handbook
codex-client/src/sse.rs 48 lines
use crate::error::StreamError;use crate::transport::ByteStream;use eventsource_stream::Eventsource;use futures::StreamExt;use tokio::sync::mpsc;use tokio::time::Duration;use tokio::time::timeout;/// Minimal SSE helper that forwards raw `data:` frames as UTF-8 strings.////// Errors and idle timeouts are sent as `Err(StreamError)` before the task exits.pub fn sse_stream(    stream: ByteStream,    idle_timeout: Duration,    tx: mpsc::Sender<Result<String, StreamError>>,) {    tokio::spawn(async move {        let mut stream = stream            .map(|res| res.map_err(|e| StreamError::Stream(e.to_string())))            .eventsource();        loop {            match timeout(idle_timeout, stream.next()).await {                Ok(Some(Ok(ev))) => {                    if tx.send(Ok(ev.data.clone())).await.is_err() {                        return;                    }                }                Ok(Some(Err(e))) => {                    let _ = tx.send(Err(StreamError::Stream(e.to_string()))).await;                    return;                }                Ok(None) => {                    let _ = tx                        .send(Err(StreamError::Stream(                            "stream closed before completion".into(),                        )))                        .await;                    return;                }                Err(_) => {                    let _ = tx.send(Err(StreamError::Timeout)).await;                    return;                }            }        }    });}