Liking cljdoc? Tell your friends :D

com.blockether.vis.internal.provider-error

Single source of truth for provider-error presentation.

Both the turn engine's answer IR (provider-error-ir, rendered by the Web channel and the TUI's final-answer bubble) and the TUI's per-iteration trace error rows derive their wording and facts from THIS namespace, so a provider failure reads IDENTICALLY everywhere it surfaces — no more divergent PROVIDER_ERROR HTTP 400 vs the polished WHAT HAPPENED: banner.

err is the error map carried on a trace entry / ex-info: {:message .. :data {:status .. :body .. :request-id ..} ..}. Every helper tolerates the bare ex-info shape too (via ex-message).

Single source of truth for provider-error presentation.

Both the turn engine's answer IR (`provider-error-ir`, rendered by the
Web channel and the TUI's final-answer bubble) and the TUI's
per-iteration trace error rows derive their wording and facts from
THIS namespace, so a provider failure reads IDENTICALLY everywhere it
surfaces — no more divergent `PROVIDER_ERROR HTTP 400` vs the polished
`WHAT HAPPENED:` banner.

`err` is the error map carried on a trace entry / ex-info:
`{:message .. :data {:status .. :body .. :request-id ..} ..}`. Every
helper tolerates the bare ex-info shape too (via `ex-message`).
raw docstring

attempt->lineclj

(attempt->line {:keys [provider model status reason]})

One attempt → a compact provider/model: <status> <reason> line, e.g. anthropic/claude-opus-4: 429 rate-limit.

One attempt → a compact `provider/model: <status> <reason>` line, e.g.
`anthropic/claude-opus-4: 429 rate-limit`.
sourceraw docstring

auth-provider-error?clj

(auth-provider-error? status message wrapper-message)
source

auth-provider-next-stepclj

(auth-provider-next-step data)
source

generic-wrapper-message?clj

(generic-wrapper-message? message)

True when the svar wrapper message is just a status echo (e.g. Exceptional status code: 400) that adds nothing beyond the HTTP row.

True when the svar wrapper message is just a status echo (e.g.
`Exceptional status code: 400`) that adds nothing beyond the HTTP row.
sourceraw docstring

invalid-thinking-signature-message?clj

(invalid-thinking-signature-message? message)
source

parse-provider-bodyclj

(parse-provider-body body)
source

provider-body-messageclj

(provider-body-message body)
source

provider-error-attemptsclj

(provider-error-attempts err)

The per-provider failure records svar accumulates on an all-providers-exhausted error — [{:provider :model :status :reason :error} …], one per provider tried. Empty when svar didn't attach them (older svar / a non-routing failure).

The per-provider failure records svar accumulates on an `all-providers-exhausted`
error — `[{:provider :model :status :reason :error} …]`, one per provider tried.
Empty when svar didn't attach them (older svar / a non-routing failure).
sourceraw docstring

provider-error-attempts-summaryclj

(provider-error-attempts-summary err)

The attempts joined into ONE scannable line (a: 429 rate-limit · b: 401 auth), or nil when there are none. The at-a-glance 'why each provider bowed out'.

The attempts joined into ONE scannable line (`a: 429 rate-limit · b: 401 auth`),
or nil when there are none. The at-a-glance 'why each provider bowed out'.
sourceraw docstring

provider-error-explanationclj

(provider-error-explanation err)

The WHAT HAPPENED: prose line — the single canonical human sentence for this failure, shared by every surface. The actionable step lives in provider-error-next-step (a separate block), so this is JUST the diagnosis.

The `WHAT HAPPENED:` prose line — the single canonical human sentence for this
failure, shared by every surface. The actionable step lives in
`provider-error-next-step` (a separate block), so this is JUST the diagnosis.
sourceraw docstring

provider-error-factsclj

(provider-error-facts err)

Ordered [label value] rows of the bare facts (no prose). Same set the IR renders as a <ul> and the TUI renders as plain rows.

Ordered `[label value]` rows of the bare facts (no prose). Same set the
IR renders as a `<ul>` and the TUI renders as plain rows.
sourceraw docstring

provider-error-infoclj

(provider-error-info err)

Structured echo of the facts a chat surface (Telegram) can render compactly without parsing the IR back out.

Structured echo of the facts a chat surface (Telegram) can render
compactly without parsing the IR back out.
sourceraw docstring

provider-error-irclj

(provider-error-ir err)

Canonical answer-IR for a provider failure. Rendered verbatim by the Web channel and the TUI final-answer bubble; the TUI trace rows mirror its wording via the helpers above. Blocks in reading order: TITLE → what happened → the actionable NEXT STEP → the bare facts → (optional) raw provider body. The root attrs carry :vis/provider-error + the full :vis/provider-error-data so a surface can paint a styled CARD instead of walking the generic nodes.

The WHAT HAPPENED: / NEXT STEP: LABELS are split out of the prose and wrapped in [:strong], so a surface renders the label BOLD while the body sentence stays plain — instead of the whole line being one undifferentiated bold/plain span. The helpers still return the label-led prose string (used by the TUI trace + tests), so the split happens here at the IR boundary.

Canonical answer-IR for a provider failure. Rendered verbatim by the Web
channel and the TUI final-answer bubble; the TUI trace rows mirror its
wording via the helpers above. Blocks in reading order: TITLE → what happened
→ the actionable NEXT STEP → the bare facts → (optional) raw provider body.
The root attrs carry `:vis/provider-error` + the full `:vis/provider-error-data`
so a surface can paint a styled CARD instead of walking the generic nodes.

The `WHAT HAPPENED:` / `NEXT STEP:` LABELS are split out of the prose and
wrapped in `[:strong]`, so a surface renders the label BOLD while the body
sentence stays plain — instead of the whole line being one undifferentiated
bold/plain span. The helpers still return the label-led prose string (used by
the TUI trace + tests), so the split happens here at the IR boundary.
sourceraw docstring

provider-error-kindclj

(provider-error-kind err)
source

provider-error-next-stepclj

(provider-error-next-step err)

The actionable NEXT STEP: line — what the user should DO — by kind. Kept SEPARATE from the diagnosis so surfaces can make it prominent.

The actionable `NEXT STEP:` line — what the user should DO — by kind. Kept
SEPARATE from the diagnosis so surfaces can make it prominent.
sourceraw docstring

provider-error-raw-bodyclj

(provider-error-raw-body err)

Truncated raw upstream body — surfaced ONLY when no structured provider message could be extracted (HTML pages, bare 5xx). nil otherwise so the readable message isn't echoed twice.

Truncated raw upstream body — surfaced ONLY when no structured provider
message could be extracted (HTML pages, bare 5xx). nil otherwise so the
readable message isn't echoed twice.
sourceraw docstring

provider-error-titleclj

(provider-error-title err)

A SHORT headline for the failure, by kind — the card title on every surface.

A SHORT headline for the failure, by kind — the card title on every surface.
sourceraw docstring

provider-structured-messageclj

(provider-structured-message body)

Human-readable message a provider put in its error envelope, if any. Covers Anthropic/OpenAI {:error {:message}}, bare {:message}, and Codex/ChatGPT {:detail}. nil when the body has no message field (HTML page, bare 5xx) — the caller then surfaces the raw body instead.

Human-readable message a provider put in its error envelope, if any.
Covers Anthropic/OpenAI `{:error {:message}}`, bare `{:message}`, and
Codex/ChatGPT `{:detail}`. nil when the body has no message field (HTML
page, bare 5xx) — the caller then surfaces the raw body instead.
sourceraw docstring

split-error-labelclj

(split-error-label s)

Split a provider-error prose line into [label body] at the first :.

provider-error-explanation / provider-error-next-step always lead with an ALL-CAPS label (WHAT HAPPENED: / NEXT STEP:). This returns ["<LABEL>: " "<body sentence>"] so a surface can render the label distinctly (BOLD in the answer IR, SGR/BOLD sentinels in the TUI trace) while the body stays plain — ONE convention, shared by every surface, so the label/body split never diverges between the IR and the TUI recap.

Returns [nil s] (whole string as the body, no label) when s does not follow the ALL-CAPS: convention, so callers can treat the label as optional without a separate nil-check.

Split a provider-error prose line into `[label body]` at the first `: `.

`provider-error-explanation` / `provider-error-next-step` always lead with
an ALL-CAPS label (`WHAT HAPPENED: ` / `NEXT STEP: `). This returns
`["<LABEL>: " "<body sentence>"]` so a surface can render the label
distinctly (BOLD in the answer IR, SGR/BOLD sentinels in the TUI trace)
while the body stays plain — ONE convention, shared by every surface, so
the label/body split never diverges between the IR and the TUI recap.

Returns `[nil s]` (whole string as the body, no label) when `s` does not
follow the `ALL-CAPS:` convention, so callers can treat the label as
optional without a separate nil-check.
sourceraw docstring

transport-throwable?clj

(transport-throwable? t)

True when Throwable t is a CONNECTION/transport failure — the SAME classification transport-error? makes from a parsed provider error, but taken straight off a Throwable so the RETRY gate and the human message agree.

Walks the whole cause chain for the message text. Idempotent by definition: a transport failure means the request never reached the model (the socket closed with no bytes, was reset/refused/timed out, DNS/TLS died), so it is ALWAYS safe to retry — regardless of whether a response STREAM had started (a pre-response failure carries no :stream?, yet is the safest retry of all). A real REJECTION carries an HTTP status, so transport-error?'s nil status guard keeps 4xx/5xx out of this path.

True when Throwable `t` is a CONNECTION/transport failure — the SAME
classification `transport-error?` makes from a parsed provider error, but
taken straight off a Throwable so the RETRY gate and the human message agree.

Walks the whole cause chain for the message text. Idempotent by definition:
a transport failure means the request never reached the model (the socket
closed with no bytes, was reset/refused/timed out, DNS/TLS died), so it is
ALWAYS safe to retry — regardless of whether a response STREAM had started
(a pre-response failure carries no `:stream?`, yet is the safest retry of
all). A real REJECTION carries an HTTP status, so `transport-error?`'s
`nil status` guard keeps 4xx/5xx out of this path.
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