use async_trait::async_trait;
use serde_json::Value;
#[derive(Debug, Clone)]
pub struct MemoryEntry {
pub key: String,
pub value: String,
pub metadata: Option<Value>,
pub created_at: chrono::DateTime<chrono::Utc>,
}
#[derive(Debug, Clone)]
pub struct EmbeddingEntry {
pub namespace: String,
pub key: String,
pub vector: Vec<f32>,
pub text: String,
pub created_at: chrono::DateTime<chrono::Utc>,
}
#[derive(Debug, Clone)]
pub struct FileIndex {
pub path: String,
pub hash: String,
pub last_indexed: chrono::DateTime<chrono::Utc>,
}
#[derive(Debug, Clone)]
pub struct Chunk {
pub file_path: String,
pub start_line: u32,
pub end_line: u32,
pub content: String,
pub embedding: Option<Vec<f32>>,
pub created_at: chrono::DateTime<chrono::Utc>,
}
#[derive(Debug, Clone)]
pub struct ConversationSearchHit {
pub chat_id: String,
pub role: String,
pub content: String,
pub created_at: chrono::DateTime<chrono::Utc>,
}
#[async_trait]
pub trait MemoryBackend: Send + Sync {
fn as_any(&self) -> &dyn std::any::Any;
async fn store(
&self,
namespace: &str,
key: &str,
value: &str,
metadata: Option<Value>,
) -> anyhow::Result<()>;
async fn recall(&self, namespace: &str, key: &str) -> anyhow::Result<Option<MemoryEntry>>;
async fn search(
&self,
namespace: &str,
query: &str,
limit: usize,
) -> anyhow::Result<Vec<MemoryEntry>>;
async fn forget(&self, namespace: &str, key: &str) -> anyhow::Result<()>;
async fn list(&self, namespace: &str) -> anyhow::Result<Vec<MemoryEntry>>;
async fn store_conversation(
&self,
chat_id: &str,
sender_id: &str,
role: &str,
content: &str,
) -> anyhow::Result<()>;
async fn store_conversation_batch(
&self,
entries: &[(&str, &str, &str, &str)],
) -> anyhow::Result<()> {
for (chat_id, sender_id, role, content) in entries {
self.store_conversation(chat_id, sender_id, role, content)
.await?;
}
Ok(())
}
async fn get_conversation_history(
&self,
chat_id: &str,
limit: usize,
) -> anyhow::Result<Vec<(String, String)>>;
async fn search_conversations(
&self,
query: &str,
limit: usize,
chat_id: Option<&str>,
) -> anyhow::Result<Vec<ConversationSearchHit>> {
let _ = (query, limit, chat_id);
Ok(Vec::new())
}
async fn get_sticker_cache(&self, sticker_id: &str) -> anyhow::Result<Option<String>>;
async fn store_sticker_cache(
&self,
sticker_id: &str,
file_id: &str,
description: &str,
) -> anyhow::Result<()>;
async fn store_embedding(
&self,
namespace: &str,
key: &str,
vector: &[f32],
text: &str,
) -> anyhow::Result<()> {
let _ = (namespace, key, vector, text);
Ok(())
}
async fn search_embeddings(
&self,
namespace: &str,
query_vector: &[f32],
limit: usize,
) -> anyhow::Result<Vec<EmbeddingEntry>> {
let _ = (namespace, query_vector, limit);
Ok(Vec::new())
}
async fn store_file_index(&self, path: &str, hash: &str) -> anyhow::Result<()> {
let _ = (path, hash);
Ok(())
}
async fn get_file_index(&self, path: &str) -> anyhow::Result<Option<FileIndex>> {
let _ = path;
Ok(None)
}
async fn store_chunk(
&self,
file_path: &str,
start_line: u32,
end_line: u32,
content: &str,
embedding: Option<&[f32]>,
) -> anyhow::Result<()> {
let _ = (file_path, start_line, end_line, content, embedding);
Ok(())
}
async fn get_chunks_for_file(&self, file_path: &str) -> anyhow::Result<Vec<Chunk>> {
let _ = file_path;
Ok(Vec::new())
}
async fn delete_chunks_for_file(&self, file_path: &str) -> anyhow::Result<()> {
let _ = file_path;
Ok(())
}
}