Loop integration layer for context management.
The loop keeps a per-session :ctx-atom for stable model-facing context
and a separate :turn-state-atom for live turn/iteration/form counters.
This namespace stamps the cursor, enriches context with env/resources/routing,
and renders the standing context block.
Loop integration layer for context management. The loop keeps a per-session `:ctx-atom` for stable model-facing context and a separate `:turn-state-atom` for live turn/iteration/form counters. This namespace stamps the cursor, enriches context with env/resources/routing, and renders the standing context block.
(current-ctx {:keys [ctx-atom] :as env})Deref the CTX atom with both :session/turn and :session/scope
stamped from the loop counters. This is the shape passed to the
renderer + derive-warnings. Returns nil when ctx-atom is missing
on env (defensive for partial test envs).
Deref the CTX atom with both `:session/turn` and `:session/scope` stamped from the loop counters. This is the shape passed to the renderer + `derive-warnings`. Returns nil when ctx-atom is missing on env (defensive for partial test envs).
(cursor-snapshot env)Build a "session_scope" map from :turn-state-atom. Mirrors the
engine's {"turn" "iter" "next_form"} shape (STRING keys — the ctx
crosses the Python boundary) used by classify-scope and the renderer.
Build a `"session_scope"` map from `:turn-state-atom`. Mirrors the
engine's `{"turn" "iter" "next_form"}` shape (STRING keys — the ctx
crosses the Python boundary) used by `classify-scope` and the renderer.(drain-warnings! _env)Compatibility shim for the former warning drain. Always returns [] so the renderer's between-iters call site stays valid.
Compatibility shim for the former warning drain. Always returns [] so the renderer's between-iters call site stays valid.
(enrich-ctx env ctx)Merge extension ctx contributions + live env/resource/routing enrichments into the raw ctx-atom value, producing the model-facing shape.
THE single enrichment path — BOTH the rendered <context> TEXT
(render-block!) and the live session dict bound in the sandbox
(session-snapshot) derive from this. Keeping it in ONE place is
load-bearing: when the two paths computed different shapes, the model saw
keys in the text that KeyError'd in code. That is exactly how
session["workspace"] (and workspace["filesystem_roots"]) went missing
from the bound dict — the ext-contributed "session_workspace" block was
merged into the TEXT but not into the binding. Merge ALL ext-ctx so no
future contributed key can drift the same way.
Recomputed each call so transient extension/env/resource/routing state stays
fresh without pushing it back into ctx-atom.
Merge extension ctx contributions + live env/resource/routing enrichments into the raw ctx-atom value, producing the model-facing shape. THE single enrichment path — BOTH the rendered `<context>` TEXT (`render-block!`) and the live `session` dict bound in the sandbox (`session-snapshot`) derive from this. Keeping it in ONE place is load-bearing: when the two paths computed different shapes, the model saw keys in the text that KeyError'd in code. That is exactly how `session["workspace"]` (and `workspace["filesystem_roots"]`) went missing from the bound dict — the ext-contributed `"session_workspace"` block was merged into the TEXT but not into the binding. Merge ALL ext-ctx so no future contributed key can drift the same way. Recomputed each call so transient extension/env/resource/routing state stays fresh without pushing it back into `ctx-atom`.
(finalize-turn! {:keys [ctx-atom] :as env}
{:keys [answer user-request turn-summary]})Side-effecting turn finalizer; compaction is the standalone session_fold verb.
Returns the intent map plus warnings.
Side-effecting turn finalizer; compaction is the standalone `session_fold` verb. Returns the intent map plus warnings.
(make-ctx-atom)(make-ctx-atom session-id)Initialize the CTX atom for a session. Uses the canonical empty scaffold.
The scaffold carries an empty "engine_warnings" vec so every swap!
path can update it without nil-puncturing.
Initialize the CTX atom for a session. Uses the canonical empty scaffold. The scaffold carries an empty `"engine_warnings"` vec so every swap! path can `update` it without nil-puncturing.
(make-turn-state-atom)Initialize the per-session turn-state atom. Holds every cursor + DB-id field the iteration loop and ctx-loop helpers consume.
Initialize the per-session turn-state atom. Holds every cursor + DB-id field the iteration loop and ctx-loop helpers consume.
(read-turn-state env)Deref the turn-state map or {} when atom is missing.
Deref the turn-state map or {} when atom is missing.
(render-block! env renderer-fn)Build the standing <context> block for the next user message. Pure data
flow, with extension/env/resource/routing enrichments recomputed each render
so transient state stays fresh without pushing it back into ctx-atom.
Build the standing `<context>` block for the next user message. Pure data flow, with extension/env/resource/routing enrichments recomputed each render so transient state stays fresh without pushing it back into `ctx-atom`.
(session-snapshot env)Read-only data mirror of the Python session dict bound in the sandbox.
Built to MATCH the rendered shape, NOT the raw atom: stamps the live cursor,
runs the shared enrich-ctx (so workspace/env/resources/routing are present
exactly as in the rendered <context> TEXT), then delegates to the canonical
eng/session-view projection. Returns nil when ctx-atom is absent.
Read-only data mirror of the Python `session` dict bound in the sandbox. Built to MATCH the rendered shape, NOT the raw atom: stamps the live cursor, runs the shared `enrich-ctx` (so workspace/env/resources/routing are present exactly as in the rendered `<context>` TEXT), then delegates to the canonical `eng/session-view` projection. Returns nil when ctx-atom is absent.
(set-turn-state! env & kvs)swap! assoc shortcut for one or more turn-state keys.
swap! `assoc` shortcut for one or more turn-state keys.
(stamp-cursor env ctx)Return a ctx map with both "session_turn" and "session_scope" synced
from the loop's running counters. Render path + every engine derivation
call goes through this so the model never sees a stale top-level
"session_turn" (e.g. after a resume that loaded turn N's snapshot but
the current loop is on turn N+1).
Return a ctx map with both `"session_turn"` and `"session_scope"` synced from the loop's running counters. Render path + every engine derivation call goes through this so the model never sees a stale top-level `"session_turn"` (e.g. after a resume that loaded turn N's snapshot but the current loop is on turn N+1).
(swap-turn-state! env f & args)swap! the turn-state map. Returns the new state. No-op if no atom on env.
swap! the turn-state map. Returns the new state. No-op if no atom on env.
(synthesize-scope env)Build the current form scope tN/iM/fK from :turn-state-atom.
Defaults each field to 1 (form-idx defaults to 0 → next-form 1) so
the helper is safe to call before the loop has initialised the
atom (e.g. early hooks).
Build the current form scope `tN/iM/fK` from `:turn-state-atom`. Defaults each field to 1 (form-idx defaults to 0 → next-form 1) so the helper is safe to call before the loop has initialised the atom (e.g. early hooks).
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |