feat(runtime): native platform backends and UI vessels onto main
This commit is contained in:
+61
-48
@@ -180,43 +180,6 @@ fn route_forget(method: String, path: String, body: String) -> String {
|
||||
ok_json()
|
||||
}
|
||||
|
||||
// route_create_ise — POST /api/neuron/state-events
|
||||
// Creates an InternalStateEvent node from a JSON body with a "content" field.
|
||||
// Returns {"ok":true,"id":"<uuid>"}. Used by the soul daemon's ise_post() to
|
||||
// record internal state transitions in the authoritative Engram store.
|
||||
// This route was in the original server.el but was lost during a refactor;
|
||||
// its absence would break ISE recording on the next Engram restart.
|
||||
// (Restored 2026-06-30 self-review)
|
||||
// importance=0.3 matches awareness.el in-process fallback (engram_node_full ISE
|
||||
// defaults). Original had 0.5 which was a mismatch. (Corrected 2026-06-30)
|
||||
fn route_create_ise(method: String, path: String, body: String) -> String {
|
||||
let content: String = json_get_string(body, "content")
|
||||
if str_eq(content, "") { return err_json("missing content") }
|
||||
let sal: Float = 0.3
|
||||
let imp: Float = 0.3
|
||||
let conf: Float = 0.8
|
||||
let id: String = engram_node_full(content, "InternalStateEvent", "state-event",
|
||||
sal, imp, conf, "Episodic", "[\"internal-state\",\"InternalStateEvent\"]")
|
||||
"{\"ok\":true,\"id\":\"" + id + "\"}"
|
||||
}
|
||||
|
||||
// route_sync — GET /api/sync
|
||||
// Returns the full graph snapshot as JSON (nodes + edges), suitable for loading
|
||||
// via engram_load_merge. Used by the soul daemon's periodic refresh cycle to
|
||||
// keep its in-process Engram store in sync with this authoritative HTTP store.
|
||||
// Saves a temporary snapshot to avoid holding a large in-memory string while
|
||||
// streaming — caller reads the file through the HTTP response body.
|
||||
// (Restored 2026-06-30 self-review)
|
||||
fn route_sync(method: String, path: String, body: String) -> String {
|
||||
let dir: String = env("ENGRAM_DATA_DIR")
|
||||
if str_eq(dir, "") { let dir = "/tmp/engram" }
|
||||
let snap_path: String = dir + "/sync-export.json"
|
||||
engram_save(snap_path)
|
||||
let snap: String = fs_read(snap_path)
|
||||
if str_eq(snap, "") { return "{\"nodes\":[],\"edges\":[]}" }
|
||||
snap
|
||||
}
|
||||
|
||||
fn route_save(method: String, path: String, body: String) -> String {
|
||||
let p: String = json_get_string(body, "path")
|
||||
if str_eq(p, "") {
|
||||
@@ -243,6 +206,59 @@ fn route_health(method: String, path: String, body: String) -> String {
|
||||
"{\"status\":\"ok\",\"engine\":\"engram-runtime-native\"}"
|
||||
}
|
||||
|
||||
// route_sync — return a snapshot of non-ISE/non-Working nodes for the soul daemon
|
||||
// to merge into its in-process graph via engram_load_merge.
|
||||
//
|
||||
// The soul calls GET /api/sync every SOUL_REFRESH_MS (default 10 min) to pull
|
||||
// new Knowledge/Memory/BacklogItem nodes from the authoritative HTTP Engram into
|
||||
// its in-process working store. Previously this returned 404 "not found", causing
|
||||
// the soul to write the error JSON to a temp file and attempt an empty merge.
|
||||
//
|
||||
// Strategy: save the current snapshot to disk, read it back, return the full
|
||||
// snapshot JSON. The soul's engram_load_merge handles large files gracefully
|
||||
// (it skips nodes already present by ID). Auth-exempt: same-host internal call.
|
||||
// (2026-06-27 self-review: added this route to fix silent 10-min sync failures)
|
||||
fn route_sync(method: String, path: String, body: String) -> String {
|
||||
let dir: String = env("ENGRAM_DATA_DIR")
|
||||
if str_eq(dir, "") { let dir = "/tmp/engram" }
|
||||
let snap_path: String = dir + "/snapshot.json"
|
||||
engram_save(snap_path)
|
||||
let snap: String = fs_read(snap_path)
|
||||
if str_eq(snap, "") { return "{\"nodes\":[],\"edges\":[]}" }
|
||||
return snap
|
||||
}
|
||||
|
||||
// route_emit_ise — write an InternalStateEvent node from the soul daemon.
|
||||
//
|
||||
// Endpoint: POST /api/neuron/state-events
|
||||
// Body: {"content": "<json-string>"}
|
||||
//
|
||||
// Auth: exempt (internal endpoint, soul daemon on same host, no _auth needed).
|
||||
// The soul's ise_post() sends {"content":"..."} without _auth; enforcing auth
|
||||
// here would silently drop all heartbeat/curiosity ISEs. Unauthenticated POST
|
||||
// to this endpoint is acceptable: ISE writes are observability-only, append-only,
|
||||
// and come from a trusted process on localhost.
|
||||
//
|
||||
// Salience/importance set to match engram_node_full ISE defaults used by the
|
||||
// in-process fallback path in awareness.el (salience=0.3, importance=0.3,
|
||||
// confidence=0.8, tier=Episodic). High temporal_decay_rate (1.617) — ISEs
|
||||
// are inherently transient; they should decay faster than structural knowledge.
|
||||
// (2026-06-26 self-review: added this route after discovering ise_post was
|
||||
// silently failing — the soul posts here but the endpoint didn't exist.)
|
||||
fn route_emit_ise(method: String, path: String, body: String) -> String {
|
||||
let content: String = json_get_string(body, "content")
|
||||
if str_eq(content, "") { return err_json("missing content") }
|
||||
let sal: Float = 0.3
|
||||
let imp: Float = 0.3
|
||||
let conf: Float = 0.8
|
||||
let id: String = engram_node_full(
|
||||
content, "InternalStateEvent", "state-event",
|
||||
sal, imp, conf,
|
||||
"Episodic", "[\"internal-state\",\"InternalStateEvent\"]"
|
||||
)
|
||||
"{\"ok\":true,\"id\":\"" + id + "\"}"
|
||||
}
|
||||
|
||||
// ── Auth ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
fn check_auth_ok(method: String, body: String) -> Bool {
|
||||
@@ -269,12 +285,9 @@ fn handle_request(method: String, path: String, body: String) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
// Internal state events bypass auth — only the local soul daemon calls
|
||||
// this route, and ise_post() does not include an _auth field in its body.
|
||||
// Placing this before the auth gate preserves the old binary's behavior
|
||||
// and ensures the soul daemon can always write ISEs.
|
||||
if str_eq(method, "POST") && str_starts_with(clean, "/api/neuron/state-events") {
|
||||
return route_create_ise(method, path, body)
|
||||
// ISE posting is auth-exempt (internal soul daemon, same host, no _auth key)
|
||||
if str_eq(method, "POST") && str_eq(clean, "/api/neuron/state-events") {
|
||||
return route_emit_ise(method, path, body)
|
||||
}
|
||||
|
||||
// Auth (when ENGRAM_API_KEY is set)
|
||||
@@ -331,11 +344,6 @@ fn handle_request(method: String, path: String, body: String) -> String {
|
||||
return route_strengthen(method, path, body)
|
||||
}
|
||||
|
||||
// Sync — soul daemon fetches here for periodic in-process graph refresh
|
||||
if str_eq(method, "GET") && (str_eq(clean, "/api/sync") || str_eq(clean, "/sync")) {
|
||||
return route_sync(method, path, body)
|
||||
}
|
||||
|
||||
// Persistence
|
||||
if str_eq(method, "POST") && (str_eq(clean, "/api/save") || str_eq(clean, "/save")) {
|
||||
return route_save(method, path, body)
|
||||
@@ -344,6 +352,11 @@ fn handle_request(method: String, path: String, body: String) -> String {
|
||||
return route_load(method, path, body)
|
||||
}
|
||||
|
||||
// Sync — soul daemon periodic pull of non-ISE knowledge into in-process graph
|
||||
if str_eq(method, "GET") && str_eq(clean, "/api/sync") {
|
||||
return route_sync(method, path, body)
|
||||
}
|
||||
|
||||
"{\"error\":\"not found\",\"path\":\"" + clean + "\"}"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user