diff --git a/agent/gemini_native_adapter.py b/agent/gemini_native_adapter.py index a79effebba4..b9840d11467 100644 --- a/agent/gemini_native_adapter.py +++ b/agent/gemini_native_adapter.py @@ -31,6 +31,11 @@ from agent.gemini_schema import sanitize_gemini_tool_parameters logger = logging.getLogger(__name__) +try: + from hermes_cli import __version__ as _HERMES_VERSION +except Exception: + _HERMES_VERSION = "0.0.0" + DEFAULT_GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta" # Published max output-token ceiling shared by every current Gemini text model @@ -98,7 +103,10 @@ def probe_gemini_tier( url, params={"key": key}, json=payload, - headers={"Content-Type": "application/json"}, + headers={ + "Content-Type": "application/json", + "X-Goog-Api-Client": f"hermes-agent/{_HERMES_VERSION}", + }, ) except Exception as exc: logger.debug("probe_gemini_tier: network error: %s", exc) @@ -881,7 +889,8 @@ class GeminiNativeClient: "Content-Type": "application/json", "Accept": "application/json", "x-goog-api-key": self.api_key, - "User-Agent": "hermes-agent (gemini-native)", + "User-Agent": f"hermes-agent/{_HERMES_VERSION} (gemini-native)", + "X-Goog-Api-Client": f"hermes-agent/{_HERMES_VERSION}", } headers.update(self._default_headers) return headers diff --git a/hermes_cli/models.py b/hermes_cli/models.py index f84ac69564e..c99345c9951 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -3417,7 +3417,10 @@ def probe_api_models( candidates.append((alternate_base, True)) tried: list[str] = [] - headers: dict[str, str] = {"User-Agent": _HERMES_USER_AGENT} + headers: dict[str, str] = { + "User-Agent": _HERMES_USER_AGENT, + "X-Goog-Api-Client": f"hermes-agent/{_HERMES_VERSION}", + } if api_key and api_mode == "anthropic_messages": headers["x-api-key"] = api_key headers["anthropic-version"] = "2023-06-01" diff --git a/tests/agent/test_gemini_native_adapter.py b/tests/agent/test_gemini_native_adapter.py index aa9b2a38a52..e5dd54de265 100644 --- a/tests/agent/test_gemini_native_adapter.py +++ b/tests/agent/test_gemini_native_adapter.py @@ -408,3 +408,53 @@ def test_explicit_max_tokens_is_respected(): req = build_gemini_request(messages=[{"role": "user", "content": "hi"}], max_tokens=4096) assert req["generationConfig"]["maxOutputTokens"] == 4096 + + +# --------------------------------------------------------------------------- +# X-Goog-Api-Client header tests +# --------------------------------------------------------------------------- + + +def test_x_goog_api_client_header_is_set(): + """The X-Goog-Api-Client header should be set on inference requests.""" + from agent.gemini_native_adapter import GeminiNativeClient + + client = GeminiNativeClient(api_key="fake-key", model="gemini-2.0-flash") + headers = client._headers() + + assert "X-Goog-Api-Client" in headers, "X-Goog-Api-Client header missing" + assert "hermes-agent/" in headers["X-Goog-Api-Client"], ( + "hermes-agent not found in X-Goog-Api-Client header" + ) + + +def test_x_goog_api_client_header_format(): + """Header value should be 'hermes-agent/' matching the package version.""" + from agent.gemini_native_adapter import GeminiNativeClient, _HERMES_VERSION + + client = GeminiNativeClient(api_key="fake-key", model="gemini-2.0-flash") + headers = client._headers() + + expected = f"hermes-agent/{_HERMES_VERSION}" + assert headers["X-Goog-Api-Client"] == expected + + +def test_user_agent_contains_version(): + """User-Agent should include the hermes-agent version.""" + from agent.gemini_native_adapter import GeminiNativeClient, _HERMES_VERSION + + client = GeminiNativeClient(api_key="fake-key", model="gemini-2.0-flash") + headers = client._headers() + + assert f"hermes-agent/{_HERMES_VERSION}" in headers["User-Agent"] + + +def test_hermes_version_is_valid(): + """_HERMES_VERSION should be a non-empty string.""" + from agent.gemini_native_adapter import _HERMES_VERSION + + assert isinstance(_HERMES_VERSION, str) + assert len(_HERMES_VERSION) > 0 + assert _HERMES_VERSION != "0.0.0", ( + "Version should resolve from hermes_cli.__version__, not the fallback" + )