1use serde::{Deserialize, Serialize};
2use std::time::SystemTime;
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
5#[serde(rename_all = "snake_case")]
6pub enum MessageType {
7 Init,
8 User,
9 Assistant,
10 Result,
11 System,
12 Tool,
13 ToolResult,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct MessageMeta {
18 pub session_id: String,
19 pub timestamp: Option<SystemTime>,
20 pub cost_usd: Option<f64>,
21 pub duration_ms: Option<u64>,
22 pub tokens_used: Option<TokenUsage>,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct TokenUsage {
27 pub input: u64,
28 pub output: u64,
29 pub total: u64,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33#[serde(tag = "type", rename_all = "snake_case")]
34pub enum Message {
35 Init {
36 #[serde(flatten)]
37 meta: MessageMeta,
38 },
39 User {
40 content: String,
41 #[serde(flatten)]
42 meta: MessageMeta,
43 },
44 Assistant {
45 content: String,
46 #[serde(flatten)]
47 meta: MessageMeta,
48 },
49 Result {
50 #[serde(flatten)]
51 meta: MessageMeta,
52 stats: ConversationStats,
53 },
54 System {
55 content: String,
56 #[serde(flatten)]
57 meta: MessageMeta,
58 },
59 Tool {
60 name: String,
61 parameters: serde_json::Value,
62 #[serde(flatten)]
63 meta: MessageMeta,
64 },
65 ToolResult {
66 tool_name: String,
67 result: serde_json::Value,
68 #[serde(flatten)]
69 meta: MessageMeta,
70 },
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct ConversationStats {
75 pub total_messages: u64,
76 pub total_cost_usd: f64,
77 pub total_duration_ms: u64,
78 pub total_tokens: TokenUsage,
79}
80
81impl Message {
82 pub fn message_type(&self) -> MessageType {
83 match self {
84 Message::Init { .. } => MessageType::Init,
85 Message::User { .. } => MessageType::User,
86 Message::Assistant { .. } => MessageType::Assistant,
87 Message::Result { .. } => MessageType::Result,
88 Message::System { .. } => MessageType::System,
89 Message::Tool { .. } => MessageType::Tool,
90 Message::ToolResult { .. } => MessageType::ToolResult,
91 }
92 }
93
94 pub fn meta(&self) -> &MessageMeta {
95 match self {
96 Message::Init { meta, .. } |
97 Message::User { meta, .. } |
98 Message::Assistant { meta, .. } |
99 Message::Result { meta, .. } |
100 Message::System { meta, .. } |
101 Message::Tool { meta, .. } |
102 Message::ToolResult { meta, .. } => meta,
103 }
104 }
105}