Files
yvgude--lean-ctx/integrations/hermes-lean-ctx/tests/test_engine_abc.py
T
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

112 lines
4.1 KiB
Python

"""ABC conformance and engine behaviour (hermetic, daemon offline)."""
from __future__ import annotations
from agent.context_engine import ContextEngine
from hermes_lean_ctx import compaction
from hermes_lean_ctx.engine import LeanCtxEngine
from hermes_lean_ctx.tokens import count_messages_tokens
from tests._helpers import make_messages, make_with_tool_block
def test_satisfies_abc(engine):
assert isinstance(engine, ContextEngine)
assert engine.name == "lean-ctx"
def test_required_attributes_present(engine):
for attr in (
"last_prompt_tokens", "last_completion_tokens", "last_total_tokens",
"threshold_tokens", "context_length", "compression_count",
):
assert isinstance(getattr(engine, attr), int)
assert engine.context_length == 200_000
assert engine.threshold_tokens == 150_000 # 200k * 0.75
def test_update_from_response_openai_and_anthropic(engine):
engine.update_from_response({"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15})
assert engine.last_prompt_tokens == 10
assert engine.last_completion_tokens == 5
assert engine.last_total_tokens == 15
engine.update_from_response({"input_tokens": 20, "output_tokens": 7})
assert engine.last_prompt_tokens == 20
assert engine.last_completion_tokens == 7
assert engine.last_total_tokens == 27 # derived when total absent
engine.update_from_response("not a dict") # tolerated
assert engine.last_prompt_tokens == 20
def test_should_compress_threshold(engine):
assert engine.should_compress(0) is False
assert engine.should_compress(engine.threshold_tokens) is True
assert engine.should_compress(engine.threshold_tokens - 1) is False
# falls back to last_prompt_tokens
engine.last_prompt_tokens = engine.threshold_tokens + 1
assert engine.should_compress() is True
def test_should_compress_preflight(engine):
engine.threshold_tokens = 5
assert engine.should_compress_preflight(make_messages(4)) is True
engine.threshold_tokens = 10_000_000
assert engine.should_compress_preflight(make_messages(1)) is False
def test_update_model_explicit_and_preset(engine):
engine.update_model("custom", context_length=32_000)
assert engine.context_length == 32_000
assert engine.threshold_tokens == 24_000
engine.update_model("claude-4-opus") # preset -> 200k
assert engine.context_length == 200_000
def test_get_status_shape(engine):
status = engine.get_status()
assert status["name"] == "lean-ctx"
assert status["daemon_available"] is False # discard port
for key in ("context_length", "threshold_tokens", "compression_count"):
assert key in status
def test_compress_offline_compacts_and_is_valid(engine):
engine._config = engine._config.with_context_length(8_000) # tiny so we compact
msgs = make_messages(40)
out = engine.compress(msgs)
assert compaction.tool_pairing_errors(out) == []
assert len(out) < len(msgs)
assert count_messages_tokens(out) < count_messages_tokens(msgs)
assert engine.compression_count == 1
# deterministic: same input compacts identically
engine2 = LeanCtxEngine(config=engine._config)
assert engine2.compress(make_messages(40)) == out
def test_compress_with_tool_block_offline():
# tiny protect budget forces the tool block fully into the summarized region
from hermes_lean_ctx.config import LeanCtxConfig
cfg = LeanCtxConfig(
base_url="http://127.0.0.1:9", timeout=2.0, context_length=1_000,
protect_fraction=0.05, protect_min_tokens=50, protect_min_messages=2,
)
eng = LeanCtxEngine(config=cfg)
out = eng.compress(make_with_tool_block())
assert compaction.tool_pairing_errors(out) == []
# no orphaned tool results survive the boundary
assert not any(m.get("role") == "tool" for m in out)
def test_compress_noop_when_small(engine):
msgs = make_messages(1)
out = engine.compress(msgs)
assert out == msgs
assert engine.compression_count == 0
def test_on_session_reset_clears_counters(engine):
engine.last_prompt_tokens = 99
engine.on_session_reset()
assert engine.last_prompt_tokens == 0