brazen 0.0.4

A stateless, swiss-army-knife adapter for every LLM provider and protocol.
Documentation
# Embedded provider table (arch §4.2). Parsed through the SAME
# `toml::from_str::<PartialConfig>` path as a user config file — the lowest-
# precedence operand of the resolution fold, never a bootstrap special case
# (config §3.5). A unit test parses this file so a malformed edit fails the
# build, not a user run.

# The transport SILENCE budget in whole seconds (config §4.3, architecture §13.15).
# The single home for this number — `bz` reads it off the resolved config and, via
# `timeouts()`, fans it onto ureq's connect + response-header + inter-chunk-idle
# budgets, so the bin holds no magic constant. It abandons an upstream that makes no
# progress (sends no bytes) for this long — applied per phase — WITHOUT capping total
# stream length, so a long-but-live generation is never cut (it is NOT a wall-clock
# total). Override in your config file / env / flag; delete this line to unbound it.
timeout = 120

[[provider]]
name = "anthropic"
base_url = "https://api.anthropic.com"
protocol = "anthropic_messages"
auth = "api_key"
api_header = { name = "x-api-key", scheme = "raw" }
beta_headers = [["anthropic-version", "2023-06-01"]]
body_defaults = { max_tokens = 4096 }   # Anthropic requires max_tokens; the row's sane default, overridable via config/flag (config §4.1)
model_prefixes = ["claude-"]            # owns the claude- family, so `bz -m claude-… "q"` routes here with no --provider (arch §4.3)
ambient = { format = "api_key_env", path = "ANTHROPIC_API_KEY" }   # vendor-conventional key alias as a ROW-SCOPED, store-miss source — below BRAZEN_API_KEY/--api-key, can't leak cross-vendor or shadow a stored cred (auth §5.5)

[[provider]]
name = "openai"
base_url = "https://api.openai.com/v1"
protocol = "openai_chat"
auth = "bearer"
api_header = { name = "Authorization", scheme = "bearer" }
model_prefixes = ["gpt-", "chatgpt-", "o1", "o3", "o4"]   # the OpenAI families; openai-responses (same models, other protocol) ships none, so it stays explicit (arch §4.3)

# Mistral speaks the OpenAI chat dialect verbatim — the severability proof: one
# row, ZERO Rust (providers §2). Reuses the OpenAiChat protocol + bearer auth.
[[provider]]
name = "mistral"
base_url = "https://api.mistral.ai/v1"
protocol = "openai_chat"
auth = "bearer"
api_header = { name = "Authorization", scheme = "bearer" }
model_prefixes = ["mistral-", "ministral-", "magistral-", "codestral-", "pixtral-"]

[[provider]]
name = "openai-responses"
base_url = "https://api.openai.com/v1"
protocol = "openai_responses"
auth = "bearer"
api_header = { name = "Authorization", scheme = "bearer" }
# No model_prefixes: openai-responses serves the SAME OpenAI model ids as `openai`
# over a different protocol. Claiming them would make every gpt-… ambiguous (78),
# so this alternate-protocol row stays opt-in via explicit --provider (arch §4.3).

# Google authenticates with a custom header NAME carrying the raw key — pure row
# DATA read by the shared ApiKeyAuth, no new Auth impl (providers §4.1).
[[provider]]
name = "google"
base_url = "https://generativelanguage.googleapis.com"
protocol = "google_generative_ai"
auth = "api_key"
api_header = { name = "x-goog-api-key", scheme = "raw" }
model_prefixes = ["gemini-"]

# Local Ollama needs no auth: `auth = "none"` reads no credential and writes no
# header, so a keyless row carries no `api_header` (providers §5.1).
[[provider]]
name = "ollama"
base_url = "http://localhost:11434"
protocol = "ollama_chat"
auth = "none"

# The installed Claude Code CLI as a pure model pass-through (claude-code spec): an
# EXEC-transport row — `exec` substitutes for base_url, `claude` carries its own
# OAuth so auth = "none". The five listed canonical fields have no wire slot on the
# CLI (spec §4.1), so they strip pre-encode. No model_prefixes: `anthropic` owns
# `claude-`; this alternate-transport row stays opt-in via explicit --provider,
# like openai-responses (arch §4.3.1).
[[provider]]
name = "claude-code"
protocol = "claude_code"
auth = "none"
exec = "claude"
unsupported_body_keys = ["max_tokens", "temperature", "top_p", "stop", "output"]