1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use uuid::Uuid;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(tag = "type")]
8pub enum Message {
9 #[serde(rename = "system")]
11 System(SystemMessage),
12
13 #[serde(rename = "assistant")]
15 Assistant(AssistantMessage),
16
17 #[serde(rename = "user")]
19 User(UserMessage),
20
21 #[serde(rename = "result")]
23 Result(ResultMessage),
24
25 #[serde(rename = "stream_event")]
27 StreamEvent(StreamEventMessage),
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct SystemMessage {
33 pub subtype: SystemSubtype,
34 pub uuid: Uuid,
35 pub session_id: String,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub agents: Option<Vec<String>>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub claude_code_version: Option<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub cwd: Option<String>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub tools: Option<Vec<String>>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub mcp_servers: Option<Vec<McpServerStatus>>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub model: Option<String>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub permission_mode: Option<String>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub compact_metadata: Option<CompactMetadata>,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
59#[serde(rename_all = "snake_case")]
60pub enum SystemSubtype {
61 Init,
62 CompactBoundary,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct McpServerStatus {
67 pub name: String,
68 pub status: String,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct CompactMetadata {
73 pub trigger: CompactTrigger,
74 pub pre_tokens: u64,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
78#[serde(rename_all = "snake_case")]
79pub enum CompactTrigger {
80 Manual,
81 Auto,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86#[serde(tag = "type")]
87pub enum ContentBlock {
88 #[serde(rename = "text")]
90 Text { text: String },
91
92 #[serde(rename = "tool_use")]
94 ToolUse {
95 id: String,
96 name: String,
97 input: serde_json::Value,
98 },
99
100 #[serde(rename = "tool_result")]
102 ToolResult {
103 tool_use_id: String,
104 content: serde_json::Value,
105 #[serde(skip_serializing_if = "Option::is_none")]
106 is_error: Option<bool>,
107 },
108
109 #[serde(rename = "thinking")]
111 Thinking {
112 thinking: String,
113 },
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct AssistantMessage {
119 pub uuid: Uuid,
120 pub session_id: String,
121 pub content: Vec<ContentBlock>,
122 pub model: String,
123 #[serde(skip_serializing_if = "Option::is_none")]
124 pub stop_reason: Option<String>,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub parent_tool_use_id: Option<String>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub usage: Option<Usage>,
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub error: Option<AssistantMessageError>,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
134#[serde(rename_all = "snake_case")]
135pub enum AssistantMessageError {
136 AuthenticationFailed,
137 BillingError,
138 RateLimit,
139 InvalidRequest,
140 ServerError,
141 Unknown,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct UserMessage {
147 pub uuid: Option<Uuid>,
148 pub session_id: String,
149 pub content: Vec<ContentBlock>,
150 #[serde(skip_serializing_if = "Option::is_none")]
151 pub parent_tool_use_id: Option<String>,
152 #[serde(default)]
153 pub is_synthetic: bool,
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub tool_use_result: Option<serde_json::Value>,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct ResultMessage {
161 pub subtype: ResultSubtype,
162 pub uuid: Uuid,
163 pub session_id: String,
164 pub duration_ms: u64,
165 pub duration_api_ms: u64,
166 pub is_error: bool,
167 pub num_turns: u32,
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub result: Option<String>,
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub stop_reason: Option<String>,
172 pub total_cost_usd: f64,
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub usage: Option<Usage>,
175 #[serde(default)]
176 pub model_usage: HashMap<String, ModelUsage>,
177 #[serde(default)]
178 pub permission_denials: Vec<PermissionDenial>,
179 #[serde(skip_serializing_if = "Option::is_none")]
180 pub structured_output: Option<serde_json::Value>,
181 #[serde(default)]
182 pub errors: Vec<String>,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
186#[serde(rename_all = "snake_case")]
187pub enum ResultSubtype {
188 Success,
189 ErrorMaxTurns,
190 ErrorDuringExecution,
191 ErrorMaxBudgetUsd,
192 ErrorMaxStructuredOutputRetries,
193}
194
195#[derive(Debug, Clone, Default, Serialize, Deserialize)]
197pub struct Usage {
198 pub input_tokens: u64,
199 pub output_tokens: u64,
200 #[serde(default)]
201 pub cache_creation_input_tokens: u64,
202 #[serde(default)]
203 pub cache_read_input_tokens: u64,
204}
205
206#[derive(Debug, Clone, Default, Serialize, Deserialize)]
208pub struct ModelUsage {
209 pub input_tokens: u64,
210 pub output_tokens: u64,
211 #[serde(default)]
212 pub cache_creation_input_tokens: u64,
213 #[serde(default)]
214 pub cache_read_input_tokens: u64,
215 pub cost_usd: f64,
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct PermissionDenial {
221 pub tool_name: String,
222 pub tool_use_id: String,
223 pub tool_input: serde_json::Value,
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize)]
228pub struct StreamEventMessage {
229 pub event: serde_json::Value,
230 pub parent_tool_use_id: Option<String>,
231 pub uuid: Uuid,
232 pub session_id: String,
233}