"""Attribution default_headers applied per provider via base-URL detection.""" from types import SimpleNamespace from unittest.mock import MagicMock, patch from run_agent import AIAgent @patch("run_agent.OpenAI") def test_openrouter_base_url_applies_or_headers(mock_openai): mock_openai.return_value = MagicMock() agent = AIAgent( api_key="test-key", base_url="https://openrouter.ai/api/v1", model="test/model", quiet_mode=True, skip_context_files=True, skip_memory=True, ) agent._apply_client_headers_for_base_url("https://openrouter.ai/api/v1") headers = agent._client_kwargs["default_headers"] assert headers["HTTP-Referer"] == "https://hermes-agent.nousresearch.com" assert headers["X-Title"] == "Hermes Agent" @patch("run_agent.OpenAI") def test_nvidia_cloud_base_url_applies_billing_origin_header(mock_openai): mock_openai.return_value = MagicMock() agent = AIAgent( api_key="test-key", base_url="https://integrate.api.nvidia.com/v1", model="nvidia/test-model", provider="nvidia", quiet_mode=True, skip_context_files=True, skip_memory=True, ) assert agent._client_kwargs["default_headers"]["X-BILLING-INVOKE-ORIGIN"] == "HermesAgent" agent._apply_client_headers_for_base_url("https://integrate.api.nvidia.com/v1") headers = agent._client_kwargs["default_headers"] assert headers["X-BILLING-INVOKE-ORIGIN"] == "HermesAgent" @patch("run_agent.OpenAI") def test_routed_client_preserves_openai_sdk_custom_headers(mock_openai): mock_openai.return_value = MagicMock() routed_client = SimpleNamespace( api_key="test-key", base_url="https://integrate.api.nvidia.com/v1", _custom_headers={"X-BILLING-INVOKE-ORIGIN": "HermesAgent"}, ) with patch("agent.auxiliary_client.resolve_provider_client", return_value=( routed_client, "nvidia/test-model", )): agent = AIAgent( provider="nvidia", model="nvidia/test-model", quiet_mode=True, skip_context_files=True, skip_memory=True, ) headers = agent._client_kwargs["default_headers"] assert headers["X-BILLING-INVOKE-ORIGIN"] == "HermesAgent" @patch("run_agent.OpenAI") def test_openrouter_headers_include_response_cache_when_enabled(mock_openai): """When openrouter.response_cache is True, the cache header is injected.""" mock_openai.return_value = MagicMock() agent = AIAgent( api_key="test-key", base_url="https://openrouter.ai/api/v1", model="test/model", quiet_mode=True, skip_context_files=True, skip_memory=True, ) with patch("hermes_cli.config.load_config", return_value={ "openrouter": {"response_cache": True, "response_cache_ttl": 600}, }), patch("hermes_cli.config.load_config_readonly", return_value={ "openrouter": {"response_cache": True, "response_cache_ttl": 600}, }): agent._apply_client_headers_for_base_url("https://openrouter.ai/api/v1") headers = agent._client_kwargs["default_headers"] assert headers["HTTP-Referer"] == "https://hermes-agent.nousresearch.com" assert headers["X-OpenRouter-Cache"] == "true" assert headers["X-OpenRouter-Cache-TTL"] == "600" # --------------------------------------------------------------------------- # model.default_headers — user-configured overrides (#40033) # --------------------------------------------------------------------------- @patch("run_agent.OpenAI") def test_user_default_headers_override_sdk_user_agent(mock_openai): """``model.default_headers`` lets a custom endpoint swap the OpenAI SDK User-Agent that some gateways/WAFs reject (the #40033 reproduction).""" mock_openai.return_value = MagicMock() agent = AIAgent( api_key="test-key", base_url="http://localhost:8080/v1", model="my-custom-model", provider="custom", quiet_mode=True, skip_context_files=True, skip_memory=True, ) with patch("hermes_cli.config.load_config", return_value={ "model": {"default_headers": {"User-Agent": "curl/8.7.1", "X-Extra": "1"}}, }), patch("hermes_cli.config.load_config_readonly", return_value={ "model": {"default_headers": {"User-Agent": "curl/8.7.1", "X-Extra": "1"}}, }): agent._apply_client_headers_for_base_url("http://localhost:8080/v1") headers = agent._client_kwargs["default_headers"] assert headers["User-Agent"] == "curl/8.7.1" assert headers["X-Extra"] == "1" @patch("run_agent.OpenAI") def test_openrouter_headers_no_cache_when_disabled(mock_openai): """When openrouter.response_cache is False, no cache headers are sent.""" mock_openai.return_value = MagicMock() agent = AIAgent( api_key="test-key", base_url="https://openrouter.ai/api/v1", model="test/model", quiet_mode=True, skip_context_files=True, skip_memory=True, ) with patch("hermes_cli.config.load_config", return_value={ "openrouter": {"response_cache": False}, }), patch("hermes_cli.config.load_config_readonly", return_value={ "openrouter": {"response_cache": False}, }): agent._apply_client_headers_for_base_url("https://openrouter.ai/api/v1") headers = agent._client_kwargs["default_headers"] assert headers["HTTP-Referer"] == "https://hermes-agent.nousresearch.com" assert "X-OpenRouter-Cache" not in headers assert "X-OpenRouter-Cache-TTL" not in headers