Liking cljdoc? Tell your friends :D

com.blockether.vis.internal.python.env

The agent's action substrate: an embedded CPython the model writes Python for.

A SESSION here owns one worker process and one embedded interpreter. Its sandbox namespace and trusted extension namespaces share that interpreter, while another session has another process, import table and native-library cache. A one-shot CLI session may run in the process it already owns.

Three rules shape everything below. One dialect crosses the boundary: JSON, in both directions — host to guest is a json.loads of a literal this namespace renders, guest to host is python-host's envelope. The guest's Python is a FILE, never a string built here: the runtime ships the sandbox runtime, auto-imports, network probe and process redirect as modules it imports, and Vis' own guest code lives under resources/vis-guest/. The boundaries are native: the worker's OS jail owns filesystem and egress confinement, while the runtime audit hook is the fail-closed file/socket backstop before policy setup. Python modules provide ergonomics, never security.

Public surface used by the loop:

create-python-context / dispose-python-context! / retire-python-context! / interrupt-guest! / take-partial-block-stdout! / python-worker-pids / set-python-binding! / bind-and-bump! / count-top-level-forms / validate-no-banned-defs! / run-python-block / persist-session-defs! / restore-session-defs! / forget-session-defs! / SYSTEM_VAR_NAMES / system-var-sym? / boundary-view / ctx->python-str / bind-ctx!

The agent's action substrate: an embedded CPython the model writes Python for.

A SESSION here owns one worker process and one embedded interpreter. Its
sandbox namespace and trusted extension namespaces share that interpreter,
while another session has another process, import table and native-library
cache. A one-shot CLI session may run in the process it already owns.

Three rules shape everything below. **One dialect crosses the boundary:**
JSON, in both directions — host to guest is a `json.loads` of a literal this
namespace renders, guest to host is `python-host`'s envelope. **The guest's
Python is a FILE**, never a string built here: the runtime ships the sandbox
runtime, auto-imports, network probe and process redirect as modules it imports,
and Vis' own guest code lives under `resources/vis-guest/`. **The boundaries are
native:** the worker's OS jail owns filesystem and egress confinement, while the
runtime audit hook is the fail-closed file/socket backstop before policy setup.
Python modules provide ergonomics, never security.

Public surface used by the loop:

  create-python-context / dispose-python-context! / retire-python-context! /
  interrupt-guest! / take-partial-block-stdout! / python-worker-pids /
  set-python-binding! / bind-and-bump! / count-top-level-forms /
  validate-no-banned-defs! / run-python-block / persist-session-defs! /
  restore-session-defs! / forget-session-defs! /
  SYSTEM_VAR_NAMES / system-var-sym? / boundary-view / ctx->python-str / bind-ctx!
raw docstring

*auto-repair-brackets?*clj

When true, a bracket-balance syntax hint ALSO appends repair-bracket-balance's single-candidate suggested fix. OFF by default: the walker only DIAGNOSES; the auto-fix stays gated behind this flag until proven safe in the wild.

When true, a bracket-balance syntax hint ALSO appends `repair-bracket-balance`'s
single-candidate suggested fix. OFF by default: the walker only DIAGNOSES; the
auto-fix stays gated behind this flag until proven safe in the wild.
sourceraw docstring

AUTO_IMPORTED_PYTHON_NAMESclj

Python names installed into builtins for every python_execution context. This is the model-facing inventory; keep it synchronized with auto-imports-python and its real-context regression test.

Python names installed into builtins for every `python_execution` context.
This is the model-facing inventory; keep it synchronized with
`auto-imports-python` and its real-context regression test.
sourceraw docstring

BANNED_DEF_HEADSclj

Python constructs refused pre-eval — belt-and-suspenders against the obvious sandbox-escape footguns on top of the interpreter's own confinement.

Python constructs refused pre-eval — belt-and-suspenders against the obvious
sandbox-escape footguns on top of the interpreter's own confinement.
sourceraw docstring

bind-and-bump!clj

(bind-and-bump! env sym val)

Set sym -> val in the env's sandbox.

Set `sym` -> `val` in the env's sandbox.
sourceraw docstring

bind-ctx!clj

(bind-ctx! session data)

Refresh session and prebound Paths from workspace.root and filesystem_roots.

project_root_path always points at the working workspace (or the host working directory for a standalone context). Each filesystem root's python_name binds its working cwd, sharing the prompt's exact entries. Removed names disappear; new names cannot overwrite tools or user variables. All are host-owned: block-local shadows cannot replace later blocks' bindings.

Refresh `session` and prebound Paths from workspace.root and filesystem_roots.

`project_root_path` always points at the working workspace (or the host working
directory for a standalone context). Each filesystem root's `python_name` binds
its working `cwd`, sharing the prompt's exact entries. Removed names disappear;
new names cannot overwrite tools or user variables.
All are host-owned: block-local shadows cannot replace later blocks' bindings.
sourceraw docstring

boundary-viewclj

(boundary-view x)
(boundary-view x path)

What a plain-data Clojure value LOOKS LIKE after the CPython round trip — the mechanical composition of ->py then ->clj without a Python context. STRINGS-ONLY: string map keys pass VERBATIM, sets/seqs -> vectors, UUID/Temporal/Date leaves -> ISO strings. A keyword/symbol anywhere (key or value, any depth) throws boundary-violation! exactly like the real boundary — fix the producer fixture, never catch it. Idempotent.

Every tool result the model sees in production (serialized structurally by ctx-renderer/render-form-value) has already crossed this boundary, so assertions about what the model reads MUST be written against THIS shape. Tests feed (boundary-view raw-result) to pin that contract without booting CPython.

What a plain-data Clojure value LOOKS LIKE after the CPython round trip —
the mechanical composition of `->py` then `->clj` without a Python context.
STRINGS-ONLY: string map keys pass VERBATIM, sets/seqs -> vectors,
UUID/Temporal/Date leaves -> ISO strings. A keyword/symbol anywhere (key or
value, any depth) throws `boundary-violation!` exactly like the real
boundary — fix the producer fixture, never catch it. Idempotent.

Every tool result the model sees in production (serialized structurally
by `ctx-renderer/render-form-value`) has already crossed this boundary,
so assertions about what the model reads MUST be written against THIS
shape. Tests feed `(boundary-view raw-result)` to pin that contract
without booting CPython.
sourceraw docstring

boundary-violation!clj

(boundary-violation! kind x path)

Throw on a keyword/symbol trying to cross the Clojure->Python boundary. The boundary is STRINGS-ONLY: every map that crosses (tool results, ctx, verb payloads) is built with string keys and string enum values at the SOURCE — there is no silent keyword->string conversion, so a keyword here means a producer bug, not data. path is the key path down from the value handed to ->py, so the offending producer field is nameable.

The message ALWAYS says WHERE: an empty path means the offending key sits on the value handed to the boundary itself, and a bare :result/:success? there is vis' own internal envelope — the producer must hand Python the PAYLOAD (:result), never the envelope that wraps it. Without that clause a report reads non-string-key :result with no location at all.

Throw on a keyword/symbol trying to cross the Clojure->Python boundary.
The boundary is STRINGS-ONLY: every map that crosses (tool results, ctx,
verb payloads) is built with string keys and string enum values at the
SOURCE — there is no silent keyword->string conversion, so a keyword here
means a producer bug, not data. `path` is the key path down from the value
handed to `->py`, so the offending producer field is nameable.

The message ALWAYS says WHERE: an empty path means the offending key sits on
the value handed to the boundary itself, and a bare `:result`/`:success?`
there is vis' own internal envelope — the producer must hand Python the
PAYLOAD (`:result`), never the envelope that wraps it. Without that clause a
report reads `non-string-key :result` with no location at all.
sourceraw docstring

context-enterable?clj

(context-enterable? environment)

Can the loop still run guest code in this environment?

False once the session was disposed or its worker was retired, or when the environment carries no sandbox at all.

An environment whose sandbox is not built YET is enterable: entering is what builds it. Answering this question must never start an interpreter, so a sandbox that does not exist is judged by retirement alone — the disposed set is keyed by session, and a session that was never created cannot be in it.

Can the loop still run guest code in this environment?

False once the session was disposed or its worker was retired, or when the
environment carries no sandbox at all.

An environment whose sandbox is not built YET is enterable: entering is what
builds it. Answering this question must never start an interpreter, so a
sandbox that does not exist is judged by retirement alone — the disposed set
is keyed by session, and a session that was never created cannot be in it.
sourceraw docstring

count-top-level-formsclj

(count-top-level-forms session code)

Number of top-level Python statements in code, counted by the session's own parser. Comment- or whitespace-only blocks answer 0.

Source the parser REFUSES throws that SyntaxError: an empty block and an unparseable one are different outcomes, and swallowing the refusal here would answer 0 for both — reporting nothing to execute for a real syntax error.

Number of top-level Python statements in `code`, counted by the session's own
parser. Comment- or whitespace-only blocks answer 0.

Source the parser REFUSES throws that SyntaxError: an empty block and an
unparseable one are different outcomes, and swallowing the refusal here would
answer 0 for both — reporting `nothing to execute` for a real syntax error.
sourceraw docstring

create-python-contextclj

(create-python-context custom-bindings roots-fn network-opts stdin)

Equip ONE session with the sandbox and answer {:python-context :sandbox-ns :initial-ns-keys}.

custom-bindings is {symbol value} — a function becomes a host tool, any other value crosses as data. roots-fn answers the directories the guest may read and write; without it the interpreter keeps whatever policy the process already had. network-opts carries the egress rules. stdin is what the guest reads from sys.stdin, or nil for none.

The order matters and is the same order it has always been: the runtime first, then the names the block may not overwrite, then the tools, then the contracts those tools carry, then discovery, then policy — so every __vis_* name and every seeded module is already BASELINE when the member snapshot is taken, and the model's live-vars view shows only what its own blocks made.

Equip ONE session with the sandbox and answer
`{:python-context :sandbox-ns :initial-ns-keys}`.

`custom-bindings` is `{symbol value}` — a function becomes a host tool, any
other value crosses as data. `roots-fn` answers the directories the guest may
read and write; without it the interpreter keeps whatever policy the process
already had. `network-opts` carries the egress rules. `stdin` is what the
guest reads from `sys.stdin`, or nil for none.

The order matters and is the same order it has always been: the runtime
first, then the names the block may not overwrite, then the tools, then the
contracts those tools carry, then discovery, then policy — so every `__vis_*`
name and every seeded module is already BASELINE when the member snapshot is
taken, and the model's live-vars view shows only what its own blocks made.
sourceraw docstring

ctx->python-strclj

(ctx->python-str data)

Render plain boundary data as a deterministic, executable Python literal.

This is deliberately a pure JVM serializer: rendering never enters CPython, never waits behind a session's GIL, and needs no process-global printer lock. It mirrors the Clojure->Python boundary (string-only map keys, list-like collections, ISO strings for Date/UUID/Temporal) and keeps insertion order plus the historical 100-column layout.

Render plain boundary data as a deterministic, executable Python literal.

This is deliberately a pure JVM serializer: rendering never enters CPython,
never waits behind a session's GIL, and needs no process-global printer
lock. It mirrors the Clojure->Python boundary (string-only map
keys, list-like collections, ISO strings for Date/UUID/Temporal) and keeps
insertion order plus the historical 100-column layout.
sourceraw docstring

dispose-python-context!clj

(dispose-python-context! session)

Drop session: its sandbox, separate trusted extension worker, host bindings and the right for this environment to run Python again. Gateway teardown kills the processes rather than entering an interpreter that may be wedged.

Drop `session`: its sandbox, separate trusted extension worker, host bindings
and the right for this environment to run Python again. Gateway teardown kills
the processes rather than entering an interpreter that may be wedged.
sourceraw docstring

dispose-sandbox!clj

(dispose-sandbox! environment)

Close the environment's sandbox without building it. Serialize with first initialization so teardown cannot miss an interpreter still being created.

Close the environment's sandbox without building it. Serialize with first
initialization so teardown cannot miss an interpreter still being created.
sourceraw docstring

ensure-interpreter!clj

(ensure-interpreter!)

Start the process's ONE interpreter, with Vis' own guest modules on the path. Idempotent: the runtime's own initialize! is, and so is this.

Public because a session is not the only thing that needs the interpreter up: a Python EXTENSION loads at startup, before any sandbox exists, and the first of the two to arrive is the one that starts it. The interpreter itself may not be on this machine yet — python-runtime/ensure-library! is what fetches it, and it costs nothing once it has.

A caller that arrives second WAITS, and that is the whole point of the lock: a flag set before the work is done let the second caller return to a Python that was still inside Py_Initialize and confine it, and the audit hook then refused the interpreter's OWN startup — getpath raising OSError, error evaluating path, and every session after it failing in vispython_exec. Measured on a gateway building two sessions at once. The flag is set only after a start SUCCEEDS, so a machine that could not fetch the interpreter this time gets to try again rather than serving a dead one.

Start the process's ONE interpreter, with Vis' own guest modules on the path.
Idempotent: the runtime's own `initialize!` is, and so is this.

Public because a session is not the only thing that needs the interpreter up:
a Python EXTENSION loads at startup, before any sandbox exists, and the first
of the two to arrive is the one that starts it. The interpreter itself may
not be on this machine yet — `python-runtime/ensure-library!` is what fetches
it, and it costs nothing once it has.

A caller that arrives second WAITS, and that is the whole point of the lock:
a flag set before the work is done let the second caller return to a Python
that was still inside `Py_Initialize` and confine it, and the audit hook then
refused the interpreter's OWN startup — `getpath` raising OSError, `error
evaluating path`, and every session after it failing in `vispython_exec`.
Measured on a gateway building two sessions at once. The flag
is set only after a start SUCCEEDS, so a machine that could not fetch the
interpreter this time gets to try again rather than serving a dead one.
sourceraw docstring

forget-session-defs!clj

(forget-session-defs! session-id)

Drop session-id's entry from the in-memory dedup memo. The on-disk snapshot deliberately SURVIVES — it is what a later process restores from.

Drop `session-id`'s entry from the in-memory dedup memo. The on-disk snapshot
deliberately SURVIVES — it is what a later process restores from.
sourceraw docstring

interrupt-guest!clj

(interrupt-guest! session)

Ask the interpreter to raise KeyboardInterrupt in the thread running guest code, answering whether it landed.

Bytecode-level, like CPython's own interrupt: a spinning while True: unwinds and the session survives; a thread blocked in a host call or inside C does not see it until it returns. A normal false means no block was running. Worker protocol failures throw so the loop can distinguish a dead control plane from that harmless race and retire only the broken process.

Ask the interpreter to raise `KeyboardInterrupt` in the thread running guest
code, answering whether it landed.

Bytecode-level, like CPython's own interrupt: a spinning `while True:` unwinds
and the session survives; a thread blocked in a host call or inside C does not
see it until it returns. A normal false means no block was running. Worker
protocol failures throw so the loop can distinguish a dead control plane from
that harmless race and retire only the broken process.
sourceraw docstring

map-python-errorclj

(map-python-error session raised code)

Map what a block RAISED into the engine's op-error shape.

:phase is :python/syntax for a parse failure, :python/host when a host tool is what failed, else :python/runtime; :line/:column come from the guest position when there is one. Syntax hints identify invalid non-ASCII characters and — through parse-diagnose — unbalanced quotes or brackets.

Map what a block RAISED into the engine's op-error shape.

`:phase` is `:python/syntax` for a parse failure, `:python/host` when a host
tool is what failed, else `:python/runtime`; `:line`/`:column` come from the
guest position when there is one. Syntax hints identify invalid non-ASCII
characters and — through `parse-diagnose` — unbalanced quotes or brackets.
sourceraw docstring

normalize-dict-keyclj

(normalize-dict-key s)

Model-input hygiene at the ONE inbound conversion: a dict key spelled ":target" is still a STRING (the model drifting into colon spelling while reading keyword-heavy source), so strip the single leading colon when an identifier char follows and the call just works — no lecture, no failure. Data keys are untouched: line numbers start with a digit, paths with a letter or /, neither with :. Produces strings, never keywords.

Model-input hygiene at the ONE inbound conversion: a dict key spelled
`":target"` is still a STRING (the model drifting into colon
spelling while reading keyword-heavy source), so strip the single leading
colon when an identifier char follows and the call just works — no
lecture, no failure. Data keys are untouched: line numbers start with a
digit, paths with a letter or `/`, neither with `:`. Produces
strings, never keywords.
sourceraw docstring

pending-guest-repliesclj

(pending-guest-replies session)

Snapshot actual sandbox and trusted-extension completions before interrupting. Cancelling a host caller does not settle these replies.

Snapshot actual sandbox and trusted-extension completions before interrupting.
Cancelling a host caller does not settle these replies.
sourceraw docstring

persist-session-defs!clj

(persist-session-defs! session session-id)

Write this session's own defs beside the session, for a LATER process.

Globals persist across turns because the interpreter does — but the interpreter dies with the PROCESS. Restart the gateway and every helper the session refined is gone while the transcript still shows it, so the next call is a NameError against code the model can still read. Best effort; answers the file when it wrote one.

Write this session's own `def`s beside the session, for a LATER process.

Globals persist across turns because the interpreter does — but the
interpreter dies with the PROCESS. Restart the gateway and every helper the
session refined is gone while the transcript still shows it, so the next call
is a NameError against code the model can still read. Best effort; answers the
file when it wrote one.
sourceraw docstring

PROCESS_SURFACEclj

THE sentences about this sandbox's process surface — written ONCE, here, and said verbatim by every surface that has to say them:

  • the sandbox-shims prompt block (prompt/sandbox-shims-prompt-block);
  • the POSIX refusal (vis-shims/posix.py), when subprocess / os.system / os.popen is called;
  • a live handle that cannot be driven (__VisShell__.__vis_op__ in vis-python/async_runtime.py);
  • the corpus entry named shell (env-python/create-python-context), when the shell tools are off and apropos("shell") / doc("shell") would otherwise answer with silence.

Every copy of one fact drifts, and the copy the model reads at the moment it is blocked is the one that must be right. Composed, never concatenated ad hoc: ban is the rule and is all the PROMPT says (invocation grammar belongs to the shell symbol's own docs, not to a supplemental block); ban + use is what a call site says, because there the model is already writing the call; off is the toggle state, and it names BOTH doors so silence is never read as "subprocess might still work"; off + extension is what DISCOVERY says, because a model that reads off alone concludes nothing in this product can start a process. The toggle closes the MODEL's door only: an installed Python extension's vis.shell is wired unconditionally in python-extensions/build-context and no toggle gates it.

Reaches Python as the __vis_process_surface__ global (see install-process-surface!), so no .py file carries a copy.

THE sentences about this sandbox's process surface — written ONCE, here, and
said verbatim by every surface that has to say them:

  - the `sandbox-shims` prompt block (`prompt/sandbox-shims-prompt-block`);
  - the POSIX refusal (`vis-shims/posix.py`), when `subprocess` / `os.system` /
    `os.popen` is called;
  - a live handle that cannot be driven (`__VisShell__.__vis_op__` in
    `vis-python/async_runtime.py`);
  - the corpus entry named `shell` (`env-python/create-python-context`), when the
    shell tools are off and `apropos("shell")` / `doc("shell")` would otherwise
    answer with silence.

Every copy of one fact drifts, and the copy the model reads at the moment it
is blocked is the one that must be right. Composed, never concatenated ad hoc:
`ban` is the rule and is all the PROMPT says (invocation grammar belongs to the
`shell` symbol's own docs, not to a supplemental block); `ban` + `use` is what a
call site says, because there the model is already writing the call; `off` is
the toggle state, and it names BOTH doors so silence is never read as
"`subprocess` might still work"; `off` + `extension` is what DISCOVERY says,
because a model that reads `off` alone concludes nothing in this product can
start a process. The toggle closes the MODEL's door only: an installed Python
extension's `vis.shell` is wired unconditionally in
`python-extensions/build-context` and no toggle gates it.

Reaches Python as the `__vis_process_surface__` global (see
`install-process-surface!`), so no `.py` file carries a copy.
sourceraw docstring

py-json-literalclj

(py-json-literal data)

data as a Python expression that evaluates to it — json.loads("…").

This is the ONLY way a host value reaches the guest. There is no putMember over a C ABI that carries text, and interpolating a repr would make every value a parsing question; JSON is the one dialect this boundary speaks.

Public because two other host namespaces cross the same boundary: JSON escapes / as \/, which Python keeps VERBATIM, so JSON text pasted straight into Python source silently corrupts every path in it.

`data` as a Python expression that evaluates to it — `json.loads("…")`.

This is the ONLY way a host value reaches the guest. There is no `putMember`
over a C ABI that carries text, and interpolating a repr would make every
value a parsing question; JSON is the one dialect this boundary speaks.

Public because two other host namespaces cross the same boundary: JSON
escapes `/` as `\/`, which Python keeps VERBATIM, so JSON text pasted
straight into Python source silently corrupts every path in it.
sourceraw docstring

python-contextclj

(python-context environment)

The environment's Python context, building the sandbox on first ask.

An environment may also carry a context DIRECTLY, with no sandbox delay and no session lifecycle around it — one interpreter someone built and handed in. That context is already the answer, so this never forces anything for it. An explicit retirement marker still refuses entry.

The environment's Python context, building the sandbox on first ask.

An environment may also carry a context DIRECTLY, with no sandbox delay and
no session lifecycle around it — one interpreter someone built and handed in.
That context is already the answer, so this never forces anything for it.
An explicit retirement marker still refuses entry.
sourceraw docstring

python-context-if-builtclj

(python-context-if-built environment)

The environment's Python context ONLY when it already exists.

A context handed in directly always exists; a sandbox delay answers only once something has forced it.

The environment's Python context ONLY when it already exists.

A context handed in directly always exists; a sandbox delay answers only once
something has forced it.
sourceraw docstring

python-worker-pidsclj

(python-worker-pids)

PIDs of the live interpreter workers owned by this gateway process.

PIDs of the live interpreter workers owned by this gateway process.
sourceraw docstring

remove-python-binding!clj

(remove-python-binding! session sym)

Remove sym from session entirely, including dotted namespace members and every discovery metadata table.

Remove `sym` from `session` entirely, including dotted namespace members and
every discovery metadata table.
sourceraw docstring

restore-session-defs!clj

(restore-session-defs! session session-id)

Re-create the helper definitions an EARLIER process persisted for session-id, answering how many are live afterwards.

The restored source is registered as a real block, so defs("name") and inspect.getsource read it back exactly like a local one, and it goes through the same rewrite so it RUNS like one.

Re-create the helper definitions an EARLIER process persisted for
`session-id`, answering how many are live afterwards.

The restored source is registered as a real block, so `defs("name")` and
`inspect.getsource` read it back exactly like a local one, and it goes
through the same rewrite so it RUNS like one.
sourceraw docstring

retire-python-context!clj

(retire-python-context! session)

Kill session's worker after its control plane stopped answering, then drop the host doors its sandbox and trusted extension namespaces owned. The worker key stays RETIRED until ordinary disposal: a late caller must not fall through to the parent runtime, and must not start a fresh interpreter under this key either — that one would carry the runtime but none of the session's tools.

Kill `session`'s worker after its control plane stopped answering, then drop
the host doors its sandbox and trusted extension namespaces owned. The worker
key stays RETIRED until ordinary disposal: a late caller must not fall through
to the parent runtime, and must not start a fresh interpreter under this key
either — that one would carry the runtime but none of the session's tools.
sourceraw docstring

retired-context-errorclj

(retired-context-error environment)

Local terminal error data for a retired environment, otherwise nil. This check never creates or enters an interpreter. Only a new turn may rebuild it.

Local terminal error data for a retired environment, otherwise nil.
This check never creates or enters an interpreter. Only a new turn may rebuild it.
sourceraw docstring

run-python-blockclj

(run-python-block session code & [_opts])

Run one Python code block in session as ONE whole-block coroutine, answering the FLAT sum-typed outcome:

{:stdout <printed>} ; SUCCESS — what the block print()ed {:error <op-error>} ; FAILURE — the raised error IS the result

A block that printed nothing carries NEITHER key: its own value is discarded, so print() is the only way anything comes back. Either outcome may carry :attachments, the artifacts the block produced.

The runtime AST-wraps the block in an async def, auto-settles every bare tool-call statement at every depth and drives it as a single coroutine.

A session this process already disposed is REFUSED: the interpreter would otherwise mint the namespace again, empty, and run the block without one of its doors.

Run one Python `code` block in `session` as ONE whole-block coroutine,
answering the FLAT sum-typed outcome:

  {:stdout <printed>}   ; SUCCESS — what the block print()ed
  {:error  <op-error>}  ; FAILURE — the raised error IS the result

A block that printed nothing carries NEITHER key: its own value is discarded,
so `print()` is the only way anything comes back. Either outcome may carry
`:attachments`, the artifacts the block produced.

The runtime AST-wraps the block in an `async def`, auto-settles every bare
tool-call statement at every depth and drives it as a single coroutine.

A session this process already disposed is REFUSED: the interpreter would
otherwise mint the namespace again, empty, and run the block without one of
its doors.
sourceraw docstring

sandboxclj

(sandbox environment)

The environment's Python sandbox, BUILDING it if this is the first ask.

create-environment stores the sandbox as a delay rather than a value: a session that never runs Python never starts an interpreter, and the wait for one belongs to the turn that needs it instead of to POST /v1/sessions. Every caller about to enter Python reads through here.

Callers that only tear down, retire, or ASK whether Python is live must use sandbox-if-built instead — forcing a sandbox in order to dispose it would start an interpreter for the sole purpose of killing it.

The environment's Python sandbox, BUILDING it if this is the first ask.

`create-environment` stores the sandbox as a delay rather than a value: a
session that never runs Python never starts an interpreter, and the wait for
one belongs to the turn that needs it instead of to `POST /v1/sessions`.
Every caller about to enter Python reads through here.

Callers that only tear down, retire, or ASK whether Python is live must use
[[sandbox-if-built]] instead — forcing a sandbox in order to dispose it would
start an interpreter for the sole purpose of killing it.
sourceraw docstring

sandbox-if-builtclj

(sandbox-if-built environment)

The environment's sandbox ONLY when it already exists, nil while it does not.

Never builds one. This is the read for teardown and for liveness questions, where an absent sandbox is an answer rather than a reason to make one.

The environment's sandbox ONLY when it already exists, nil while it does not.

Never builds one. This is the read for teardown and for liveness questions,
where an absent sandbox is an answer rather than a reason to make one.
sourceraw docstring

sandbox-nsclj

(sandbox-ns environment)

The environment's sandbox namespace, building the sandbox on first ask.

The environment's sandbox namespace, building the sandbox on first ask.
sourceraw docstring

seed-cli-runtime!clj

(seed-cli-runtime! session {:keys [argv env]})

Seed a standalone vis-agent python CLI session with script argv (bound to sys.argv) and, when non-empty, an env map merged into os.environ.

This is what gives the CLI real-python semantics: unlike the agent sandbox, whose environment is scrubbed because the human never sees it, the CLI forwards the caller's own.

Seed a standalone `vis-agent python` CLI session with script `argv` (bound to
`sys.argv`) and, when non-empty, an `env` map merged into `os.environ`.

This is what gives the CLI real-`python` semantics: unlike the agent sandbox,
whose environment is scrubbed because the human never sees it, the CLI
forwards the caller's own.
sourceraw docstring

set-python-binding!clj

(set-python-binding! session sym val)

Bind sym -> val in session's globals.

A FUNCTION becomes a host tool: the name is registered for this session in [[python-host]] and installed by the runtime as a deferred callable, so await tool(...) and gather(tool(...), …) work exactly like the tools the context was built with. A dotted name publishes one declared method through a capability namespace instead of exposing the extension's raw object. Anything else is DATA and crosses as JSON.

Bind `sym` -> `val` in `session`'s globals.

A FUNCTION becomes a host tool: the name is registered for this session in
[[python-host]] and installed by the runtime as a deferred callable, so
`await tool(...)` and `gather(tool(...), …)` work exactly like the tools the
context was built with. A dotted name publishes one declared method through a
capability namespace instead of exposing the extension's raw object. Anything
else is DATA and crosses as JSON.
sourceraw docstring

set-python-binding-contract!clj

(set-python-binding-contract! session sym contract)

Attach a portable description to an installed Python extension callable. No runtime shim or parallel registry: the value comes from its symbol entry.

Attach a portable description to an installed Python extension callable.
No runtime shim or parallel registry: the value comes from its symbol entry.
sourceraw docstring

set-python-binding-doc!clj

(set-python-binding-doc! session sym text)

The model-facing description of sym, what in-sandbox doc(name) prints.

The model-facing description of `sym`, what in-sandbox `doc(name)` prints.
sourceraw docstring

set-python-binding-keys!clj

(set-python-binding-keys! session sym keys-text)

The options-dict vocabulary of sym — which keys the dict must carry and which it may omit — printed by doc(name) under the call line.

The options-dict vocabulary of `sym` — which keys the dict must carry and
which it may omit — printed by `doc(name)` under the call line.
sourceraw docstring

set-python-binding-signature!clj

(set-python-binding-signature! session sym signature)

The declared parameter list of sym, what inspect.signature reports through the deferred wrapper's __wrapped__.

The declared parameter list of `sym`, what `inspect.signature` reports through
the deferred wrapper's `__wrapped__`.
sourceraw docstring

sym->py-nameclj

(sym->py-name sym)

Clojure tool/binding symbol -> a Python-LEGAL global name. Purely mechanical: / and - fold to _ (alias fold + kebab->snake); a trailing ! (mutation marker) is dropped; a trailing ? (predicate) becomes an is_ prefix. So git/status -> git_status, git/commit! -> git_commit, and file-exists -> file_exists. FULL SNAKE: this is how the agent reaches the tools — git_status() calls git/status.

Clojure tool/binding symbol -> a Python-LEGAL global name. Purely mechanical:
`/` and `-` fold to `_` (alias fold + kebab->snake); a trailing `!` (mutation
marker) is dropped; a trailing `?` (predicate) becomes an `is_` prefix. So
`git/status` -> `git_status`, `git/commit!` -> `git_commit`, and `file-exists` ->
`file_exists`. FULL SNAKE:
this is how the agent reaches the tools — `git_status()` calls `git/status`.
sourceraw docstring

system-var-sym?clj

(system-var-sym? sym)
source

SYSTEM_VAR_NAMESclj

Host-owned globals refreshed with the standing context and hidden from user live vars.

Host-owned globals refreshed with the standing context and hidden from user live vars.
sourceraw docstring

take-partial-block-stdout!clj

(take-partial-block-stdout! session)

Drain what session printed while its current block was running.

The runtime mirrors writes here because code parked inside C may have to be killed before its ordinary block outcome can return.

Drain what `session` printed while its current block was running.

The runtime mirrors writes here because code parked inside C may have to be
killed before its ordinary block outcome can return.
sourceraw docstring

validate-no-banned-defs!clj

(validate-no-banned-defs! session code)

Throws :vis/banned-def-head when code references a banned construct (BANNED_DEF_HEADS). A parse failure is silent — the run that follows surfaces a clean syntax error with its line and column.

Throws `:vis/banned-def-head` when `code` references a banned construct
([[BANNED_DEF_HEADS]]). A parse failure is silent — the run that follows
surfaces a clean syntax error with its line and column.
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