Files
aiturk-hermes-ide/tests/gateway/test_slash_command_profile_scope.py
T

95 lines
2.7 KiB
Python

"""Gateway slash commands must do their blocking work inside the routed profile.
The multiplexed inbound handler wraps the whole message in
``_profile_runtime_scope``, which installs the routed profile's ``HERMES_HOME``
override and its secret scope as **contextvars**. A bare
``loop.run_in_executor(None, ...)`` starts the worker with an EMPTY context, so
``SessionDB()`` / ``get_hermes_home()`` inside the worker resolve the LAUNCH
home — /insights reported the default profile's conversations from another
profile's chat. ``/compress`` already routes through
``_run_in_executor_with_context``; every other hop in the mixin must too.
Drives the real mixin methods and the real ``_profile_runtime_scope``: the
contextvar loss is a property of the hop, so mocking the hop away would test
nothing.
"""
from __future__ import annotations
from pathlib import Path
import pytest
@pytest.fixture
def profile_home(tmp_path, monkeypatch):
root = tmp_path / ".hermes"
home = root / "profiles" / "coder"
home.mkdir(parents=True)
monkeypatch.setattr(Path, "home", lambda: tmp_path)
monkeypatch.setenv("HERMES_HOME", str(root))
return home
@pytest.fixture
def runner():
"""Minimal host exposing the mixin plus the runner's executor helpers."""
from gateway.run import GatewayRunner
from gateway.slash_commands import GatewaySlashCommandsMixin
class _Runner(GatewaySlashCommandsMixin):
_run_in_executor_with_context = GatewayRunner._run_in_executor_with_context
_get_executor = GatewayRunner._get_executor
r = _Runner()
r.adapters = {}
r._pending_skills_reload_notes = {}
return r
class _Event:
def __init__(self, args: str = ""):
self._args = args
self.source = None
def get_command_args(self) -> str:
return self._args
@pytest.mark.asyncio
async def test_insights_opens_session_db_under_the_routed_home(
runner, profile_home, monkeypatch
):
import agent.insights as insights_mod
import hermes_state
from gateway.run import _profile_runtime_scope
from hermes_constants import get_hermes_home
seen: dict = {}
class _RecordingDB:
def __init__(self, *a, **kw):
seen["home"] = str(get_hermes_home())
def close(self):
pass
class _Engine:
def __init__(self, db):
pass
def generate(self, **kw):
return {}
def format_gateway(self, report):
return "ok"
monkeypatch.setattr(hermes_state, "SessionDB", _RecordingDB)
monkeypatch.setattr(insights_mod, "InsightsEngine", _Engine)
with _profile_runtime_scope(profile_home):
result = await runner._handle_insights_command(_Event(""))
assert result == "ok"
assert seen["home"] == str(profile_home)