Skip to main content

Module provider

Module provider 

Source
Expand description

Provider + model resolution. Mirrors the Anthropic-protocol slice of the TS packages/coding-agent/src/core/model-resolver.ts (resolveCliModel + the provider/id[:thinking] parsing in crate::args).

v1 is Anthropic-protocol only (plan §5.16: “OAuth/Copilot skipped v1; API-key auth only” — now extended to include third-party Anthropic-compatible endpoints via ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN and a ~/.rpi/models.json catalog; OAuth is still deferred). The TS ModelRuntime/ModelRegistry multi-provider machinery is not ported; this module builds a single AnthropicProvider from a resolved credential and resolves a Model + ThinkingLevel against the catalog.

§Auth resolution precedence (mirrors upstream anthropic.ts:resolve)

  1. --api-key → provider default key (sent as x-api-key).
  2. ~/.rpi/auth.json anthropic.api_key.key — the persistent rpi auth login credential (sent as x-api-key). This is the “logged-in” path.
  3. ~/.rpi/models.json provider with authHeader: true + apiKeyAuthorization: Bearer <key> (a static gateway credential — the models.json file alone is a complete third-party-endpoint setup, no env var needed).
  4. ANTHROPIC_AUTH_TOKEN env → Authorization: Bearer <token> (folded into each model’s headers; the provider’s has_header_auth recognizes it and skips x-api-key, so a token-only setup does not error on a missing key).
  5. ANTHROPIC_API_KEY env → provider default key (x-api-key).
  6. None of the above ⇒ ResolveError::NoApiKey.

When a Bearer source (item 3 or 4) wins, the provider is built with api_key = None — the header on each model carries the auth. When a key source wins (1, 2, or 5), the provider carries the key as x-api-key.

§Endpoint + catalog

  • --base-url / ANTHROPIC_BASE_URL overrides model.base_url at resolve time (the request URL is built from it per-request in rpi-ai).
  • ~/.rpi/models.json (if present) merges/overrides the built-in catalog: each anthropic-messages provider contributes its models, with provider-level base_url/headers/authHeader folded in. The models.json provider id (e.g. gateway) is config-namespacing only in v1: every models.json model is stamped provider = "anthropic" so it routes through the single AnthropicProvider (the per-model base_url + headers carry the endpoint/auth differentiation). A --model gateway/custom-claude just strips the gateway/ prefix and matches the custom-claude id.

§Model pattern precedence (mirrors resolveCliModel)

  1. --model may carry provider/id[:thinking]. A leading anthropic/ (case-insensitive) is stripped; any other foo/ prefix is also stripped so a models.json provider id (e.g. gateway/…) addresses its model.
  2. Otherwise treat --model as id[:thinking]: if a trailing :level is a valid thinking level, strip it and apply it (overriding --thinking); else the whole string is the id.
  3. A --provider that isn’t anthropic is a hard error (v1 has no other provider). --provider anthropic is accepted and just confirms the default.
  4. The model id is matched exactly, case-insensitively against the catalog. The TS resolver additionally does fuzzy/partial matching; v1 keeps it exact to avoid surprising model picks (partial match is a common source of “got the wrong model” bugs — documented as a divergence in docs/m6-cli-open-questions.md).
  5. No --model ⇒ [pick_default_model]: (a) the built-in default (DEFAULT_MODEL_ID = claude-sonnet-5) if it is already authenticated (has a folded Bearer, or the provider holds an x-api-key); otherwise (b) the first authenticated model in the catalog — mirroring the TS findInitialModel step-4 fallback availableModels[0] over the auth-filtered snapshot. This lets a models.json-only gateway config “just work”: the built-in Anthropic models carry no auth, so the gateway model (the only authenticated one) is picked. The all-builtin/no-custom-code default (ANTHROPIC_API_KEY path) still selects claude-sonnet-5. Last resort falls back to DEFAULT_MODEL_ID (or the catalog head) — unreachable in practice because the auth gate refuses an unauthed catalog earlier.

Structs§

ResolvedModel
The resolved run configuration: the provider handle, the chosen model, and the effective thinking level (after --thinking / :level / model-clamp).

Enums§

ResolveError
A resolution error. The TS resolver returns { error, warning }; v1 folds both into a single enum since the CLI treats them the same (print + non-zero exit) except NoApiKey, which prints guidance then exits.

Constants§

ANTHROPIC_API_KEY_ENV
The env var consulted for the API key. Mirrors TS ANTHROPIC_API_KEY.
ANTHROPIC_AUTH_TOKEN_ENV
The env var consulted for a bearer token (routed as Authorization: Bearer). Mirrors TS ANTHROPIC_AUTH_TOKEN — used by third-party Anthropic-compatible gateways (one-api/new-api/claude-code-router and private reverse proxies) that authenticate via Authorization rather than x-api-key.
ANTHROPIC_BASE_URL_ENV
The env var that overrides the Anthropic endpoint base URL. Mirrors TS ANTHROPIC_BASE_URL — point this at a gateway/proxy that speaks the /v1/messages protocol.
DEFAULT_MODEL_ID
The v1-default model id when --model is absent. Mirrors the TS defaultModelPerProvider["anthropic"] (the first current-generation reasoning model in the catalog).
DEFAULT_THINKING_LEVEL
The default thinking level when neither --thinking nor a :level suffix is present. Mirrors the TS DEFAULT_THINKING_LEVEL ("medium", clamped to model capabilities by the harness’s provider build_params).
NO_API_KEY_HINT
Hint text surfaced when no credential source is available. Lists every accepted source so the user can pick the one that fits their setup.
OPENAI_API_KEY_ENV
Standard OpenAI API-key environment variable used by the openai-completions provider.

Functions§

available_catalog
The catalog the TUI’s /model selector displays (read-only). Re-derives the auth-filtered snapshot the provider was built from so the selector shows exactly the models that can actually run (mirrors pi getAvailableSnapshot: available = all.filter(m => configuredProviders.has(m.provider)) — v1’s single-provider equivalent of “configured” is [model_is_authed]).
resolve
Resolve the provider + model + thinking level from the CLI flags + env + ~/.rpi/ config.