This repository has been archived on 2026-05-05. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
engram-retired/crates/engram-core/src/mem_storage.rs
T
Will Anderson f33d789471 feat: HNSW index, consolidation engine, Kotlin/TS/Go bindings, SQLite migration connector
- vector.rs: replace flat O(n) scan with instant-distance HNSW for stores
  >= 100 nodes; flat scan retained as fallback for small graphs; dirty-flag
  persistence in sled triggers index rebuild only when nodes are added

- consolidation.rs: Episodic → Semantic promotion based on activation_count
  and salience_floor thresholds; global decay pass after each cycle;
  ConsolidationConfig + ConsolidationReport types; 8 tests

- migration.rs: reads Neuron SQLite (memory_nodes, knowledge_entries,
  graph_edges) and writes to Engram sled; placeholder unit-vector embeddings
  with TODO for ONNX; 5 tests including full in-memory DB roundtrip

- crates/engram-migrate: CLI binary (engram-migrate --sqlite / --output)

- crates/engram-jni: JNI cdylib exposing open/close/put_node/get_node/
  activate/search_embedding/touch/decay/node_count/edge_count via
  Java_ai_neuron_engram_EngramDb_* entry points; 6 tests

- bindings/kotlin: EngramDb.kt (AutoCloseable JNI wrapper), EngramNode,
  EngramEdge, ActivatedNode, EngramTypes; build.gradle.kts; settings.gradle.kts

- bindings/typescript: engram-wasm crate (wasm-bindgen, serde-wasm-bindgen);
  WasmEngramDb with in-memory backend (sled not available in WASM);
  TypeScript wrapper (index.ts, types.ts, package.json, tsconfig.json)

- bindings/go: engram.go (CGo wrapper), engram.h (C header), engram_test.go
  (4 tests covering open/close/put_node/get_node/node_count/decay); go.mod

- engram-core: wasm feature gate for in-memory backend; mem_storage.rs;
  activation.activate_mem for WASM path; Node::with_id helper;
  salience.rs doctest fixed (text block)

- examples/basic.rs: consolidation section added
- examples/migrate.rs: migration API demonstration

Build: cargo build --workspace -- zero warnings, zero errors
Tests: 38 pass (25 engram-core + 7 engram-ffi + 6 engram-jni)
2026-04-27 16:00:47 -05:00

100 lines
3.3 KiB
Rust

/// In-memory storage backend for environments without a filesystem.
///
/// Used when the `wasm` feature is enabled (e.g. browser via wasm-bindgen).
/// Implements the same logical interface as the sled-backed `storage` module
/// so that `EngramDb` can work identically in both environments.
///
/// All state lives in a `MemStore` that is held by `EngramDb` under a `RwLock`
/// so concurrent reads are fine and writes are serialised.
use crate::error::{EngramError, EngramResult};
use crate::types::{Edge, Node};
use std::collections::HashMap;
use uuid::Uuid;
#[derive(Default)]
pub struct MemStore {
pub nodes: HashMap<Uuid, Node>,
/// from_id → list of edges
pub edges_from: HashMap<Uuid, Vec<Edge>>,
/// to_id → list of edges
pub edges_to: HashMap<Uuid, Vec<Edge>>,
}
impl MemStore {
pub fn new() -> Self {
Self::default()
}
// ── Node operations ───────────────────────────────────────────────────────
pub fn write_node(&mut self, node: &Node) -> EngramResult<()> {
self.nodes.insert(node.id, node.clone());
Ok(())
}
pub fn read_node(&self, id: Uuid) -> EngramResult<Option<Node>> {
Ok(self.nodes.get(&id).cloned())
}
pub fn scan_nodes(&self) -> EngramResult<Vec<Node>> {
Ok(self.nodes.values().cloned().collect())
}
pub fn node_count(&self) -> usize {
self.nodes.len()
}
// ── Edge operations ───────────────────────────────────────────────────────
pub fn write_edge(&mut self, edge: &Edge) -> EngramResult<()> {
self.edges_from
.entry(edge.from_id)
.or_default()
.push(edge.clone());
self.edges_to
.entry(edge.to_id)
.or_default()
.push(edge.clone());
Ok(())
}
pub fn read_edges_from(&self, from_id: Uuid) -> EngramResult<Vec<Edge>> {
Ok(self
.edges_from
.get(&from_id)
.cloned()
.unwrap_or_default())
}
pub fn read_edges_to(&self, to_id: Uuid) -> EngramResult<Vec<Edge>> {
Ok(self
.edges_to
.get(&to_id)
.cloned()
.unwrap_or_default())
}
pub fn edge_count(&self) -> usize {
self.edges_from.values().map(|v| v.len()).sum()
}
// ── Vector operations ─────────────────────────────────────────────────────
pub fn scan_vectors(&self) -> EngramResult<Vec<(Uuid, Vec<f32>)>> {
Ok(self
.nodes
.iter()
.map(|(id, n)| (*id, n.embedding.clone()))
.collect())
}
// ── Salience ──────────────────────────────────────────────────────────────
pub fn write_salience(&mut self, id: Uuid, salience: f32) -> EngramResult<()> {
if let Some(node) = self.nodes.get_mut(&id) {
node.salience = salience;
}
Ok(())
}
}