/ tests / hermes_cli / test_arcee_provider.py
test_arcee_provider.py
  1  """Tests for Arcee AI provider support — standard direct API provider."""
  2  
  3  import types
  4  
  5  import pytest
  6  
  7  from hermes_cli.auth import (
  8      PROVIDER_REGISTRY,
  9      resolve_provider,
 10      get_api_key_provider_status,
 11      resolve_api_key_provider_credentials,
 12  )
 13  
 14  
 15  _OTHER_PROVIDER_KEYS = (
 16      "OPENAI_API_KEY", "ANTHROPIC_API_KEY", "DEEPSEEK_API_KEY",
 17      "GOOGLE_API_KEY", "GEMINI_API_KEY", "DASHSCOPE_API_KEY",
 18      "XAI_API_KEY", "KIMI_API_KEY", "KIMI_CN_API_KEY",
 19      "MINIMAX_API_KEY", "MINIMAX_CN_API_KEY", "AI_GATEWAY_API_KEY",
 20      "KILOCODE_API_KEY", "HF_TOKEN", "GLM_API_KEY", "ZAI_API_KEY",
 21      "XIAOMI_API_KEY", "TOKENHUB_API_KEY", "COPILOT_GITHUB_TOKEN", "GH_TOKEN", "GITHUB_TOKEN",
 22  )
 23  
 24  
 25  # =============================================================================
 26  # Provider Registry
 27  # =============================================================================
 28  
 29  
 30  class TestArceeProviderRegistry:
 31      def test_registered(self):
 32          assert "arcee" in PROVIDER_REGISTRY
 33  
 34      def test_name(self):
 35          assert PROVIDER_REGISTRY["arcee"].name == "Arcee AI"
 36  
 37      def test_auth_type(self):
 38          assert PROVIDER_REGISTRY["arcee"].auth_type == "api_key"
 39  
 40      def test_inference_base_url(self):
 41          assert PROVIDER_REGISTRY["arcee"].inference_base_url == "https://api.arcee.ai/api/v1"
 42  
 43      def test_api_key_env_vars(self):
 44          assert PROVIDER_REGISTRY["arcee"].api_key_env_vars == ("ARCEEAI_API_KEY",)
 45  
 46      def test_base_url_env_var(self):
 47          assert PROVIDER_REGISTRY["arcee"].base_url_env_var == "ARCEE_BASE_URL"
 48  
 49  
 50  # =============================================================================
 51  # Aliases
 52  # =============================================================================
 53  
 54  
 55  class TestArceeAliases:
 56      @pytest.mark.parametrize("alias", ["arcee", "arcee-ai", "arceeai"])
 57      def test_alias_resolves(self, alias, monkeypatch):
 58          for key in _OTHER_PROVIDER_KEYS + ("OPENROUTER_API_KEY",):
 59              monkeypatch.delenv(key, raising=False)
 60          monkeypatch.setenv("ARCEEAI_API_KEY", "arc-test-12345")
 61          assert resolve_provider(alias) == "arcee"
 62  
 63      def test_normalize_provider_models_py(self):
 64          from hermes_cli.models import normalize_provider
 65          assert normalize_provider("arcee-ai") == "arcee"
 66          assert normalize_provider("arceeai") == "arcee"
 67  
 68      def test_normalize_provider_providers_py(self):
 69          from hermes_cli.providers import normalize_provider
 70          assert normalize_provider("arcee-ai") == "arcee"
 71          assert normalize_provider("arceeai") == "arcee"
 72  
 73  
 74  # =============================================================================
 75  # Credentials
 76  # =============================================================================
 77  
 78  
 79  class TestArceeCredentials:
 80      def test_status_configured(self, monkeypatch):
 81          monkeypatch.setenv("ARCEEAI_API_KEY", "arc-test")
 82          status = get_api_key_provider_status("arcee")
 83          assert status["configured"]
 84  
 85      def test_status_not_configured(self, monkeypatch):
 86          monkeypatch.delenv("ARCEEAI_API_KEY", raising=False)
 87          status = get_api_key_provider_status("arcee")
 88          assert not status["configured"]
 89  
 90      def test_openrouter_key_does_not_make_arcee_configured(self, monkeypatch):
 91          """OpenRouter users should NOT see arcee as configured."""
 92          monkeypatch.delenv("ARCEEAI_API_KEY", raising=False)
 93          monkeypatch.setenv("OPENROUTER_API_KEY", "sk-or-test")
 94          status = get_api_key_provider_status("arcee")
 95          assert not status["configured"]
 96  
 97      def test_resolve_credentials(self, monkeypatch):
 98          monkeypatch.setenv("ARCEEAI_API_KEY", "arc-direct-key")
 99          monkeypatch.delenv("ARCEE_BASE_URL", raising=False)
100          creds = resolve_api_key_provider_credentials("arcee")
101          assert creds["api_key"] == "arc-direct-key"
102          assert creds["base_url"] == "https://api.arcee.ai/api/v1"
103  
104      def test_custom_base_url_override(self, monkeypatch):
105          monkeypatch.setenv("ARCEEAI_API_KEY", "arc-x")
106          monkeypatch.setenv("ARCEE_BASE_URL", "https://custom.arcee.example/v1")
107          creds = resolve_api_key_provider_credentials("arcee")
108          assert creds["base_url"] == "https://custom.arcee.example/v1"
109  
110  
111  # =============================================================================
112  # Model catalog
113  # =============================================================================
114  
115  
116  class TestArceeModelCatalog:
117      def test_static_model_list(self):
118          """Arcee has a static _PROVIDER_MODELS catalog entry. Specific model
119          names change with releases and don't belong in tests.
120          """
121          from hermes_cli.models import _PROVIDER_MODELS
122          assert "arcee" in _PROVIDER_MODELS
123          assert len(_PROVIDER_MODELS["arcee"]) >= 1
124  
125      def test_canonical_provider_entry(self):
126          from hermes_cli.models import CANONICAL_PROVIDERS
127          slugs = [p.slug for p in CANONICAL_PROVIDERS]
128          assert "arcee" in slugs
129  
130  
131  # =============================================================================
132  # Model normalization
133  # =============================================================================
134  
135  
136  class TestArceeNormalization:
137      def test_in_matching_prefix_strip_set(self):
138          from hermes_cli.model_normalize import _MATCHING_PREFIX_STRIP_PROVIDERS
139          assert "arcee" in _MATCHING_PREFIX_STRIP_PROVIDERS
140  
141      def test_strips_prefix(self):
142          from hermes_cli.model_normalize import normalize_model_for_provider
143          assert normalize_model_for_provider("arcee/trinity-mini", "arcee") == "trinity-mini"
144  
145      def test_bare_name_unchanged(self):
146          from hermes_cli.model_normalize import normalize_model_for_provider
147          assert normalize_model_for_provider("trinity-mini", "arcee") == "trinity-mini"
148  
149  
150  # =============================================================================
151  # URL mapping
152  # =============================================================================
153  
154  
155  class TestArceeURLMapping:
156      def test_url_to_provider(self):
157          from agent.model_metadata import _URL_TO_PROVIDER
158          assert _URL_TO_PROVIDER.get("api.arcee.ai") == "arcee"
159  
160      def test_provider_prefixes(self):
161          from agent.model_metadata import _PROVIDER_PREFIXES
162          assert "arcee" in _PROVIDER_PREFIXES
163          assert "arcee-ai" in _PROVIDER_PREFIXES
164          assert "arceeai" in _PROVIDER_PREFIXES
165  
166      def test_trajectory_compressor_detects_arcee(self):
167          import trajectory_compressor as tc
168          comp = tc.TrajectoryCompressor.__new__(tc.TrajectoryCompressor)
169          comp.config = types.SimpleNamespace(base_url="https://api.arcee.ai/api/v1")
170          assert comp._detect_provider() == "arcee"
171  
172  
173  # =============================================================================
174  # providers.py overlay + aliases
175  # =============================================================================
176  
177  
178  class TestArceeProvidersModule:
179      def test_overlay_exists(self):
180          from hermes_cli.providers import HERMES_OVERLAYS
181          assert "arcee" in HERMES_OVERLAYS
182          overlay = HERMES_OVERLAYS["arcee"]
183          assert overlay.transport == "openai_chat"
184          assert overlay.base_url_env_var == "ARCEE_BASE_URL"
185          assert not overlay.is_aggregator
186  
187      def test_label(self):
188          from hermes_cli.models import _PROVIDER_LABELS
189          assert _PROVIDER_LABELS["arcee"] == "Arcee AI"
190  
191  
192  # =============================================================================
193  # Auxiliary client — main-model-first design
194  # =============================================================================
195  
196  
197  class TestArceeAuxiliary:
198      def test_main_model_first_design(self):
199          """Arcee uses main-model-first — no entry in _API_KEY_PROVIDER_AUX_MODELS."""
200          from agent.auxiliary_client import _API_KEY_PROVIDER_AUX_MODELS
201          assert "arcee" not in _API_KEY_PROVIDER_AUX_MODELS