mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 06:51:16 +08:00
fix(gateway): avoid cross-user mirror writes in per-user group sessions
This commit is contained in:
@@ -77,6 +77,46 @@ class TestFindSessionId:
|
||||
|
||||
assert result == "sess_topic_a"
|
||||
|
||||
def test_user_id_disambiguates_same_group_chat(self, tmp_path):
|
||||
sessions_dir, index_file = _setup_sessions(tmp_path, {
|
||||
"alice": {
|
||||
"session_id": "sess_alice",
|
||||
"origin": {"platform": "telegram", "chat_id": "-1001", "user_id": "alice"},
|
||||
"updated_at": "2026-01-01T00:00:00",
|
||||
},
|
||||
"bob": {
|
||||
"session_id": "sess_bob",
|
||||
"origin": {"platform": "telegram", "chat_id": "-1001", "user_id": "bob"},
|
||||
"updated_at": "2026-02-01T00:00:00",
|
||||
},
|
||||
})
|
||||
|
||||
with patch.object(mirror_mod, "_SESSIONS_DIR", sessions_dir), \
|
||||
patch.object(mirror_mod, "_SESSIONS_INDEX", index_file):
|
||||
result = _find_session_id("telegram", "-1001", user_id="alice")
|
||||
|
||||
assert result == "sess_alice"
|
||||
|
||||
def test_ambiguous_same_group_chat_without_user_id_returns_none(self, tmp_path):
|
||||
sessions_dir, index_file = _setup_sessions(tmp_path, {
|
||||
"alice": {
|
||||
"session_id": "sess_alice",
|
||||
"origin": {"platform": "telegram", "chat_id": "-1001", "user_id": "alice"},
|
||||
"updated_at": "2026-01-01T00:00:00",
|
||||
},
|
||||
"bob": {
|
||||
"session_id": "sess_bob",
|
||||
"origin": {"platform": "telegram", "chat_id": "-1001", "user_id": "bob"},
|
||||
"updated_at": "2026-02-01T00:00:00",
|
||||
},
|
||||
})
|
||||
|
||||
with patch.object(mirror_mod, "_SESSIONS_DIR", sessions_dir), \
|
||||
patch.object(mirror_mod, "_SESSIONS_INDEX", index_file):
|
||||
result = _find_session_id("telegram", "-1001")
|
||||
|
||||
assert result is None
|
||||
|
||||
def test_no_match_returns_none(self, tmp_path):
|
||||
sessions_dir, index_file = _setup_sessions(tmp_path, {
|
||||
"sess": {
|
||||
@@ -189,6 +229,35 @@ class TestMirrorToSession:
|
||||
assert (sessions_dir / "sess_topic_a.jsonl").exists()
|
||||
assert not (sessions_dir / "sess_topic_b.jsonl").exists()
|
||||
|
||||
def test_successful_mirror_uses_user_id_for_group_session(self, tmp_path):
|
||||
sessions_dir, index_file = _setup_sessions(tmp_path, {
|
||||
"alice": {
|
||||
"session_id": "sess_alice",
|
||||
"origin": {"platform": "telegram", "chat_id": "-1001", "user_id": "alice"},
|
||||
"updated_at": "2026-01-01T00:00:00",
|
||||
},
|
||||
"bob": {
|
||||
"session_id": "sess_bob",
|
||||
"origin": {"platform": "telegram", "chat_id": "-1001", "user_id": "bob"},
|
||||
"updated_at": "2026-02-01T00:00:00",
|
||||
},
|
||||
})
|
||||
|
||||
with patch.object(mirror_mod, "_SESSIONS_DIR", sessions_dir), \
|
||||
patch.object(mirror_mod, "_SESSIONS_INDEX", index_file), \
|
||||
patch("gateway.mirror._append_to_sqlite"):
|
||||
result = mirror_to_session(
|
||||
"telegram",
|
||||
"-1001",
|
||||
"Hello group!",
|
||||
source_label="cli",
|
||||
user_id="alice",
|
||||
)
|
||||
|
||||
assert result is True
|
||||
assert (sessions_dir / "sess_alice.jsonl").exists()
|
||||
assert not (sessions_dir / "sess_bob.jsonl").exists()
|
||||
|
||||
def test_no_matching_session(self, tmp_path):
|
||||
sessions_dir, index_file = _setup_sessions(tmp_path, {})
|
||||
|
||||
|
||||
@@ -167,6 +167,39 @@ class TestSendMessageTool:
|
||||
media_files=[],
|
||||
)
|
||||
|
||||
def test_mirror_receives_current_session_user_id(self):
|
||||
config, _telegram_cfg = _make_config()
|
||||
|
||||
with patch("gateway.config.load_gateway_config", return_value=config), \
|
||||
patch("tools.interrupt.is_interrupted", return_value=False), \
|
||||
patch("model_tools._run_async", side_effect=_run_async_immediately), \
|
||||
patch("tools.send_message_tool._send_to_platform", new=AsyncMock(return_value={"success": True})), \
|
||||
patch("gateway.session_context.get_session_env") as get_session_env_mock, \
|
||||
patch("gateway.mirror.mirror_to_session", return_value=True) as mirror_mock:
|
||||
get_session_env_mock.side_effect = lambda name, default="": {
|
||||
"HERMES_SESSION_PLATFORM": "telegram",
|
||||
"HERMES_SESSION_USER_ID": "user-123",
|
||||
}.get(name, default)
|
||||
result = json.loads(
|
||||
send_message_tool(
|
||||
{
|
||||
"action": "send",
|
||||
"target": "telegram:12345",
|
||||
"message": "hello",
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
assert result["success"] is True
|
||||
mirror_mock.assert_called_once_with(
|
||||
"telegram",
|
||||
"12345",
|
||||
"hello",
|
||||
source_label="telegram",
|
||||
thread_id=None,
|
||||
user_id="user-123",
|
||||
)
|
||||
|
||||
def test_top_level_send_failure_redacts_query_token(self):
|
||||
config, _telegram_cfg = _make_config()
|
||||
leaked = "very-secret-query-token-123456"
|
||||
|
||||
Reference in New Issue
Block a user