refactor(hermes_cli): provider cluster — shared _overlay_pdef, pool-select guard collapse, docstring compaction (WHY kept)

This commit is contained in:
Teknium
2026-09-02 22:14:12 -07:00
parent d211f8562c
commit e789d79cfe
4 changed files with 96 additions and 132 deletions
+26 -35
View File
@@ -1,10 +1,9 @@
"""Shared runtime provider resolution for CLI, gateway, cron, and helpers.
This module owns the resolution ORDER (:func:`resolve_runtime_provider`), the api_mode / base_url
helpers and the pool / OAuth / explicit paths. Custom-provider lookup lives in
:mod:`hermes_cli.runtime_provider_custom`; Azure Foundry, OpenRouter/bare-custom, Bedrock and
external-process builders in :mod:`hermes_cli.runtime_provider_backends`. Both are re-exported
here so ``hermes_cli.runtime_provider.<name>`` imports and test patches keep working."""
"""Shared runtime provider resolution for CLI, gateway, cron, and helpers: the resolution ORDER
(:func:`resolve_runtime_provider`), api_mode / base_url helpers and the pool / OAuth / explicit paths.
Custom-provider lookup lives in :mod:`hermes_cli.runtime_provider_custom`; Azure Foundry,
OpenRouter/bare-custom, Bedrock and external-process builders in
:mod:`hermes_cli.runtime_provider_backends` — both re-exported here so
``hermes_cli.runtime_provider.<name>`` imports and test patches keep working."""
from __future__ import annotations
@@ -72,12 +71,11 @@ def _resolves_to_custom(name: str) -> bool:
def _config_base_url_trustworthy_for_bare_custom(cfg_base_url: str, cfg_provider: str) -> bool:
"""Whether ``model.base_url`` may back bare ``custom`` runtime resolution.
The model picker can select Custom while ``model.provider`` still reflects a previous provider.
Non-loopback URLs are rejected unless the YAML provider is already ``custom`` or a local-server
alias (ollama/vllm/llamacpp — else a legit LAN ollama endpoint silently falls through to
OpenRouter), so a stale OpenRouter/Z.ai base_url cannot hijack local sessions."""
"""Whether ``model.base_url`` may back bare ``custom`` runtime resolution. The picker can select
Custom while ``model.provider`` still names a previous provider, so non-loopback URLs are rejected
unless the YAML provider is already ``custom`` or a local-server alias (ollama/vllm/llamacpp —
else a legit LAN ollama endpoint falls through to OpenRouter): a stale OpenRouter/Z.ai base_url
cannot hijack local sessions."""
cfg_provider_norm = (cfg_provider or "").strip().lower()
bu = (cfg_base_url or "").strip()
if not bu:
@@ -105,11 +103,10 @@ _VALID_API_MODES = {"chat_completions", "codex_responses", "anthropic_messages",
def _detect_api_mode_for_url(base_url: str) -> Optional[str]:
"""Auto-detect api_mode from the resolved base URL, or None.
Exact-hostname matches reject lookalike subdomains (api.anthropic.com.attacker.test) and
path-segment spoofing (proxy.test/api.anthropic.com/v1). Official OpenAI hosts (incl. the
data-residency us./eu. regional hosts) need Responses for GPT-5.x tool calls with reasoning."""
"""Auto-detect api_mode from the resolved base URL, or None. Exact-hostname matches reject
lookalike subdomains (api.anthropic.com.attacker.test) and path-segment spoofing
(proxy.test/api.anthropic.com/v1). Official OpenAI hosts (incl. us./eu. data-residency hosts)
need Responses for GPT-5.x tool calls with reasoning."""
normalized = (base_url or "").strip().lower().rstrip("/")
hostname = base_url_hostname(base_url)
mandated = _HOST_MANDATED_API_MODES.get(hostname)
@@ -214,7 +211,6 @@ def _configured_or_fallback_api_mode(
provider: str, model_cfg: Dict[str, Any], base_url: str, effective_model: Any, *, opencode_by_model: bool
) -> str:
"""Persisted ``model.api_mode`` when it belongs to this provider, else URL/transport fallback.
OpenCode Zen/Go serve both anthropic_messages and chat_completions models, so (when
``opencode_by_model``) their mode is always re-derived from the effective model."""
if opencode_by_model and _models.opencode_provider_family(provider) is not None:
@@ -320,10 +316,9 @@ def _host_derived_api_key(base_url: str) -> str:
def _host_gated_env_key_candidates(base_url: str, *, ollama: bool) -> list:
"""Env API keys gated on their authoritative hosts, then the host-derived ``<VENDOR>_API_KEY``.
Sending OPENAI/OPENROUTER/OLLAMA keys to an unrelated endpoint leaks credentials
(GHSA-76xc-57q6-vm5m); match on HOST, not substring. ``_host_derived_api_key`` skips OLLAMA,
so callers that want it opt in via ``ollama``."""
(GHSA-76xc-57q6-vm5m); match on HOST, not substring. ``_host_derived_api_key`` skips OLLAMA, so
callers that want it opt in via ``ollama``."""
is_openai = base_url_host_matches(base_url, "openai.com") or base_url_host_matches(base_url, "openai.azure.com")
candidates = []
if ollama:
@@ -570,14 +565,12 @@ def _resolve_from_pool(
if not (pool and pool.has_credentials()):
return None
entry = pool.select()
pool_api_key = _pool_entry_api_key(entry) if entry is not None else ""
if provider == "nous" and entry is not None:
if entry is None:
return None
pool_api_key = _pool_entry_api_key(entry)
if provider == "nous":
entry, pool_api_key = _refresh_nous_pool_entry(pool, entry, pool_api_key)
if (
entry is not None
and pool_api_key
and credential_pool_matches_provider(pool, provider, base_url=_pool_entry_base_url(entry))
):
if pool_api_key and credential_pool_matches_provider(pool, provider, base_url=_pool_entry_base_url(entry)):
return _resolve_runtime_from_pool_entry(
provider=provider, entry=entry, requested_provider=requested_provider,
model_cfg=model_cfg, pool=pool, target_model=target_model,
@@ -939,9 +932,8 @@ def resolve_runtime_provider(
*, requested: Optional[str] = None, explicit_api_key: Optional[str] = None,
explicit_base_url: Optional[str] = None, target_model: Optional[str] = None,
) -> Dict[str, Any]:
"""Resolve runtime provider credentials for agent execution.
Ladder (order is behavior — each rung returns or raises, else falls to the next):
"""Resolve runtime provider credentials for agent execution. Ladder (order is behavior — each
rung returns or raises, else falls to the next):
1. disabled-provider guard (``providers.<name>.enabled: false``)
2. requested-name shortcuts: moa, anthropic@azure, azure-foundry, vertex
3. named custom provider / llamacpp alias / bare-custom direct alias
@@ -951,9 +943,8 @@ def resolve_runtime_provider(
7. OAuth specs (nous/codex/xai/qwen; "auto" swallows AuthError and logs) → minimax-oauth
→ external-process → anthropic env → bedrock → registry api_key providers
8. OpenRouter / bare-custom fallback
target_model: overrides model_cfg["default"] when computing provider-specific api_mode
(e.g. OpenCode Zen/Go where different models route through different API surfaces)."""
target_model overrides model_cfg["default"] when computing provider-specific api_mode (e.g.
OpenCode Zen/Go where different models route through different API surfaces)."""
requested_provider = resolve_requested_provider(requested)
_raise_if_provider_disabled(requested_provider)
runtime = _resolve_requested_shortcuts(requested_provider, explicit_api_key, explicit_base_url, target_model)