TUI provider management dialogs - model picker, model manager, provider router. Config I/O and data helpers live in tui/config.clj.
The channel-neutral brain — status probing, limits, live model
catalogs, presets, persistence shapes — lives in
com.blockether.vis.internal.providers (exposed through vis.core)
and can be SHARED across channels. This namespace owns only the
lanterna interaction layer.
ALL provider OAuth is driven ENTIRELY through the gateway —
Anthropic + Codex over browser/PKCE, GitHub Copilot over device code —
via /v1/providers/:id/auth/{start,complete,poll,cancel} and /logout.
The TUI therefore needs NO provider extension on its own classpath, holds
no credential secret at any moment, and behaves identically when attached
to a gateway on another machine.
TUI provider management dialogs - model picker, model manager, provider router.
Config I/O and data helpers live in tui/config.clj.
The channel-neutral brain — status probing, limits, live model
catalogs, presets, persistence shapes — lives in
`com.blockether.vis.internal.providers` (exposed through `vis.core`)
and can be SHARED across channels. This namespace owns only the
lanterna interaction layer.
ALL provider OAuth is driven ENTIRELY through the gateway —
Anthropic + Codex over browser/PKCE, GitHub Copilot over device code —
via `/v1/providers/:id/auth/{start,complete,poll,cancel}` and `/logout`.
The TUI therefore needs NO provider extension on its own classpath, holds
no credential secret at any moment, and behaves identically when attached
to a gateway on another machine.(api-key-transient-spec)PURE: the magit transient an API-key sign-in runs. k reads the key INLINE on
the dialog's hint row (echoed as *, and the armed value renders as dots, so
the credential never lands on screen), a submits it to the gateway, Esc
cancels. No cursor to move, no full-screen prompt: the provider's own guidance
stays visible above the popup.
PURE: the magit transient an API-key sign-in runs. `k` reads the key INLINE on the dialog's hint row (echoed as `*`, and the armed value renders as dots, so the credential never lands on screen), `a` submits it to the gateway, Esc cancels. No cursor to move, no full-screen prompt: the provider's own guidance stays visible above the popup.
(auth-provider-items)One row per auth-capable provider, labelled with its GATEWAY auth verdict.
The N status probes fan out onto worker futures and are joined once, so opening the dialog costs one round trip of latency instead of N serialized blocking gateway calls on the UI thread.
One row per auth-capable provider, labelled with its GATEWAY auth verdict. The N status probes fan out onto worker futures and are joined once, so opening the dialog costs one round trip of latency instead of N serialized blocking gateway calls on the UI thread.
(authenticate-provider! screen provider)(authenticate-provider! screen provider force?)The ONE auth entry point for every channel action (auth dialog, provider
manager, add-provider). EVERY kind goes through the gateway: device for
GitHub Copilot, PKCE for Codex/Anthropic, api-key for everything else.
No provider credential is ever exchanged or written in the TUI process.
The ONE auth entry point for every channel action (auth dialog, provider manager, add-provider). EVERY kind goes through the gateway: device for GitHub Copilot, PKCE for Codex/Anthropic, `api-key` for everything else. No provider credential is ever exchanged or written in the TUI process.
(logout-provider! screen provider)Confirm, then log provider out through the gateway. The provider STAYS in the
config — only its credential is dropped. Returns true when the logout ran.
Confirm, then log `provider` out through the gateway. The provider STAYS in the config — only its credential is dropped. Returns true when the logout ran.
(model-transient-page-size rows)PURE: how many models one transient page holds inside rows usable body rows.
Reserves the popup's own chrome — the leading blank, the Models header and
the Commands group carrying paging plus Show every model — and never asks
for more single-key bindings than exist.
PURE: how many models one transient page holds inside `rows` usable body rows. Reserves the popup's own chrome — the leading blank, the `Models` header and the `Commands` group carrying paging plus `Show every model` — and never asks for more single-key bindings than exist.
(model-transient-spec entries page marks)(model-transient-spec entries page marks page-size)PURE: the magit transient spec for the model picker. entries are
build-model-list rows, and each real model becomes a COMMAND bound to one
letter — a model is chosen with a single keystroke exactly like d sets the
default, never with a cursor. Models past one page are reached with magit's
n / p, and the :show-all sentinel becomes *. marks is
{:default id :fallback id} for the models this provider already holds, so
the tagged pair stays findable without reading the cards.
PURE: the magit transient spec for the model picker. `entries` are
`build-model-list` rows, and each real model becomes a COMMAND bound to one
letter — a model is chosen with a single keystroke exactly like `d` sets the
default, never with a cursor. Models past one page are reached with magit's
`n` / `p`, and the `:show-all` sentinel becomes `*`. `marks` is
`{:default id :fallback id}` for the models this provider already holds, so
the tagged pair stays findable without reading the cards.(provider-action-items provider)(provider-action-items provider status)(provider-action-items provider status is-fallback)(provider-action-items provider status is-fallback is-default)Actions for one provider row.
is-fallback (the row already carries the FALLBACK tag) is what adds
:clear-fallback; is-default (the row holds the PRIMARY tag) is what
REMOVES :fallback. The daemon refuses a fallback naming the primary's own
provider, so offering that action on the primary's card is a guaranteed
rejection dialog — the web settings panel disables the same button for the
same reason. Pass both values to the painter and the key handler or the two
menus disagree.
Actions for one provider row. `is-fallback` (the row already carries the FALLBACK tag) is what adds `:clear-fallback`; `is-default` (the row holds the PRIMARY tag) is what REMOVES `:fallback`. The daemon refuses a fallback naming the primary's own provider, so offering that action on the primary's card is a guaranteed rejection dialog — the web settings panel disables the same button for the same reason. Pass both values to the painter and the key handler or the two menus disagree.
(provider-transient! screen g region provider-id)Run ONE provider's magit transient inside the CALLER's frame — the same
commands show-provider-dialog! offers on Enter, reachable straight from a
Settings row so a provider needs no dialog of its own.
The fleet, the default tag and the fallback tag are re-read from the LIVE config on every call, so the popup reasons about what the daemon persisted and not about a snapshot the caller carried in. Returns true when something changed and the caller should reload its inventory.
Run ONE provider's magit transient inside the CALLER's frame — the same commands `show-provider-dialog!` offers on Enter, reachable straight from a Settings row so a provider needs no dialog of its own. The fleet, the default tag and the fallback tag are re-read from the LIVE config on every call, so the popup reasons about what the daemon persisted and not about a snapshot the caller carried in. Returns true when something changed and the caller should reload its inventory.
(provider-transient-spec actions)PURE: the magit transient spec for ONE provider row's actions (whatever
provider-action-items offered). Every action keeps the SINGLE key it already
advertised, so the popup is driven by direct keystrokes — d, f, a — with
no cursor at all, and the commands are grouped the way magit groups a popup:
routing first, then the account verbs. A group with no surviving action is
dropped, so a provider that cannot authenticate never shows an empty heading.
PURE: the magit transient spec for ONE provider row's `actions` (whatever `provider-action-items` offered). Every action keeps the SINGLE key it already advertised, so the popup is driven by direct keystrokes — `d`, `f`, `a` — with no cursor at all, and the commands are grouped the way magit groups a popup: routing first, then the account verbs. A group with no surviving action is dropped, so a provider that cannot authenticate never shows an empty heading.
(show-provider-dialog! screen)(show-provider-dialog! screen current-config)Provider manager dialog. Esc saves and closes. Provider order has no routing semantics; choose exactly one default provider/model pair.
A provider's OWN commands no longer live here: provider-transient! runs them
as a magit band inside whatever frame asks, which is how Settings reaches
them.
Provider manager dialog. Esc saves and closes. Provider order has no routing semantics; choose exactly one default provider/model pair. A provider's OWN commands no longer live here: `provider-transient!` runs them as a magit band inside whatever frame asks, which is how Settings reaches them.
(show-provider-status! screen provider)(show-provider-status! screen provider status limits)Status + limits as the RICH canonical markdown form, painted through the IR walker — the same report the web renders as markdown. The fallback arity fetches diagnostics through the gateway, never through local provider OAuth.
Status + limits as the RICH canonical markdown form, painted through the IR walker — the same report the web renders as markdown. The fallback arity fetches diagnostics through the gateway, never through local provider OAuth.
(show-welcome! screen)First-run welcome screen. The single primary action (Enter) drops straight
into the provider picker; ? explains how the key is used; Esc quits.
Returns {:providers [cfg]} once a provider is added, or nil if the user
quits without connecting one.
First-run welcome screen. The single primary action (Enter) drops straight
into the provider picker; `?` explains how the key is used; Esc quits.
Returns `{:providers [cfg]}` once a provider is added, or nil if the user
quits without connecting one.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |