neuron_types/stream.rs
1//! Streaming event types for incremental LLM responses.
2
3use std::fmt;
4use std::pin::Pin;
5
6use futures::Stream;
7
8use crate::types::{Message, TokenUsage};
9
10/// Error information from a stream event.
11#[derive(Debug, Clone)]
12pub struct StreamError {
13 /// Human-readable error message.
14 pub message: String,
15 /// Whether the error is retryable (e.g., rate limit, transient network).
16 pub is_retryable: bool,
17}
18
19impl StreamError {
20 /// Create a non-retryable error from a message string.
21 #[must_use]
22 pub fn non_retryable(message: impl Into<String>) -> Self {
23 Self {
24 message: message.into(),
25 is_retryable: false,
26 }
27 }
28
29 /// Create a retryable error from a message string.
30 #[must_use]
31 pub fn retryable(message: impl Into<String>) -> Self {
32 Self {
33 message: message.into(),
34 is_retryable: true,
35 }
36 }
37}
38
39impl fmt::Display for StreamError {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 write!(f, "{}", self.message)
42 }
43}
44
45/// An event emitted during streaming completion.
46#[derive(Debug, Clone)]
47pub enum StreamEvent {
48 /// Incremental text content.
49 TextDelta(String),
50 /// Incremental thinking/reasoning content.
51 ThinkingDelta(String),
52 /// Incremental signature content for thinking verification.
53 SignatureDelta(String),
54 /// A tool use block has started.
55 ToolUseStart {
56 /// Tool call identifier.
57 id: String,
58 /// Tool name.
59 name: String,
60 },
61 /// Incremental tool input JSON.
62 ToolUseInputDelta {
63 /// Tool call identifier (matches `ToolUseStart.id`).
64 id: String,
65 /// JSON fragment.
66 delta: String,
67 },
68 /// A tool use block has ended.
69 ToolUseEnd {
70 /// Tool call identifier.
71 id: String,
72 },
73 /// The complete assembled message (sent at the end of the stream).
74 MessageComplete(Message),
75 /// Token usage statistics for the stream.
76 Usage(TokenUsage),
77 /// An error occurred during streaming.
78 Error(StreamError),
79}
80
81/// Handle to a streaming completion response.
82pub struct StreamHandle {
83 /// The stream of events. Consume with `StreamExt::next()`.
84 pub receiver: Pin<Box<dyn Stream<Item = StreamEvent> + Send>>,
85}
86
87impl fmt::Debug for StreamHandle {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 f.debug_struct("StreamHandle").finish_non_exhaustive()
90 }
91}