Compare commits

...

1 Commits

Author SHA1 Message Date
Jai Suphavadeeprasit
c7458c1af8 init 2026-06-27 20:53:36 -04:00
4 changed files with 58 additions and 3 deletions

View File

@@ -55,10 +55,32 @@ def hermes_client_tag() -> str:
return f"client=hermes-client-v{_hermes_version()}"
def nous_portal_tags() -> List[str]:
def conversation_tag(session_id: str) -> str:
"""Return the ``conversation=...`` tag for a Hermes session/conversation.
Format: ``conversation=<session_id>``. ``session_id`` is the canonical
Hermes conversation identifier (``AIAgent.session_id``) — the same value
used for ``~/.hermes/sessions/`` storage, session logs, and lineage.
Unlike the product/client tags this is high-cardinality (one value per
conversation), so it is only appended when a session id is actually
available — never as part of the always-on base tag set.
"""
return f"conversation={session_id}"
def nous_portal_tags(session_id: str | None = None) -> List[str]:
"""Return the canonical list of Nous Portal product tags.
Always returns a fresh list so callers can mutate it freely
(e.g. ``merged_extra.setdefault("tags", []).extend(nous_portal_tags())``).
When ``session_id`` is provided, a ``conversation=<session_id>`` tag is
appended so Portal usage can be attributed to a specific Hermes
conversation. Callers without a session id (e.g. the auxiliary client's
always-on base tags) omit it and get the canonical two-tag set.
"""
return ["product=hermes-agent", hermes_client_tag()]
tags = ["product=hermes-agent", hermes_client_tag()]
if session_id:
tags.append(conversation_tag(session_id))
return tags

View File

@@ -13,7 +13,7 @@ class NousProfile(ProviderProfile):
def build_extra_body(
self, *, session_id: str | None = None, **context
) -> dict[str, Any]:
return {"tags": nous_portal_tags()}
return {"tags": nous_portal_tags(session_id=session_id)}
def build_api_kwargs_extras(
self,

View File

@@ -42,6 +42,33 @@ def test_nous_portal_tags_returns_fresh_list():
assert "client=test-mutation" not in b
def test_conversation_tag_format():
"""The conversation tag carries the session id verbatim."""
from agent.portal_tags import conversation_tag
assert conversation_tag("abc-123") == "conversation=abc-123"
def test_nous_portal_tags_appends_conversation_when_session_id_given():
"""A session id adds a third, high-cardinality conversation tag."""
from agent.portal_tags import conversation_tag, nous_portal_tags
tags = nous_portal_tags(session_id="sess-42")
assert "product=hermes-agent" in tags
assert conversation_tag("sess-42") in tags
assert len(tags) == 3
def test_nous_portal_tags_omits_conversation_without_session_id():
"""Base tag set stays at two tags when no session id is available."""
from agent.portal_tags import nous_portal_tags
for empty in (None, ""):
tags = nous_portal_tags(session_id=empty)
assert len(tags) == 2
assert not any(t.startswith("conversation=") for t in tags)
def test_auxiliary_client_nous_extra_body_uses_helper():
"""auxiliary_client.NOUS_EXTRA_BODY must match the canonical helper output."""
from agent.auxiliary_client import NOUS_EXTRA_BODY

View File

@@ -414,6 +414,12 @@ class TestNousProfile:
body = p.build_extra_body()
assert body["tags"] == nous_portal_tags()
def test_tags_include_conversation_when_session_id(self):
from agent.portal_tags import conversation_tag
p = get_provider_profile("nous")
body = p.build_extra_body(session_id="sess-99")
assert conversation_tag("sess-99") in body["tags"]
def test_auth_type(self):
p = get_provider_profile("nous")
assert p.auth_type == "oauth_device_code"