diff --git a/agent/auxiliary_client.py b/agent/auxiliary_client.py index f470e142a..648c4acef 100644 --- a/agent/auxiliary_client.py +++ b/agent/auxiliary_client.py @@ -74,6 +74,12 @@ _PROVIDER_ALIASES = { "minimax_cn": "minimax-cn", "claude": "anthropic", "claude-code": "anthropic", + "github": "copilot", + "github-copilot": "copilot", + "github-model": "copilot", + "github-models": "copilot", + "github-copilot-acp": "copilot-acp", + "copilot-acp-agent": "copilot-acp", } @@ -89,10 +95,11 @@ def _normalize_aux_provider(provider: Optional[str]) -> str: if normalized == "main": # Resolve to the user's actual main provider so named custom providers # and non-aggregator providers (DeepSeek, Alibaba, etc.) work correctly. - main_prov = _read_main_provider() + main_prov = (_read_main_provider() or "").strip().lower() if main_prov and main_prov not in ("auto", "main", ""): - return main_prov - return "custom" + normalized = main_prov + else: + return "custom" return _PROVIDER_ALIASES.get(normalized, normalized) diff --git a/tests/agent/test_auxiliary_client.py b/tests/agent/test_auxiliary_client.py index b5b74bd30..1134f8348 100644 --- a/tests/agent/test_auxiliary_client.py +++ b/tests/agent/test_auxiliary_client.py @@ -19,6 +19,7 @@ from agent.auxiliary_client import ( _read_codex_access_token, _get_provider_chain, _is_payment_error, + _normalize_aux_provider, _try_payment_fallback, _resolve_auto, ) @@ -54,6 +55,17 @@ def codex_auth_dir(tmp_path, monkeypatch): return codex_dir +class TestNormalizeAuxProvider: + def test_maps_github_copilot_aliases(self): + assert _normalize_aux_provider("github") == "copilot" + assert _normalize_aux_provider("github-copilot") == "copilot" + assert _normalize_aux_provider("github-models") == "copilot" + + def test_maps_github_copilot_acp_aliases(self): + assert _normalize_aux_provider("github-copilot-acp") == "copilot-acp" + assert _normalize_aux_provider("copilot-acp-agent") == "copilot-acp" + + class TestReadCodexAccessToken: def test_valid_auth_store(self, tmp_path, monkeypatch): hermes_home = tmp_path / "hermes" diff --git a/tests/agent/test_auxiliary_named_custom_providers.py b/tests/agent/test_auxiliary_named_custom_providers.py index 0f307d57f..5152428b6 100644 --- a/tests/agent/test_auxiliary_named_custom_providers.py +++ b/tests/agent/test_auxiliary_named_custom_providers.py @@ -100,6 +100,26 @@ class TestResolveProviderClientMainAlias: assert client is not None assert "beans.local" in str(client.base_url) + def test_main_resolves_github_copilot_alias(self, tmp_path): + _write_config(tmp_path, { + "model": {"default": "gpt-5.4", "provider": "github-copilot"}, + }) + with ( + patch("hermes_cli.auth.resolve_api_key_provider_credentials", return_value={ + "api_key": "ghu_test_token", + "base_url": "https://api.githubcopilot.com", + }), + patch("agent.auxiliary_client.OpenAI") as mock_openai, + ): + mock_openai.return_value = MagicMock() + from agent.auxiliary_client import resolve_provider_client + + client, model = resolve_provider_client("main", "gpt-5.4") + + assert client is not None + assert model == "gpt-5.4" + assert mock_openai.called + class TestResolveProviderClientNamedCustom: """resolve_provider_client should resolve named custom providers directly."""