mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-20 15:33:54 +00:00
test(gateway): adapter→session-key integration for Discord + Telegram
Completes the review's ask for "adapter-to-session-key integration coverage for Discord and a non-Discord platform" on #20096. Drives a concrete adapter's real BasePlatformAdapter.build_source with an injected gateway_runner, asserts the matched route's profile is stamped on the source, and that build_session_key scopes the key under agent:<profile>: (versus the shared agent:main: namespace). Covers Discord and Telegram — the Telegram case is the bug-#2 path that previously fell through to default. Adds a regression anchor: without gateway_runner, profile stays None and the key lands in agent:main (the silent fallback the fix removes for non-Discord). Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f58e4622cf
commit
c29ab7b9fe
1 changed files with 89 additions and 1 deletions
|
|
@ -6,9 +6,11 @@ from unittest.mock import MagicMock, patch
|
|||
|
||||
import pytest
|
||||
|
||||
from gateway.session import SessionSource
|
||||
from gateway.session import SessionSource, build_session_key
|
||||
from gateway.run import GatewayRunner
|
||||
from gateway.profile_routing import ProfileRoute
|
||||
from gateway.config import Platform
|
||||
from gateway.platforms.base import BasePlatformAdapter
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -331,3 +333,89 @@ class TestGatewayRunnerInjection:
|
|||
# every adapter, not just the ones that pre-declared it (Discord).
|
||||
assert hasattr(_ToyAdapter, "gateway_runner")
|
||||
assert _ToyAdapter.gateway_runner is None
|
||||
|
||||
|
||||
# A concrete adapter we can instantiate without the full platform stack.
|
||||
# ``build_source`` only reads ``self.platform`` and ``self.gateway_runner``, so a
|
||||
# bare instance with those two attrs exercises the real BasePlatformAdapter
|
||||
# method end-to-end. Clearing ``__abstractmethods__`` lets ``__new__`` bypass
|
||||
# the ABC instantiation guard without stubbing connect/send/get_chat_info/…
|
||||
class _StubAdapter(BasePlatformAdapter):
|
||||
pass
|
||||
|
||||
|
||||
_StubAdapter.__abstractmethods__ = frozenset() # type: ignore[attr-defined]
|
||||
|
||||
|
||||
def _stub_adapter(platform: Platform, runner) -> "_StubAdapter":
|
||||
a = _StubAdapter.__new__(_StubAdapter)
|
||||
a.platform = platform
|
||||
a.gateway_runner = runner
|
||||
return a
|
||||
|
||||
|
||||
class TestAdapterToSessionKeyIntegration:
|
||||
"""Adapter -> ``source.profile`` -> session-key integration coverage.
|
||||
|
||||
The review asked for integration coverage for Discord AND a non-Discord
|
||||
platform. These drive a concrete adapter's real ``build_source``
|
||||
(BasePlatformAdapter) with an injected ``gateway_runner``, assert the
|
||||
matched route's profile is stamped on the source, and that the resulting
|
||||
session key is profile-scoped (``agent:<profile>:...`` rather than the
|
||||
shared ``agent:main:...``). The Telegram case is the bug-#2 regression:
|
||||
pre-fix it never received ``gateway_runner`` and fell through to default.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _routes():
|
||||
return [
|
||||
ProfileRoute(name="dc", platform="discord", profile="coder",
|
||||
guild_id="111", chat_id="222"),
|
||||
ProfileRoute(name="tg", platform="telegram", profile="ops",
|
||||
chat_id="-1001234567890"),
|
||||
]
|
||||
|
||||
def test_discord_adapter_stamps_profile_and_scopes_key(self, mock_runner):
|
||||
mock_runner.config.profile_routes = self._routes()
|
||||
adapter = _stub_adapter(Platform.DISCORD, mock_runner)
|
||||
|
||||
source = adapter.build_source(
|
||||
chat_id="222", chat_type="group", guild_id="111", user_id="u1",
|
||||
)
|
||||
assert source.profile == "coder"
|
||||
|
||||
key = build_session_key(source, profile=source.profile)
|
||||
assert key.startswith("agent:coder:"), key
|
||||
# A default-profile key would land in agent:main — must differ.
|
||||
assert key != build_session_key(source, profile=None)
|
||||
|
||||
def test_telegram_adapter_stamps_profile_and_scopes_key(self, mock_runner):
|
||||
"""Non-Discord platform (bug #2). The adapter now receives
|
||||
``gateway_runner``, so ``build_source`` stamps the profile and the
|
||||
session key is isolated under ``agent:ops:`` instead of ``agent:main:``."""
|
||||
mock_runner.config.profile_routes = self._routes()
|
||||
adapter = _stub_adapter(Platform.TELEGRAM, mock_runner)
|
||||
|
||||
source = adapter.build_source(
|
||||
chat_id="-1001234567890", chat_type="group", user_id="u1",
|
||||
)
|
||||
assert source.profile == "ops"
|
||||
|
||||
key = build_session_key(source, profile=source.profile)
|
||||
assert key.startswith("agent:ops:"), key
|
||||
assert key != build_session_key(source, profile=None)
|
||||
|
||||
def test_adapter_without_runner_falls_back_to_default_namespace(self, mock_runner):
|
||||
"""Regression anchor: with no ``gateway_runner`` injected (the pre-fix
|
||||
state for non-Discord adapters), ``build_source`` leaves ``profile=None``
|
||||
and the session key is the shared ``agent:main:`` namespace — no
|
||||
per-profile isolation. This is the silent fallback the fix removes for
|
||||
non-Discord platforms."""
|
||||
adapter = _stub_adapter(Platform.TELEGRAM, runner=None)
|
||||
|
||||
source = adapter.build_source(
|
||||
chat_id="-1001234567890", chat_type="group", user_id="u1",
|
||||
)
|
||||
assert source.profile is None
|
||||
key = build_session_key(source, profile=source.profile)
|
||||
assert key.startswith("agent:main:"), key
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue