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:
@@ -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, "[]")
|
||||
|
||||
Reference in New Issue
Block a user