Files
hermes-agent/tests/tools/test_delegate_child_cache_ttl.py
2026-10-08 17:22:54 +02:00

65 lines
3.0 KiB
Python

"""Subagents never inherit the 1h prompt-cache tier: with ``prompt_caching.cache_ttl: 1h`` the parent
keeps 1h, the child is built at 5m, and the child's wire markers carry no ``ttl``. A disabled cache
stays disabled (the child is not re-enabled to 5m)."""
from types import SimpleNamespace
from agent.prompt_caching import apply_anthropic_cache_control
from tools.delegate_tool import _apply_child_cache_ttl
def _markers(messages):
out = []
for m in messages:
c = m.get("content")
if isinstance(c, list):
out += [b["cache_control"] for b in c if isinstance(b, dict) and "cache_control" in b]
if "cache_control" in m:
out.append(m["cache_control"])
return out
def test_child_1h_becomes_5m_and_wire_markers_drop_ttl():
child = SimpleNamespace(_cache_ttl="1h")
_apply_child_cache_ttl(child)
assert child._cache_ttl == "5m"
msgs = [{"role": "system", "content": "sys"}, {"role": "user", "content": "hi"},
{"role": "assistant", "content": "ok"}, {"role": "user", "content": "go"}]
wire = apply_anthropic_cache_control([dict(m) for m in msgs], cache_ttl=child._cache_ttl)
marks = _markers(wire)
assert marks and all("ttl" not in m for m in marks), marks
# and the parent's 1h layout really is different, so this is not a vacuous check
parent_marks = _markers(apply_anthropic_cache_control([dict(m) for m in msgs], cache_ttl="1h"))
assert any(m.get("ttl") == "1h" for m in parent_marks)
def test_disabled_and_5m_are_left_alone():
for ttl in (None, "5m"):
child = SimpleNamespace(_cache_ttl=ttl)
_apply_child_cache_ttl(child)
assert child._cache_ttl == ttl
def test_real_spawn_path_applies_it(tmp_path, monkeypatch):
"""Through ``_build_child_agent`` with a real AIAgent: parent configured 1h, child ends at 5m, and the
parent is untouched."""
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "config.yaml").write_text(
"prompt_caching:\n cache_ttl: 1h\nmodel:\n default: anthropic/claude-sonnet-4.6\n", encoding="utf-8")
from run_agent import AIAgent
from tools import delegate_tool as dt
import tools.delegate_tool_config as dtc
monkeypatch.setattr(dt, "_load_config", dict)
monkeypatch.setattr(dtc, "_load_config", dict)
kw = dict(api_key="k", base_url="https://openrouter.ai/api/v1", provider="openrouter",
api_mode="chat_completions", model="anthropic/claude-sonnet-4.6", platform="cli", quiet_mode=True,
skip_context_files=True, skip_memory=True, save_trajectories=False, enabled_toolsets=["file"])
parent = AIAgent(session_id="p", **kw)
assert parent._cache_ttl == "1h", "fixture: the operator's 1h must actually be in effect"
child = dt._build_child_agent(task_index=0, goal="goal", context=None, toolsets=["file"], model=None,
max_iterations=4, task_count=1, parent_agent=parent)
try:
assert child._cache_ttl == "5m"
assert parent._cache_ttl == "1h"
finally:
child.close()
parent.close()