pub struct Provider {Show 15 fields
pub name: String,
pub base_url: String,
pub exec: Option<String>,
pub transport: Option<TransportSpec>,
pub protocol: ProtocolId,
pub auth: AuthId,
pub api_header: Option<HeaderSpec>,
pub beta_headers: Vec<(String, String)>,
pub generation_query: Vec<(String, String)>,
pub model_aliases: BTreeMap<String, String>,
pub context_windows: BTreeMap<String, u32>,
pub unsupported_body_keys: Vec<String>,
pub models: Option<ModelsOverride>,
pub oauth: Option<OAuthConfig>,
pub ambient: Option<AmbientSpec>,
}Expand description
A resolved provider row (arch §4.2). Pure data: name is a table key never
matched on in the pipeline; protocol/auth are registry keys; model_aliases
drives the computed alias→wire-id lookup. Sparse user/file rows fold onto the
embedded defaults before a complete Provider is resolved (config §3.2).
Fields§
§name: String§base_url: StringThe HTTP host, or "" on an exec-transport row (claude-code spec §7.1):
exec substitutes for it, and the exec transport never reads a URL — the
empty-set path, not a special case.
exec: Option<String>The subprocess program for an exec-transport dialect (claude-code spec §7.1):
a name resolved on PATH or an absolute path, carried onto
ProviderCtx.exec. Unread on HTTP-dialect rows (like ambient); a
claude_code row without it fails at encode with a Config error.
transport: Option<TransportSpec>The operator-selected transport delegate (transport spec §4.2): Some routes
EVERY request this row makes — generation, --list-models, --count-tokens,
--raw, and the OAuth refresh — through the operator’s program instead of the
built-in ureq/rustls stack, so the operator owns the HTTP/TLS wire identity.
Mutually exclusive with exec (that field already means “the child is the
provider”); resolution surfaces a row carrying both (→78). None on every
shipped row: the built-in transport is unchanged.
protocol: ProtocolId§auth: AuthId§api_header: Option<HeaderSpec>The auth header to write, present for every keyed row and absent exactly when
auth = "none" — resolution pairs the two or fails (IncompleteProvider,
→78), so a keyed row’s api_header.is_some() is a resolve invariant.
beta_headers: Vec<(String, String)>§generation_query: Vec<(String, String)>Ordered query pairs appended to generation POST URLs only (config §4.3.1). The protocol still owns the path; the shared encoded/raw request tail adds these with the generic query codec. Empty leaves every existing URL unchanged.
model_aliases: BTreeMap<String, String>§context_windows: BTreeMap<String, u32>The per-model context windows this row DECLARES (model-discovery §5.5): wire
model id → input-token limit. The SECOND source of a stated window, beneath the
list a --list-models GET actually served — most providers serve none (Anthropic,
OpenAI, Ollama), and the denominator a harness divides usage by has to come from
somewhere that reaches the request, the event, and every consumer above. A row
states only what its operator knows; an id absent from the map states nothing and
the key stays off the wire, never fabricated. Empty for every shipped row —
brazen declares no capacity it did not observe.
unsupported_body_keys: Vec<String>Canonical request-body fields this backend cannot accept — the inverse of
body_defaults (config §4.1): fill_absent’s sibling strip_unsupported
drops each from the request whatever its source, so the encoder never emits
it. Keys name CANONICAL fields (max_tokens, not the wire max_output_tokens),
so the canonical→wire rename stays owned by encode. Empty for every backend
that takes the standard params; the Codex row pins the three it 400s on.
models: Option<ModelsOverride>The [provider.models] discovery override (config §4.4): the --list-models
GET path/query and response list keys over the protocol default. None ⇒ the
protocol default shape; carried verbatim (the verb overlays it per key). No
resolve invariant — any protocol may carry or omit it.
oauth: Option<OAuthConfig>The auth-row OAuthConfig (auth §7.1), present exactly when auth = "oauth2" — resolution pairs the two or fails (IncompleteProvider, →78),
so the OAuth2 impl’s oauth.is_some() is a resolve invariant (auth §1.3).
ambient: Option<AmbientSpec>The row’s ambient credential source (auth §5.5), present when the row opts
into zero-setup discovery (Claude Code’s ~/.claude/.credentials.json).
None ⇒ the store is the only credential source. Unlike oauth/api_header
it has no resolve invariant: any auth model may name an ambient fallback.