mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-28 20:57:07 +08:00
Compare commits
2 Commits
chore/remo
...
hermes/her
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce2d3bed2a | ||
|
|
4437a5dade |
@@ -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,11 @@ class GeminiNativeClient:
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"x-goog-api-key": self.api_key,
|
||||
"User-Agent": "hermes-agent (gemini-native)",
|
||||
# Google requires platform/library clients to identify themselves
|
||||
# via x-goog-api-client (company-product/version format).
|
||||
# See https://ai.google.dev/gemini-api/docs/partner-integration
|
||||
"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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -475,6 +475,7 @@ AUTHOR_MAP = {
|
||||
"bzarnitz13@gmail.com": "Beandon13",
|
||||
"tony@tonysimons.dev": "asimons81",
|
||||
"jetha@google.com": "jethac",
|
||||
"dharmadhikari@google.com": "vishal-dharm",
|
||||
"jani@0xhoneyjar.xyz": "deep-name",
|
||||
# LINE messaging plugin (synthesis PR)
|
||||
"32443648+leepoweii@users.noreply.github.com": "leepoweii",
|
||||
|
||||
@@ -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/<version>' 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"
|
||||
)
|
||||
|
||||
@@ -115,6 +115,19 @@ class TestGenerateGeminiTts:
|
||||
# Audio payload should match the PCM we put in
|
||||
assert data[44:] == fake_pcm_bytes
|
||||
|
||||
def test_x_goog_api_client_header_is_set(self, tmp_path, monkeypatch, mock_gemini_response):
|
||||
"""Google requires platform clients to send x-goog-api-client."""
|
||||
from tools.tts_tool import _generate_gemini_tts
|
||||
|
||||
monkeypatch.setenv("GEMINI_API_KEY", "test-key")
|
||||
|
||||
with patch("requests.post", return_value=mock_gemini_response) as mock_post:
|
||||
_generate_gemini_tts("Hi", str(tmp_path / "test.wav"), {})
|
||||
|
||||
headers = mock_post.call_args[1]["headers"]
|
||||
assert "X-Goog-Api-Client" in headers
|
||||
assert headers["X-Goog-Api-Client"].startswith("hermes-agent/")
|
||||
|
||||
def test_default_voice_and_model(self, tmp_path, monkeypatch, mock_gemini_response):
|
||||
from tools.tts_tool import (
|
||||
DEFAULT_GEMINI_TTS_MODEL,
|
||||
|
||||
@@ -1617,11 +1617,21 @@ def _generate_gemini_tts(text: str, output_path: str, tts_config: Dict[str, Any]
|
||||
},
|
||||
}
|
||||
|
||||
try:
|
||||
from hermes_cli import __version__ as _hermes_version
|
||||
except Exception:
|
||||
_hermes_version = "0.0.0"
|
||||
|
||||
endpoint = f"{base_url}/models/{model}:generateContent"
|
||||
response = requests.post(
|
||||
endpoint,
|
||||
params={"key": api_key},
|
||||
headers={"Content-Type": "application/json"},
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
# Google requires platform/library clients to identify themselves
|
||||
# via x-goog-api-client. See https://ai.google.dev/gemini-api/docs/partner-integration
|
||||
"X-Goog-Api-Client": f"hermes-agent/{_hermes_version}",
|
||||
},
|
||||
json=payload,
|
||||
timeout=60,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user