soul loop-2: session events, conversation persistence, richer health + inbox

- soul.el: emit_session_start_event() logs structured InternalStateEvent on every boot; pre-serve snapshot saves boot-time graph mutations before any requests arrive
- routes.el: /health now returns boot count, node/edge counts, pulse; /api/sessions endpoint surfaces session-start history
- awareness.el: perceive() tries soul-inbox-pending then soul-inbox fallback, catches both tagging conventions
- chat.el: conv_history_persist/load provide cross-restart conversation continuity via engram
This commit is contained in:
2026-05-06 22:04:06 -05:00
parent 4fc0294a49
commit f2599919be
4 changed files with 111 additions and 3 deletions
+31 -1
View File
@@ -123,6 +123,33 @@ fn clean_llm_response(s: String) -> String {
return s3
}
// conv_history_persist save conversation history to engram for cross-restart continuity.
// Stores as a Conversation node. Overwrites by using consistent label "conv:history".
fn conv_history_persist(hist: String) -> Void {
if str_eq(hist, "") { return "" }
if str_eq(hist, "[]") { return "" }
let ts: Int = time_now()
let tags: String = "[\"conv-history\",\"persistent\"]"
let discard: String = engram_node_full(
hist, "Conversation", "conv:history",
el_from_float(0.7), el_from_float(0.8), el_from_float(0.9),
"Episodic", tags
)
}
// conv_history_load restore conversation history from engram on first access.
// Returns the most recent "conv:history" node content, or "" if none found.
fn conv_history_load() -> String {
let results: String = engram_search_json("conv:history", 3)
if str_eq(results, "") { return "" }
if str_eq(results, "[]") { return "" }
let node: String = json_array_get(results, 0)
let content: String = json_get(node, "content")
// Validate it looks like a JSON array
if !str_starts_with(content, "[") { return "" }
return content
}
fn handle_chat(body: String) -> String {
let message: String = json_get(body, "message")
if str_eq(message, "") {
@@ -132,7 +159,9 @@ fn handle_chat(body: String) -> String {
let ctx: String = engram_compile(message)
let system: String = build_system_prompt(ctx)
let stored_hist: String = state_get("conv_history")
// Load from state; if empty, try to recover from engram (cross-restart continuity)
let state_hist: String = state_get("conv_history")
let stored_hist: String = if str_eq(state_hist, "") { conv_history_load() } else { state_hist }
let hist_len: Int = if str_eq(stored_hist, "") { 0 } else { json_array_len(stored_hist) }
let full_system: String = if hist_len > 0 {
system + "\n\n[RECENT CONVERSATION — last " + int_to_str(hist_len) + " turns]\n" + stored_hist
@@ -163,6 +192,7 @@ fn handle_chat(body: String) -> String {
updated_hist2
}
state_set("conv_history", final_hist)
conv_history_persist(final_hist)
let activation_nodes: String = engram_activate_json(message, 2)
let act_ok: Bool = !str_eq(activation_nodes, "") && !str_eq(activation_nodes, "[]")