Liking cljdoc? Tell your friends :D
Clojure only.

com.blockether.vis.core

vis - broad host facade.

This is the ONLY namespace extensions, channel adapters, embedded callers, and tests should import. It deliberately re-exports host, registry, runtime, persistence, prompt, diagnostic, and sandbox helpers from com.blockether.vis.internal.*. The internal tree is not stable; the names exposed here are the host contract.

Canonical runtime language: Session -> Turn -> Iteration -> Block.

A Turn is one user request plus assistant answer inside a Session. New code and documentation should use turn/user-request language.

Primary surfaces:

  • Session / turn runtime: create!, send!, turn!, by-id, by-channel, env-for, close!, delete!, set-title!.
  • Environment runtime: create-environment, dispose-environment!, get-router, rebuild-router!, resolve-effective-model.
  • Extension contract: extension, symbol, value, render-prompt, register-extension!, registered-extensions, discovery, reload.
  • Registries: command, channel, provider, and backend registration helpers for host-owned and embedded use.
  • Persistence facade: db-* functions and connection helpers. The implementation namespace / extension slot are spelled persistance; human-facing language is Persistence.
  • Prompt / Python-sandbox / formatting / cancellation / notifications / doctor helpers shared by channels and extensions.

Not every export is equally high-level. send!, extension maps, registry builders, read-side persistence helpers, and Markdown export are the preferred integration surface. Low-level sandbox, parse-repair, dispatcher, and write-side db helpers are exported because this is a host facade, but ordinary extensions should avoid depending on them unless they are implementing host-level behavior.

Binary entry: -main (invoked by clojure -M:vis, AOT'd to a Java entry class via :gen-class for the GraalVM native-image build).

vis - broad host facade.

This is the ONLY namespace extensions, channel adapters, embedded
callers, and tests should import. It deliberately re-exports host,
registry, runtime, persistence, prompt, diagnostic, and sandbox
helpers from `com.blockether.vis.internal.*`. The internal tree is
not stable; the names exposed here are the host contract.

Canonical runtime language:
  Session -> Turn -> Iteration -> Block.

A Turn is one user request plus assistant answer inside a Session.
New code and documentation should use turn/user-request language.

Primary surfaces:
  - Session / turn runtime: create!, send!, turn!, by-id,
    by-channel, env-for, close!, delete!, set-title!.
  - Environment runtime: create-environment, dispose-environment!,
    get-router, rebuild-router!, resolve-effective-model.
  - Extension contract: extension, symbol, value, render-prompt,
    register-extension!, registered-extensions, discovery, reload.
  - Registries: command, channel, provider, and backend registration
    helpers for host-owned and embedded use.
  - Persistence facade: db-* functions and connection helpers. The
    implementation namespace / extension slot are spelled
    `persistance`; human-facing language is Persistence.
  - Prompt / Python-sandbox / formatting / cancellation /
    notifications / doctor helpers shared by channels and extensions.

Not every export is equally high-level. `send!`, extension maps,
registry builders, read-side persistence helpers, and Markdown export
are the preferred integration surface. Low-level sandbox, parse-repair,
dispatcher, and write-side db helpers are exported because this is a
host facade, but ordinary extensions should avoid depending on them
unless they are implementing host-level behavior.

Binary entry: -main (invoked by `clojure -M:vis`, AOT'd to a Java
entry class via `:gen-class` for the GraalVM native-image build).
raw docstring

->astclj

(->ast v)

Soft-normalize any answer-input value into canonical [:ir & blocks]. Pure, total, idempotent.

Identity-preserving: when the input already satisfies the canonical invariants (canonical?), the return value is the SAME object. This keeps downstream System/identityHashCode caches (format-answer-with-thinking-data, etc.) hot across repeated render passes — walker output is computed once per canonical IR identity, not once per equal-but-fresh allocation.

Before canonicalization, Hiccup child positions are walked with clojure+.walk semantics and non-vector sequential values (notably lazy seqs from (map ...) inside answer IR) are safely realized to at most 100 items, then replaced with an explicit … many more marker when truncated. This avoids persisting Java LazySeq identity strings and avoids hanging on infinite seqs.

See namespace docstring for the full canonical-form invariants.

Soft-normalize any answer-input value into canonical [:ir & blocks].
Pure, total, idempotent.

Identity-preserving: when the input already satisfies the canonical
invariants (`canonical?`), the return value is the SAME object.
This keeps downstream `System/identityHashCode` caches
(`format-answer-with-thinking-data`, etc.) hot across repeated
render passes — walker output is computed once per canonical IR
identity, not once per equal-but-fresh allocation.

Before canonicalization, Hiccup child positions are walked with
`clojure+.walk` semantics and non-vector sequential values (notably
lazy seqs from `(map ...)` inside answer IR) are safely realized to
at most 100 items, then replaced with an explicit `… many more`
marker when truncated. This avoids persisting Java LazySeq identity
strings and avoids hanging on infinite seqs.

See namespace docstring for the full canonical-form invariants.
sourceraw docstring

->dateclj

(->date v)
source

->epoch-msclj

(->epoch-ms v)
source

->idclj

(->id v)
source

->kwclj

(->kw v)

Keyword/string -> TEXT, stripping the leading colon. Nil -> nil.

Keyword/string -> TEXT, stripping the leading colon. Nil -> nil.
sourceraw docstring

->kw-backclj

(->kw-back v)
source

->refclj

(->ref v)

Normalize an entity reference to a string ID for SQL. Accepts: UUID, string, or nil. Returns string or nil.

The ONLY way to extract a SQL-ready string from an entity reference -- pass the plain UUID or string directly.

Normalize an entity reference to a string ID for SQL.
Accepts: UUID, string, or nil. Returns string or nil.

The ONLY way to extract a SQL-ready string from an entity
reference -- pass the plain UUID or string directly.
sourceraw docstring

->svar-modelclj

(->svar-model model)
(->svar-model provider-id model)

Coerce a model representation to svar-native {:name str}.

Coerce a model representation to svar-native `{:name str}`.
sourceraw docstring

->svar-providerclj

(->svar-provider provider)

Coerce a provider map to svar-native shape (:id, :api-key, :base-url, :api-style, :models, optional :responses-path, optional :llm-headers).

svar's make-router calls normalize-provider which auto-resolves :base-url from svar's KNOWN_PROVIDERS table for built-in providers, so we forward :base-url ONLY when the provider map has one explicitly (vis-only providers like :github-models, user overrides, or OAuth-supplied URLs). For known providers svar fills in the URL itself - stop fighting it.

When :api-key is nil, look the provider up in the global provider registry (registry.clj) and call its :provider/get-token-fn to resolve a usable token. Each provider implementation handles its own auth lifecycle (OAuth refresh, env-var fallback, provider-specific headers, ...) so this fn stays provider-agnostic and never references a concrete provider ns by name.

Coerce a provider map to svar-native shape (`:id`, `:api-key`,
`:base-url`, `:api-style`, `:models`, optional `:responses-path`,
optional `:llm-headers`).

svar's `make-router` calls `normalize-provider` which auto-resolves
`:base-url` from svar's `KNOWN_PROVIDERS` table for built-in
providers, so we forward `:base-url` ONLY when the provider map
has one explicitly (vis-only providers like `:github-models`,
user overrides, or OAuth-supplied URLs). For known providers
svar fills in the URL itself - stop fighting it.

When `:api-key` is nil, look the provider up in the global
provider registry (registry.clj) and call its
`:provider/get-token-fn` to resolve a usable token. Each provider
implementation handles its own auth lifecycle (OAuth refresh,
env-var fallback, provider-specific headers, ...) so this fn stays
provider-agnostic and never references a concrete provider ns by
name.
sourceraw docstring

->uuidclj

(->uuid v)
source

-mainclj

(-main & args)
source

active-extensionsclj

(active-extensions environment)

Returns the seq of registered extensions whose :ext/activation-fn returns truthy for environment, in registration order. Single source of truth for activation; call ONCE at the top of a turn.

Returns the seq of registered extensions whose `:ext/activation-fn` returns
truthy for `environment`, in registration order. Single source of truth for
activation; call ONCE at the top of a turn.
sourceraw docstring

active-modelclj

(active-model)

Return the primary model name string, or nil.

Return the primary model name string, or nil.
sourceraw docstring

active-providerclj

(active-provider)

Return the first (primary) provider from config, or nil.

Return the first (primary) provider from config, or nil.
sourceraw docstring

active-slashesclj

(active-slashes env)

Aggregate :ext/slash-commands from every active extension for env. Order: extension registration order (stable). Returns a vec.

This is the ONLY source of truth for engine slash dispatch (which already has a turn env handy). Channels that lack a per-turn env should use registered-slashes (no activation filtering).

Aggregate `:ext/slash-commands` from every active extension for `env`.
Order: extension registration order (stable). Returns a vec.

This is the ONLY source of truth for engine slash dispatch (which
already has a turn env handy). Channels that lack a per-turn env
should use `registered-slashes` (no activation filtering).
sourceraw docstring

add-channel-event-listener!clj

source

add-config-provider!clj

(add-config-provider! provider-cfg)
(add-config-provider! provider-cfg source)

Append a provider config to the persisted fleet (no-op when the id is already configured). Returns the new fleet or nil on no-op.

Append a provider config to the persisted fleet (no-op when the id
is already configured). Returns the new fleet or nil on no-op.
sourceraw docstring

add-python-extension-change-listener!clj

(add-python-extension-change-listener! listener-id f)

Subscribe f to Python-extension set changes. f receives {:extensions [<validated ext map> ...] :removed [<ext-name> ...]} after every (re)load that changed anything: :extensions is the full freshly-registered set, :removed the names that no longer exist. Re-registering the same listener-id replaces the old listener. Returns listener-id.

Subscribe `f` to Python-extension set changes. `f` receives
`{:extensions [<validated ext map> ...] :removed [<ext-name> ...]}`
after every (re)load that changed anything: `:extensions` is the full
freshly-registered set, `:removed` the names that no longer exist.
Re-registering the same `listener-id` replaces the old listener.
Returns `listener-id`.
sourceraw docstring

add-title-listener!clj

(add-title-listener! session-id listener-fn)

Register listener-fn for session-id. The fn is invoked with the new title (a string) every time the title changes. Multiple listeners are supported; they fire in unspecified order.

Returns the listener fn so callers can pass it to remove-title-listener! later.

Register `listener-fn` for `session-id`. The fn is invoked with
the new title (a string) every time the title changes. Multiple
listeners are supported; they fire in unspecified order.

Returns the listener fn so callers can pass it to
`remove-title-listener!` later.
sourceraw docstring

add-title-pending-listener!clj

(add-title-pending-listener! session-id listener-fn)

Register listener-fn for session-id; invoked with a boolean (true when title generation starts, false when it ends). Returns the listener fn for later remove-title-pending-listener!.

Register `listener-fn` for `session-id`; invoked with a boolean
(true when title generation starts, false when it ends). Returns the
listener fn for later `remove-title-pending-listener!`.
sourceraw docstring

all-provider-limitsclj

(all-provider-limits)

Return normalized limits reports for every registered provider in registration order.

Return normalized limits reports for every registered provider in
registration order.
sourceraw docstring

answer->irclj

(answer->ir answer)

Lift a final-answer value into canonical IR.

The Markdown-answer pipeline produces exactly two final-answer shapes:

  • {:answer markdown} - plain-prose answer
  • {:vis/answer-mode :needs-input :answer/text string} - needs-input gate

Returns canonical [:ir & blocks]. nil yields [:ir {}]. Anything outside the two canonical shapes is an upstream bug.

Lift a final-answer value into canonical IR.

The Markdown-answer pipeline produces exactly two final-answer shapes:
  - `{:answer markdown}`                                  - plain-prose answer
  - `{:vis/answer-mode :needs-input :answer/text string}` - needs-input gate

Returns canonical `[:ir & blocks]`. nil yields `[:ir {}]`.
Anything outside the two canonical shapes is an upstream bug.
sourceraw docstring

ask-code!clj

(ask-code! opts)

One-shot routed svar/ask-code! against the global router. Plain-text completion + Markdown-code-block extraction — returns the svar map {:blocks :raw :reasoning :tokens :cost :duration-ms :assistant-message :provider-state}. :blocks is a vec of {:lang :source} (one entry per Markdown code block); concatenate yourself with svar.internal.codes/concat-sources if you need a single string. ask! (JSON-spec) is gone; every Vis caller uses ask-code!.

One-shot routed `svar/ask-code!` against the global router.
Plain-text completion + Markdown-code-block extraction — returns the
svar map `{:blocks :raw :reasoning :tokens :cost :duration-ms
:assistant-message :provider-state}`. `:blocks` is a vec of
`{:lang :source}` (one entry per Markdown code block); concatenate
yourself with `svar.internal.codes/concat-sources` if you need a
single string. `ask!` (JSON-spec) is gone; every Vis caller uses
`ask-code!`.
sourceraw docstring

assemble-initial-messagesclj

(assemble-initial-messages {:keys [stable-prompt-messages initial-user-content
                                   previous-turn-context user-images
                                   skipped-images]})

Initial provider messages for one turn. Deliberately excludes full prior dialog transcript: Vis state flows through persisted iterations, defs, and DB-backed tools. The current user message is tagged as CURRENT-USER-MESSAGE.

One full previous-turn context block may be prepended so short follow-ups can inspect the prior exchange without replaying the whole session.

:user-images (from attachments/collect-user-images) turns the user message multimodal: svar image blocks ride ahead of the text block and an ATTACHED-IMAGES manifest inside the text names each one. :skipped-images entries appear in the manifest only.

Initial provider messages for one turn. Deliberately excludes full prior
dialog transcript: Vis state flows through persisted iterations,
defs, and DB-backed tools. The current user message is tagged as
`CURRENT-USER-MESSAGE`.

One full previous-turn context block may be prepended so short follow-ups
can inspect the prior exchange without replaying the whole session.

`:user-images` (from `attachments/collect-user-images`) turns the user
message multimodal: svar image blocks ride ahead of the text block and
an `ATTACHED-IMAGES` manifest inside the text names each one.
`:skipped-images` entries appear in the manifest only.
sourceraw docstring

assemble-stable-prompt-messagesclj

(assemble-stable-prompt-messages
  environment
  {:keys [system-prompt active-extensions session-context] :as opts})

Assemble provider-prefix messages.

Send order is explicit and tested: SYSTEM-PROMPT - CORE_SYSTEM_PROMPT + caller addendum PROJECT-INSTRUCTIONS - AGENTS.md / CLAUDE.md contents (when present) TURN-SYSTEM-CONTEXT - turn-scoped runtime capability context. Today it contains extension prompt fragments; future extension reloads should replace this one message, never append a second extension context.

Extension fragments are separate from the core system prompt and are not repeated in per-iteration trailers.

Required opts: :active-extensions - vec from (active-extensions env). Drives environment, extension prompt, and hint collection.

Optional opts: :system-prompt - caller addendum appended to CORE. :session-context - rendered fenced-Python session = {…} block (standing session state: workspace / env / routing / tools). Embedded ONCE here as a cached system message; the loop re-emits only the session[...] = … structural delta in the conversation when it changes mid-turn.

Assemble provider-prefix messages.

Send order is explicit and tested:
  `SYSTEM-PROMPT`         - CORE_SYSTEM_PROMPT + caller addendum
  `PROJECT-INSTRUCTIONS`  - AGENTS.md / CLAUDE.md contents (when present)
  `TURN-SYSTEM-CONTEXT`   - turn-scoped runtime capability context. Today
                            it contains extension prompt fragments; future
                            extension reloads should replace this one
                            message, never append a second extension
                            context.

Extension fragments are separate from the core system prompt and are not
repeated in per-iteration trailers.

Required opts:
  `:active-extensions` - vec from `(active-extensions env)`. Drives
     environment, extension prompt, and hint collection.

Optional opts:
  `:system-prompt`            - caller addendum appended to CORE.
  `:session-context`          - rendered fenced-Python `session = {…}` block
     (standing session state: workspace / env / routing / tools). Embedded
     ONCE here as a cached system message; the loop re-emits only the
     `session[...] = …` structural delta in the conversation when it changes
     mid-turn.
sourceraw docstring

auto-archive-hot-symbols!clj

(auto-archive-hot-symbols! _environment)

Deprecated NOOP. Cross-turn def survival was removed when the definition_* sidecar tables were dropped; the Python sandbox starts fresh each turn, so there is nothing to archive.

Deprecated NOOP. Cross-turn def survival was removed when the
`definition_*` sidecar tables were dropped; the Python sandbox starts
fresh each turn, so there is nothing to archive.
sourceraw docstring

available-theme-idsclj

(available-theme-ids)
(available-theme-ids extensions)

Theme ids from the process registry plus optional unregistered extension descriptor maps. Normally extensions are already installed into themes by register-extension!; the argument remains for pure tests/previews.

Theme ids from the process registry plus optional unregistered extension
descriptor maps. Normally extensions are already installed into `themes`
by `register-extension!`; the argument remains for pure tests/previews.
sourceraw docstring

beautify-pythonclj

(beautify-python code)

ruff-format code (cached). nil/blank -> "". Never throws — falls back to the verbatim source when ruff can't format or isn't available.

ruff-format `code` (cached). nil/blank -> "". Never throws — falls back to
the verbatim source when ruff can't format or isn't available.
sourceraw docstring

bind-and-bump!clj

(bind-and-bump! env sym val)

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

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

build-system-promptclj

(build-system-prompt {:keys [system-prompt]})

Core system prompt + optional caller addendum + config prompt + SYSTEM.md / APPEND_SYSTEM.md file overrides.

Assembled in send order (later blocks positionally reinforce earlier): base, then the caller's :system-prompt addendum, then the :system-prompt pulled from Vis config (vis.edn / .vis/config.edn / ~/.vis/config.edn, deep-merged), then ~/.vis/APPEND_SYSTEM.md, then <workspace>/.vis/APPEND_SYSTEM.md. The config + file hooks let a project append house rules without any caller having to pass them.

Full rewrite precedence for the base: <workspace>/.vis/SYSTEM.md > ~/.vis/SYSTEM.md > config :system-prompt map with :replace? true > CORE_SYSTEM_PROMPT. When a file/config replaces the base, addenda and append files are still appended after it.

Core system prompt + optional caller addendum + config prompt +
SYSTEM.md / APPEND_SYSTEM.md file overrides.

Assembled in send order (later blocks positionally reinforce earlier):
base, then the caller's `:system-prompt` addendum, then the
`:system-prompt` pulled from Vis config (`vis.edn` / `.vis/config.edn` /
`~/.vis/config.edn`, deep-merged), then `~/.vis/APPEND_SYSTEM.md`, then
`<workspace>/.vis/APPEND_SYSTEM.md`. The config + file hooks let a project
append house rules without any caller having to pass them.

Full rewrite precedence for the base: `<workspace>/.vis/SYSTEM.md` >
`~/.vis/SYSTEM.md` > config `:system-prompt` map with `:replace? true` >
`CORE_SYSTEM_PROMPT`. When a file/config replaces the base, addenda and
append files are still appended after it.
sourceraw docstring

by-channelclj

(by-channel channel)
source

by-cmdclj

(by-cmd cmd)

Lookup the channel whose :channel/cmd equals cmd. Returns nil when no channel claims that command.

Lookup the channel whose :channel/cmd equals `cmd`. Returns nil
when no channel claims that command.
sourceraw docstring

by-idclj

(by-id id)

Return the session record (UUID :id) or nil.

Return the session record (UUID `:id`) or nil.
sourceraw docstring

cache-env!clj

(cache-env! session-id env)

Insert env into the cache under session-id (UUID, or string normalized via cache-key). Returns {:id <UUID> :environment env}.

Insert `env` into the cache under `session-id` (UUID, or string
normalized via `cache-key`). Returns `{:id <UUID> :environment env}`.
sourceraw docstring

cancel!clj

(cancel! token)

Abort the in-flight turn. Flips the cooperative flag AND runs every registered on-cancel! callback. Each callback is wrapped in its own try/catch so one bad consumer cannot starve the rest. Safe to call multiple times — on the second call the flag is already set, and the callback list has typically drained because workers disposed themselves.

Abort the in-flight turn. Flips the cooperative flag AND runs every
registered `on-cancel!` callback. Each callback is wrapped in its
own `try`/`catch` so one bad consumer cannot starve the rest.
Safe to call multiple times — on the second call the flag is
already set, and the callback list has typically drained because
workers disposed themselves.
sourceraw docstring

cancellation-atomclj

(cancellation-atom token)

Cooperative flag atom — read with @ at iteration boundaries when the consumer can return without external help.

Cooperative flag atom — read with `@` at iteration boundaries when
the consumer can return without external help.
sourceraw docstring

cancellation-set-future!clj

(cancellation-set-future! token fut)

Register a worker Future so cancel! interrupts it. Thin convenience over on-cancel!: wraps .cancel(true) in a thunk and discards the returned dispose! (the future's own completion makes the second cancel a no-op).

Returns the future for convenient threading.

Register a worker `Future` so `cancel!` interrupts it. Thin
convenience over `on-cancel!`: wraps `.cancel(true)` in a thunk
and discards the returned `dispose!` (the future's own completion
makes the second cancel a no-op).

Returns the future for convenient threading.
sourceraw docstring

cancellation-tokenclj

(cancellation-token)

Construct a fresh cancellation token.

The token bundles two things every cancellable boundary needs:

  • ::flag — cooperative boolean atom, polled at iteration boundaries by callers that can return gracefully.
  • ::callbacks — vec of [id thunk] pairs run by cancel! so any number of in-flight workers (provider HTTP call, Python eval future, voice recorder) can register their own hard-cancel hook.

cancellation-set-future! (legacy single-future API) is kept for call sites that have not migrated yet; it now routes through the callback registry too so behaviour stays identical.

Construct a fresh cancellation token.

The token bundles two things every cancellable boundary needs:
  - `::flag`      — cooperative boolean atom, polled at iteration
                     boundaries by callers that can return
                     gracefully.
  - `::callbacks` — vec of `[id thunk]` pairs run by `cancel!` so
                     any number of in-flight workers (provider
                     HTTP call, Python eval future, voice recorder)
                     can register their own hard-cancel hook.

`cancellation-set-future!` (legacy single-future API) is kept for
call sites that have not migrated yet; it now routes through the
callback registry too so behaviour stays identical.
sourceraw docstring

cancellation?clj

(cancellation? e)

True if the given throwable was caused by a cancel! call. Channels should treat this as a normal (cancelled) outcome rather than an error and avoid showing stack traces.

True if the given throwable was caused by a `cancel!` call. Channels
should treat this as a normal (cancelled) outcome rather than an
error and avoid showing stack traces.
sourceraw docstring

cancelled?clj

(cancelled? token)

True once cancel! has been called on this token.

True once `cancel!` has been called on this token.
sourceraw docstring

channelclj

(channel spec)

Build and validate a channel descriptor map.

Build and validate a channel descriptor map.
sourceraw docstring

channel-by-idclj

(channel-by-id id)

Lookup the channel by :channel/id. Returns nil when absent.

Lookup the channel by :channel/id. Returns nil when absent.
sourceraw docstring

channel-contributions-forclj

(channel-contributions-for channel-id)
(channel-contributions-for channel-id slot)

Return registered extension channel contributions for channel-id in extension registration order. With slot, return only contributions for that channel slot. Contributions are passive data; the channel owns each slot's fn arity + return contract.

Return registered extension channel contributions for `channel-id` in
extension registration order. With `slot`, return only contributions for
that channel slot. Contributions are passive data; the channel owns each
slot's fn arity + return contract.
sourceraw docstring

channel-event-listenersclj

source

close!clj

(close! id)
source

close-all!clj

(close-all!)
source

coalesce-formsclj

(coalesce-forms forms)

Merge each maximal run of ADJACENT, successful coalescable native op-cards into a single card. cat/patch coalesce only for the SAME file; format_code coalesces adjacent per-file acks into one roll-up across files. Every other form passes through untouched. The ONE projection both channels apply before rendering an iteration's forms, so repeated tool acks never render as a stack of look-alike sibling bubbles. Always returns a vector.

Merge each maximal run of ADJACENT, successful coalescable native op-cards into
a single card. `cat`/`patch` coalesce only for the SAME file; `format_code`
coalesces adjacent per-file acks into one roll-up across files. Every other
form passes through untouched. The ONE projection both channels apply before
rendering an iteration's forms, so repeated tool acks never render as a stack
of look-alike sibling bubbles. Always returns a vector.
sourceraw docstring

colorclj

(color k)
(color theme-map k)

Return RGB vector for palette token k in theme-map (or selected/default theme).

Return RGB vector for palette token `k` in `theme-map` (or selected/default theme).
sourceraw docstring

commandclj

(command spec)

Build and validate a command map. Children are NOT validated recursively; they're checked the first time dispatch! or render-help walks into them, which keeps dynamic subcommands from forcing their fn at build time.

Build and validate a command map. Children are NOT validated
recursively; they're checked the first time `dispatch!` or
`render-help` walks into them, which keeps dynamic subcommands
from forcing their fn at build time.
sourceraw docstring

config-pathclj

source

configured-providersclj

(configured-providers)

The persisted provider fleet (global + project overlay), priority order, catalog metadata applied (base-url/api-style filled in).

The persisted provider fleet (global + project overlay), priority
order, catalog metadata applied (base-url/api-style filled in).
sourceraw docstring

create!clj

(create! channel)
(create! channel {:keys [title external-id workspace-id]})

Create a brand-new session.

Opts (all optional): :title display title :external-id channel-specific external id :workspace-id pre-spawned workspace to pin the new session to. When omitted, a trunk workspace is auto-minted in create-environment.

Create a brand-new session.

Opts (all optional):
  :title         display title
  :external-id   channel-specific external id
  :workspace-id  pre-spawned workspace to pin the new session to.
                 When omitted, a trunk workspace is auto-minted in
                 create-environment.
sourceraw docstring

create-environmentclj

(create-environment router
                    {:keys [db session channel external-id title workspace-id
                            child]})

Creates a vis environment (component) for session lifecycle and querying.

The environment holds:

  • Python sandbox context with custom bindings + bindings cache
  • DB connection (or shared-mem datasource)
  • Router (LLM provider config)
  • Extension registry atom

Params: router - Required. Result of llm/make-router. opts - Map with :db and optional :session, :channel, :external-id, :title.

:db accepted forms: nil - no DB (sandbox-only execution) :memory - ephemeral in-process SQLite DB path string - persistent SQLite DB at path {:path p} - persistent SQLite DB at path {:datasource ds} - caller-owned DataSource (not closed on dispose)

Returns the vis environment map.

Creates a vis environment (component) for session lifecycle and
querying.

The environment holds:
  - Python sandbox context with custom bindings + bindings cache
  - DB connection (or shared-mem datasource)
  - Router (LLM provider config)
  - Extension registry atom

Params:
  `router` - Required. Result of `llm/make-router`.
  `opts`   - Map with `:db` and optional `:session`,
              `:channel`, `:external-id`, `:title`.

  `:db` accepted forms:
    nil               - no DB (sandbox-only execution)
    :memory           - ephemeral in-process SQLite DB
    path string       - persistent SQLite DB at path
    {:path p}         - persistent SQLite DB at path
    {:datasource ds}  - caller-owned DataSource (not closed on dispose)

Returns the vis environment map.
sourceraw docstring

create-python-contextclj

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

Create the embedded-GraalPy sandbox context with all available bindings.

custom-bindings — map of symbol->value (tool fns + engine values). Fns are wired as Python callables; values are marshalled. Returns:

{:python-context <org.graalvm.polyglot.Context> :sandbox-ns :python ; placeholder (Python has one top scope) :initial-ns-keys #{...baseline globals...}}

roots-fn (optional) — a 0-arg fn returning the current allowed root path strings; when supplied the sandbox gets REAL filesystem access confined to them. Omitted ⇒ no Python filesystem (IO-NONE).

Create the embedded-GraalPy sandbox context with all available bindings.

`custom-bindings` — map of symbol->value (tool fns + engine values). Fns are
wired as Python callables; values are marshalled. Returns:

  {:python-context          <org.graalvm.polyglot.Context>
   :sandbox-ns       :python          ; placeholder (Python has one top scope)
   :initial-ns-keys  #{...baseline globals...}}

`roots-fn` (optional) — a 0-arg fn returning the current allowed root path
strings; when supplied the sandbox gets REAL filesystem access confined to
them. Omitted ⇒ no Python filesystem (IO-NONE).
sourceraw docstring

current-configclj

(current-config)

Return the current provider config. Loads from disk on first call.

Return the current provider config. Loads from disk on first call.
sourceraw docstring

custom-bindingsclj

(custom-bindings env)

Current custom sandbox bindings {sym -> value}.

Current custom sandbox bindings {sym -> value}.
sourceraw docstring

db-create-connection!clj

(db-create-connection! db-spec)

Open a persistence connection from db-spec.

Common spec forms: nil - no DB (returns nil) :memory - in-memory ephemeral store (backend-defined) "path/to.db" - file-backed store (backend-defined) {:backend :sqlite :path ...} - explicit backend selection {:backend :sqlite :datasource ds} - caller-owned DataSource

With a single registered backend, omitting :backend works and the facade tags the returned store map with the chosen backend so all subsequent facade calls dispatch correctly.

Triggers manifest/scan-extensions! on first call so a freshly started JVM with no extensions yet required has a chance to load any backend-providing namespaces from the classpath.

Open a persistence connection from `db-spec`.

Common spec forms:
  nil              - no DB (returns nil)
  :memory          - in-memory ephemeral store (backend-defined)
  "path/to.db"   - file-backed store (backend-defined)
  {:backend :sqlite :path ...}     - explicit backend selection
  {:backend :sqlite :datasource ds} - caller-owned DataSource

With a single registered backend, omitting `:backend` works and the
facade tags the returned store map with the chosen backend so all
subsequent facade calls dispatch correctly.

Triggers `manifest/scan-extensions!` on first call so a freshly
started JVM with no extensions yet required has a chance to load
any backend-providing namespaces from the classpath.
sourceraw docstring

db-delete-session-tree!clj

(db-delete-session-tree! db-info id)
source

db-dispose-connection!clj

(db-dispose-connection! store)
source

db-dispose-shared-connection!clj

(db-dispose-shared-connection!)

Close the shared connection if one is open. Idempotent.

Close the shared connection if one is open. Idempotent.
sourceraw docstring

db-error->user-messageclj

(db-error->user-message e)

Translate a persistence exception into something a human can act on. Backend adapters own backend-specific recognition; unknown errors fall back to (ex-message e).

Translate a persistence exception into something a human can act on.
Backend adapters own backend-specific recognition; unknown errors fall
back to `(ex-message e)`.
sourceraw docstring

db-find-session-by-externalclj

(db-find-session-by-external db-info channel ext-id)
source

db-fork-session!clj

(db-fork-session! db-info session-id opts)
source

db-get-extension-aggregateclj

(db-get-extension-aggregate db-info opts)
source

db-get-sessionclj

(db-get-session db-info ref)
source

db-infoclj

(db-info)

Return the process-wide shared DB connection bound to (config/resolve-db-spec). Thin wrapper over persistance.core/db-shared-connection! that fills in the default db-spec so frontend callers stay clear of config resolution.

Return the process-wide shared DB connection bound to
`(config/resolve-db-spec)`. Thin wrapper over
`persistance.core/db-shared-connection!` that fills in the default db-spec
so frontend callers stay clear of config resolution.
sourceraw docstring

db-latest-session-state-idclj

(db-latest-session-state-id db-info session-id)
source

db-list-extension-aggregatesclj

(db-list-extension-aggregates db-info opts)
source

db-list-iteration-attachmentsclj

(db-list-iteration-attachments db-info iteration-id)
source

db-list-iterations-attachmentsclj

(db-list-iterations-attachments db-info iteration-ids)
source

db-list-session-attachmentsclj

(db-list-session-attachments db-info session-id)
source

db-list-session-statesclj

(db-list-session-states db-info session-id)
source

db-list-session-turn-iterationsclj

(db-list-session-turn-iterations db-info session-turn-ref)
source

db-list-session-turn-statesclj

(db-list-session-turn-states db-info session-turn-id)
source

db-list-session-turnsclj

(db-list-session-turns db-info session-ref)
source

db-list-session-turns-by-statusclj

(db-list-session-turns-by-status db-info status)
source

db-list-sessionsclj

(db-list-sessions db-info channel)
source

db-list-turn-all-attachmentsclj

(db-list-turn-all-attachments db-info session-turn-soul-id)
source

db-list-turn-attachmentsclj

(db-list-turn-attachments db-info session-turn-soul-id)
source

db-list-turns-attachmentsclj

(db-list-turns-attachments db-info session-turn-soul-ids)
source

db-load-ctx-historyclj

(db-load-ctx-history db-info session-id)
source

db-load-latest-ctxclj

(db-load-latest-ctx db-info session-id)
source

db-log!clj

(db-log! db-info opts)
source

db-read-attachmentclj

(db-read-attachment db-info attachment-id)
source

db-resolve-session-idclj

(db-resolve-session-id db-info sel)
source

db-retry-session-turn!clj

(db-retry-session-turn! db-info session-turn-soul-id opts)
source

(db-search db-info query opts)

Backend-neutral full-text search facade. Delegates to the registered persistence backend, which RENDERS the neutral query DSL into its native full-text query and runs it. No caller passes an engine dialect — only the DSL in search-query-dsl-doc.

query is the DSL — a string (implicit-AND of its words) or a DSL map. opts: :owner-table restrict to one owner table (string) :field restrict to one indexed field (string) :limit max hits (backend default applies when nil)

Returns a vector of hits sorted by relevance (best first), each {:owner-table :owner-id :field :snippet :rank}. Backends MUST honor the DSL; an engine that cannot express a node should degrade it (e.g. :near -> :all), never reject well-formed DSL. A MALFORMED query (e.g. a lone :not) may throw — that is a DSL logic error, distinct from un-matchable content.

Backend-neutral full-text search facade. Delegates to the registered
persistence backend, which RENDERS the neutral query DSL into its native
full-text query and runs it. No caller passes an engine dialect — only the
DSL in `search-query-dsl-doc`.

`query` is the DSL — a string (implicit-AND of its words) or a DSL map.
`opts`:
  :owner-table  restrict to one owner table (string)
  :field        restrict to one indexed field (string)
  :limit        max hits (backend default applies when nil)

Returns a vector of hits sorted by relevance (best first), each
`{:owner-table :owner-id :field :snippet :rank}`. Backends MUST honor the
DSL; an engine that cannot express a node should degrade it (e.g. :near ->
:all), never reject well-formed DSL. A MALFORMED query (e.g. a lone :not)
may throw — that is a DSL logic error, distinct from un-matchable content.
sourceraw docstring

db-shared-connection!clj

(db-shared-connection! db-spec)

Return the process-wide shared persistence connection for db-spec, opening it on first call and caching the handle for the lifetime of the JVM. Subsequent calls return the cached handle regardless of the db-spec argument - the singleton intentionally pins to the first spec it saw.

Pair with db-dispose-shared-connection! on process shutdown.

Return the process-wide shared persistence connection for `db-spec`,
 opening it on first call and caching the handle for the lifetime of
 the JVM. Subsequent calls return the cached handle regardless of
 the `db-spec` argument - the singleton intentionally pins to the
 first spec it saw.

Pair with `db-dispose-shared-connection!` on process shutdown.
sourceraw docstring

db-store-iteration!clj

(db-store-iteration! db-info opts)

Same delegating shape as the macro-defined fns, but with input validation kept here so every backend gets the same precondition guarantees for free.

Same delegating shape as the macro-defined fns, but with input
validation kept here so every backend gets the same precondition
guarantees for free.
sourceraw docstring

db-store-session!clj

(db-store-session! db-info opts)
source

db-store-session-turn!clj

(db-store-session-turn! db-info opts)
source

db-sweep-orphaned-running-turns!clj

(db-sweep-orphaned-running-turns!)
(db-sweep-orphaned-running-turns! db)

Mark every :running turn as :interrupted. Run at process start to clean up turns that crashed or were killed mid-write so the next turn's handover digest renders the right outcome instead of guessing. Returns the number of turns swept.

Mark every `:running` turn as `:interrupted`. Run at process start
to clean up turns that crashed or were killed mid-write so the next
turn's handover digest renders the right outcome instead of guessing.
Returns the number of turns swept.
sourceraw docstring

db-turn-historyclj

(db-turn-history db-info session-ref)
source

db-update-session-title!clj

(db-update-session-title! db-info ref title)
source

db-update-session-turn!clj

(db-update-session-turn! db-info session-turn-id opts)
source

db-workspace-insert!clj

(db-workspace-insert! db-info opts)
source

default-themeclj

source

default-theme-idclj

The built-in theme id used when config has no explicit theme.

The built-in theme id used when config has no explicit theme.
sourceraw docstring

delete!clj

(delete! id)
source

deregister-backend!clj

(deregister-backend! id)
source

deregister-channel!clj

(deregister-channel! id)
source

deregister-cmd!clj

(deregister-cmd! nm)
(deregister-cmd! parent nm)

Remove a registered command. parent defaults to [] (top-level).

Remove a registered command. `parent` defaults to `[]` (top-level).
sourceraw docstring

deregister-extension!clj

(deregister-extension! ns-sym)

Drop an extension from the global registry AND reverse every side effect register-extension! dispatched: deregister each CLI subcommand, channel, provider, and persistence backend. Returns nil.

Plan caveat: side-effect cleanup on :removed extensions. Used by Stays available for diagnostic surfaces.

Drop an extension from the global registry AND reverse every side
effect `register-extension!` dispatched: deregister each CLI
subcommand, channel, provider, and persistence backend. Returns nil.

Plan caveat: side-effect cleanup on `:removed` extensions. Used by
Stays available for diagnostic surfaces.
sourceraw docstring

deregister-provider!clj

(deregister-provider! id)
source

diff-line-kindclj

(diff-line-kind line)

Classify ONE unified-diff line for channel-neutral colouring: :meta (file headers ---/+++), :hunk (@@), :add (+), :del (-), or :ctx (context / unchanged). The SINGLE classifier both channels share — the TUI maps the kind to an ANSI colour, the web to a CSS class — so a diff fence colours IDENTICALLY in both, from one source of truth (no per-channel copy to drift).

Classify ONE unified-diff line for channel-neutral colouring: `:meta` (file
headers `---`/`+++`), `:hunk` (`@@`), `:add` (`+`), `:del` (`-`), or `:ctx`
(context / unchanged). The SINGLE classifier both channels share — the TUI maps
the kind to an ANSI colour, the web to a CSS class — so a `diff` fence colours
IDENTICALLY in both, from one source of truth (no per-channel copy to drift).
sourceraw docstring

discover-extensions!clj

(discover-extensions!)

Public entry point for vis's extension wiring.

First loads the BUILT-IN extensions (load-builtin-extensions! — core modules like the foundation v/ kernel that register via the same API but ship in the main jar). Then runs manifest/scan-extensions! (which scans every META-INF/vis-extension/vis.edn, requires every namespace listed under each manifest's :nses key, and returns the merged parsed manifests) and merges those manifests into this namespace's manifest registry. Returns the count of namespaces declared under :nses across the merged manifests.

Idempotent on every layer.

Public entry point for vis's extension wiring.

First loads the BUILT-IN extensions (`load-builtin-extensions!` — core
modules like the foundation `v/` kernel that register via the same API but
ship in the main jar). Then runs `manifest/scan-extensions!` (which scans
every `META-INF/vis-extension/vis.edn`, `require`s every namespace listed
under each manifest's `:nses` key, and returns the merged parsed manifests)
and merges those manifests into this namespace's manifest registry. Returns
the count of namespaces declared under `:nses` across the merged manifests.

Idempotent on every layer.
sourceraw docstring

dismiss!clj

(dismiss! id)

Drop the entry with the given id, regardless of its :until deadline. Returns true when an entry was actually removed. Watchers fire when the value changed.

Drop the entry with the given id, regardless of its `:until`
deadline. Returns true when an entry was actually removed.
Watchers fire when the value changed.
sourceraw docstring

dismiss-all!clj

(dismiss-all!)

Drop every notification. Returns the new (empty) vec.

Drop every notification. Returns the new (empty) vec.
sourceraw docstring

dispatch!clj

(dispatch! root args)
(dispatch! root args {:keys [print-fn]})

Resolve the command for args against root, parse the residual tokens against the resolved command's :cmd/args spec, and call its :cmd/run-fn with [parsed-args residual].

When the command lacks :cmd/run-fn and has subcommands, prints help for that level via render-command. When --help/-h is in the residual, also prints help.

Returns: {:status :ok :command cmd :result <whatever run-fn returned>} {:status :help :command cmd :help-text <string>} {:status :no-match :args args}

Resolve the command for `args` against `root`, parse the residual
tokens against the resolved command's `:cmd/args` spec, and call
its `:cmd/run-fn` with `[parsed-args residual]`.

When the command lacks `:cmd/run-fn` and has subcommands, prints
help for that level via `render-command`. When `--help`/`-h` is
in the residual, also prints help.

Returns:
  {:status :ok       :command cmd :result <whatever run-fn returned>}
  {:status :help     :command cmd :help-text <string>}
  {:status :no-match :args args}
sourceraw docstring

display-labelclj

(display-label pid)

Human-readable label for a provider id. Never persisted.

Human-readable label for a provider id. Never persisted.
sourceraw docstring

display-model-nameclj

(display-model-name m)

DISPLAY-ONLY normalization of a model id: path-style ids (google/gemma-4-12b-qat, org/model as LM Studio / HF name them) render with the slashes flattened to dashes (google-gemma-4-12b-qat), so a provider/model label never reads as three ambiguous segments. The wire/config id keeps its slashes — never feed this back to a router or provider. nil-safe; non-strings and blanks return nil.

DISPLAY-ONLY normalization of a model id: path-style ids
(`google/gemma-4-12b-qat`, `org/model` as LM Studio / HF name them)
render with the slashes flattened to dashes (`google-gemma-4-12b-qat`),
so a `provider/model` label never reads as three ambiguous segments.
The wire/config id keeps its slashes — never feed this back to a
router or provider. nil-safe; non-strings and blanks return nil.
sourceraw docstring

dispose-environment!clj

(dispose-environment! environment)

Disposes a vis environment and releases resources. For persistent DBs (created with :path), data is preserved. For disposable DBs, all data is deleted.

A sub_loop CHILD env BORROWS the parent's DB connection (:owns-db? false) — disposing the child must NOT close it, or the parent loses its DB mid-turn.

Disposes a vis environment and releases resources. For persistent DBs
(created with `:path`), data is preserved. For disposable DBs, all
data is deleted.

A sub_loop CHILD env BORROWS the parent's DB connection (`:owns-db?` false) —
disposing the child must NOT close it, or the parent loses its DB mid-turn.
sourceraw docstring

doctor-exit-codeclj

(doctor-exit-code messages)

Compute the doctor exit code from a vec of messages. 0 / 1 / 2 by max level. Plan Q19/d2.

Compute the doctor exit code from a vec of messages. 0 / 1 / 2 by
max level. Plan Q19/d2.
sourceraw docstring

doctor-format-outputclj

(doctor-format-output messages)
(doctor-format-output messages {:keys [use-ansi?]})

Build the full TTY output from a vec of messages. Empty result prints a placeholder. Caller routes it to stdout. ANSI is auto-detected; pass :use-ansi? to override.

Build the full TTY output from a vec of messages. Empty result
prints a placeholder. Caller routes it to stdout. ANSI is
auto-detected; pass `:use-ansi?` to override.
sourceraw docstring

doctor-startup-hintclj

(doctor-startup-hint)
(doctor-startup-hint environment)

Return a single-line string like ⚠ vis: 2 issues detected - run \bin/vis doctor` for details.when warn/error count > 0; nil otherwise. Caller decides whether to print (skipped when the command being dispatched ISvis doctor`).

Return a single-line string like `⚠ vis: 2 issues detected - run
\`bin/vis doctor\` for details.` when warn/error count > 0;
nil otherwise. Caller decides whether to print (skipped when the
command being dispatched IS `vis doctor`).
sourceraw docstring

dsclj

(ds db-info)
source

env-forclj

(env-for id)
source

error-messageclj

(error-message v)

Build an error message string from a Throwable, map, or string.

Build an error message string from a Throwable, map, or string.
sourceraw docstring

extensioncljmacro

(extension spec)

Build extension spec and stamp caller namespace for reload/source tracking.

Build extension spec and stamp caller namespace for reload/source tracking.
sourceraw docstring

extension-aggregate-create!clj

(extension-aggregate-create! env row)

Append one extension-owned aggregate row. Returns the decoded row. Extension id is always filled from current extension callback context.

Append one extension-owned aggregate row. Returns the decoded row.
Extension id is always filled from current extension callback context.
sourceraw docstring

extension-aggregate-getclj

(extension-aggregate-get env query)

Return one extension-owned aggregate row by query, or nil. Defaults to the latest row when the query is not unique.

Return one extension-owned aggregate row by query, or nil. Defaults to the
latest row when the query is not unique.
sourceraw docstring

extension-aggregate-put!clj

(extension-aggregate-put! env row)

Upsert one singleton extension-owned aggregate row for key/kind/scope. Returns the decoded row.

Upsert one singleton extension-owned aggregate row for key/kind/scope.
Returns the decoded row.
sourceraw docstring

extension-delete-aggregate!clj

(extension-delete-aggregate! env query)

Delete extension-owned aggregate rows matching query. Cross-extension delete is impossible through this API because extension id is runtime-filled.

Delete extension-owned aggregate rows matching query. Cross-extension delete
is impossible through this API because extension id is runtime-filled.
sourceraw docstring

extension-env-overridesclj

(extension-env-overrides)

Persisted extension environment overrides from ~/.vis/config.edn under :environment. Keys are environment variable names as strings. Values are strings. This does NOT mutate the process environment; extension code should call extension-env-value when it wants config-over-env resolution.

Persisted extension environment overrides from `~/.vis/config.edn`
under `:environment`. Keys are environment variable names as
strings. Values are strings. This does NOT mutate the process
environment; extension code should call `extension-env-value` when
it wants config-over-env resolution.
sourceraw docstring

extension-env-statusclj

(extension-env-status name)

Return source and value metadata for an extension-declared env var. :source is one of :config, :env, or :unset.

Return source and value metadata for an extension-declared env var.
`:source` is one of `:config`, `:env`, or `:unset`.
sourceraw docstring

extension-env-valueclj

(extension-env-value name)

Resolve an extension-declared env var as config override -> real env. Blank/missing values return nil.

Resolve an extension-declared env var as config override -> real env.
Blank/missing values return nil.
sourceraw docstring

extension-id-of-nsclj

(extension-id-of-ns ns-sym)

Reverse lookup: given a namespace symbol, return the extension id that registered it under :nses, or nil.

Reverse lookup: given a namespace symbol, return the extension id
that registered it under `:nses`, or `nil`.
sourceraw docstring

extension-list-aggregatesclj

(extension-list-aggregates env query)

List extension-owned aggregate rows. The current extension id is always applied; normal extension code cannot list another extension's rows.

List extension-owned aggregate rows. The current extension id is always
applied; normal extension code cannot list another extension's rows.
sourceraw docstring

extension-load-failuresclj

(extension-load-failures)

Vec of {:source :extension-load :extension-id :extension-ns :path :class :reason} maps for every extension namespace whose (require ns) threw during the most recent classpath scan, plus any vis.edn that failed to parse. Empty vec when every namespace loaded cleanly.

The shape of each entry matches (:project ctx) :warnings so callers can splice it straight into environment context.

Vec of `{:source :extension-load :extension-id :extension-ns :path
:class :reason}` maps for every extension namespace whose
`(require ns)` threw during the most recent classpath scan, plus
any vis.edn that failed to parse. Empty vec when every namespace
loaded cleanly.

The shape of each entry matches `(:project ctx) :warnings` so
callers can splice it straight into environment context.
sourceraw docstring

extension-namespacesclj

(extension-namespaces id)

Vector of namespaces declared under :nses for an id. Empty when the id is unknown.

Vector of namespaces declared under `:nses` for an id. Empty when
the id is unknown.
sourceraw docstring

extension-source-markers-ofclj

(extension-source-markers-of ns-sym)

Lookup the source markers stored for ns-sym. Returns the marker map ({:source-paths :source-mtime-max :source-hash-sha256}) or nil when the extension was never registered (or its markers computation failed at register time).

Lookup the source markers stored for `ns-sym`. Returns the marker
map (`{:source-paths :source-mtime-max :source-hash-sha256}`) or
nil when the extension was never registered (or its markers
computation failed at register time).
sourceraw docstring

extension-theme-settingsclj

(extension-theme-settings)
(extension-theme-settings theme-registry)

Return a registry in extension :ext/theme compact settings shape.

Return a registry in extension `:ext/theme` compact settings shape.
sourceraw docstring

extension-update-aggregate!clj

(extension-update-aggregate! env query f & args)

Atomic singleton update. Reads the current content for query, applies f, and writes the returned value as :content. Query must include :key and :kind.

Atomic singleton update. Reads the current content for query, applies f, and
writes the returned value as :content. Query must include :key and :kind.
sourceraw docstring

extract-codeclj

(extract-code input)

Walk the AST and return a vector of strings, one per [:code ...] block, in source order. Used by vis --code.

Walk the AST and return a vector of strings, one per [:code ...] block,
in source order. Used by `vis --code`.
sourceraw docstring

extract-textclj

(extract-text input)

Walk the AST and return concatenated plain-text content of all [:p] blocks (inline content stripped). Used by voice TTS.

Walk the AST and return concatenated plain-text content of all [:p]
blocks (inline content stripped). Used by voice TTS.
sourceraw docstring

final-answer-code-error-messageclj

(final-answer-code-error-message exception)
source

find-leafclj

(find-leaf root args)

Walk the tree from root consuming tokens until either:

  • a child matches and has no further subcommands
  • or no child matches the next token

Returns {:command resolved-cmd :path [name...] :residual [token...]}, or nil when even the root's name doesn't match args[0]. The residual is everything LEFT after the resolved command name.

Walk the tree from `root` consuming tokens until either:
  - a child matches and has no further subcommands
  - or no child matches the next token

Returns `{:command resolved-cmd :path [name...] :residual [token...]}`,
or nil when even the root's name doesn't match args[0]. The
residual is everything LEFT after the resolved command name.
sourceraw docstring

find-namedclj

(find-named root args)

Like find-leaf, but matches against the bare arg vector ignoring the root command's name (the way cli/-main typically gets called). Useful when the root is implicit and you just want the resolved subcommand for the given args.

Like `find-leaf`, but matches against the bare arg vector ignoring
the root command's name (the way `cli/-main` typically gets called).
Useful when the root is implicit and you just want the resolved
subcommand for the given args.
sourceraw docstring

first-run?clj

(first-run?)

True on a genuine FIRST run: no provider configured AND no global ~/.vis/config.edn has ever been written. Distinguishes the full welcome (brand-new user) from a returning user who merely has no provider right now (e.g. removed their only one).

True on a genuine FIRST run: no provider configured AND no global
`~/.vis/config.edn` has ever been written. Distinguishes the full welcome
(brand-new user) from a returning user who merely has no provider right now
(e.g. removed their only one).
sourceraw docstring

for-telegram-chat!clj

(for-telegram-chat! chat-id)
source

form->displayclj

(form->display m)

Project the canonical display fields off a source map (loop chunk/block, a restored row) — the ONE projection every form builder + the gateway uses instead of hand-listing keys. Drops nils so a merge never stamps empty keys.

Project the canonical display fields off a source map (loop chunk/block, a
restored row) — the ONE projection every form builder + the gateway uses
instead of hand-listing keys. Drops nils so a merge never stamps empty keys.
sourceraw docstring

form-display-keysclj

Every field carried VERBATIM from the loop to a channel to render a form — the complete passthrough set, NOT the handful the gateway computes/renames itself (:stdout/:error are bounded, :silent/:duration_ms are derived; those stay explicit gateway overrides). Add a new verbatim display field HERE and ->display/<-wire flow it across every boundary.

Grouped: the source the model wrote, the result surfaces (raw + the pre-rendered op-card), the native-tool badge identity (label + colour), the per-form display projections, the tool-call linkage, and the repair/timeout flags channels surface.

Every field carried VERBATIM from the loop to a channel to render a form — the
complete passthrough set, NOT the handful the gateway computes/renames itself
(`:stdout`/`:error` are bounded, `:silent`/`:duration_ms` are derived; those
stay explicit gateway overrides). Add a new verbatim display field HERE and
`->display`/`<-wire` flow it across every boundary.

Grouped: the source the model wrote, the result surfaces (raw + the
pre-rendered op-card), the native-tool badge identity (label + colour), the
per-form display projections, the tool-call linkage, and the repair/timeout
flags channels surface.
sourceraw docstring

form<-wireclj

(form<-wire event)

Read the canonical display fields back off a gateway WIRE event into a form, tolerant of snake_case keys and re-keywording the keyword-valued fields. The single inbound projection the channels use — the mirror of ->display.

Read the canonical display fields back off a gateway WIRE event into a form,
tolerant of snake_case keys and re-keywording the keyword-valued fields. The
single inbound projection the channels use — the mirror of `->display`.
sourceraw docstring

format-clojureclj

(format-clojure code-str _width)

Source is shown as written — no reformatting. Returns code-str trimmed of trailing whitespace (or unchanged when not a string).

Source is shown as written — no reformatting. Returns `code-str`
trimmed of trailing whitespace (or unchanged when not a string).
sourceraw docstring

format-costclj

(format-cost cost)

Render a dollar cost as '~$0.006954' (six decimal places, US locale). Returns nil when cost is nil, zero, negative, or non-numeric. Accepts either the bare number or a :total-cost map. Detailed cost maps render the total first and the breakdown parenthesized, in order: in, cached, write, out — e.g. '~$0.006954 (in ~$0.001200, cached ~$0.000400, out ~$0.005354)'. The parenthesized breakdown renders only when at least two of those slots carry a positive value; otherwise just the total.

Render a dollar cost as '~$0.006954' (six decimal places, US
locale). Returns nil when `cost` is nil, zero, negative, or
non-numeric. Accepts either the bare number or a `:total-cost`
map. Detailed cost maps render the total first and the breakdown
parenthesized, in order: in, cached, write, out — e.g.
'~$0.006954 (in ~$0.001200, cached ~$0.000400, out ~$0.005354)'.
The parenthesized breakdown renders only when at least two of
those slots carry a positive value; otherwise just the total.
sourceraw docstring

format-dateclj

(format-date d)

Format a java.util.Date as dd-MM-yyyy HH:mm in local timezone.

Format a `java.util.Date` as `dd-MM-yyyy HH:mm` in local timezone.
sourceraw docstring

format-durationclj

(format-duration ms)

Human-readable millisecond duration. e.g. 2.3s, 1m 15s. Always uses Locale/US so the decimal separator is a dot regardless of the JVM default locale. Coerces the input to long up-front because callers routinely pass a double from (/ ns 1e6).

Human-readable millisecond duration. e.g. `2.3s`, `1m 15s`. Always
uses Locale/US so the decimal separator is a dot regardless of
the JVM default locale. Coerces the input to long up-front because
callers routinely pass a double from `(/ ns 1e6)`.
sourceraw docstring

format-errorclj

(format-error v)

Add the standard ERROR: prefix to an error message, idempotent.

Add the standard `ERROR: ` prefix to an error message, idempotent.
sourceraw docstring

format-iterationsclj

(format-iterations n)
(format-iterations n {:keys [silent-count]})

Render an iteration count as '1 iter' or '3 iters'. Returns nil when n is nil or non-numeric. Optional :silent-count appends hidden/silent bookkeeping count, e.g. '3 iters (2 silent)'.

Render an iteration count as '1 iter' or '3 iters'. Returns nil
when `n` is nil or non-numeric. Optional `:silent-count` appends
hidden/silent bookkeeping count, e.g. '3 iters (2 silent)'.
sourceraw docstring

format-meta-lineclj

(format-meta-line result)
(format-meta-line result opts)

Single-line turn summary for plain-text surfaces (the CLI [...] bracket and the Telegram tagline): the shared meta-summary-line with the fallback note folded inline. The TUI instead uses meta-summary-line + meta-fallback-note directly so it can float the note on its own faint row — same words, same numbers, just two rows. Returns "" when there's nothing to show.

Single-line turn summary for plain-text surfaces (the CLI `[...]` bracket and
the Telegram tagline): the shared `meta-summary-line` with the fallback note
folded inline. The TUI instead uses `meta-summary-line` + `meta-fallback-note`
directly so it can float the note on its own faint row — same words, same
numbers, just two rows. Returns "" when there's nothing to show.
sourceraw docstring

format-tokensclj

(format-tokens {:keys [input output] :as tokens})

Render token counts in the canonical compact grouped form: 'tok <input>→<output> (cached <cached-input>)' when cached input is positive, otherwise 'tok <input>→<output>'.

The arrow reads 'prompt produced completion'. Cached is cached input tokens, parenthesized because provider APIs report cache hits inside prompt usage. :cached is the provider field; :cached-input / :input-cached are accepted aliases so usage maps can name the direction explicitly.

Cache visibility: the (cached N) segment renders only when N is positive. Zero / missing cache info stays hidden so meta lines do not show noisy (cached 0) decorations.

Returns nil when no known field carries a number.

Render token counts in the canonical compact grouped form:
'tok <input>→<output> (cached <cached-input>)' when cached input is
positive, otherwise 'tok <input>→<output>'.

The arrow reads 'prompt produced completion'. Cached is cached
input tokens, parenthesized because provider APIs report cache
hits inside prompt usage. `:cached` is the provider field;
`:cached-input` / `:input-cached` are accepted aliases so usage
maps can name the direction explicitly.

Cache visibility: the `(cached N)` segment renders only when N is
positive. Zero / missing cache info stays hidden so meta lines do
not show noisy `(cached 0)` decorations.

Returns nil when no known field carries a number.
sourceraw docstring

gateway-attach-turn-sync!clj

(gateway-attach-turn-sync! sid tid {:keys [on-event]})

Attach to an ALREADY-submitted turn tid on sid and block until it reaches a terminal event, returning the same engine-shaped result as submit-turn-sync!.

Creates NO new turn: it drives in-process (TUI) rendering for a turn the gateway queued and then auto-drains, so a busy-time submission becomes a real gateway queued record instead of a client-side shadow queue. Optional :on-event fires for every replay/live event of tid.

Attach to an ALREADY-submitted turn `tid` on `sid` and block until it reaches a
terminal event, returning the same engine-shaped result as `submit-turn-sync!`.

Creates NO new turn: it drives in-process (TUI) rendering for a turn the gateway
queued and then auto-drains, so a busy-time submission becomes a real gateway
queued record instead of a client-side shadow queue. Optional `:on-event` fires
for every replay/live event of `tid`.
sourceraw docstring

gateway-auth-required?clj

(gateway-auth-required?)

True when this gateway instance demands the bearer token. OFF by default on a loopback bind (a localhost single-user daemon — the token dance is pure friction there); ALWAYS on for a non-loopback bind; --require-token forces it on loopback too.

True when this gateway instance demands the bearer token. OFF by
default on a loopback bind (a localhost single-user daemon — the
token dance is pure friction there); ALWAYS on for a non-loopback
bind; `--require-token` forces it on loopback too.
sourceraw docstring

gateway-cancel-turn!clj

(gateway-cancel-turn! sid tid)

Fire the cancellation token of a running turn. Returns {:status "cancelling"} or {:error ...}.

Fire the cancellation token of a running turn. Returns
`{:status "cancelling"}` or `{:error ...}`.
sourceraw docstring

gateway-close-session!clj

(gateway-close-session! sid)

DELETE a session: dispose the live environment, trash the session's draft clones (primary + auto-cloned filesystem roots — only DRAFTS have clones; a trunk workspace's roots are the user's real dirs and are never touched), then delete the session tree. Idempotent. NOTE: this is the DELETE path — merely quitting/closing a session (navigating away, no server call) keeps the draft intact so it can be resumed.

DELETE a session: dispose the live environment, trash the session's draft
clones (primary + auto-cloned filesystem roots — only DRAFTS have clones; a
trunk workspace's roots are the user's real dirs and are never touched),
then delete the session tree. Idempotent. NOTE: this is the DELETE path —
merely quitting/closing a session (navigating away, no server call) keeps
the draft intact so it can be resumed.
sourceraw docstring

gateway-context-snapshotclj

(gateway-context-snapshot sid)

The read-only ctx mirror the model sees as its bound session (ctx-loop/session-snapshot), for an existing session, ENRICHED for the USER with :session/archived (the GC'd/summarized entities that are no longer in the model's live ctx). Resolving the env through lp/env-for rehydrates an evicted session on demand. nil when the session does not exist.

The read-only ctx mirror the model sees as its bound `session`
(`ctx-loop/session-snapshot`), for an existing session, ENRICHED for
the USER with `:session/archived` (the GC'd/summarized entities that are
no longer in the model's live ctx). Resolving the env
through `lp/env-for` rehydrates an evicted session on demand.
nil when the session does not exist.
sourceraw docstring

gateway-create-session!clj

(gateway-create-session! {:keys [channel title external-id workspace-id]})

Create a fresh gateway-managed session. Defaults to :api, but in-process clients such as the TUI can pass :channel :tui and still use the same gateway turn/event machinery without pretending to be an HTTP client.

Create a fresh gateway-managed session. Defaults to `:api`, but in-process
clients such as the TUI can pass `:channel :tui` and still use the same
gateway turn/event machinery without pretending to be an HTTP client.
sourceraw docstring

gateway-current-seqclj

(gateway-current-seq sid)

Highest event :seq assigned for sid so far. Subscribing with this as the cursor yields a live-only stream (empty replay).

Highest event `:seq` assigned for `sid` so far. Subscribing with this
as the cursor yields a live-only stream (empty replay).
sourceraw docstring

gateway-delete-queued-turn!clj

(gateway-delete-queued-turn! sid tid)

Remove a queued turn before it starts. Returns deleted status or an error.

Remove a queued turn before it starts. Returns deleted status or an error.
sourceraw docstring

gateway-deregister-routes!clj

(gateway-deregister-routes! id)
source

gateway-events-sinceclj

(gateway-events-since sid cursor)

Read-only peek at the replay ring: stored events with :seq > cursor, oldest first. Lets a page renderer locate the running turn's turn.started seq so its SSE reconnect can replay the WHOLE in-flight turn instead of only what happens after connect.

Read-only peek at the replay ring: stored events with `:seq` > cursor,
oldest first. Lets a page renderer locate the running turn's
`turn.started` seq so its SSE reconnect can replay the WHOLE in-flight
turn instead of only what happens after connect.
sourceraw docstring

gateway-get-turnclj

(gateway-get-turn sid tid)

Wire view of one turn record, or nil.

Wire view of one turn record, or nil.
sourceraw docstring

gateway-list-sessionsclj

(gateway-list-sessions)
(gateway-list-sessions channel)

Wire souls for every persisted session.

CROSS-CHANNEL by default (channel = :all): a conversation started in the web is visible in the TUI and vice-versa. Pass a specific channel keyword only when a caller genuinely needs a single-channel slice (e.g. Telegram resolving a chat by external-id).

Wire souls for every persisted session.

CROSS-CHANNEL by default (`channel` = `:all`): a conversation started
in the web is visible in the TUI and vice-versa. Pass a specific
channel keyword only when a caller genuinely needs a single-channel
slice (e.g. Telegram resolving a chat by external-id).
sourceraw docstring

gateway-list-turnsclj

(gateway-list-turns sid)

Wire views of every turn for sid, newest first: persisted history hydrated from the engine DB (survives daemon restarts), plus only genuinely live gateway overlay rows (running/queued or terminal rows not yet visible in persistence).

DEDUP: the gateway's tid is NOT the engine's persisted row id - the engine mints its own id inside send!. Once the durable row is visible, prefer it: it owns the iteration trace. Keeping the completed gateway row alongside the persisted row rendered the last request/response twice after refresh, with the transient duplicate missing the iterations disclosure.

Wire views of every turn for `sid`, newest first: persisted history hydrated
from the engine DB (survives daemon restarts), plus only genuinely live gateway
overlay rows (running/queued or terminal rows not yet visible in persistence).

DEDUP: the gateway's `tid` is NOT the engine's persisted row id - the engine
mints its own id inside `send!`. Once the durable row is visible, prefer it:
it owns the iteration trace. Keeping the completed gateway row alongside the
persisted row rendered the last request/response twice after refresh, with the
transient duplicate missing the iterations disclosure.
sourceraw docstring

gateway-reconcile-running-turns!clj

(gateway-reconcile-running-turns!)

Gateway facade for startup/client resume reconciliation of orphaned running turns.

Gateway facade for startup/client resume reconciliation of orphaned running turns.
sourceraw docstring

gateway-register-routes!clj

(gateway-register-routes! id contribution)

Imperative escape hatch: register (or replace, by id) a route contribution from an embedded/REPL caller. Extensions should prefer the declarative :gateway.slot/http-routes channel-contribution slot — the gateway pulls it with no registration call at all.

Imperative escape hatch: register (or replace, by `id`) a route
contribution from an embedded/REPL caller. Extensions should prefer
the declarative `:gateway.slot/http-routes` channel-contribution slot
— the gateway pulls it with no registration call at all.
sourceraw docstring

gateway-release-session!clj

(gateway-release-session! sid)

Release the live runtime for a session while keeping persisted data resumable.

This is the gateway facade for local clients that are merely closing a view (for example a TUI tab or process exit). Use close-session! for DELETE.

Release the live runtime for a session while keeping persisted data resumable.

This is the gateway facade for local clients that are merely closing a view
(for example a TUI tab or process exit). Use `close-session!` for DELETE.
sourceraw docstring

gateway-running?clj

(gateway-running?)
source

gateway-session-modelclj

(gateway-session-model sid)

The session's persisted model preference as {:provider :model} (DB-backed shared store), or nil for the router default.

The session's persisted model preference as `{:provider :model}`
(DB-backed shared store), or nil for the router default.
sourceraw docstring

gateway-session-model-cachedclj

(gateway-session-model-cached sid)

Cached variant of session-model for hot render paths. Still part of the gateway facade: callers do not reach into the session-model store directly.

Cached variant of `session-model` for hot render paths. Still part of the
gateway facade: callers do not reach into the session-model store directly.
sourceraw docstring

gateway-session-workspaceclj

(gateway-session-workspace sid)

Workspace state for a channel surface (the web footer AND the TUI directory picker): {:id :draft? :root :repo-root :label :fork-ms :filesystem-roots} for the session pinned to sid (soul id), or nil. :id is the workspace-id every filesystem-root mutation (add/remove-filesystem-root!) needs — WITHOUT it the TUI picker treats the session as read-only and C-a silently no-ops. :filesystem-roots is the normalized [{:trunk :clone :fork-ms}]. Lets the footer announce that the session — and its extra roots — are isolated drafts. Resolves soul → latest state → workspace; never throws.

Workspace state for a channel surface (the web footer AND the TUI
directory picker): `{:id :draft? :root :repo-root :label :fork-ms
:filesystem-roots}` for the session pinned to `sid` (soul id), or nil.
`:id` is the workspace-id every filesystem-root mutation
(`add/remove-filesystem-root!`) needs — WITHOUT it the TUI picker treats the
session as read-only and C-a silently no-ops. `:filesystem-roots` is the
normalized `[{:trunk :clone :fork-ms}]`. Lets the footer announce that the
session — and its extra roots — are isolated drafts. Resolves soul → latest
state → workspace; never throws.
sourceraw docstring

gateway-set-session-model!clj

(gateway-set-session-model! sid provider model)

Set (or clear, with blank model) the per-session PROVIDER + MODEL preference. Every turn submitted for sid routes through it (the engine reads it at turn start; router-for-model hoists the model, an unknown name degrades to the default order). Channel-agnostic: web + TUI + embedded callers all set it here, persisted in the DB and shared across channels.

Set (or clear, with blank model) the per-session PROVIDER + MODEL
preference. Every turn submitted for `sid` routes through it (the engine
reads it at turn start; `router-for-model` hoists the model, an unknown
name degrades to the default order). Channel-agnostic: web + TUI + embedded
callers all set it here, persisted in the DB and shared across channels.
sourceraw docstring

gateway-soulclj

(gateway-soul sid)

Wire soul for one session: persisted record + live gateway status.

Wire soul for one session: persisted record + live gateway status.
sourceraw docstring

gateway-start!clj

(gateway-start!)
(gateway-start! {:keys [port host token-file require-token?]})

Start the gateway on the Ring Jetty adapter with virtual threads. Returns {:port :host :token-file}. Throws when already running. Safe to call from any host process - the daemon (vis serve), a TUI run, or an embedded caller.

Start the gateway on the Ring Jetty adapter with virtual threads.
Returns `{:port :host :token-file}`. Throws when already running.
Safe to call from any host process - the daemon (`vis serve`), a TUI
run, or an embedded caller.
sourceraw docstring

gateway-stop!clj

(gateway-stop!)

Stop the gateway server if running. Idempotent.

Stop the gateway server if running. Idempotent.
sourceraw docstring

gateway-submit-turn!clj

(gateway-submit-turn! sid
                      {:keys [request messages idempotency-key model
                              reasoning-default cancel-token extra-body
                              turn-features workspace engine-opts attachments]})

Submit one turn for sid. Async: starts immediately when idle, otherwise queues.

Returns {:turn record} (plus :idempotent? true on an idempotency replay) or {:error :session-not-found | :invalid-request, ...}. One engine turn still runs per session; busy submissions become visible queued records.

Submit one turn for `sid`. Async: starts immediately when idle, otherwise queues.

Returns `{:turn record}` (plus `:idempotent? true` on an idempotency
replay) or `{:error :session-not-found | :invalid-request, ...}`. One engine
turn still runs per session; busy submissions become visible queued records.
sourceraw docstring

gateway-submit-turn-sync!clj

(gateway-submit-turn-sync! sid {:keys [on-event] :as opts})

Submit one turn through the gateway and block until that turn reaches a terminal event.

Accepts the same request keys as submit-turn!; optional :on-event is called for every replay/live event for the submitted turn. Returns an engine-shaped result map for in-process clients (CLI/TUI/Telegram) that need a blocking call without bypassing the canonical gateway machinery.

Submit one turn through the gateway and block until that turn reaches a terminal event.

Accepts the same request keys as `submit-turn!`; optional `:on-event` is called
for every replay/live event for the submitted turn. Returns an engine-shaped
result map for in-process clients (CLI/TUI/Telegram) that need a blocking
call without bypassing the canonical gateway machinery.
sourceraw docstring

gateway-subscribe!clj

(gateway-subscribe! sid sub-id sink cursor)

Register an SSE sink and return the replay vector (events with :seq > cursor) ATOMICALLY with the registration, so no event can fall between replay and live fan-out. The caller serializes replay writes against live sink calls (see server.clj).

Before capturing replay, HYDRATE any turn currently running in a sibling process from the cross-process journal (bus/hydrate!) — but only when this process isn't already tracking a live turn (:current-turn unset), so an already-mirrored turn isn't re-delivered to existing subscribers. This materializes the running turn's row + ring HERE, so a watcher joining a turn in flight elsewhere replays it from turn.started (user bubble + running frame) instead of catching only the bare deltas after connect.

Register an SSE sink and return the replay vector (events with
`:seq` > `cursor`) ATOMICALLY with the registration, so no event can
fall between replay and live fan-out. The caller serializes replay
writes against live sink calls (see server.clj).

Before capturing replay, HYDRATE any turn currently running in a sibling
process from the cross-process journal (`bus/hydrate!`) — but only when this
process isn't already tracking a live turn (`:current-turn` unset), so an
already-mirrored turn isn't re-delivered to existing subscribers. This
materializes the running turn's row + ring HERE, so a watcher joining a turn
in flight elsewhere replays it from `turn.started` (user bubble + running
frame) instead of catching only the bare deltas after connect.
sourceraw docstring

gateway-transcriptclj

(gateway-transcript sid)

Rich persisted transcript rows for sid: turns oldest-first, each carrying its persisted iteration rows under :iterations. This is the gateway facade escape hatch for in-process renderers that need full historical trace detail without reaching around the gateway into persistence directly.

Rich persisted transcript rows for `sid`: turns oldest-first, each carrying
its persisted iteration rows under `:iterations`. This is the gateway facade
escape hatch for in-process renderers that need full historical trace detail
without reaching around the gateway into persistence directly.
sourceraw docstring

gateway-unsubscribe!clj

(gateway-unsubscribe! sid sub-id)
source

gateway-update-queued-turn!clj

(gateway-update-queued-turn! sid tid request)

Replace the prompt text for a queued turn. Returns the updated turn or an error.

Replace the prompt text for a queued turn. Returns the updated turn or an error.
sourceraw docstring

get-localsclj

(get-locals _environment)

User-defined sandbox vars surface. Live-vars introspection is cosmetic-off for the Python engine (the agent uses its own Python scope + stdlib), so this returns an empty map. Kept as a stable seam for the trailer/renderer callers.

User-defined sandbox vars surface. Live-vars introspection is cosmetic-off
for the Python engine (the agent uses its own Python scope + stdlib), so this
returns an empty map. Kept as a stable seam for the trailer/renderer callers.
sourceraw docstring

get-resourceclj

(get-resource session id)

DATA map for session+id, or nil.

DATA map for `session`+`id`, or nil.
sourceraw docstring

get-routerclj

(get-router)

Get or create the shared LLM router.

Honors :router opts from ~/.vis/config.edn (:rate-limit, :network, :budget, ...). Without that block svar's built-in defaults apply. See config/router-opts for the supported keys.

Get or create the shared LLM router.

Honors `:router` opts from `~/.vis/config.edn` (`:rate-limit`,
`:network`, `:budget`, ...). Without that block svar's built-in
defaults apply. See `config/router-opts` for the supported keys.
sourceraw docstring

has-provider?clj

(has-provider? provider-id)
source

hide-tool-code?clj

(hide-tool-code? {:keys [error success?] :as form})

Should a channel DROP a form's synthesized invocation source (the name(args) code block) instead of showing it as code? YES for a SUCCESSFUL native tool call (cat/rg/patch/…) that is NOT python_execution: the op-card (result-card) already says what ran, so the source is redundant chrome. python_execution — the model's OWN program — always keeps its code; an ERRORED form keeps it too (the inline error needs the surrounding source). The ONE predicate the TUI and web both consult so the code-chrome decision can't drift between channels.

Should a channel DROP a form's synthesized invocation source (the `name(args)`
code block) instead of showing it as code? YES for a SUCCESSFUL native tool
call (cat/rg/patch/…) that is NOT `python_execution`: the op-card
(`result-card`) already says what ran, so the source is redundant chrome.
`python_execution` — the model's OWN program — always keeps its code; an
ERRORED form keeps it too (the inline error needs the surrounding source).
The ONE predicate the TUI and web both consult so the code-chrome decision
can't drift between channels.
sourceraw docstring

humanize-fact-keyclj

(humanize-fact-key k)

Human-facing label for a fact/entity key. A turn_<N> key reads as Turn <N> for DISPLAY. Every other key is shown with underscores/hyphens normalized to SPACES and the first letter capitalized (api_key -> Api key, clj_eval_render -> Clj eval render). DISPLAY ONLY — the stored key stays verbatim, so restore still matches. Canonical across the context panel and every channel (TUI, web).

Fact/entity keys are model-authored strings (strings-only boundary), so (str k) is total here — no keyword branch.

Human-facing label for a fact/entity key. A `turn_<N>` key reads as
`Turn <N>` for DISPLAY. Every other key is shown with
underscores/hyphens normalized to SPACES and the first letter capitalized
(`api_key` -> `Api key`, `clj_eval_render` -> `Clj eval render`).
DISPLAY ONLY — the stored key stays verbatim, so restore still
matches. Canonical across the context panel and every channel (TUI, web).

Fact/entity keys are model-authored strings (strings-only boundary),
so `(str k)` is total here — no keyword branch.
sourceraw docstring

init!clj

(init!)

Redirect System/out and System/err to the log file. Lanterna uses tty-in / tty-out for terminal I/O. Call from the TUI entry point.

Redirect System/out and System/err to the log file. Lanterna uses
tty-in / tty-out for terminal I/O. Call from the TUI entry point.
sourceraw docstring

init-cli!clj

(init-cli!)

Logging init for non-TUI processes. Same redirects as init! but without the shutdown hook (CLI commands run to completion and exit).

Logging init for non-TUI processes. Same redirects as init! but
without the shutdown hook (CLI commands run to completion and exit).
sourceraw docstring

install-extension!clj

(install-extension! environment ext)

Register a validated extension into environment (per-env registration, distinct from the global-registry register-extension! defined earlier in this file).

Checks :ext/requires - if the extension declares dependencies, all listed extension namespaces must already be registered. Throws on missing dependencies.

If an extension with the same :ext/name is already registered, it is replaced (not duplicated). Enables hot-swap via reload-extension! (removed for GraalVM native-image compatibility).

Returns environment for chaining.

Register a validated extension into `environment` (per-env registration,
distinct from the global-registry `register-extension!` defined earlier
in this file).

Checks `:ext/requires` - if the extension declares dependencies, all
listed extension namespaces must already be registered. Throws on
missing dependencies.

If an extension with the same `:ext/name` is already registered,
it is replaced (not duplicated). Enables hot-swap via
`reload-extension!` (removed for GraalVM native-image compatibility).

Returns `environment` for chaining.
sourceraw docstring

invoke-symbol-wrapperclj

(invoke-symbol-wrapper ext sym-entry args env)

Full invocation pipeline for an observed tool symbol entry: before-fn -> fn -> after-fn, with on-error-fn catching :fn errors.

Every hook can override :fn, :args, :env via its return map. :before-fn can return {:result val} to short-circuit. :on-error-fn can return {:result val}, {:error err}, or {:fn :args :env} to retry.

The implementation's final value must be a canonical internal envelope. The wrapper records channel/provenance from that envelope, then returns only the payload :result to Python. Failure envelopes are converted into thrown ex-info so ordinary Python error reporting handles them.

Raw helper symbols (:ext.symbol/raw? true) bypass this function entirely.

Full invocation pipeline for an observed tool symbol entry:
before-fn -> fn -> after-fn, with on-error-fn catching :fn errors.

Every hook can override :fn, :args, :env via its return map.
:before-fn can return {:result val} to short-circuit.
:on-error-fn can return {:result val}, {:error err}, or {:fn :args :env} to retry.

The implementation's final value must be a canonical internal envelope.
The wrapper records channel/provenance from that envelope, then
returns only the payload `:result` to Python. Failure envelopes are converted
into thrown ex-info so ordinary Python error reporting handles them.

Raw helper symbols (`:ext.symbol/raw? true`) bypass this function entirely.
sourceraw docstring

limits-dynamic-summaryclj

(limits-dynamic-summary limits)
(limits-dynamic-summary limits max-rows)

Compact one-line summary of the most informative :dynamic :limits rows for a provider's normalized limits report.

Picks rows with signal first, falls back to all rows when nothing has signal yet (so a fresh, all-zero report still surfaces SOMETHING rather than collapsing to empty). Takes up to max-rows (default 2) and joins them with ·.

Returns nil when there's nothing to render.

Compact one-line summary of the most informative `:dynamic :limits`
rows for a provider's normalized limits report.

Picks rows with signal first, falls back to all rows when nothing
has signal yet (so a fresh, all-zero report still surfaces SOMETHING
rather than collapsing to empty). Takes up to `max-rows` (default 2)
and joins them with ` · `.

Returns nil when there's nothing to render.
sourceraw docstring

limits-format-numberclj

(limits-format-number n)

Render a numeric usage/limit/remaining value with a single-decimal suffix when the value is non-integral, else as a clean integer. Locale/ROOT keeps the JVM locale from injecting a comma decimal separator next to English suffix text.

Render a numeric usage/limit/remaining value with a single-decimal
suffix when the value is non-integral, else as a clean integer.
`Locale/ROOT` keeps the JVM locale from injecting a comma decimal
separator next to English suffix text.
sourceraw docstring

limits-format-usageclj

(limits-format-usage {:keys [used limit remaining unlimited?] :as row})

Render the usage/remaining portion of a row as a short string, choosing the most informative shape the row's numbers allow:

  • explicit unlimited? flag -> "unlimited"
  • percentage-style row -> "47% left"
  • used + limit + remaining -> "3/5 used (2 left)"
  • used + limit -> "3/5 used"
  • remaining + limit -> "2/5 left"
  • remaining only -> "2 left"
  • used only -> "3 used"
  • none of the above -> nil

Returns nil only when the row carries no usage signal at all, so callers can (when usage ...) to skip empty cells.

Render the usage/remaining portion of a row as a short string,
choosing the most informative shape the row's numbers allow:

  - explicit `unlimited?` flag         -> "unlimited"
  - percentage-style row               -> "47% left"
  - used + limit + remaining           -> "3/5 used (2 left)"
  - used + limit                       -> "3/5 used"
  - remaining + limit                  -> "2/5 left"
  - remaining only                     -> "2 left"
  - used only                          -> "3 used"
  - none of the above                  -> nil

Returns nil only when the row carries no usage signal at all, so
callers can `(when usage ...)` to skip empty cells.
sourceraw docstring

limits-generic-labelclj

(limits-generic-label row)

Human label for a dynamic-limit row. Hand-rolled overrides for the widely-known plan rows; fallback derives a label from :label or :id, trimming the redundant Quota / Quota (%) suffixes the raw provider rows ship with.

Human label for a dynamic-limit row. Hand-rolled overrides for the
widely-known plan rows; fallback derives a label from `:label` or
`:id`, trimming the redundant ` Quota` / ` Quota (%)` suffixes the
raw provider rows ship with.
sourceraw docstring

limits-label+usageclj

(limits-label+usage row)

Compose "<label> <usage>" for a single row, or "<label>" when the row has no usage signal. Returns nil when both are blank/absent.

Compose `"<label> <usage>"` for a single row, or `"<label>"`
when the row has no usage signal. Returns nil when both are
blank/absent.
sourceraw docstring

limits-percentage-row?clj

(limits-percentage-row? {:keys [id kind limit remaining]})

True when the row is best displayed as a percent-remaining (the provider reports a 0-100 percentage rather than raw token counts). The ID allowlist covers the Codex / Z.ai plan windows; the :rate + :limit 100 heuristic catches generic percentage rows.

True when the row is best displayed as a percent-remaining (the
provider reports a 0-100 percentage rather than raw token counts).
The ID allowlist covers the Codex / Z.ai plan windows; the
`:rate` + `:limit 100` heuristic catches generic percentage rows.
sourceraw docstring

limits-row-has-signal?clj

(limits-row-has-signal? row)

True when the row has any usage signal worth surfacing. Used to prefer non-zero rows when the visible area is tight.

True when the row has any usage signal worth surfacing. Used to
prefer non-zero rows when the visible area is tight.
sourceraw docstring

list-resourcesclj

(list-resources session)

Vector of live resource DATA maps for session, dead ones pruned first. This is what the footer renders and what :session/resources carries into ctx — ONLY the calling session's resources.

Vector of live resource DATA maps for `session`, dead ones pruned first. This
is what the footer renders and what `:session/resources` carries into ctx —
ONLY the calling session's resources.
sourceraw docstring

llm-text!clj

(llm-text! {:keys [messages system prompt reasoning temperature routing]
            :as opts})

Fast helper LLM call for extensions.

Uses svar routing (:routing {:optimize :cost}) instead of Vis-side model name heuristics. The call still goes through svar/ask-code! because Vis no longer uses the retired ask! structured-output path; :lang "text", :reasoning :off, and :code-tail-pointer? true make the return a plain text string under :text. Callers may pass either :messages or :system + :prompt.

Fast helper LLM call for extensions.

Uses svar routing (`:routing {:optimize :cost}`) instead of Vis-side model
name heuristics. The call still goes through `svar/ask-code!` because Vis no
longer uses the retired `ask!` structured-output path; `:lang "text"`,
`:reasoning :off`, and `:code-tail-pointer? true` make the return a plain
text string under :text. Callers may pass either :messages or :system +
:prompt.
sourceraw docstring

load-configclj

(load-config)

Load provider config in svar-native syntax from ~/.vis/config.edn.

Load provider config in svar-native syntax from `~/.vis/config.edn`.
sourceraw docstring

load-config-rawclj

(load-config-raw)

Load raw config as global ~/.vis/config.edn, then the project-local .vis/config.edn overlay, then the root vis.edn overlay. Later sources win; nested maps merge; scalar/vector values replace.

Load raw config as global `~/.vis/config.edn`, then the project-local
`.vis/config.edn` overlay, then the root `vis.edn` overlay. Later sources
win; nested maps merge; scalar/vector values replace.
sourceraw docstring

load-python-extensions!clj

(load-python-extensions!)
(load-python-extensions! {:keys [dirs]})

Scan the Python extension dirs (default: ~/.vis/extensions and <cwd>/.vis/extensions) and (re)load every *.py file. Idempotent: when no file changed since the last scan this is a cheap no-op. On any change the whole set is torn down and rebuilt (contexts are ~40ms warm on the shared engine) — deterministic ordering, no partial states.

A file that fails to load is recorded in load-failures (and surfaced by vis doctor) — it never crashes the host.

Returns {:loaded n :failed n :changed? bool}.

Scan the Python extension dirs (default: `~/.vis/extensions` and
`<cwd>/.vis/extensions`) and (re)load every `*.py` file. Idempotent:
when no file changed since the last scan this is a cheap no-op. On any
change the whole set is torn down and rebuilt (contexts are ~40ms warm
on the shared engine) — deterministic ordering, no partial states.

A file that fails to load is recorded in `load-failures` (and surfaced
by `vis doctor`) — it never crashes the host.

Returns `{:loaded n :failed n :changed? bool}`.
sourceraw docstring

loaded-python-extensionsclj

(loaded-python-extensions)

Snapshot of the currently loaded Python extensions: {<canonical-path> {:sha ... :ext-name ...}} (context handle elided).

Snapshot of the currently loaded Python extensions:
`{<canonical-path> {:sha ... :ext-name ...}} ` (context handle elided).
sourceraw docstring

make-progress-trackerclj

(make-progress-tracker)
(make-progress-tracker {:keys [on-update]})

Create a phased progress tracker.

Returns {:on-chunk fn :get-timeline fn}. The :on-chunk fn accepts the loop's phased chunks and returns nil. The :get-timeline fn returns the accumulated timeline vec (oldest-iteration first).

on-update (when supplied) is called (on-update timeline chunk) after every chunk update, so the consumer can re-render incrementally.

Create a phased progress tracker.

Returns `{:on-chunk fn :get-timeline fn}`. The `:on-chunk` fn
accepts the loop's phased chunks and returns nil. The
`:get-timeline` fn returns the accumulated timeline vec
(oldest-iteration first).

`on-update` (when supplied) is called `(on-update timeline chunk)`
after every chunk update, so the consumer can re-render
incrementally.
sourceraw docstring

markdown->irclj

(markdown->ir text)
(markdown->ir text {:keys [soft-break]})

Parse a Markdown string into canonical answer-IR. Idempotent: when the input is already canonical IR, returns it unchanged (identical? preserved — cache-friendly).

This is the SINGLE entry point for turning Markdown source into IR. Used by:

  • the final-answer pipeline (model's plain-prose Markdown answer)
  • thinking text from the model
  • user-typed messages from the TUI input box

Returns canonical [:ir & blocks] directly (no further ->ast round-trip needed). Empty / nil input yields [:ir {}].

Implementation: commonmark-java parser + GFM tables / strikethrough extensions, then a faithful Node→IR walker. Soft line breaks collapse to a single space; hard line breaks become [:br].

opts (2-arity) currently understands {:soft-break :hard}, which lifts every bare newline to [:br] instead of a space — used for line-oriented user/pasted input so the rendered bubble keeps the exact line structure the user typed. Default keeps prose semantics.

Parse a Markdown string into canonical answer-IR.
Idempotent: when the input is already canonical IR, returns it
unchanged (`identical?` preserved — cache-friendly).

This is the SINGLE entry point for turning Markdown source into IR.
Used by:
  - the final-answer pipeline (model's plain-prose Markdown answer)
  - thinking text from the model
  - user-typed messages from the TUI input box

Returns canonical `[:ir & blocks]` directly (no further `->ast`
round-trip needed). Empty / nil input yields `[:ir {}]`.

Implementation: commonmark-java parser + GFM tables / strikethrough
extensions, then a faithful Node→IR walker. Soft line breaks collapse
to a single space; hard line breaks become `[:br]`.

`opts` (2-arity) currently understands `{:soft-break :hard}`, which
lifts every bare newline to `[:br]` instead of a space — used for
line-oriented user/pasted input so the rendered bubble keeps the
exact line structure the user typed. Default keeps prose semantics.
sourceraw docstring

meta-fallback-noteclj

(meta-fallback-note {:keys [llm-selected llm-fallback? llm-routing-trace]})

Faint routing note, present only when the turn fell back to another model: ↳ from <selected-model> — <reason>, retried N× reason prefers the HTTP status (429) on the fallback event, then the reason keyword, then the free-form error. Retries count :llm.routing/provider-retry events in the trace. Returns nil when there was no fallback. Shared so the TUI can float it on its own faint row while CLI/Telegram fold it inline.

Faint routing note, present only when the turn fell back to another model:
  ↳ from <selected-model> — <reason>, retried N×
`reason` prefers the HTTP status (429) on the fallback event, then the reason
keyword, then the free-form error. Retries count `:llm.routing/provider-retry`
events in the trace. Returns nil when there was no fallback. Shared so the TUI
can float it on its own faint row while CLI/Telegram fold it inline.
sourceraw docstring

meta-summary-lineclj

(meta-summary-line result)
(meta-summary-line {:keys [tokens cost duration-ms] :as result}
                   {:keys [model prefix suffix]})

The canonical, humanized turn-summary MAIN line, shared verbatim by the CLI bracket, the TUI bubble footer, and the Telegram tagline:

<provider/model> · <in→out (cached)> · ~$cost · <duration>

Zero-usage and zero-cost slots are dropped (no "0→0", no "$0"), so a turn that produced nothing reads as just the model + time. Does NOT include the fallback note — that is meta-fallback-note, which single-line surfaces fold in via format-meta-line and the TUI floats on a second row.

opts keeps the legacy override hooks: {:model <string|false> :prefix [...] :suffix [...]}:model false suppresses the model slot, a string overrides it; prefix/suffix are extra slots spliced in around the standard ones.

The canonical, humanized turn-summary MAIN line, shared verbatim by the CLI
bracket, the TUI bubble footer, and the Telegram tagline:

  <provider/model>  ·  <in→out (cached)>  ·  ~$cost  ·  <duration>

Zero-usage and zero-cost slots are dropped (no "0→0", no "$0"), so a turn
that produced nothing reads as just the model + time. Does NOT include the
fallback note — that is `meta-fallback-note`, which single-line surfaces fold
in via `format-meta-line` and the TUI floats on a second row.

`opts` keeps the legacy override hooks: `{:model <string|false> :prefix [...]
:suffix [...]}` — `:model false` suppresses the model slot, a string overrides
it; prefix/suffix are extra slots spliced in around the standard ones.
sourceraw docstring

model-nameclj

(model-name model)

Extract the model name string from a model (string or {:name str}).

Extract the model name string from a model (string or `{:name str}`).
sourceraw docstring

model-routing-statusclj

(model-routing-status displayed-provider displayed-model)
(model-routing-status router displayed-provider displayed-model)

Live routing health for the model a channel is DISPLAYING (displayed-provider

  • displayed-model — the per-session pick or the config default the picker shows).

svar opens a circuit breaker on a provider after repeated transient failures (5xx / 'Overloaded' 529 / dropped streams) and routes turns to the next AVAILABLE provider so work keeps flowing. The displayed model is computed from config ORDER and is NOT breaker-aware, so during an outage the picker says opus while turns actually land on zai. This reconciles the two: when the displayed provider's breaker is open/half-open, it reports what svar is actually serving so the channel can surface ⚠ <displayed> overloaded — routing to <serving>.

Returns nil when the displayed provider is healthy, else {:overloaded-provider <kw> :overloaded-model <str> :serving-provider <kw> :serving-model <str>}. serving-* is nil if every provider is down.

Live routing health for the model a channel is DISPLAYING (`displayed-provider`
+ `displayed-model` — the per-session pick or the config default the picker
shows).

svar opens a circuit breaker on a provider after repeated transient failures
(5xx / 'Overloaded' 529 / dropped streams) and routes turns to the next
AVAILABLE provider so work keeps flowing. The displayed model is computed
from config ORDER and is NOT breaker-aware, so during an outage the picker
says `opus` while turns actually land on `zai`. This reconciles the two: when
the displayed provider's breaker is open/half-open, it reports what svar is
actually serving so the channel can surface
`⚠ <displayed> overloaded — routing to <serving>`.

Returns nil when the displayed provider is healthy, else
`{:overloaded-provider <kw> :overloaded-model <str>
  :serving-provider <kw> :serving-model <str>}`. `serving-*` is nil if every
provider is down.
sourceraw docstring

native-tool-form?clj

(native-tool-form? {tool-name :vis/tool-name})

True when form is a NATIVE tool call (cat/rg/patch/…): it carries a :vis/tool-name and therefore renders as an op-card via result-card.

True when `form` is a NATIVE tool call (cat/rg/patch/…): it carries a
`:vis/tool-name` and therefore renders as an op-card via `result-card`.
sourceraw docstring

normalize-reasoningclj

(normalize-reasoning text)

Canonical normalization for model reasoning / thinking text before it is rendered as a trace. Reasoning streams carry whitespace-padded blank rows (trailing spaces/tabs the model emits) and paragraph-style double newlines that make the compact thinking block look ragged (glm-5.2 especially). Strip per-line trailing whitespace, collapse every run of newlines down to ONE line break, then give the trace BREATHING ROOM: a line that ENDS A SENTENCE (./!/?/, optionally closed by a quote/paren/bracket) and is followed by more text gets a blank line after it, so consecutive sentences read as separate paragraphs instead of a wall. Finally trim. Shared by every channel so the TUI bubble and the web thinking card normalize identically.

Canonical normalization for model reasoning / thinking text before it is
rendered as a trace. Reasoning streams carry whitespace-padded blank rows
(trailing spaces/tabs the model emits) and paragraph-style double newlines
that make the compact thinking block look ragged (glm-5.2 especially). Strip
per-line trailing whitespace, collapse every run of newlines down to ONE line
break, then give the trace BREATHING ROOM: a line that ENDS A SENTENCE
(`.`/`!`/`?`/`…`, optionally closed by a quote/paren/bracket) and is
followed by more text gets a blank line after it, so consecutive sentences
read as separate paragraphs instead of a wall. Finally trim. Shared by every
channel so the TUI bubble and the web thinking card normalize identically.
sourceraw docstring

notificationsclj

(notifications)

Vec of currently-active notifications, oldest first. Implicitly prunes expired entries before returning so a paint loop reading this never has to re-check :until deadlines.

Vec of currently-active notifications, oldest first. Implicitly
prunes expired entries before returning so a paint loop reading
this never has to re-check `:until` deadlines.
sourceraw docstring

notify!clj

(notify! text & {:keys [level ttl-ms] :or {level :info ttl-ms DEFAULT_TTL_MS}})

Push a new notification. Returns the entry's id (uuid string) so the caller can later dismiss! it manually.

Options: :level one of #{:info :success :warn :error} - default :info. Channels use the level for visual treatment (color, emoji prefix, etc.). :ttl-ms lifespan in ms. Default 3000. nil = sticky / no auto expiry; the notification stays until dismiss!d.

The notification is appended to the in-memory vec and every registered watcher is fired with the new full vec.

Push a new notification. Returns the entry's id (uuid string) so
the caller can later `dismiss!` it manually.

Options:
  :level   one of #{:info :success :warn :error} - default :info.
           Channels use the level for visual treatment (color,
           emoji prefix, etc.).
  :ttl-ms  lifespan in ms. Default 3000. nil = sticky / no auto
           expiry; the notification stays until `dismiss!`d.

The notification is appended to the in-memory vec and every
registered watcher is fired with the new full vec.
sourceraw docstring

now-msclj

(now-ms)
source

on-cancel!clj

(on-cancel! token thunk)

Register a no-arg thunk to fire the moment cancel! is invoked on token. Returns a dispose! thunk the caller MUST invoke when the cancellable work finishes normally — otherwise callbacks accumulate for the token's lifetime.

If cancel! has already fired on this token, thunk runs synchronously here and dispose! is a no-op. This matches the contract every consumer wants: registering AFTER cancellation must still cancel, not silently swallow the request.

Replaces the atom-watch pattern earlier eval boundaries hand-rolled: one shared callback list, no per-consumer add-watch / remove-watch plumbing, no risk of leaving a watch on the flag after the worker finishes.

Register a no-arg `thunk` to fire the moment `cancel!` is invoked
on `token`. Returns a `dispose!` thunk the caller MUST invoke when
the cancellable work finishes normally — otherwise callbacks
accumulate for the token's lifetime.

If `cancel!` has already fired on this token, `thunk` runs
synchronously here and `dispose!` is a no-op. This matches the
contract every consumer wants: registering AFTER cancellation
must still cancel, not silently swallow the request.

Replaces the atom-watch pattern earlier eval boundaries hand-rolled:
one shared callback list, no per-consumer add-watch / remove-watch
plumbing, no risk of leaving a watch on the flag after the worker
finishes.
sourceraw docstring

op-presentationclj

(op-presentation op)

Engine-owned presentation metadata for a tool's :op keyword: {:tag ...}. Tool wrappers merge this into their :info/:metadata so channels read canonical keys.

Badge LABEL is derived from :tag by the channel, not stored here. Color / glyph / layout remain pure channel concerns.

Engine-owned presentation metadata for a tool's `:op` keyword:
`{:tag ...}`. Tool wrappers merge this into their `:info`/`:metadata`
so channels read canonical keys.

Badge LABEL is derived from `:tag` by the channel, not stored here.
Color / glyph / layout remain pure channel concerns.
sourceraw docstring

op-tagclj

(op-tag op-keyword)

Return the :observation | :mutation tag for op-keyword. Unknown ops fail closed; every symbol must declare :tag inline on its vis/symbol entry.

Return the `:observation | :mutation` tag for `op-keyword`. Unknown
ops fail closed; every symbol must declare `:tag` inline on its
`vis/symbol` entry.
sourceraw docstring

original-stdoutclj

source

pad-leftclj

(pad-left s w)
source

pad-rightclj

(pad-right s w)
source

paletteclj

Default palette. Kept as a named var for channels that only need colours.

Default palette. Kept as a named var for channels that only need colours.
sourceraw docstring

palleteclj

Deprecated misspelling retained as an alias for callers/searches using 'pallete'. Prefer palette.

Deprecated misspelling retained as an alias for callers/searches using
'pallete'. Prefer `palette`.
sourceraw docstring

parse-argsclj

(parse-args arg-specs raw-args)

Parse raw-args against arg-specs. Returns a map of {arg-name value}. Positional specs are matched in order; flag specs by --name; boolean flags need no value. Unknown flags are silently dropped so commands can layer their own loose flags.

Parse `raw-args` against `arg-specs`. Returns a map of
`{arg-name value}`. Positional specs are matched in order; flag
specs by `--name`; boolean flags need no value. Unknown flags
are silently dropped so commands can layer their own loose flags.
sourceraw docstring

parse-block-displayclj

(parse-block-display form-source)

Return the model's authored source as ONE verbatim :code segment.

The engine is full-Python: the source is Python and we keep it VERBATIM here — exactly what the model wrote, no splitting, no classification. This is the canonical segment (tests + the model's own context depend on it being the raw bytes). Channels that want a beautified view call prettify-python at paint time; the IR stays raw.

Pure helper. Never throws. Blank / nil input returns [].

Return the model's authored source as ONE verbatim `:code` segment.

The engine is full-Python: the source is Python and we keep it VERBATIM here —
exactly what the model wrote, no splitting, no classification. This is the
canonical segment (tests + the model's own context depend on it being the raw
bytes). Channels that want a beautified view call `prettify-python` at paint
time; the IR stays raw.

Pure helper. Never throws. Blank / nil input returns `[]`.
sourceraw docstring

providerclj

(provider spec)

Build and validate a provider descriptor.

Build and validate a provider descriptor.
sourceraw docstring

provider-auth-kindclj

(provider-auth-kind pid)

How a provider id authenticates: :oauth (interactive flow owned by the provider extension), :none (local, no credentials), or :api-key.

How a provider id authenticates: `:oauth` (interactive flow owned by
the provider extension), `:none` (local, no credentials), or
`:api-key`.
sourceraw docstring

provider-base-urlclj

(provider-base-url provider)

Resolve base-url for a provider: explicit field on the provider map first (so user-supplied URLs win), then the merged catalog.

Resolve base-url for a provider: explicit field on the provider
map first (so user-supplied URLs win), then the merged catalog.
sourceraw docstring

provider-by-idclj

(provider-by-id id)

Lookup a provider by :provider/id. Returns nil when absent.

Lookup a provider by `:provider/id`. Returns nil when absent.
sourceraw docstring

provider-config-with-modelsclj

(provider-config-with-models preset models)

Minimal persistable provider config for a preset + chosen models.

Minimal persistable provider config for a preset + chosen models.
sourceraw docstring

provider-configured?clj

(provider-configured?)

True when at least one provider is configured (global or project config). The single predicate entry points use to branch onboarding vs normal start — never trips the resolve-config throw.

True when at least one provider is configured (global or project config).
The single predicate entry points use to branch onboarding vs normal start —
never trips the `resolve-config` throw.
sourceraw docstring

provider-default-model-configsclj

(provider-default-model-configs preset)

Preset :default-models as persisted {:name str} model maps.

Preset `:default-models` as persisted `{:name str}` model maps.
sourceraw docstring

provider-default-model-namesclj

(provider-default-model-names provider)

Union of model names already on the provider map plus the preset / provider :default-models, deduped. The list-building below sorts, so order here is irrelevant.

Union of model names already on the provider map plus the preset /
provider `:default-models`, deduped. The list-building below sorts,
so order here is irrelevant.
sourceraw docstring

provider-ensure-base-urlclj

(provider-ensure-base-url provider)
source

provider-fetch-modelsclj

(provider-fetch-models provider)

List models for a vis provider via svar/models!.

Returns vec of chat model id strings, or nil on failure. Filters out TTS / embedding / speech / image and provider-excluded models.

Routing through svar means the call automatically picks up provider-specific OAuth headers (anthropic-version, anthropic-beta for the Anthropic Claude subscription; chatgpt-account-id for OpenAI Codex; bare Bearer for everyone else).

provider is a vis-shaped provider map. We coerce to svar shape (resolving OAuth tokens via the provider's :provider/get-token-fn when :api-key is absent) and ask svar.

List models for a vis provider via `svar/models!`.

Returns vec of chat model id strings, or nil on failure. Filters
out TTS / embedding / speech / image and provider-excluded models.

Routing through svar means the call automatically picks up
provider-specific OAuth headers (`anthropic-version`,
`anthropic-beta` for the Anthropic Claude subscription;
`chatgpt-account-id` for OpenAI Codex; bare Bearer for everyone
else).

`provider` is a vis-shaped provider map. We coerce to svar shape
(resolving OAuth tokens via the provider's `:provider/get-token-fn`
when `:api-key` is absent) and ask svar.
sourceraw docstring

provider-idsclj

(provider-ids)

Set of configured provider :id keywords.

Set of configured provider `:id` keywords.
sourceraw docstring

provider-initial-limitsclj

(provider-initial-limits provider)

Placeholder limits report while the real fetch runs.

Placeholder limits report while the real fetch runs.
sourceraw docstring

provider-initial-statusclj

(provider-initial-status provider)

Placeholder status while a real probe runs in the background.

Placeholder status while a real probe runs in the background.
sourceraw docstring

provider-limitsclj

(provider-limits provider-id)

Return a normalized, spec-validated limits report for one provider id.

The provider's optional :provider/limits-fn supplies the dynamic portion. This host wrapper backfills static svar metadata and always returns a valid ::report envelope, even when the provider-specific implementation is absent, missing, throws, or returns malformed data.

Providers that only have static svar catalog metadata still return a usable :ok report so callers can surface RPM / TPM without needing a registered runtime extension.

Return a normalized, spec-validated limits report for one provider id.

The provider's optional `:provider/limits-fn` supplies the dynamic
portion. This host wrapper backfills static svar metadata and always
returns a valid `::report` envelope, even when the provider-specific
implementation is absent, missing, throws, or returns malformed data.

Providers that only have static svar catalog metadata still return a
usable `:ok` report so callers can surface RPM / TPM without needing a
registered runtime extension.
sourceraw docstring

provider-limits-safeclj

(provider-limits-safe provider)

Normalized limits report for a provider id; an error report instead of a throw.

Normalized limits report for a provider id; an error report instead
of a throw.
sourceraw docstring

provider-local-no-auth-idsclj

Local OpenAI-compatible providers that need no credentials.

Local OpenAI-compatible providers that need no credentials.
sourceraw docstring

provider-model-optionsclj

(provider-model-options provider)
(provider-model-options provider default-models show-all?)

Selectable model ids for a provider: live-fetched + defaults, deduped, sorted, env default pinned first. When show-all? is false, dated snapshot variants (gpt-4o-2024-08-06) are hidden.

Returns {:models [id ...] :hidden-count n} — channels render their own 'show all' affordance from :hidden-count.

Selectable model ids for a provider: live-fetched + defaults,
deduped, sorted, env default pinned first. When `show-all?` is
false, dated snapshot variants (gpt-4o-2024-08-06) are hidden.

Returns `{:models [id ...] :hidden-count n}` — channels render
their own 'show all' affordance from `:hidden-count`.
sourceraw docstring

provider-model-visible?clj

(provider-model-visible? provider-id model-id)

True when svar's provider-scoped model filters allow this model id.

True when svar's provider-scoped model filters allow this model id.
sourceraw docstring

provider-oauth-idsclj

Providers whose credentials come from an interactive OAuth flow and live OUTSIDE config.edn (keychain / token files owned by the provider extension).

Providers whose credentials come from an interactive OAuth flow and
live OUTSIDE config.edn (keychain / token files owned by the
provider extension).
sourceraw docstring

provider-persisted-configclj

(provider-persisted-config provider)

Convert an in-memory provider entry to the durable on-disk shape.

Convert an in-memory provider entry to the durable on-disk shape.
sourceraw docstring

provider-presetsclj

(provider-presets)

All known provider presets, sorted for the 'Add Provider' picker.

All known provider presets, sorted for the 'Add Provider' picker.
sourceraw docstring

provider-presets-availableclj

(provider-presets-available)

Provider presets not yet in the configured fleet — the 'Add Provider' picker contents.

Provider presets not yet in the configured fleet — the 'Add
Provider' picker contents.
sourceraw docstring

provider-statusclj

(provider-status provider)

Auth/liveness status for a CONFIGURED provider map. Local providers are probed for real; an explicit :api-key is trusted; otherwise the registered extension's status/detect fns answer. Never throws.

Auth/liveness status for a CONFIGURED provider map. Local providers
are probed for real; an explicit `:api-key` is trusted; otherwise
the registered extension's status/detect fns answer. Never throws.
sourceraw docstring

provider-status-mdclj

(provider-status-md provider)
(provider-status-md provider status limits)

The provider status + limits report as MARKDOWN — one rich canonical form every channel renders natively: the web through its markdown pipeline, the TUI through markdown->ir + the IR walker. The same facts as [[status-text]], structured instead of flat.

The provider status + limits report as MARKDOWN — one rich canonical
form every channel renders natively: the web through its markdown
pipeline, the TUI through `markdown->ir` + the IR walker. The same
facts as [[status-text]], structured instead of flat.
sourceraw docstring

provider-status-of-registeredclj

(provider-status-of-registered provider)

Status of a REGISTERED provider descriptor via its :provider/status-fn (falling back to :provider/detect-fn). Never throws.

Status of a REGISTERED provider descriptor via its `:provider/status-fn`
(falling back to `:provider/detect-fn`). Never throws.
sourceraw docstring

provider-status-textclj

(provider-status-text provider)
(provider-status-text provider status limits)

Multi-line human status + limits report for a configured provider. The single source for the TUI 'Show Status + Limits' dialog and the web status view.

Multi-line human status + limits report for a configured provider.
The single source for the TUI 'Show Status + Limits' dialog and the
web status view.
sourceraw docstring

provider-templateclj

(provider-template pid)

Preset descriptor for a provider id, merged from a provider extension's metadata and svar's catalog. Returns nil for unknown or intentionally removed ids.

Preset descriptor for a provider id, merged from a provider
extension's metadata and svar's catalog. Returns nil for unknown or
intentionally removed ids.
sourceraw docstring

provider-url-hostclj

(provider-url-host url)

Extract host from URL for display. 'https://llm.blockether.com/v1' -> 'llm.blockether.com'.

Extract host from URL for display. 'https://llm.blockether.com/v1' ->
'llm.blockether.com'.
sourceraw docstring

publish-channel-event!clj

source

python-extension-load-failuresclj

(python-extension-load-failures)

Load failures from the most recent Python-extension scan: [{:file <path> :error <message>} ...].

Load failures from the most recent Python-extension scan:
`[{:file <path> :error <message>} ...]`.
sourceraw docstring

reasoning->irclj

(reasoning->ir text)

Reasoning / thinking text -> canonical answer-IR. The SINGLE shared entry point for rendering a model's thinking trace (TUI thinking bubble AND the web thinking card), so both channels paint the SAME structure. Reasoning is line-oriented (a trace, not flowing prose): normalize via normalize-reasoning then lift every bare newline to a HARD break ([:br]) via {:soft-break :hard}. Without the hard break a bold heading collapses onto its body line (the TUI **heading** body bug); with it the heading keeps its own line, matching the web ticker's marked({:breaks true}).

Reasoning / thinking text -> canonical answer-IR. The SINGLE shared entry
point for rendering a model's thinking trace (TUI thinking bubble AND the web
thinking card), so both channels paint the SAME structure. Reasoning is
line-oriented (a trace, not flowing prose): normalize via `normalize-reasoning`
then lift every bare newline to a HARD break (`[:br]`) via `{:soft-break
:hard}`. Without the hard break a bold heading collapses onto its body line
(the TUI `**heading** body` bug); with it the heading keeps its own line,
matching the web ticker's `marked({:breaks true})`.
sourceraw docstring

reasoning-collapse-min-hiddenclj

Minimum number of HIDDEN reasoning rows required before a thinking trace is COLLAPSED behind a disclosure at all. If the remainder beyond the preview is smaller than this, the whole trace renders inline — a +1 more toggle that only reveals one extra line is pure friction. One source of truth shared by the TUI thinking bubble and the web thinking card.

Minimum number of HIDDEN reasoning rows required before a thinking trace is
COLLAPSED behind a disclosure at all. If the remainder beyond the preview is
smaller than this, the whole trace renders inline — a `+1 more` toggle that
only reveals one extra line is pure friction. One source of truth shared by
the TUI thinking bubble and the web thinking card.
sourceraw docstring

reasoning-preview-line-limitclj

Canonical reasoning PREVIEW height shared by every channel. Up to this many rows/lines of a thinking trace stay visible; the remainder folds behind a +N more disclosure (web) / ▸ THINKING +N more toggle (TUI). One source of truth so the TUI bubble and the web card clamp reasoning to the SAME height.

Canonical reasoning PREVIEW height shared by every channel. Up to this many
rows/lines of a thinking trace stay visible; the remainder folds behind a
`+N more` disclosure (web) / `▸ THINKING +N more` toggle (TUI). One
source of truth so the TUI bubble and the web card clamp reasoning to the
SAME height.
sourceraw docstring

rebuild-router!clj

(rebuild-router! config)

Rebuild the router from the given config. Used when provider settings change.

Forwards :router opts so live config edits (e.g. tuning :same-provider-delays-ms) take effect on the next set-provider! without restarting the JVM.

Rebuild the router from the given config. Used when provider settings change.

Forwards `:router` opts so live config edits (e.g. tuning
`:same-provider-delays-ms`) take effect on the next `set-provider!`
without restarting the JVM.
sourceraw docstring

rediscover!clj

(rediscover!)

Force a fresh classpath scan, discarding the cached manifests. Test/REPL utility - production code should use the idempotent scan-extensions! instead.

Force a fresh classpath scan, discarding the cached manifests.
Test/REPL utility - production code should use the idempotent
`scan-extensions!` instead.
sourceraw docstring

refresh-cached-routers!clj

(refresh-cached-routers! router)

Reseat :router on every cached env's environment map.

create-environment snapshots the router into (:router env) at construction time, and the iteration loop calls (svar/ask-code! (:router environment) ...) - not the global router-atom. So when a frontend changes provider config and rebuilds the global router, every long-lived env in the cache (TUI keeps one for the whole session) keeps talking to the previous model until disposed.

Call this immediately after rebuild-router! so the next send! on any cached session picks up the new router.

Reseat `:router` on every cached env's environment map.

`create-environment` snapshots the router into
`(:router env)` at construction time, and the iteration loop calls
`(svar/ask-code! (:router environment) ...)` - not the global
`router-atom`. So when a frontend changes provider
config and rebuilds the global router, every long-lived env in the
cache (TUI keeps one for the whole session) keeps talking to the
*previous* model until disposed.

Call this immediately after `rebuild-router!` so the
next `send!` on any cached session picks up the new router.
sourceraw docstring

register-backend!clj

(register-backend! id ns-sym)

Register a persistence backend implementation.

id - keyword identity, e.g. :sqlite. ns-sym - fully qualified namespace symbol that defines the backend functions (db-open!, db-close!, db-log!, every store-*/db-* fn used by this facade). Vars are resolved lazily via ns-resolve so REPL redefinition just works.

Idempotent on id. Returns id.

Register a persistence backend implementation.

`id`     - keyword identity, e.g. `:sqlite`.
`ns-sym` - fully qualified namespace symbol that defines the backend
           functions (`db-open!`, `db-close!`, `db-log!`, every
           `store-*`/`db-*` fn used by this facade). Vars are
           resolved lazily via `ns-resolve` so REPL redefinition
           just works.

Idempotent on `id`. Returns `id`.
sourceraw docstring

register-channel!clj

(register-channel! spec)

Register a channel in the global registry. Idempotent on :channel/id - re-registering replaces the prior spec. Returns the validated channel.

Register a channel in the global registry.
Idempotent on :channel/id - re-registering replaces the prior spec.
Returns the validated channel.
sourceraw docstring

register-cmd!clj

(register-cmd! spec)

Register a command in the global registry. Idempotent on [:cmd/parent :cmd/name] - re-registering replaces the prior entry, useful for REPL-driven development. Returns the validated command map.

Register a command in the global registry. Idempotent on
`[:cmd/parent :cmd/name]` - re-registering replaces the prior
entry, useful for REPL-driven development. Returns the validated
command map.
sourceraw docstring

register-extension!clj

(register-extension! ext)

Register an extension in the global process-level registry.

This is THE single entry point for everything an extension contributes to vis. Whatever the extension declares -- Python sandbox symbols (:ext.engine/symbols), CLI commands (:ext/cli), channels (:ext/channels), LLM providers (:ext/providers), persistence backends (:ext/persistance) -- gets routed here and dispatched into the matching sub-registry as a side effect.

Also computes source-file markers (paths, max-mtime, sha256) and stores them in a sidecar atom read by the tool-envelope emitter (UI extension provenance label).

Idempotent on :ext/name. Returns the validated extension.

Register an extension in the global process-level registry.

This is THE single entry point for everything an extension
contributes to vis. Whatever the extension declares -- Python sandbox
symbols (`:ext.engine/symbols`), CLI commands (`:ext/cli`), channels
(`:ext/channels`), LLM providers (`:ext/providers`), persistence
backends (`:ext/persistance`) -- gets routed here and dispatched into
the matching sub-registry as a side effect.

Also computes source-file markers (paths, max-mtime, sha256) and
stores them in a sidecar atom read by the tool-envelope emitter
(UI extension provenance label).

Idempotent on `:ext/name`. Returns the validated extension.
sourceraw docstring

register-op-hook!clj

(register-op-hook! {:keys [op phase owner] hook-fn :fn :or {phase :after}})

Register a cross-cutting hook on operation :op (its op-keyword, e.g. :struct_patch). :phase is :after (default — sees & may rewrite the result envelope), :before (sees & may rewrite the args vector), or :around (MIDDLEWARE — wraps the call). :fn is, for :after, (fn [env op-kw args result] -> result-envelope); for :before, (fn [env op-kw args] -> args-vector); for :around, (fn [env op-kw args next] -> result) where next runs the inner call and may be invoked zero+ times (skip / retry) or wrapped in try/catch (recover — this is how an op is made NOT to fail). :owner (an ext keyword) makes the registration idempotent across :reloads — re-registering the same owner+phase for an op REPLACES the prior one. Returns the op-keyword.

Register a cross-cutting hook on operation `:op` (its op-keyword, e.g.
:struct_patch). `:phase` is :after (default — sees & may rewrite the result
envelope), :before (sees & may rewrite the args vector), or :around (MIDDLEWARE
— wraps the call). `:fn` is, for :after, (fn [env op-kw args result] ->
result-envelope); for :before, (fn [env op-kw args] -> args-vector); for
:around, (fn [env op-kw args next] -> result) where `next` runs the inner call
and may be invoked zero+ times (skip / retry) or wrapped in try/catch (recover
— this is how an op is made NOT to fail). `:owner` (an ext keyword) makes the
registration idempotent across `:reload`s — re-registering the same
owner+phase for an op REPLACES the prior one. Returns the op-keyword.
sourceraw docstring

register-provider!clj

(register-provider! spec)

Register a provider in the global registry. Idempotent on :provider/id - re-registering replaces the previous descriptor. Returns the validated provider.

Register a provider in the global registry. Idempotent on
`:provider/id` - re-registering replaces the previous descriptor.
Returns the validated provider.
sourceraw docstring

register-resource!clj

(register-resource! session resource)
(register-resource! session
                    resource
                    {:keys [stop-fn restart-fn alive-fn logs-fn] :as fns})

Register (or replace) a resource UNDER session. resource is the DATA map (needs at least :id, unique within the session; :kind defaults to :resource). fns carries the live lifecycle thunks {:stop-fn :restart-fn :alive-fn :logs-fn} (all optional — a resource with no :stop-fn reports can_stop false). Returns the stored DATA map.

Register (or replace) a resource UNDER `session`. `resource` is the DATA map
(needs at least `:id`, unique within the session; `:kind` defaults to
`:resource`). `fns` carries the live lifecycle thunks `{:stop-fn :restart-fn
:alive-fn :logs-fn}` (all optional — a resource with no `:stop-fn` reports
`can_stop false`). Returns the stored DATA map.
sourceraw docstring

register-theme!clj

(register-theme! theme-map)
(register-theme! id theme-map)

Add or replace one theme in the process registry.

Arity 1 expects a full theme map with :name. Arity 2 accepts either a full theme map or a compact settings map such as {"PADDING" "0px"}.

Add or replace one theme in the process registry.

Arity 1 expects a full theme map with `:name`. Arity 2 accepts either a
full theme map or a compact settings map such as `{"PADDING" "0px"}`.
sourceraw docstring

register-themes!clj

(register-themes! theme-map)

Add every entry from an extension-style theme map.

{"THEME_NAME" {"PADDING" "0px"}}

Values may be compact settings maps or full theme maps.

Add every entry from an extension-style theme map.

  {"THEME_NAME" {"PADDING" "0px"}}

Values may be compact settings maps or full theme maps.
sourceraw docstring

register-toggle!clj

(register-toggle! spec)

Register one toggle. spec must satisfy :toggle/spec.

Re-registering the same :id is idempotent: metadata MERGES, the live VALUE in state is preserved (user overrides survive reload). Returns the canonical registered spec.

Register one toggle. `spec` must satisfy `:toggle/spec`.

Re-registering the same `:id` is idempotent: metadata MERGES, the
live VALUE in `state` is preserved (user overrides survive reload).
Returns the canonical registered spec.
sourceraw docstring

register-toggles!clj

(register-toggles! specs)

Convenience: register a sequence of specs in order, returns the vec of canonical specs.

Convenience: register a sequence of specs in order, returns the
vec of canonical specs.
sourceraw docstring

registered-backendsclj

(registered-backends)

Map of registered backends keyed by id.

Map of registered backends keyed by id.
sourceraw docstring

registered-channelsclj

(registered-channels)

All globally registered channels as a vector.

All globally registered channels as a vector.
sourceraw docstring

registered-commandsclj

(registered-commands)

Return all registered commands as a vector, in registration order.

Return all registered commands as a vector, in registration order.
sourceraw docstring

registered-extension-idsclj

(registered-extension-ids)

Sorted vector of every extension id known to the manifest registry.

Sorted vector of every extension id known to the manifest registry.
sourceraw docstring

registered-extensionsclj

(registered-extensions)
source

registered-extensions-summaryclj

(registered-extensions-summary)

Pure data view of the manifest registry: returns {<id> {:nses [...]}} for every loaded extension.

Pure data view of the manifest registry: returns `{<id> {:nses [...]}}`
for every loaded extension.
sourceraw docstring

registered-providersclj

(registered-providers)
source

registered-slashesclj

(registered-slashes)

Walk every globally registered extension and return the union of their :ext/slash-commands specs. Activation-fn filtering is NOT applied here — channels that surface slash UX before a session is running (TUI palette overlay, Telegram setMyCommands) use this env-less view. The engine dispatch path itself goes through active-slashes env so per-session activation-fn rules still hold.

Walk every globally registered extension and return the union of
their `:ext/slash-commands` specs. Activation-fn filtering is NOT
applied here — channels that surface slash UX before a session is
running (TUI palette overlay, Telegram `setMyCommands`) use this
env-less view. The engine dispatch path itself goes through
`active-slashes env` so per-session activation-fn rules still hold.
sourceraw docstring

registered-startable-resourcesclj

(registered-startable-resources)

Union of every registered extension's :ext/startable-resources — the declarative resources any channel's Resources UI can start (each with its own label + proposed options + start-fn).

A startable may declare a :visible-fn (() -> bool) to gate its appearance, e.g. behind a feature toggle; non-visible ones are dropped here so EVERY channel's Resources UI (web modal + TUI dialog) hides them uniformly.

Union of every registered extension's `:ext/startable-resources` — the
declarative resources any channel's Resources UI can start (each with its own
label + proposed options + start-fn).

A startable may declare a `:visible-fn` (() -> bool) to gate its appearance,
e.g. behind a feature toggle; non-visible ones are dropped here so EVERY
channel's Resources UI (web modal + TUI dialog) hides them uniformly.
sourceraw docstring

registered-togglesclj

(registered-toggles)

Vec of every registered toggle's normalized spec, in registration insertion order. Stable for the TUI settings dialog.

Vec of every registered toggle's normalized spec, in registration
insertion order. Stable for the TUI settings dialog.
sourceraw docstring

registered-underclj

(registered-under parent-path)

Return the vector of registered commands whose :cmd/parent equals parent-path (a vector of names). Use this from a parent command's :cmd/subcommands slot - typically as a 0-arg fn so newly registered children appear immediately:

{:cmd/name "ext"
 :cmd/doc  "Run an extension command."
 :cmd/subcommands #(registered-under ["ext"])}
Return the vector of registered commands whose `:cmd/parent` equals
`parent-path` (a vector of names). Use this from a parent command's
`:cmd/subcommands` slot - typically as a 0-arg fn so newly
registered children appear immediately:

    {:cmd/name "ext"
     :cmd/doc  "Run an extension command."
     :cmd/subcommands #(registered-under ["ext"])}
sourceraw docstring

reload-config!clj

(reload-config!)
source

reload-python-extensions!clj

(reload-python-extensions!)
(reload-python-extensions! opts)

Force a full reload of every Python extension (even when no file changed). Same return shape as load-python-extensions!. Live sessions pick the new tool bindings up at the next turn boundary.

Force a full reload of every Python extension (even when no file
changed). Same return shape as `load-python-extensions!`. Live
sessions pick the new tool bindings up at the next turn boundary.
sourceraw docstring

remove-channel-event-listener!clj

source

remove-config-provider!clj

(remove-config-provider! provider-id)
(remove-config-provider! provider-id source)

Remove every persisted provider entry for provider-id from ~/.vis/config.edn, preserving unrelated global config keys. Project-local .vis/config.edn is an overlay and is not edited by this writer. Returns true when the global file changed.

Remove every persisted provider entry for `provider-id` from
`~/.vis/config.edn`, preserving unrelated global config keys. Project-local
`.vis/config.edn` is an overlay and is not edited by this writer. Returns
true when the global file changed.
sourceraw docstring

remove-provider!clj

(remove-provider! provider-id)
(remove-provider! provider-id source)

Remove a provider from the persisted fleet AND run the registered extension's logout when present. Returns true when config changed.

Remove a provider from the persisted fleet AND run the registered
extension's logout when present. Returns true when config changed.
sourceraw docstring

remove-python-extension-change-listener!clj

(remove-python-extension-change-listener! listener-id)

Remove a listener registered with [[add-change-listener!]]. Returns nil.

Remove a listener registered with [[add-change-listener!]]. Returns nil.
sourceraw docstring

remove-title-listener!clj

(remove-title-listener! session-id listener-fn)

Deregister a previously added listener. Idempotent.

Deregister a previously added listener. Idempotent.
sourceraw docstring

remove-title-pending-listener!clj

(remove-title-pending-listener! session-id listener-fn)

Deregister a previously added pending listener. Idempotent.

Deregister a previously added pending listener. Idempotent.
sourceraw docstring

renderclj

(render input flavor)
(render input flavor opts)

Render any answer input into a flavor.

Input: string | Hiccup vector | [:ir ...] AST | sequential of mixed Flavor: :html | :markdown | :plain Opts: {:context #{:answer :thinking :status :error} :max-length int - hard cap; truncate at paragraph boundary}

Render any answer input into a flavor.

Input:  string | Hiccup vector | [:ir ...] AST | sequential of mixed
Flavor: :html | :markdown | :plain
Opts:   {:context    #{:answer :thinking :status :error}
         :max-length int  - hard cap; truncate at paragraph boundary}
sourceraw docstring

render-commandclj

(render-command cmd path)

Render multi-section help for a single command: USAGE / DESCRIPTION / SUBCOMMANDS / ARGUMENTS / FLAGS / EXAMPLES.

Empty sections are omitted. path is the command-name chain leading up to and including this command - used for the USAGE line when :cmd/usage isn't set.

Render multi-section help for a single command:
  USAGE / DESCRIPTION / SUBCOMMANDS / ARGUMENTS / FLAGS / EXAMPLES.

Empty sections are omitted. `path` is the command-name chain
leading up to and including this command - used for the USAGE line
when `:cmd/usage` isn't set.
sourceraw docstring

render-form-valueclj

(render-form-value _src v)

THE model-facing string for one tool/form VALUE: the canonical STRUCTURED serialization of the result, and nothing else. Tools return maps or vectors and the model reads them as DATA — there is NO per-tool rendering, no hash-gutter file views, no rg grouping.

:op (the call head) is stripped from maps since the call is already visible in the assistant replay; src is accepted for call-site compatibility but no longer affects the output. File reads return :anchors as an ordered {"ln:hash" text} map — the key IS the patch from_anchor — so editing resolves straight off this structured data.

THE model-facing string for one tool/form VALUE: the canonical
STRUCTURED serialization of the result, and nothing else. Tools return
maps or vectors and the model reads them as DATA — there is NO per-tool
rendering, no hash-gutter file views, no rg grouping.

`:op` (the call head) is stripped from maps since the call is already
visible in the assistant replay; `src` is accepted for call-site
compatibility but no longer affects the output. File reads return `:anchors`
as an ordered `{"ln:hash" text}` map — the key IS the `patch from_anchor`
— so editing resolves straight off this structured data.
sourceraw docstring

render-promptclj

(render-prompt {:keys [heading usage-note notes] :as opts})

Render canonical :ext/prompt-fn text from symbol docstrings + arglists.

Accepts an extension map or any map with:

  • :ext/description or :heading
  • :ext.engine/alias optional {:alias 'v}
  • :ext.engine/symbols vector of symbol + value entries
  • :usage-note optional extra note added to the heading
  • :notes optional string or seq of extra lines appended verbatim

Returns a prompt string suitable for :ext/prompt-fn.

Render canonical :ext/prompt-fn text from symbol docstrings + arglists.

Accepts an extension map or any map with:
- :ext/description      or :heading
- :ext.engine/alias optional {:alias 'v}
- :ext.engine/symbols  vector of symbol + value entries
- :usage-note   optional extra note added to the heading
- :notes        optional string or seq of extra lines appended verbatim

Returns a prompt string suitable for :ext/prompt-fn.
sourceraw docstring

render-treeclj

(render-tree root)

Top-level overview rendered when the binary is invoked with no arguments (or via vis help). Shows the root doc, then a single COMMANDS block listing every immediate subcommand.

Top-level overview rendered when the binary is invoked with no
arguments (or via `vis help`). Shows the root doc, then a single
COMMANDS block listing every immediate subcommand.
sourceraw docstring

reset-themes!clj

(reset-themes!)

Reset process registry to built-in themes. Test/dev helper.

Reset process registry to built-in themes. Test/dev helper.
sourceraw docstring

resolve-configclj

(resolve-config)
(resolve-config explicit-config)

Resolve provider config: explicit -> ~/.vis/config.edn. Throws when nothing is available.

Resolve provider config: explicit -> `~/.vis/config.edn`.
Throws when nothing is available.
sourceraw docstring

resolve-db-specclj

(resolve-db-spec)
(resolve-db-spec explicit-db-spec)

Resolve DB spec: explicit -> VIS_DB_PATH env -> :db-spec from config.edn -> default sqlite at ~/.vis/vis.mdb.

Resolve DB spec: explicit -> VIS_DB_PATH env -> `:db-spec` from
config.edn -> default sqlite at `~/.vis/vis.mdb`.
sourceraw docstring

resolve-effective-modelclj

(resolve-effective-model router)
(resolve-effective-model router _routing-overrides)

Best-effort root model descriptor from router config.

The returned map carries :name (model id, e.g. "gpt-4o") AND :provider (provider id keyword, e.g. :openai) so every caller can persist BOTH alongside the model. Earlier versions returned just the model map and the provider id was silently dropped on the way to the DB - leaving the meta layer with no way to render provider/model.

Best-effort root model descriptor from router config.

The returned map carries `:name` (model id, e.g. "gpt-4o") AND
`:provider` (provider id keyword, e.g. `:openai`) so every caller
can persist BOTH alongside the model. Earlier versions returned
just the model map and the provider id was silently dropped on
the way to the DB - leaving the meta layer with no way to render
`provider/model`.
sourceraw docstring

resolve-subcommandsclj

(resolve-subcommands cmd)

Return the static vector of subcommands, calling the dynamic fn when needed. Returns [] when the command has no children.

Return the static vector of subcommands, calling the dynamic fn
when needed. Returns `[]` when the command has no children.
sourceraw docstring

resource-logsclj

(resource-logs session id)

Captured output lines for session+id, via the resource's :logs-fn thunk. Returns a vector of line strings (newest last), or nil when the resource has no logs-fn (can_logs false) or is unknown. Shell backgrounds expose their ring buffer; managed language REPLs can expose launcher logs.

Captured output lines for `session`+`id`, via the resource's `:logs-fn` thunk.
Returns a vector of line strings (newest last), or nil when the resource has
no logs-fn (`can_logs false`) or is unknown. Shell backgrounds expose their
ring buffer; managed language REPLs can expose launcher logs.
sourceraw docstring

restart-resource!clj

(restart-resource! session id)

Run a resource's :restart-fn (kept registered). Scoped to session. The restart-fn owns re-registration of any changed DATA (e.g. a new port).

Run a resource's `:restart-fn` (kept registered). Scoped to `session`. The
restart-fn owns re-registration of any changed DATA (e.g. a new port).
sourceraw docstring

result-cardclj

(result-card {:keys [tool-color-role result-summary result-render]
              tool-name :vis/tool-name})

Canonical tool-result CARD descriptor — the ONE place the op-card / collapse decision is made, so the TUI and web AGREE on tool?/label/colour/summary/ collapsible instead of each re-deriving it from the raw form. Given an executed form map, returns the op-card shape for a NATIVE TOOL result:

{:tool? true :label "RG" — op-card badge label (tool-label) :color-role :tool-color/search — badge colour role (keyword-normalized, since a JSON wire hop stringifies it) :summary "5 hits in 1 file" — the HEADLINE (:result-summary), nil when the tool authored none :body "…markdown…" — the detail body (:result-render), nil for a summary-only tool (move/delete) :collapsible? true} — true ⇔ there's a body to fold under the summary (a chevron/<details>)

nil for a NON-tool form (no :vis/tool-name) — its result rendering stays channel-specific (raw value / stdout). The badge is whatever the tool's :summary already produced; no first-line-of-body heuristic.

Canonical tool-result CARD descriptor — the ONE place the op-card / collapse
decision is made, so the TUI and web AGREE on `tool?`/label/colour/summary/
collapsible instead of each re-deriving it from the raw form. Given an executed
form map, returns the op-card shape for a NATIVE TOOL result:

  {:tool?        true
   :label        "RG"                — op-card badge label (`tool-label`)
   :color-role   :tool-color/search   — badge colour role (keyword-normalized,
                                        since a JSON wire hop stringifies it)
   :summary      "5 hits in 1 file"  — the HEADLINE (`:result-summary`), nil
                                        when the tool authored none
   :body         "…markdown…"        — the detail body (`:result-render`), nil
                                        for a summary-only tool (move/delete)
   :collapsible? true}                — true ⇔ there's a body to fold under
                                        the summary (a chevron/`<details>`)

`nil` for a NON-tool form (no `:vis/tool-name`) — its result rendering stays
channel-specific (raw value / stdout). The badge is whatever the tool's
`:summary` already produced; no first-line-of-body heuristic.
sourceraw docstring

result-cardsclj

(result-cards form)

The op-card descriptor(s) a form renders — the ONE place a channel asks "what cards does this form show?" so the TUI and web never re-derive it differently.

A python block that print()ed several tool results carries a :cards vector of canonical mini-forms; each becomes its OWN op-card via result-card. Any other form yields its single result-card (or none). Always a vector — channels just iterate. Empty when the form has no tool card at all (plain value / stdout).

The op-card descriptor(s) a form renders — the ONE place a channel asks "what
cards does this form show?" so the TUI and web never re-derive it differently.

A python block that print()ed several tool results carries a `:cards` vector of
canonical mini-forms; each becomes its OWN op-card via `result-card`. Any other
form yields its single `result-card` (or none). Always a vector — channels just
iterate. Empty when the form has no tool card at all (plain value / stdout).
sourceraw docstring

router-initialized?clj

(router-initialized?)

True once the shared router has been built (via get-router/rebuild-router!). Lets a frontend defer the FIRST build to lazy first-use instead of forcing it at startup — so OAuth token fetches (Copilot/Codex) never run at TUI boot.

True once the shared router has been built (via `get-router`/`rebuild-router!`).
Lets a frontend defer the FIRST build to lazy first-use instead of forcing it
at startup — so OAuth token fetches (Copilot/Codex) never run at TUI boot.
sourceraw docstring

router-optsclj

(router-opts config)

Extracts svar/make-router opts from a Vis config map.

Reads the :router block from ~/.vis/config.edn:

{:router
 {:rate-limit {:same-provider-delays-ms [2000 3000 6000]
               :fallback-after-ms 30000
               :respect-retry-after? true
               :fallback-provider? true}
  :network    {:timeout-ms 300000 :idle-timeout-ms 45000}
  :budget     {:max-tokens 1000000 :max-cost 5.0}}}

Returns {} when no :router block is present so svar's built-in defaults win. Unknown keys are dropped — only the keys svar's make-router knows about flow through.

See com.blockether.svar.internal.router/make-router for the authoritative key reference.

Extracts `svar/make-router` opts from a Vis config map.

Reads the `:router` block from `~/.vis/config.edn`:

```clojure
{:router
 {:rate-limit {:same-provider-delays-ms [2000 3000 6000]
               :fallback-after-ms 30000
               :respect-retry-after? true
               :fallback-provider? true}
  :network    {:timeout-ms 300000 :idle-timeout-ms 45000}
  :budget     {:max-tokens 1000000 :max-cost 5.0}}}
```

Returns `{}` when no `:router` block is present so svar's built-in
defaults win. Unknown keys are dropped — only the keys svar's
`make-router` knows about flow through.

See `com.blockether.svar.internal.router/make-router` for the
authoritative key reference.
sourceraw docstring

run-doctor-checksclj

(run-doctor-checks environment)

Walk every registered extension, invoke its :ext/doctor-fn, return a vec of message maps with :ext auto-injected. The extension's fn is responsible for stamping :check-id on each message when it wants per-section grouping in the formatter.

Plan §10: extensions in registration order; messages in fn-return order. Activation-fn ignored: every registered extension's fn runs.

Walk every registered extension, invoke its `:ext/doctor-fn`,
return a vec of message maps with `:ext` auto-injected. The
extension's fn is responsible for stamping `:check-id` on each
message when it wants per-section grouping in the formatter.

Plan §10: extensions in registration order; messages in fn-return
order. Activation-fn ignored: every registered extension's fn runs.
sourceraw docstring

save-config!clj

(save-config! config)
(save-config! config source)

Persist provider config to ~/.vis/config.edn.

When the first provider (the active provider) changes, the newly selected provider's optional :provider/on-selected-fn is invoked after the file write. Hook failures are logged and never prevent config persistence.

Persist provider config to `~/.vis/config.edn`.

When the first provider (the active provider) changes, the newly
selected provider's optional `:provider/on-selected-fn` is invoked
after the file write. Hook failures are logged and never prevent
config persistence.
sourceraw docstring

save-config-providers!clj

(save-config-providers! providers)
(save-config-providers! providers source)

Replace the :providers vec in the GLOBAL config file (project overlay files are never edited), preserving unrelated keys, then reload the in-memory config so the running router sees the change. Returns the persisted vec.

Replace the `:providers` vec in the GLOBAL config file (project
overlay files are never edited), preserving unrelated keys, then
reload the in-memory config so the running router sees the change.
Returns the persisted vec.
sourceraw docstring

save-extension-env-var!clj

(save-extension-env-var! name value)

Persist or clear one extension env override in ~/.vis/config.edn. Blank/nil value removes the override, revealing the process env value again if one exists. Preserves all other config keys.

Persist or clear one extension env override in `~/.vis/config.edn`.
Blank/nil `value` removes the override, revealing the process env
value again if one exists. Preserves all other config keys.
sourceraw docstring

search-textclj

(search-text v)

Universal plain-text projection for full-text search / clipboard / logging. Accepts canonical IR, a markdown string, or anything ->ast can coerce; returns a single concatenated string suitable for FT5 indexing or substring matching.

IR-side rendering: all prose/list/quote/table text collapses to spaces; :code/:c bodies are included verbatim (often the highest-signal text for search). Strings are lifted via markdown->ir so search hits the same shape regardless of upstream contract.

Idempotent on canonical input via the markdown->ir shortcut.

Universal plain-text projection for full-text search / clipboard /
logging. Accepts canonical IR, a markdown string, or anything
`->ast` can coerce; returns a single concatenated string suitable
for FT5 indexing or substring matching.

IR-side rendering: all prose/list/quote/table text collapses to spaces;
`:code`/`:c` bodies are included verbatim (often the highest-signal text
for search).
Strings are lifted via `markdown->ir` so search hits the same shape
regardless of upstream contract.

Idempotent on canonical input via the `markdown->ir` shortcut.
sourceraw docstring

send!clj

(send! id messages)
(send! id messages opts)
source

session->markdownclj

(session->markdown db-info session-ref)
(session->markdown db-info session-ref opts)

Project a full session as a Markdown document on top of the IR pipeline.

Project a full session as a Markdown document on top of the IR
pipeline.
sourceraw docstring

session-model-ofclj

(session-model-of db-info sid)

The preference for session sid as {:provider :model}, or nil for the router default. Prefers the immediate in-memory value, else the DB. Use on the routing path (engine, gateway).

The preference for session `sid` as `{:provider :model}`, or nil for the
router default. Prefers the immediate in-memory value, else the DB. Use on
the routing path (engine, gateway).
sourceraw docstring

session-model-of-cachedclj

(session-model-of-cached db-info sid)

Like model-of but DISPLAY-oriented: when no pending value exists, a recent DB value is served from a tiny TTL cache so callers can read it every frame without a DB hit.

Like `model-of` but DISPLAY-oriented: when no pending value exists, a recent
DB value is served from a tiny TTL cache so callers can read it every frame
without a DB hit.
sourceraw docstring

set-provider!clj

(set-provider! provider)

Set the single active provider config. Persists to disk, updates in-memory state, rebuilds the global router, and reseats cached session envs. provider is a svar-native provider map {:id :base-url :api-key :models [...]}. Replaces an existing provider with the same :id or appends a new entry.

Set the single active provider config. Persists to disk, updates
in-memory state, rebuilds the global router, and reseats cached
session envs. `provider` is a svar-native provider map
`{:id :base-url :api-key :models [...]}`. Replaces an existing
provider with the same `:id` or appends a new entry.
sourceraw docstring

set-python-binding!clj

(set-python-binding! python-context sym val)

Bind sym -> val in the Python sandbox globals. Clojure fns are wired as callables; everything else is marshalled.

ASYNC-BY-DEFAULT: a tool fn bound here is also DEFERRED (wrapped by __vis_deferred__, same as build-agent-context's defer step) so await tool(...) / gather(tool(...)) work. This matters because extension and foundation tools are (re)installed via this fn AFTER the context's own defer pass — without deferring here they'd stay raw/synchronous and the await the prompt teaches would fail. The compaction verbs (session_fold/session_drop/__vis_par__) are bound via create-python-context, not here, so they stay direct. No-op when the async preamble isn't installed (the printer/parser helper contexts never bind tools).

Bind `sym` -> `val` in the Python sandbox globals. Clojure fns are wired as
callables; everything else is marshalled.

ASYNC-BY-DEFAULT: a tool fn bound here is also DEFERRED (wrapped by
`__vis_deferred__`, same as `build-agent-context`'s defer step) so
`await tool(...)` / `gather(tool(...))` work. This matters because extension
and foundation tools are (re)installed via this fn AFTER the context's own
defer pass — without deferring here they'd stay raw/synchronous and the
`await` the prompt teaches would fail. The compaction verbs
(`session_fold`/`session_drop`/`__vis_par__`) are bound via `create-python-context`, not
here, so they stay direct. No-op when the async preamble isn't installed
(the printer/parser helper contexts never bind tools).
sourceraw docstring

set-session-model!clj

(set-session-model! db-info sid provider model)

Set (or clear, with blank model) the PROVIDER + MODEL preference for session sid. Takes effect IMMEDIATELY for reads; the DB write is debounced so rapid cycling coalesces to one write. Returns {:provider :model} (or nil).

Set (or clear, with blank model) the PROVIDER + MODEL preference for session
`sid`. Takes effect IMMEDIATELY for reads; the DB write is debounced so
rapid cycling coalesces to one write. Returns `{:provider :model}` (or nil).
sourceraw docstring

set-title!clj

(set-title! id title)

Host-driven title change. Resolves the live env (if any) so the in-memory atom + listener fan-out stay in sync; falls back to a plain DB write when no env is live for this session (e.g. vis sessions rename ops).

Host-driven title change. Resolves the live env (if any) so the
in-memory atom + listener fan-out stay in sync; falls back to a
plain DB write when no env is live for this session (e.g.
`vis sessions` rename ops).
sourceraw docstring

shutdown!clj

(shutdown!)

Flush and stop all telemere handlers. Call after the TUI screen stops.

Flush and stop all telemere handlers. Call after the TUI screen
stops.
sourceraw docstring

slash-by-pathclj

(slash-by-path env path)

Return the slash spec whose full path = path, or nil. path is a non-empty vec of names like ["workspace" "apply"]. When multiple specs share the path (per-channel partitioning), returns the first registered.

Return the slash spec whose full path = `path`, or nil. `path` is a
non-empty vec of names like `["workspace" "apply"]`. When
multiple specs share the path (per-channel partitioning), returns
the first registered.
sourceraw docstring

slash-childrenclj

(slash-children env)
(slash-children env parent)

Return the vec of slash specs whose :slash/parent = parent vec. parent defaults to [] (top-level commands).

Return the vec of slash specs whose `:slash/parent` = `parent` vec.
`parent` defaults to `[]` (top-level commands).
sourceraw docstring

slash-dispatchclj

(slash-dispatch env ctx text)

Dispatch slash text against env. ctx carries channel-side knobs:

:channel/id keyword, required (:tui, :telegram, ...) :session/id session-soul UUID (optional unless slash declares :slash/requires #{:session}) :workspace/id workspace UUID (optional unless required) :db-info persistence handle (always passed when present in the channel env) :reply! (fn [ir-or-string]) for channels that want an immediate side-effect surface :publish! (fn [event]) bus for cross-channel events

Return shapes documented at the namespace docstring.

Dispatch slash `text` against `env`. `ctx` carries channel-side knobs:

  :channel/id            keyword, required (:tui, :telegram, ...)
  :session/id            session-soul UUID (optional unless slash
                         declares `:slash/requires #{:session}`)
  :workspace/id          workspace UUID (optional unless required)
  :db-info               persistence handle (always passed when
                         present in the channel env)
  :reply!                (fn [ir-or-string]) for channels that want
                         an immediate side-effect surface
  :publish!              (fn [event]) bus for cross-channel events

Return shapes documented at the namespace docstring.
sourceraw docstring

slash-parseclj

(slash-parse text)

Tokenise a slash text into {:path :args :raw} or nil.

This function performs PURE tokenisation. It does NOT consult any slash registry; the engine resolves the longest matching prefix at dispatch time once it has the env. This keeps parse pure and testable in isolation.

Tokenise a slash `text` into `{:path :args :raw}` or nil.

This function performs PURE tokenisation. It does NOT consult any
slash registry; the engine resolves the longest matching prefix at
dispatch time once it has the env. This keeps `parse` pure and
testable in isolation.
sourceraw docstring

stable-prompt-textclj

(stable-prompt-text messages)

Join stable prompt message contents for token budgeting and debug bindings only. Provider sends the original message vector; this is not a send path.

Join stable prompt message contents for token budgeting and debug bindings only.
Provider sends the original message vector; this is not a send path.
sourceraw docstring

stop-resource!clj

(stop-resource! session id)

Run a resource's :stop-fn and unregister it. THE single stop path — the agent tool and the footer both land here, always scoped to session so no session can stop another's resource. Returns a result map.

Run a resource's `:stop-fn` and unregister it. THE single stop path — the
agent tool and the footer both land here, always scoped to `session` so no
session can stop another's resource. Returns a result map.
sourceraw docstring

symbolclj

(symbol v)
(symbol v opts)

Build a function symbol entry FROM A CLOJURE VAR.

The 3-arg form (symbol sym-name f opts) is a test-friendly direct constructor: pass the sandbox-visible symbol, the implementation fn, and an opts map whose :doc / :arglists are read directly from opts instead of var meta. Production code uses the var form.

The var supplies :symbol (var name), :fn (the var's value), :doc and :arglists (read from var metadata - i.e. the underlying defn's docstring + arglists). Pass it as #'my-tool.

Observed tools return canonical internal envelope maps and must provide a symbol-specific channel renderer. The model-facing surface is the per-iteration trailer (real Python form values); no per-tool model-side render exists.

Raw helpers pass :raw? true and return plain values directly, with no envelope enforcement, channel sink, or tool metadata.

Optional opts: :symbol - override the Python sandbox name (default: var name). :doc-fn - compute doc lazily from (sym v) when the var lacks a docstring (third-party vars only). :raw? - true for plain composable helpers. :tag - REQUIRED :observation | :mutation for observed tools (unless :raw? true). :before-fn :after-fn :on-error-fn

Observed tool functions return canonical internal envelope maps. The wrapper records the envelope, then returns only its payload to Python; failure envelopes are converted into thrown ex-info so Python reports normal errors.

:doc and :arglists ALWAYS come from var metadata — the previous test-only (symbol sym-name f opts) 3-arg form is RETIRED. Tests that want to register an inline fn must defn it first and pass #'the-fn.

See docs/src/extensions/hooks.md for hook semantics.

Build a function symbol entry FROM A CLOJURE VAR.

The 3-arg form `(symbol sym-name f opts)` is a test-friendly direct
constructor: pass the sandbox-visible symbol, the implementation fn, and
an opts map whose `:doc` / `:arglists` are read directly from opts
instead of var meta. Production code uses the var form.

The var supplies `:symbol` (var name), `:fn` (the var's value), `:doc` and
`:arglists` (read from var metadata - i.e. the underlying defn's
docstring + arglists). Pass it as `#'my-tool`.

Observed tools return canonical internal envelope maps and must provide
a symbol-specific channel renderer. The model-facing surface is the
per-iteration trailer (real Python form values); no per-tool model-side
render exists.

Raw helpers pass `:raw? true` and return plain values directly, with no
envelope enforcement, channel sink, or tool metadata.

Optional opts:
  :symbol      - override the Python sandbox name (default: var name).
  :doc-fn      - compute doc lazily from `(sym v)` when the var
                 lacks a docstring (third-party vars only).
  :raw?        - true for plain composable helpers.
  :tag         - REQUIRED `:observation | :mutation` for observed
                 tools (unless `:raw? true`).
  :before-fn :after-fn :on-error-fn

Observed tool functions return canonical internal envelope maps. The
wrapper records the envelope, then returns only its payload to Python; failure
envelopes are converted into thrown ex-info so Python reports normal errors.

`:doc` and `:arglists` ALWAYS come from var metadata — the previous
test-only `(symbol sym-name f opts)` 3-arg form is RETIRED. Tests
that want to register an inline fn must `defn` it first and pass
`#'the-fn`.

See `docs/src/extensions/hooks.md` for hook semantics.
sourceraw docstring

sync-active-extension-symbols!clj

(sync-active-extension-symbols! environment)
(sync-active-extension-symbols! environment active-extensions)

Make the Python sandbox's callable globals match active extension state.

install-extension! keeps every extension row in :extensions, but only active extensions contribute callable symbols. Called after per-env installation and again at turn start so :ext/activation-fn changes become real tool availability, not just prompt visibility.

The Python sandbox is FLAT globals (no namespaces/aliases/macros): active extensions putMember their symbols straight into the top scope; deactivated extensions have theirs removed (putMember nil). Symbol names are snake-ified by env/set-python-binding!.

Make the Python sandbox's callable globals match active extension state.

`install-extension!` keeps every extension row in `:extensions`, but only
active extensions contribute callable symbols. Called after per-env
installation and again at turn start so `:ext/activation-fn` changes become
real tool availability, not just prompt visibility.

The Python sandbox is FLAT globals (no namespaces/aliases/macros): active
extensions putMember their symbols straight into the top scope; deactivated
extensions have theirs removed (putMember nil). Symbol names are snake-ified
by env/set-python-binding!.
sourceraw docstring

system-var-sym?clj

(system-var-sym? sym)
source

SYSTEM_VAR_NAMESclj

Engine-owned symbols hidden from user live-var listings.

Engine-owned symbols hidden from user live-var listings.
sourceraw docstring

test-python-extensions!clj

(test-python-extensions!)
(test-python-extensions! {:keys [dirs]})

Discover and run every Python test (test_*.py / *_test.py) across the extension dirs (default: ~/.vis/extensions and <cwd>/.vis/extensions), each in its own TRUSTED GraalPy context via the built-in pytest-compat shim. Tests import the extension's own package through the sys.path sugar, exactly like extension.py does.

Returns {:files n :ok? bool :passed n :failed n :errored n :skipped n :tests [{:file :nodeid :outcome :message}] :results [{:file :ok? :tests …}]}. Counts are DERIVED from :tests (the flat per-test list) — the single source of truth. Never throws: a file that blows up at import is one :errored result, not a crash.

Discover and run every Python test (`test_*.py` / `*_test.py`) across the
extension dirs (default: `~/.vis/extensions` and `<cwd>/.vis/extensions`),
each in its own TRUSTED GraalPy context via the built-in `pytest`-compat
shim. Tests import the extension's own package through the `sys.path` sugar,
exactly like `extension.py` does.

Returns `{:files n :ok? bool :passed n :failed n :errored n :skipped n
:tests [{:file :nodeid :outcome :message}] :results [{:file :ok? :tests …}]}`.
Counts are DERIVED from `:tests` (the flat per-test list) — the single source
of truth. Never throws: a file that blows up at import is one `:errored`
result, not a crash.
sourceraw docstring

themeclj

(theme id)

Return registered theme by id (string or keyword). Unknown ids fall back to default-theme.

Return registered theme by id (string or keyword). Unknown ids fall back to
`default-theme`.
sourceraw docstring

theme->web-css-varsclj

(theme->web-css-vars {:keys [palette]})

CSS custom-property map ("--bg" -> "#rrggbb") for a theme map - the palette-named tokens, the derived bg/fg mixes, and the luminance-delta-normalized border hairlines.

CSS custom-property map ("--bg" -> "#rrggbb") for a theme map -
the palette-named tokens, the derived bg/fg mixes, and the
luminance-delta-normalized border hairlines.
sourceraw docstring

theme-registryclj

(theme-registry)

Return current immutable theme registry map.

Return current immutable theme registry map.
sourceraw docstring

themesclj

source

toggle-add-listener!clj

(toggle-add-listener! f)

Register a no-arg-or-event listener fn. Returns a dispose! thunk the caller invokes when their consumer goes away (channel close, extension reload, ...).

Register a no-arg-or-event listener fn. Returns a `dispose!` thunk
the caller invokes when their consumer goes away (channel close,
extension reload, ...).
sourceraw docstring

toggle-choicesclj

(toggle-choices id)

Vec of legal choices for an :enum toggle. Empty when id is unregistered or registered as :boolean.

Vec of legal choices for an `:enum` toggle. Empty when `id` is
unregistered or registered as `:boolean`.
sourceraw docstring

toggle-cycle-value!clj

(toggle-cycle-value! id)

Advance an :enum toggle one step through its registered :choices. Wraps at the end. Throws on boolean toggles.

Advance an `:enum` toggle one step through its registered
`:choices`. Wraps at the end. Throws on boolean toggles.
sourceraw docstring

toggle-enabled?clj

(toggle-enabled? id)

Boolean cast of (value-of id), OR forced ON in the current dynamic scope (*forced-on*). Fail-closed: returns false when id is not registered and not forced. Hot-path — one set lookup + one atom deref.

Boolean cast of `(value-of id)`, OR forced ON in the current dynamic scope
(`*forced-on*`). Fail-closed: returns `false` when `id` is not registered and
not forced. Hot-path — one set lookup + one atom deref.
sourceraw docstring

toggle-reset-to-default!clj

(toggle-reset-to-default! id)

Drop the user override for id so resolution falls back to the registered default. Notifies listeners when the effective value changes.

Drop the user override for `id` so resolution falls back to the
registered default. Notifies listeners when the effective value
changes.
sourceraw docstring

toggle-set-enabled!clj

(toggle-set-enabled! id value)

Boolean alias of set-value! for the TUI dialog — keeps the common toggle-flip call sites readable. Refuses :enum toggles so an accidental boolean-flip on a multi-value toggle surfaces loudly; use cycle-value! / set-value! for those.

Boolean alias of `set-value!` for the TUI dialog — keeps the
common toggle-flip call sites readable. Refuses `:enum` toggles
so an accidental boolean-flip on a multi-value toggle surfaces
loudly; use `cycle-value!` / `set-value!` for those.
sourceraw docstring

toggle-set-value!clj

(toggle-set-value! id value)

Set id to value and notify listeners. Returns the new value. Validation matches the registered :type: :boolean — coerce to boolean. :enum — must be one of :choices; otherwise throws :vis.toggles/invalid-value so the bug surfaces at the call site instead of later in render.

Set `id` to `value` and notify listeners. Returns the new value.
Validation matches the registered `:type`:
  `:boolean` — coerce to boolean.
  `:enum`    — must be one of `:choices`; otherwise throws
                `:vis.toggles/invalid-value` so the bug surfaces
                at the call site instead of later in render.
sourceraw docstring

toggle-specclj

(toggle-spec id)

Lookup the registered spec for id, or nil.

Lookup the registered spec for `id`, or nil.
sourceraw docstring

toggle-typeclj

(toggle-type id)

:boolean / :enum / nil for unknown.

`:boolean` / `:enum` / nil for unknown.
sourceraw docstring

toggle-valueclj

(toggle-value id)

Resolve the live value for id. Lookup order:

  1. live override in state,
  2. registered default,
  3. nil if the toggle isn't registered.

Returns the raw value (boolean for :boolean toggles, any value from :choices for :enum toggles). enabled? is the boolean-cast convenience for the common boolean path.

Resolve the live value for `id`. Lookup order:
  1. live override in `state`,
  2. registered default,
  3. `nil` if the toggle isn't registered.

Returns the raw value (boolean for `:boolean` toggles, any value
from `:choices` for `:enum` toggles). `enabled?` is the
boolean-cast convenience for the common boolean path.
sourceraw docstring

toggles-for-channelclj

(toggles-for-channel channel)

visible-toggles further scoped to channel via toggle-for-channel?. Channels render THIS instead of visible-toggles so each Settings UI only shows controls it actually honours.

`visible-toggles` further scoped to `channel` via `toggle-for-channel?`.
Channels render THIS instead of `visible-toggles` so each Settings UI
only shows controls it actually honours.
sourceraw docstring

toggles-hydrate-from-config!clj

(toggles-hydrate-from-config! config-map)

Bulk-apply persisted toggle values from (:toggles config-map). Silently skips ids not in the registry so a stale config file from a previous install can't break boot. Routes through set-value! so enum entries get validated; individual invalid values are dropped (logged via the listener) instead of aborting the whole hydrate.

Bulk-apply persisted toggle values from `(:toggles config-map)`. Silently
skips ids not in the registry so a stale config file from a
previous install can't break boot. Routes through `set-value!`
so enum entries get validated; individual invalid values are
dropped (logged via the listener) instead of aborting the whole
hydrate.
sourceraw docstring

toggles-snapshotclj

(toggles-snapshot)

Return a map {id value} of EVERY persistable toggle's effective value, intended for serialisation. Skips toggles whose :persist? is false. Boolean toggles are coerced to boolean; enum toggles surface their raw choice value. Orphans from a previously-installed extension are dropped.

Return a map `{id value}` of EVERY persistable toggle's effective
value, intended for serialisation. Skips toggles whose
`:persist?` is false. Boolean toggles are coerced to boolean;
enum toggles surface their raw choice value. Orphans from a
previously-installed extension are dropped.
sourceraw docstring

tool-color-rolesclj

The canonical set of native-tool op-card BADGE colour roles — the ONE list both channels colour against (TUI maps each to a lanterna fg, the web to a --tool-* CSS var). Hand-maintained per-channel maps were free to drift; a guard test in each channel asserts its map covers every role here, so a new role can't be added in one channel and silently forgotten in the other.

The canonical set of native-tool op-card BADGE colour roles — the ONE list both
channels colour against (TUI maps each to a lanterna fg, the web to a `--tool-*`
CSS var). Hand-maintained per-channel maps were free to drift; a guard test in
each channel asserts its map covers every role here, so a new role can't be
added in one channel and silently forgotten in the other.
sourceraw docstring

tool-labelclj

(tool-label wire-name)

The op-card badge LABEL for a native tool's wire name: the name uppercased, except the few label-overrides rename. ONE place both channels derive it from so the TUI badge and the web label never drift. nil for a non-tool form.

The op-card badge LABEL for a native tool's wire name: the name uppercased,
except the few `label-overrides` rename. ONE place both channels derive it from
so the TUI badge and the web label never drift. nil for a non-tool form.
sourceraw docstring

tty-inclj

source

tty-outclj

source

turn!clj

(turn! environment messages)
(turn! environment messages opts)

Runs one session turn on an RLM environment using iterative LLM code evaluation.

Params: environment - RLM environment from create-environment. messages - Vector of message maps. Always a vector, e.g.: [(svar/user <prompt-text>)] [(svar/user <prompt-text> (svar/image <b64> <mime-type>))] opts - Map, optional:

  • :spec - Output spec for structured answers.
  • :model - Override config's default model.
  • :max-context-tokens - Token budget for context.
  • :debug? - Enable verbose debug logging (default: false). Logs iteration details, code evaluation, LLM responses at :info level with :rlm-phase context.
  • :reasoning-default - Optional base reasoning effort for reasoning-capable models. Accepts :low/:medium/:high or low/medium/high strings. Adaptive escalation still applies.
  • :extra-body - Optional provider-specific request-body params merged into the upstream LLM call after auto max_tokens + reasoning translation.

Returns: Map with:

  • :trace - Vector of iteration trace entries, each containing: {:iteration N :response <llm-response-text> :blocks [{:id 0 :code <code-str> :result <value> :error nil :envelope {:started-at-ms 10 :finished-at-ms 15 ...}} ...]}
  • :iteration-count - Number of iterations used.
  • :duration-ms - Turn duration in milliseconds.
  • :tokens - Token usage map {:input N :output N :total N}.
  • :cost - Cost map {:input-cost N :output-cost N :total-cost N}.
  • :confidence - Confidence level (:high/:medium/:low) from final iteration.
  • :reasoning - String summary of how the answer was derived (from LLM's FINAL call).
  • :status - Only present on failure (:error or :cancelled).
Runs one session turn on an RLM environment using iterative LLM code evaluation.

 Params:
 `environment` - RLM environment from create-environment.
 `messages` - Vector of message maps. Always a vector, e.g.:
              [(svar/user <prompt-text>)]
              [(svar/user <prompt-text> (svar/image <b64> <mime-type>))]
`opts` - Map, optional:
  - :spec - Output spec for structured answers.
  - :model - Override config's default model.
   - :max-context-tokens - Token budget for context.
   - :debug? - Enable verbose debug logging (default: false). Logs iteration details,
     code evaluation, LLM responses at :info level with :rlm-phase context.
   - :reasoning-default - Optional base reasoning effort for reasoning-capable models.
     Accepts :low/:medium/:high or low/medium/high strings. Adaptive escalation still applies.
   - :extra-body - Optional provider-specific request-body params merged into the
     upstream LLM call after auto max_tokens + reasoning translation.

 Returns:
Map with:
   - :trace - Vector of iteration trace entries, each containing:
       {:iteration N
        :response <llm-response-text>
        :blocks [{:id 0 :code <code-str> :result <value> :error nil
                  :envelope {:started-at-ms 10 :finished-at-ms 15 ...}}
                    ...]}
  - :iteration-count - Number of iterations used.
  - :duration-ms - Turn duration in milliseconds.
  - :tokens - Token usage map {:input N :output N :total N}.
  - :cost - Cost map {:input-cost N :output-cost N :total-cost N}.
  - :confidence - Confidence level (:high/:medium/:low) from final iteration.
   - :reasoning - String summary of how the answer was derived (from LLM's FINAL call).
   - :status - Only present on failure (`:error` or `:cancelled`).
sourceraw docstring

unknown-flagsclj

(unknown-flags arg-specs raw-args)

Return a vector of --flag tokens in raw-args that are NOT declared in arg-specs. Walks the args the same way parse-args does so that a string-typed flag's VALUE (e.g. bar in --out bar) is never misclassified as an unknown flag. Boolean flags don't consume their next token. Universal --help / -h are always considered known.

Used by dispatch! to refuse unknown flags and surface the list of accepted flags via render-command. Pure; no side effects.

Unknown flags are reported only by their leading token; we don't know whether the user intended them to take a value, so the walker conservatively advances by one token after each unknown.

Return a vector of `--flag` tokens in `raw-args` that are NOT declared
in `arg-specs`. Walks the args the same way `parse-args` does so that
a string-typed flag's VALUE (e.g. `bar` in `--out bar`) is never
misclassified as an unknown flag. Boolean flags don't consume their
next token. Universal `--help` / `-h` are always considered known.

Used by `dispatch!` to refuse unknown flags and surface the list of
accepted flags via `render-command`. Pure; no side effects.

Unknown flags are reported only by their leading token; we don't
know whether the user intended them to take a value, so the walker
conservatively advances by one token after each unknown.
sourceraw docstring

unregister-op-hooks-for-owner!clj

(unregister-op-hooks-for-owner! owner)

Remove EVERY op-hook registered by owner (all ops + phases). Driven by deregister-extension! so an extension's hooks die with it; also callable directly to dynamically tear an extension's hooks down.

Remove EVERY op-hook registered by `owner` (all ops + phases). Driven by
`deregister-extension!` so an extension's hooks die with it; also callable
directly to dynamically tear an extension's hooks down.
sourceraw docstring

unregister-resource!clj

(unregister-resource! session id)

Drop a resource from session (does NOT run its stop-fn — caller decides). Returns true if something was removed.

Drop a resource from `session` (does NOT run its stop-fn — caller decides).
Returns true if something was removed.
sourceraw docstring

unregister-theme!clj

(unregister-theme! id)

Remove a theme id. Built-ins reset to their built-in value instead of being removed, so the registry always keeps light and dark available.

Remove a theme id. Built-ins reset to their built-in value instead of being
removed, so the registry always keeps light and dark available.
sourceraw docstring

unregister-themes!clj

(unregister-themes! ids)
source

unwatch-notifications!clj

(unwatch-notifications! key)

Remove the watcher registered under key. Returns true when one was actually removed.

Remove the watcher registered under `key`. Returns true when one
was actually removed.
sourceraw docstring

update-config-provider!clj

(update-config-provider! provider-id f)
(update-config-provider! provider-id f source)

Apply f to the persisted provider entry with provider-id and save. Returns the new fleet.

Apply `f` to the persisted provider entry with `provider-id` and
save. Returns the new fleet.
sourceraw docstring

update-resource!clj

(update-resource! session id patch)

Patch the DATA of an existing resource (e.g. flip :status, refresh :detail). No-op if unknown. Returns the updated DATA map or nil.

Patch the DATA of an existing resource (e.g. flip `:status`, refresh
`:detail`). No-op if unknown. Returns the updated DATA map or nil.
sourceraw docstring

validate-argsclj

(validate-args arg-specs parsed)

Validate parsed args against spec. Returns nil on success, or an error string describing the missing required arguments.

Validate parsed args against spec. Returns nil on success, or an
error string describing the missing required arguments.
sourceraw docstring

valueclj

(value v)
(value v opts-or-val)
(value sym-name val opts)

Build a value symbol entry FROM A CLOJURE VAR - a plain constant/data binding.

The var supplies :symbol (var name), :val (the var's value, unless :val is provided in opts to override - used by macro-shim entries), and :doc (from var metadata, i.e. the defn's docstring).

(def ^{:doc "Maximum retry attempts."} max-retries 3) (vis/value #'max-retries)

Opts: :symbol - override the Python sandbox name (default: var name). :val - explicit value override (rare; for macro shims that bind a marker map instead of the var's own value).

Build a value symbol entry FROM A CLOJURE VAR - a plain constant/data binding.

The var supplies `:symbol` (var name), `:val` (the var's value, unless `:val`
is provided in opts to override - used by macro-shim entries), and `:doc`
(from var metadata, i.e. the defn's docstring).

(def ^{:doc "Maximum retry attempts."} max-retries 3)
(vis/value #'max-retries)

Opts:
  :symbol - override the Python sandbox name (default: var name).
  :val - explicit value override (rare; for macro shims that bind a
         marker map instead of the var's own value).
sourceraw docstring

virtual-threads-available?clj

(virtual-threads-available?)

True when this JVM exposes Java virtual-thread APIs. Reflection keeps source compatible with older runtimes.

True when this JVM exposes Java virtual-thread APIs. Reflection keeps
source compatible with older runtimes.
sourceraw docstring

vis-darkclj

Default Vis dark theme.

Default Vis dark theme.
sourceraw docstring

vis-lightclj

Default Vis light theme.

Default Vis light theme.
sourceraw docstring

visible-togglesclj

(visible-toggles)

registered-toggles filtered to what settings UIs should SHOW — provider-specific knobs declare a :visible-fn so e.g. the OpenAI Codex verbosity cycle only appears when a Codex provider is actually configured, and :settings? false toggles (e.g. reasoning-effort, which has its own Ctrl+R control) stay out of the Settings dialog entirely. State ops always work on the FULL registry; visibility is a presentation concern only.

`registered-toggles` filtered to what settings UIs should SHOW —
provider-specific knobs declare a `:visible-fn` so e.g. the OpenAI
Codex verbosity cycle only appears when a Codex provider is actually
configured, and `:settings? false` toggles (e.g. reasoning-effort, which
has its own Ctrl+R control) stay out of the Settings dialog entirely.
State ops always work on the FULL registry; visibility is a presentation
concern only.
sourceraw docstring

watch-notifications!clj

(watch-notifications! key f)

Register a watcher under key. The fn f is called with the full active-notifications vec on every push / dismiss / clear. Replacing an existing watcher under the same key is fine - typical pattern is (watch! :tui-screen render-bump).

Watchers run synchronously on the mutating thread, AFTER the atom swap. They MUST be cheap (microseconds) - anything heavier should bounce work onto a future.

Register a watcher under `key`. The fn `f` is called with the
full active-notifications vec on every push / dismiss / clear.
Replacing an existing watcher under the same key is fine -
typical pattern is `(watch! :tui-screen render-bump)`.

Watchers run synchronously on the mutating thread, AFTER the
atom swap. They MUST be cheap (microseconds) - anything heavier
should bounce work onto a future.
sourceraw docstring

web-css-rootclj

(web-css-root theme-or-id)

A :root{...} CSS block for a theme id (or theme map): every shared var from theme->web-css-vars plus color-scheme, ready to serve AFTER the static stylesheet so it overrides the baked-in defaults.

A `:root{...}` CSS block for a theme id (or theme map): every shared
var from `theme->web-css-vars` plus `color-scheme`, ready to serve
AFTER the static stylesheet so it overrides the baked-in defaults.
sourceraw docstring

wire-json-prettyclj

(wire-json-pretty x)

Pretty-printed (2-space indent) JSON via [[->wire]] — for HUMAN-facing surfaces (the web ctx rail's trailer view), never the wire itself.

Pretty-printed (2-space indent) JSON via [[->wire]] — for
HUMAN-facing surfaces (the web ctx rail's trailer view), never the
wire itself.
sourceraw docstring

wire-json-strclj

(wire-json-str x)

Encode any engine value as a JSON string via [[->wire]].

Encode any engine value as a JSON string via [[->wire]].
sourceraw docstring

worker-futureclj

(worker-future f)
(worker-future name f)

Run f on a cancellable worker Future. Uses a virtual thread when the JVM supports it, otherwise falls back to a named daemon platform thread.

The returned value implements java.util.concurrent.Future plus Clojure deref/realized? protocols so legacy future call sites can migrate without losing timeout/cancellation behavior.

Run `f` on a cancellable worker Future. Uses a virtual thread when the JVM
supports it, otherwise falls back to a named daemon platform thread.

The returned value implements java.util.concurrent.Future plus Clojure
deref/realized? protocols so legacy `future` call sites can migrate without
losing timeout/cancellation behavior.
sourceraw docstring

worker-runtimeclj

(worker-runtime)

Runtime probe for worker execution. :worker-helper is stable metadata for diagnostics; :virtual-threads? reports whether new worker tasks will use Java virtual threads.

Runtime probe for worker execution. `:worker-helper` is stable metadata for
diagnostics; `:virtual-threads?` reports whether new worker tasks will use
Java virtual threads.
sourceraw docstring

workspace-abandon!clj

(workspace-abandon! db-info {:keys [workspace-id reason]})

Release backend-owned roots and transition the row to :discarded. A :live backend (trunk) owns no clone, so its shared root is never deleted.

Release backend-owned roots and transition the row to :discarded. A `:live`
backend (trunk) owns no clone, so its shared root is never deleted.
sourceraw docstring

workspace-add-filesystem-root!clj

(workspace-add-filesystem-root! db-info workspace-id path)

Add path to the workspace's extra filesystem roots. Drafts require the same isolation capabilities for every added root; live workspaces add it live.

Add `path` to the workspace's extra filesystem roots. Drafts require the same
isolation capabilities for every added root; live workspaces add it live.
sourceraw docstring

workspace-apply!clj

(workspace-apply! db-info {:keys [workspace-id]})

Land the draft's since-fork edits into the user's real dirs (trunk), leaving them uncommitted for the user to review/commit. A draft is about the WHOLE workspace: this lands the primary clone AND every auto-cloned filesystem root (each into its own trunk). Vis owns no git lifecycle. Adds/modifications come from the mtime diff; deletions are files that existed at the fork but the agent removed in the draft. Returns {:status :ok :changed [{:status :path :root}] :landed n :workspace ws}.

Land the draft's since-fork edits into the user's real dirs (trunk),
leaving them uncommitted for the user to review/commit. A draft is about
the WHOLE workspace: this lands the primary clone AND every auto-cloned
filesystem root (each into its own trunk). Vis owns no git lifecycle.
Adds/modifications come from the mtime diff; deletions are files that
existed at the fork but the agent removed in the draft. Returns
`{:status :ok :changed [{:status :path :root}] :landed n :workspace ws}`.
sourceraw docstring

workspace-backendclj

(workspace-backend backend)

Validate and return a workspace backend descriptor.

Required keys: :workspace.backend/id keyword :workspace.backend/capabilities capability set :workspace.backend/available-fn ({:source-root :store-root} -> bool or {:available? bool :reason keyword :details map}) :workspace.backend/fork-fn ({:source-root :store-root :name} -> path) :workspace.backend/discard-fn ({:root} -> nil)

Validate and return a workspace backend descriptor.

Required keys:
  :workspace.backend/id            keyword
  :workspace.backend/capabilities  capability set
  :workspace.backend/available-fn  ({:source-root :store-root} -> bool or
                                   {:available? bool :reason keyword :details map})
  :workspace.backend/fork-fn       ({:source-root :store-root :name} -> path)
  :workspace.backend/discard-fn    ({:root} -> nil)
sourceraw docstring

workspace-capabilities-forclj

(workspace-capabilities-for workspace-or-root)

Capability matrix for a workspace (or root path), using the real derived workspace storage location rather than assuming source and destination are on the same filesystem.

Capability matrix for a workspace (or root path), using the real derived
workspace storage location rather than assuming source and destination are
on the same filesystem.
sourceraw docstring

workspace-capability-matrixclj

(workspace-capability-matrix source-root)
(workspace-capability-matrix source-root store-root)

Describe every registered backend for source-root, including availability and declared capabilities. This is the public feature-discovery surface. It never loads extensions: extension discovery owns backend registration.

Describe every registered backend for `source-root`, including availability
and declared capabilities. This is the public feature-discovery surface.
It never loads extensions: extension discovery owns backend registration.
sourceraw docstring

workspace-change-root!clj

(workspace-change-root! db-info session-state-id path)

Repoint session-state-id's PRIMARY filesystem root to path — the session now works in a different project directory: shell cwd, relative path resolution, file tools (cat/patch/write), and search (rg/find_files) all follow from the next turn, because they resolve through the session's pinned workspace. Additional filesystem roots CARRY OVER (they are session-scoped permissions, not root-relative); an entry equal to the new root is dropped as redundant. Refuses while the session is in a draft — a draft is a fork of the OLD root, so apply/abandon it first. Returns the newly pinned trunk workspace (or the current one when path already IS the root).

Repoint `session-state-id`'s PRIMARY filesystem root to `path` — the
session now works in a different project directory: shell cwd, relative
path resolution, file tools (cat/patch/write), and search (rg/find_files)
all follow from the next turn, because they resolve through the session's
pinned workspace. Additional filesystem roots CARRY OVER (they are
session-scoped permissions, not root-relative); an entry equal to the new
root is dropped as redundant. Refuses while the session is in a draft —
a draft is a fork of the OLD root, so apply/abandon it first. Returns the
newly pinned trunk workspace (or the current one when `path` already IS
the root).
sourceraw docstring

workspace-create!clj

(workspace-create! db-info
                   {:keys [session-state-id label from required-capabilities]})

Create an isolated DRAFT using the strongest available backend and pin it to :session-state-id. The backend must provide the full draft capability set; core never silently falls back to a shared root.

The fork PARENT is chosen so apply! lands back where it forked from: pass :from <parent-workspace> to clone that workspace's :root and inherit its :repo-root (apply target); otherwise the parent is the user's real cwd (trunk).

Create an isolated DRAFT using the strongest available backend and pin it
to `:session-state-id`. The backend must provide the full draft capability
set; core never silently falls back to a shared root.

The fork PARENT is chosen so `apply!` lands back where it forked from:
pass `:from <parent-workspace>` to clone that workspace's `:root` and
inherit its `:repo-root` (apply target); otherwise the parent is the
user's real cwd (trunk).
sourceraw docstring

workspace-create-dir!clj

(workspace-create-dir! parent name)

Create a single child directory name under existing directory parent. Returns the canonical path of the (possibly already-existing) child. Throws when parent is not a directory or name is not a single safe path segment. name may not contain a separator, be blank, or be ./...

Create a single child directory `name` under existing directory `parent`.
Returns the canonical path of the (possibly already-existing) child. Throws
when `parent` is not a directory or `name` is not a single safe path segment.
`name` may not contain a separator, be blank, or be `.`/`..`.
sourceraw docstring

workspace-create-trunk-at!clj

(workspace-create-trunk-at! db-info root)

Mint a TRUNK workspace rooted at root (an arbitrary directory), not pinned to any session. Lets a channel open a session under a directory OTHER than the one vis was launched from — a tab in another project. Returns the workspace row (with :id) to pass as :workspace-id when creating the session.

Mint a TRUNK workspace rooted at `root` (an arbitrary directory), not
pinned to any session. Lets a channel open a session under a directory
OTHER than the one vis was launched from — a tab in another project.
Returns the workspace row (with `:id`) to pass as `:workspace-id` when
creating the session.
sourceraw docstring

workspace-cwdclj

(workspace-cwd)

Resolve the current workspace cwd. In production the channel wrapper binds *workspace-root* per turn, so the process-cwd fallback only fires from REPL / test / one-off CLI paths that have no session context.

Resolve the current workspace cwd. In production the channel
wrapper binds `*workspace-root*` per turn, so the process-cwd
fallback only fires from REPL / test / one-off CLI paths that have
no session context.
sourceraw docstring

workspace-deregister-backend!clj

(workspace-deregister-backend! backend-id)
source

workspace-display-labelclj

(workspace-display-label workspace)
(workspace-display-label db-info workspace session)

Human-facing label for workspace. Order: explicit :label → pinned session title → clone name (:branch) → id prefix.

Human-facing label for `workspace`. Order: explicit `:label` →
pinned session title → clone name (`:branch`) → id prefix.
sourceraw docstring

workspace-ensure-workspace!clj

(workspace-ensure-workspace! db-info {:keys [session-state-id]})

Find-or-create the session's workspace. The DEFAULT is TRUNK — the user's real cwd (no clone); the agent works directly in the repo until /draft new. Resume returns whatever the session was pinned to (trunk, or an open draft). Idempotent per session-state.

Find-or-create the session's workspace. The DEFAULT is TRUNK — the
user's real cwd (no clone); the agent works directly in the repo
until `/draft new`. Resume returns whatever the session was pinned to
(trunk, or an open draft). Idempotent per session-state.
sourceraw docstring

workspace-filesystem-rootsclj

(workspace-filesystem-roots ws)

Extra filesystem roots configured for ws, normalized to [{:trunk :clone :fork-ms :backend}].

Extra filesystem roots configured for `ws`, normalized to
`[{:trunk :clone :fork-ms :backend}]`.
sourceraw docstring

workspace-focus!clj

(workspace-focus! db-info workspace-id)

Stamp last_focused_at_ms and upsert the per-repo repo_focus pointer. Returns the updated workspace record.

Stamp `last_focused_at_ms` and upsert the per-repo `repo_focus`
pointer. Returns the updated workspace record.
sourceraw docstring

workspace-for-sessionclj

(workspace-for-session db-info session-state-id)

Workspace pinned to session-state-id, or nil.

Workspace pinned to `session-state-id`, or nil.
sourceraw docstring

workspace-getclj

(workspace-get db-info workspace-id)

Return the workspace with workspace-id, or nil.

Return the workspace with `workspace-id`, or nil.
sourceraw docstring

workspace-isolation-supported?clj

(workspace-isolation-supported?)
(workspace-isolation-supported? root)

True when the current root can create full draft workspaces.

True when the current root can create full draft workspaces.
sourceraw docstring

workspace-last-focusedclj

(workspace-last-focused db-info repo-id)

Workspace id from repo_focus for repo-id, or nil.

Workspace id from `repo_focus` for `repo-id`, or nil.
sourceraw docstring

workspace-list-activeclj

(workspace-list-active db-info repo-id)

Active workspaces for repo-id, newest first.

Active workspaces for `repo-id`, newest first.
sourceraw docstring

workspace-list-active-with-sessionsclj

(workspace-list-active-with-sessions db-info repo-id)

Like list-active but each entry is the {:workspace :session-state} pair, sorted by last_focused_at_ms DESC NULLS LAST, then created_at DESC.

Like `list-active` but each entry is the `{:workspace :session-state}`
pair, sorted by `last_focused_at_ms` DESC NULLS LAST, then
`created_at` DESC.
sourceraw docstring

workspace-list-finishedclj

(workspace-list-finished db-info repo-id)

Discarded workspaces for repo-id, newest first.

Discarded workspaces for `repo-id`, newest first.
sourceraw docstring

workspace-normalize-rootclj

(workspace-normalize-root root)

Canonicalize a workspace root string/File. Blank/nil → nil.

Canonicalize a workspace root string/File. Blank/nil → nil.
sourceraw docstring

workspace-register-backend!clj

(workspace-register-backend! backend)

Register a workspace backend. Idempotent by backend id.

Register a workspace backend. Idempotent by backend id.
sourceraw docstring

workspace-register-hook!clj

(workspace-register-hook! hook-id hook-fn)

Register hook-fn for hook-id ∈ {:on-spawn :on-apply :on-discard}. Synchronous; exceptions swallowed.

Register `hook-fn` for `hook-id` ∈ {:on-spawn :on-apply :on-discard}.
Synchronous; exceptions swallowed.
sourceraw docstring

workspace-registered-backendsclj

(workspace-registered-backends)

Registered workspace backends ordered by descending priority.

Registered workspace backends ordered by descending priority.
sourceraw docstring

workspace-remove-filesystem-root!clj

(workspace-remove-filesystem-root! db-info workspace-id path)

Remove path from the workspace's extra filesystem roots and release any backend-owned isolated root.

Remove `path` from the workspace's extra filesystem roots and release any
backend-owned isolated root.
sourceraw docstring

workspace-rootclj

(workspace-root env-or-root)

Extract a canonical :workspace/root from an env map or raw root value.

Extract a canonical :workspace/root from an env map or raw root value.
sourceraw docstring

workspace-set-label!clj

(workspace-set-label! db-info {:keys [workspace-id label]})

Set the workspace's human-friendly :label. Empty/nil clears it.

Set the workspace's human-friendly `:label`. Empty/nil clears it.
sourceraw docstring

workspace-statusclj

(workspace-status db-info workspace-id)

Enrich a workspace record with live status. Stamps :workspace/root, :workspace/sandbox?, :workspace/exists?, :workspace/changed (count of since-fork edits) and :workspace/dirty?. No git.

Enrich a workspace record with live status. Stamps
`:workspace/root`, `:workspace/sandbox?`, `:workspace/exists?`, `:workspace/changed`
(count of since-fork edits) and `:workspace/dirty?`. No git.
sourceraw docstring

workspace-subdirsclj

(workspace-subdirs path)

Child directory names (non-hidden) of path, case-insensitively sorted. Empty vec when path is blank, not a directory, or unreadable.

Child directory names (non-hidden) of `path`, case-insensitively sorted.
Empty vec when `path` is blank, not a directory, or unreadable.
sourceraw docstring

workspace-supports?clj

(workspace-supports? source-root required)
(workspace-supports? source-root store-root required)

True when some backend can provide required for the given roots.

True when some backend can provide `required` for the given roots.
sourceraw docstring

workspace-trunk-infoclj

(workspace-trunk-info)
(workspace-trunk-info root)

The user's real cwd (trunk). No git read; just the launch dir.

The user's real cwd (trunk). No git read; just the launch dir.
sourceraw docstring

workspace-with-sessionclj

(workspace-with-session db-info workspace-id)

Hydrate workspace-id with its pinned session_state. Returns {:workspace <ws> :session-state <ss>}.

Hydrate `workspace-id` with its pinned `session_state`. Returns
`{:workspace <ws> :session-state <ss>}`.
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