mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-24 16:54:43 +00:00
test(agent): pin the #61932 all-oversized-tail dead-end shape as compressible
Regression test for the exact issue #61932 report: head + an 8-message protected tail made exclusively of oversized tool pairs. Pre-fix, compress_start >= compress_end made compress() a pure no-op and the retry loop ended in 'Cannot compress further'; post-fix the Phase-1 pressure demotion reclaims the tail in one pass while preserving tool_call/tool_result pairing.
This commit is contained in:
parent
d12ea20009
commit
18d83b4da9
1 changed files with 58 additions and 0 deletions
|
|
@ -210,6 +210,64 @@ class TestProtectedTailPressure61932:
|
|||
# progress (never a pure no-op dead-end above the window).
|
||||
assert tok < c.threshold_tokens or last_progress
|
||||
|
||||
def test_all_oversized_tail_dead_end_shape_now_compresses(
|
||||
self, compressor_128k
|
||||
):
|
||||
"""Exact #61932 dead-end: the protected tail ALONE holds everything.
|
||||
|
||||
Head (3 messages) + an 8-message tail of exclusively oversized tool
|
||||
pairs. The tail token budget + the ``_MAX_TAIL_MESSAGE_FLOOR`` (8)
|
||||
floor protect every non-head message, so ``compress_start >=
|
||||
compress_end`` — pre-fix ``compress()`` returned the transcript
|
||||
UNCHANGED, incremented ``_ineffective_compression_count``, and the
|
||||
retry loop died with "Cannot compress further". Post-fix the Phase-1
|
||||
pressure pass demotes the oversized tool bodies even though the
|
||||
summary window is empty, so the same call materially shrinks the
|
||||
transcript below the context window.
|
||||
"""
|
||||
c = compressor_128k
|
||||
msgs: list[dict] = [
|
||||
{"role": "system", "content": "You are Hermes."},
|
||||
{"role": "user", "content": "Investigate thoroughly"},
|
||||
{"role": "assistant", "content": "OK"},
|
||||
]
|
||||
for i in range(4):
|
||||
msgs.extend(_unique_tool_pair(i, 200_000))
|
||||
assert len(msgs) == 11 # 3 head + 8-message all-oversized tail
|
||||
|
||||
before = estimate_messages_tokens_rough(msgs)
|
||||
assert before > c.context_length, "fixture must start over-context"
|
||||
|
||||
out = c.compress(list(msgs), current_tokens=before)
|
||||
after = estimate_messages_tokens_rough(out)
|
||||
|
||||
# The dead-end is broken: one pass reclaims the bulk of the tail.
|
||||
assert after < c.context_length, (
|
||||
f"still over context: {after:,} >= {c.context_length:,}"
|
||||
)
|
||||
assert after < before * 0.25, (
|
||||
f"expected the oversized tail to demote: {before:,} → {after:,}"
|
||||
)
|
||||
|
||||
# tool_call/tool_result pairing must survive demotion — never orphan
|
||||
# a tool result or a tool call (provider 400s otherwise). Whole
|
||||
# pairs may legitimately be summarized away together.
|
||||
call_ids = {
|
||||
tc["id"]
|
||||
for m in out
|
||||
if m.get("role") == "assistant"
|
||||
for tc in (m.get("tool_calls") or [])
|
||||
if isinstance(tc, dict)
|
||||
}
|
||||
tool_result_ids = [
|
||||
m.get("tool_call_id") for m in out if m.get("role") == "tool"
|
||||
]
|
||||
assert tool_result_ids, "expected surviving tool pairs in the tail"
|
||||
for rid in tool_result_ids:
|
||||
assert rid in call_ids, f"orphaned tool result {rid!r}"
|
||||
for cid in call_ids:
|
||||
assert cid in tool_result_ids, f"orphaned tool call {cid!r}"
|
||||
|
||||
def test_light_tail_still_keeps_recent_tool_bodies(self, compressor_128k):
|
||||
"""Pressure demotion must not fire on a normal-sized protected tail."""
|
||||
c = compressor_128k
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue