Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
"""Regression: a would-grow refusal must not disarm the proactive-prune runway.
|
||||
|
||||
#91830 follow-up. ``ContextCompressor.compress()`` zeroes
|
||||
``_proactive_prune_rearm_tokens`` on its successful tail — correct for a
|
||||
COMMITTED compaction (the boundary already broke the prompt-cache prefix, so
|
||||
the throttle restarts from the new baseline). But ``compress_context``'s
|
||||
anti-growth guard can then REFUSE the result and keep the original
|
||||
transcript, whose cached prefix is intact. Before the fix, that refusal
|
||||
returned with the in-memory runway still at 0 while the durable
|
||||
``model_config`` copy kept the old value:
|
||||
|
||||
- the very next eligible iteration's proactive prune fired without the
|
||||
regrowth interval #79640 introduced — an immediate, unthrottled
|
||||
cache-breaking rewrite of history that was still byte-identical to what
|
||||
the provider had cached, and
|
||||
- memory and disk disagreed until the next restart silently re-armed the
|
||||
throttle from the stale durable row.
|
||||
|
||||
The refusal branch now restores the runway from the attempt snapshot, the
|
||||
same targeted restore the rotation-failure rollback already performed.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from hermes_state import SessionDB
|
||||
|
||||
|
||||
def _build_agent(db: SessionDB, session_id: str):
|
||||
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,
|
||||
)
|
||||
# Skip the one-time aux-model feasibility probe (may hit the network).
|
||||
agent._compression_feasibility_checked = True
|
||||
return agent
|
||||
|
||||
|
||||
def test_would_grow_refusal_restores_prune_runway(tmp_path: Path) -> None:
|
||||
db = SessionDB(db_path=tmp_path / "state.db")
|
||||
session_id = "WOULD_GROW_RUNWAY"
|
||||
db.create_session(session_id, source="test")
|
||||
|
||||
agent = _build_agent(db, session_id)
|
||||
compressor = agent.context_compressor
|
||||
armed_runway = 250_000
|
||||
compressor._proactive_prune_rearm_tokens = armed_runway
|
||||
# Arm the durable copy too, exactly as a committed prune would have
|
||||
# (prune_tool_results_only persists it via archive_and_compact's
|
||||
# model_config_patch) — the refusal must leave it untouched.
|
||||
db.patch_session_model_config(
|
||||
session_id, {"_proactive_prune_rearm_tokens": armed_runway}
|
||||
)
|
||||
|
||||
messages = [{"role": "user", "content": f"m{i} " + "x" * 200} for i in range(10)]
|
||||
|
||||
def _growing_compress(msgs, **_kw):
|
||||
# Mirror the real compress() tail: it zeroes the in-memory runway
|
||||
# before returning — then return a transcript LARGER than the input
|
||||
# so the caller's anti-growth guard refuses the commit.
|
||||
compressor._proactive_prune_rearm_tokens = 0
|
||||
return list(msgs) + [
|
||||
{"role": "assistant", "content": "GROWN " * 20_000},
|
||||
]
|
||||
|
||||
with patch.object(type(compressor), "compress", side_effect=_growing_compress):
|
||||
returned, _sp = agent._compress_context(messages, "sys", approx_tokens=120_000)
|
||||
|
||||
# Refusal contract: original transcript kept, refusal flagged.
|
||||
assert returned == messages
|
||||
assert compressor._last_compress_refused_would_grow is True
|
||||
# The runway must survive the refusal — memory re-aligned with the
|
||||
# (never-cleared) durable copy, keeping the #79640 throttle armed.
|
||||
assert compressor._proactive_prune_rearm_tokens == armed_runway
|
||||
assert (
|
||||
db.get_session_model_config_value(
|
||||
session_id, "_proactive_prune_rearm_tokens", 0
|
||||
)
|
||||
== armed_runway
|
||||
)
|
||||
# And the compression lock must not leak.
|
||||
assert db.get_compression_lock_holder(session_id) is None
|
||||
Reference in New Issue
Block a user