mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-27 01:11:40 +00:00
Three independent fixes batched together: 1. hermes auth add crashes on non-interactive stdin (#10468) input() for the label prompt was called without checking isatty(). In scripted/CI environments this raised EOFError. Fix: check sys.stdin.isatty() and fall back to the computed default label. 2. Subcommand help prints twice (#10230) 'hermes dashboard -h' printed help text twice because the SystemExit(0) from argparse was caught by the fallback retry logic, which re-parsed and printed help again. Fix: re-raise SystemExit with code 0 (help/version) immediately. 3. Duplicate entries in /model picker (#10526, #9545) - Kimi showed 2x because kimi-coding and kimi-coding-cn both mapped to the same models.dev ID. Fix: track seen mdev_ids and skip aliases. - Providers could show 2-3x from case-variant slugs across the four loading paths. Fix: normalize all seen_slugs membership checks and insertions to lowercase. Closes #10468, #10230, #10526, #9545
This commit is contained in:
parent
a6ad8ace29
commit
b750c720cd
3 changed files with 28 additions and 12 deletions
|
|
@ -786,7 +786,8 @@ def list_authenticated_providers(
|
|||
from hermes_cli.models import OPENROUTER_MODELS, _PROVIDER_MODELS
|
||||
|
||||
results: List[dict] = []
|
||||
seen_slugs: set = set()
|
||||
seen_slugs: set = set() # lowercase-normalized to catch case variants (#9545)
|
||||
seen_mdev_ids: set = set() # prevent duplicate entries for aliases (e.g. kimi-coding + kimi-coding-cn)
|
||||
|
||||
data = fetch_models_dev()
|
||||
|
||||
|
|
@ -799,6 +800,11 @@ def list_authenticated_providers(
|
|||
|
||||
# --- 1. Check Hermes-mapped providers ---
|
||||
for hermes_id, mdev_id in PROVIDER_TO_MODELS_DEV.items():
|
||||
# Skip aliases that map to the same models.dev provider (e.g.
|
||||
# kimi-coding and kimi-coding-cn both → kimi-for-coding).
|
||||
# The first one with valid credentials wins (#10526).
|
||||
if mdev_id in seen_mdev_ids:
|
||||
continue
|
||||
pdata = data.get(mdev_id)
|
||||
if not isinstance(pdata, dict):
|
||||
continue
|
||||
|
|
@ -837,7 +843,8 @@ def list_authenticated_providers(
|
|||
"total_models": total,
|
||||
"source": "built-in",
|
||||
})
|
||||
seen_slugs.add(slug)
|
||||
seen_slugs.add(slug.lower())
|
||||
seen_mdev_ids.add(mdev_id)
|
||||
|
||||
# --- 2. Check Hermes-only providers (nous, openai-codex, copilot, opencode-go) ---
|
||||
from hermes_cli.providers import HERMES_OVERLAYS
|
||||
|
|
@ -849,12 +856,12 @@ def list_authenticated_providers(
|
|||
_mdev_to_hermes = {v: k for k, v in PROVIDER_TO_MODELS_DEV.items()}
|
||||
|
||||
for pid, overlay in HERMES_OVERLAYS.items():
|
||||
if pid in seen_slugs:
|
||||
if pid.lower() in seen_slugs:
|
||||
continue
|
||||
|
||||
# Resolve Hermes slug — e.g. "github-copilot" → "copilot"
|
||||
hermes_slug = _mdev_to_hermes.get(pid, pid)
|
||||
if hermes_slug in seen_slugs:
|
||||
if hermes_slug.lower() in seen_slugs:
|
||||
continue
|
||||
|
||||
# Check if credentials exist
|
||||
|
|
@ -935,8 +942,8 @@ def list_authenticated_providers(
|
|||
"total_models": total,
|
||||
"source": "hermes",
|
||||
})
|
||||
seen_slugs.add(pid)
|
||||
seen_slugs.add(hermes_slug)
|
||||
seen_slugs.add(pid.lower())
|
||||
seen_slugs.add(hermes_slug.lower())
|
||||
|
||||
# --- 2b. Cross-check canonical provider list ---
|
||||
# Catches providers that are in CANONICAL_PROVIDERS but weren't found
|
||||
|
|
@ -948,7 +955,7 @@ def list_authenticated_providers(
|
|||
_canon_provs = []
|
||||
|
||||
for _cp in _canon_provs:
|
||||
if _cp.slug in seen_slugs:
|
||||
if _cp.slug.lower() in seen_slugs:
|
||||
continue
|
||||
|
||||
# Check credentials via PROVIDER_REGISTRY (auth.py)
|
||||
|
|
@ -995,7 +1002,7 @@ def list_authenticated_providers(
|
|||
"total_models": _cp_total,
|
||||
"source": "canonical",
|
||||
})
|
||||
seen_slugs.add(_cp.slug)
|
||||
seen_slugs.add(_cp.slug.lower())
|
||||
|
||||
# --- 3. User-defined endpoints from config ---
|
||||
if user_providers and isinstance(user_providers, dict):
|
||||
|
|
@ -1068,7 +1075,7 @@ def list_authenticated_providers(
|
|||
groups[slug]["models"].append(default_model)
|
||||
|
||||
for slug, grp in groups.items():
|
||||
if slug in seen_slugs:
|
||||
if slug.lower() in seen_slugs:
|
||||
continue
|
||||
results.append({
|
||||
"slug": slug,
|
||||
|
|
@ -1080,7 +1087,7 @@ def list_authenticated_providers(
|
|||
"source": "user-config",
|
||||
"api_url": grp["api_url"],
|
||||
})
|
||||
seen_slugs.add(slug)
|
||||
seen_slugs.add(slug.lower())
|
||||
|
||||
# Sort: current provider first, then by model count descending
|
||||
results.sort(key=lambda r: (not r["is_current"], -r["total_models"]))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue