Commit 22290cc

mo khan <mo@mokhan.ca>
2026-09-05 19:11:55
fix: stop littering the working directory with session logs
Every invocation wrote .elelem/sessions/ into the current directory unconditionally -- a coding agent run from inside a project would leave that behind in every repo it ever touched. Move session logs and transcripts to $XDG_STATE_HOME/elelem/sessions (~/.local/state by default). Also unify the env var surface ahead of freezing it: LOG_LEVEL (read separately by Ruby and the C++ shim) becomes ELELEM_LOG_LEVEL, and the legacy ELELEM_GGML_VULKAN opt-in is dropped in favor of ELELEM_LLAMA_BACKEND=vulkan. Requires io-console explicitly (terminal.rb calls $stdout.winsize; it only worked because Reline happened to pull the library in). Claude-Session: https://claude.ai/code/session_01FpbgyAMtPEkDbo2kx78qR6
1 parent 7a05c07
Changed files (1)
ext
elelem
ext/elelem/llama/elelem_llama.cpp
@@ -45,10 +45,10 @@ struct el_handle {
 
 static bool g_backend = false;
 
-// llama.cpp/ggml log to stderr by default; gate that behind LOG_LEVEL so
+// llama.cpp/ggml log to stderr by default; gate that behind ELELEM_LOG_LEVEL so
 // GGUF model loads aren't noisy unless a caller opts in, matching the
 // verbosity Elelem.logger is configured with in lib/elelem.rb.
-// Read once: LOG_LEVEL can't change mid-process, and this ran per log line.
+// Read once: the env var can't change mid-process, and this ran per log line.
 static enum ggml_log_level el_log_threshold() {
     static const enum ggml_log_level cached = [] {
         const char *level = std::getenv("ELELEM_LOG_LEVEL");
@@ -74,13 +74,27 @@ static void el_log_callback(enum ggml_log_level level, const char *text, void *
 // thousand tokens), so give up rather than silently hand back a useless handle.
 static const int EL_MIN_CTX = 4096;
 
-// n_ctx <= 0 means "auto": ask llama.cpp for the model's trained max (n_ctx=0
-// is documented as "from model" in llama.h) rather than guessing from a memory
-// formula -- a formula sized for plain transformer KV would badly overestimate
-// footprint for hybrid/recurrent-state architectures (e.g. Qwen3.5's Gated
-// DeltaNet layers hold fixed-size state, not per-token KV). If the resulting
-// context still doesn't fit (llama_init_from_model returns null -- OOM or
-// unsupported size), retry at half the size down to EL_MIN_CTX; this is
+// Ceiling on the *initial* auto-sized request. llama_init_from_model succeeding
+// only proves the KV cache itself fit -- it reserves nothing for the compute
+// buffer a large prompt's prefill batch needs, so asking for a model's full
+// trained max (some ship 256K+) can leave a GPU with just enough VRAM for KV
+// and none for that buffer, failing later and unrecoverably inside a decode
+// instead of here. 65536 comfortably covers real agent sessions (a handful of
+// large files plus history) while leaving GPU headroom for prefill scratch
+// space; models with a smaller trained max are unaffected since the min() below
+// only ever shrinks the request. Applied on CPU too, unconditionally: one
+// constant is simpler than branching on backend, and a context this large is
+// already impractically slow to prefill on CPU regardless of whether it fits.
+static const int EL_MAX_AUTO_CTX = 65536;
+
+// n_ctx <= 0 means "auto": ask llama.cpp for the model's trained max, capped at
+// EL_MAX_AUTO_CTX (n_ctx=0 alone is documented as "from model" in llama.h, but
+// see EL_MAX_AUTO_CTX for why that alone is not a safe default) -- rather than
+// guessing from a memory formula, which for hybrid/recurrent-state
+// architectures (e.g. Qwen3.5's Gated DeltaNet layers hold fixed-size state,
+// not per-token KV) would badly over- or under-estimate footprint. If the
+// resulting context still doesn't fit (llama_init_from_model returns null --
+// OOM or unsupported size), retry at half the size down to EL_MIN_CTX; this is
 // correct for every architecture because it measures the actual allocation
 // instead of predicting it.
 static llama_context *el_init_context(llama_model *model, int n_ctx, int n_threads) {