mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
Systematic prune per AGENTS.md test policy, one pass over every major test tree (gateway, hermes_cli, tools, agent, run_agent, plugins, cli, cron, tui_gateway, honcho/openviking, root-level): - DELETE: source-reading tests (read_text/getsource on prod files), change-detector tests (exact catalog counts, model-name snapshots, config version literals), mock-echo tests (assert a mock returns what it was told), assertion-free/trivial tests, near-duplicate parametrizations (boundaries + one representative kept), async/sync twin duplicates, cosmetic within-file variations. - KEEP (mandatory): security/redaction/approval guards, message-role alternation invariants, prompt-caching/deterministic-call-id invariants, issue-number regression tests (deduped), E2E tests. - 6 test files deleted outright (script-style/no-assert or fully redundant); conftest.py, fakes/, fixtures/ untouched. - tests/acp/conftest.py added: autouse fixture stubs the live models.dev/GitHub/Copilot/Anthropic inventory fetches that ACP server tests performed on every session create — test_server.py 147s → 3.4s, and the tests are now genuinely hermetic. - Sleep-based slowness shrunk where safe (codex_ttfb_watchdog, compression_concurrent_fork, etc.); no wall-clock assertion tightened. Verification: full hermetic suite via scripts/run_tests.sh — 2439 files, 31,130 tests passed, 0 failed, 0 flaky retries, 315s wall (baseline: 583s wall, 13,564s subprocess CPU).
84 lines
3.2 KiB
Python
84 lines
3.2 KiB
Python
"""Regression for #23975: context compression must survive a mid-flight
|
|
gateway interrupt.
|
|
|
|
While the compression summary LLM call is in flight, an incoming gateway
|
|
message sets the thread interrupt flag. The Codex Responses aux stream polls
|
|
that flag and used to raise InterruptedError unconditionally — aborting the
|
|
summary, which then fell back to a degraded static "summary unavailable"
|
|
marker (losing the real handoff). Compression now runs its summary call
|
|
under aux_interrupt_protection(), so the interrupt poll is masked for the
|
|
compression task only (timeouts and other aux tasks stay interruptible).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import patch
|
|
|
|
import agent.auxiliary_client as aux
|
|
|
|
|
|
class TestAuxInterruptProtection:
|
|
|
|
|
|
def test_context_manager_is_reentrant(self):
|
|
with aux.aux_interrupt_protection():
|
|
assert aux._aux_interrupt_protected() is True
|
|
with aux.aux_interrupt_protection():
|
|
assert aux._aux_interrupt_protected() is True
|
|
# inner exit must NOT clear protection while still inside outer
|
|
assert aux._aux_interrupt_protected() is True
|
|
assert aux._aux_interrupt_protected() is False
|
|
|
|
def test_restores_on_exception(self):
|
|
try:
|
|
with aux.aux_interrupt_protection():
|
|
raise ValueError("boom")
|
|
except ValueError:
|
|
pass
|
|
assert aux._aux_interrupt_protected() is False
|
|
|
|
|
|
|
|
class TestCompressionProtectsSummaryCall:
|
|
"""The compressor must wrap its summary call_llm in aux_interrupt_protection
|
|
so a mid-flight interrupt doesn't abort it (#23975)."""
|
|
|
|
def test_compressor_call_site_uses_protection(self):
|
|
# The summary call must run inside aux_interrupt_protection. We assert
|
|
# the protection flag is ACTIVE at the moment call_llm is invoked.
|
|
from agent.context_compressor import ContextCompressor
|
|
|
|
seen = {}
|
|
|
|
class _Resp:
|
|
class _Choice:
|
|
class _Msg:
|
|
content = "[CONTEXT SUMMARY]: ok"
|
|
message = _Msg()
|
|
choices = [_Choice()]
|
|
|
|
def fake_call_llm(**kwargs):
|
|
# Capture whether protection was active during the call.
|
|
seen["protected"] = aux._aux_interrupt_protected()
|
|
seen["task"] = kwargs.get("task")
|
|
return _Resp()
|
|
|
|
with patch("agent.context_compressor.get_model_context_length", return_value=100000):
|
|
c = ContextCompressor(model="test", quiet_mode=True)
|
|
|
|
msgs = [
|
|
{"role": "user", "content": "do a thing"},
|
|
{"role": "assistant", "content": "working"},
|
|
{"role": "user", "content": "more"},
|
|
{"role": "assistant", "content": "done"},
|
|
]
|
|
with patch("agent.context_compressor.call_llm", side_effect=fake_call_llm):
|
|
summary = c._generate_summary(msgs)
|
|
|
|
assert summary is not None
|
|
assert seen.get("task") == "compression"
|
|
assert seen.get("protected") is True, (
|
|
"compression summary call must run under aux_interrupt_protection"
|
|
)
|
|
# Protection must be cleared after the call returns.
|
|
assert aux._aux_interrupt_protected() is False
|