/* * el_seed.h — El language seed runtime header * * Declares all OS-boundary primitives available to compiled El programs. * All functions use the __ prefix convention. Signatures use el_val_t (= int64_t) * as the universal value type. * * el_seed.c is the complete C boundary for the El runtime. The heavy runtime * (el_runtime.c) has been retired — everything lives in el_seed.c plus the * native El runtime (runtime/ *.el files). * * Link requirements: * -lcurl — HTTP client (__http_do, __http_do_to_file) * -lpthread — threading (__thread_create, __thread_join, __mutex_new, ...) * * Canonical compile (via elb): * elb builds and links el_seed.c automatically. */ #pragma once #include #include /* ── Value model ───────────────────────────────────────────────────────────── * All El values are el_val_t (int64_t). On 64-bit systems a pointer fits. * String -> el_val_t (holds const char* via uintptr_t cast) * Int -> el_val_t (stored directly) * Bool -> el_val_t (0 = false, nonzero = true) * Void -> void */ typedef int64_t el_val_t; #define EL_STR(s) ((el_val_t)(uintptr_t)(s)) #define EL_CSTR(v) ((const char*)(uintptr_t)(v)) #define EL_INT(v) (v) #define EL_NULL ((el_val_t)0) /* Float values share the el_val_t slot via bit-cast. */ static inline double el_to_float(el_val_t v) { union { int64_t i; double f; } u; u.i = (int64_t)v; return u.f; } static inline el_val_t el_from_float(double f) { union { double f; int64_t i; } u; u.f = f; return (el_val_t)u.i; } #ifdef __cplusplus extern "C" { #endif /* ── String primitives ───────────────────────────────────────────────────── */ el_val_t __str_len(el_val_t s); el_val_t __str_char_at(el_val_t s, el_val_t i); /* returns Int (byte value) */ el_val_t __str_alloc(el_val_t n); /* malloc(n+1), zero-init, return String */ el_val_t __str_set_char(el_val_t s, el_val_t i, el_val_t c); /* s[i]=c, return s */ el_val_t __str_cmp(el_val_t a, el_val_t b); /* strcmp result as Int */ el_val_t __str_ncmp(el_val_t a, el_val_t b, el_val_t n); /* strncmp */ el_val_t __str_concat_raw(el_val_t a, el_val_t b); /* malloc+strcpy concat */ el_val_t __str_slice_raw(el_val_t s, el_val_t start, el_val_t end); /* substring copy */ el_val_t __int_to_str(el_val_t n); el_val_t __str_to_int(el_val_t s); el_val_t __float_to_str(el_val_t f); /* f is bit-cast double */ el_val_t __str_to_float(el_val_t s); /* strtod, bit-cast result */ /* ── I/O ─────────────────────────────────────────────────────────────────── */ void __println(el_val_t s); void __print(el_val_t s); el_val_t __readline(void); /* ── Filesystem ──────────────────────────────────────────────────────────── */ el_val_t __fs_read(el_val_t path); el_val_t __fs_write(el_val_t path, el_val_t content); el_val_t __fs_exists(el_val_t path); el_val_t __fs_list_raw(el_val_t path); /* newline-separated filenames */ el_val_t __fs_mkdir(el_val_t path); el_val_t __fs_write_bytes(el_val_t path, el_val_t bytes, el_val_t n); /* ── HTTP client ─────────────────────────────────────────────────────────── */ /* Unified HTTP call. headers_json is a JSON object of header name->value pairs * (e.g. {"Authorization":"Bearer ...","Content-Type":"application/json"}). * Use "" or "{}" for no extra headers. timeout_ms <= 0 uses the default. */ el_val_t __http_do(el_val_t method, el_val_t url, el_val_t body, el_val_t headers_json, el_val_t timeout_ms); /* Stream response body directly to a file. Returns 1 on success, 0 on failure. */ el_val_t __http_do_to_file(el_val_t method, el_val_t url, el_val_t body, el_val_t headers_json, el_val_t out_path); /* ── HTTP server ─────────────────────────────────────────────────────────── */ /* Blocking HTTP server. handler_name is the El function name to dispatch to. * v1 handler: (method, path, body) -> String * v2 handler: (method, path, headers_map, body) -> String or envelope */ void __http_serve(el_val_t port, el_val_t handler_name); void __http_serve_v2(el_val_t port, el_val_t handler_name); /* Build a structured HTTP response envelope. * headers_json: JSON object literal like {"Content-Type":"text/plain"} or "{}" */ el_val_t __http_response(el_val_t status, el_val_t headers_json, el_val_t body); /* ── HTTP SSE — Server-Sent Events streaming ─────────────────────────────── */ /* Returns the raw file descriptor for the current HTTP connection. * Valid only inside an http_serve_v2 handler before it returns. * Returns -1 if called outside a handler context. */ el_val_t __http_conn_fd(void); /* Sends SSE response headers on conn_id (the fd from __http_conn_fd), * keeping the connection open for streaming. Returns 1 on success, 0 on * write failure. Call once at the start of an SSE handler. */ el_val_t __http_sse_open(el_val_t conn_id); /* Writes one SSE event frame: "data: \n\n". data must not contain * newlines. Returns 1 on success, 0 if the client disconnected. */ el_val_t __http_sse_send(el_val_t conn_id, el_val_t data); /* Closes the SSE connection. The handler must return http_sse_sentinel() * so the HTTP worker does not double-close the fd. */ el_val_t __http_sse_close(el_val_t conn_id); /* ── Threading ───────────────────────────────────────────────────────────── */ /* Create a thread that calls the named El function with a String argument. * fn_name is resolved via dlsym(RTLD_DEFAULT, fn_name). Returns a thread * handle Int that can be passed to __thread_join. Returns -1 on failure. */ el_val_t __thread_create(el_val_t fn_name, el_val_t arg); /* Wait for thread tid (returned by __thread_create) to finish. * Returns the thread's return value as a String. */ el_val_t __thread_join(el_val_t tid); /* Allocate a new mutex. Returns a handle Int (index into internal table). */ el_val_t __mutex_new(void); void __mutex_lock(el_val_t m); void __mutex_unlock(el_val_t m); /* ── Subprocess ──────────────────────────────────────────────────────────── */ el_val_t __exec(el_val_t cmd); /* popen, capture all stdout, return String */ void __exec_bg(el_val_t cmd); /* fire and forget */ /* ── Environment and process ─────────────────────────────────────────────── */ el_val_t __env_get(el_val_t key); /* getenv, return "" if not set */ void __exit_program(el_val_t code); el_val_t __args_json(void); /* CLI args as JSON array string */ /* ── Time ────────────────────────────────────────────────────────────────── */ el_val_t __time_now_ns(void); /* clock_gettime REALTIME, nanoseconds */ void __sleep_ms(el_val_t ms); /* ── UUID ────────────────────────────────────────────────────────────────── */ el_val_t __uuid_v4(void); /* ── Math ────────────────────────────────────────────────────────────────── */ el_val_t __sqrt_f(el_val_t f); el_val_t __log_f(el_val_t f); el_val_t __ln_f(el_val_t f); el_val_t __sin_f(el_val_t f); el_val_t __cos_f(el_val_t f); el_val_t __pi_f(void); /* ── JSON ────────────────────────────────────────────────────────────────── */ el_val_t __json_get(el_val_t json, el_val_t key); el_val_t __json_get_raw(el_val_t json_str, el_val_t key); el_val_t __json_parse(el_val_t s); el_val_t __json_stringify(el_val_t v); el_val_t __json_parse_map(el_val_t json_str); /* alias for __json_parse */ el_val_t __json_stringify_val(el_val_t val); /* alias for __json_stringify */ el_val_t __json_array_len(el_val_t json_str); el_val_t __json_array_get(el_val_t json_str, el_val_t index); el_val_t __json_array_get_string(el_val_t json_str, el_val_t index); el_val_t __json_get_string(el_val_t json_str, el_val_t key); el_val_t __json_get_int(el_val_t json_str, el_val_t key); el_val_t __json_get_float(el_val_t json_str, el_val_t key); el_val_t __json_get_bool(el_val_t json_str, el_val_t key); el_val_t __json_set(el_val_t json_str, el_val_t key, el_val_t value); /* ── State K/V ───────────────────────────────────────────────────────────── */ el_val_t __state_set(el_val_t key, el_val_t value); el_val_t __state_get(el_val_t key); el_val_t __state_del(el_val_t key); el_val_t __state_keys(void); /* ── HTML/URL ────────────────────────────────────────────────────────────── */ el_val_t __html_sanitize(el_val_t input_html, el_val_t allowlist_json); el_val_t __url_encode(el_val_t s); el_val_t __url_decode(el_val_t s); /* ── Engram ──────────────────────────────────────────────────────────────── */ el_val_t __engram_node(el_val_t content, el_val_t node_type, el_val_t salience); el_val_t __engram_node_full(el_val_t content, el_val_t node_type, el_val_t label, el_val_t salience, el_val_t importance, el_val_t confidence, el_val_t tier, el_val_t tags); el_val_t __engram_node_layered(el_val_t content, el_val_t node_type, el_val_t label, el_val_t salience, el_val_t certainty, el_val_t confidence, el_val_t status, el_val_t tags, el_val_t layer_id); el_val_t __engram_add_layer(el_val_t name, el_val_t priority, el_val_t suppressible, el_val_t transparent, el_val_t injectable); el_val_t __engram_remove_layer(el_val_t layer_id); el_val_t __engram_list_layers(void); el_val_t __engram_get_node(el_val_t id); void __engram_strengthen(el_val_t node_id); void __engram_forget(el_val_t node_id); el_val_t __engram_node_count(void); el_val_t __engram_search(el_val_t query, el_val_t limit); el_val_t __engram_scan_nodes(el_val_t limit, el_val_t offset); void __engram_connect(el_val_t from_id, el_val_t to_id, el_val_t weight, el_val_t relation); el_val_t __engram_edge_between(el_val_t from_id, el_val_t to_id); el_val_t __engram_neighbors(el_val_t node_id); el_val_t __engram_neighbors_filtered(el_val_t node_id, el_val_t max_depth, el_val_t direction); el_val_t __engram_edge_count(void); el_val_t __engram_activate(el_val_t query, el_val_t depth); el_val_t __engram_save(el_val_t path); el_val_t __engram_load(el_val_t path); el_val_t __engram_get_node_json(el_val_t id); el_val_t __engram_get_node_by_label(el_val_t label); el_val_t __engram_search_json(el_val_t query, el_val_t limit); el_val_t __engram_scan_nodes_json(el_val_t limit, el_val_t offset); el_val_t __engram_scan_nodes_by_type_json(el_val_t node_type, el_val_t limit, el_val_t offset); el_val_t __engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction); el_val_t __engram_activate_json(el_val_t query, el_val_t depth); el_val_t __engram_stats_json(void); el_val_t __engram_list_layers_json(void); el_val_t __engram_compile_layered_json(el_val_t intent, el_val_t depth); /* ── Cryptographic hashing ────────────────────────────────────────────────── */ /* __sha256_hex — return the SHA-256 hex digest of a string. * The returned string is 64 hex characters (lowercase). */ el_val_t __sha256_hex(el_val_t s); /* ── args init (called from main) ────────────────────────────────────────── */ /* Store argc/argv for __args_json. Call once at the start of main(). */ void el_seed_init_args(int argc, char** argv); #ifdef __cplusplus } #endif