refactor(plugins/model-providers): reuse agent.reasoning_effort clamps, per-model dict tables, compact profiles
This commit is contained in:
@@ -1,28 +1,6 @@
|
||||
"""CommandCode provider profile.
|
||||
|
||||
CommandCode provides a unified API that fronts 20+ models from DeepSeek, Qwen,
|
||||
Kimi, GLM, MiniMax, StepFun, Xiaomi Mimo, Google Gemini, and OpenAI GPT — all
|
||||
accessible through either OpenAI-compatible chat completions or Anthropic
|
||||
Messages endpoints from a single base URL and API key.
|
||||
|
||||
Two provider profiles are registered:
|
||||
|
||||
``commandcode``
|
||||
``api_mode=chat_completions`` — standard OpenAI-compatible endpoint.
|
||||
Model prefix: ``deepseek/deepseek-v4-pro``, ``Qwen/Qwen3.7-Max``, etc.
|
||||
|
||||
``commandcode-anthropic``
|
||||
``api_mode=anthropic_messages`` — Anthropic Messages API-compatible.
|
||||
Model names: ``claude-sonnet-4-6``, ``claude-opus-4-7``,
|
||||
``claude-haiku-4-5-20251001``.
|
||||
|
||||
Both use the same ``COMMANDCODE_API_KEY`` env var and
|
||||
``https://api.commandcode.ai/provider/v1`` base URL. The
|
||||
``commandcode-anthropic`` profile relies on ``agent/anthropic_adapter.py``
|
||||
recognizing the ``api.commandcode.ai`` hostname for Bearer auth (the
|
||||
CommandCode /anthropic endpoint uses ``Authorization: Bearer``, not
|
||||
Anthropic's native ``x-api-key`` header).
|
||||
"""
|
||||
"""CommandCode provider profiles: ``commandcode`` (chat_completions) and
|
||||
``commandcode-anthropic`` (anthropic_messages, Bearer auth — see
|
||||
``agent/anthropic_adapter.py``). Same key and base URL for both."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -35,74 +13,63 @@ from providers.base import ProviderProfile, _profile_user_agent
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# ── Shared constants ──────────────────────────────────────────────────────────
|
||||
_COMMANDCODE_BASE = "https://api.commandcode.ai/provider/v1"
|
||||
_COMMANDCODE_MODELS_URL = f"{_COMMANDCODE_BASE}/models"
|
||||
# Both profiles authenticate with the same key; each carries its own base-URL
|
||||
# override var so each renders its own card on the desktop Keys tab (rows are
|
||||
# keyed by env var, and the shared API key attributes to the first profile).
|
||||
_COMMANDCODE_ENV = ("COMMANDCODE_API_KEY", "COMMANDCODE_BASE_URL")
|
||||
_COMMANDCODE_ANTHROPIC_ENV = ("COMMANDCODE_API_KEY", "COMMANDCODE_ANTHROPIC_BASE_URL")
|
||||
|
||||
|
||||
def _fetch_commandcode_models(
|
||||
timeout: float = 10.0,
|
||||
base_url: str | None = None,
|
||||
) -> list[str] | None:
|
||||
"""Fetch the live model list from the CommandCode /models endpoint.
|
||||
"""Fetch model IDs from the public (unauthenticated) /models endpoint.
|
||||
|
||||
Returns a flat list of model IDs or None on failure.
|
||||
No auth required — the public models endpoint is open.
|
||||
|
||||
``base_url`` overrides the endpoint only when the caller passed a URL
|
||||
that differs from the default ``_COMMANDCODE_BASE`` (a user-configured
|
||||
``model.base_url`` / ``COMMANDCODE_BASE_URL`` pointing at a proxy or
|
||||
custom deployment). The picker passes base_url unconditionally, falling
|
||||
back to the profile default — equality means "not customised".
|
||||
The picker passes base_url unconditionally, so only a value differing from
|
||||
the default counts as a customised endpoint.
|
||||
"""
|
||||
caller_base = (base_url or "").strip()
|
||||
if caller_base and caller_base.rstrip("/") != _COMMANDCODE_BASE.rstrip("/"):
|
||||
models_url = caller_base.rstrip("/") + "/models"
|
||||
else:
|
||||
models_url = _COMMANDCODE_MODELS_URL
|
||||
caller_base = (base_url or "").strip().rstrip("/")
|
||||
custom = caller_base and caller_base != _COMMANDCODE_BASE
|
||||
models_url = caller_base + "/models" if custom else _COMMANDCODE_MODELS_URL
|
||||
try:
|
||||
req = urllib.request.Request(models_url)
|
||||
req.add_header("Accept", "application/json")
|
||||
req.add_header("User-Agent", _profile_user_agent())
|
||||
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
||||
data = json.loads(resp.read().decode())
|
||||
# Response shape: {"object": "list", "data": [{"id": "..."}, ...]}
|
||||
return [
|
||||
m["id"]
|
||||
for m in data.get("data", [])
|
||||
if isinstance(m, dict) and "id" in m
|
||||
]
|
||||
return [m["id"] for m in data.get("data", []) if isinstance(m, dict) and "id" in m]
|
||||
except Exception as exc:
|
||||
logger.debug("fetch_models(commandcode): %s", exc)
|
||||
return None
|
||||
|
||||
|
||||
# ── Chat Completions profile ──────────────────────────────────────────────────
|
||||
|
||||
class CommandCodeProfile(ProviderProfile):
|
||||
"""CommandCode — OpenAI-compatible chat completions endpoint."""
|
||||
|
||||
def fetch_models(
|
||||
self,
|
||||
*,
|
||||
api_key: str | None = None,
|
||||
base_url: str | None = None,
|
||||
timeout: float = 8.0,
|
||||
self, *, api_key: str | None = None, base_url: str | None = None, timeout: float = 8.0
|
||||
) -> list[str] | None:
|
||||
"""Fetch from the public CommandCode /models endpoint."""
|
||||
return _fetch_commandcode_models(timeout=timeout, base_url=base_url)
|
||||
|
||||
|
||||
class CommandCodeAnthropicProfile(ProviderProfile):
|
||||
"""CommandCode — Anthropic Messages API-compatible endpoint."""
|
||||
|
||||
def fetch_models(
|
||||
self, *, api_key: str | None = None, base_url: str | None = None, timeout: float = 8.0
|
||||
) -> list[str] | None:
|
||||
"""Public /models endpoint, filtered to Anthropic-family models."""
|
||||
all_models = _fetch_commandcode_models(timeout=timeout, base_url=base_url)
|
||||
if all_models is None:
|
||||
return None
|
||||
return [m for m in all_models if m.startswith("claude-")]
|
||||
|
||||
|
||||
commandcode = CommandCodeProfile(
|
||||
name="commandcode",
|
||||
aliases=("commandcode-chat",),
|
||||
api_mode="chat_completions",
|
||||
env_vars=_COMMANDCODE_ENV,
|
||||
# Same key as the anthropic profile; distinct base-URL override vars so each
|
||||
# profile renders its own card on the desktop Keys tab (rows keyed by env var).
|
||||
env_vars=("COMMANDCODE_API_KEY", "COMMANDCODE_BASE_URL"),
|
||||
display_name="CommandCode",
|
||||
description="CommandCode — 20+ models via OpenAI-compatible API",
|
||||
signup_url="https://commandcode.ai/",
|
||||
@@ -124,53 +91,19 @@ commandcode = CommandCodeProfile(
|
||||
default_aux_model="deepseek/deepseek-v4-flash",
|
||||
)
|
||||
|
||||
|
||||
# ── Anthropic Messages profile ────────────────────────────────────────────────
|
||||
|
||||
class CommandCodeAnthropicProfile(ProviderProfile):
|
||||
"""CommandCode — Anthropic Messages API-compatible endpoint.
|
||||
|
||||
Uses Bearer auth (same API key), not Anthropic's native x-api-key header.
|
||||
``agent/anthropic_adapter.py`` must recognize ``api.commandcode.ai``
|
||||
as a Bearer-auth domain for this to work.
|
||||
"""
|
||||
|
||||
def fetch_models(
|
||||
self,
|
||||
*,
|
||||
api_key: str | None = None,
|
||||
base_url: str | None = None,
|
||||
timeout: float = 8.0,
|
||||
) -> list[str] | None:
|
||||
"""Fetch from the public CommandCode /models endpoint.
|
||||
|
||||
Filter to Anthropic-family models only (claude-*).
|
||||
"""
|
||||
all_models = _fetch_commandcode_models(timeout=timeout, base_url=base_url)
|
||||
if all_models is None:
|
||||
return None
|
||||
return [m for m in all_models if m.startswith("claude-")]
|
||||
|
||||
|
||||
commandcode_anthropic = CommandCodeAnthropicProfile(
|
||||
name="commandcode-anthropic",
|
||||
aliases=("commandcode-claude",),
|
||||
api_mode="anthropic_messages",
|
||||
env_vars=_COMMANDCODE_ANTHROPIC_ENV,
|
||||
env_vars=("COMMANDCODE_API_KEY", "COMMANDCODE_ANTHROPIC_BASE_URL"),
|
||||
display_name="CommandCode (Anthropic)",
|
||||
description="CommandCode — Claude models via Anthropic Messages API",
|
||||
signup_url="https://commandcode.ai/",
|
||||
base_url=_COMMANDCODE_BASE,
|
||||
models_url=_COMMANDCODE_MODELS_URL,
|
||||
fallback_models=(
|
||||
"claude-sonnet-4-6",
|
||||
"claude-opus-4-7",
|
||||
"claude-haiku-4-5-20251001",
|
||||
),
|
||||
fallback_models=("claude-sonnet-4-6", "claude-opus-4-7", "claude-haiku-4-5-20251001"),
|
||||
default_aux_model="claude-haiku-4-5-20251001",
|
||||
)
|
||||
|
||||
|
||||
# ── Registration ──────────────────────────────────────────────────────────────
|
||||
register_provider(commandcode)
|
||||
register_provider(commandcode_anthropic)
|
||||
|
||||
Reference in New Issue
Block a user