1use async_trait::async_trait;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct MemoryEntry {
6 pub id: String,
7 pub key: String,
8 pub content: String,
9 pub category: MemoryCategory,
10 pub timestamp: String,
11 pub session_id: Option<String>,
12 pub score: Option<f64>,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
16#[serde(rename_all = "snake_case")]
17pub enum MemoryCategory {
18 Core,
19 Daily,
20 Conversation,
21 Custom(String),
22}
23
24impl std::fmt::Display for MemoryCategory {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 Self::Core => write!(f, "core"),
28 Self::Daily => write!(f, "daily"),
29 Self::Conversation => write!(f, "conversation"),
30 Self::Custom(name) => write!(f, "{name}"),
31 }
32 }
33}
34
35#[async_trait]
36pub trait Memory: Send + Sync {
37 fn name(&self) -> &str;
38
39 async fn store(
40 &self,
41 key: &str,
42 content: &str,
43 category: MemoryCategory,
44 session_id: Option<&str>,
45 ) -> anyhow::Result<()>;
46
47 async fn recall(
48 &self,
49 query: &str,
50 limit: usize,
51 session_id: Option<&str>,
52 ) -> anyhow::Result<Vec<MemoryEntry>>;
53
54 async fn get(&self, key: &str) -> anyhow::Result<Option<MemoryEntry>>;
55
56 async fn list(
57 &self,
58 category: Option<&MemoryCategory>,
59 session_id: Option<&str>,
60 ) -> anyhow::Result<Vec<MemoryEntry>>;
61
62 async fn forget(&self, key: &str) -> anyhow::Result<bool>;
63 async fn count(&self) -> anyhow::Result<usize>;
64 async fn health_check(&self) -> bool;
65}