hermes-agent/tests/agent/test_compression_logging_session_context.py
kshitijk4poor d9bd7ce827 test(compression): pin rotation-fallback tests to in_place=False ahead of default flip
These 7 test sites assert rotation behavior (fork, child sessions, lock
contention, logging session-context follows id rotation, boundary hooks fire
on rotation). Pin each builder to in_place=False explicitly so they keep
exercising the retained rotation fallback regardless of the global default
(flipped to True in #38763). Rotation stays a working opt-out fallback and
deserves continued coverage — these are NOT deleted.

Pinned sites:
- test_compression_concurrent_fork._build_agent_with_db
- test_compression_logging_session_context._build_agent_with_db
- test_compression_rotation_state._build_agent_with_db
- test_compression_boundary_hook._make_agent (2 helpers: CompressionBoundaryHook + SessionCompressEvent)
- test_compression_concurrent_sessions._build_agent_with_db
2026-06-25 12:56:05 -07:00

84 lines
3.4 KiB
Python

"""Regression: compaction must move the LOGGING session context with the id.
When ``compress_context`` rotates ``agent.session_id`` it updates the
gateway/tools session context (``gateway.session_context.set_current_session_id``,
which moves ``HERMES_SESSION_ID`` env + ContextVar). The ``[session_id]`` tag on
log lines comes from a SEPARATE mechanism — ``hermes_logging._session_context``
(a threading.local read by the global LogRecord factory), set once per turn in
``conversation_loop.py``. Before the fix, the rotation block never updated it, so
log lines emitted after a mid-turn compaction carried the STALE old id while the
message body / session DB / gateway state carried the new one (see #34089). This
asserts the logging context follows the rotation.
"""
from __future__ import annotations
import os
from pathlib import Path
from unittest.mock import MagicMock, patch
import hermes_logging
from hermes_state import SessionDB
def _build_agent_with_db(db: SessionDB, session_id: str):
"""Mirror tests/agent/test_compression_concurrent_fork.py's harness."""
with patch.dict(os.environ, {"OPENROUTER_API_KEY": "test-key"}):
from run_agent import AIAgent
agent = AIAgent(
api_key="test-key",
base_url="https://openrouter.ai/api/v1",
model="test/model",
quiet_mode=True,
session_db=db,
session_id=session_id,
skip_context_files=True,
skip_memory=True,
)
compressor = MagicMock()
compressor.compress.return_value = [
{"role": "user", "content": "[CONTEXT COMPACTION] summary"},
{"role": "user", "content": "tail"},
]
compressor.compression_count = 1
compressor.last_prompt_tokens = 0
compressor.last_completion_tokens = 0
compressor._last_summary_error = None
compressor._last_compress_aborted = False
compressor._last_aux_model_failure_model = None
compressor._last_aux_model_failure_error = None
agent.context_compressor = compressor
# This test covers the ROTATION fallback (logging session-context follows
# the id rotation) — pin in_place=False so it keeps exercising rotation
# regardless of the global default (flipped to True in #38763).
agent.compression_in_place = False
return agent
def test_logging_session_context_follows_compression_rotation(tmp_path: Path) -> None:
db = SessionDB(db_path=tmp_path / "state.db")
parent_sid = "PARENT_LOGCTX_SESSION"
db.create_session(parent_sid, source="cli")
agent = _build_agent_with_db(db, parent_sid)
# conversation_loop.py pins the logging tag to the ORIGINAL id at turn start.
hermes_logging.set_session_context(parent_sid)
try:
messages = [{"role": "user", "content": f"m{i}"} for i in range(20)]
agent._compress_context(messages, "sys", approx_tokens=120_000)
# The id actually rotated (sanity — otherwise the assertion is vacuous).
assert agent.session_id != parent_sid
# The logging context must now match the NEW id, not the stale one.
current = getattr(hermes_logging._session_context, "session_id", None)
assert current == agent.session_id, (
"Logging session context did not follow the compaction rotation: "
f"log tag still {current!r}, agent.session_id is {agent.session_id!r} "
"(see #34089)."
)
finally:
hermes_logging.clear_session_context()