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
822 lines
31 KiB
Python
822 lines
31 KiB
Python
"""Wizard configuration metadata."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
from dataclasses import dataclass
|
|
from typing import Literal
|
|
|
|
from config.config import (
|
|
ANTHROPIC_REASONING_MODEL,
|
|
AZURE_OPENAI_REASONING_MODEL,
|
|
BEDROCK_REASONING_MODEL,
|
|
DEEPSEEK_REASONING_MODEL,
|
|
DEFAULT_OLLAMA_HOST,
|
|
DEFAULT_OLLAMA_MODEL,
|
|
GEMINI_REASONING_MODEL,
|
|
GROQ_REASONING_MODEL,
|
|
MINIMAX_REASONING_MODEL,
|
|
NVIDIA_REASONING_MODEL,
|
|
OPENAI_REASONING_MODEL,
|
|
OPENROUTER_REASONING_MODEL,
|
|
)
|
|
from config.llm_auth.provider_catalog import require_provider_spec
|
|
from config.local_env import PROJECT_ROOT as PROJECT_ROOT
|
|
from config.local_env import get_project_env_path
|
|
from integrations.llm_cli.base import LLMCLIAdapter
|
|
|
|
PROJECT_ENV_PATH = get_project_env_path()
|
|
|
|
CredentialKind = Literal["api_key", "host", "cli", "none"]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ModelOption:
|
|
"""A selectable default model."""
|
|
|
|
value: str
|
|
label: str
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ProviderOption:
|
|
"""Wizard metadata for a supported LLM provider."""
|
|
|
|
value: str
|
|
label: str
|
|
group: str
|
|
api_key_env: str
|
|
model_env: str
|
|
default_model: str
|
|
models: tuple[ModelOption, ...]
|
|
#: If set, ``sync_provider_env`` also writes this key (same value) for legacy .env files.
|
|
legacy_model_env: str | None = None
|
|
#: Env var that holds the *toolcall* model for this provider. ``None`` for
|
|
#: providers that don't expose a separate toolcall model (e.g. CLI-backed
|
|
#: providers like ``codex``/``claude-code``, or Ollama).
|
|
toolcall_model_env: str | None = None
|
|
#: Env var that holds the *classification* model for this provider. When
|
|
#: unset, ``sync_provider_env`` falls back to replacing ``_REASONING_MODEL``
|
|
#: with ``_CLASSIFICATION_MODEL`` in ``model_env``.
|
|
classification_model_env: str | None = None
|
|
endpoint_env: str = ""
|
|
api_version_env: str = ""
|
|
#: Human-readable name for the credential requested during onboarding. Most
|
|
#: providers want an API key; Ollama wants a host URL. Used as the wizard
|
|
#: prompt label, e.g. ``{label} {credential_label} ({api_key_env})``.
|
|
credential_label: str = "API key"
|
|
#: Whether the credential should be prompted as a secret (hidden input).
|
|
#: API keys are secrets; a local Ollama host URL is not.
|
|
credential_secret: bool = True
|
|
#: Optional hint shown as the default value in the prompt (e.g. the
|
|
#: default Ollama host URL). Empty string means no default.
|
|
credential_default: str = ""
|
|
#: ``cli`` providers use ``adapter_factory`` and vendor auth (no API key in .env).
|
|
credential_kind: CredentialKind = "api_key"
|
|
adapter_factory: Callable[[], LLMCLIAdapter] | None = None
|
|
#: Whether the CLI should accept model IDs outside the curated quick-pick list.
|
|
#: Use this for providers whose model catalogs are large, account-gated, or
|
|
#: updated independently of OpenSRE releases.
|
|
allow_custom_models: bool = False
|
|
|
|
def __post_init__(self) -> None:
|
|
spec = require_provider_spec(self.value)
|
|
kind_map = {"api_key": "api_key", "cli": "cli", "none": "ambient", "host": "local"}
|
|
catalog_kind = kind_map[self.credential_kind]
|
|
mismatches = {
|
|
"api_key_env": (self.api_key_env, spec.api_key_env),
|
|
"model_env": (self.model_env, spec.model_env),
|
|
"legacy_model_env": (self.legacy_model_env, spec.legacy_model_env),
|
|
"toolcall_model_env": (self.toolcall_model_env, spec.toolcall_model_env),
|
|
"classification_model_env": (
|
|
self.classification_model_env,
|
|
spec.classification_model_env,
|
|
),
|
|
"endpoint_env": (self.endpoint_env, spec.endpoint_env),
|
|
"api_version_env": (self.api_version_env, spec.api_version_env),
|
|
"credential_kind": (catalog_kind, spec.credential_kind),
|
|
"allow_custom_models": (self.allow_custom_models, spec.allow_custom_models),
|
|
}
|
|
drift = {name: values for name, values in mismatches.items() if values[0] != values[1]}
|
|
if drift:
|
|
details = ", ".join(
|
|
f"{name}: {actual!r} != {expected!r}" for name, (actual, expected) in drift.items()
|
|
)
|
|
raise ValueError(
|
|
f"ProviderOption {self.value!r} drifts from provider catalog: {details}"
|
|
)
|
|
|
|
|
|
# Source: https://docs.anthropic.com/en/docs/about-claude/models/overview
|
|
ANTHROPIC_MODELS = (
|
|
ModelOption(value=ANTHROPIC_REASONING_MODEL, label="Claude Opus 4.7"),
|
|
ModelOption(value="claude-fable-5", label="Claude Fable 5 — most capable"),
|
|
ModelOption(value="claude-sonnet-4-6", label="Claude Sonnet 4.6"),
|
|
ModelOption(value="claude-haiku-4-5", label="Claude Haiku 4.5"),
|
|
)
|
|
|
|
# Source: https://platform.openai.com/docs/models
|
|
# Codex model IDs are intentionally omitted here: OpenSRE's direct OpenAI
|
|
# provider uses Chat Completions, while Codex models require a different API path.
|
|
OPENAI_MODELS = (
|
|
ModelOption(value=OPENAI_REASONING_MODEL, label="GPT-5.4 mini"),
|
|
ModelOption(value="gpt-5.6-sol", label="GPT-5.6 Sol — flagship"),
|
|
ModelOption(value="gpt-5.6-terra", label="GPT-5.6 Terra — balanced"),
|
|
ModelOption(value="gpt-5.6-luna", label="GPT-5.6 Luna — cost-efficient"),
|
|
ModelOption(value="gpt-5.5", label="GPT-5.5"),
|
|
ModelOption(value="gpt-5.4", label="GPT-5.4"),
|
|
ModelOption(value="gpt-5.4-nano", label="GPT-5.4 nano"),
|
|
)
|
|
|
|
# Source: https://openrouter.ai/api/v1/models
|
|
OPENROUTER_MODELS = (
|
|
ModelOption(value=OPENROUTER_REASONING_MODEL, label="OpenRouter Auto (smart routing)"),
|
|
ModelOption(value="openai/gpt-5.6-sol", label="GPT-5.6 Sol (via OpenRouter)"),
|
|
ModelOption(value="openai/gpt-5.6-terra", label="GPT-5.6 Terra (via OpenRouter)"),
|
|
ModelOption(value="openai/gpt-5.6-luna", label="GPT-5.6 Luna (via OpenRouter)"),
|
|
ModelOption(value="openai/gpt-5.5", label="GPT-5.5 (via OpenRouter)"),
|
|
ModelOption(value="anthropic/claude-opus-4.7", label="Claude Opus 4.7 (via OpenRouter)"),
|
|
ModelOption(value="anthropic/claude-sonnet-4.6", label="Claude Sonnet 4.6 (via OpenRouter)"),
|
|
ModelOption(value="anthropic/claude-haiku-4.5", label="Claude Haiku 4.5 (via OpenRouter)"),
|
|
ModelOption(
|
|
value="google/gemini-3.1-pro-preview", label="Gemini 3.1 Pro (preview, via OpenRouter)"
|
|
),
|
|
ModelOption(
|
|
value="google/gemini-3-flash-preview", label="Gemini 3 Flash (preview, via OpenRouter)"
|
|
),
|
|
ModelOption(
|
|
value="google/gemini-3.1-flash-lite-preview",
|
|
label="Gemini 3.1 Flash-Lite (preview, via OpenRouter)",
|
|
),
|
|
ModelOption(
|
|
value="google/gemini-3.1-flash-image-preview",
|
|
label="Gemini 3.1 Flash Image (preview, via OpenRouter)",
|
|
),
|
|
ModelOption(
|
|
value="google/gemini-3-pro-image-preview",
|
|
label="Gemini 3 Pro Image (preview, via OpenRouter)",
|
|
),
|
|
ModelOption(value="meta-llama/llama-4-maverick", label="Llama 4 Maverick (via OpenRouter)"),
|
|
ModelOption(value="meta-llama/llama-4-scout", label="Llama 4 Scout (via OpenRouter)"),
|
|
ModelOption(value="mistralai/mistral-large-2512", label="Mistral Large 3 (via OpenRouter)"),
|
|
ModelOption(value="x-ai/grok-4", label="Grok 4 (via OpenRouter)"),
|
|
ModelOption(value="x-ai/grok-4-fast", label="Grok 4 Fast (via OpenRouter)"),
|
|
ModelOption(value="moonshotai/kimi-k2.5", label="Kimi K2.5 (via OpenRouter)"),
|
|
ModelOption(value="z-ai/glm-4.7", label="GLM 4.7 (via OpenRouter)"),
|
|
ModelOption(value="minimax/minimax-m2", label="MiniMax M2 (via OpenRouter)"),
|
|
ModelOption(value="deepseek/deepseek-v3.2", label="DeepSeek V3.2 (via OpenRouter)"),
|
|
ModelOption(value="qwen/qwen-3.6-plus-preview", label="Qwen 3.6 Plus (via OpenRouter)"),
|
|
)
|
|
|
|
DEEPSEEK_MODELS = (
|
|
ModelOption(value=DEEPSEEK_REASONING_MODEL, label="DeepSeek V4 Pro"),
|
|
ModelOption(value="deepseek-v4-flash", label="DeepSeek V4 Flash"),
|
|
)
|
|
|
|
GEMINI_MODELS = (
|
|
ModelOption(value=GEMINI_REASONING_MODEL, label="Gemini 3.1 Pro (preview)"),
|
|
ModelOption(value="gemini-3-flash-preview", label="Gemini 3 Flash (preview)"),
|
|
ModelOption(value="gemini-3.1-flash-lite-preview", label="Gemini 3.1 Flash-Lite (preview)"),
|
|
ModelOption(value="gemini-3.1-flash-image-preview", label="Gemini 3.1 Flash Image (preview)"),
|
|
ModelOption(value="gemini-3-pro-image-preview", label="Gemini 3 Pro Image (preview)"),
|
|
)
|
|
|
|
NVIDIA_MODELS = (
|
|
ModelOption(
|
|
value=NVIDIA_REASONING_MODEL,
|
|
label="Nemotron 3 Super 120B (5x higher throughput for agentic AI)",
|
|
),
|
|
ModelOption(value="nvidia/nemotron-3-nano-30b-a3b", label="Nemotron 3 Nano 30B"),
|
|
)
|
|
|
|
MINIMAX_MODELS = (
|
|
ModelOption(value=MINIMAX_REASONING_MODEL, label="MiniMax M3"),
|
|
ModelOption(value="MiniMax-M2.7-highspeed", label="MiniMax M2.7 highspeed"),
|
|
)
|
|
|
|
GROQ_MODELS = (
|
|
ModelOption(value=GROQ_REASONING_MODEL, label="Llama 3.3 70B Versatile"),
|
|
ModelOption(value="llama-3.1-8b-instant", label="Llama 3.1 8B Instant"),
|
|
ModelOption(value="openai/gpt-oss-120b", label="GPT-OSS 120B"),
|
|
ModelOption(value="openai/gpt-oss-20b", label="GPT-OSS 20B"),
|
|
ModelOption(value="qwen/qwen3-32b", label="Qwen3 32B"),
|
|
ModelOption(value="meta-llama/llama-4-scout-17b-16e-instruct", label="Llama 4 Scout 17B"),
|
|
)
|
|
|
|
# Azure OpenAI model values are deployment names in your resource.
|
|
# Source: https://learn.microsoft.com/en-us/azure/ai-foundry/model-inference/concepts/models
|
|
AZURE_OPENAI_MODELS = (
|
|
ModelOption(value=AZURE_OPENAI_REASONING_MODEL, label="gpt-5.4-mini deployment"),
|
|
ModelOption(value="gpt-5.6-sol", label="gpt-5.6-sol deployment"),
|
|
ModelOption(value="gpt-5.6-terra", label="gpt-5.6-terra deployment"),
|
|
ModelOption(value="gpt-5.6-luna", label="gpt-5.6-luna deployment"),
|
|
ModelOption(value="gpt-5.5", label="gpt-5.5 deployment"),
|
|
ModelOption(value="gpt-5.4", label="gpt-5.4 deployment"),
|
|
ModelOption(value="gpt-5.4-nano", label="gpt-5.4-nano deployment"),
|
|
ModelOption(value="gpt-5-mini", label="gpt-5-mini deployment"),
|
|
ModelOption(value="gpt-5", label="gpt-5 deployment"),
|
|
ModelOption(value="gpt-4.1", label="gpt-4.1 deployment"),
|
|
ModelOption(value="gpt-4.1-mini", label="gpt-4.1-mini deployment"),
|
|
ModelOption(value="o3-mini", label="o3-mini deployment"),
|
|
)
|
|
|
|
BEDROCK_MODELS = (
|
|
ModelOption(
|
|
value=BEDROCK_REASONING_MODEL,
|
|
label="Claude Sonnet 4.6 (US cross-region) — default",
|
|
),
|
|
ModelOption(
|
|
value="us.anthropic.claude-opus-4-7",
|
|
label="Claude Opus 4.7 (US cross-region) — most capable",
|
|
),
|
|
ModelOption(
|
|
value="us.anthropic.claude-opus-4-6-v1",
|
|
label="Claude Opus 4.6 (US cross-region)",
|
|
),
|
|
ModelOption(
|
|
value="us.anthropic.claude-opus-4-5-20251101-v1:0",
|
|
label="Claude Opus 4.5 (US cross-region)",
|
|
),
|
|
ModelOption(
|
|
value="us.anthropic.claude-opus-4-1-20250805-v1:0",
|
|
label="Claude Opus 4.1 (US cross-region)",
|
|
),
|
|
ModelOption(
|
|
value="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
label="Claude Sonnet 4.5 (US cross-region)",
|
|
),
|
|
ModelOption(
|
|
value="us.anthropic.claude-sonnet-4-20250514-v1:0",
|
|
label="Claude Sonnet 4 (US cross-region)",
|
|
),
|
|
ModelOption(
|
|
value="us.anthropic.claude-haiku-4-5-20251001-v1:0",
|
|
label="Claude Haiku 4.5 (US cross-region) — fast, cost-efficient",
|
|
),
|
|
ModelOption(
|
|
value="us.meta.llama4-maverick-17b-instruct-v1:0",
|
|
label="Llama 4 Maverick 17B (US cross-region)",
|
|
),
|
|
ModelOption(
|
|
value="us.amazon.nova-pro-v1:0",
|
|
label="Amazon Nova Pro (US cross-region)",
|
|
),
|
|
ModelOption(
|
|
value="mistral.mistral-large-3-675b-instruct",
|
|
label="Mistral Large 3 675B Instruct (on-demand)",
|
|
),
|
|
)
|
|
|
|
OLLAMA_MODELS = (
|
|
ModelOption(value="llama3.2", label="Llama 3.2 (3B) — recommended"),
|
|
ModelOption(value="llama3.1:8b", label="Llama 3.1 (8B)"),
|
|
ModelOption(value="mistral", label="Mistral 7B"),
|
|
ModelOption(value="qwen2.5:7b", label="Qwen 2.5 (7B)"),
|
|
)
|
|
|
|
# Source: https://platform.claude.com/docs/en/about-claude/models/overview (verified 2026-05-21).
|
|
# Empty value means "no --model" so Claude Code uses its configured default.
|
|
CLAUDE_CODE_MODELS = (
|
|
ModelOption(
|
|
value="",
|
|
label="CLI default (no --model; use Claude Code configured model)",
|
|
),
|
|
ModelOption(value="claude-fable-5", label="Claude Fable 5 — most capable"),
|
|
ModelOption(value="claude-opus-4-7", label="Claude Opus 4.7"),
|
|
ModelOption(value="claude-sonnet-4-6", label="Claude Sonnet 4.6 — balanced"),
|
|
ModelOption(value="claude-haiku-4-5", label="Claude Haiku 4.5 — fast, cost-efficient"),
|
|
)
|
|
|
|
# Source: https://developers.openai.com/codex/cli/features (verified 2026-05-21).
|
|
# Empty value means "no -m" so the Codex CLI uses its configured default/current model.
|
|
CODEX_MODELS = (
|
|
ModelOption(
|
|
value="",
|
|
label="CLI default (no -m; use Codex configured model)",
|
|
),
|
|
ModelOption(value="gpt-5.6-sol", label="gpt-5.6-sol — newest frontier coding"),
|
|
ModelOption(value="gpt-5.6-terra", label="gpt-5.6-terra — balanced"),
|
|
ModelOption(value="gpt-5.6-luna", label="gpt-5.6-luna — fast, cost-efficient"),
|
|
ModelOption(value="gpt-5.5", label="gpt-5.5 — frontier coding"),
|
|
ModelOption(value="gpt-5.4", label="gpt-5.4 — fallback default"),
|
|
ModelOption(value="gpt-5.4-mini", label="gpt-5.4-mini — fast, cost-efficient"),
|
|
ModelOption(value="gpt-5.3-codex", label="gpt-5.3-codex — coding-optimized"),
|
|
ModelOption(
|
|
value="gpt-5.3-codex-spark",
|
|
label="gpt-5.3-codex-spark — research preview (ChatGPT Pro)",
|
|
),
|
|
)
|
|
|
|
# Source: google-gemini/gemini-cli, packages/core/src/config/models.ts (verified 2026-05-21).
|
|
# Empty value means "no --model" so Gemini CLI uses its configured/default model.
|
|
GEMINI_CLI_MODELS = (
|
|
ModelOption(
|
|
value="",
|
|
label="CLI default (no --model; use Gemini CLI configured model)",
|
|
),
|
|
ModelOption(
|
|
value="gemini-3.1-pro-preview",
|
|
label="gemini-3.1-pro-preview — newest frontier (preview)",
|
|
),
|
|
ModelOption(
|
|
value="gemini-3-flash-preview",
|
|
label="gemini-3-flash-preview — fast (preview)",
|
|
),
|
|
ModelOption(
|
|
value="gemini-3.1-flash-lite-preview",
|
|
label="gemini-3.1-flash-lite-preview — fastest (preview)",
|
|
),
|
|
ModelOption(
|
|
value="gemini-2.5-pro",
|
|
label="gemini-2.5-pro — stable, strongest reasoning",
|
|
),
|
|
ModelOption(
|
|
value="gemini-2.5-flash",
|
|
label="gemini-2.5-flash — stable, balanced",
|
|
),
|
|
ModelOption(
|
|
value="gemini-2.5-flash-lite",
|
|
label="gemini-2.5-flash-lite — stable, fastest",
|
|
),
|
|
)
|
|
|
|
# Source: ``agy`` ``/models`` (verified 2026-05-26 against agy 1.0.2).
|
|
# Empty value means "no --model" so agy uses its currently configured model.
|
|
# Note: agy 1.0.2 does not yet expose ``--model`` in headless ``-p`` mode
|
|
# (verified locally), so the adapter ignores any value via ``del model`` in
|
|
# ``build()``. Catalog is forward-compat: once Google ships ``--model`` in
|
|
# headless, the wizard selection plus ``model_env_key="ANTIGRAVITY_CLI_MODEL"``
|
|
# will route through to ``argv`` in a one-line change to ``antigravity_cli.py``.
|
|
# Effort variants (Low/Medium/High/Thinking) shown in ``/models`` belong on
|
|
# opensre's existing ``reasoning_effort`` knob, not here.
|
|
ANTIGRAVITY_CLI_MODELS = (
|
|
ModelOption(
|
|
value="",
|
|
label="CLI default (no --model; use agy's currently configured model)",
|
|
),
|
|
ModelOption(value="gemini-3.5-flash", label="gemini-3.5-flash — fast"),
|
|
ModelOption(value="gemini-3.1-pro", label="gemini-3.1-pro — strongest Google reasoning"),
|
|
ModelOption(value="claude-sonnet-4.6", label="claude-sonnet-4.6 — Anthropic balanced"),
|
|
ModelOption(value="claude-opus-4.6", label="claude-opus-4.6 — Anthropic most capable"),
|
|
ModelOption(value="gpt-oss-120b", label="gpt-oss-120b — open-source"),
|
|
)
|
|
|
|
# Source: https://opencode.ai/docs/zen (verified 2026-05-21).
|
|
# OpenCode routes models through OpenCode Zen using the ``opencode/`` prefix.
|
|
# Curated subset of the full ~40-model catalog; the wizard's custom-ID escape
|
|
# hatch covers anything not pre-listed here.
|
|
OPENCODE_MODELS = (
|
|
ModelOption(
|
|
value="",
|
|
label="CLI default (no -m; use OpenCode configured model)",
|
|
),
|
|
ModelOption(value="opencode/gpt-5.5", label="GPT-5.5 (OpenCode Zen) — frontier"),
|
|
ModelOption(value="opencode/gpt-5.4", label="GPT-5.4 (OpenCode Zen)"),
|
|
ModelOption(value="opencode/gpt-5.4-mini", label="GPT-5.4 mini (OpenCode Zen) — fast"),
|
|
ModelOption(
|
|
value="opencode/gpt-5.3-codex",
|
|
label="GPT-5.3 Codex (OpenCode Zen) — coding-optimized",
|
|
),
|
|
ModelOption(
|
|
value="opencode/gpt-5.3-codex-spark",
|
|
label="GPT-5.3 Codex Spark (OpenCode Zen) — research preview",
|
|
),
|
|
ModelOption(
|
|
value="opencode/claude-opus-4-7",
|
|
label="Claude Opus 4.7 (OpenCode Zen) — most capable",
|
|
),
|
|
ModelOption(
|
|
value="opencode/claude-sonnet-4-6",
|
|
label="Claude Sonnet 4.6 (OpenCode Zen) — balanced",
|
|
),
|
|
ModelOption(
|
|
value="opencode/claude-haiku-4-5",
|
|
label="Claude Haiku 4.5 (OpenCode Zen) — fast",
|
|
),
|
|
ModelOption(value="opencode/gemini-3.1-pro", label="Gemini 3.1 Pro (OpenCode Zen)"),
|
|
ModelOption(value="opencode/gemini-3-flash", label="Gemini 3 Flash (OpenCode Zen)"),
|
|
ModelOption(value="opencode/kimi-k2.6", label="Kimi K2.6 (OpenCode Zen)"),
|
|
ModelOption(value="opencode/minimax-m2.7", label="MiniMax M2.7 (OpenCode Zen)"),
|
|
ModelOption(value="opencode/qwen3.6-plus", label="Qwen3.6 Plus (OpenCode Zen)"),
|
|
ModelOption(value="opencode/glm-5.1", label="GLM 5.1 (OpenCode Zen)"),
|
|
ModelOption(
|
|
value="opencode/minimax-m2.5-free",
|
|
label="MiniMax M2.5 (OpenCode Zen) — free tier",
|
|
),
|
|
ModelOption(
|
|
value="opencode/deepseek-v4-flash-free",
|
|
label="DeepSeek V4 Flash (OpenCode Zen) — free tier",
|
|
),
|
|
)
|
|
|
|
|
|
CURSOR_MODELS = (
|
|
ModelOption(
|
|
value="",
|
|
label="CLI default (no --model; use Cursor configured model)",
|
|
),
|
|
ModelOption(value="auto", label="auto"),
|
|
ModelOption(value="gpt-5", label="gpt-5"),
|
|
ModelOption(value="sonnet-4", label="sonnet-4"),
|
|
ModelOption(value="sonnet-4-thinking", label="sonnet-4-thinking"),
|
|
)
|
|
|
|
|
|
def _codex_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.codex import CodexAdapter
|
|
|
|
return CodexAdapter()
|
|
|
|
|
|
def _cursor_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.cursor import CursorAdapter
|
|
|
|
return CursorAdapter()
|
|
|
|
|
|
def _claude_code_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.claude_code import ClaudeCodeAdapter
|
|
|
|
return ClaudeCodeAdapter()
|
|
|
|
|
|
def _gemini_cli_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.gemini_cli import GeminiCLIAdapter
|
|
|
|
return GeminiCLIAdapter()
|
|
|
|
|
|
def _antigravity_cli_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.antigravity_cli import AntigravityCLIAdapter
|
|
|
|
return AntigravityCLIAdapter()
|
|
|
|
|
|
def _opencode_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.opencode import OpenCodeAdapter
|
|
|
|
return OpenCodeAdapter()
|
|
|
|
|
|
def _kimi_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.kimi import KimiAdapter
|
|
|
|
return KimiAdapter()
|
|
|
|
|
|
def _copilot_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.copilot import CopilotAdapter
|
|
|
|
return CopilotAdapter()
|
|
|
|
|
|
def _grok_cli_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.grok_cli import GrokCLIAdapter
|
|
|
|
return GrokCLIAdapter()
|
|
|
|
|
|
_GROK_CLI_DEFAULT_MODEL_OPTION = ModelOption(
|
|
value="",
|
|
label="CLI default (no -m; use Grok Build configured model)",
|
|
)
|
|
|
|
# Static fallback used when ``grok models`` is unavailable at wizard time.
|
|
GROK_CLI_MODELS = (
|
|
_GROK_CLI_DEFAULT_MODEL_OPTION,
|
|
ModelOption(value="grok-build", label="grok-build"),
|
|
ModelOption(value="grok-composer-2.5-fast", label="grok-composer-2.5-fast"),
|
|
)
|
|
|
|
|
|
def _pi_adapter_factory() -> LLMCLIAdapter:
|
|
from integrations.llm_cli.pi_cli import PiAdapter
|
|
|
|
return PiAdapter()
|
|
|
|
|
|
# Pi is BYOK/multi-provider; models use the ``provider/model`` form. These are a
|
|
# convenience shortlist — ``allow_custom_models=True`` lets users type any model
|
|
# (and PI_MODEL overrides at runtime). Run ``pi --list-models`` for the full set.
|
|
PI_MODELS = (
|
|
ModelOption(value="", label="CLI default (no --model; use Pi configured model)"),
|
|
ModelOption(value="google/gemini-2.5-flash-lite", label="google/gemini-2.5-flash-lite"),
|
|
ModelOption(value="google/gemini-2.5-flash", label="google/gemini-2.5-flash"),
|
|
ModelOption(value="anthropic/claude-haiku-4-5", label="anthropic/claude-haiku-4-5"),
|
|
ModelOption(value="openai/gpt-4o-mini", label="openai/gpt-4o-mini"),
|
|
)
|
|
|
|
|
|
KIMI_MODELS = (
|
|
ModelOption(
|
|
value="",
|
|
label="CLI default (no -m; use Kimi configured model)",
|
|
),
|
|
ModelOption(value="kimi-k2-thinking-turbo", label="kimi-k2-thinking-turbo"),
|
|
ModelOption(value="kimi-k2.5", label="kimi-k2.5"),
|
|
ModelOption(value="kimi-k2.6", label="kimi-k2.6"),
|
|
)
|
|
|
|
|
|
# Empty value means "no --model" so Copilot CLI uses its configured default model.
|
|
# We do not hardcode model identifiers here: the Copilot CLI's accepted --model
|
|
# values are not stable across releases and live behind GitHub-side gating, so
|
|
# baking them in risks "model not found" errors after the user has finished the
|
|
# wizard. Users override via COPILOT_MODEL when they know what their plan exposes.
|
|
COPILOT_MODELS = (
|
|
ModelOption(
|
|
value="",
|
|
label="CLI default (no --model; use Copilot CLI configured model)",
|
|
),
|
|
)
|
|
|
|
|
|
SUPPORTED_PROVIDERS = (
|
|
ProviderOption(
|
|
value="anthropic",
|
|
label="Anthropic API key",
|
|
group="Hosted providers",
|
|
api_key_env="ANTHROPIC_API_KEY",
|
|
model_env="ANTHROPIC_REASONING_MODEL",
|
|
default_model=ANTHROPIC_REASONING_MODEL,
|
|
models=ANTHROPIC_MODELS,
|
|
legacy_model_env="ANTHROPIC_MODEL",
|
|
toolcall_model_env="ANTHROPIC_TOOLCALL_MODEL",
|
|
classification_model_env="ANTHROPIC_CLASSIFICATION_MODEL",
|
|
),
|
|
ProviderOption(
|
|
value="claude-code",
|
|
label="Anthropic Claude Code CLI",
|
|
group="Hosted providers",
|
|
api_key_env="",
|
|
model_env="CLAUDE_CODE_MODEL",
|
|
default_model="",
|
|
models=CLAUDE_CODE_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_claude_code_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="openai",
|
|
label="OpenAI API key",
|
|
group="Hosted providers",
|
|
api_key_env="OPENAI_API_KEY",
|
|
model_env="OPENAI_REASONING_MODEL",
|
|
default_model=OPENAI_REASONING_MODEL,
|
|
models=OPENAI_MODELS,
|
|
legacy_model_env="OPENAI_MODEL",
|
|
toolcall_model_env="OPENAI_TOOLCALL_MODEL",
|
|
classification_model_env="OPENAI_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="codex",
|
|
label="OpenAI Codex CLI",
|
|
group="Hosted providers",
|
|
api_key_env="",
|
|
model_env="CODEX_MODEL",
|
|
default_model="",
|
|
models=CODEX_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_codex_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="openrouter",
|
|
label="OpenRouter",
|
|
group="Hosted providers",
|
|
api_key_env="OPENROUTER_API_KEY",
|
|
model_env="OPENROUTER_REASONING_MODEL",
|
|
default_model=OPENROUTER_REASONING_MODEL,
|
|
models=OPENROUTER_MODELS,
|
|
legacy_model_env="OPENROUTER_MODEL",
|
|
toolcall_model_env="OPENROUTER_TOOLCALL_MODEL",
|
|
classification_model_env="OPENROUTER_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="deepseek",
|
|
label="DeepSeek",
|
|
group="Hosted providers",
|
|
api_key_env="DEEPSEEK_API_KEY",
|
|
model_env="DEEPSEEK_REASONING_MODEL",
|
|
default_model=DEEPSEEK_REASONING_MODEL,
|
|
models=DEEPSEEK_MODELS,
|
|
legacy_model_env="DEEPSEEK_MODEL",
|
|
toolcall_model_env="DEEPSEEK_TOOLCALL_MODEL",
|
|
classification_model_env="DEEPSEEK_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="gemini",
|
|
label="Google Gemini API key",
|
|
group="Hosted providers",
|
|
api_key_env="GEMINI_API_KEY",
|
|
model_env="GEMINI_REASONING_MODEL",
|
|
default_model=GEMINI_REASONING_MODEL,
|
|
models=GEMINI_MODELS,
|
|
legacy_model_env="GEMINI_MODEL",
|
|
toolcall_model_env="GEMINI_TOOLCALL_MODEL",
|
|
classification_model_env="GEMINI_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="gemini-cli",
|
|
label="Google Gemini CLI",
|
|
group="Hosted providers",
|
|
api_key_env="",
|
|
model_env="GEMINI_CLI_MODEL",
|
|
default_model="",
|
|
models=GEMINI_CLI_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_gemini_cli_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="antigravity-cli",
|
|
label="Google Antigravity CLI",
|
|
group="Hosted providers",
|
|
api_key_env="",
|
|
model_env="ANTIGRAVITY_CLI_MODEL",
|
|
default_model="",
|
|
models=ANTIGRAVITY_CLI_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_antigravity_cli_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="nvidia",
|
|
label="NVIDIA NIM",
|
|
group="Hosted providers",
|
|
api_key_env="NVIDIA_API_KEY",
|
|
model_env="NVIDIA_REASONING_MODEL",
|
|
default_model=NVIDIA_REASONING_MODEL,
|
|
models=NVIDIA_MODELS,
|
|
legacy_model_env="NVIDIA_MODEL",
|
|
toolcall_model_env="NVIDIA_TOOLCALL_MODEL",
|
|
classification_model_env="NVIDIA_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="minimax",
|
|
label="MiniMax",
|
|
group="Hosted providers",
|
|
api_key_env="MINIMAX_API_KEY",
|
|
model_env="MINIMAX_REASONING_MODEL",
|
|
default_model=MINIMAX_REASONING_MODEL,
|
|
models=MINIMAX_MODELS,
|
|
legacy_model_env="MINIMAX_MODEL",
|
|
toolcall_model_env="MINIMAX_TOOLCALL_MODEL",
|
|
classification_model_env="MINIMAX_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="bedrock",
|
|
label="Amazon Bedrock (IAM auth)",
|
|
group="Hosted providers",
|
|
# Intentionally empty: Bedrock authenticates via the IAM credential
|
|
# chain (env, ~/.aws/credentials, instance profile) — no API key to
|
|
# prompt for. Empty string is safe: every downstream check uses
|
|
# ``bool(provider.api_key_env)`` or ``.get()`` (never subscript).
|
|
api_key_env="",
|
|
model_env="BEDROCK_REASONING_MODEL",
|
|
default_model=BEDROCK_REASONING_MODEL,
|
|
models=BEDROCK_MODELS,
|
|
toolcall_model_env="BEDROCK_TOOLCALL_MODEL",
|
|
classification_model_env="BEDROCK_CLASSIFICATION_MODEL",
|
|
credential_label="AWS region (uses IAM credentials)",
|
|
credential_secret=False,
|
|
# credential_kind="none" causes flow.py to skip the credential prompt
|
|
# entirely. Region is picked up from AWS_DEFAULT_REGION / ~/.aws/config.
|
|
credential_kind="none",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="groq",
|
|
label="Groq API key",
|
|
group="Hosted providers",
|
|
api_key_env="GROQ_API_KEY",
|
|
model_env="GROQ_REASONING_MODEL",
|
|
default_model=GROQ_REASONING_MODEL,
|
|
models=GROQ_MODELS,
|
|
legacy_model_env="GROQ_MODEL",
|
|
toolcall_model_env="GROQ_TOOLCALL_MODEL",
|
|
classification_model_env="GROQ_CLASSIFICATION_MODEL",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="azure-openai",
|
|
label="Azure OpenAI",
|
|
group="Hosted providers",
|
|
api_key_env="AZURE_OPENAI_API_KEY",
|
|
model_env="AZURE_OPENAI_REASONING_MODEL",
|
|
default_model=AZURE_OPENAI_REASONING_MODEL,
|
|
models=AZURE_OPENAI_MODELS,
|
|
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",
|
|
credential_default="https://your-resource.openai.azure.com",
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="grok-cli",
|
|
label="xAI Grok Build CLI",
|
|
group="Hosted providers",
|
|
api_key_env="",
|
|
model_env="GROK_CLI_MODEL",
|
|
default_model="",
|
|
models=GROK_CLI_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_grok_cli_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="cursor",
|
|
label="Cursor Agent CLI",
|
|
group="Local CLI providers",
|
|
api_key_env="",
|
|
model_env="CURSOR_MODEL",
|
|
default_model="auto",
|
|
models=CURSOR_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_cursor_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="opencode",
|
|
label="OpenCode CLI",
|
|
group="Local CLI providers",
|
|
api_key_env="",
|
|
model_env="OPENCODE_MODEL",
|
|
default_model="",
|
|
models=OPENCODE_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_opencode_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="kimi",
|
|
label="Kimi Code CLI",
|
|
group="Local CLI providers",
|
|
api_key_env="",
|
|
model_env="KIMI_MODEL",
|
|
default_model="",
|
|
models=KIMI_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_kimi_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="copilot",
|
|
label="GitHub Copilot CLI",
|
|
group="Local CLI providers",
|
|
api_key_env="",
|
|
model_env="COPILOT_MODEL",
|
|
default_model="",
|
|
models=COPILOT_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_copilot_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="pi",
|
|
label="Pi CLI (pi.dev, BYOK multi-provider)",
|
|
group="Local CLI providers",
|
|
api_key_env="",
|
|
model_env="PI_MODEL",
|
|
default_model="",
|
|
models=PI_MODELS,
|
|
credential_kind="cli",
|
|
credential_secret=False,
|
|
adapter_factory=_pi_adapter_factory,
|
|
allow_custom_models=True,
|
|
),
|
|
ProviderOption(
|
|
value="ollama",
|
|
label="Ollama (local)",
|
|
group="Local providers",
|
|
api_key_env="OLLAMA_HOST",
|
|
model_env="OLLAMA_MODEL",
|
|
default_model=DEFAULT_OLLAMA_MODEL,
|
|
models=OLLAMA_MODELS,
|
|
credential_label="host URL",
|
|
credential_secret=False,
|
|
credential_default=DEFAULT_OLLAMA_HOST,
|
|
credential_kind="host",
|
|
allow_custom_models=True,
|
|
),
|
|
)
|
|
|
|
PROVIDER_BY_VALUE = {provider.value: provider for provider in SUPPORTED_PROVIDERS}
|