Skip to main content

gproxy_protocol/protocol/claude/message/
stream.rs

1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5use crate::protocol::claude::common::{
6    AssistantRole, Citation, ClaudeModel, Container, ContentBlock, ContextManagementResponse,
7    JsonObject, MessageObjectType, StopDetails, StopReason, TypedObject, Usage,
8};
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11#[serde(untagged)]
12pub enum StreamEvent {
13    Known(Box<KnownStreamEvent>),
14    Unknown(TypedObject),
15}
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18#[serde(tag = "type")]
19pub enum KnownStreamEvent {
20    #[serde(rename = "message_start")]
21    MessageStart {
22        message: Box<CreateMessageStartBody>,
23        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
24        extra: JsonObject,
25    },
26    #[serde(rename = "content_block_start")]
27    ContentBlockStart {
28        index: u64,
29        content_block: Box<ContentBlock>,
30        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
31        extra: JsonObject,
32    },
33    #[serde(rename = "content_block_delta")]
34    ContentBlockDelta {
35        index: u64,
36        delta: Box<EventDelta>,
37        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
38        extra: JsonObject,
39    },
40    #[serde(rename = "content_block_stop")]
41    ContentBlockStop {
42        index: u64,
43        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
44        extra: JsonObject,
45    },
46    #[serde(rename = "message_delta")]
47    MessageDelta {
48        #[serde(skip_serializing_if = "Option::is_none")]
49        context_management: Option<Box<ContextManagementResponse>>,
50        delta: Box<MessageDelta>,
51        #[serde(skip_serializing_if = "Option::is_none")]
52        usage: Option<Box<Usage>>,
53        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
54        extra: JsonObject,
55    },
56    #[serde(rename = "message_stop")]
57    MessageStop {
58        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
59        extra: JsonObject,
60    },
61    #[serde(rename = "ping")]
62    Ping {
63        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
64        extra: JsonObject,
65    },
66    #[serde(rename = "error")]
67    Error {
68        error: StreamError,
69        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
70        extra: JsonObject,
71    },
72}
73
74#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
75#[serde(untagged)]
76pub enum EventDelta {
77    Known(Box<KnownEventDelta>),
78    Unknown(TypedObject),
79}
80
81#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
82#[serde(tag = "type")]
83pub enum KnownEventDelta {
84    #[serde(rename = "text_delta")]
85    Text {
86        text: String,
87        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
88        extra: JsonObject,
89    },
90    #[serde(rename = "input_json_delta")]
91    InputJson {
92        partial_json: String,
93        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
94        extra: JsonObject,
95    },
96    #[serde(rename = "citations_delta")]
97    Citations {
98        citation: Box<Citation>,
99        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
100        extra: JsonObject,
101    },
102    #[serde(rename = "thinking_delta")]
103    Thinking {
104        #[serde(default, skip_serializing_if = "Option::is_none")]
105        estimated_tokens: Option<u64>,
106        thinking: String,
107        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
108        extra: JsonObject,
109    },
110    #[serde(rename = "signature_delta")]
111    Signature {
112        signature: String,
113        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
114        extra: JsonObject,
115    },
116    #[serde(rename = "compaction_delta")]
117    Compaction {
118        content: String,
119        encrypted_content: String,
120        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
121        extra: JsonObject,
122    },
123}
124
125#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
126pub struct CreateMessageStartBody {
127    pub id: String,
128    #[serde(rename = "type")]
129    pub type_: MessageObjectType,
130    pub role: AssistantRole,
131    pub content: Vec<ContentBlock>,
132    pub model: ClaudeModel,
133    pub stop_reason: Option<StopReason>,
134    pub stop_sequence: Option<String>,
135    pub usage: Usage,
136    #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
137    pub extra: JsonObject,
138}
139
140#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
141pub struct MessageDelta {
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub container: Option<Container>,
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub stop_reason: Option<StopReason>,
146    #[serde(skip_serializing_if = "Option::is_none")]
147    pub stop_sequence: Option<String>,
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub stop_details: Option<StopDetails>,
150    #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
151    pub extra: JsonObject,
152}
153
154#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
155pub struct StreamError {
156    #[serde(rename = "type")]
157    pub type_: String,
158    pub message: String,
159    #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
160    pub extra: JsonObject,
161}