init: Engram v0.1 — native memory substrate for accumulating intelligence
Memory is not stored and retrieved — it is activated and propagated. Implements the spreading activation model with salience decay, typed edges, four memory tiers, and flat cosine vector search over a sled embedded store.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "engram-ffi"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "C FFI bindings for engram-core"
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
engram-core = { path = "../engram-core" }
|
||||
uuid = { version = "1", features = ["v4", "serde"] }
|
||||
@@ -0,0 +1,118 @@
|
||||
/// C FFI stubs for engram-core.
|
||||
///
|
||||
/// These are minimal stubs for v0.1 — enough to link from Kotlin, TypeScript (via WASM
|
||||
/// or Node native addon), and Go. Full binding generation will use cbindgen in v0.2.
|
||||
///
|
||||
/// All pointers passed across the FFI boundary must remain valid for the duration of
|
||||
/// the call. Strings are null-terminated UTF-8. The caller owns all returned heap memory
|
||||
/// and must free it via the corresponding `engram_free_*` function.
|
||||
///
|
||||
/// # Safety
|
||||
/// All functions in this module are `unsafe` because they accept raw pointers.
|
||||
/// Callers are responsible for ensuring pointer validity and correct lifetimes.
|
||||
use engram_core::EngramDb;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::c_char;
|
||||
use std::path::Path;
|
||||
|
||||
/// Opaque handle to an open EngramDb instance.
|
||||
pub struct EngramHandle {
|
||||
db: EngramDb,
|
||||
}
|
||||
|
||||
/// Open an engram database at the given path.
|
||||
///
|
||||
/// Returns a heap-allocated handle on success, or null on failure.
|
||||
/// The caller must eventually call `engram_close` to free the handle.
|
||||
///
|
||||
/// # Safety
|
||||
/// `path` must be a valid, null-terminated UTF-8 string.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn engram_open(path: *const c_char) -> *mut EngramHandle {
|
||||
if path.is_null() {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
let path_str = match CStr::from_ptr(path).to_str() {
|
||||
Ok(s) => s,
|
||||
Err(_) => return std::ptr::null_mut(),
|
||||
};
|
||||
match EngramDb::open(Path::new(path_str)) {
|
||||
Ok(db) => Box::into_raw(Box::new(EngramHandle { db })),
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Close and free an engram database handle.
|
||||
///
|
||||
/// After this call, `handle` is invalid and must not be used.
|
||||
///
|
||||
/// # Safety
|
||||
/// `handle` must have been returned by `engram_open` and not yet freed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn engram_close(handle: *mut EngramHandle) {
|
||||
if !handle.is_null() {
|
||||
drop(Box::from_raw(handle));
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the number of nodes in the database.
|
||||
///
|
||||
/// Returns -1 on error.
|
||||
///
|
||||
/// # Safety
|
||||
/// `handle` must be a valid, non-null pointer from `engram_open`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn engram_node_count(handle: *const EngramHandle) -> i64 {
|
||||
if handle.is_null() {
|
||||
return -1;
|
||||
}
|
||||
match (*handle).db.node_count() {
|
||||
Ok(n) => n as i64,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the number of edges in the database.
|
||||
///
|
||||
/// Returns -1 on error.
|
||||
///
|
||||
/// # Safety
|
||||
/// `handle` must be a valid, non-null pointer from `engram_open`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn engram_edge_count(handle: *const EngramHandle) -> i64 {
|
||||
if handle.is_null() {
|
||||
return -1;
|
||||
}
|
||||
match (*handle).db.edge_count() {
|
||||
Ok(n) => n as i64,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply salience decay across all nodes.
|
||||
///
|
||||
/// Returns the number of nodes updated, or -1 on error.
|
||||
///
|
||||
/// # Safety
|
||||
/// `handle` must be a valid, non-null pointer from `engram_open`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn engram_decay(handle: *mut EngramHandle, factor: f32) -> i64 {
|
||||
if handle.is_null() {
|
||||
return -1;
|
||||
}
|
||||
match (*handle).db.decay(factor) {
|
||||
Ok(n) => n as i64,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Free a C string returned by engram FFI functions.
|
||||
///
|
||||
/// # Safety
|
||||
/// `s` must have been allocated by an engram FFI function, not by the caller.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn engram_free_string(s: *mut c_char) {
|
||||
if !s.is_null() {
|
||||
drop(CString::from_raw(s));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user