1use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
7#[serde(transparent)]
8pub struct SessionId(pub Uuid);
9
10impl SessionId {
11 #[must_use]
12 pub fn new() -> Self {
13 Self(Uuid::new_v4())
14 }
15}
16
17impl Default for SessionId {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl std::fmt::Display for SessionId {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "{}", self.0)
26 }
27}
28
29#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
30#[serde(rename_all = "lowercase")]
31pub enum Role {
32 System,
33 User,
34 Assistant,
35 Tool,
36}
37
38impl Role {
39 #[must_use]
42 pub const fn as_wire_str(self) -> &'static str {
43 match self {
44 Self::System => "system",
45 Self::User => "user",
46 Self::Assistant => "assistant",
47 Self::Tool => "tool",
48 }
49 }
50
51 #[must_use]
55 pub fn from_wire_str(s: &str) -> Option<Self> {
56 Some(match s {
57 "system" => Self::System,
58 "user" => Self::User,
59 "assistant" => Self::Assistant,
60 "tool" => Self::Tool,
61 _ => return None,
62 })
63 }
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct Message {
68 pub role: Role,
69 pub content: String,
70 #[serde(skip_serializing_if = "Vec::is_empty", default)]
71 pub tool_calls: Vec<ToolCall>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct ToolCall {
76 pub id: String,
77 pub server: String,
78 pub tool: String,
79 pub arguments: serde_json::Value,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct ToolResult {
84 pub call_id: String,
85 pub content: serde_json::Value,
86 #[serde(default)]
87 pub is_error: bool,
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn session_id_is_unique() {
96 let a = SessionId::new();
97 let b = SessionId::new();
98 assert_ne!(a, b);
99 }
100
101 #[test]
102 fn message_serde_roundtrip() {
103 let msg = Message {
104 role: Role::Assistant,
105 content: "hello".into(),
106 tool_calls: vec![],
107 };
108 let json = serde_json::to_string(&msg).unwrap();
109 let back: Message = serde_json::from_str(&json).unwrap();
110 assert!(matches!(back.role, Role::Assistant));
111 assert_eq!(back.content, "hello");
112 }
113}