mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-18 04:41:56 +00:00
fix(providers): set User-Agent on ProviderProfile.fetch_models
Some catalog endpoints (OpenCode Zen, etc.) sit behind a WAF that returns 403 for the default Python-urllib/<ver> User-Agent. The generic profile-based live fetch in providers/base.py was silently failing for any such provider — falling through to the static catalog and missing newly-launched models. Set a generic 'hermes-cli/<version>' UA on the catalog probe so every api_key provider profile benefits. Verified live against opencode-zen: before this change, profile.fetch_models() raised HTTP 403; after, it returns 42 models including gpt-5.5, gpt-5.5-pro, kimi-k2.6, glm-5.1 and the *-free variants the static catalog doesn't list. Also strip the now-stale comment in validate_requested_model() claiming opencode-zen's /models returns 404 against the HTML marketing site — the API endpoint at /zen/v1/models returns 200 with valid JSON. Surfaced by #2651 (@aashizpoudel) — fixes the same user-facing gap their PR targeted, applied at the right layer so all api_key provider profiles get live catalogs through the same code path. Co-authored-by: Aashish Poudel <mr.aashiz@gmail.com>
This commit is contained in:
parent
647cc0bb0d
commit
5360b54244
3 changed files with 26 additions and 7 deletions
|
|
@ -3702,13 +3702,12 @@ def validate_requested_model(
|
||||||
|
|
||||||
# Static-catalog fallback: when the /models probe was unreachable,
|
# Static-catalog fallback: when the /models probe was unreachable,
|
||||||
# validate against the curated list from provider_model_ids() — same
|
# validate against the curated list from provider_model_ids() — same
|
||||||
# pattern as the openai-codex and minimax branches above. This fixes
|
# pattern as the openai-codex and minimax branches above. This keeps
|
||||||
# /model switches in the gateway for providers like opencode-go and
|
# /model switches working in the gateway for providers whose /models
|
||||||
# opencode-zen whose /models endpoint returns 404 against the HTML
|
# endpoint is temporarily unreachable or returns a non-JSON payload.
|
||||||
# marketing site. Without this block, validate_requested_model would
|
# Without this block, validate_requested_model would reject every model
|
||||||
# reject every model on such providers, switch_model() would return
|
# on such providers, switch_model() would return success=False, and
|
||||||
# success=False, and the gateway would never write to
|
# the gateway would never write to _session_model_overrides.
|
||||||
# _session_model_overrides.
|
|
||||||
provider_label = _PROVIDER_LABELS.get(normalized, normalized)
|
provider_label = _PROVIDER_LABELS.get(normalized, normalized)
|
||||||
try:
|
try:
|
||||||
catalog_models = provider_model_ids(normalized)
|
catalog_models = provider_model_ids(normalized)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,20 @@ logger = logging.getLogger(__name__)
|
||||||
OMIT_TEMPERATURE = object()
|
OMIT_TEMPERATURE = object()
|
||||||
|
|
||||||
|
|
||||||
|
def _profile_user_agent() -> str:
|
||||||
|
"""Return a ``hermes-cli/<version>`` UA string, with a stable fallback.
|
||||||
|
|
||||||
|
Used by ``ProviderProfile.fetch_models`` so the catalog probe is not
|
||||||
|
served the default ``Python-urllib/<ver>`` UA — some providers
|
||||||
|
(OpenCode Zen, etc.) sit behind a WAF that returns 403 for that.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from hermes_cli import __version__ as _ver # lazy: avoid layer cycle at import time
|
||||||
|
return f"hermes-cli/{_ver}"
|
||||||
|
except Exception:
|
||||||
|
return "hermes-cli"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ProviderProfile:
|
class ProviderProfile:
|
||||||
"""Base provider profile — subclass or instantiate with overrides."""
|
"""Base provider profile — subclass or instantiate with overrides."""
|
||||||
|
|
@ -153,6 +167,10 @@ class ProviderProfile:
|
||||||
if api_key:
|
if api_key:
|
||||||
req.add_header("Authorization", f"Bearer {api_key}")
|
req.add_header("Authorization", f"Bearer {api_key}")
|
||||||
req.add_header("Accept", "application/json")
|
req.add_header("Accept", "application/json")
|
||||||
|
# Some providers (e.g. OpenCode Zen) sit behind a WAF that blocks
|
||||||
|
# the default ``Python-urllib/<ver>`` User-Agent. Set a generic
|
||||||
|
# hermes-cli UA so the catalog endpoint is reachable.
|
||||||
|
req.add_header("User-Agent", _profile_user_agent())
|
||||||
for k, v in self.default_headers.items():
|
for k, v in self.default_headers.items():
|
||||||
req.add_header(k, v)
|
req.add_header(k, v)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,8 @@ AUTHOR_MAP = {
|
||||||
"altriatree@gmail.com": "TruaShamu",
|
"altriatree@gmail.com": "TruaShamu",
|
||||||
"m@mobrienv.dev": "mikeyobrien",
|
"m@mobrienv.dev": "mikeyobrien",
|
||||||
"qiyin.zuo@pcitc.com": "qiyin-code",
|
"qiyin.zuo@pcitc.com": "qiyin-code",
|
||||||
|
"mr.aashiz@gmail.com": "aashizpoudel",
|
||||||
|
"30312689+aashizpoudel@users.noreply.github.com": "aashizpoudel",
|
||||||
"oleksii.lisikh@gmail.com": "olisikh",
|
"oleksii.lisikh@gmail.com": "olisikh",
|
||||||
"jeremy@geocaching.com": "outdoorsea",
|
"jeremy@geocaching.com": "outdoorsea",
|
||||||
"leone.parise@gmail.com": "leoneparise",
|
"leone.parise@gmail.com": "leoneparise",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue