Liking cljdoc? Tell your friends :D

com.blockether.vis.internal.provider.service

Channel-neutral provider management service.

Everything a channel needs to render and mutate the provider fleet — status probing, account limits, live model catalogs, presets, and config persistence — WITHOUT any UI. Hoisted from the TUI extension (channel_tui/provider.clj) so any future surface manages the SAME fleet through the SAME primitives; the channels keep only their interaction layer (lanterna dialogs, ...).

Auth is classified, not implemented, here: auth-kind tells a channel whether a provider wants an API key, an interactive OAuth flow (owned by the provider extension + channel), or nothing (local). The registry's :provider/*-fn contract stays the single integration point for provider extensions, so a provider extension automatically works in every channel.

Channel-neutral provider management service.

Everything a channel needs to render and mutate the provider fleet
— status probing, account limits, live model catalogs, presets, and
config persistence — WITHOUT any UI. Hoisted from the TUI extension
(`channel_tui/provider.clj`) so any future surface manages the SAME
fleet through the SAME primitives; the channels keep only their
interaction layer (lanterna dialogs, ...).

Auth is classified, not implemented, here: `auth-kind` tells a
channel whether a provider wants an API key, an interactive OAuth
flow (owned by the provider extension + channel), or nothing
(local). The registry's `:provider/*-fn` contract stays the single
integration point for provider extensions, so a provider extension
automatically works in every channel.
raw docstring

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 its id exists).

Append a provider config to the persisted fleet (no-op when its id exists).
sourceraw docstring

auth-kindclj

(auth-kind pid)
(auth-kind pid provider)

How a provider authenticates: :command (an api_key_command mints the credential — never prompt), :oauth (the registered extension declares an interactive :provider/auth-fn), :managed (the extension owns configuration and exposes no interactive flow), :none (local, no credentials), or :api-key.

Ownership never overrides authentication: a managed provider with auth-fn is OAuth-capable while remaining automatically bound and absent from Add Provider. The 1-arity classifies by id alone and therefore can never see a command-minted provider; pass the configured provider map when that answer decides whether to prompt a human.

How a provider authenticates: `:command` (an `api_key_command` mints the
credential — never prompt), `:oauth` (the registered extension declares an
interactive `:provider/auth-fn`), `:managed` (the extension owns configuration
and exposes no interactive flow), `:none` (local, no credentials), or `:api-key`.

Ownership never overrides authentication: a managed provider with `auth-fn` is
OAuth-capable while remaining automatically bound and absent from Add Provider.
The 1-arity classifies by id alone and therefore can never see a command-minted
provider; pass the configured provider map when that answer decides whether to
prompt a human.
sourceraw docstring

auth-summaryclj

(auth-summary status decorated?)

The one human reading of a provider's authentication state: verified, rejected, usable; live check unavailable, or -- while nothing has proven the credential -- saved, not verified / not verified. A key that is only STORED is never reported as proven. decorated? appends the glyph the dialogs paint; the CLI passes false.

The one human reading of a provider's authentication state: `verified`,
`rejected`, `usable; live check unavailable`, or -- while nothing has proven
the credential -- `saved, not verified` / `not verified`. A key that is only
STORED is never reported as proven. `decorated?` appends the glyph the
dialogs paint; the CLI passes false.
sourceraw docstring

auth-verdictclj

(auth-verdict status)

The daemon-classified authentication state. Missing evidence is neutral, never inferred as success or rejection from credential presence alone.

The daemon-classified authentication state. Missing evidence is neutral, never
inferred as success or rejection from credential presence alone.
sourceraw docstring

authenticated-preset-providersclj

(authenticated-preset-providers)

Registered providers that BIND THEMSELVES — the credential lives OUTSIDE the persisted fleet, so the provider is usable with no Add provider step at all. Shaped as minimal picker rows ({:id … :models …} carrying the preset's default catalog models) and appended by picker-fleet.

Two ways in. A MANAGED provider (managed?) binds because its runtime issues the credential: there is nothing local to probe and nothing a human could add. Every other provider binds only when its OWN :provider/detect-fn (local, no network) finds one — an OAuth token file, a keychain entry.

A provider with neither, or with no default models, is skipped.

Registered providers that BIND THEMSELVES — the credential lives OUTSIDE the
persisted fleet, so the provider is usable with no `Add provider` step at all.
Shaped as minimal picker rows (`{:id … :models …}` carrying the preset's
default catalog models) and appended by [[picker-fleet]].

Two ways in. A MANAGED provider ([[managed?]]) binds because its runtime
issues the credential: there is nothing local to probe and nothing a human
could add. Every other provider binds only when its OWN `:provider/detect-fn`
(local, no network) finds one — an OAuth token file, a keychain entry.

A provider with neither, or with no default models, is skipped.
sourceraw docstring

available-presetsclj

(available-presets)

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

A MANAGED provider is never offered here: it carries no credential a human supplies and it binds itself, so an Add provider row for it could only ask for a key that every seam below must refuse.

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

A MANAGED provider is never offered here: it carries no credential a human
supplies and it binds itself, so an `Add provider` row for it could only ask
for a key that every seam below must refuse.
sourceraw docstring

clear-fallback-selection!clj

(clear-fallback-selection!)
(clear-fallback-selection! source)

Drop the fallback tag. The fleet keeps every provider; only the second root goes away, leaving svar's own priority order to decide what follows the primary.

Drop the fallback tag. The fleet keeps every provider; only the second root
goes away, leaving svar's own priority order to decide what follows the
primary.
sourceraw docstring

clear-provider-api-key!clj

(clear-provider-api-key! provider-id)
(clear-provider-api-key! provider-id source)

Forget provider-id's stored API key while KEEPING its config entry.

This is what "log out" means for a key-only provider: the credential goes, the provider stays configured with its models, base-url and tags, so signing back in is one key away. Returns true when a key was actually cleared.

Forget `provider-id`'s stored API key while KEEPING its config entry.

This is what "log out" means for a key-only provider: the credential goes, the
provider stays configured with its models, base-url and tags, so signing back in
is one key away. Returns true when a key was actually cleared.
sourceraw docstring

command-minted?clj

(command-minted? provider)

True when the credential is minted BY THE MACHINE: config carries an api_key_command, so the helper mints (and rotates) the token on every request and there is nothing for a human to type or paste.

True when the credential is minted BY THE MACHINE: config carries an
`api_key_command`, so the helper mints (and rotates) the token on every
request and there is nothing for a human to type or paste.
sourceraw docstring

configured-model-namesclj

(configured-model-names provider)

Model names a provider declares in config, in the exact order they are written in vis.yml. Never filtered by svar's catalog visibility rules - an explicitly configured model is a statement of intent, not a suggestion.

Model names a provider declares in config, in the exact order they are
written in vis.yml. Never filtered by svar's catalog visibility rules - an
explicitly configured model is a statement of intent, not a suggestion.
sourceraw docstring

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

configured-providers-cachedclj

(configured-providers-cached)

Frame/request-frequency read of configured-providers that never re-runs the full enumeration on a warm caller. The enumeration behind config/load-config parses four config files per call — ~200ms on machines with slow file IO — which stalled every TUI footer frame when it ran on the render thread (issue #29).

  • FRESH snapshot → returned as-is (pure atom read).
  • STALE snapshot → returned immediately; a single-flight background refresh replaces it off-thread.
  • COLD (first read / just invalidated) → enumerates synchronously ONCE, so callers always get a real fleet, never a nil-because-cold.
Frame/request-frequency read of `configured-providers` that never re-runs
the full enumeration on a warm caller. The enumeration behind
`config/load-config` parses four config files per call — ~200ms on
machines with slow file IO — which stalled every TUI footer frame when it
ran on the render thread (issue #29).

- FRESH snapshot → returned as-is (pure atom read).
- STALE snapshot → returned immediately; a single-flight background
  refresh replaces it off-thread.
- COLD (first read / just invalidated) → enumerates synchronously ONCE, so
  callers always get a real fleet, never a nil-because-cold.
sourceraw docstring

dated-variant?clj

(dated-variant? id)
source

default-model-configsclj

(default-model-configs preset)

Preset :default-models as persisted model maps. A bare-string entry becomes {:name str}; a MAP entry is carried through verbatim (name normalized) so a provider can declare :context / :output-limit / … for a model svar's pinned catalog doesn't know yet — no svar release, no enrich hook. ->svar-model whitelists which of those keys svar honors, so extra keys are harmless.

Preset `:default-models` as persisted model maps. A bare-string entry
becomes `{:name str}`; a MAP entry is carried through verbatim (name
normalized) so a provider can declare `:context` / `:output-limit` / … for
a model svar's pinned catalog doesn't know yet — no svar release, no
enrich hook. `->svar-model` whitelists which of those keys svar honors, so
extra keys are harmless.
sourceraw docstring

default-model-namesclj

(default-model-names provider)

Union of model names already on the provider map plus the preset / provider :default-models, deduped. Config order leads: the models a user wrote in vis.yml come first and model-options keeps them there.

Union of model names already on the provider map plus the preset /
provider `:default-models`, deduped. Config order leads: the models a
user wrote in vis.yml come first and `model-options` keeps them there.
sourceraw docstring

default-selectionclj

(default-selection)
(default-selection fleet)

The valid PRIMARY provider/model pair for fleet, read against THIS machine's merged config. resolve-default-selection is the resolution itself.

The valid PRIMARY provider/model pair for `fleet`, read against THIS machine's
merged config. `resolve-default-selection` is the resolution itself.
sourceraw docstring

demote-unreachable-providersclj

(demote-unreachable-providers router)

Health-order a ROUTER (svar shape, {:providers [...]}) for one turn: LOCAL providers that fail the liveness probe sink to the END of the fleet — kept as last resort, never silently dropped — so a dead local endpoint can't catch a turn (or an svar fallback) that a healthy provider should have taken. Probes run ONLY when local providers are configured (≤ ~2.5s each; zero cost otherwise). Returns {:router r :demoted [provider-ids]}. NEVER throws — routing must survive a broken probe (falls back to the router as-is), so callers need no defensive wrapping.

Health-order a ROUTER (svar shape, `{:providers [...]}`) for one
turn: LOCAL providers that fail the liveness probe sink to the END
of the fleet — kept as last resort, never silently dropped — so a
dead local endpoint can't catch a turn (or an svar fallback) that a
healthy provider should have taken. Probes run ONLY when local
providers are configured (≤ ~2.5s each; zero cost otherwise).
Returns `{:router r :demoted [provider-ids]}`. NEVER throws —
routing must survive a broken probe (falls back to the router
as-is), so callers need no defensive wrapping.
sourceraw docstring

ensure-base-urlclj

(ensure-base-url provider)
source

fallback-selectionclj

(fallback-selection)
(fallback-selection fleet)
(fallback-selection fleet primary)

Return the valid FALLBACK provider/model pair for fleet, or nil.

The fallback is the pair the router drops to when the primary provider cannot serve the turn, so — unlike the primary — it is never implicit: an unset, unknown, or same-provider-as-primary tag resolves to nil rather than inventing a second choice nobody asked for. Only the MODEL is lenient (an unknown model name falls back to the provider's first), mirroring default-selection.

Return the valid FALLBACK provider/model pair for `fleet`, or nil.

The fallback is the pair the router drops to when the primary provider cannot
serve the turn, so — unlike the primary — it is never implicit: an unset,
unknown, or same-provider-as-primary tag resolves to nil rather than inventing
a second choice nobody asked for. Only the MODEL is lenient (an unknown model
name falls back to the provider's first), mirroring `default-selection`.
sourceraw docstring

fetch-modelsclj

(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

format-limit-rowclj

(format-limit-row {:keys [label scope kind is-unlimited used limit remaining
                          note window]})
source

format-status-valueclj

(format-status-value v)

One provider-status VALUE as text: a keyword by name, a map or sequence flattened to k: v in key order, anything else str. Recursive, so a nested plan map renders inside its own row.

One provider-status VALUE as text: a keyword by name, a map or sequence
flattened to `k: v` in key order, anything else `str`. Recursive, so a nested
plan map renders inside its own row.
sourceraw docstring

github-copilot-account-typesclj

GitHub Copilot preset id -> device-flow account type.

GitHub Copilot preset id -> device-flow account type.
sourceraw docstring

initial-provider-limitsclj

(initial-provider-limits provider)

Placeholder limits report while the real fetch runs.

Placeholder limits report while the real fetch runs.
sourceraw docstring

initial-provider-statusclj

(initial-provider-status provider)

Placeholder status while a real probe runs in the background. A credential gap is decided synchronously — it is a pure read of the config already in hand, plus at most one cached credential-command probe — so the card never flashes an authenticated verdict it is about to retract.

Placeholder status while a real probe runs in the background. A credential gap
is decided synchronously — it is a pure read of the config already in hand,
plus at most one cached credential-command probe — so the card never flashes
an authenticated verdict it is about to retract.
sourceraw docstring

invalidate-configured-providers!clj

(invalidate-configured-providers!)

Drop the fleet snapshot so the next configured-providers-cached read re-enumerates. Called by every same-process fleet mutation — which is what lets the TTL stay long (issue #29 follow-up: invalidate on change instead of polling).

Drop the fleet snapshot so the next `configured-providers-cached` read
re-enumerates. Called by every same-process fleet mutation — which is what
lets the TTL stay long (issue #29 follow-up: invalidate on change instead
of polling).
sourceraw docstring

limits-probe-timeout-msclj

Wall a provider's :provider/limits-fn gets before its report is declared late. /v1/router asks EVERY provider for one before the model picker can paint, so a single account endpoint that hangs used to hold the entire payload until the client's own 30s bound aborted it — and the model you were switching to never arrived.

Wall a provider's `:provider/limits-fn` gets before its report is declared
late. `/v1/router` asks EVERY provider for one before the model picker can
paint, so a single account endpoint that hangs used to hold the entire payload
until the client's own 30s bound aborted it — and the model you were switching
to never arrived.
sourceraw docstring

local-no-auth-provider-idsclj

Local OpenAI-compatible providers that need no credentials.

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

managed?clj

(managed? provider-id)

True when the extension that registered provider-id owns its binding and configuration. Managed providers bind as soon as their extension loads and stay out of Add Provider. Authentication is independent: :provider/auth-fn may still obtain a provider-owned credential on first use.

True when the extension that registered `provider-id` owns its binding and
configuration. Managed providers bind as soon as their extension loads and stay
out of Add Provider. Authentication is independent: `:provider/auth-fn` may still
obtain a provider-owned credential on first use.
sourceraw docstring

model-optionsclj

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

Selectable model ids for a provider: configured models first IN vis.yml ORDER, then live-fetched + preset defaults deduped and 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: configured models first IN vis.yml
ORDER, then live-fetched + preset defaults deduped and 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

oauth-provider-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

persisted-provider-configclj

(persisted-provider-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

picker-fleetclj

(picker-fleet)

The provider fleet a model picker should render: the persisted configured-providers first, then authenticated-preset-providers (authenticated-but-unconfigured OAuth providers whose creds live outside config) appended. This is what channel model pickers enumerate so authenticated providers are selectable even before they're saved into the fleet.

Failure-isolated by construction: the base fleet reads through the never-nil configured-providers-cached (no per-open 4-file parse, no render-thread stall), and the authenticated-preset enumeration degrades to empty on any error. A transient hiccup therefore drops the OAuth extras at worst — it NEVER throws and NEVER blanks the picker of already-configured providers.

The provider fleet a model picker should render: the persisted
`configured-providers` first, then `authenticated-preset-providers`
(authenticated-but-unconfigured OAuth providers whose creds live outside
config) appended. This is what channel model pickers enumerate so
authenticated providers are selectable even before they're saved into the
fleet.

Failure-isolated by construction: the base fleet reads through the
never-nil `configured-providers-cached` (no per-open 4-file parse, no
render-thread stall), and the authenticated-preset enumeration degrades to
empty on any error. A transient hiccup therefore drops the OAuth extras at
worst — it NEVER throws and NEVER blanks the picker of already-configured
providers.
sourceraw docstring

probe-local-reachableclj

(probe-local-reachable provider)

Probe a local OpenAI-compatible provider (Ollama / LM Studio) by GETting its <base-url>/models endpoint with a short timeout. Reachable → {:is-authenticated true …}; refused / timeout / other → {:is-authenticated false :error "<human hint>"} so the channel can SAY why the dot is red. Blocking ≤ ~2.5s — call off the render path.

Probe a local OpenAI-compatible provider (Ollama / LM Studio) by
GETting its `<base-url>/models` endpoint with a short timeout.
Reachable → `{:is-authenticated true …}`; refused / timeout / other →
`{:is-authenticated false :error "<human hint>"}` so the channel can
SAY why the dot is red. Blocking ≤ ~2.5s — call off the render path.
sourceraw docstring

probe-timeout-msclj

Wall a provider lifecycle callback (:provider/status-fn, :provider/detect-fn) gets before it is declared wedged. These callbacks are trusted extension code — often Python — and a hung one used to hold the gateway request, and the card behind it, for the client's whole 30s budget.

Wall a provider lifecycle callback (`:provider/status-fn`,
`:provider/detect-fn`) gets before it is declared wedged. These callbacks are
trusted extension code — often Python — and a hung one used to hold the
gateway request, and the card behind it, for the client's whole 30s budget.
sourceraw docstring

provider-config-with-modelsclj

(provider-config-with-models preset models)

Persistable provider config carrying the provider's complete catalog.

Persistable provider config carrying the provider's complete catalog.
sourceraw docstring

provider-limits-safeclj

(provider-limits-safe provider)

Normalized limits report for a provider id; an error report instead of a throw, and never slower than limits-probe-timeout-ms.

A late probe is deliberately NOT cancelled: provider-limits memoizes the report it is still computing, so abandoning this read leaves the next one warm.

Normalized limits report for a provider id; an error report instead
of a throw, and never slower than `limits-probe-timeout-ms`.

A late probe is deliberately NOT cancelled: `provider-limits` memoizes the
report it is still computing, so abandoning this read leaves the next one warm.
sourceraw docstring

provider-reachable?clj

(provider-reachable? provider)

Cheap ROUTING-time liveness verdict: local providers (Ollama / LM Studio) get the real HTTP probe; remote providers are assumed reachable — their auth/network failures surface as call errors svar already fails over on, and a per-turn network check against every remote backend would tax every turn.

Cheap ROUTING-time liveness verdict: local providers (Ollama /
LM Studio) get the real HTTP probe; remote providers are assumed
reachable — their auth/network failures surface as call errors svar
already fails over on, and a per-turn network check against every
remote backend would tax every turn.
sourceraw docstring

provider-statusclj

(provider-status provider)

Auth/liveness status for a CONFIGURED provider map, with one explicit :auth-state every channel paints:

  • :verified — a live provider check accepted the credential,
  • :rejected — the credential/config was explicitly refused,
  • :degraded — the credential remains usable but its live check failed,
  • :unverified — a credential exists but no live check can prove it (or no credential exists yet).

:is-authenticated remains the independent usability bit: a degraded or unverified entry can still route only when it is true; rejection forces it false. Never throws.

Auth/liveness status for a CONFIGURED provider map, with one explicit
`:auth-state` every channel paints:

- `:verified` — a live provider check accepted the credential,
- `:rejected` — the credential/config was explicitly refused,
- `:degraded` — the credential remains usable but its live check failed,
- `:unverified` — a credential exists but no live check can prove it (or
  no credential exists yet).

`:is-authenticated` remains the independent usability bit: a degraded or
unverified entry can still route only when it is true; rejection forces it false.
Never throws.
sourceraw docstring

rebuild-shared-router!clj

(rebuild-shared-router!)

Drop the configured-provider cache, then fire the registered router-rebuild hook best-effort so the shared router (and every cached session env that snapshotted it) rebuilds from current config. No-op before loop registers (early boot) or when the router was never built — reload-router! guards the latter on router-initialized?.

PUBLIC because AUTH needs it too: a provider whose credential cannot be resolved is skipped at router build, so signing in must rebuild or the daemon keeps routing as though that provider did not exist.

Drop the configured-provider cache, then fire the registered router-rebuild
hook best-effort so the shared router (and every cached session env that
snapshotted it) rebuilds from current config. No-op before `loop` registers
(early boot) or when the router was never built — `reload-router!` guards the
latter on `router-initialized?`.

PUBLIC because AUTH needs it too: a provider whose credential cannot be resolved
is skipped at router build, so signing in must rebuild or the daemon keeps
routing as though that provider did not exist.
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. Invalidates the fleet snapshot. Returns true when config changed. Extension-managed providers are rejected before logout or any config mutation with :type :provider/managed.

Remove a provider from the persisted fleet AND run the registered
extension's logout when present. Invalidates the fleet snapshot.
Returns true when config changed. Extension-managed providers are rejected
before logout or any config mutation with `:type :provider/managed`.
sourceraw docstring

reprioritize-providersclj

(reprioritize-providers provider-entries)

Renumber :priority from vector position; returns a vector.

svar bakes :priority at make-router time from the DECLARED index, and every candidate sort reads that NUMBER rather than vector order (see svar…router/candidate-sort-key). Reordering a router's :providers vector alone therefore promotes a provider in NAME only: the health gate below, a session pin and a coordinator's models preference each looked applied while svar kept routing to the original head. Every Vis reorder ends here.

Renumber `:priority` from vector position; returns a vector.

svar bakes `:priority` at `make-router` time from the DECLARED index, and every
candidate sort reads that NUMBER rather than vector order (see
`svar…router/candidate-sort-key`). Reordering a router's `:providers` vector
alone therefore promotes a provider in NAME only: the health gate below, a
session pin and a coordinator's `models` preference each looked applied while
svar kept routing to the original head. Every Vis reorder ends here.
sourceraw docstring

resolve-default-selectionclj

(resolve-default-selection cfg fleet)

PURE: the valid PRIMARY provider/model pair cfg's tags name within fleet. Explicit config wins; an untagged config falls back to the first provider and its first model, so a fleet always HAS a primary root while it has a provider.

Pure because every surface must resolve the tag the way the router does — channels hold the config they just read, and a channel that re-read global state here would answer for a different machine's config in a test and for a stale one in a race.

PURE: the valid PRIMARY provider/model pair `cfg`'s tags name within `fleet`.
Explicit config wins; an untagged config falls back to the first provider and
its first model, so a fleet always HAS a primary root while it has a provider.

Pure because every surface must resolve the tag the way the router does —
channels hold the config they just read, and a channel that re-read global
state here would answer for a different machine's config in a test and for a
stale one in a race.
sourceraw docstring

router-rebuild-hook-valclj

(router-rebuild-hook-val)

Current registered router-rebuild hook fn (or nil) — inspection/test accessor.

Current registered router-rebuild hook fn (or nil) — inspection/test accessor.
sourceraw docstring

safe-provider-statusclj

(safe-provider-status provider)

Status of a REGISTERED provider descriptor via its :provider/status-fn (falling back to :provider/detect-fn). Never throws, and never runs longer than probe-timeout-ms: a callback that is still going by then answers {:is-authenticated false :error "…timed out…"} — an honest verdict the surface can paint — instead of parking the thread that asked.

Status of a REGISTERED provider descriptor via its `:provider/status-fn`
(falling back to `:provider/detect-fn`). Never throws, and never runs longer
than `probe-timeout-ms`: a callback that is still going by then answers
`{:is-authenticated false :error "…timed out…"}` — an honest verdict the
surface can paint — instead of parking the thread that asked.
sourceraw docstring

save-default-selection!clj

(save-default-selection! provider-id model)
(save-default-selection! provider-id model source)

Persist exactly one PRIMARY provider/model pair — the router root every turn starts on. A fallback tag naming the same provider is dropped, so the two tags always name two providers.

Persist exactly one PRIMARY provider/model pair — the router root every turn
starts on. A fallback tag naming the same provider is dropped, so the two tags
always name two providers.
sourceraw docstring

save-fallback-selection!clj

(save-fallback-selection! provider-id model)
(save-fallback-selection! provider-id model source)

Persist exactly one FALLBACK provider/model pair — the router's SECOND root, used when the primary provider cannot serve the turn. Throws when it names the primary's provider, an unknown provider, or a model that provider does not expose.

Persist exactly one FALLBACK provider/model pair — the router's SECOND root,
used when the primary provider cannot serve the turn. Throws when it names the
primary's provider, an unknown provider, or a model that provider does not
expose.
sourceraw docstring

save-provider-api-key!clj

(save-provider-api-key! provider-id api-key)
(save-provider-api-key! provider-id api-key source)

Persist api-key for provider-id in THIS process' config — the headless twin of a channel's API-key dialog, so a phone (or a TUI attached to a remote gateway) never writes provider credentials on the wrong machine. Adds the provider from its preset when the fleet does not carry it yet.

Persist `api-key` for `provider-id` in THIS process' config — the headless
twin of a channel's API-key dialog, so a phone (or a TUI attached to a remote
gateway) never writes provider credentials on the wrong machine. Adds the
provider from its preset when the fleet does not carry it yet.
sourceraw docstring

save-providers!clj

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

Replace the provider vector in the global string-keyed config while preserving unrelated keys, then refresh runtime provider state.

Replace the provider vector in the global string-keyed config while preserving
unrelated keys, then refresh runtime provider state.
sourceraw docstring

set-router-rebuild-hook!clj

(set-router-rebuild-hook! f)

Register the function loop calls to rebuild the shared router from current config and reseed every cached session env. Idempotent; latest wins; nil clears.

Register the function `loop` calls to rebuild the shared router from current
config and reseed every cached session env. Idempotent; latest wins; nil clears.
sourceraw docstring

status-entry-labelclj

(status-entry-label k)

Human label for one provider-status key — the SAME spelling wherever a status map is painted (CLI table, dialog, markdown card), so one map cannot read three ways.

Human label for one provider-status key — the SAME spelling wherever a status
map is painted (CLI table, dialog, markdown card), so one map cannot read three
ways.
sourceraw docstring

status-mdclj

(status-md 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 and the TUI through its transient Markdown layout 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 and the TUI through its transient Markdown layout walker. The same
facts as [[status-text]], structured instead of flat.
sourceraw docstring

status-textclj

(status-text 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

summary-owned-status-keysclj

Status keys the Authenticated: line already speaks for. No channel repeats them as a detail row -- the CLI, the TUI dialog and the web view hide the same three.

Status keys the `Authenticated:` line already speaks for. No channel repeats
them as a detail row -- the CLI, the TUI dialog and the web view hide the
same three.
sourceraw docstring

update-config-provider!clj

(update-config-provider! provider-id f)
(update-config-provider! provider-id f source)

Apply f to one persisted provider and save the resulting fleet.

Apply `f` to one persisted provider and save the resulting fleet.
sourceraw docstring

update-providers!clj

(update-providers! f)
(update-providers! f source)

Read-modify-write the persisted provider fleet under the machine-store lock: f receives the CURRENT provider vector and answers the next one.

The read has to happen inside the lock. Reading the fleet, adding one provider and writing the whole vector back is a lost update the moment a second session (or the gateway's own toggle writer) does the same: both saw the same fleet and the last write silently dropped the other's provider.

Read-modify-write the persisted provider fleet under the machine-store lock:
`f` receives the CURRENT provider vector and answers the next one.

The read has to happen inside the lock. Reading the fleet, adding one provider
and writing the whole vector back is a lost update the moment a second session
(or the gateway's own toggle writer) does the same: both saw the same fleet and
the last write silently dropped the other's provider.
sourceraw docstring

url-hostclj

(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

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