mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-20 15:33:54 +00:00
test(gateway): cover ws_orphan_reap session recovery (#63207)
Regression tests for find_latest_gateway_session_for_peer and SessionStore stale-routing self-heal when end_reason is ws_orphan_reap. Pin manual approval mode in blocking E2E tests so smart aux-LLM resolution does not flake CI.
This commit is contained in:
parent
ca907480ae
commit
7452467f54
3 changed files with 56 additions and 0 deletions
|
|
@ -425,6 +425,16 @@ class TestBlockingApprovalE2E:
|
|||
os.environ.pop("HERMES_GATEWAY_SESSION", None)
|
||||
os.environ.pop("HERMES_EXEC_ASK", None)
|
||||
os.environ.pop("HERMES_SESSION_KEY", None)
|
||||
# These E2E tests exercise manual gateway blocking; default config is
|
||||
# approvals.mode=smart which may auto-approve/deny via aux LLM before
|
||||
# notify_cb runs (flaky on CI when the LLM is slow or unavailable).
|
||||
self._approval_mode_patch = patch(
|
||||
"tools.approval._get_approval_mode", return_value="manual"
|
||||
)
|
||||
self._approval_mode_patch.start()
|
||||
|
||||
def teardown_method(self):
|
||||
self._approval_mode_patch.stop()
|
||||
|
||||
def test_blocking_approval_approve_once(self):
|
||||
"""check_all_command_guards blocks until resolve_gateway_approval is called."""
|
||||
|
|
|
|||
|
|
@ -142,6 +142,24 @@ class TestRuntimeStaleGuard:
|
|||
# A brand-new session row must NOT have been created.
|
||||
db.create_session.assert_not_called()
|
||||
|
||||
def test_stale_ws_orphan_reap_entry_recovered_preserving_session_id(self, tmp_path):
|
||||
"""Stale ``ws_orphan_reap`` entry → recovery reopens the SAME session_id (#63207)."""
|
||||
source = _source()
|
||||
db = _db_returning({"sid_stale": {"end_reason": "ws_orphan_reap", "id": "sid_stale"}})
|
||||
db.find_latest_gateway_session_for_peer.return_value = {
|
||||
"id": "sid_stale",
|
||||
"started_at": (datetime.now() - timedelta(hours=2)).timestamp(),
|
||||
}
|
||||
store = _make_store_with_db(tmp_path, db)
|
||||
key = store._generate_session_key(source)
|
||||
store._entries[key] = _make_entry(key, "sid_stale")
|
||||
|
||||
result = store.get_or_create_session(source)
|
||||
|
||||
assert result.session_id == "sid_stale"
|
||||
db.reopen_session.assert_called_once_with("sid_stale")
|
||||
db.create_session.assert_not_called()
|
||||
|
||||
def test_stale_entry_creates_fresh_when_recovery_returns_none(self, tmp_path):
|
||||
"""Stale entry, no recoverable row → brand-new session (no silent drop)."""
|
||||
source = _source()
|
||||
|
|
|
|||
|
|
@ -5627,6 +5627,34 @@ def test_gateway_session_peer_round_trip_and_recovery(db):
|
|||
assert recovered["id"] == "gw-session"
|
||||
|
||||
|
||||
def test_gateway_session_recovery_reopens_ws_orphan_reap_rows(db):
|
||||
"""Rows wrongly ended by the TUI ws-orphan reaper must be recoverable (#63207)."""
|
||||
db.create_session(
|
||||
"reaped-gw-session",
|
||||
"telegram",
|
||||
user_id="user-1",
|
||||
session_key="agent:main:telegram:dm:chat-1",
|
||||
chat_id="chat-1",
|
||||
chat_type="dm",
|
||||
)
|
||||
db.append_message("reaped-gw-session", "user", "hello")
|
||||
db.end_session("reaped-gw-session", "ws_orphan_reap")
|
||||
|
||||
recovered = db.find_latest_gateway_session_for_peer(
|
||||
source="telegram",
|
||||
user_id="user-1",
|
||||
session_key="agent:main:telegram:dm:chat-1",
|
||||
chat_id="chat-1",
|
||||
chat_type="dm",
|
||||
)
|
||||
assert recovered["id"] == "reaped-gw-session"
|
||||
|
||||
db.reopen_session("reaped-gw-session")
|
||||
row = db.get_session("reaped-gw-session")
|
||||
assert row["ended_at"] is None
|
||||
assert row["end_reason"] is None
|
||||
|
||||
|
||||
def test_gateway_session_recovery_reopens_legacy_agent_close_rows(db):
|
||||
db.create_session(
|
||||
"closed-gw-session",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue