From 479d1aff6cd31cb1891d45c14d8c58b56fa73092 Mon Sep 17 00:00:00 2001 From: Jai Suphavadeeprasit Date: Sat, 27 Jun 2026 20:53:36 -0400 Subject: [PATCH] init --- agent/portal_tags.py | 26 ++++++++++++++++++++-- plugins/model-providers/nous/__init__.py | 2 +- tests/agent/test_portal_tags.py | 27 +++++++++++++++++++++++ tests/providers/test_provider_profiles.py | 6 +++++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/agent/portal_tags.py b/agent/portal_tags.py index 647c52a076af..50a42ee2778c 100644 --- a/agent/portal_tags.py +++ b/agent/portal_tags.py @@ -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`` 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=`` 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 diff --git a/plugins/model-providers/nous/__init__.py b/plugins/model-providers/nous/__init__.py index 0e8df173df82..b5cd886854e0 100644 --- a/plugins/model-providers/nous/__init__.py +++ b/plugins/model-providers/nous/__init__.py @@ -13,7 +13,7 @@ class NousProfile(ProviderProfile): def build_extra_body( self, *, session_id: str | None = None, **context ) -> dict[str, Any]: - body: dict[str, Any] = {"tags": nous_portal_tags()} + body: dict[str, Any] = {"tags": nous_portal_tags(session_id=session_id)} provider_preferences = context.get("provider_preferences") if provider_preferences: body["provider"] = provider_preferences diff --git a/tests/agent/test_portal_tags.py b/tests/agent/test_portal_tags.py index 7c873ef0f607..69b96c443037 100644 --- a/tests/agent/test_portal_tags.py +++ b/tests/agent/test_portal_tags.py @@ -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 diff --git a/tests/providers/test_provider_profiles.py b/tests/providers/test_provider_profiles.py index bd450cb56009..73ca4e279083 100644 --- a/tests/providers/test_provider_profiles.py +++ b/tests/providers/test_provider_profiles.py @@ -425,6 +425,12 @@ class TestNousProfile: "provider": preferences, } + 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"