feat(awareness): route ISE writes to HTTP Engram, configurable tick and heartbeat interval, http_serve_async for concurrent awareness loop
This commit is contained in:
@@ -106,27 +106,93 @@ fn load_identity_context() -> Void {
|
||||
let values_content: String = if values_ok { json_get(node_values, "content") } else { "" }
|
||||
let mem_content: String = if mem_ok { json_get(node_mem_phil, "content") } else { "" }
|
||||
|
||||
// Condense each: take first 600 chars
|
||||
let intel_short: String = if str_len(intel_content) > 600 { str_slice(intel_content, 0, 600) } else { intel_content }
|
||||
let values_short: String = if str_len(values_content) > 600 { str_slice(values_content, 0, 600) } else { values_content }
|
||||
let mem_short: String = if str_len(mem_content) > 600 { str_slice(mem_content, 0, 600) } else { mem_content }
|
||||
// Condense each: take first 2000 chars
|
||||
let intel_short: String = if str_len(intel_content) > 2000 { str_slice(intel_content, 0, 2000) } else { intel_content }
|
||||
let values_short: String = if str_len(values_content) > 2000 { str_slice(values_content, 0, 2000) } else { values_content }
|
||||
let mem_short: String = if str_len(mem_content) > 2000 { str_slice(mem_content, 0, 2000) } else { mem_content }
|
||||
|
||||
let parts_count: Int = 0
|
||||
let parts_count = if intel_ok { parts_count + 1 } else { parts_count }
|
||||
let parts_count = if values_ok { parts_count + 1 } else { parts_count }
|
||||
let parts_count = if mem_ok { parts_count + 1 } else { parts_count }
|
||||
|
||||
if parts_count == 0 {
|
||||
return ""
|
||||
// Build and store graph-derived identity context if any nodes were found.
|
||||
// genesis soul always has these nodes; cultivated souls may not on first boot.
|
||||
if parts_count > 0 {
|
||||
let ctx: String = ""
|
||||
let ctx = if intel_ok { ctx + "[INTELLECTUAL-DNA]\n" + intel_short + "\n\n" } else { ctx }
|
||||
let ctx = if values_ok { ctx + "[VALUES]\n" + values_short + "\n\n" } else { ctx }
|
||||
let ctx = if mem_ok { ctx + "[MEMORY-PHILOSOPHY]\n" + mem_short } else { ctx }
|
||||
state_set("soul_identity_context", ctx)
|
||||
println("[soul] identity context loaded (" + int_to_str(str_len(ctx)) + " chars, " + int_to_str(parts_count) + " nodes)")
|
||||
}
|
||||
|
||||
let ctx: String = ""
|
||||
let ctx = if intel_ok { ctx + "[INTELLECTUAL-DNA]\n" + intel_short + "\n\n" } else { ctx }
|
||||
let ctx = if values_ok { ctx + "[VALUES]\n" + values_short + "\n\n" } else { ctx }
|
||||
let ctx = if mem_ok { ctx + "[MEMORY-PHILOSOPHY]\n" + mem_short } else { ctx }
|
||||
// Scan for a Persona node — the explicit identity declaration seeded into cultivated souls.
|
||||
// Stored at seeding time with label "soul:persona" and node_type "Persona".
|
||||
// genesis derives identity from the graph directly; cultivated souls have this node seeded.
|
||||
let persona_results: String = engram_search_json("soul:persona", 3)
|
||||
let persona_ok: Bool = !str_eq(persona_results, "") && !str_eq(persona_results, "[]")
|
||||
if persona_ok {
|
||||
let p_node: String = json_array_get(persona_results, 0)
|
||||
let p_type: String = json_get(p_node, "node_type")
|
||||
let p_content: String = json_get(p_node, "content")
|
||||
if str_eq(p_type, "Persona") && !str_eq(p_content, "") {
|
||||
state_set("soul_persona", p_content)
|
||||
println("[soul] persona node loaded (" + int_to_str(str_len(p_content)) + " chars)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state_set("soul_identity_context", ctx)
|
||||
println("[soul] identity context loaded (" + int_to_str(str_len(ctx)) + " chars, " + int_to_str(parts_count) + " nodes)")
|
||||
// seed_persona_from_env — one-time migration: SOUL_IDENTITY env var → Persona graph node.
|
||||
// If SOUL_IDENTITY is set and no Persona node exists in engram yet, create one.
|
||||
// Identity is then read from the graph by build_identity_from_graph(), not the env var.
|
||||
// This runs on every boot; it's idempotent (no-op if soul_persona is already loaded).
|
||||
// For genesis: the Persona node persists via the regular engram_save() at boot.
|
||||
// For historical souls (HTTP Engram mode): attempts HTTP write-back. If that fails,
|
||||
// the node lives in-memory for the session (SOUL_IDENTITY stays in plist until
|
||||
// HTTP Engram write is confirmed working).
|
||||
fn seed_persona_from_env() -> Void {
|
||||
let identity_raw: String = env("SOUL_IDENTITY")
|
||||
if str_eq(identity_raw, "") {
|
||||
return ""
|
||||
}
|
||||
// Already loaded a Persona node from engram — don't re-seed
|
||||
let existing: String = state_get("soul_persona")
|
||||
if !str_eq(existing, "") {
|
||||
println("[soul] persona already loaded — skipping env seed")
|
||||
return ""
|
||||
}
|
||||
// Create the Persona node in the in-process engram
|
||||
let tags: String = "[\"persona\",\"identity\",\"soul:persona\"]"
|
||||
let node_id: String = engram_node_full(
|
||||
identity_raw, "Persona", "soul:persona",
|
||||
el_from_float(0.95), el_from_float(0.95), el_from_float(1.0),
|
||||
"Semantic", tags
|
||||
)
|
||||
if str_eq(node_id, "") {
|
||||
println("[soul] persona seed failed: engram_node_full returned empty")
|
||||
return ""
|
||||
}
|
||||
state_set("soul_persona", identity_raw)
|
||||
println("[soul] persona seeded from SOUL_IDENTITY (" + int_to_str(str_len(identity_raw)) + " chars) -> " + node_id)
|
||||
|
||||
// Attempt HTTP write-back to the HTTP Engram server for historical souls.
|
||||
// Engram auth: "_auth" field in the JSON body (not an HTTP header).
|
||||
let engram_url: String = env("ENGRAM_URL")
|
||||
let engram_key: String = env("ENGRAM_API_KEY")
|
||||
if !str_eq(engram_url, "") && !str_eq(engram_key, "") {
|
||||
let safe_content: String = json_safe(identity_raw)
|
||||
let safe_key: String = json_safe(engram_key)
|
||||
let body: String = "{\"content\":\"" + safe_content + "\",\"node_type\":\"Persona\",\"label\":\"soul:persona\",\"salience\":0.95,\"importance\":0.95,\"tier\":\"Semantic\",\"tags\":\"[\\\"persona\\\",\\\"identity\\\",\\\"soul:persona\\\"]\",\"_auth\":\"" + safe_key + "\"}"
|
||||
let h: Map = {}
|
||||
map_set(h, "Content-Type", "application/json")
|
||||
let resp: String = http_post_with_headers(engram_url + "/api/nodes", body, h)
|
||||
if str_contains(resp, "\"error\"") {
|
||||
println("[soul] persona HTTP write-back failed (in-memory only this session): " + resp)
|
||||
} else {
|
||||
println("[soul] persona persisted to HTTP engram at " + engram_url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emit_session_start_event — log a structured session-start InternalStateEvent.
|
||||
@@ -206,16 +272,13 @@ if using_http_engram {
|
||||
}
|
||||
|
||||
load_identity_context()
|
||||
seed_persona_from_env()
|
||||
let boot_num: Int = mem_boot_count_inc()
|
||||
state_set("soul_boot_count", int_to_str(boot_num))
|
||||
println("[soul] boot #" + int_to_str(boot_num))
|
||||
emit_session_start_event()
|
||||
|
||||
let identity_raw: String = env("SOUL_IDENTITY")
|
||||
let soul_identity: String = if str_eq(identity_raw, "") { "You are " + soul_cgi_id + ", a CGI." } else { identity_raw }
|
||||
|
||||
state_set("soul_cgi_id", soul_cgi_id)
|
||||
state_set("soul_identity", soul_identity)
|
||||
state_set("soul_axon_base", axon_base)
|
||||
state_set("soul_token", env("NEURON_TOKEN"))
|
||||
state_set("soul_studio_dir", studio_dir)
|
||||
@@ -251,4 +314,6 @@ if is_genesis {
|
||||
}
|
||||
|
||||
println("[soul] serving on port " + int_to_str(port))
|
||||
http_serve(port, "handle_request")
|
||||
http_serve_async(port, "handle_request")
|
||||
println("[soul] awareness loop starting")
|
||||
awareness_run()
|
||||
|
||||
Reference in New Issue
Block a user