feat: /provider command + fix gateway bugs + harden parse_model_input
/provider command (CLI + gateway):
Shows all providers with auth status (✓/✗), aliases, and active marker.
Users can now discover what provider names work with provider:model syntax.
Gateway bugs fixed:
- Config was saved even when validation.persist=False (told user 'session
only' but actually persisted the unvalidated model)
- HERMES_INFERENCE_PROVIDER env var not set on provider switch, causing
the switch to be silently overridden if that env var was already set
parse_model_input hardened:
- Colon only treated as provider delimiter if left side is a recognized
provider name or alias. 'anthropic/claude-3.5-sonnet:beta' now passes
through as a model name instead of trying provider='anthropic/claude-3.5-sonnet'.
- HTTP URLs, random colons no longer misinterpreted.
56 tests passing across model validation, CLI commands, and integration.
This commit is contained in:
parent
34792dd907
commit
666f2dd486
6 changed files with 169 additions and 20 deletions
29
cli.py
29
cli.py
|
|
@ -2161,6 +2161,35 @@ class HermesCLI:
|
|||
print(" Usage: /model <model-name>")
|
||||
print(" /model provider:model-name (to switch provider)")
|
||||
print(" Example: /model openrouter:anthropic/claude-sonnet-4.5")
|
||||
print(" See /provider for available providers")
|
||||
elif cmd_lower == "/provider":
|
||||
from hermes_cli.models import list_available_providers, normalize_provider, _PROVIDER_LABELS
|
||||
from hermes_cli.auth import resolve_provider as _resolve_provider
|
||||
# Resolve current provider
|
||||
raw_provider = normalize_provider(self.provider)
|
||||
if raw_provider == "auto":
|
||||
try:
|
||||
current = _resolve_provider(
|
||||
self.requested_provider,
|
||||
explicit_api_key=self._explicit_api_key,
|
||||
explicit_base_url=self._explicit_base_url,
|
||||
)
|
||||
except Exception:
|
||||
current = "openrouter"
|
||||
else:
|
||||
current = raw_provider
|
||||
current_label = _PROVIDER_LABELS.get(current, current)
|
||||
print(f"\n Current provider: {current_label} ({current})\n")
|
||||
providers = list_available_providers()
|
||||
print(" Available providers:")
|
||||
for p in providers:
|
||||
marker = " ← active" if p["id"] == current else ""
|
||||
auth = "✓" if p["authenticated"] else "✗"
|
||||
aliases = f" (also: {', '.join(p['aliases'])})" if p["aliases"] else ""
|
||||
print(f" [{auth}] {p['id']:<14} {p['label']}{aliases}{marker}")
|
||||
print()
|
||||
print(" Switch: /model provider:model-name")
|
||||
print(" Setup: hermes setup")
|
||||
elif cmd_lower.startswith("/prompt"):
|
||||
# Use original case so prompt text isn't lowercased
|
||||
self._handle_prompt_command(cmd_original)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue