Files
hermes-agent/tests/agent/test_hygiene_timeout_cooldown_isolation.py
T
Christopher 5602f04a6e fix(agent): clear in-memory cooldown when hygiene overwrites the shared row
A later hygiene idle-timeout write can replace an aux-model cooldown on
the shared column. Drop the in-memory timer on that refresh so the
in-agent compressor is not still blocked after the DB row is hygiene.
2026-08-16 02:01:41 -07:00

95 lines
3.0 KiB
Python

"""Hygiene idle-timeout cooldowns must not block the in-agent compressor."""
from __future__ import annotations
import time
from pathlib import Path
from unittest.mock import patch
from agent.context_compressor import ContextCompressor
from hermes_state import SessionDB
_HYGIENE_TIMEOUT_ERROR = (
"session hygiene compression timed out with no output from the summary model"
)
def _bound_compressor(db: SessionDB, session_id: str) -> ContextCompressor:
with patch(
"agent.context_compressor.get_model_context_length",
return_value=100_000,
):
compressor = ContextCompressor(
model="test/model",
threshold_percent=0.85,
protect_first_n=2,
protect_last_n=2,
quiet_mode=True,
)
compressor.bind_session_state(db, session_id)
return compressor
def test_hygiene_idle_timeout_does_not_block_in_agent_compressor(tmp_path: Path):
db = SessionDB(db_path=tmp_path / "state.db")
session_id = "hyg-timeout-sid"
db.create_session(session_id, source="telegram")
db.record_compression_failure_cooldown(
session_id,
time.time() + 300,
_HYGIENE_TIMEOUT_ERROR,
)
compressor = _bound_compressor(db, session_id)
# Hygiene still sees the durable row so the pre-agent pass can skip.
assert db.get_compression_failure_cooldown(session_id) is not None
# The in-conversation compressor must not inherit that watchdog timeout.
assert compressor.get_active_compression_failure_cooldown() is None
db.close()
def test_aux_model_fault_cooldown_still_blocks_in_agent_compressor(tmp_path: Path):
db = SessionDB(db_path=tmp_path / "state.db")
session_id = "aux-fault-sid"
db.create_session(session_id, source="telegram")
db.record_compression_failure_cooldown(
session_id,
time.time() + 300,
"rate limited",
)
compressor = _bound_compressor(db, session_id)
state = compressor.get_active_compression_failure_cooldown()
assert state is not None
assert state["error"] == "rate limited"
db.close()
def test_hygiene_row_clears_stale_in_memory_aux_cooldown(tmp_path: Path):
"""A later hygiene overwrite must not leave the in-memory aux cooldown armed."""
db = SessionDB(db_path=tmp_path / "state.db")
session_id = "hyg-overwrite-sid"
db.create_session(session_id, source="telegram")
db.record_compression_failure_cooldown(
session_id,
time.time() + 300,
"rate limited",
)
compressor = _bound_compressor(db, session_id)
loaded = compressor.get_active_compression_failure_cooldown()
assert loaded is not None
assert loaded["error"] == "rate limited"
db.record_compression_failure_cooldown(
session_id,
time.time() + 300,
_HYGIENE_TIMEOUT_ERROR,
)
assert compressor.get_active_compression_failure_cooldown(refresh=True) is None
assert compressor.get_active_compression_failure_cooldown() is None
db.close()