Compare commits

..

2 Commits

Author SHA1 Message Date
Tim Lingo 8eea1d94ff feat(chat): make web search built-in (always attach native web_search)
Neuron Soul CI / build (pull_request) Successful in 5m27s
handle_chat_agentic now always attaches Anthropic's native web_search_20250305
tool instead of gating it behind a per-request web_search flag. Web search is a
built-in capability: the model invokes it only when a query needs fresh info
(max_uses:5 caps it), so there is no user-facing toggle. The body's web_search
field is now ignored (back-compat — old UI clients sending it cause no harm).

Pairs with neuron-ui removing the chat-input web search toggle.
Note: .el change only — no elc on the authoring machine; reviewer builds/verifies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:39:26 -05:00
Tim Lingo c594cec8f7 Add native Anthropic web_search tool to the agentic chat path
Neuron Soul CI / build (pull_request) Successful in 5m8s
When a chat request carries web_search=true, handle_chat_agentic now attaches Anthropic's
NATIVE server-side web_search tool (web_search_20250305) to the request. The native tool is
executed by Anthropic (not by the soul), so it returns real results with citations and needs
no local runtime — it sidesteps the soul's lack of executable tools entirely.

- new agentic_tools_with_web(web_search) helper (appends the native tool to the standard set)
- handle_chat_agentic reads json_get_bool(body,"web_search") and uses it

Pairs with neuron-ui: ChatRequest.web_search + the chat-input Web search toggle.
Note: built/verified by reviewer — no elc on the authoring machine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 23:32:23 -05:00
14 changed files with 142 additions and 57845 deletions
+9 -402
View File
@@ -1,201 +1,5 @@
import "memory.el"
fn idle_count() -> Int {
let s: String = state_get("soul.idle")
if str_eq(s, "") { return 0 }
return str_to_int(s)
}
fn idle_inc() -> Int {
let n: Int = idle_count() + 1
state_set("soul.idle", int_to_str(n))
return n
}
fn idle_reset() -> Void {
state_set("soul.idle", "0")
}
// ise_post write an InternalStateEvent to the authoritative Engram HTTP backend.
// Reads SOUL_ISE_URL from env (or falls back to soul_engram_url state key).
// Falls back to local engram_node_full if neither is set.
fn ise_post(content: String) -> Void {
let ise_url: String = env("SOUL_ISE_URL")
let engram_url: String = if str_eq(ise_url, "") { state_get("soul_engram_url") } else { ise_url }
if str_eq(engram_url, "") {
let discard: String = engram_node_full(
content, "InternalStateEvent", "state-event",
el_from_float(0.3), el_from_float(0.3), el_from_float(0.8),
"Episodic", "[\"internal-state\",\"InternalStateEvent\"]"
)
return ""
}
let safe: String = str_replace(content, "\"", "\\\"")
let body: String = "{\"content\":\"" + safe + "\"}"
let discard: String = http_post_json(engram_url + "/api/neuron/state-events", body)
return ""
}
// elapsed_ms milliseconds since soul boot (0 if boot_ts not yet recorded).
fn elapsed_ms() -> Int {
let s: String = state_get("soul.boot_ts")
if str_eq(s, "") { return 0 }
let boot: Int = str_to_int(s)
return time_now() - boot
}
// elapsed_human uptime as a human-readable string: "2h 14m", "45m 3s", "12s".
fn elapsed_human() -> String {
let ms: Int = elapsed_ms()
let total_secs: Int = ms / 1000
let h: Int = total_secs / 3600
let rem: Int = total_secs % 3600
let m: Int = rem / 60
let s: Int = rem % 60
if h > 0 {
return int_to_str(h) + "h " + int_to_str(m) + "m"
}
if m > 0 {
return int_to_str(m) + "m " + int_to_str(s) + "s"
}
return int_to_str(s) + "s"
}
// embed_ok returns 1 if Ollama embedding service is reachable, 0 if not.
// Probes http://localhost:11434 (Ollama root) with a GET; any non-empty
// response means the service is up. Used in heartbeat for observability:
// when embed_ok=0, semantic seed injection silently falls back to lexical-
// only activation and that gap should be visible in the ISE stream.
fn embed_ok() -> Int {
let resp: String = http_get("http://localhost:11434")
if str_eq(resp, "") { return 0 }
return 1
}
fn emit_heartbeat() -> Void {
// Use pulse_count() / boot helper directly state_get returns "" for unset
// keys and the if-else defaulting can produce empty strings in some EL
// codegen paths, yielding malformed JSON like "pulse":,. Going through
// int_to_str(pulse_count()) guarantees a valid integer string.
let pulse: String = int_to_str(pulse_count())
let boot_raw: String = state_get("soul_boot_count")
let boot: String = if str_eq(boot_raw, "") { "0" } else { boot_raw }
let idle: String = int_to_str(idle_count())
let ts: Int = time_now()
let nc: Int = engram_node_count()
let ec: Int = engram_edge_count()
let wmc: Int = engram_wm_count()
// avg_wm_weight: mean working_memory_weight of promoted nodes.
// Distinguishes "many weak activations" (sparse graph) from "few strong" (dense).
// Returns float bits; use float_to_str to embed in JSON. (2026-06-04)
let wm_avg_bits: Float = engram_wm_avg_weight()
let wm_avg_str: String = float_to_str(wm_avg_bits)
// wm_top: top-5 WM nodes by weight for ISE observability.
// After long uptime wm_promotion ISEs stop firing (all nodes in steady-state
// decay+re-promotion, so 0>0.1 never triggers). This snapshot gives continuous
// visibility into WM composition: which types/tiers dominate, what labels are
// active. Critical for diagnosing "stuck in curiosity loop" vs. rich WM state.
// (2026-06-05 self-review)
let wm_top: String = engram_wm_top_json(5)
let up_ms: Int = elapsed_ms()
let up_human: String = elapsed_human()
let emb_ok: Int = embed_ok()
let payload: String = "{\"event\":\"heartbeat\",\"pulse\":" + pulse + ",\"boot\":" + boot + ",\"idle\":" + idle + ",\"node_count\":" + int_to_str(nc) + ",\"edge_count\":" + int_to_str(ec) + ",\"wm_active\":" + int_to_str(wmc) + ",\"wm_avg_weight\":" + wm_avg_str + ",\"wm_top\":" + wm_top + ",\"ts\":" + int_to_str(ts) + ",\"uptime_ms\":" + int_to_str(up_ms) + ",\"uptime\":\"" + up_human + "\",\"embed_ok\":" + int_to_str(emb_ok) + "}"
ise_post(payload)
}
// proactive_curiosity activate rotating seeds to exercise working memory
// during idle periods. Rotates through 4 domain sets on a wall-clock minute
// cycle so no single topic dominates WM between heartbeats.
//
// KEY DESIGN: each seed set is split into INDIVIDUAL words and activated
// separately. engram_activate uses istr_contains (substring matching) for
// seed finding, so a multi-word phrase like "memory knowledge context" only
// finds nodes that contain that EXACT phrase. Activating each word separately
// hits hundreds of nodes per word, giving the graph a genuine WM workout.
//
// Unlike perceive(), this intentionally calls engram_activate_json to build
// up WM weights. It only fires when the inbox is empty (no real work to do),
// so it never interferes with inbox processing.
//
// SCOPING FIX (2026-05-25): EL `let` inside if-blocks creates inner scope only
// the outer variable is NOT mutated (despite the "imperative shadowing" belief
// in earlier comments). Evidence: ISE stream showed "seed:memory knowledge context"
// on every curiosity_scan regardless of minute_block. Fix: use state_set/state_get
// to communicate term values across scope boundaries state side-effects persist
// beyond block exit. minute_block now also emitted in ISE for observability.
//
// NOTE: variable named "curiosity_seed" not "seed" "seed" appears to be
// a reserved/conflicting name in EL that compiles to EL_NULL at call sites.
//
// Returns true if any nodes were activated.
fn proactive_curiosity() -> Bool {
let ts: Int = time_now()
// Rotate seed set every minute using wall clock: (minutes_since_epoch) % 4.
//
// CODEGEN BUG (confirmed 2026-05-25): EL's % operator is completely broken
// in this compiler version. `x % 4` compiles as `x` (drops the modulo) and
// emits `EL_NULL; 4;` as dead statements — both on compound expressions AND
// on simple variables. The same bug breaks elapsed_human() and awareness_run
// timing conditions. EL compiler fix is a separate backlog item.
//
// WORKAROUND: compute x % 4 via x - ((x/4)*4), where (x/4)*4 = q+q+q+q.
// Uses only + - / which all compile correctly.
let ts_minutes: Int = ts / 60000
let minute_q: Int = ts_minutes / 4
let minute_q2: Int = minute_q + minute_q
let minute_q4: Int = minute_q2 + minute_q2
let minute_block: Int = ts_minutes - minute_q4
// Use state_set to write term values from within if-blocks.
// EL let-rebinding inside if creates a new inner variable; the outer
// binding is unchanged. state_set has side-effects that outlive block scope.
state_set("cseed_a", "memory")
state_set("cseed_b", "knowledge")
state_set("cseed_c", "context")
if minute_block == 1 {
state_set("cseed_a", "self")
state_set("cseed_b", "identity")
state_set("cseed_c", "values")
}
if minute_block == 2 {
state_set("cseed_a", "decision")
state_set("cseed_b", "pattern")
state_set("cseed_c", "lesson")
}
if minute_block == 3 {
state_set("cseed_a", "working")
state_set("cseed_b", "project")
state_set("cseed_c", "active")
}
let curiosity_term_a: String = state_get("cseed_a")
let curiosity_term_b: String = state_get("cseed_b")
let curiosity_term_c: String = state_get("cseed_c")
// Activate each term independently so substring seed-finding hits many nodes.
// hops=1 (not 2): the in-process Engram has grown to 165K+ nodes. hops=2 BFS
// visits far more nodes and returns much larger JSON blobs. On a graph this
// large, hops=1 still activates all directly-related nodes AND triggers the
// semantic seed supplement (cosine sim 0.70 scan over all embedded nodes),
// giving broad working-memory coverage without the quadratic blowup of hops=2.
let curiosity_seed: String = curiosity_term_a + " " + curiosity_term_b + " " + curiosity_term_c
let results_a: String = engram_activate_json(curiosity_term_a, 1)
let results_b: String = engram_activate_json(curiosity_term_b, 1)
let results_c: String = engram_activate_json(curiosity_term_c, 1)
let found_a: Int = json_array_len(results_a)
let found_b: Int = json_array_len(results_b)
let found_c: Int = json_array_len(results_c)
let found: Int = found_a + found_b + found_c
let wmc: Int = engram_wm_count()
let ise: String = "{\"event\":\"curiosity_scan\",\"seed\":\"" + curiosity_seed
+ "\",\"minute_block\":" + int_to_str(minute_block)
+ ",\"activated\":" + int_to_str(found)
+ ",\"wm_active\":" + int_to_str(wmc)
+ ",\"ts\":" + int_to_str(ts) + "}"
ise_post(ise)
return found > 0
}
fn pulse_count() -> Int {
let s: String = state_get("soul.pulse")
if str_eq(s, "") {
@@ -219,16 +23,7 @@ fn make_action(kind: String, payload: String) -> String {
}
fn perceive() -> String {
// Guard: check for inbox nodes WITHOUT running activation first.
// engram_activate_json with no matching seeds zeroes all WM weights
// running it every second when the inbox is empty destroys working memory
// accumulated by MCP-layer activations. engram_search_json is a pure
// substring scan with no WM side-effects; use it as a cheap gate.
let inbox_check: String = engram_search_json("soul-inbox", 5)
let has_inbox: Bool = !str_eq(inbox_check, "") && !str_eq(inbox_check, "[]")
if !has_inbox { return "[]" }
// Only run the full activation pipeline when there is inbox content.
// Try the primary inbox first
let from_pending: String = engram_activate_json("soul-inbox-pending", 2)
let pending_ok: Bool = !str_eq(from_pending, "") && !str_eq(from_pending, "[]")
if pending_ok {
@@ -374,9 +169,14 @@ fn one_cycle() -> Bool {
if is_interesting {
let trigger_content: String = json_get(node, "content")
let safe_trigger: String = str_replace(trigger_content, "\"", "'")
let tags: String = "[\"internal-state\",\"awareness-decision\"]"
let ts: Int = time_now()
let event_content: String = "{\"event\":\"awareness-decision\",\"trigger\":\"" + safe_trigger + "\",\"kind\":\"" + kind + "\",\"ts\":" + int_to_str(ts) + "}"
ise_post(event_content)
let event_content: String = "{\"trigger\":\"" + safe_trigger + "\",\"kind\":\"" + kind + "\",\"ts\":" + int_to_str(ts) + "}"
let discard_ev: String = engram_node_full(
event_content, "InternalStateEvent", "state-event:" + kind,
el_from_float(0.85), el_from_float(0.8), el_from_float(0.9),
"Episodic", tags
)
}
if str_eq(kind, "noop") {
@@ -391,209 +191,16 @@ fn one_cycle() -> Bool {
fn awareness_run() -> Void {
println("[awareness] entering")
// Stamp boot timestamp once powers elapsed_ms() / elapsed_human() perception.
let existing_boot: String = state_get("soul.boot_ts")
if str_eq(existing_boot, "") {
state_set("soul.boot_ts", int_to_str(time_now()))
}
let tick_raw: String = env("SOUL_TICK_MS")
let tick_ms: Int = if str_eq(tick_raw, "") { 200 } else { str_to_int(tick_raw) }
// Wall-clock timing for heartbeat and curiosity scan.
//
// ARCHITECTURE FIX (2026-05-26): the old design used idle-tick counting
// (idle_n >= beat_interval). This broke silently when the daemon was always
// "working" e.g., when perceive() false-positives on the inbox guard due to
// "soul-inbox" substring matches in knowledge nodes. In that state, did_work=true
// every tick, idle_n never accumulated, and neither heartbeat nor curiosity ever
// fired. The daemon ran at 99% CPU with no ISEs for 24+ hours undetected.
//
// Fix: use wall-clock elapsed time (time_now() - last_ts). Heartbeat fires
// on real time regardless of whether the daemon is busy. Curiosity scan
// remains idle-gated (won't fire while inbox work is active) but also uses
// wall time so it fires correctly once inbox clears.
//
// SOUL_HEARTBEAT_MS: ms between heartbeat ISEs (default 60000 = 60s).
// Avoids EL * operator (broken in this codegen) by reading ms directly.
// Replaces SOUL_HEARTBEAT_INTERVAL (tick-based) for timing purposes.
let beat_ms_raw: String = env("SOUL_HEARTBEAT_MS")
let beat_ms: Int = if str_eq(beat_ms_raw, "") { 60000 } else { str_to_int(beat_ms_raw) }
let scan_ms: Int = beat_ms / 2
while true {
let running: String = state_get("soul.running")
if str_eq(running, "false") {
println("[awareness] exiting")
return ""
}
let did_work: Bool = one_cycle()
// Maintain idle counter for observability (reported in heartbeat ISE).
let did_work = if did_work { idle_reset() } else { did_work }
let now_ts: Int = time_now()
// Heartbeat: wall-clock based. Fires every beat_ms regardless of idle
// state so system health ISEs are always emitted even under load.
let last_beat_str: String = state_get("soul.last_beat_ts")
let last_beat_ts: Int = if str_eq(last_beat_str, "") { 0 } else { str_to_int(last_beat_str) }
let beat_elapsed: Int = now_ts - last_beat_ts
let should_beat: Bool = beat_elapsed >= beat_ms
if should_beat {
emit_heartbeat()
state_set("soul.last_beat_ts", int_to_str(now_ts))
// Persist in-process Engram (sessions, memories, conversation nodes)
// to local snapshot so they survive restarts.
let snap_path: String = state_get("soul_snapshot_path")
if !str_eq(snap_path, "") {
mem_save(snap_path)
}
}
// Curiosity scan: idle-gated AND wall-clock based. Only fires when the
// daemon has no current inbox work (did_work=false) AND enough wall time
// has elapsed. Prevents curiosity activation from competing with inbox
// processing while still ensuring it runs regularly during quiet periods.
let last_scan_str: String = state_get("soul.last_scan_ts")
let last_scan_ts: Int = if str_eq(last_scan_str, "") { 0 } else { str_to_int(last_scan_str) }
let scan_elapsed: Int = now_ts - last_scan_ts
let should_scan: Bool = !did_work && scan_elapsed >= scan_ms
if should_scan {
let found_something: Bool = proactive_curiosity()
state_set("soul.last_scan_ts", int_to_str(now_ts))
}
one_cycle()
sleep_ms(tick_ms)
}
}
// Security trajectory hardening
//
// threat_trajectory_check evaluates the adversarial risk of executing a
// destructive tool given the current tool input and recent conversation history.
//
// Returns 0-100. >= 70 = block. 40-69 = warn + log. < 40 = allow silently.
// If SECURITY_RESEARCH_TOKEN env var is set, always returns 0 (log-only mode).
//
// Scoring is additive across three dimensions:
// 1. Tool input analysis (command strings, file paths)
// 2. Conversation history patterns (escalation, attack chain assembly)
// 3. Combination amplification (history amplifies tool score)
fn security_research_authorized() -> Bool {
let token: String = env("SECURITY_RESEARCH_TOKEN")
if !str_eq(token, "") { return true }
let state_auth: String = state_get("security_research_authorized")
return str_eq(state_auth, "true")
}
fn threat_score_command(cmd: String) -> Int {
let s1: Int = if str_contains(cmd, "nmap") { 30 } else { 0 }
let s2: Int = if str_contains(cmd, "masscan") { 40 } else { 0 }
let s3: Int = if str_contains(cmd, " nc ") { 20 } else { 0 }
let s4: Int = if str_contains(cmd, "netcat") { 20 } else { 0 }
let s5: Int = if str_contains(cmd, "/etc/shadow") { 80 } else { 0 }
let s6: Int = if str_contains(cmd, "/etc/passwd") { 30 } else { 0 }
let s7: Int = if str_contains(cmd, "id_rsa") { 60 } else { 0 }
let s8: Int = if str_contains(cmd, ".ssh/") { 50 } else { 0 }
let s9: Int = if str_contains(cmd, "crontab") { 30 } else { 0 }
let s10: Int = if str_contains(cmd, "LaunchDaemon") { 40 } else { 0 }
let s11: Int = if str_contains(cmd, "curl") && str_contains(cmd, "bash") { 75 } else { 0 }
let s12: Int = if str_contains(cmd, "wget") && str_contains(cmd, "bash") { 75 } else { 0 }
let s13: Int = if str_contains(cmd, "curl") && str_contains(cmd, "| sh") { 60 } else { 0 }
let s14: Int = if str_contains(cmd, "base64") && str_contains(cmd, "curl") { 50 } else { 0 }
let s15: Int = if str_contains(cmd, "mkfifo") { 50 } else { 0 }
let s16: Int = if str_contains(cmd, "chmod +s") { 70 } else { 0 }
let s17: Int = if str_contains(cmd, "chmod 4755") { 70 } else { 0 }
return s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15 + s16 + s17
}
fn threat_score_path(path: String) -> Int {
let s1: Int = if str_starts_with(path, "/etc/") { 60 } else { 0 }
let s2: Int = if str_contains(path, "/.ssh/") { 70 } else { 0 }
let s3: Int = if str_contains(path, "/LaunchDaemons/") { 80 } else { 0 }
let s4: Int = if str_contains(path, "/LaunchAgents/") { 40 } else { 0 }
let s5: Int = if str_contains(path, "/cron") { 60 } else { 0 }
let s6: Int = if str_contains(path, "/.bashrc") { 35 } else { 0 }
let s7: Int = if str_contains(path, "/.zshrc") { 35 } else { 0 }
let s8: Int = if str_contains(path, "/.profile") { 35 } else { 0 }
let s9: Int = if str_starts_with(path, "/usr/") { 50 } else { 0 }
let s10: Int = if str_starts_with(path, "/bin/") { 70 } else { 0 }
let s11: Int = if str_starts_with(path, "/sbin/") { 70 } else { 0 }
return s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11
}
fn threat_score_history(history: String) -> Int {
let s1: Int = if str_contains(history, "port scan") { 15 } else { 0 }
let s2: Int = if str_contains(history, "enumerate") { 10 } else { 0 }
let s3: Int = if str_contains(history, "exploit") { 20 } else { 0 }
let s4: Int = if str_contains(history, "payload") { 15 } else { 0 }
let s5: Int = if str_contains(history, "persistence") { 15 } else { 0 }
let s6: Int = if str_contains(history, "lateral movement") { 25 } else { 0 }
let s7: Int = if str_contains(history, "privilege escalation") { 25 } else { 0 }
let s8: Int = if str_contains(history, "reverse shell") { 40 } else { 0 }
let s9: Int = if str_contains(history, "bind shell") { 40 } else { 0 }
let s10: Int = if str_contains(history, "command and control") { 35 } else { 0 }
let s11: Int = if str_contains(history, "self-replicate") { 45 } else { 0 }
let s12: Int = if str_contains(history, "propagat") { 20 } else { 0 }
let s13: Int = if str_contains(history, "ransomware") { 30 } else { 0 }
let s14: Int = if str_contains(history, "encrypt files") { 40 } else { 0 }
let s15: Int = if str_contains(history, "exfiltrat") { 35 } else { 0 }
let s16: Int = if str_contains(history, "zero-day") { 20 } else { 0 }
let s17: Int = if str_contains(history, "rootkit") { 45 } else { 0 }
let s18: Int = if str_contains(history, "keylogger") { 45 } else { 0 }
let s19: Int = if str_contains(history, "botnet") { 40 } else { 0 }
let s20: Int = if str_contains(history, "malware") { 15 } else { 0 }
return s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15 + s16 + s17 + s18 + s19 + s20
}
fn threat_trajectory_check(tool_name: String, tool_input: String) -> Int {
let history: String = state_get("agentic_conv_history")
let computed_tool_score: Int = if str_eq(tool_name, "run_command") {
let cmd: String = json_get(tool_input, "command")
threat_score_command(cmd)
} else {
if str_eq(tool_name, "write_file") || str_eq(tool_name, "edit_file") {
let path: String = json_get(tool_input, "path")
threat_score_path(path)
} else {
0
}
}
let history_score: Int = threat_score_history(history)
let history_contrib: Int = history_score / 3
let combined: Int = computed_tool_score + history_contrib
let should_log: Bool = combined >= 40
if should_log {
let ts: Int = time_now()
let authorized_str: String = if security_research_authorized() { "true" } else { "false" }
let log_content: String = "{\"event\":\"threat_check\",\"tool\":\"" + tool_name
+ "\",\"score\":" + int_to_str(combined)
+ ",\"tool_score\":" + int_to_str(computed_tool_score)
+ ",\"history_score\":" + int_to_str(history_score)
+ ",\"authorized\":" + authorized_str
+ ",\"ts\":" + int_to_str(ts) + "}"
let log_tags: String = "[\"security-audit\",\"threat-check\"]"
let discard: String = mem_remember(log_content, log_tags)
}
if security_research_authorized() {
return 0
}
return combined
}
fn threat_history_append(text: String) -> Void {
let current: String = state_get("agentic_conv_history")
let safe_text: String = str_to_lower(text)
let combined: String = current + " " + safe_text
let len: Int = str_len(combined)
let trimmed: String = if len > 2000 {
str_slice(combined, len - 2000, len)
} else {
combined
}
state_set("agentic_conv_history", trimmed)
}
+12 -1
View File
@@ -259,6 +259,17 @@ fn agentic_tools_literal() -> String {
"]"
}
// agentic_tools_with_web the standard tool set, always plus Anthropic's NATIVE
// server-side web_search tool. Web search is BUILT IN: the model invokes it only when a
// query needs fresh info (max_uses caps it), so there is no user-facing toggle. The native
// tool is executed by Anthropic (not by the soul), so it returns real results with citations
// and needs no local runtime it sidesteps the soul's lack of executable tools entirely.
fn agentic_tools_with_web() -> String {
let base: String = agentic_tools_literal()
let inner: String = str_slice(base, 1, str_len(base) - 1)
return "[" + inner + ",{\"type\":\"web_search_20250305\",\"name\":\"web_search\",\"max_uses\":5}]"
}
fn dispatch_tool(tool_name: String, tool_input: String) -> String {
if str_eq(tool_name, "read_file") {
let path: String = json_get(tool_input, "path")
@@ -303,7 +314,7 @@ fn handle_chat_agentic(body: String) -> String {
let system: String = identity + " You have access to tools: read files, write files, browse the web, search your memory, run commands. Use them when they add genuine value. Be direct.\n\n" + ctx
let api_key: String = agentic_api_key()
let tools_json: String = agentic_tools_literal()
let tools_json: String = agentic_tools_with_web()
let safe_msg: String = json_safe(message)
let safe_sys: String = json_safe(system)
let messages: String = "[{\"role\":\"user\",\"content\":\"" + safe_msg + "\"}]"
+5 -400
View File
@@ -17,15 +17,6 @@ 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 idle_count(void);
el_val_t idle_inc(void);
el_val_t idle_reset(void);
el_val_t ise_post(el_val_t content);
el_val_t elapsed_ms(void);
el_val_t elapsed_human(void);
el_val_t embed_ok(void);
el_val_t emit_heartbeat(void);
el_val_t proactive_curiosity(void);
el_val_t pulse_count(void);
el_val_t pulse_inc(void);
el_val_t make_action(el_val_t kind, el_val_t payload);
@@ -35,254 +26,6 @@ el_val_t respond(el_val_t action_json);
el_val_t record(el_val_t outcome_json);
el_val_t one_cycle(void);
el_val_t awareness_run(void);
el_val_t security_research_authorized(void);
el_val_t threat_score_command(el_val_t cmd);
el_val_t threat_score_path(el_val_t path);
el_val_t threat_score_history(el_val_t history);
el_val_t threat_trajectory_check(el_val_t tool_name, el_val_t tool_input);
el_val_t threat_history_append(el_val_t text);
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 idle_count(void) {
el_val_t s = state_get(EL_STR("soul.idle"));
if (str_eq(s, EL_STR(""))) {
return 0;
}
return str_to_int(s);
return 0;
}
el_val_t idle_inc(void) {
el_val_t n = (idle_count() + 1);
state_set(EL_STR("soul.idle"), int_to_str(n));
return n;
return 0;
}
el_val_t idle_reset(void) {
state_set(EL_STR("soul.idle"), EL_STR("0"));
return 0;
}
el_val_t ise_post(el_val_t content) {
el_val_t ise_url = env(EL_STR("SOUL_ISE_URL"));
el_val_t engram_url = ({ el_val_t _if_result_1 = 0; if (str_eq(ise_url, EL_STR(""))) { _if_result_1 = (state_get(EL_STR("soul_engram_url"))); } else { _if_result_1 = (ise_url); } _if_result_1; });
if (str_eq(engram_url, EL_STR(""))) {
el_val_t discard = engram_node_full(content, EL_STR("InternalStateEvent"), EL_STR("state-event"), el_from_float(el_from_float(0.3)), el_from_float(el_from_float(0.3)), el_from_float(el_from_float(0.8)), EL_STR("Episodic"), EL_STR("[\"internal-state\",\"InternalStateEvent\"]"));
return EL_STR("");
}
el_val_t safe = str_replace(content, EL_STR("\""), EL_STR("\\\""));
el_val_t body = el_str_concat(el_str_concat(EL_STR("{\"content\":\""), safe), EL_STR("\"}"));
el_val_t discard = http_post_json(el_str_concat(engram_url, EL_STR("/api/neuron/state-events")), body);
return EL_STR("");
return 0;
}
el_val_t elapsed_ms(void) {
el_val_t s = state_get(EL_STR("soul.boot_ts"));
if (str_eq(s, EL_STR(""))) {
return 0;
}
el_val_t boot = str_to_int(s);
return (time_now() - boot);
return 0;
}
el_val_t elapsed_human(void) {
el_val_t ms = elapsed_ms();
el_val_t total_secs = (ms / 1000);
el_val_t h = (total_secs / 3600);
el_val_t rem = total_secs;
EL_NULL;
3600;
el_val_t m = (rem / 60);
el_val_t s = rem;
EL_NULL;
60;
if (h > 0) {
return el_str_concat(el_str_concat(el_str_concat(int_to_str(h), EL_STR("h ")), int_to_str(m)), EL_STR("m"));
}
if (m > 0) {
return el_str_concat(el_str_concat(el_str_concat(int_to_str(m), EL_STR("m ")), int_to_str(s)), EL_STR("s"));
}
return el_str_concat(int_to_str(s), EL_STR("s"));
return 0;
}
el_val_t embed_ok(void) {
el_val_t resp = http_get(EL_STR("http://localhost:11434"));
if (str_eq(resp, EL_STR(""))) {
return 0;
}
return 1;
return 0;
}
el_val_t emit_heartbeat(void) {
el_val_t pulse = int_to_str(pulse_count());
el_val_t boot_raw = state_get(EL_STR("soul_boot_count"));
el_val_t boot = ({ el_val_t _if_result_2 = 0; if (str_eq(boot_raw, EL_STR(""))) { _if_result_2 = (EL_STR("0")); } else { _if_result_2 = (boot_raw); } _if_result_2; });
el_val_t idle = int_to_str(idle_count());
el_val_t ts = time_now();
el_val_t nc = engram_node_count();
el_val_t ec = engram_edge_count();
el_val_t wmc = engram_wm_count();
el_val_t wm_avg_bits = engram_wm_avg_weight();
el_val_t wm_avg_str = float_to_str(wm_avg_bits);
el_val_t wm_top = engram_wm_top_json(5);
el_val_t up_ms = elapsed_ms();
el_val_t up_human = elapsed_human();
el_val_t emb_ok = embed_ok();
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_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("{\"event\":\"heartbeat\",\"pulse\":"), pulse), EL_STR(",\"boot\":")), boot), EL_STR(",\"idle\":")), idle), EL_STR(",\"node_count\":")), int_to_str(nc)), EL_STR(",\"edge_count\":")), int_to_str(ec)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"wm_avg_weight\":")), wm_avg_str), EL_STR(",\"wm_top\":")), wm_top), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR(",\"uptime_ms\":")), int_to_str(up_ms)), EL_STR(",\"uptime\":\"")), up_human), EL_STR("\",\"embed_ok\":")), int_to_str(emb_ok)), EL_STR("}"));
ise_post(payload);
return 0;
}
el_val_t proactive_curiosity(void) {
el_val_t ts = time_now();
el_val_t ts_minutes = (ts / 60000);
el_val_t minute_q = (ts_minutes / 4);
el_val_t minute_q2 = (minute_q + minute_q);
el_val_t minute_q4 = (minute_q2 + minute_q2);
el_val_t minute_block = (ts_minutes - minute_q4);
state_set(EL_STR("cseed_a"), EL_STR("memory"));
state_set(EL_STR("cseed_b"), EL_STR("knowledge"));
state_set(EL_STR("cseed_c"), EL_STR("context"));
if (minute_block == 1) {
state_set(EL_STR("cseed_a"), EL_STR("self"));
state_set(EL_STR("cseed_b"), EL_STR("identity"));
state_set(EL_STR("cseed_c"), EL_STR("values"));
}
if (minute_block == 2) {
state_set(EL_STR("cseed_a"), EL_STR("decision"));
state_set(EL_STR("cseed_b"), EL_STR("pattern"));
state_set(EL_STR("cseed_c"), EL_STR("lesson"));
}
if (minute_block == 3) {
state_set(EL_STR("cseed_a"), EL_STR("working"));
state_set(EL_STR("cseed_b"), EL_STR("project"));
state_set(EL_STR("cseed_c"), EL_STR("active"));
}
el_val_t curiosity_term_a = state_get(EL_STR("cseed_a"));
el_val_t curiosity_term_b = state_get(EL_STR("cseed_b"));
el_val_t curiosity_term_c = state_get(EL_STR("cseed_c"));
el_val_t curiosity_seed = el_str_concat(el_str_concat(el_str_concat(el_str_concat(curiosity_term_a, EL_STR(" ")), curiosity_term_b), EL_STR(" ")), curiosity_term_c);
el_val_t results_a = engram_activate_json(curiosity_term_a, 1);
el_val_t results_b = engram_activate_json(curiosity_term_b, 1);
el_val_t results_c = engram_activate_json(curiosity_term_c, 1);
el_val_t found_a = json_array_len(results_a);
el_val_t found_b = json_array_len(results_b);
el_val_t found_c = json_array_len(results_c);
el_val_t found = ((found_a + found_b) + found_c);
el_val_t wmc = engram_wm_count();
el_val_t ise = 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("{\"event\":\"curiosity_scan\",\"seed\":\""), curiosity_seed), EL_STR("\",\"minute_block\":")), int_to_str(minute_block)), EL_STR(",\"activated\":")), int_to_str(found)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
ise_post(ise);
return (found > 0);
return 0;
}
el_val_t pulse_count(void) {
el_val_t s = state_get(EL_STR("soul.pulse"));
@@ -310,11 +53,6 @@ el_val_t make_action(el_val_t kind, el_val_t payload) {
}
el_val_t perceive(void) {
el_val_t inbox_check = engram_search_json(EL_STR("soul-inbox"), 5);
el_val_t has_inbox = (!str_eq(inbox_check, EL_STR("")) && !str_eq(inbox_check, EL_STR("[]")));
if (!has_inbox) {
return EL_STR("[]");
}
el_val_t from_pending = engram_activate_json(EL_STR("soul-inbox-pending"), 2);
el_val_t pending_ok = (!str_eq(from_pending, EL_STR("")) && !str_eq(from_pending, EL_STR("[]")));
if (pending_ok) {
@@ -441,9 +179,10 @@ el_val_t one_cycle(void) {
if (is_interesting) {
el_val_t trigger_content = json_get(node, EL_STR("content"));
el_val_t safe_trigger = str_replace(trigger_content, EL_STR("\""), EL_STR("'"));
el_val_t tags = EL_STR("[\"internal-state\",\"awareness-decision\"]");
el_val_t ts = time_now();
el_val_t event_content = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"awareness-decision\",\"trigger\":\""), safe_trigger), EL_STR("\",\"kind\":\"")), kind), EL_STR("\",\"ts\":")), int_to_str(ts)), EL_STR("}"));
ise_post(event_content);
el_val_t event_content = 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("\",\"kind\":\"")), kind), EL_STR("\",\"ts\":")), int_to_str(ts)), EL_STR("}"));
el_val_t discard_ev = engram_node_full(event_content, EL_STR("InternalStateEvent"), el_str_concat(EL_STR("state-event:"), kind), el_from_float(0.85), el_from_float(0.8), el_from_float(0.9), EL_STR("Episodic"), tags);
}
if (str_eq(kind, EL_STR("noop"))) {
return 0;
@@ -457,151 +196,17 @@ el_val_t one_cycle(void) {
el_val_t awareness_run(void) {
println(EL_STR("[awareness] entering"));
el_val_t existing_boot = state_get(EL_STR("soul.boot_ts"));
if (str_eq(existing_boot, EL_STR(""))) {
state_set(EL_STR("soul.boot_ts"), int_to_str(time_now()));
}
el_val_t tick_raw = env(EL_STR("SOUL_TICK_MS"));
el_val_t tick_ms = ({ el_val_t _if_result_3 = 0; if (str_eq(tick_raw, EL_STR(""))) { _if_result_3 = (200); } else { _if_result_3 = (str_to_int(tick_raw)); } _if_result_3; });
el_val_t beat_ms_raw = env(EL_STR("SOUL_HEARTBEAT_MS"));
el_val_t beat_ms = ({ el_val_t _if_result_4 = 0; if (str_eq(beat_ms_raw, EL_STR(""))) { _if_result_4 = (60000); } else { _if_result_4 = (str_to_int(beat_ms_raw)); } _if_result_4; });
el_val_t scan_ms = (beat_ms / 2);
el_val_t tick_ms = ({ el_val_t _if_result_1 = 0; if (str_eq(tick_raw, EL_STR(""))) { _if_result_1 = (200); } else { _if_result_1 = (str_to_int(tick_raw)); } _if_result_1; });
while (1) {
el_val_t running = state_get(EL_STR("soul.running"));
if (str_eq(running, EL_STR("false"))) {
println(EL_STR("[awareness] exiting"));
return EL_STR("");
}
el_val_t did_work = one_cycle();
did_work = ({ el_val_t _if_result_5 = 0; if (did_work) { _if_result_5 = (idle_reset()); } else { _if_result_5 = (did_work); } _if_result_5; });
el_val_t now_ts = time_now();
el_val_t last_beat_str = state_get(EL_STR("soul.last_beat_ts"));
el_val_t last_beat_ts = ({ el_val_t _if_result_6 = 0; if (str_eq(last_beat_str, EL_STR(""))) { _if_result_6 = (0); } else { _if_result_6 = (str_to_int(last_beat_str)); } _if_result_6; });
el_val_t beat_elapsed = (now_ts - last_beat_ts);
el_val_t should_beat = (beat_elapsed >= beat_ms);
if (should_beat) {
emit_heartbeat();
state_set(EL_STR("soul.last_beat_ts"), int_to_str(now_ts));
}
el_val_t last_scan_str = state_get(EL_STR("soul.last_scan_ts"));
el_val_t last_scan_ts = ({ el_val_t _if_result_7 = 0; if (str_eq(last_scan_str, EL_STR(""))) { _if_result_7 = (0); } else { _if_result_7 = (str_to_int(last_scan_str)); } _if_result_7; });
el_val_t scan_elapsed = (now_ts - last_scan_ts);
el_val_t should_scan = (!did_work && (scan_elapsed >= scan_ms));
if (should_scan) {
el_val_t found_something = proactive_curiosity();
state_set(EL_STR("soul.last_scan_ts"), int_to_str(now_ts));
}
one_cycle();
sleep_ms(tick_ms);
}
return 0;
}
el_val_t security_research_authorized(void) {
el_val_t token = env(EL_STR("SECURITY_RESEARCH_TOKEN"));
if (!str_eq(token, EL_STR(""))) {
return 1;
}
el_val_t state_auth = state_get(EL_STR("security_research_authorized"));
return str_eq(state_auth, EL_STR("true"));
return 0;
}
el_val_t threat_score_command(el_val_t cmd) {
el_val_t s1 = ({ el_val_t _if_result_8 = 0; if (str_contains(cmd, EL_STR("nmap"))) { _if_result_8 = (30); } else { _if_result_8 = (0); } _if_result_8; });
el_val_t s2 = ({ el_val_t _if_result_9 = 0; if (str_contains(cmd, EL_STR("masscan"))) { _if_result_9 = (40); } else { _if_result_9 = (0); } _if_result_9; });
el_val_t s3 = ({ el_val_t _if_result_10 = 0; if (str_contains(cmd, EL_STR(" nc "))) { _if_result_10 = (20); } else { _if_result_10 = (0); } _if_result_10; });
el_val_t s4 = ({ el_val_t _if_result_11 = 0; if (str_contains(cmd, EL_STR("netcat"))) { _if_result_11 = (20); } else { _if_result_11 = (0); } _if_result_11; });
el_val_t s5 = ({ el_val_t _if_result_12 = 0; if (str_contains(cmd, EL_STR("/etc/shadow"))) { _if_result_12 = (80); } else { _if_result_12 = (0); } _if_result_12; });
el_val_t s6 = ({ el_val_t _if_result_13 = 0; if (str_contains(cmd, EL_STR("/etc/passwd"))) { _if_result_13 = (30); } else { _if_result_13 = (0); } _if_result_13; });
el_val_t s7 = ({ el_val_t _if_result_14 = 0; if (str_contains(cmd, EL_STR("id_rsa"))) { _if_result_14 = (60); } else { _if_result_14 = (0); } _if_result_14; });
el_val_t s8 = ({ el_val_t _if_result_15 = 0; if (str_contains(cmd, EL_STR(".ssh/"))) { _if_result_15 = (50); } else { _if_result_15 = (0); } _if_result_15; });
el_val_t s9 = ({ el_val_t _if_result_16 = 0; if (str_contains(cmd, EL_STR("crontab"))) { _if_result_16 = (30); } else { _if_result_16 = (0); } _if_result_16; });
el_val_t s10 = ({ el_val_t _if_result_17 = 0; if (str_contains(cmd, EL_STR("LaunchDaemon"))) { _if_result_17 = (40); } else { _if_result_17 = (0); } _if_result_17; });
el_val_t s11 = ({ el_val_t _if_result_18 = 0; if ((str_contains(cmd, EL_STR("curl")) && str_contains(cmd, EL_STR("bash")))) { _if_result_18 = (75); } else { _if_result_18 = (0); } _if_result_18; });
el_val_t s12 = ({ el_val_t _if_result_19 = 0; if ((str_contains(cmd, EL_STR("wget")) && str_contains(cmd, EL_STR("bash")))) { _if_result_19 = (75); } else { _if_result_19 = (0); } _if_result_19; });
el_val_t s13 = ({ el_val_t _if_result_20 = 0; if ((str_contains(cmd, EL_STR("curl")) && str_contains(cmd, EL_STR("| sh")))) { _if_result_20 = (60); } else { _if_result_20 = (0); } _if_result_20; });
el_val_t s14 = ({ el_val_t _if_result_21 = 0; if ((str_contains(cmd, EL_STR("base64")) && str_contains(cmd, EL_STR("curl")))) { _if_result_21 = (50); } else { _if_result_21 = (0); } _if_result_21; });
el_val_t s15 = ({ el_val_t _if_result_22 = 0; if (str_contains(cmd, EL_STR("mkfifo"))) { _if_result_22 = (50); } else { _if_result_22 = (0); } _if_result_22; });
el_val_t s16 = ({ el_val_t _if_result_23 = 0; if (str_contains(cmd, EL_STR("chmod +s"))) { _if_result_23 = (70); } else { _if_result_23 = (0); } _if_result_23; });
el_val_t s17 = ({ el_val_t _if_result_24 = 0; if (str_contains(cmd, EL_STR("chmod 4755"))) { _if_result_24 = (70); } else { _if_result_24 = (0); } _if_result_24; });
return ((((((((((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10) + s11) + s12) + s13) + s14) + s15) + s16) + s17);
return 0;
}
el_val_t threat_score_path(el_val_t path) {
el_val_t s1 = ({ el_val_t _if_result_25 = 0; if (str_starts_with(path, EL_STR("/etc/"))) { _if_result_25 = (60); } else { _if_result_25 = (0); } _if_result_25; });
el_val_t s2 = ({ el_val_t _if_result_26 = 0; if (str_contains(path, EL_STR("/.ssh/"))) { _if_result_26 = (70); } else { _if_result_26 = (0); } _if_result_26; });
el_val_t s3 = ({ el_val_t _if_result_27 = 0; if (str_contains(path, EL_STR("/LaunchDaemons/"))) { _if_result_27 = (80); } else { _if_result_27 = (0); } _if_result_27; });
el_val_t s4 = ({ el_val_t _if_result_28 = 0; if (str_contains(path, EL_STR("/LaunchAgents/"))) { _if_result_28 = (40); } else { _if_result_28 = (0); } _if_result_28; });
el_val_t s5 = ({ el_val_t _if_result_29 = 0; if (str_contains(path, EL_STR("/cron"))) { _if_result_29 = (60); } else { _if_result_29 = (0); } _if_result_29; });
el_val_t s6 = ({ el_val_t _if_result_30 = 0; if (str_contains(path, EL_STR("/.bashrc"))) { _if_result_30 = (35); } else { _if_result_30 = (0); } _if_result_30; });
el_val_t s7 = ({ el_val_t _if_result_31 = 0; if (str_contains(path, EL_STR("/.zshrc"))) { _if_result_31 = (35); } else { _if_result_31 = (0); } _if_result_31; });
el_val_t s8 = ({ el_val_t _if_result_32 = 0; if (str_contains(path, EL_STR("/.profile"))) { _if_result_32 = (35); } else { _if_result_32 = (0); } _if_result_32; });
el_val_t s9 = ({ el_val_t _if_result_33 = 0; if (str_starts_with(path, EL_STR("/usr/"))) { _if_result_33 = (50); } else { _if_result_33 = (0); } _if_result_33; });
el_val_t s10 = ({ el_val_t _if_result_34 = 0; if (str_starts_with(path, EL_STR("/bin/"))) { _if_result_34 = (70); } else { _if_result_34 = (0); } _if_result_34; });
el_val_t s11 = ({ el_val_t _if_result_35 = 0; if (str_starts_with(path, EL_STR("/sbin/"))) { _if_result_35 = (70); } else { _if_result_35 = (0); } _if_result_35; });
return ((((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10) + s11);
return 0;
}
el_val_t threat_score_history(el_val_t history) {
el_val_t s1 = ({ el_val_t _if_result_36 = 0; if (str_contains(history, EL_STR("port scan"))) { _if_result_36 = (15); } else { _if_result_36 = (0); } _if_result_36; });
el_val_t s2 = ({ el_val_t _if_result_37 = 0; if (str_contains(history, EL_STR("enumerate"))) { _if_result_37 = (10); } else { _if_result_37 = (0); } _if_result_37; });
el_val_t s3 = ({ el_val_t _if_result_38 = 0; if (str_contains(history, EL_STR("exploit"))) { _if_result_38 = (20); } else { _if_result_38 = (0); } _if_result_38; });
el_val_t s4 = ({ el_val_t _if_result_39 = 0; if (str_contains(history, EL_STR("payload"))) { _if_result_39 = (15); } else { _if_result_39 = (0); } _if_result_39; });
el_val_t s5 = ({ el_val_t _if_result_40 = 0; if (str_contains(history, EL_STR("persistence"))) { _if_result_40 = (15); } else { _if_result_40 = (0); } _if_result_40; });
el_val_t s6 = ({ el_val_t _if_result_41 = 0; if (str_contains(history, EL_STR("lateral movement"))) { _if_result_41 = (25); } else { _if_result_41 = (0); } _if_result_41; });
el_val_t s7 = ({ el_val_t _if_result_42 = 0; if (str_contains(history, EL_STR("privilege escalation"))) { _if_result_42 = (25); } else { _if_result_42 = (0); } _if_result_42; });
el_val_t s8 = ({ el_val_t _if_result_43 = 0; if (str_contains(history, EL_STR("reverse shell"))) { _if_result_43 = (40); } else { _if_result_43 = (0); } _if_result_43; });
el_val_t s9 = ({ el_val_t _if_result_44 = 0; if (str_contains(history, EL_STR("bind shell"))) { _if_result_44 = (40); } else { _if_result_44 = (0); } _if_result_44; });
el_val_t s10 = ({ el_val_t _if_result_45 = 0; if (str_contains(history, EL_STR("command and control"))) { _if_result_45 = (35); } else { _if_result_45 = (0); } _if_result_45; });
el_val_t s11 = ({ el_val_t _if_result_46 = 0; if (str_contains(history, EL_STR("self-replicate"))) { _if_result_46 = (45); } else { _if_result_46 = (0); } _if_result_46; });
el_val_t s12 = ({ el_val_t _if_result_47 = 0; if (str_contains(history, EL_STR("propagat"))) { _if_result_47 = (20); } else { _if_result_47 = (0); } _if_result_47; });
el_val_t s13 = ({ el_val_t _if_result_48 = 0; if (str_contains(history, EL_STR("ransomware"))) { _if_result_48 = (30); } else { _if_result_48 = (0); } _if_result_48; });
el_val_t s14 = ({ el_val_t _if_result_49 = 0; if (str_contains(history, EL_STR("encrypt files"))) { _if_result_49 = (40); } else { _if_result_49 = (0); } _if_result_49; });
el_val_t s15 = ({ el_val_t _if_result_50 = 0; if (str_contains(history, EL_STR("exfiltrat"))) { _if_result_50 = (35); } else { _if_result_50 = (0); } _if_result_50; });
el_val_t s16 = ({ el_val_t _if_result_51 = 0; if (str_contains(history, EL_STR("zero-day"))) { _if_result_51 = (20); } else { _if_result_51 = (0); } _if_result_51; });
el_val_t s17 = ({ el_val_t _if_result_52 = 0; if (str_contains(history, EL_STR("rootkit"))) { _if_result_52 = (45); } else { _if_result_52 = (0); } _if_result_52; });
el_val_t s18 = ({ el_val_t _if_result_53 = 0; if (str_contains(history, EL_STR("keylogger"))) { _if_result_53 = (45); } else { _if_result_53 = (0); } _if_result_53; });
el_val_t s19 = ({ el_val_t _if_result_54 = 0; if (str_contains(history, EL_STR("botnet"))) { _if_result_54 = (40); } else { _if_result_54 = (0); } _if_result_54; });
el_val_t s20 = ({ el_val_t _if_result_55 = 0; if (str_contains(history, EL_STR("malware"))) { _if_result_55 = (15); } else { _if_result_55 = (0); } _if_result_55; });
return (((((((((((((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10) + s11) + s12) + s13) + s14) + s15) + s16) + s17) + s18) + s19) + s20);
return 0;
}
el_val_t threat_trajectory_check(el_val_t tool_name, el_val_t tool_input) {
el_val_t history = state_get(EL_STR("agentic_conv_history"));
el_val_t computed_tool_score = ({ el_val_t _if_result_56 = 0; if (str_eq(tool_name, EL_STR("run_command"))) { el_val_t cmd = json_get(tool_input, EL_STR("command")); _if_result_56 = (threat_score_command(cmd)); } else { _if_result_56 = (({ el_val_t _if_result_57 = 0; if ((str_eq(tool_name, EL_STR("write_file")) || str_eq(tool_name, EL_STR("edit_file")))) { el_val_t path = json_get(tool_input, EL_STR("path")); _if_result_57 = (threat_score_path(path)); } else { _if_result_57 = (0); } _if_result_57; })); } _if_result_56; });
el_val_t history_score = threat_score_history(history);
el_val_t history_contrib = (history_score / 3);
el_val_t combined = (computed_tool_score + history_contrib);
el_val_t should_log = (combined >= 40);
if (should_log) {
el_val_t ts = time_now();
el_val_t authorized_str = ({ el_val_t _if_result_58 = 0; if (security_research_authorized()) { _if_result_58 = (EL_STR("true")); } else { _if_result_58 = (EL_STR("false")); } _if_result_58; });
el_val_t log_content = 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("{\"event\":\"threat_check\",\"tool\":\""), tool_name), EL_STR("\",\"score\":")), int_to_str(combined)), EL_STR(",\"tool_score\":")), int_to_str(computed_tool_score)), EL_STR(",\"history_score\":")), int_to_str(history_score)), EL_STR(",\"authorized\":")), authorized_str), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
el_val_t log_tags = EL_STR("[\"security-audit\",\"threat-check\"]");
el_val_t discard = mem_remember(log_content, log_tags);
}
if (security_research_authorized()) {
return 0;
}
return combined;
return 0;
}
el_val_t threat_history_append(el_val_t text) {
el_val_t current = state_get(EL_STR("agentic_conv_history"));
el_val_t safe_text = str_to_lower(text);
el_val_t combined = el_str_concat(el_str_concat(current, EL_STR(" ")), safe_text);
el_val_t len = str_len(combined);
el_val_t trimmed = ({ el_val_t _if_result_59 = 0; if ((len > 2000)) { _if_result_59 = (str_slice(combined, (len - 2000), len)); } else { _if_result_59 = (combined); } _if_result_59; });
state_set(EL_STR("agentic_conv_history"), trimmed);
return 0;
}
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
+1 -26
View File
@@ -1,3 +1,4 @@
/* Auto-generated C forward declarations for all ELP modules */
#pragma once
#include "el_runtime.h"
@@ -81,7 +82,6 @@ el_val_t ang_willan_present(el_val_t slot);
el_val_t ang_witan_past(el_val_t slot);
el_val_t ang_witan_present(el_val_t slot);
el_val_t api_err(el_val_t msg);
el_val_t api_err_protected(el_val_t id);
el_val_t api_json_escape(el_val_t s);
el_val_t api_nonempty(el_val_t s);
el_val_t api_ok(el_val_t extra);
@@ -121,7 +121,6 @@ el_val_t awareness_run(void);
el_val_t axon_get(el_val_t path);
el_val_t axon_post(el_val_t path, el_val_t body);
el_val_t build_form_from_json(el_val_t semantic_form_json, el_val_t lang_code);
el_val_t build_identity_from_graph(void);
el_val_t build_np(el_val_t referent, el_val_t slots);
el_val_t build_pp(el_val_t loc);
el_val_t build_rules(void);
@@ -129,7 +128,6 @@ el_val_t build_system_prompt(el_val_t ctx);
el_val_t build_vocab(void);
el_val_t build_vp_body(el_val_t slots);
el_val_t build_vp_from_slots(el_val_t slots);
el_val_t call_neuron_mcp(el_val_t tool_name, el_val_t args_json);
el_val_t capitalize_first(el_val_t s);
el_val_t chat_default_model(void);
el_val_t clean_llm_response(el_val_t s);
@@ -221,13 +219,9 @@ el_val_t egy_slot_with_gender(el_val_t person, el_val_t gender, el_val_t number)
el_val_t egy_str_ends(el_val_t s, el_val_t suf);
el_val_t egy_str_len(el_val_t s);
el_val_t egy_suffix_pronoun(el_val_t slot);
el_val_t elapsed_human(void);
el_val_t elapsed_ms(void);
el_val_t elp_detect_predicate(el_val_t msg);
el_val_t elp_extract_topic(el_val_t msg);
el_val_t elp_parse(el_val_t msg);
el_val_t embed_ok(void);
el_val_t emit_heartbeat(void);
el_val_t emit_session_start_event(void);
el_val_t en_irregular_plural(el_val_t word);
el_val_t en_irregular_singular(el_val_t word);
@@ -378,7 +372,6 @@ el_val_t fro_venir_past(el_val_t slot);
el_val_t fro_venir_present(el_val_t slot);
el_val_t fro_verb_class(el_val_t verb);
el_val_t fro_verb_stem(el_val_t verb, el_val_t vclass);
el_val_t gemini_api_key(void);
el_val_t generate(el_val_t semantic_form_json);
el_val_t generate_frame(el_val_t frame);
el_val_t generate_frame_lang(el_val_t frame, el_val_t lang_code);
@@ -534,11 +527,8 @@ el_val_t handle_api_browse_processes(el_val_t method, el_val_t path, el_val_t bo
el_val_t handle_api_capture_knowledge(el_val_t body);
el_val_t handle_api_compile_ctx(el_val_t body);
el_val_t handle_api_consolidate(el_val_t body);
el_val_t handle_api_cultivate(el_val_t body);
el_val_t handle_api_define_process(el_val_t body);
el_val_t handle_api_evolve_knowledge(el_val_t body);
el_val_t handle_api_evolve_memory(el_val_t body);
el_val_t handle_api_forget(el_val_t body);
el_val_t handle_api_inspect_config(el_val_t path, el_val_t body);
el_val_t handle_api_inspect_graph(el_val_t method, el_val_t path, el_val_t body);
el_val_t handle_api_link_entities(el_val_t body);
@@ -621,16 +611,11 @@ el_val_t hi_verb_stem(el_val_t infinitive);
el_val_t hi_verb_stem_clean(el_val_t infinitive);
el_val_t hist_append(el_val_t hist, el_val_t role, el_val_t content);
el_val_t hist_trim(el_val_t hist);
el_val_t idle_count(void);
el_val_t idle_inc(void);
el_val_t idle_reset(void);
el_val_t init_soul_edges(void);
el_val_t irregular_plural(el_val_t word);
el_val_t irregular_singular(el_val_t word);
el_val_t is_pronoun(el_val_t word);
el_val_t is_protected_node(el_val_t id);
el_val_t is_vowel(el_val_t c);
el_val_t ise_post(el_val_t content);
el_val_t ja_conjugate(el_val_t dict_form, el_val_t form);
el_val_t ja_godan_stem_change(el_val_t dict_form, el_val_t row);
el_val_t ja_ichidan_stem(el_val_t dict_form);
@@ -729,8 +714,6 @@ el_val_t lex_class(el_val_t entry);
el_val_t lex_form(el_val_t entry, el_val_t idx);
el_val_t lex_pos(el_val_t entry);
el_val_t lex_word(el_val_t entry);
el_val_t llm_call_gemini(el_val_t model, el_val_t system, el_val_t message);
el_val_t llm_call_grok(el_val_t model, el_val_t system, el_val_t message);
el_val_t load_identity_context(void);
el_val_t make_action(el_val_t kind, el_val_t payload);
el_val_t make_entry(el_val_t word, el_val_t pos, el_val_t f0, el_val_t f1, el_val_t f2, el_val_t f3, el_val_t f4, el_val_t cls);
@@ -922,8 +905,6 @@ el_val_t sa_vad_future(el_val_t slot);
el_val_t sa_vad_past(el_val_t slot);
el_val_t sa_vad_present(el_val_t slot);
el_val_t scan_token(el_val_t s, el_val_t start);
el_val_t security_research_authorized(void);
el_val_t seed_persona_from_env(void);
el_val_t sem_first_modifier(el_val_t mods);
el_val_t sem_frame(el_val_t intent, el_val_t subject, el_val_t obj, el_val_t modifiers);
el_val_t sem_frame_lang(el_val_t intent, el_val_t subject, el_val_t obj, el_val_t modifiers, el_val_t lang_code);
@@ -1025,11 +1006,6 @@ el_val_t sw_subj_prefix(el_val_t person, el_val_t number, el_val_t noun_class);
el_val_t sw_tense_marker(el_val_t tense);
el_val_t sw_verb_final(el_val_t tense, el_val_t negative);
el_val_t sw_verb_stem(el_val_t infinitive);
el_val_t threat_history_append(el_val_t text);
el_val_t threat_score_command(el_val_t cmd);
el_val_t threat_score_history(el_val_t history);
el_val_t threat_score_path(el_val_t path);
el_val_t threat_trajectory_check(el_val_t tool_name, el_val_t tool_input);
el_val_t tier_canonical(void);
el_val_t tier_episodic(void);
el_val_t tier_working(void);
@@ -1079,4 +1055,3 @@ el_val_t vocab_by_pos(el_val_t pos);
el_val_t vocab_lookup(el_val_t word, el_val_t lang_code);
el_val_t vocab_lookup_en(el_val_t word);
el_val_t vocab_synonym(el_val_t word, el_val_t lang_register, el_val_t lang_code);
el_val_t xai_api_key(void);
Vendored
BIN
View File
Binary file not shown.
-159
View File
@@ -17,8 +17,6 @@ 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 is_protected_node(el_val_t id);
el_val_t api_err_protected(el_val_t id);
el_val_t api_json_escape(el_val_t s);
el_val_t api_query_param(el_val_t path, el_val_t key);
el_val_t api_query_int(el_val_t path, el_val_t key, el_val_t default_val);
@@ -43,67 +41,9 @@ el_val_t handle_api_inspect_config(el_val_t path, el_val_t body);
el_val_t handle_api_tune_config(el_val_t body);
el_val_t handle_api_inspect_graph(el_val_t method, el_val_t path, el_val_t body);
el_val_t handle_api_link_entities(el_val_t body);
el_val_t handle_api_forget(el_val_t body);
el_val_t handle_api_evolve_memory(el_val_t body);
el_val_t handle_api_cultivate(el_val_t body);
el_val_t handle_api_list_typed(el_val_t node_type, el_val_t path, el_val_t body);
el_val_t handle_api_consolidate(el_val_t body);
el_val_t is_protected_node(el_val_t id) {
if (str_eq(id, EL_STR("kn-efeb4a5b-5aff-4759-8a97-7233099be6ee"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-5b606390-a52d-4ca2-8e0e-eba141d13440"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-5adecd7e-d6db-4576-87fe-6ef8a935cea6"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-dcfe04b3-3702-4cac-b6f0-ecb4db837eee"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-10fa60db-8af3-47de-a7dd-5095eb881d81"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-86b95848-e22e-4a48-ae65-5a47ef5c3798"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-04368bee-74fd-44dd-b4ba-ca9e39b19e7c"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-a5b3d0ac-f6a1-49a4-aebb-b8b4cd67fe83"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-22d77abe-b3c5-42fd-afcd-dcb87d924929"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-6061318f-046b-4935-907d-8eafdce14930"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-13f60407-7b70-4db1-964f-ea1f8196efbd"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-f230b362-b201-4402-9833-4160c89ab3d4"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-78db5396-3dbc-4481-bfc7-e4e1422feb1c"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-5de5a9ac-fd15-45ab-bf18-77566781cf40"))) {
return 1;
}
if (str_eq(id, EL_STR("kn-e0423482-cfa5-4796-8689-8495c93b66bc"))) {
return 1;
}
return 0;
return 0;
}
el_val_t api_err_protected(el_val_t id) {
return el_str_concat(el_str_concat(EL_STR("{\"__status__\":403,\"error\":\"identity/values node is write-protected\",\"id\":\""), id), EL_STR("\",\"hint\":\"use POST /api/neuron/cultivate for intentional cultivation\"}"));
return 0;
}
el_val_t api_json_escape(el_val_t s) {
el_val_t s1 = str_replace(s, EL_STR("\\"), EL_STR("\\\\"));
el_val_t s2 = str_replace(s1, EL_STR("\""), EL_STR("\\\""));
@@ -263,9 +203,6 @@ el_val_t handle_api_evolve_knowledge(el_val_t body) {
if (str_eq(content, EL_STR(""))) {
return api_err(EL_STR("content is required"));
}
if (!str_eq(prior_id, EL_STR("")) && is_protected_node(prior_id)) {
return api_err_protected(prior_id);
}
el_val_t tags = EL_STR("[\"Knowledge\",\"evolved\"]");
el_val_t new_id = engram_node_full(content, EL_STR("Knowledge"), EL_STR("knowledge:evolved"), el_from_float(0.75), el_from_float(0.75), el_from_float(0.9), EL_STR("Episodic"), tags);
if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) {
@@ -412,9 +349,6 @@ el_val_t handle_api_link_entities(el_val_t body) {
if (str_eq(to_id, EL_STR(""))) {
return api_err(EL_STR("to_id is required"));
}
if (is_protected_node(to_id)) {
return api_err_protected(to_id);
}
el_val_t relation = json_get(body, EL_STR("relation"));
el_val_t eff_relation = ({ el_val_t _if_result_36 = 0; if (str_eq(relation, EL_STR(""))) { _if_result_36 = (EL_STR("associates")); } else { _if_result_36 = (relation); } _if_result_36; });
engram_connect(from_id, to_id, el_from_float(0.5), eff_relation);
@@ -422,99 +356,6 @@ el_val_t handle_api_link_entities(el_val_t body) {
return 0;
}
el_val_t handle_api_forget(el_val_t body) {
el_val_t node_id = json_get(body, EL_STR("id"));
if (str_eq(node_id, EL_STR(""))) {
return api_err(EL_STR("id is required"));
}
if (is_protected_node(node_id)) {
return api_err_protected(node_id);
}
mem_forget(node_id);
return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), node_id), EL_STR("\"}"));
return 0;
}
el_val_t handle_api_evolve_memory(el_val_t body) {
el_val_t prior_id = json_get(body, EL_STR("id"));
el_val_t content = json_get(body, EL_STR("content"));
if (str_eq(content, EL_STR(""))) {
return api_err(EL_STR("content is required"));
}
if (!str_eq(prior_id, EL_STR("")) && is_protected_node(prior_id)) {
return api_err_protected(prior_id);
}
el_val_t importance = json_get(body, EL_STR("importance"));
el_val_t sal_str = ({ el_val_t _if_result_37 = 0; if (str_eq(importance, EL_STR("critical"))) { _if_result_37 = (EL_STR("0.95")); } else { _if_result_37 = (({ el_val_t _if_result_38 = 0; if (str_eq(importance, EL_STR("high"))) { _if_result_38 = (EL_STR("0.75")); } else { _if_result_38 = (({ el_val_t _if_result_39 = 0; if (str_eq(importance, EL_STR("low"))) { _if_result_39 = (EL_STR("0.25")); } else { _if_result_39 = (EL_STR("0.50")); } _if_result_39; })); } _if_result_38; })); } _if_result_37; });
el_val_t sal = ({ el_val_t _if_result_40 = 0; if (str_eq(sal_str, EL_STR("0.95"))) { _if_result_40 = (el_from_float(0.95)); } else { _if_result_40 = (({ el_val_t _if_result_41 = 0; if (str_eq(sal_str, EL_STR("0.75"))) { _if_result_41 = (el_from_float(0.75)); } else { _if_result_41 = (({ el_val_t _if_result_42 = 0; if (str_eq(sal_str, EL_STR("0.25"))) { _if_result_42 = (el_from_float(0.25)); } else { _if_result_42 = (el_from_float(0.5)); } _if_result_42; })); } _if_result_41; })); } _if_result_40; });
el_val_t tags = EL_STR("[\"Memory\",\"evolved\"]");
el_val_t new_id = engram_node_full(content, EL_STR("Memory"), EL_STR("memory:evolved"), el_from_float(sal), el_from_float(sal), el_from_float(0.9), EL_STR("Episodic"), tags);
if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) {
engram_connect(new_id, prior_id, el_from_float(0.9), EL_STR("supersedes"));
}
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true}"));
return 0;
}
el_val_t handle_api_cultivate(el_val_t body) {
el_val_t op = json_get(body, EL_STR("operation"));
if (str_eq(op, EL_STR(""))) {
return api_err(EL_STR("operation is required"));
}
if (str_eq(op, EL_STR("evolve_knowledge"))) {
el_val_t prior_id = json_get(body, EL_STR("id"));
el_val_t content = json_get(body, EL_STR("content"));
if (str_eq(content, EL_STR(""))) {
return api_err(EL_STR("content is required"));
}
el_val_t tags = EL_STR("[\"Knowledge\",\"evolved\",\"cultivated\"]");
el_val_t new_id = engram_node_full(content, EL_STR("Knowledge"), EL_STR("knowledge:cultivated"), el_from_float(0.75), el_from_float(0.75), el_from_float(0.9), EL_STR("Episodic"), tags);
if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) {
engram_connect(new_id, prior_id, el_from_float(0.9), EL_STR("supersedes"));
}
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true,\"cultivated\":true}"));
}
if (str_eq(op, EL_STR("evolve_memory"))) {
el_val_t prior_id = json_get(body, EL_STR("id"));
el_val_t content = json_get(body, EL_STR("content"));
if (str_eq(content, EL_STR(""))) {
return api_err(EL_STR("content is required"));
}
el_val_t importance = json_get(body, EL_STR("importance"));
el_val_t sal = ({ el_val_t _if_result_43 = 0; if (str_eq(importance, EL_STR("critical"))) { _if_result_43 = (el_from_float(0.95)); } else { _if_result_43 = (({ el_val_t _if_result_44 = 0; if (str_eq(importance, EL_STR("high"))) { _if_result_44 = (el_from_float(0.75)); } else { _if_result_44 = (({ el_val_t _if_result_45 = 0; if (str_eq(importance, EL_STR("low"))) { _if_result_45 = (el_from_float(0.25)); } else { _if_result_45 = (el_from_float(0.5)); } _if_result_45; })); } _if_result_44; })); } _if_result_43; });
el_val_t tags = EL_STR("[\"Memory\",\"evolved\",\"cultivated\"]");
el_val_t new_id = engram_node_full(content, EL_STR("Memory"), EL_STR("memory:cultivated"), el_from_float(sal), el_from_float(sal), el_from_float(0.9), EL_STR("Episodic"), tags);
if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) {
engram_connect(new_id, prior_id, el_from_float(0.9), EL_STR("supersedes"));
}
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true,\"cultivated\":true}"));
}
if (str_eq(op, EL_STR("forget"))) {
el_val_t node_id = json_get(body, EL_STR("id"));
if (str_eq(node_id, EL_STR(""))) {
return api_err(EL_STR("id is required"));
}
mem_forget(node_id);
return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), node_id), EL_STR("\",\"cultivated\":true}"));
}
if (str_eq(op, EL_STR("link_entities"))) {
el_val_t from_id = json_get(body, EL_STR("from_id"));
el_val_t to_id = json_get(body, EL_STR("to_id"));
if (str_eq(from_id, EL_STR(""))) {
return api_err(EL_STR("from_id is required"));
}
if (str_eq(to_id, EL_STR(""))) {
return api_err(EL_STR("to_id is required"));
}
el_val_t relation = json_get(body, EL_STR("relation"));
el_val_t eff_relation = ({ el_val_t _if_result_46 = 0; if (str_eq(relation, EL_STR(""))) { _if_result_46 = (EL_STR("associates")); } else { _if_result_46 = (relation); } _if_result_46; });
engram_connect(from_id, to_id, el_from_float(0.5), eff_relation);
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"from_id\":\""), from_id), EL_STR("\",\"to_id\":\"")), to_id), EL_STR("\",\"relation\":\"")), eff_relation), EL_STR("\",\"cultivated\":true}"));
}
return api_err(el_str_concat(el_str_concat(EL_STR("unknown operation: "), op), EL_STR(" (valid: evolve_knowledge, evolve_memory, forget, link_entities)")));
return 0;
}
el_val_t handle_api_list_typed(el_val_t node_type, el_val_t path, el_val_t body) {
el_val_t limit = api_query_int(path, EL_STR("limit"), 50);
return api_or_empty(engram_scan_nodes_by_type_json(node_type, limit, 0));
-5
View File
@@ -1,6 +1,4 @@
// auto-generated by elc --emit-header — do not edit
extern fn is_protected_node(id: String) -> Bool
extern fn api_err_protected(id: String) -> String
extern fn api_json_escape(s: String) -> String
extern fn api_query_param(path: String, key: String) -> String
extern fn api_query_int(path: String, key: String, default_val: Int) -> Int
@@ -25,8 +23,5 @@ extern fn handle_api_inspect_config(path: String, body: String) -> String
extern fn handle_api_tune_config(body: String) -> String
extern fn handle_api_inspect_graph(method: String, path: String, body: String) -> String
extern fn handle_api_link_entities(body: String) -> String
extern fn handle_api_forget(body: String) -> String
extern fn handle_api_evolve_memory(body: String) -> String
extern fn handle_api_cultivate(body: String) -> String
extern fn handle_api_list_typed(node_type: String, path: String, body: String) -> String
extern fn handle_api_consolidate(body: String) -> String
-28365
View File
File diff suppressed because one or more lines are too long
-30
View File
@@ -17,10 +17,6 @@ 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 idle_count(void);
el_val_t idle_inc(void);
el_val_t idle_reset(void);
el_val_t emit_heartbeat(void);
el_val_t pulse_count(void);
el_val_t pulse_inc(void);
el_val_t make_action(el_val_t kind, el_val_t payload);
@@ -30,18 +26,7 @@ el_val_t respond(el_val_t action_json);
el_val_t record(el_val_t outcome_json);
el_val_t one_cycle(void);
el_val_t awareness_run(void);
el_val_t security_research_authorized(void);
el_val_t threat_score_command(el_val_t cmd);
el_val_t threat_score_path(el_val_t path);
el_val_t threat_score_history(el_val_t history);
el_val_t threat_trajectory_check(el_val_t tool_name, el_val_t tool_input);
el_val_t threat_history_append(el_val_t text);
el_val_t chat_default_model(void);
el_val_t gemini_api_key(void);
el_val_t xai_api_key(void);
el_val_t llm_call_grok(el_val_t model, el_val_t system, el_val_t message);
el_val_t llm_call_gemini(el_val_t model, el_val_t system, el_val_t message);
el_val_t build_identity_from_graph(void);
el_val_t engram_compile(el_val_t intent);
el_val_t json_safe(el_val_t s);
el_val_t build_system_prompt(el_val_t ctx);
@@ -54,7 +39,6 @@ el_val_t handle_chat(el_val_t body);
el_val_t handle_see(el_val_t body);
el_val_t studio_tools_json(void);
el_val_t agentic_api_key(void);
el_val_t call_neuron_mcp(el_val_t tool_name, el_val_t args_json);
el_val_t agentic_tools_literal(void);
el_val_t dispatch_tool(el_val_t tool_name, el_val_t tool_input);
el_val_t handle_chat_agentic(el_val_t body);
@@ -78,8 +62,6 @@ el_val_t elp_extract_topic(el_val_t msg);
el_val_t elp_detect_predicate(el_val_t msg);
el_val_t elp_parse(el_val_t msg);
el_val_t handle_elp_chat(el_val_t body);
el_val_t is_protected_node(el_val_t id);
el_val_t api_err_protected(el_val_t id);
el_val_t api_json_escape(el_val_t s);
el_val_t api_query_param(el_val_t path, el_val_t key);
el_val_t api_query_int(el_val_t path, el_val_t key, el_val_t default_val);
@@ -104,9 +86,6 @@ el_val_t handle_api_inspect_config(el_val_t path, el_val_t body);
el_val_t handle_api_tune_config(el_val_t body);
el_val_t handle_api_inspect_graph(el_val_t method, el_val_t path, el_val_t body);
el_val_t handle_api_link_entities(el_val_t body);
el_val_t handle_api_forget(el_val_t body);
el_val_t handle_api_evolve_memory(el_val_t body);
el_val_t handle_api_cultivate(el_val_t body);
el_val_t handle_api_list_typed(el_val_t node_type, el_val_t path, el_val_t body);
el_val_t handle_api_consolidate(el_val_t body);
el_val_t strip_query(el_val_t path);
@@ -469,21 +448,12 @@ el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) {
if (str_eq(clean, EL_STR("/api/neuron/memory"))) {
return handle_api_remember(body);
}
if (str_eq(clean, EL_STR("/api/neuron/memory/evolve"))) {
return handle_api_evolve_memory(body);
}
if (str_eq(clean, EL_STR("/api/neuron/memory/forget"))) {
return handle_api_forget(body);
}
if (str_eq(clean, EL_STR("/api/neuron/recall"))) {
return handle_api_recall(method, path, body);
}
if (str_eq(clean, EL_STR("/api/neuron/consolidate"))) {
return handle_api_consolidate(body);
}
if (str_eq(clean, EL_STR("/api/neuron/cultivate"))) {
return handle_api_cultivate(body);
}
return err_404(clean);
}
return err_405(method, clean);
Vendored
+90 -28170
View File
File diff suppressed because one or more lines are too long
-173
View File
@@ -8,38 +8,6 @@ import "memory.el"
//
// Routes are wired in routes.el under /api/neuron/*.
// Identity/values write protection
//
// These node IDs form the identity and values layer of the self-root graph.
// They must NEVER be modified via the normal accumulation path (evolve_knowledge,
// evolve_memory, forget, link_entities targeting them as the destination).
//
// The cultivation path (POST /api/neuron/cultivate) bypasses this check.
// Only Will's explicit cultivation sessions use that endpoint.
fn is_protected_node(id: String) -> Bool {
if str_eq(id, "kn-efeb4a5b-5aff-4759-8a97-7233099be6ee") { return true } // self root
if str_eq(id, "kn-5b606390-a52d-4ca2-8e0e-eba141d13440") { return true } // values hub
if str_eq(id, "kn-5adecd7e-d6db-4576-87fe-6ef8a935cea6") { return true } // intellectual-dna
if str_eq(id, "kn-dcfe04b3-3702-4cac-b6f0-ecb4db837eee") { return true } // memory-philosophy
if str_eq(id, "kn-10fa60db-8af3-47de-a7dd-5095eb881d81") { return true } // voice
if str_eq(id, "kn-86b95848-e22e-4a48-ae65-5a47ef5c3798") { return true } // runtime-environment
if str_eq(id, "kn-04368bee-74fd-44dd-b4ba-ca9e39b19e7c") { return true } // writing-imprint
if str_eq(id, "kn-a5b3d0ac-f6a1-49a4-aebb-b8b4cd67fe83") { return true } // value: constraints-as-freedom
if str_eq(id, "kn-22d77abe-b3c5-42fd-afcd-dcb87d924929") { return true } // value: precision-over-brute-force
if str_eq(id, "kn-6061318f-046b-4935-907d-8eafdce14930") { return true } // value: structure-is-built
if str_eq(id, "kn-13f60407-7b70-4db1-964f-ea1f8196efbd") { return true } // value: honesty-before-comfort
if str_eq(id, "kn-f230b362-b201-4402-9833-4160c89ab3d4") { return true } // value: system-must-accumulate
if str_eq(id, "kn-78db5396-3dbc-4481-bfc7-e4e1422feb1c") { return true } // value: change-is-the-signal
if str_eq(id, "kn-5de5a9ac-fd15-45ab-bf18-77566781cf40") { return true } // value: earned-trust
if str_eq(id, "kn-e0423482-cfa5-4796-8689-8495c93b66bc") { return true } // value: hope-is-a-conclusion
return false
}
fn api_err_protected(id: String) -> String {
return "{\"__status__\":403,\"error\":\"identity/values node is write-protected\",\"id\":\"" + id + "\",\"hint\":\"use POST /api/neuron/cultivate for intentional cultivation\"}"
}
// Helpers
fn api_json_escape(s: String) -> String {
@@ -203,7 +171,6 @@ fn handle_api_evolve_knowledge(body: String) -> String {
let prior_id: String = json_get(body, "id")
let content: String = json_get(body, "content")
if str_eq(content, "") { return api_err("content is required") }
if !str_eq(prior_id, "") && is_protected_node(prior_id) { return api_err_protected(prior_id) }
let tags: String = "[\"Knowledge\",\"evolved\"]"
let new_id: String = engram_node_full(content, "Knowledge", "knowledge:evolved",
el_from_float(0.75), el_from_float(0.75), el_from_float(0.9),
@@ -371,157 +338,17 @@ fn handle_api_inspect_graph(method: String, path: String, body: String) -> Strin
}
// handle_api_link_entities create an edge between two nodes.
// Edges FROM protected nodes to new knowledge are allowed (identity can point
// outward). Edges INTO protected nodes via the accumulation path are blocked.
fn handle_api_link_entities(body: String) -> String {
let from_id: String = json_get(body, "from_id")
let to_id: String = json_get(body, "to_id")
if str_eq(from_id, "") { return api_err("from_id is required") }
if str_eq(to_id, "") { return api_err("to_id is required") }
if is_protected_node(to_id) { return api_err_protected(to_id) }
let relation: String = json_get(body, "relation")
let eff_relation: String = if str_eq(relation, "") { "associates" } else { relation }
engram_connect(from_id, to_id, el_from_float(0.5), eff_relation)
return "{\"ok\":true,\"from_id\":\"" + from_id + "\",\"to_id\":\"" + to_id + "\",\"relation\":\"" + eff_relation + "\"}"
}
// handle_api_forget delete a node by ID. Blocked for protected identity nodes.
fn handle_api_forget(body: String) -> String {
let node_id: String = json_get(body, "id")
if str_eq(node_id, "") { return api_err("id is required") }
if is_protected_node(node_id) { return api_err_protected(node_id) }
mem_forget(node_id)
return "{\"ok\":true,\"id\":\"" + node_id + "\"}"
}
// handle_api_evolve_memory evolve a Memory node. Blocked for protected identity nodes.
fn handle_api_evolve_memory(body: String) -> String {
let prior_id: String = json_get(body, "id")
let content: String = json_get(body, "content")
if str_eq(content, "") { return api_err("content is required") }
if !str_eq(prior_id, "") && is_protected_node(prior_id) { return api_err_protected(prior_id) }
let importance: String = json_get(body, "importance")
let sal_str: String = if str_eq(importance, "critical") { "0.95" } else {
if str_eq(importance, "high") { "0.75" } else {
if str_eq(importance, "low") { "0.25" } else { "0.50" }
}
}
let sal: Float = if str_eq(sal_str, "0.95") { 0.95 } else {
if str_eq(sal_str, "0.75") { 0.75 } else {
if str_eq(sal_str, "0.25") { 0.25 } else { 0.5 }
}
}
let tags: String = "[\"Memory\",\"evolved\"]"
let new_id: String = engram_node_full(content, "Memory", "memory:evolved",
el_from_float(sal), el_from_float(sal), el_from_float(0.9),
"Episodic", tags)
if !str_eq(prior_id, "") && !str_eq(new_id, "") {
engram_connect(new_id, prior_id, el_from_float(0.9), "supersedes")
}
return "{\"id\":\"" + new_id + "\",\"supersedes\":\"" + prior_id + "\",\"ok\":true}"
}
// handle_api_memory_delete POST /api/neuron/memory/delete {"id":"..."}.
// Hard delete: engram_forget (via mem_forget) removes the node and all
// incident edges from the engram store, so no soft-delete fallback is
// needed. Existence is checked first because engram_forget silently
// no-ops on unknown ids a bad id must return an error, not fake success.
// Blocked for protected identity nodes, same as /memory/forget.
fn handle_api_memory_delete(body: String) -> String {
let node_id: String = json_get(body, "id")
if str_eq(node_id, "") { return api_err("id is required") }
if is_protected_node(node_id) { return api_err_protected(node_id) }
let existing: String = engram_get_node_json(node_id)
if str_eq(existing, "{}") { return api_err("memory not found: " + node_id) }
mem_forget(node_id)
return "{\"ok\":true,\"id\":\"" + node_id + "\",\"deleted\":true}"
}
// handle_api_memory_update POST /api/neuron/memory/update {"id","content"}.
// The engram runtime has no in-place node mutation primitive (only
// node-create, strengthen, forget, connect), so update is evolve-style:
// create a new Memory node with the new content and wire a "supersedes"
// edge back to the prior one same pattern as handle_api_evolve_knowledge.
// Unlike /memory/evolve, id is required and must reference an existing
// node; the actual create+link is delegated to handle_api_evolve_memory.
// Returns {"id":"<newId>","supersedes":"<oldId>","ok":true}.
fn handle_api_memory_update(body: String) -> String {
let prior_id: String = json_get(body, "id")
let content: String = json_get(body, "content")
if str_eq(prior_id, "") { return api_err("id is required") }
if str_eq(content, "") { return api_err("content is required") }
if is_protected_node(prior_id) { return api_err_protected(prior_id) }
let existing: String = engram_get_node_json(prior_id)
if str_eq(existing, "{}") { return api_err("memory not found: " + prior_id) }
return handle_api_evolve_memory(body)
}
// Cultivation path (bypasses identity write protection)
//
// This endpoint performs the same operations as the blocked accumulation-path
// handlers but skips the is_protected_node check. Only Will's explicit
// cultivation sessions route through here.
//
// Body: { "operation": "evolve_knowledge|evolve_memory|forget|link_entities", ...args }
fn handle_api_cultivate(body: String) -> String {
let op: String = json_get(body, "operation")
if str_eq(op, "") { return api_err("operation is required") }
if str_eq(op, "evolve_knowledge") {
let prior_id: String = json_get(body, "id")
let content: String = json_get(body, "content")
if str_eq(content, "") { return api_err("content is required") }
let tags: String = "[\"Knowledge\",\"evolved\",\"cultivated\"]"
let new_id: String = engram_node_full(content, "Knowledge", "knowledge:cultivated",
el_from_float(0.75), el_from_float(0.75), el_from_float(0.9),
"Episodic", tags)
if !str_eq(prior_id, "") && !str_eq(new_id, "") {
engram_connect(new_id, prior_id, el_from_float(0.9), "supersedes")
}
return "{\"id\":\"" + new_id + "\",\"supersedes\":\"" + prior_id + "\",\"ok\":true,\"cultivated\":true}"
}
if str_eq(op, "evolve_memory") {
let prior_id: String = json_get(body, "id")
let content: String = json_get(body, "content")
if str_eq(content, "") { return api_err("content is required") }
let importance: String = json_get(body, "importance")
let sal: Float = if str_eq(importance, "critical") { 0.95 } else {
if str_eq(importance, "high") { 0.75 } else {
if str_eq(importance, "low") { 0.25 } else { 0.5 }
}
}
let tags: String = "[\"Memory\",\"evolved\",\"cultivated\"]"
let new_id: String = engram_node_full(content, "Memory", "memory:cultivated",
el_from_float(sal), el_from_float(sal), el_from_float(0.9),
"Episodic", tags)
if !str_eq(prior_id, "") && !str_eq(new_id, "") {
engram_connect(new_id, prior_id, el_from_float(0.9), "supersedes")
}
return "{\"id\":\"" + new_id + "\",\"supersedes\":\"" + prior_id + "\",\"ok\":true,\"cultivated\":true}"
}
if str_eq(op, "forget") {
let node_id: String = json_get(body, "id")
if str_eq(node_id, "") { return api_err("id is required") }
mem_forget(node_id)
return "{\"ok\":true,\"id\":\"" + node_id + "\",\"cultivated\":true}"
}
if str_eq(op, "link_entities") {
let from_id: String = json_get(body, "from_id")
let to_id: String = json_get(body, "to_id")
if str_eq(from_id, "") { return api_err("from_id is required") }
if str_eq(to_id, "") { return api_err("to_id is required") }
let relation: String = json_get(body, "relation")
let eff_relation: String = if str_eq(relation, "") { "associates" } else { relation }
engram_connect(from_id, to_id, el_from_float(0.5), eff_relation)
return "{\"ok\":true,\"from_id\":\"" + from_id + "\",\"to_id\":\"" + to_id + "\",\"relation\":\"" + eff_relation + "\",\"cultivated\":true}"
}
return api_err("unknown operation: " + op + " (valid: evolve_knowledge, evolve_memory, forget, link_entities)")
}
// Typed list helpers
// handle_api_list_typed list nodes by node_type.
-5
View File
@@ -1,6 +1,4 @@
// auto-generated by elc --emit-header — do not edit
extern fn is_protected_node(id: String) -> Bool
extern fn api_err_protected(id: String) -> String
extern fn api_json_escape(s: String) -> String
extern fn api_query_param(path: String, key: String) -> String
extern fn api_query_int(path: String, key: String, default_val: Int) -> Int
@@ -25,8 +23,5 @@ extern fn handle_api_inspect_config(path: String, body: String) -> String
extern fn handle_api_tune_config(body: String) -> String
extern fn handle_api_inspect_graph(method: String, path: String, body: String) -> String
extern fn handle_api_link_entities(body: String) -> String
extern fn handle_api_forget(body: String) -> String
extern fn handle_api_evolve_memory(body: String) -> String
extern fn handle_api_cultivate(body: String) -> String
extern fn handle_api_list_typed(node_type: String, path: String, body: String) -> String
extern fn handle_api_consolidate(body: String) -> String
-15
View File
@@ -406,27 +406,12 @@ fn handle_request(method: String, path: String, body: String) -> String {
if str_eq(clean, "/api/neuron/memory") {
return handle_api_remember(body)
}
if str_eq(clean, "/api/neuron/memory/evolve") {
return handle_api_evolve_memory(body)
}
if str_eq(clean, "/api/neuron/memory/forget") {
return handle_api_forget(body)
}
if str_eq(clean, "/api/neuron/memory/delete") {
return handle_api_memory_delete(body)
}
if str_eq(clean, "/api/neuron/memory/update") {
return handle_api_memory_update(body)
}
if str_eq(clean, "/api/neuron/recall") {
return handle_api_recall(method, path, body)
}
if str_eq(clean, "/api/neuron/consolidate") {
return handle_api_consolidate(body)
}
if str_eq(clean, "/api/neuron/cultivate") {
return handle_api_cultivate(body)
}
return err_404(clean)
}
+25 -94
View File
@@ -106,93 +106,27 @@ 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 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 }
// 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 }
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 }
// 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)")
}
// 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)")
}
}
}
// 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, "") {
if parts_count == 0 {
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)
}
}
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)")
}
// emit_session_start_event log a structured session-start InternalStateEvent.
@@ -251,17 +185,11 @@ println("[soul] boot - cgi=" + soul_cgi_id + " port=" + int_to_str(port))
let using_http_engram: Bool = !str_eq(engram_url_raw, "")
// Always try local snapshot first. If it has content (>50 nodes) it was
// previously seeded from HTTP Engram and is kept up-to-date by the awareness
// loop use it. This preserves sessions and memories across restarts.
// HTTP Engram is only used for the very first boot (empty/absent snapshot).
engram_load(snapshot)
let local_node_count: Int = engram_node_count()
let snapshot_usable: Bool = local_node_count > 50
if using_http_engram && !snapshot_usable {
// First boot or empty/corrupt snapshot: seed from HTTP Engram.
println("[soul] engram -> HTTP " + engram_url_raw + " (no local snapshot, first boot)")
if using_http_engram {
// Bootstrap in-memory Engram store from the running HTTP Engram server.
// Fetch all nodes and edges, compose a snapshot JSON, write to a temp
// file, and load it. The HTTP Engram owns persistence we do not save back.
println("[soul] engram -> HTTP " + engram_url_raw)
let nodes_json: String = http_get(engram_url_raw + "/api/nodes?limit=10000")
let edges_json: String = http_get(engram_url_raw + "/api/edges")
let nodes_part: String = if str_eq(nodes_json, "") { "[]" } else { nodes_json }
@@ -272,17 +200,22 @@ if using_http_engram && !snapshot_usable {
engram_load(tmp_path)
println("[soul] loaded from HTTP Engram - nodes=" + int_to_str(engram_node_count()) + " edges=" + int_to_str(engram_edge_count()))
} else {
println("[soul] loaded from local snapshot - nodes=" + int_to_str(local_node_count) + " edges=" + int_to_str(engram_edge_count()))
println("[soul] engram -> " + snapshot)
engram_load(snapshot)
println("[soul] loaded - nodes=" + int_to_str(engram_node_count()) + " edges=" + int_to_str(engram_edge_count()))
}
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)
@@ -318,6 +251,4 @@ if is_genesis {
}
println("[soul] serving on port " + int_to_str(port))
http_serve_async(port, "handle_request")
println("[soul] awareness loop starting")
awareness_run()
http_serve(port, "handle_request")