71ab7eafde
Routes a new event_type "chat_as_soul" through dharma/recv. The Studio preassembles the system_prompt + transcript and dispatches per-speaker; the soul-binary just performs the LLM call as the requested speaker_slug. No engram_compile here — each soul has its own engram (88xx) and the Studio queries it before composing the prompt. Also: track the previously-untracked split source modules (chat, routes, memory, awareness, studio) and add build.sh so the binary can be rebuilt without the studio’s concat trick. elb resolves the import graph and emits one .c per .el; we link them together with cc. dist/soul-el now points at dist/neuron via symlink (matching the launchctl plist).
178 lines
6.6 KiB
EmacsLisp
178 lines
6.6 KiB
EmacsLisp
import "../foundation/elp/src/elp.el"
|
|
import "memory.el"
|
|
import "chat.el"
|
|
|
|
fn auth_headers(tok: String) -> Map {
|
|
let m: Map = {}
|
|
map_set(m, "Content-Type", "application/json")
|
|
if !str_eq(tok, "") {
|
|
map_set(m, "Authorization", "Bearer " + tok)
|
|
}
|
|
return m
|
|
}
|
|
|
|
fn axon_get(path: String) -> String {
|
|
let base: String = state_get("soul_axon_base")
|
|
let tok: String = state_get("soul_token")
|
|
let h: Map = auth_headers(tok)
|
|
return http_get_with_headers(base + path, h)
|
|
}
|
|
|
|
fn axon_post(path: String, body: String) -> String {
|
|
let base: String = state_get("soul_axon_base")
|
|
let tok: String = state_get("soul_token")
|
|
let h: Map = auth_headers(tok)
|
|
return http_post_with_headers(base + path, body, h)
|
|
}
|
|
|
|
fn handle_conversations(method: String) -> String {
|
|
let resp: String = engram_scan_nodes_json(500, 0)
|
|
if str_eq(resp, "") {
|
|
return "[]"
|
|
}
|
|
return resp
|
|
}
|
|
|
|
fn handle_config(method: String, body: String) -> String {
|
|
if str_eq(method, "POST") {
|
|
let new_model: String = json_get(body, "model")
|
|
if !str_eq(new_model, "") {
|
|
state_set("soul_model", new_model)
|
|
}
|
|
let provider: String = json_get(body, "provider")
|
|
let api_key: String = json_get(body, "api_key")
|
|
if !str_eq(provider, "") && !str_eq(api_key, "") {
|
|
state_set("key_" + provider, api_key)
|
|
}
|
|
}
|
|
let current_model: String = state_get("soul_model")
|
|
let display: String = if str_eq(current_model, "") { "claude-sonnet-4-5" } else { current_model }
|
|
return "{\"model\":\"" + display + "\",\"ok\":true}"
|
|
}
|
|
|
|
fn dharma_registry() -> String {
|
|
let cgi_id: String = state_get("soul_cgi_id")
|
|
let principal: String = state_get("soul_principal")
|
|
return "{\"registry\":[{\"cgi\":\"" + cgi_id + "\","
|
|
+ "\"principal\":\"" + principal + "\","
|
|
+ "\"covenant\":\"Principal Covenant v1\","
|
|
+ "\"registered\":\"2026-05-01\",\"provenance\":\"genesis\","
|
|
+ "\"entry\":1}],"
|
|
+ "\"network_status\":\"initializing\","
|
|
+ "\"total_cgis\":1}"
|
|
}
|
|
|
|
fn dharma_network_state() -> String {
|
|
let cgi_id: String = state_get("soul_cgi_id")
|
|
return "{\"active_members\":[{\"id\":\"" + cgi_id + "\",\"role\":\"cgi-entity\",\"status\":\"online\"}],"
|
|
+ "\"pending_approvals\":[],\"recent_events\":[]}"
|
|
}
|
|
|
|
fn handle_dharma(path: String, method: String, body: String) -> String {
|
|
if str_eq(path, "/api/dharma/registry") {
|
|
return dharma_registry()
|
|
}
|
|
if str_eq(path, "/api/dharma/network") {
|
|
return dharma_network_state()
|
|
}
|
|
if str_eq(path, "/api/dharma/submit") {
|
|
let content: String = json_get(body, "content")
|
|
let session_type: String = json_get(body, "type")
|
|
return "{\"ok\":true,\"submitted\":true,\"message\":\"Queued for Dharma Network\"}"
|
|
}
|
|
if str_eq(path, "/api/dharma/approve") {
|
|
let cgi_id: String = json_get(body, "cgi_id")
|
|
return "{\"ok\":true,\"approved\":true}"
|
|
}
|
|
return "{\"error\":\"unknown dharma endpoint\"}"
|
|
}
|
|
|
|
fn handle_tool(path: String, method: String, body: String) -> String {
|
|
if str_eq(path, "/api/tools/file/read") {
|
|
let file_path: String = json_get(body, "path")
|
|
if str_eq(file_path, "") {
|
|
return "{\"error\":\"path required\"}"
|
|
}
|
|
let content: String = fs_read(file_path)
|
|
let s1: String = str_replace(content, "\\", "\\\\")
|
|
let s2: String = str_replace(s1, "\"", "\\\"")
|
|
let s3: String = str_replace(s2, "\n", "\\n")
|
|
let s4: String = str_replace(s3, "\r", "\\r")
|
|
return "{\"content\":\"" + s4 + "\",\"path\":\"" + file_path + "\"}"
|
|
}
|
|
|
|
if str_eq(path, "/api/tools/file/write") {
|
|
let file_path: String = json_get(body, "path")
|
|
let content: String = json_get(body, "content")
|
|
if str_eq(file_path, "") {
|
|
return "{\"error\":\"path required\"}"
|
|
}
|
|
fs_write(file_path, content)
|
|
return "{\"ok\":true,\"path\":\"" + file_path + "\"}"
|
|
}
|
|
|
|
if str_eq(path, "/api/tools/file/list") {
|
|
let dir_path: String = json_get(body, "path")
|
|
if str_eq(dir_path, "") {
|
|
return "{\"error\":\"path required\"}"
|
|
}
|
|
let entries = fs_list(dir_path)
|
|
return "{\"entries\":" + json_stringify(entries) + "}"
|
|
}
|
|
|
|
if str_eq(path, "/api/tools/web/get") {
|
|
let url: String = json_get(body, "url")
|
|
if str_eq(url, "") {
|
|
return "{\"error\":\"url required\"}"
|
|
}
|
|
let result: String = http_get(url)
|
|
let s1: String = str_replace(result, "\\", "\\\\")
|
|
let s2: String = str_replace(s1, "\"", "\\\"")
|
|
let s3: String = str_replace(s2, "\n", "\\n")
|
|
let s4: String = str_replace(s3, "\r", "\\r")
|
|
return "{\"result\":\"" + s4 + "\"}"
|
|
}
|
|
|
|
if str_eq(path, "/api/tools/web/post") {
|
|
let url: String = json_get(body, "url")
|
|
let post_body: String = json_get(body, "body")
|
|
if str_eq(url, "") {
|
|
return "{\"error\":\"url required\"}"
|
|
}
|
|
let result: String = http_post(url, post_body)
|
|
let s1: String = str_replace(result, "\\", "\\\\")
|
|
let s2: String = str_replace(s1, "\"", "\\\"")
|
|
let s3: String = str_replace(s2, "\n", "\\n")
|
|
let s4: String = str_replace(s3, "\r", "\\r")
|
|
return "{\"result\":\"" + s4 + "\"}"
|
|
}
|
|
|
|
return "{\"error\":\"unknown tool\",\"path\":\"" + path + "\"}"
|
|
}
|
|
|
|
fn handle_nlg(path: String, method: String, body: String) -> String {
|
|
if str_eq(path, "/api/nlg/generate") {
|
|
if !str_eq(method, "POST") {
|
|
return "{\"error\":\"POST required\"}"
|
|
}
|
|
let lang_req: String = json_get(body, "lang")
|
|
let lang_code: String = if str_eq(lang_req, "") { "en" } else { lang_req }
|
|
let text: String = generate_lang(body, lang_code)
|
|
let safe: String = str_replace(text, "\"", "'")
|
|
return "{\"text\":\"" + safe + "\",\"lang\":\"" + lang_code + "\",\"ok\":true}"
|
|
}
|
|
if str_eq(path, "/api/nlg/languages") {
|
|
return "{\"languages\":[\"en\",\"es\",\"fr\",\"de\",\"ru\",\"ja\",\"fi\",\"ar\",\"hi\",\"sw\",\"la\",\"he\",\"grc\",\"ang\",\"sa\",\"got\",\"non\",\"enm\",\"pi\",\"fro\",\"goh\",\"sga\",\"txb\",\"peo\",\"akk\",\"uga\",\"egy\",\"sux\",\"gez\",\"cop\",\"zh\"],\"count\":31}"
|
|
}
|
|
return "{\"error\":\"unknown nlg path\"}"
|
|
}
|
|
|
|
fn render_studio() -> String {
|
|
let studio_dir: String = state_get("soul_studio_dir")
|
|
let html: String = fs_read(studio_dir + "/index.html")
|
|
if str_eq(html, "") {
|
|
return "<html><body style='background:#080810;color:#e8e0cf;font-family:monospace;padding:2rem'>Studio not found at " + studio_dir + "</body></html>"
|
|
}
|
|
return html
|
|
}
|