#![cfg(feature = "semantic")]
use std::path::PathBuf;
use std::sync::Arc;
use context_forge::{kind, Config, ContextForge, Embedder, SaveOptions};
struct ConstantEmbedder {
dims: usize,
}
impl Embedder for ConstantEmbedder {
fn embed(&self, text: &str) -> context_forge::Result<Vec<f32>> {
let seed = (text.len() % 13) as f32 / 13.0;
Ok(vec![seed; self.dims])
}
}
fn in_memory_config() -> Config {
let mut cfg = Config::default();
cfg.db_path = PathBuf::from(":memory:");
cfg
}
#[tokio::test]
async fn builder_accepts_injected_custom_embedder() {
let embedder: Arc<dyn Embedder> = Arc::new(ConstantEmbedder { dims: 384 });
let cf = ContextForge::builder(in_memory_config())
.with_embedder(embedder)
.build()
.await
.expect("build with injected embedder");
let opts = SaveOptions::default();
cf.save("the deploy used a canary rollout", kind::SNAPSHOT, &opts)
.await
.expect("save with injected embedder");
cf.save("lunch options near the office", kind::SNAPSHOT, &opts)
.await
.expect("save second entry");
let hits = cf
.query("deploy rollout", None, 4096)
.await
.expect("query with injected embedder");
assert!(
hits.iter().any(|e| e.content.contains("canary")),
"the relevant entry should be retrieved"
);
}
#[tokio::test]
async fn injected_embedder_shared_across_builds() {
let shared: Arc<dyn Embedder> = Arc::new(ConstantEmbedder { dims: 384 });
for _ in 0..3 {
let cf = ContextForge::builder(in_memory_config())
.with_embedder(Arc::clone(&shared))
.build()
.await
.expect("build sharing one embedder");
cf.save(
"shared embedder entry",
kind::SNAPSHOT,
&SaveOptions::default(),
)
.await
.expect("save");
}
}