diff --git a/cli.py b/cli.py index a4b8c4b3..d576387b 100755 --- a/cli.py +++ b/cli.py @@ -973,6 +973,8 @@ def save_config_value(key_path: str, value: any) -> bool: return False + + # ============================================================================ # HermesCLI Class # ============================================================================ @@ -2890,6 +2892,14 @@ class HermesCLI: for mid, desc in curated: current_marker = " ← current" if (is_active and mid == self.model) else "" print(f" {mid}{current_marker}") + elif p["id"] == "custom": + from hermes_cli.models import _get_custom_base_url + custom_url = _get_custom_base_url() or os.getenv("OPENAI_BASE_URL", "") + if custom_url: + print(f" endpoint: {custom_url}") + if is_active: + print(f" model: {self.model} ← current") + print(f" (use /model custom:)") else: print(f" (use /model {p['id']}:)") print() diff --git a/gateway/run.py b/gateway/run.py index 2887ee7a..e5efbe22 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -2380,8 +2380,14 @@ class GatewayRunner: lines = [ f"🤖 **Current model:** `{current}`", f"**Provider:** {provider_label}", - "", ] + # Show custom endpoint URL when using a custom provider + if current_provider == "custom": + from hermes_cli.models import _get_custom_base_url + custom_url = _get_custom_base_url() or os.getenv("OPENAI_BASE_URL", "") + if custom_url: + lines.append(f"**Endpoint:** `{custom_url}`") + lines.append("") curated = curated_models_for_provider(current_provider) if curated: lines.append(f"**Available models ({provider_label}):**") @@ -2391,7 +2397,7 @@ class GatewayRunner: lines.append(f"• `{mid}`{label}{marker}") lines.append("") lines.append("To change: `/model model-name`") - lines.append("Switch provider: `/model provider:model-name`") + lines.append("Switch provider: `/model provider-name` or `/model provider:model-name`") return "\n".join(lines) # Parse provider:model syntax diff --git a/hermes_cli/models.py b/hermes_cli/models.py index 8463170e..495c0ca7 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -389,6 +389,7 @@ def detect_provider_for_model( Returns ``None`` when no confident match is found. Priority: + 0. Bare provider name → switch to that provider's default model 1. Direct provider with credentials (highest) 2. Direct provider without credentials → remap to OpenRouter slug 3. OpenRouter catalog match @@ -399,6 +400,21 @@ def detect_provider_for_model( name_lower = name.lower() + # --- Step 0: bare provider name typed as model --- + # If someone types `/model nous` or `/model anthropic`, treat it as a + # provider switch and pick the first model from that provider's catalog. + # Skip "custom" and "openrouter" — custom has no model catalog, and + # openrouter requires an explicit model name to be useful. + resolved_provider = _PROVIDER_ALIASES.get(name_lower, name_lower) + if resolved_provider not in {"custom", "openrouter"}: + default_models = _PROVIDER_MODELS.get(resolved_provider, []) + if ( + resolved_provider in _PROVIDER_LABELS + and default_models + and resolved_provider != normalize_provider(current_provider) + ): + return (resolved_provider, default_models[0]) + # Aggregators list other providers' models — never auto-switch TO them _AGGREGATORS = {"nous", "openrouter"}