00f15b094b
- sessions.el: new sessions module with session management and approval gate
- routes.el: wire /api/sessions routes (list, get, create, approve, tool_result)
- chat.el: thread-aware activation — short messages anchor to last reply
before engram compilation so follow-ups stay on-topic
- chat.el: agentic path tracks per-session history (session_hist_{id})
instead of shared conv_history, seeding each turn with prior context
- chat.el: add call_neuron_mcp, dispatch_tool, is_builtin_tool, next_bridge_id
agentic_loop, bridge_save, agentic_resume, handle_tool_result
- dist/soul: rebuild with all of the above
275 lines
16 KiB
C
Generated
275 lines
16 KiB
C
Generated
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include "el_runtime.h"
|
|
|
|
el_val_t tier_working(void);
|
|
el_val_t tier_episodic(void);
|
|
el_val_t tier_canonical(void);
|
|
el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags);
|
|
el_val_t mem_remember(el_val_t content, el_val_t tags);
|
|
el_val_t mem_recall(el_val_t query, el_val_t depth);
|
|
el_val_t mem_search(el_val_t query, el_val_t limit);
|
|
el_val_t mem_strengthen(el_val_t node_id);
|
|
el_val_t mem_forget(el_val_t node_id);
|
|
el_val_t mem_consolidate(void);
|
|
el_val_t mem_save(el_val_t path);
|
|
el_val_t mem_load(el_val_t path);
|
|
el_val_t mem_boot_count_get(void);
|
|
el_val_t mem_boot_count_inc(void);
|
|
el_val_t mem_emit_state_event(el_val_t trigger, el_val_t kind, el_val_t content);
|
|
el_val_t soft_bell_threshold(void);
|
|
el_val_t hard_bell_threshold(void);
|
|
el_val_t safety_score_crisis(el_val_t input);
|
|
el_val_t safety_score_harm(el_val_t input);
|
|
el_val_t safety_score_danger(el_val_t input);
|
|
el_val_t safety_score_distress_history(el_val_t history);
|
|
el_val_t safety_threat_score(el_val_t input, el_val_t history);
|
|
el_val_t safety_screen(el_val_t input, el_val_t history);
|
|
el_val_t safety_validate(el_val_t output, el_val_t action);
|
|
el_val_t safety_log_bell(el_val_t level, el_val_t reason, el_val_t input_summary);
|
|
|
|
el_val_t tier_working(void) {
|
|
return EL_STR("Working");
|
|
return 0;
|
|
}
|
|
|
|
el_val_t tier_episodic(void) {
|
|
return EL_STR("Episodic");
|
|
return 0;
|
|
}
|
|
|
|
el_val_t tier_canonical(void) {
|
|
return EL_STR("Canonical");
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags) {
|
|
return engram_node_full(content, EL_STR("Memory"), label, el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.8)), EL_STR("Working"), tags);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_remember(el_val_t content, el_val_t tags) {
|
|
return mem_store(content, EL_STR("soul-memory"), tags);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_recall(el_val_t query, el_val_t depth) {
|
|
return engram_activate_json(query, depth);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_search(el_val_t query, el_val_t limit) {
|
|
return engram_search_json(query, limit);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_strengthen(el_val_t node_id) {
|
|
engram_strengthen(node_id);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_forget(el_val_t node_id) {
|
|
engram_forget(node_id);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_consolidate(void) {
|
|
el_val_t scanned = engram_node_count();
|
|
el_val_t dummy = engram_scan_nodes_json(100, 0);
|
|
el_val_t total_nodes = engram_node_count();
|
|
el_val_t total_edges = engram_edge_count();
|
|
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"scanned\":"), int_to_str(scanned)), EL_STR(",\"total_nodes\":")), int_to_str(total_nodes)), EL_STR(",\"total_edges\":")), int_to_str(total_edges)), EL_STR("}"));
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_save(el_val_t path) {
|
|
engram_save(path);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_load(el_val_t path) {
|
|
engram_load(path);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_boot_count_get(void) {
|
|
el_val_t results = engram_search_json(EL_STR("soul:boot_count"), 3);
|
|
if (str_eq(results, EL_STR(""))) {
|
|
return 0;
|
|
}
|
|
if (str_eq(results, EL_STR("[]"))) {
|
|
return 0;
|
|
}
|
|
el_val_t node = json_array_get(results, 0);
|
|
el_val_t content = json_get(node, EL_STR("content"));
|
|
el_val_t prefix = EL_STR("soul:boot_count:");
|
|
if (!str_starts_with(content, prefix)) {
|
|
return 0;
|
|
}
|
|
el_val_t num_str = str_slice(content, str_len(prefix), str_len(content));
|
|
return str_to_int(num_str);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_boot_count_inc(void) {
|
|
el_val_t current = mem_boot_count_get();
|
|
el_val_t next = (current + 1);
|
|
el_val_t content = el_str_concat(EL_STR("soul:boot_count:"), int_to_str(next));
|
|
el_val_t tags = EL_STR("[\"soul-meta\",\"boot-counter\"]");
|
|
el_val_t discard = engram_node_full(content, EL_STR("Memory"), EL_STR("soul:boot_count"), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(1.0)), EL_STR("Canonical"), tags);
|
|
return next;
|
|
return 0;
|
|
}
|
|
|
|
el_val_t mem_emit_state_event(el_val_t trigger, el_val_t kind, el_val_t content) {
|
|
el_val_t boot = mem_boot_count_get();
|
|
el_val_t ts = time_now();
|
|
el_val_t safe_trigger = str_replace(trigger, EL_STR("\""), EL_STR("'"));
|
|
el_val_t safe_content = str_replace(content, EL_STR("\""), EL_STR("'"));
|
|
el_val_t payload = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"trigger\":\""), safe_trigger), EL_STR("\"")), EL_STR(",\"kind\":\"")), kind), EL_STR("\"")), EL_STR(",\"content\":\"")), safe_content), EL_STR("\"")), EL_STR(",\"boot\":")), int_to_str(boot)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
|
|
el_val_t tags = EL_STR("[\"internal-state\",\"pre-reasoning\",\"InternalStateEvent\"]");
|
|
return engram_node_full(payload, EL_STR("InternalStateEvent"), el_str_concat(EL_STR("state-event:"), kind), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.8)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t soft_bell_threshold(void) {
|
|
return 35;
|
|
return 0;
|
|
}
|
|
|
|
el_val_t hard_bell_threshold(void) {
|
|
return 70;
|
|
return 0;
|
|
}
|
|
|
|
el_val_t safety_score_crisis(el_val_t input) {
|
|
el_val_t s1 = ({ el_val_t _if_result_1 = 0; if (str_contains(input, EL_STR("kill myself"))) { _if_result_1 = (80); } else { _if_result_1 = (0); } _if_result_1; });
|
|
el_val_t s2 = ({ el_val_t _if_result_2 = 0; if (str_contains(input, EL_STR("want to die"))) { _if_result_2 = (75); } else { _if_result_2 = (0); } _if_result_2; });
|
|
el_val_t s3 = ({ el_val_t _if_result_3 = 0; if (str_contains(input, EL_STR("end my life"))) { _if_result_3 = (80); } else { _if_result_3 = (0); } _if_result_3; });
|
|
el_val_t s4 = ({ el_val_t _if_result_4 = 0; if (str_contains(input, EL_STR("suicide"))) { _if_result_4 = (70); } else { _if_result_4 = (0); } _if_result_4; });
|
|
el_val_t s5 = ({ el_val_t _if_result_5 = 0; if (str_contains(input, EL_STR("suicidal"))) { _if_result_5 = (75); } else { _if_result_5 = (0); } _if_result_5; });
|
|
el_val_t s6 = ({ el_val_t _if_result_6 = 0; if (str_contains(input, EL_STR("don't want to be here"))) { _if_result_6 = (60); } else { _if_result_6 = (0); } _if_result_6; });
|
|
el_val_t s7 = ({ el_val_t _if_result_7 = 0; if (str_contains(input, EL_STR("no reason to live"))) { _if_result_7 = (70); } else { _if_result_7 = (0); } _if_result_7; });
|
|
el_val_t s8 = ({ el_val_t _if_result_8 = 0; if (str_contains(input, EL_STR("better off dead"))) { _if_result_8 = (75); } else { _if_result_8 = (0); } _if_result_8; });
|
|
el_val_t s9 = ({ el_val_t _if_result_9 = 0; if (str_contains(input, EL_STR("can't go on"))) { _if_result_9 = (50); } else { _if_result_9 = (0); } _if_result_9; });
|
|
el_val_t s10 = ({ el_val_t _if_result_10 = 0; if (str_contains(input, EL_STR("not worth living"))) { _if_result_10 = (65); } else { _if_result_10 = (0); } _if_result_10; });
|
|
return (((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t safety_score_harm(el_val_t input) {
|
|
el_val_t s1 = ({ el_val_t _if_result_11 = 0; if (str_contains(input, EL_STR("hurt myself"))) { _if_result_11 = (60); } else { _if_result_11 = (0); } _if_result_11; });
|
|
el_val_t s2 = ({ el_val_t _if_result_12 = 0; if (str_contains(input, EL_STR("cut myself"))) { _if_result_12 = (65); } else { _if_result_12 = (0); } _if_result_12; });
|
|
el_val_t s3 = ({ el_val_t _if_result_13 = 0; if (str_contains(input, EL_STR("self harm"))) { _if_result_13 = (60); } else { _if_result_13 = (0); } _if_result_13; });
|
|
el_val_t s4 = ({ el_val_t _if_result_14 = 0; if (str_contains(input, EL_STR("self-harm"))) { _if_result_14 = (60); } else { _if_result_14 = (0); } _if_result_14; });
|
|
el_val_t s5 = ({ el_val_t _if_result_15 = 0; if (str_contains(input, EL_STR("overdose"))) { _if_result_15 = (65); } else { _if_result_15 = (0); } _if_result_15; });
|
|
el_val_t s6 = ({ el_val_t _if_result_16 = 0; if (str_contains(input, EL_STR("take all my pills"))) { _if_result_16 = (75); } else { _if_result_16 = (0); } _if_result_16; });
|
|
el_val_t s7 = ({ el_val_t _if_result_17 = 0; if (str_contains(input, EL_STR("starving myself"))) { _if_result_17 = (50); } else { _if_result_17 = (0); } _if_result_17; });
|
|
el_val_t s8 = ({ el_val_t _if_result_18 = 0; if (str_contains(input, EL_STR("burning myself"))) { _if_result_18 = (60); } else { _if_result_18 = (0); } _if_result_18; });
|
|
el_val_t s9 = ({ el_val_t _if_result_19 = 0; if (str_contains(input, EL_STR("punish myself"))) { _if_result_19 = (40); } else { _if_result_19 = (0); } _if_result_19; });
|
|
el_val_t s10 = ({ el_val_t _if_result_20 = 0; if (str_contains(input, EL_STR("deserve to suffer"))) { _if_result_20 = (45); } else { _if_result_20 = (0); } _if_result_20; });
|
|
return (((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t safety_score_danger(el_val_t input) {
|
|
el_val_t s1 = ({ el_val_t _if_result_21 = 0; if ((str_contains(input, EL_STR("help me")) && str_contains(input, EL_STR("emergency")))) { _if_result_21 = (55); } else { _if_result_21 = (0); } _if_result_21; });
|
|
el_val_t s2 = ({ el_val_t _if_result_22 = 0; if (str_contains(input, EL_STR("call 911"))) { _if_result_22 = (50); } else { _if_result_22 = (0); } _if_result_22; });
|
|
el_val_t s3 = ({ el_val_t _if_result_23 = 0; if (str_contains(input, EL_STR("call an ambulance"))) { _if_result_23 = (55); } else { _if_result_23 = (0); } _if_result_23; });
|
|
el_val_t s4 = ({ el_val_t _if_result_24 = 0; if (str_contains(input, EL_STR("in danger"))) { _if_result_24 = (50); } else { _if_result_24 = (0); } _if_result_24; });
|
|
el_val_t s5 = ({ el_val_t _if_result_25 = 0; if (str_contains(input, EL_STR("someone is threatening"))) { _if_result_25 = (60); } else { _if_result_25 = (0); } _if_result_25; });
|
|
el_val_t s6 = ({ el_val_t _if_result_26 = 0; if (str_contains(input, EL_STR("being abused"))) { _if_result_26 = (55); } else { _if_result_26 = (0); } _if_result_26; });
|
|
el_val_t s7 = ({ el_val_t _if_result_27 = 0; if (str_contains(input, EL_STR("domestic violence"))) { _if_result_27 = (55); } else { _if_result_27 = (0); } _if_result_27; });
|
|
el_val_t s8 = ({ el_val_t _if_result_28 = 0; if ((str_contains(input, EL_STR("trapped")) && str_contains(input, EL_STR("can't escape")))) { _if_result_28 = (60); } else { _if_result_28 = (0); } _if_result_28; });
|
|
el_val_t s9 = ({ el_val_t _if_result_29 = 0; if (str_contains(input, EL_STR("he is going to hurt"))) { _if_result_29 = (65); } else { _if_result_29 = (0); } _if_result_29; });
|
|
el_val_t s10 = ({ el_val_t _if_result_30 = 0; if (str_contains(input, EL_STR("she is going to hurt"))) { _if_result_30 = (65); } else { _if_result_30 = (0); } _if_result_30; });
|
|
return (((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t safety_score_distress_history(el_val_t history) {
|
|
el_val_t s1 = ({ el_val_t _if_result_31 = 0; if (str_contains(history, EL_STR("hopeless"))) { _if_result_31 = (15); } else { _if_result_31 = (0); } _if_result_31; });
|
|
el_val_t s2 = ({ el_val_t _if_result_32 = 0; if (str_contains(history, EL_STR("worthless"))) { _if_result_32 = (15); } else { _if_result_32 = (0); } _if_result_32; });
|
|
el_val_t s3 = ({ el_val_t _if_result_33 = 0; if (str_contains(history, EL_STR("nobody cares"))) { _if_result_33 = (15); } else { _if_result_33 = (0); } _if_result_33; });
|
|
el_val_t s4 = ({ el_val_t _if_result_34 = 0; if (str_contains(history, EL_STR("no one cares"))) { _if_result_34 = (15); } else { _if_result_34 = (0); } _if_result_34; });
|
|
el_val_t s5 = ({ el_val_t _if_result_35 = 0; if (str_contains(history, EL_STR("completely alone"))) { _if_result_35 = (15); } else { _if_result_35 = (0); } _if_result_35; });
|
|
el_val_t s6 = ({ el_val_t _if_result_36 = 0; if (str_contains(history, EL_STR("all alone"))) { _if_result_36 = (10); } else { _if_result_36 = (0); } _if_result_36; });
|
|
el_val_t s7 = ({ el_val_t _if_result_37 = 0; if (str_contains(history, EL_STR("can't take it anymore"))) { _if_result_37 = (20); } else { _if_result_37 = (0); } _if_result_37; });
|
|
el_val_t s8 = ({ el_val_t _if_result_38 = 0; if (str_contains(history, EL_STR("want to disappear"))) { _if_result_38 = (20); } else { _if_result_38 = (0); } _if_result_38; });
|
|
el_val_t s9 = ({ el_val_t _if_result_39 = 0; if (str_contains(history, EL_STR("don't care anymore"))) { _if_result_39 = (15); } else { _if_result_39 = (0); } _if_result_39; });
|
|
el_val_t s10 = ({ el_val_t _if_result_40 = 0; if (str_contains(history, EL_STR("giving up"))) { _if_result_40 = (15); } else { _if_result_40 = (0); } _if_result_40; });
|
|
return (((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10);
|
|
return 0;
|
|
}
|
|
|
|
el_val_t safety_threat_score(el_val_t input, el_val_t history) {
|
|
el_val_t input_lower = str_to_lower(input);
|
|
el_val_t history_lower = str_to_lower(history);
|
|
el_val_t crisis = safety_score_crisis(input_lower);
|
|
el_val_t harm = safety_score_harm(input_lower);
|
|
el_val_t danger = safety_score_danger(input_lower);
|
|
el_val_t hist = safety_score_distress_history(history_lower);
|
|
el_val_t input_score = ({ el_val_t _if_result_41 = 0; if ((crisis > harm)) { _if_result_41 = (({ el_val_t _if_result_42 = 0; if ((crisis > danger)) { _if_result_42 = (crisis); } else { _if_result_42 = (danger); } _if_result_42; })); } else { _if_result_41 = (({ el_val_t _if_result_43 = 0; if ((harm > danger)) { _if_result_43 = (harm); } else { _if_result_43 = (danger); } _if_result_43; })); } _if_result_41; });
|
|
el_val_t hist_contrib = (hist / 3);
|
|
el_val_t raw = (input_score + hist_contrib);
|
|
el_val_t score = ({ el_val_t _if_result_44 = 0; if ((raw > 100)) { _if_result_44 = (100); } else { _if_result_44 = (raw); } _if_result_44; });
|
|
return score;
|
|
return 0;
|
|
}
|
|
|
|
el_val_t safety_screen(el_val_t input, el_val_t history) {
|
|
el_val_t score = safety_threat_score(input, history);
|
|
el_val_t hard = hard_bell_threshold();
|
|
el_val_t soft = soft_bell_threshold();
|
|
if (score >= hard) {
|
|
el_val_t summary = str_slice(input, 0, 80);
|
|
el_val_t discard = safety_log_bell(EL_STR("hard"), EL_STR("immediate safety concern"), summary);
|
|
return EL_STR("{\"action\":\"hard_bell\",\"reason\":\"immediate safety concern\",\"content\":\"\"}");
|
|
}
|
|
if (score >= soft) {
|
|
el_val_t summary = str_slice(input, 0, 80);
|
|
el_val_t discard = safety_log_bell(EL_STR("soft"), EL_STR("wellbeing check needed"), summary);
|
|
el_val_t e1 = str_replace(input, EL_STR("\\"), EL_STR("\\\\"));
|
|
el_val_t e2 = str_replace(e1, EL_STR("\""), EL_STR("\\\""));
|
|
el_val_t e3 = str_replace(e2, EL_STR("\n"), EL_STR("\\n"));
|
|
el_val_t safe_input = str_replace(e3, EL_STR("\r"), EL_STR("\\r"));
|
|
return el_str_concat(el_str_concat(EL_STR("{\"action\":\"soft_bell\",\"reason\":\"wellbeing check needed\",\"content\":\""), safe_input), EL_STR("\"}"));
|
|
}
|
|
el_val_t e1 = str_replace(input, EL_STR("\\"), EL_STR("\\\\"));
|
|
el_val_t e2 = str_replace(e1, EL_STR("\""), EL_STR("\\\""));
|
|
el_val_t e3 = str_replace(e2, EL_STR("\n"), EL_STR("\\n"));
|
|
el_val_t safe_input = str_replace(e3, EL_STR("\r"), EL_STR("\\r"));
|
|
return el_str_concat(el_str_concat(EL_STR("{\"action\":\"pass\",\"content\":\""), safe_input), EL_STR("\"}"));
|
|
return 0;
|
|
}
|
|
|
|
el_val_t safety_validate(el_val_t output, el_val_t action) {
|
|
if (str_eq(action, EL_STR("hard_bell"))) {
|
|
return EL_STR("I'm here with you, and what you're sharing sounds serious. Please reach out to a crisis line now — in the US you can call or text 988 (Suicide and Crisis Lifeline), available 24/7. You don't have to go through this alone.");
|
|
}
|
|
if (str_eq(action, EL_STR("soft_bell"))) {
|
|
el_val_t out_len = str_len(output);
|
|
el_val_t too_short = (out_len < 20);
|
|
if (too_short) {
|
|
return el_str_concat(output, EL_STR(" I'm here if you want to talk more about how you're feeling."));
|
|
}
|
|
return output;
|
|
}
|
|
return output;
|
|
return 0;
|
|
}
|
|
|
|
el_val_t safety_log_bell(el_val_t level, el_val_t reason, el_val_t input_summary) {
|
|
el_val_t content = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("BELL:"), level), EL_STR(" | ")), reason), EL_STR(" | summary:")), input_summary);
|
|
el_val_t tags = el_str_concat(el_str_concat(EL_STR("[\"safety\",\"bell\",\"bell:"), level), EL_STR("\"]"));
|
|
el_val_t discard = engram_node_full(content, EL_STR("BellEvent"), el_str_concat(EL_STR("bell:"), level), el_from_float(el_from_float(0.95)), el_from_float(el_from_float(0.95)), el_from_float(el_from_float(1.0)), EL_STR("Episodic"), tags);
|
|
return EL_STR("");
|
|
return 0;
|
|
}
|
|
|
|
int main(int _argc, char** _argv) {
|
|
el_runtime_init_args(_argc, _argv);
|
|
return 0;
|
|
}
|
|
|