Archived
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)
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/// engram-migrate — import a Neuron SQLite database into an Engram sled store.
|
||||
///
|
||||
/// Usage:
|
||||
/// engram-migrate --sqlite ~/.neuron/neuron.db --output ~/.engram/neuron
|
||||
///
|
||||
/// The tool reads memory_nodes, knowledge_entries, and graph_edges from the
|
||||
/// Neuron SQLite database and writes them to a new Engram sled store.
|
||||
///
|
||||
/// Embeddings are placeholder random unit vectors (dimension 384 by default).
|
||||
/// Re-run with a real embedding model once the ONNX engine is available.
|
||||
use engram_core::migration::{migrate_from_neuron, MigrationConfig};
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
if args.len() < 5 {
|
||||
eprintln!("Usage: engram-migrate --sqlite <path> --output <path>");
|
||||
eprintln!(" --sqlite Path to the Neuron SQLite database (e.g. ~/.neuron/neuron.db)");
|
||||
eprintln!(" --output Path for the new Engram sled store (e.g. ~/.engram/neuron)");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let mut sqlite_path: Option<PathBuf> = None;
|
||||
let mut output_path: Option<PathBuf> = None;
|
||||
let mut embedding_dim: usize = 384;
|
||||
|
||||
let mut i = 1;
|
||||
while i < args.len() {
|
||||
match args[i].as_str() {
|
||||
"--sqlite" => {
|
||||
i += 1;
|
||||
sqlite_path = Some(PathBuf::from(&args[i]));
|
||||
}
|
||||
"--output" => {
|
||||
i += 1;
|
||||
output_path = Some(PathBuf::from(&args[i]));
|
||||
}
|
||||
"--embedding-dim" => {
|
||||
i += 1;
|
||||
embedding_dim = args[i].parse().unwrap_or(384);
|
||||
}
|
||||
_ => {
|
||||
eprintln!("Unknown argument: {}", args[i]);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let sqlite_path = match sqlite_path {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
eprintln!("Missing --sqlite argument");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let output_path = match output_path {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
eprintln!("Missing --output argument");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if !sqlite_path.exists() {
|
||||
eprintln!("SQLite file not found: {}", sqlite_path.display());
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
println!("Migrating Neuron database...");
|
||||
println!(" Source: {}", sqlite_path.display());
|
||||
println!(" Output: {}", output_path.display());
|
||||
println!(" Embedding dim: {}", embedding_dim);
|
||||
println!();
|
||||
|
||||
let config = MigrationConfig {
|
||||
sqlite_path,
|
||||
engram_path: output_path,
|
||||
embedding_dim,
|
||||
};
|
||||
|
||||
match migrate_from_neuron(&config) {
|
||||
Ok(report) => {
|
||||
println!("Migration complete.");
|
||||
println!(" Memories migrated: {}", report.memories_migrated);
|
||||
println!(" Knowledge migrated: {}", report.knowledge_migrated);
|
||||
println!(" Edges created: {}", report.edges_created);
|
||||
|
||||
if !report.errors.is_empty() {
|
||||
println!();
|
||||
println!("Non-fatal errors ({}):", report.errors.len());
|
||||
for e in &report.errors {
|
||||
println!(" - {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Migration failed: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user