pub mod in_memory;
#[cfg(feature = "rag")]
pub mod trueno;
pub use in_memory::InMemorySubstrate;
#[cfg(feature = "rag")]
pub use trueno::TruenoMemory;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::agent::result::AgentError;
pub type MemoryId = String;
#[derive(Debug, Clone, Default)]
pub struct MemoryFilter {
pub agent_id: Option<String>,
pub source: Option<MemorySource>,
pub since: Option<chrono::DateTime<chrono::Utc>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum MemorySource {
Conversation,
ToolResult,
System,
User,
}
#[derive(Debug, Clone)]
pub struct MemoryFragment {
pub id: MemoryId,
pub content: String,
pub source: MemorySource,
pub relevance_score: f32,
pub created_at: chrono::DateTime<chrono::Utc>,
}
#[async_trait]
pub trait MemorySubstrate: Send + Sync {
async fn remember(
&self,
agent_id: &str,
content: &str,
source: MemorySource,
embedding: Option<&[f32]>,
) -> Result<MemoryId, AgentError>;
async fn recall(
&self,
query: &str,
limit: usize,
filter: Option<MemoryFilter>,
query_embedding: Option<&[f32]>,
) -> Result<Vec<MemoryFragment>, AgentError>;
async fn set(
&self,
agent_id: &str,
key: &str,
value: serde_json::Value,
) -> Result<(), AgentError>;
async fn get(&self, agent_id: &str, key: &str)
-> Result<Option<serde_json::Value>, AgentError>;
async fn forget(&self, id: MemoryId) -> Result<(), AgentError>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_memory_source_serialization() {
let sources = vec![
MemorySource::Conversation,
MemorySource::ToolResult,
MemorySource::System,
MemorySource::User,
];
for source in &sources {
let json = serde_json::to_string(source).expect("serialize failed");
let back: MemorySource = serde_json::from_str(&json).expect("deserialize failed");
assert_eq!(*source, back);
}
}
#[test]
fn test_memory_filter_default() {
let filter = MemoryFilter::default();
assert!(filter.agent_id.is_none());
assert!(filter.source.is_none());
assert!(filter.since.is_none());
}
}