1use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct MessageOrigin {
10 #[serde(rename = "kind", skip_serializing_if = "Option::is_none")]
11 pub kind: Option<String>,
12 #[serde(flatten)]
13 pub extra: HashMap<String, serde_json::Value>,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, Default)]
18pub struct MessageBase {
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub uuid: Option<String>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 #[serde(rename = "parentUuid")]
23 pub parent_uuid: Option<String>,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 pub timestamp: Option<String>,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 #[serde(rename = "createdAt")]
28 pub created_at: Option<String>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 #[serde(rename = "isMeta")]
31 pub is_meta: Option<bool>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 #[serde(rename = "isVirtual")]
34 pub is_virtual: Option<bool>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 #[serde(rename = "isCompactSummary")]
37 pub is_compact_summary: Option<bool>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 #[serde(rename = "toolUseResult")]
40 pub tool_use_result: Option<serde_json::Value>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub origin: Option<MessageOrigin>,
43 #[serde(flatten)]
44 pub extra: HashMap<String, serde_json::Value>,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct AttachmentMessage {
50 #[serde(flatten)]
51 pub base: MessageBase,
52 #[serde(rename = "type")]
53 pub message_type: String, #[serde(skip_serializing_if = "Option::is_none")]
55 pub path: Option<String>,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct UserMessage {
61 #[serde(flatten)]
62 pub base: MessageBase,
63 #[serde(rename = "type")]
64 pub message_type: String, pub message: UserMessageContent,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct UserMessageContent {
71 pub content: UserContent,
72 #[serde(flatten)]
73 pub extra: HashMap<String, serde_json::Value>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78#[serde(untagged)]
79pub enum UserContent {
80 Text(String),
81 Blocks(Vec<UserContentBlock>),
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct UserContentBlock {
87 #[serde(rename = "type")]
88 pub block_type: String,
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub text: Option<String>,
91 #[serde(flatten)]
92 pub extra: HashMap<String, serde_json::Value>,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct AssistantMessage {
98 #[serde(flatten)]
99 pub base: MessageBase,
100 #[serde(rename = "type")]
101 pub message_type: String, #[serde(skip_serializing_if = "Option::is_none")]
103 pub message: Option<AssistantMessageContent>,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct AssistantMessageContent {
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub content: Option<serde_json::Value>,
111 #[serde(flatten)]
112 pub extra: HashMap<String, serde_json::Value>,
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct ProgressMessage {
118 #[serde(flatten)]
119 pub base: MessageBase,
120 #[serde(rename = "type")]
121 pub message_type: String, #[serde(skip_serializing_if = "Option::is_none")]
123 pub progress: Option<serde_json::Value>,
124}
125
126pub type SystemMessageLevel = String;
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct SystemMessage {
132 #[serde(flatten)]
133 pub base: MessageBase,
134 #[serde(rename = "type")]
135 pub message_type: String, #[serde(skip_serializing_if = "Option::is_none")]
137 pub subtype: Option<String>,
138 #[serde(skip_serializing_if = "Option::is_none")]
139 pub level: Option<SystemMessageLevel>,
140 #[serde(skip_serializing_if = "Option::is_none")]
141 pub message: Option<String>,
142}
143
144pub type SystemLocalCommandMessage = SystemMessage;
146
147pub type SystemBridgeStatusMessage = SystemMessage;
149
150pub type SystemTurnDurationMessage = SystemMessage;
152
153pub type SystemThinkingMessage = SystemMessage;
155
156pub type SystemMemorySavedMessage = SystemMessage;
158
159pub type SystemStopHookSummaryMessage = SystemMessage;
161
162pub type SystemInformationalMessage = SystemMessage;
164
165pub type SystemCompactBoundaryMessage = SystemMessage;
167
168pub type SystemMicrocompactBoundaryMessage = SystemMessage;
170
171pub type SystemPermissionRetryMessage = SystemMessage;
173
174pub type SystemScheduledTaskFireMessage = SystemMessage;
176
177pub type SystemAwaySummaryMessage = SystemMessage;
179
180pub type SystemAgentsKilledMessage = SystemMessage;
182
183pub type SystemApiMetricsMessage = SystemMessage;
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct SystemApiErrorMessage {
189 #[serde(flatten)]
190 pub base: MessageBase,
191 #[serde(rename = "type")]
192 pub message_type: String, #[serde(skip_serializing_if = "Option::is_none")]
194 pub subtype: Option<String>,
195 #[serde(skip_serializing_if = "Option::is_none")]
196 pub level: Option<SystemMessageLevel>,
197 #[serde(skip_serializing_if = "Option::is_none")]
198 pub message: Option<String>,
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub error: Option<String>,
201}
202
203pub type SystemFileSnapshotMessage = SystemMessage;
205
206#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct HookResultMessage {
209 #[serde(flatten)]
210 pub base: MessageBase,
211 #[serde(rename = "type")]
212 pub message_type: String, }
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct ToolUseSummaryMessage {
218 #[serde(flatten)]
219 pub base: MessageBase,
220 #[serde(rename = "type")]
221 pub message_type: String, }
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct TombstoneMessage {
227 #[serde(flatten)]
228 pub base: MessageBase,
229 #[serde(rename = "type")]
230 pub message_type: String, }
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
235pub struct StreamEvent {
236 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
237 pub event_type: Option<String>,
238 #[serde(flatten)]
239 pub extra: HashMap<String, serde_json::Value>,
240}
241
242pub type RequestStartEvent = StreamEvent;
244
245pub type StopHookInfo = HashMap<String, serde_json::Value>;
247
248pub type CompactMetadata = HashMap<String, serde_json::Value>;
250
251pub type PartialCompactDirection = String;
253
254pub type CollapsedReadSearchGroup = HashMap<String, serde_json::Value>;
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct GroupedToolUseMessage {
260 #[serde(flatten)]
261 pub base: MessageBase,
262 #[serde(rename = "type")]
263 pub message_type: String, }
265
266pub type CollapsibleMessage = MessageBase;
268
269pub type NormalizedAssistantMessage = AssistantMessage;
271
272pub type NormalizedUserMessage = UserMessage;
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
277#[serde(tag = "type")]
278pub enum NormalizedMessage {
279 #[serde(rename = "assistant")]
280 Assistant(AssistantMessage),
281 #[serde(rename = "user")]
282 User(UserMessage),
283 #[serde(rename = "progress")]
284 Progress(ProgressMessage),
285 #[serde(rename = "system")]
286 System(SystemMessage),
287 #[serde(rename = "attachment")]
288 Attachment(AttachmentMessage),
289}
290
291pub type RenderableMessage = Message;
293
294#[derive(Debug, Clone, Serialize, Deserialize)]
296#[serde(tag = "type")]
297pub enum Message {
298 #[serde(rename = "user")]
299 User(UserMessage),
300 #[serde(rename = "assistant")]
301 Assistant(AssistantMessage),
302 #[serde(rename = "progress")]
303 Progress(ProgressMessage),
304 #[serde(rename = "system")]
305 System(SystemMessage),
306 #[serde(rename = "attachment")]
307 Attachment(AttachmentMessage),
308 #[serde(rename = "hook_result")]
309 HookResult(HookResultMessage),
310 #[serde(rename = "tool_use_summary")]
311 ToolUseSummary(ToolUseSummaryMessage),
312 #[serde(rename = "tombstone")]
313 Tombstone(TombstoneMessage),
314 #[serde(rename = "grouped_tool_use")]
315 GroupedToolUse(GroupedToolUseMessage),
316}
317
318pub fn create_away_summary_message(content: &str) -> Message {
321 Message::System(SystemMessage {
322 base: MessageBase {
323 uuid: Some(uuid::Uuid::new_v4().to_string()),
324 timestamp: Some(chrono::Utc::now().to_rfc3339()),
325 created_at: Some(chrono::Utc::now().to_rfc3339()),
326 is_meta: Some(false),
327 ..Default::default()
328 },
329 message_type: "system".to_string(),
330 subtype: Some("away_summary".to_string()),
331 level: None,
332 message: Some(content.to_string()),
333 })
334}