claude_code_rs/types/
messages.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use super::content::ContentBlock;
5
6#[derive(Debug, Clone)]
11pub enum Message {
12 System {
14 subtype: String,
15 data: Value,
16 },
17
18 Assistant {
20 message: AssistantMessage,
21 },
22
23 User {
25 message: UserMessage,
26 },
27
28 Result {
30 result: ResultMessage,
31 },
32
33 Unknown {
35 message_type: String,
36 raw: Value,
37 },
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct AssistantMessage {
43 #[serde(default)]
44 pub id: Option<String>,
45 #[serde(default)]
46 pub model: Option<String>,
47 #[serde(default)]
48 pub content: Vec<ContentBlock>,
49 #[serde(default)]
50 pub stop_reason: Option<String>,
51 #[serde(default)]
52 pub usage: Option<Usage>,
53 #[serde(flatten)]
55 pub extra: Value,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct UserMessage {
61 #[serde(default)]
62 pub id: Option<String>,
63 #[serde(default)]
64 pub content: UserContent,
65 #[serde(flatten)]
66 pub extra: Value,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize, Default)]
71#[serde(untagged)]
72pub enum UserContent {
73 Text(String),
74 Blocks(Vec<ContentBlock>),
75 #[default]
76 Empty,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct ResultMessage {
82 #[serde(default)]
83 pub subtype: Option<String>,
84 #[serde(default)]
85 pub is_error: bool,
86 #[serde(default)]
87 pub error: Option<String>,
88 #[serde(default)]
89 pub duration_ms: Option<f64>,
90 #[serde(default)]
91 pub duration_api_ms: Option<f64>,
92 #[serde(default)]
93 pub num_turns: Option<u32>,
94 #[serde(default)]
95 pub session_id: Option<String>,
96 #[serde(default)]
97 pub cost_usd: Option<f64>,
98 #[serde(default)]
99 pub total_cost_usd: Option<f64>,
100 #[serde(default)]
101 pub usage: Option<Usage>,
102 #[serde(flatten)]
103 pub extra: Value,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct Usage {
109 #[serde(default)]
110 pub input_tokens: Option<u64>,
111 #[serde(default)]
112 pub output_tokens: Option<u64>,
113 #[serde(default)]
114 pub cache_creation_input_tokens: Option<u64>,
115 #[serde(default)]
116 pub cache_read_input_tokens: Option<u64>,
117 #[serde(flatten)]
118 pub extra: Value,
119}
120
121impl Message {
122 pub fn is_result(&self) -> bool {
124 matches!(self, Message::Result { .. })
125 }
126
127 pub fn is_error(&self) -> bool {
129 matches!(self, Message::Result { result } if result.is_error)
130 }
131
132 pub fn text(&self) -> Option<String> {
134 match self {
135 Message::Assistant { message } => {
136 let texts: Vec<&str> = message
137 .content
138 .iter()
139 .filter_map(|b| b.as_text())
140 .collect();
141 if texts.is_empty() {
142 None
143 } else {
144 Some(texts.join(""))
145 }
146 }
147 _ => None,
148 }
149 }
150
151 pub fn session_id(&self) -> Option<&str> {
153 match self {
154 Message::Result { result } => result.session_id.as_deref(),
155 _ => None,
156 }
157 }
158}