Skip to main content

gproxy_protocol/claude/message/
stream.rs

1use serde::{Deserialize, Serialize};
2
3use crate::claude::common::{
4    AssistantRole, Citation, ClaudeModel, Container, ContentBlock, ContextManagementResponse,
5    InputTransformation, MessageObjectType, StopDetails, StopReason, TypedObject, Usage,
6};
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9#[serde(untagged)]
10#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
11pub enum StreamEvent {
12    Known(Box<KnownStreamEvent>),
13    Unknown(TypedObject),
14}
15
16impl StreamEvent {
17    /// SSE event name: the wire `type` of this event, if any.
18    pub fn event_name(&self) -> Option<&str> {
19        match self {
20            Self::Known(event) => Some(event.event_name()),
21            Self::Unknown(object) => Some(object.type_.as_str()),
22        }
23    }
24}
25
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
27#[serde(tag = "type")]
28#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
29pub enum KnownStreamEvent {
30    #[serde(rename = "message_start")]
31    MessageStart {
32        message: Box<CreateMessageStartBody>,
33        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
34        rest: serde_json::Map<String, serde_json::Value>,
35    },
36    #[serde(rename = "content_block_start")]
37    ContentBlockStart {
38        index: u64,
39        content_block: Box<ContentBlock>,
40        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
41        rest: serde_json::Map<String, serde_json::Value>,
42    },
43    #[serde(rename = "content_block_delta")]
44    ContentBlockDelta {
45        index: u64,
46        delta: Box<EventDelta>,
47        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
48        rest: serde_json::Map<String, serde_json::Value>,
49    },
50    #[serde(rename = "content_block_stop")]
51    ContentBlockStop {
52        index: u64,
53        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
54        rest: serde_json::Map<String, serde_json::Value>,
55    },
56    #[serde(rename = "message_delta")]
57    MessageDelta {
58        #[serde(skip_serializing_if = "Option::is_none")]
59        context_management: Option<Box<ContextManagementResponse>>,
60        delta: Box<MessageDelta>,
61        #[serde(skip_serializing_if = "Option::is_none")]
62        input_transformations: Option<Vec<InputTransformation>>,
63        #[serde(skip_serializing_if = "Option::is_none")]
64        usage: Option<Box<Usage>>,
65        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
66        rest: serde_json::Map<String, serde_json::Value>,
67    },
68    #[serde(rename = "message_stop")]
69    MessageStop {
70        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
71        rest: serde_json::Map<String, serde_json::Value>,
72    },
73    #[serde(rename = "ping")]
74    Ping {
75        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
76        rest: serde_json::Map<String, serde_json::Value>,
77    },
78    #[serde(rename = "error")]
79    Error {
80        error: StreamError,
81        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
82        rest: serde_json::Map<String, serde_json::Value>,
83    },
84}
85
86impl KnownStreamEvent {
87    /// SSE event name: the exact serde rename of this variant.
88    pub fn event_name(&self) -> &'static str {
89        match self {
90            Self::MessageStart { .. } => "message_start",
91            Self::ContentBlockStart { .. } => "content_block_start",
92            Self::ContentBlockDelta { .. } => "content_block_delta",
93            Self::ContentBlockStop { .. } => "content_block_stop",
94            Self::MessageDelta { .. } => "message_delta",
95            Self::MessageStop { .. } => "message_stop",
96            Self::Ping { .. } => "ping",
97            Self::Error { .. } => "error",
98        }
99    }
100}
101
102#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
103#[serde(untagged)]
104#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
105pub enum EventDelta {
106    Known(Box<KnownEventDelta>),
107    Unknown(TypedObject),
108}
109
110#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111#[serde(tag = "type")]
112#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
113pub enum KnownEventDelta {
114    #[serde(rename = "text_delta")]
115    Text {
116        text: String,
117        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
118        rest: serde_json::Map<String, serde_json::Value>,
119    },
120    #[serde(rename = "input_json_delta")]
121    InputJson {
122        partial_json: String,
123        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
124        rest: serde_json::Map<String, serde_json::Value>,
125    },
126    #[serde(rename = "citations_delta")]
127    Citations {
128        citation: Box<Citation>,
129        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
130        rest: serde_json::Map<String, serde_json::Value>,
131    },
132    #[serde(rename = "thinking_delta")]
133    Thinking {
134        #[serde(default, skip_serializing_if = "Option::is_none")]
135        estimated_tokens: Option<u64>,
136        thinking: String,
137        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
138        rest: serde_json::Map<String, serde_json::Value>,
139    },
140    #[serde(rename = "signature_delta")]
141    Signature {
142        signature: String,
143        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
144        rest: serde_json::Map<String, serde_json::Value>,
145    },
146    #[serde(rename = "compaction_delta")]
147    Compaction {
148        content: String,
149        encrypted_content: String,
150        #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
151        rest: serde_json::Map<String, serde_json::Value>,
152    },
153}
154
155#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
156#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
157pub struct CreateMessageStartBody {
158    pub id: String,
159    #[serde(rename = "type")]
160    pub type_: MessageObjectType,
161    pub role: AssistantRole,
162    pub content: Vec<ContentBlock>,
163    pub model: ClaudeModel,
164    pub stop_reason: Option<StopReason>,
165    pub stop_sequence: Option<String>,
166    #[serde(skip_serializing_if = "Option::is_none")]
167    pub usage: Option<Usage>,
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub input_transformations: Option<Vec<InputTransformation>>,
170    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
171    pub rest: serde_json::Map<String, serde_json::Value>,
172}
173
174#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
175#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
176pub struct MessageDelta {
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub container: Option<Container>,
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub stop_reason: Option<StopReason>,
181    #[serde(skip_serializing_if = "Option::is_none")]
182    pub stop_sequence: Option<String>,
183    #[serde(skip_serializing_if = "Option::is_none")]
184    pub stop_details: Option<StopDetails>,
185    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
186    pub rest: serde_json::Map<String, serde_json::Value>,
187}
188
189#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
190#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
191pub struct StreamError {
192    #[serde(rename = "type")]
193    pub type_: String,
194    pub message: String,
195    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
196    pub rest: serde_json::Map<String, serde_json::Value>,
197}