Liking cljdoc? Tell your friends :D

com.blockether.vis.internal.ctx-engine

Pure helpers for the model-facing context snapshot.

The mutable session state lives outside this namespace; these functions only advance the turn/iteration cursor, project form envelopes for persisted result messages, and compute utilization metadata.

Pure helpers for the model-facing context snapshot.

The mutable session state lives outside this namespace; these functions only
advance the turn/iteration cursor, project form envelopes for persisted
result messages, and compute utilization metadata.
raw docstring

advance-iterclj

(advance-iter ctx _form-results-vec)

Advance the cursor so the next iter starts at "iter" (current+1), "next_form" 1. Prior tool outputs are carried by append-only message history, not by mutable context state. CTX is STRING-KEYED end to end — it is bound into Python as the context dict and nippy-persisted, and both surfaces are strings-only.

Advance the cursor so the next iter starts at "iter" (current+1),
"next_form" 1. Prior tool outputs are carried by append-only message
history, not by mutable context state. CTX is STRING-KEYED end to end —
it is bound into Python as the `context` dict and nippy-persisted, and
both surfaces are strings-only.
sourceraw docstring

block->envelopeclj

(block->envelope block position cursor)
(block->envelope block _position cursor head-tag-resolver)

Project one loop-side block {:code :result :error :stdout} plus its 1-based position and the engine cursor into the form envelope shape (one block = one form, 1:1):

{:scope :tag :src :duration-ms :result :error :stdout}

:src carries the block's source text. :tag is derived from the source via classify-form-tag. :result is included only when the block has one (engine convention: drop on default/nil). :error is included only when the block errored. :stdout (what the block PRINTED) is the single display surface — channels paint it, and the model reads it back. :duration-ms is derived from the loop's block envelope so persisted TUI replays keep the same footer timing as live progress bubbles.

Every result is walked through realize-value so any IDeref (Var, atom) is derefed and lazy seqs land as data, never as #:vis{:ref :expr} placeholders left over from persistence flattening unrealized seqs.

Project one loop-side block `{:code :result :error :stdout}` plus its
1-based position and the engine cursor into the form envelope shape
(one block = one form, 1:1):

  {:scope :tag :src :duration-ms :result :error :stdout}

`:src` carries the block's source text. `:tag` is derived from the source via
`classify-form-tag`. `:result` is included only when the block has
one (engine convention: drop on default/nil). `:error` is included
only when the block errored. `:stdout` (what the block PRINTED) is the
single display surface — channels paint it, and the model reads it back.
`:duration-ms` is derived from the loop's block envelope so persisted TUI
replays keep the same footer timing as live progress bubbles.

Every result is walked through `realize-value` so any `IDeref` (Var,
atom) is derefed and lazy seqs land as data, never as
`#:vis{:ref :expr}` placeholders left over from persistence flattening
unrealized seqs.
sourceraw docstring

blocks->formsclj

(blocks->forms blocks cursor)
(blocks->forms blocks {:keys [turn iter]} head-tag-resolver)

Map a loop-side blocks vec into a vec of engine envelopes. :cursor is {:turn :iter} of THIS iter; each block gets a 1-based form position by its index in the vec.

3-arity passes head-tag-resolver (see classify-form-tag) through to every block->envelope call so extension-declared mutation tools (patch, git/commit!, any symbol with inline :tag on its vis/symbol entry) classify correctly without the engine hard-coding their symbol set.

Map a loop-side blocks vec into a vec of engine envelopes. `:cursor`
is `{:turn :iter}` of THIS iter; each block gets a 1-based form
position by its index in the vec.

3-arity passes `head-tag-resolver` (see `classify-form-tag`) through
to every `block->envelope` call so extension-declared mutation tools
(`patch`, `git/commit!`, any symbol with inline `:tag` on its
`vis/symbol` entry) classify correctly without the engine
hard-coding their symbol set.
sourceraw docstring

classify-form-tagclj

(classify-form-tag src)
(classify-form-tag src head-tag-resolver)

Classify a form-source string as :observation or :mutation.

1-arity: pure, engine-only. Returns :mutation when the head is a member of core-mutation-heads; everything else is :observation. Use this from contexts that have no access to the extension registry (tests, pure tools).

2-arity: takes head-tag-resolver, an optional fn (fn [^Symbol head]) -> :mutation | :observation | nil. The resolver wins when it returns a non-nil tag; on nil the engine falls back to core-mutation-heads. The integration layer in loop.clj builds the resolver from extension/op-tag so every extension-declared tool (patch, git/commit!, anything new an extension ships) classifies correctly without the engine hard- coding its symbol.

Classify a form-source string as `:observation` or `:mutation`.

1-arity: pure, engine-only. Returns `:mutation` when the head is a
member of `core-mutation-heads`; everything else is `:observation`.
Use this from contexts that have no access to the extension
registry (tests, pure tools).

2-arity: takes `head-tag-resolver`, an optional fn
`(fn [^Symbol head]) -> :mutation | :observation | nil`. The
resolver wins when it returns a non-nil tag; on nil the engine
falls back to `core-mutation-heads`. The integration layer in
`loop.clj` builds the resolver from `extension/op-tag` so every
extension-declared tool (`patch`, `git/commit!`, anything new an
extension ships) classifies correctly without the engine hard-
coding its symbol.
sourceraw docstring

compact-srcclj

(compact-src src)

One-line, length-capped form source — the auto-summary listing AND the renderer's src line on pre-turn <results> pins share it.

One-line, length-capped form source — the auto-summary listing AND
the renderer's src line on pre-turn `<results>` pins share it.
sourceraw docstring

DEFAULT_PROMPT_BUDGET_TOKENSclj

Soft per-call request-size guardrail surfaced to the model as session_utilization.auto_compress_above. ~72% of a typical 200k window, leaving headroom for the model's own output. Compared against PROVIDER-reported input tokens (no local tokenizer) — see utilization.

Soft per-call request-size guardrail surfaced to the model as
`session_utilization.auto_compress_above`. ~72% of a typical 200k window,
leaving headroom for the model's own output. Compared against PROVIDER-reported
input tokens (no local tokenizer) — see `utilization`.
sourceraw docstring

empty-ctxclj

(empty-ctx)
(empty-ctx session-id)

A minimal CTX scaffold with all model-facing keys filled by empty / default values. Useful as the starting point for scenario replays.

Includes the engine-ephemeral key "engine_warnings" so the rest of the system can swap! it without nil-puncturing. Stripped at persistence boundaries via strip-ephemeral.

CTX is STRING-KEYED end to end: it is bound into Python as the context dict (strings-only boundary) and nippy-persisted (strings-only DB), so there is no keyword->string projection anywhere between.

A minimal CTX scaffold with all model-facing keys filled by empty /
default values. Useful as the starting point for scenario replays.

Includes the engine-ephemeral key `"engine_warnings"` so the rest of
the system can swap! it without nil-puncturing. Stripped at
persistence boundaries via `strip-ephemeral`.

CTX is STRING-KEYED end to end: it is bound into Python as the `context`
dict (strings-only boundary) and nippy-persisted (strings-only DB), so
there is no keyword->string projection anywhere between.
sourceraw docstring

enter-turnclj

(enter-turn ctx turn-pos)

Idempotent turn-start sync. Sets :session/turn to turn-pos, resets :session/scope to {:turn turn-pos :iter 1 :next-form 1}, clears :engine/blockers, then runs gc-pass. Safe to call repeatedly with the same turn-pos (no-op semantically); safe to call when ctx was loaded fresh from DB at turn-pos > 1.

THIS is what the integration layer (vis loop) calls at the start of every turn. Single chokepoint for engine turn-state advance — no advance-turn alias, no auto-incrementing variant. The integration layer always knows the target turn-pos (DB tracks session_turn_soul.position), so the engine takes it as an explicit arg.

Idempotent turn-start sync. Sets `:session/turn` to `turn-pos`,
resets `:session/scope` to `{:turn turn-pos :iter 1 :next-form 1}`,
clears `:engine/blockers`, then runs `gc-pass`.
Safe to call repeatedly with the same `turn-pos` (no-op
semantically); safe to call when ctx was loaded fresh from DB at
turn-pos > 1.

THIS is what the integration layer (vis loop) calls at the start
of every turn. Single chokepoint for engine turn-state advance —
no `advance-turn` alias, no auto-incrementing variant. The integration
layer always knows the target turn-pos (DB tracks
`session_turn_soul.position`), so the engine takes it as an explicit
arg.
sourceraw docstring

finalize-turnclj

(finalize-turn ctx _form-scope _args)

Finalize a turn: the loop ships :answer to the channel and the engine returns ctx unchanged so the turn can settle.

Finalize a turn: the loop ships `:answer` to the channel and the engine
returns ctx unchanged so the turn can settle.
sourceraw docstring

form-head-nameclj

(form-head-name src)

Return the head call NAME (a string) of src — a Python source string — or nil when src is not a name(...) call form. Leading comments and blank lines are skipped. Reading the head name (rather than scanning the raw source) avoids false positives — a "patch(x)" inside a string can't match. Used by classify-form-tag.

Return the head call NAME (a string) of `src` — a Python source string —
or nil when `src` is not a `name(...)` call form. Leading comments and
blank lines are skipped. Reading the head name (rather than scanning the
raw source) avoids false positives — a `"patch(x)"` inside a string can't
match. Used by `classify-form-tag`.
sourceraw docstring

gc-passclj

(gc-pass ctx)

Passthrough. Tasks/facts/archive are gone — there is nothing to GC. Kept so the turn-lifecycle chokepoint (enter-turn) and any external callers stay valid.

Passthrough. Tasks/facts/archive are gone — there is nothing to GC.
Kept so the turn-lifecycle chokepoint (`enter-turn`) and any external
callers stay valid.
sourceraw docstring

malformed-scope?clj

(malformed-scope? s)

True if s is a string but does not parse as ::cs/scope-form.

True if `s` is a string but does not parse as `::cs/scope-form`.
sourceraw docstring

model-facing-keysclj

EXACT set of session_* keys the model is meant to see. This is the SINGLE definition of 'model-facing'; session-view selects on it so engine bookkeeping cannot leak into the rendered <context> or bound context dict. "session_utilization" is derived (from "engine_utilization"), so it is folded in by session-view rather than listed here.

EXACT set of `session_*` keys the model is meant to see. This is the
SINGLE definition of 'model-facing'; `session-view` selects on it so engine
bookkeeping cannot leak into the rendered `<context>` or bound `context`
dict. `"session_utilization"` is derived (from `"engine_utilization"`),
so it is folded in by `session-view` rather than listed here.
sourceraw docstring

model-form-envelopeclj

(model-form-envelope r)

Project one executed-form envelope onto the MODEL contract the trailer stores: :scope :src :result :error (+ engine forensic fields), WITHOUT the channel sink slice, the host failure/metadata chains, or :tag. The mutation/observation tag stays load-bearing on LIVE op envelopes and on the persisted rows — but NOTHING reads it from the trailer (the observation-prune that once did was removed), and the model can see what a form does from :src. The full envelopes stay on the progress chunks and the persisted session_turn_iteration.forms rows — channels and the persisted forms rows keep total fidelity; the trailer is what rides every prompt.

Empty payloads are DROPPED, not rendered: "result": None / [] / {} and empty :error maps say nothing the form's absence of an error/result doesn't already say — the :src stays, the dead field goes.

Project one executed-form envelope onto the MODEL contract the
trailer stores: `:scope :src :result :error` (+ engine forensic
fields), WITHOUT the channel sink slice, the host failure/metadata
chains, or `:tag`. The mutation/observation tag stays load-bearing
on LIVE op envelopes and on the persisted rows — but NOTHING reads
it from the trailer (the observation-prune that once did was
removed), and the model can see what a form does from `:src`. The
full envelopes stay on the progress chunks and the persisted
`session_turn_iteration.forms` rows — channels and the persisted
forms rows keep total fidelity; the trailer is what rides every
prompt.

Empty payloads are DROPPED, not rendered: `"result": None` /
`[]` / `{}` and empty `:error` maps say nothing the form's absence
of an error/result doesn't already say — the `:src` stays, the dead
field goes.
sourceraw docstring

parse-scope-formclj

(parse-scope-form s)

Parse a tN/iM (or legacy tN/iM/fK) scope into {:turn :iter :form} or nil if malformed. :form is nil for an iteration-level scope. Pure value-or-nil.

Parse a `tN/iM` (or legacy `tN/iM/fK`) scope into `{:turn :iter :form}` or nil
if malformed. `:form` is nil for an iteration-level scope. Pure value-or-nil.
sourceraw docstring

scope-compareclj

(scope-compare a b)

Total order on form-scope strings by (turn, iter, form). Returns int. Compares parsed segments; malformed scopes sort before all valid ones to make their presence obvious in render.

Total order on form-scope strings by (turn, iter, form). Returns int.
Compares parsed segments; malformed scopes sort before all valid ones to
make their presence obvious in render.
sourceraw docstring

session-viewclj

(session-view ctx)
(session-view ctx _warnings)

THE single projection from engine-internal ctx to the model-facing session_* view.

Both consumers derive from this, so the rendered <context> block and the Python context dict are the same map by construction:

  • ctx-renderer/render-ctx serializes this view
  • ctx-loop/session-snapshot binds this view as read-only context

Keeps ONLY model-facing-keys (so engine bookkeeping never leaks) and projects "engine_utilization""session_utilization". The second arity takes legacy warnings for call-site compatibility but ignores them. Pure; STRING keys in and out.

THE single projection from engine-internal ctx to the model-facing
`session_*` view.

Both consumers derive from this, so the rendered `<context>` block and the
Python `context` dict are the same map by construction:
  - `ctx-renderer/render-ctx` serializes this view
  - `ctx-loop/session-snapshot` binds this view as read-only `context`

Keeps ONLY `model-facing-keys` (so engine bookkeeping never leaks) and
projects `"engine_utilization"` → `"session_utilization"`. The second
arity takes legacy `warnings` for call-site compatibility but ignores them.
Pure; STRING keys in and out.
sourceraw docstring

strip-ephemeralclj

(strip-ephemeral ctx)

Remove every "engine_*" key from a ctx. Call before Nippy-snapshotting to persistence so transient mutator state (warnings, pending satisfy requests) does not leak into the durable record.

Remove every `"engine_*"` key from a ctx. Call before Nippy-snapshotting
to persistence so transient mutator state (warnings, pending satisfy
requests) does not leak into the durable record.
sourceraw docstring

utilizationclj

(utilization request-tokens window-tokens turn-tokens fold-cap)

Pure: the "session_utilization" map the model reads to see how much of the context window the LAST request consumed. Keys are spelled out so they can't be misread: last_request_tokens input size of the most recent model call model_input_limit HARD per-call ceiling (provider rejects above) saturation last-request / model-input-limit, as a rounded percentage — how FULL the per-call window is headroom_tokens tokens still free before the ceiling (model_input_limit - last request); the actionable 'can I keep going or must I fold?' auto_compress_above soft guardrail threshold for request size turn_total_tokens cumulative input this turn (billing, NOT a per-call limit — may exceed the limit safely) Returns nil until a request has actually been measured (req <= 0), so the first iter of a turn shows nothing rather than a bogus 0%.

Pure: the `"session_utilization"` map the model reads to see how much
of the context window the LAST request consumed. Keys are spelled out
so they can't be misread:
  last_request_tokens  input size of the most recent model call
  model_input_limit    HARD per-call ceiling (provider rejects above)
  saturation           last-request / model-input-limit, as a rounded
                       percentage — how FULL the per-call window is
  headroom_tokens      tokens still free before the ceiling
                       (model_input_limit - last request); the
                       actionable 'can I keep going or must I fold?'
  auto_compress_above  soft guardrail threshold for request size
  turn_total_tokens    cumulative input this turn (billing, NOT a
                       per-call limit — may exceed the limit safely)
Returns nil until a request has actually been measured (req <= 0), so
the first iter of a turn shows nothing rather than a bogus 0%.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close