use async_trait::async_trait;
use crate::entry::{ContextEntry, ScoredEntry};
use crate::error::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[async_trait]
pub trait ContextStorage: Send + Sync {
async fn save(&self, entry: &ContextEntry) -> Result<()>;
async fn get_top_k(&self, k: usize) -> Result<Vec<ContextEntry>>;
async fn get_all(&self) -> Result<Vec<ContextEntry>>;
async fn delete(&self, id: &str) -> Result<bool>;
async fn clear(&self) -> Result<usize>;
async fn clear_scope(&self, scope: &str) -> Result<usize>;
async fn count(&self) -> Result<usize>;
async fn save_embedding(&self, id: &str, embedding: &[f32]) -> Result<()> {
tracing::trace!(id = %id, dims = embedding.len(), "save_embedding: no-op");
let _ = (id, embedding);
Ok(())
}
async fn get_unembedded(&self, limit: usize) -> Result<Vec<ContextEntry>> {
tracing::trace!(limit = %limit, "get_unembedded: using get_all fallback");
let all = self.get_all().await?;
Ok(all.into_iter().take(limit).collect())
}
}
#[async_trait]
pub trait Searcher: Send + Sync {
async fn search_semantic(
&self,
embedding: &[f32],
scope: Option<&str>,
limit: usize,
) -> Result<Vec<ScoredEntry>> {
tracing::trace!(dims = embedding.len(), "search_semantic: no-op");
let _ = (embedding, scope, limit);
Ok(Vec::new())
}
async fn search(
&self,
query: &str,
scope: Option<&str>,
limit: usize,
) -> Result<Vec<ScoredEntry>>;
}