synaptic_memory/
file_history.rs1use std::path::PathBuf;
2
3use async_trait::async_trait;
4use synaptic_core::{MemoryStore, Message, SynapticError};
5
6pub struct FileChatMessageHistory {
11 path: PathBuf,
12}
13
14impl FileChatMessageHistory {
15 pub fn new(path: impl Into<PathBuf>) -> Self {
20 Self { path: path.into() }
21 }
22
23 fn session_path(&self, session_id: &str) -> PathBuf {
24 self.path.join(format!("{session_id}.json"))
25 }
26
27 async fn read_messages(&self, session_id: &str) -> Result<Vec<Message>, SynapticError> {
28 let path = self.session_path(session_id);
29 match tokio::fs::read_to_string(&path).await {
30 Ok(contents) => {
31 let messages: Vec<Message> = serde_json::from_str(&contents).map_err(|e| {
32 SynapticError::Memory(format!("failed to parse {}: {e}", path.display()))
33 })?;
34 Ok(messages)
35 }
36 Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(Vec::new()),
37 Err(e) => Err(SynapticError::Memory(format!(
38 "failed to read {}: {e}",
39 path.display()
40 ))),
41 }
42 }
43
44 async fn write_messages(
45 &self,
46 session_id: &str,
47 messages: &[Message],
48 ) -> Result<(), SynapticError> {
49 if let Some(parent) = self.session_path(session_id).parent() {
51 tokio::fs::create_dir_all(parent)
52 .await
53 .map_err(|e| SynapticError::Memory(format!("failed to create directory: {e}")))?;
54 }
55
56 let path = self.session_path(session_id);
57 let json = serde_json::to_string_pretty(messages)
58 .map_err(|e| SynapticError::Memory(format!("failed to serialize messages: {e}")))?;
59 tokio::fs::write(&path, json)
60 .await
61 .map_err(|e| SynapticError::Memory(format!("failed to write {}: {e}", path.display())))
62 }
63}
64
65#[async_trait]
66impl MemoryStore for FileChatMessageHistory {
67 async fn append(&self, session_id: &str, message: Message) -> Result<(), SynapticError> {
68 let mut messages = self.read_messages(session_id).await?;
69 messages.push(message);
70 self.write_messages(session_id, &messages).await
71 }
72
73 async fn load(&self, session_id: &str) -> Result<Vec<Message>, SynapticError> {
74 self.read_messages(session_id).await
75 }
76
77 async fn clear(&self, session_id: &str) -> Result<(), SynapticError> {
78 self.write_messages(session_id, &[]).await
79 }
80}