synaptic_session/
store_session.rs1use std::sync::Arc;
2
3use serde::{Deserialize, Serialize};
4use synaptic_core::{now_iso, Store, SynapticError};
5use synaptic_graph::StoreCheckpointer;
6use synaptic_memory::ChatMessageHistory;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct SessionInfo {
11 pub id: String,
12 pub created_at: String,
13}
14
15pub struct SessionManager {
21 store: Arc<dyn Store>,
22}
23
24impl SessionManager {
25 pub fn new(store: Arc<dyn Store>) -> Self {
27 Self { store }
28 }
29
30 pub async fn create_session(&self) -> Result<String, SynapticError> {
32 let id = uuid::Uuid::new_v4().to_string();
33 let info = SessionInfo {
34 id: id.clone(),
35 created_at: now_iso(),
36 };
37 let value = serde_json::to_value(&info)
38 .map_err(|e| SynapticError::Store(format!("failed to serialize session info: {e}")))?;
39 self.store.put(&["sessions"], &id, value).await?;
40 Ok(id)
41 }
42
43 pub async fn list_sessions(&self) -> Result<Vec<SessionInfo>, SynapticError> {
45 let items = self.store.search(&["sessions"], None, 10_000).await?;
46 let mut sessions: Vec<SessionInfo> = items
47 .into_iter()
48 .filter_map(|item| serde_json::from_value(item.value).ok())
49 .collect();
50 sessions.sort_by(|a, b| a.created_at.cmp(&b.created_at));
51 Ok(sessions)
52 }
53
54 pub async fn get_session(&self, id: &str) -> Result<Option<SessionInfo>, SynapticError> {
56 let item = self.store.get(&["sessions"], id).await?;
57 match item {
58 Some(item) => {
59 let info: SessionInfo = serde_json::from_value(item.value).map_err(|e| {
60 SynapticError::Store(format!("failed to deserialize session info: {e}"))
61 })?;
62 Ok(Some(info))
63 }
64 None => Ok(None),
65 }
66 }
67
68 pub async fn delete_session(&self, id: &str) -> Result<(), SynapticError> {
70 self.store.delete(&["sessions"], id).await?;
72
73 self.store.delete(&["memory", id], "messages").await?;
75 self.store.delete(&["memory", id], "summary").await?;
76
77 let checkpoints = self
79 .store
80 .search(&["checkpoints", id], None, 10_000)
81 .await?;
82 for ckpt in checkpoints {
83 self.store.delete(&["checkpoints", id], &ckpt.key).await?;
84 }
85
86 Ok(())
87 }
88
89 pub fn memory(&self) -> ChatMessageHistory {
91 ChatMessageHistory::new(self.store.clone())
92 }
93
94 pub fn checkpointer(&self) -> StoreCheckpointer {
96 StoreCheckpointer::new(self.store.clone())
97 }
98
99 pub fn store(&self) -> &Arc<dyn Store> {
101 &self.store
102 }
103}