use noos::{
hybrid_recall, ActivationSource, AtomSource, AtomType, InMemoryStore, MemoryAtom,
MemoryStore, RecallOptions, Synapse, SynapseType,
};
use std::collections::HashMap;
fn make_atom(id: &str, content: &str, topics: Vec<String>) -> MemoryAtom {
MemoryAtom {
id: id.into(),
content: content.into(),
embedding: None,
atom_type: AtomType::Episodic,
source: AtomSource::default(),
importance: 0.7,
access_count: 0,
last_accessed_at: 0.0,
created_at: 0.0,
topics,
domain: None,
consolidated_from: None,
is_consolidated: false,
parent_id: None,
depth: None,
label: None,
child_ids: None,
superseded: false,
suppressed: false,
dormant: false,
tags: vec![],
encoding_context: None,
retrieval_reward: None,
reconsolidation_count: None,
arousal: None,
valence: None,
epoch: None,
crystallized: false,
}
}
#[test]
fn hybrid_recall_finds_topic_match() {
let atoms = vec![
make_atom("a1", "Rust async basics", vec!["rust".into(), "async".into()]),
make_atom("a2", "Python type hints", vec!["python".into(), "types".into()]),
make_atom("a3", "Rust ownership rules", vec!["rust".into(), "ownership".into()]),
];
let synapses = HashMap::new();
let results = hybrid_recall(
&atoms,
None, "How does rust ownership work?",
&synapses,
&RecallOptions::default(),
);
assert!(
!results.is_empty(),
"Topic-matching query should retrieve at least one atom"
);
assert!(
results.iter().any(|a| a.atom.id == "a3"),
"Ownership query should retrieve the ownership atom"
);
}
#[test]
fn activation_sources_distinguish_retrieval_paths() {
let v = ActivationSource::Vector;
let g = ActivationSource::Graph;
let c = ActivationSource::Convergent;
assert_ne!(v, g);
assert_ne!(g, c);
}
#[tokio::test]
async fn in_memory_store_round_trip() {
let mut store = InMemoryStore::new();
let atom = make_atom("a1", "Test content", vec!["test".into()]);
store.store_atom(atom.clone()).await.unwrap();
let retrieved = store.get_atom("a1").await.unwrap();
assert!(retrieved.is_some());
assert_eq!(retrieved.unwrap().content, "Test content");
let atom2 = make_atom("a2", "Related", vec!["test".into()]);
store.store_atom(atom2).await.unwrap();
let syn = Synapse {
id: "s1".into(),
source: "a1".into(),
target: "a2".into(),
synapse_type: SynapseType::RelatesTo,
strength: 0.6,
created_at: 0.0,
last_accessed_at: None,
access_count: None,
};
store.store_synapse(syn).await.unwrap();
let syns = store.get_synapses_for("a1").await.unwrap();
assert_eq!(syns.len(), 1);
assert_eq!(syns[0].target, "a2");
assert_eq!(store.atom_count(), 2);
}
#[test]
fn recall_options_default_is_usable() {
let mut opts = RecallOptions::default();
assert_eq!(opts.top_k, 10);
assert_eq!(opts.graph_depth, 2);
opts.top_k = 5;
assert_eq!(opts.top_k, 5);
}