diff --git a/hermes_cli/auth_commands.py b/hermes_cli/auth_commands.py index 09f520982a..988895bfc5 100644 --- a/hermes_cli/auth_commands.py +++ b/hermes_cli/auth_commands.py @@ -83,7 +83,8 @@ _PROVIDER_ALIASES = { def _normalize_provider(provider: str) -> str: normalized = (provider or "").strip().lower() - return _PROVIDER_ALIASES.get(normalized) or _resolve_custom_provider_input(normalized) or normalized + return (_PROVIDER_ALIASES.get(normalized) or _resolve_custom_provider_input(normalized) + or auth_mod._plugin_aliases().get(normalized) or normalized) def _migrate_legacy_custom_pool_key(provider: str, legacy_key: str) -> None: diff --git a/hermes_cli/models_catalog_static.py b/hermes_cli/models_catalog_static.py index c6461cdb44..f74f487819 100644 --- a/hermes_cli/models_catalog_static.py +++ b/hermes_cli/models_catalog_static.py @@ -463,7 +463,7 @@ _PROVIDER_ALIASES = dict(( ("grok-oauth", "xai-oauth"), ("xai-oauth", "xai-oauth"), ("x-ai-oauth", "xai-oauth"), ("xai-grok-oauth", "xai-oauth"), ("x-ai", "xai"), ("x.ai", "xai"), ("nim", "nvidia"), ("nvidia-nim", "nvidia"), ("build-nvidia", "nvidia"), ("nemotron", "nvidia"), ("lmstudio", "lmstudio"), ("lm-studio", "lmstudio"), - ("lm_studio", "lmstudio"), + ("lm_studio", "lmstudio"), ("chatgpt", "openai-codex"), ("chatgpt-codex", "openai-codex"), ("ollama", "custom"), # bare "ollama" = local; use "ollama-cloud" for cloud ("ollama_cloud", "ollama-cloud"), )) diff --git a/tests/hermes_cli/test_api_key_providers.py b/tests/hermes_cli/test_api_key_providers.py index 97c262de33..480bf0681c 100644 --- a/tests/hermes_cli/test_api_key_providers.py +++ b/tests/hermes_cli/test_api_key_providers.py @@ -223,6 +223,19 @@ class TestResolveProvider: assert resolve_provider("chatgpt") == "openai-codex" assert resolve_provider("chatgpt-codex") == "openai-codex" + def test_alias_chatgpt_every_alias_table(self): + """Issue #95794: the runtime (providers.py), the /model parser (models_catalog_static via + parse_model_input) and ``hermes auth login`` all resolve the ChatGPT alias, not just auth.""" + from hermes_cli.providers import normalize_provider + from hermes_cli.models import parse_model_input + from hermes_cli.auth_commands import _normalize_provider + + assert normalize_provider("chatgpt") == "openai-codex" + assert normalize_provider("chatgpt-codex") == "openai-codex" + assert parse_model_input("chatgpt:gpt-5.5", "openrouter") == ("openai-codex", "gpt-5.5") + assert parse_model_input("chatgpt-codex:gpt-5.5", "openrouter") == ("openai-codex", "gpt-5.5") + assert _normalize_provider("chatgpt") == "openai-codex" + def test_alias_github_copilot(self): assert resolve_provider("github-copilot") == "copilot" diff --git a/website/docs/reference/cli-commands.md b/website/docs/reference/cli-commands.md index 72ac60be26..e0f51a63f9 100644 --- a/website/docs/reference/cli-commands.md +++ b/website/docs/reference/cli-commands.md @@ -118,7 +118,7 @@ Common options: | `--oneshot` | With `-q`/`--query-file`: answer the query and exit (the pre-0.21 single-query behavior) instead of seeding an interactive session. Implied on non-TTY stdio and by `-Q`. | | `-m`, `--model ` | Override the model for this run. | | `-t`, `--toolsets ` | Enable a comma-separated set of toolsets. | -| `--provider ` | Force a provider: `auto`, `openrouter`, `nous`, `openai-codex`, `copilot-acp`, `copilot`, `anthropic`, `gemini`, `huggingface`, `novita` (aliases `novita-ai`, `novitaai`), `openai-api`, `zai`, `kimi-coding`, `kimi-coding-cn`, `minimax`, `minimax-cn`, `minimax-oauth`, `kilocode`, `xiaomi`, `arcee`, `gmi`, `upstage` (alias `solar`), `alibaba`, `alibaba-cn`, `alibaba-coding-plan` (alias `alibaba_coding`), `alibaba-coding-plan-cn`, `alibaba-token-plan`, `alibaba-token-plan-cn`, `deepseek`, `nvidia`, `ollama-cloud`, `xai` (alias `grok`), `xai-oauth` (alias `grok-oauth`), `qwen-oauth`, `bedrock`, `opencode-zen`, `opencode-go`, `commandcode`, `commandcode-anthropic`, `ai-gateway`, `azure-foundry`, `lmstudio`, `stepfun`, `tencent-tokenhub` (alias `tencent`, `tokenhub`), `router` (aliases `ramp-router`, `ramp`), `nebius-token-factory` (aliases `nebius`, `nebius-tf`, `tokenfactory`), `tencent-tokenplan` (aliases `tokenplan`, `tencent-lkeap`). | +| `--provider ` | Force a provider: `auto`, `openrouter`, `nous`, `openai-codex` (aliases `chatgpt`, `chatgpt-codex`), `copilot-acp`, `copilot`, `anthropic`, `gemini`, `huggingface`, `novita` (aliases `novita-ai`, `novitaai`), `openai-api`, `zai`, `kimi-coding`, `kimi-coding-cn`, `minimax`, `minimax-cn`, `minimax-oauth`, `kilocode`, `xiaomi`, `arcee`, `gmi`, `upstage` (alias `solar`), `alibaba`, `alibaba-cn`, `alibaba-coding-plan` (alias `alibaba_coding`), `alibaba-coding-plan-cn`, `alibaba-token-plan`, `alibaba-token-plan-cn`, `deepseek`, `nvidia`, `ollama-cloud`, `xai` (alias `grok`), `xai-oauth` (alias `grok-oauth`), `qwen-oauth`, `bedrock`, `opencode-zen`, `opencode-go`, `commandcode`, `commandcode-anthropic`, `ai-gateway`, `azure-foundry`, `lmstudio`, `stepfun`, `tencent-tokenhub` (alias `tencent`, `tokenhub`), `router` (aliases `ramp-router`, `ramp`), `nebius-token-factory` (aliases `nebius`, `nebius-tf`, `tokenfactory`), `tencent-tokenplan` (aliases `tokenplan`, `tencent-lkeap`). | | `-s`, `--skills ` | Preload one or more skills for the session (can be repeated or comma-separated). | | `-v`, `--verbose` | Verbose output. | | `-Q`, `--quiet` | Programmatic mode: suppress banner/spinner/tool previews. |