4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
267 lines
8.3 KiB
Python
267 lines
8.3 KiB
Python
"""Canonical LLM provider auth and model-selection metadata."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Literal
|
|
|
|
CredentialKind = Literal["api_key", "cli", "ambient", "local"]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ProviderSpec:
|
|
"""Provider facts shared by config, auth, wizard, and runtime checks."""
|
|
|
|
value: str
|
|
label: str
|
|
credential_kind: CredentialKind
|
|
api_key_env: str = ""
|
|
model_env: str = ""
|
|
legacy_model_env: str | None = None
|
|
toolcall_model_env: str | None = None
|
|
classification_model_env: str | None = None
|
|
cli_model_env: str | None = None
|
|
endpoint_env: str = ""
|
|
api_version_env: str = ""
|
|
allow_custom_models: bool = False
|
|
|
|
@property
|
|
def uses_open_sre_api_key(self) -> bool:
|
|
return self.credential_kind == "api_key" and bool(self.api_key_env)
|
|
|
|
|
|
PROVIDER_SPECS: tuple[ProviderSpec, ...] = (
|
|
ProviderSpec(
|
|
value="anthropic",
|
|
label="Anthropic API key",
|
|
credential_kind="api_key",
|
|
api_key_env="ANTHROPIC_API_KEY",
|
|
model_env="ANTHROPIC_REASONING_MODEL",
|
|
legacy_model_env="ANTHROPIC_MODEL",
|
|
toolcall_model_env="ANTHROPIC_TOOLCALL_MODEL",
|
|
classification_model_env="ANTHROPIC_CLASSIFICATION_MODEL",
|
|
),
|
|
ProviderSpec(
|
|
value="openai",
|
|
label="OpenAI API key",
|
|
credential_kind="api_key",
|
|
api_key_env="OPENAI_API_KEY",
|
|
model_env="OPENAI_REASONING_MODEL",
|
|
legacy_model_env="OPENAI_MODEL",
|
|
toolcall_model_env="OPENAI_TOOLCALL_MODEL",
|
|
classification_model_env="OPENAI_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="openrouter",
|
|
label="OpenRouter",
|
|
credential_kind="api_key",
|
|
api_key_env="OPENROUTER_API_KEY",
|
|
model_env="OPENROUTER_REASONING_MODEL",
|
|
legacy_model_env="OPENROUTER_MODEL",
|
|
toolcall_model_env="OPENROUTER_TOOLCALL_MODEL",
|
|
classification_model_env="OPENROUTER_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="deepseek",
|
|
label="DeepSeek",
|
|
credential_kind="api_key",
|
|
api_key_env="DEEPSEEK_API_KEY",
|
|
model_env="DEEPSEEK_REASONING_MODEL",
|
|
legacy_model_env="DEEPSEEK_MODEL",
|
|
toolcall_model_env="DEEPSEEK_TOOLCALL_MODEL",
|
|
classification_model_env="DEEPSEEK_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="gemini",
|
|
label="Google Gemini API key",
|
|
credential_kind="api_key",
|
|
api_key_env="GEMINI_API_KEY",
|
|
model_env="GEMINI_REASONING_MODEL",
|
|
legacy_model_env="GEMINI_MODEL",
|
|
toolcall_model_env="GEMINI_TOOLCALL_MODEL",
|
|
classification_model_env="GEMINI_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="nvidia",
|
|
label="NVIDIA NIM",
|
|
credential_kind="api_key",
|
|
api_key_env="NVIDIA_API_KEY",
|
|
model_env="NVIDIA_REASONING_MODEL",
|
|
legacy_model_env="NVIDIA_MODEL",
|
|
toolcall_model_env="NVIDIA_TOOLCALL_MODEL",
|
|
classification_model_env="NVIDIA_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="minimax",
|
|
label="MiniMax",
|
|
credential_kind="api_key",
|
|
api_key_env="MINIMAX_API_KEY",
|
|
model_env="MINIMAX_REASONING_MODEL",
|
|
legacy_model_env="MINIMAX_MODEL",
|
|
toolcall_model_env="MINIMAX_TOOLCALL_MODEL",
|
|
classification_model_env="MINIMAX_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="groq",
|
|
label="Groq API key",
|
|
credential_kind="api_key",
|
|
api_key_env="GROQ_API_KEY",
|
|
model_env="GROQ_REASONING_MODEL",
|
|
legacy_model_env="GROQ_MODEL",
|
|
toolcall_model_env="GROQ_TOOLCALL_MODEL",
|
|
classification_model_env="GROQ_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="azure-openai",
|
|
label="Azure OpenAI",
|
|
credential_kind="api_key",
|
|
api_key_env="AZURE_OPENAI_API_KEY",
|
|
model_env="AZURE_OPENAI_REASONING_MODEL",
|
|
legacy_model_env="AZURE_OPENAI_MODEL",
|
|
toolcall_model_env="AZURE_OPENAI_TOOLCALL_MODEL",
|
|
classification_model_env="AZURE_OPENAI_CLASSIFICATION_MODEL",
|
|
endpoint_env="AZURE_OPENAI_BASE_URL",
|
|
api_version_env="AZURE_OPENAI_API_VERSION",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="bedrock",
|
|
label="Amazon Bedrock (IAM auth)",
|
|
credential_kind="ambient",
|
|
model_env="BEDROCK_REASONING_MODEL",
|
|
toolcall_model_env="BEDROCK_TOOLCALL_MODEL",
|
|
classification_model_env="BEDROCK_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="ollama",
|
|
label="Ollama (local)",
|
|
credential_kind="local",
|
|
api_key_env="OLLAMA_HOST",
|
|
model_env="OLLAMA_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="codex",
|
|
label="OpenAI Codex CLI",
|
|
credential_kind="cli",
|
|
model_env="CODEX_MODEL",
|
|
cli_model_env="CODEX_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="cursor",
|
|
label="Cursor Agent CLI",
|
|
credential_kind="cli",
|
|
model_env="CURSOR_MODEL",
|
|
cli_model_env="CURSOR_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="claude-code",
|
|
label="Anthropic Claude Code CLI",
|
|
credential_kind="cli",
|
|
model_env="CLAUDE_CODE_MODEL",
|
|
cli_model_env="CLAUDE_CODE_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="gemini-cli",
|
|
label="Google Gemini CLI",
|
|
credential_kind="cli",
|
|
model_env="GEMINI_CLI_MODEL",
|
|
cli_model_env="GEMINI_CLI_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="antigravity-cli",
|
|
label="Google Antigravity CLI",
|
|
credential_kind="cli",
|
|
model_env="ANTIGRAVITY_CLI_MODEL",
|
|
cli_model_env="ANTIGRAVITY_CLI_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="opencode",
|
|
label="OpenCode CLI",
|
|
credential_kind="cli",
|
|
model_env="OPENCODE_MODEL",
|
|
cli_model_env="OPENCODE_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="kimi",
|
|
label="Kimi Code CLI",
|
|
credential_kind="cli",
|
|
model_env="KIMI_MODEL",
|
|
cli_model_env="KIMI_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="copilot",
|
|
label="GitHub Copilot CLI",
|
|
credential_kind="cli",
|
|
model_env="COPILOT_MODEL",
|
|
cli_model_env="COPILOT_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="grok-cli",
|
|
label="xAI Grok Build CLI",
|
|
credential_kind="cli",
|
|
model_env="GROK_CLI_MODEL",
|
|
cli_model_env="GROK_CLI_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderSpec(
|
|
value="pi",
|
|
label="Pi CLI (pi.dev, BYOK multi-provider)",
|
|
credential_kind="cli",
|
|
model_env="PI_MODEL",
|
|
cli_model_env="PI_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
)
|
|
|
|
PROVIDER_BY_VALUE: dict[str, ProviderSpec] = {spec.value: spec for spec in PROVIDER_SPECS}
|
|
SUPPORTED_PROVIDER_VALUES: tuple[str, ...] = tuple(spec.value for spec in PROVIDER_SPECS)
|
|
API_KEY_PROVIDER_ENVS: dict[str, str] = {
|
|
spec.value: spec.api_key_env for spec in PROVIDER_SPECS if spec.uses_open_sre_api_key
|
|
}
|
|
KEYLESS_PROVIDER_VALUES: frozenset[str] = frozenset(
|
|
spec.value for spec in PROVIDER_SPECS if not spec.uses_open_sre_api_key
|
|
)
|
|
|
|
|
|
def provider_spec(provider: str) -> ProviderSpec | None:
|
|
"""Return the provider spec for *provider*, if supported."""
|
|
return PROVIDER_BY_VALUE.get(provider.strip().lower())
|
|
|
|
|
|
def require_provider_spec(provider: str) -> ProviderSpec:
|
|
"""Return the provider spec or raise ``KeyError`` for unsupported providers."""
|
|
spec = provider_spec(provider)
|
|
if spec is None:
|
|
raise KeyError(provider)
|
|
return spec
|
|
|
|
|
|
__all__ = [
|
|
"API_KEY_PROVIDER_ENVS",
|
|
"CredentialKind",
|
|
"KEYLESS_PROVIDER_VALUES",
|
|
"PROVIDER_BY_VALUE",
|
|
"PROVIDER_SPECS",
|
|
"ProviderSpec",
|
|
"SUPPORTED_PROVIDER_VALUES",
|
|
"provider_spec",
|
|
"require_provider_spec",
|
|
]
|