Skip to main content

serdes_ai_streaming/
lib.rs

1//! # serdes-ai-streaming
2//!
3//! Streaming support for serdes-ai.
4//!
5//! This crate provides infrastructure for handling streaming responses
6//! from LLM providers, including SSE parsing, async stream abstractions,
7//! delta accumulation, and agent streaming.
8//!
9//! ## Core Concepts
10//!
11//! - **[`AgentStream`]**: Stream agent execution with typed events
12//! - **[`AgentStreamEvent`]**: Events emitted during streaming (text, tools, thinking)
13//! - **[`PartialResponse`]**: Accumulate deltas into complete responses
14//! - **[`SseParser`]**: Parse Server-Sent Events from HTTP responses
15//! - **Debouncing**: Temporal grouping for efficient streaming
16//!
17//! ## Example - Basic Streaming
18//!
19//! ```ignore
20//! use serdes_ai_streaming::{AgentStream, AgentStreamExt};
21//! use futures::StreamExt;
22//!
23//! let stream = AgentStream::new(delta_stream, "run-123");
24//!
25//! // Stream only text deltas
26//! let mut text_stream = stream.text_deltas();
27//! while let Some(text) = text_stream.next().await {
28//!     print!("{}", text);
29//! }
30//! ```
31//!
32//! ## Example - SSE Parsing
33//!
34//! ```ignore
35//! use serdes_ai_streaming::{SseParser, SseEventExt};
36//!
37//! let mut parser = SseParser::new();
38//! parser.feed_str("data: {\"content\": \"hello\"}\n\n");
39//!
40//! while let Some(event) = parser.next_event() {
41//!     if let Some(delta) = event.to_response_delta() {
42//!         println!("Delta: {:?}", delta);
43//!     }
44//! }
45//! ```
46//!
47//! ## Example - Debouncing
48//!
49//! ```ignore
50//! use serdes_ai_streaming::{StreamDebounceExt, TextStreamExt};
51//! use std::time::Duration;
52//!
53//! let debounced = text_stream
54//!     .debounce(Duration::from_millis(50))
55//!     .flat_map(|batch| futures::stream::iter(batch));
56//!
57//! // Or coalesce into larger chunks
58//! let chunked = text_stream.coalesce(100, 1000);
59//! ```
60
61#![warn(missing_docs)]
62#![deny(unsafe_code)]
63
64pub mod agent_stream;
65pub mod debounce;
66pub mod error;
67pub mod events;
68pub mod partial_response;
69pub mod parts_manager;
70pub mod sse;
71
72#[cfg(feature = "websocket")]
73#[cfg_attr(docsrs, doc(cfg(feature = "websocket")))]
74pub mod websocket;
75
76// Re-exports
77pub use agent_stream::{
78    AgentStream, AgentStreamExt, OutputStream, ResponseStream, StreamConfig, StreamState,
79    TextDelta, TextDeltaStream,
80};
81pub use debounce::{
82    CoalescedTextStream, DebouncedStream, StreamDebounceExt, TextStreamExt, ThrottledStream,
83};
84pub use error::{StreamError, StreamResult};
85pub use events::AgentStreamEvent;
86pub use partial_response::{PartialResponse, ResponseDelta};
87pub use parts_manager::{ManagedPart, ModelResponsePartsManager, ToolCallAccumulator, VendorId};
88pub use sse::{SseEvent, SseEventExt, SseParser, SseStream};
89
90/// Prelude for common imports.
91pub mod prelude {
92    pub use crate::{
93        AgentStream, AgentStreamEvent, AgentStreamExt, PartialResponse, ResponseDelta, SseEvent,
94        SseEventExt, SseParser, StreamConfig, StreamDebounceExt, StreamError, StreamResult,
95        StreamState, TextDelta, TextStreamExt,
96    };
97}
98
99#[cfg(test)]
100mod tests {
101    #[test]
102    fn test_prelude_imports() {
103        use crate::prelude::*;
104
105        let _ = StreamState::Pending;
106        let config = StreamConfig::default();
107        assert!(config.emit_partial_outputs);
108    }
109}