agent_diva_core/session/
store.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct Session {
9 pub key: String,
11 pub messages: Vec<ChatMessage>,
13 pub created_at: DateTime<Utc>,
15 pub updated_at: DateTime<Utc>,
17 pub metadata: serde_json::Value,
19 #[serde(default)]
21 pub last_consolidated: usize,
22}
23
24impl Session {
25 pub fn new(key: impl Into<String>) -> Self {
27 let now = Utc::now();
28 Self {
29 key: key.into(),
30 messages: Vec::new(),
31 created_at: now,
32 updated_at: now,
33 metadata: serde_json::Value::Object(serde_json::Map::new()),
34 last_consolidated: 0,
35 }
36 }
37
38 pub fn add_message(&mut self, role: impl Into<String>, content: impl Into<String>) {
40 self.messages.push(ChatMessage {
41 role: role.into(),
42 content: content.into(),
43 timestamp: Utc::now(),
44 tool_call_id: None,
45 tool_calls: None,
46 name: None,
47 reasoning_content: None,
48 thinking_blocks: None,
49 });
50 self.updated_at = Utc::now();
51 }
52
53 pub fn add_full_message(&mut self, msg: ChatMessage) {
55 self.messages.push(msg);
56 self.updated_at = Utc::now();
57 }
58
59 pub fn get_history(&self, max_messages: usize) -> Vec<ChatMessage> {
61 let consolidated = self.last_consolidated.min(self.messages.len());
63 let unconsolidated = &self.messages[consolidated..];
64 let start = unconsolidated.len().saturating_sub(max_messages);
65 let mut sliced: Vec<ChatMessage> = unconsolidated[start..]
66 .iter()
67 .filter(|m| matches!(m.role.as_str(), "user" | "assistant" | "tool"))
68 .cloned()
69 .collect();
70 if let Some(pos) = sliced.iter().position(|m| m.role == "user") {
72 sliced = sliced[pos..].to_vec();
73 }
74 sliced
75 }
76
77 pub fn clear(&mut self) {
79 self.messages.clear();
80 self.last_consolidated = 0;
81 self.updated_at = Utc::now();
82 }
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct ChatMessage {
88 pub role: String,
90 pub content: String,
92 pub timestamp: DateTime<Utc>,
94 #[serde(skip_serializing_if = "Option::is_none", default)]
96 pub tool_call_id: Option<String>,
97 #[serde(skip_serializing_if = "Option::is_none", default)]
99 pub tool_calls: Option<Vec<serde_json::Value>>,
100 #[serde(skip_serializing_if = "Option::is_none", default)]
102 pub name: Option<String>,
103 #[serde(skip_serializing_if = "Option::is_none", default)]
105 pub reasoning_content: Option<String>,
106 #[serde(skip_serializing_if = "Option::is_none", default)]
108 pub thinking_blocks: Option<Vec<serde_json::Value>>,
109}
110
111impl ChatMessage {
112 pub fn new(role: impl Into<String>, content: impl Into<String>) -> Self {
114 Self {
115 role: role.into(),
116 content: content.into(),
117 timestamp: Utc::now(),
118 tool_call_id: None,
119 tool_calls: None,
120 name: None,
121 reasoning_content: None,
122 thinking_blocks: None,
123 }
124 }
125
126 pub fn with_tool_metadata(
128 role: impl Into<String>,
129 content: impl Into<String>,
130 tool_call_id: Option<String>,
131 tool_calls: Option<Vec<serde_json::Value>>,
132 name: Option<String>,
133 ) -> Self {
134 Self {
135 role: role.into(),
136 content: content.into(),
137 timestamp: Utc::now(),
138 tool_call_id,
139 tool_calls,
140 name,
141 reasoning_content: None,
142 thinking_blocks: None,
143 }
144 }
145
146 pub fn to_llm_format(&self) -> serde_json::Value {
148 serde_json::json!({
149 "role": &self.role,
150 "content": &self.content,
151 })
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn test_session_creation() {
161 let session = Session::new("telegram:12345");
162 assert_eq!(session.key, "telegram:12345");
163 assert!(session.messages.is_empty());
164 }
165
166 #[test]
167 fn test_add_message() {
168 let mut session = Session::new("test");
169 session.add_message("user", "Hello");
170 session.add_message("assistant", "Hi there!");
171
172 assert_eq!(session.messages.len(), 2);
173 assert_eq!(session.messages[0].role, "user");
174 assert_eq!(session.messages[1].role, "assistant");
175 }
176
177 #[test]
178 fn test_get_history() {
179 let mut session = Session::new("test");
180 for i in 0..60 {
181 session.add_message("user", format!("Message {}", i));
182 }
183
184 let history = session.get_history(50);
185 assert_eq!(history.len(), 50);
186 }
187}