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 { thinking: String },
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct AssistantMessage {
117 pub uuid: Uuid,
118 pub session_id: String,
119 pub content: Vec<ContentBlock>,
120 pub model: String,
121 #[serde(skip_serializing_if = "Option::is_none")]
122 pub stop_reason: Option<String>,
123 #[serde(skip_serializing_if = "Option::is_none")]
124 pub parent_tool_use_id: Option<String>,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub usage: Option<Usage>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub error: Option<AssistantMessageError>,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
132#[serde(rename_all = "snake_case")]
133pub enum AssistantMessageError {
134 AuthenticationFailed,
135 BillingError,
136 RateLimit,
137 InvalidRequest,
138 ServerError,
139 Unknown,
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct UserMessage {
145 pub uuid: Option<Uuid>,
146 pub session_id: String,
147 pub content: Vec<ContentBlock>,
148 #[serde(skip_serializing_if = "Option::is_none")]
149 pub parent_tool_use_id: Option<String>,
150 #[serde(default)]
151 pub is_synthetic: bool,
152 #[serde(skip_serializing_if = "Option::is_none")]
153 pub tool_use_result: Option<serde_json::Value>,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct ResultMessage {
159 pub subtype: ResultSubtype,
160 pub uuid: Uuid,
161 pub session_id: String,
162 pub duration_ms: u64,
163 pub duration_api_ms: u64,
164 pub is_error: bool,
165 pub num_turns: u32,
166 #[serde(skip_serializing_if = "Option::is_none")]
167 pub result: Option<String>,
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub stop_reason: Option<String>,
170 pub total_cost_usd: f64,
171 #[serde(skip_serializing_if = "Option::is_none")]
172 pub usage: Option<Usage>,
173 #[serde(default)]
174 pub model_usage: HashMap<String, ModelUsage>,
175 #[serde(default)]
176 pub permission_denials: Vec<PermissionDenial>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub structured_output: Option<serde_json::Value>,
179 #[serde(default)]
180 pub errors: Vec<String>,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
184#[serde(rename_all = "snake_case")]
185pub enum ResultSubtype {
186 Success,
187 ErrorMaxTurns,
188 ErrorDuringExecution,
189 ErrorMaxBudgetUsd,
190 ErrorMaxStructuredOutputRetries,
191}
192
193#[derive(Debug, Clone, Default, Serialize, Deserialize)]
195pub struct Usage {
196 pub input_tokens: u64,
197 pub output_tokens: u64,
198 #[serde(default)]
199 pub cache_creation_input_tokens: u64,
200 #[serde(default)]
201 pub cache_read_input_tokens: u64,
202}
203
204#[derive(Debug, Clone, Default, Serialize, Deserialize)]
206pub struct ModelUsage {
207 pub input_tokens: u64,
208 pub output_tokens: u64,
209 #[serde(default)]
210 pub cache_creation_input_tokens: u64,
211 #[serde(default)]
212 pub cache_read_input_tokens: u64,
213 pub cost_usd: f64,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct PermissionDenial {
219 pub tool_name: String,
220 pub tool_use_id: String,
221 pub tool_input: serde_json::Value,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct StreamEventMessage {
227 pub event: serde_json::Value,
228 pub parent_tool_use_id: Option<String>,
229 pub uuid: Uuid,
230 pub session_id: String,
231}