hermes - ✅(Solved) Fix Gateway agent-cache teardown test patches wrong cleanup_vm binding [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#15489Fetched 2026-04-26 05:27:08
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Participants
Timeline (top)
labeled ×3cross-referenced ×1

Error Message

E AssertionError: assert 'hard-session' in []

Root Cause

Bug Description

tests/gateway/test_agent_cache.py::TestAgentCacheIdleResume::test_close_vs_release_full_teardown_difference fails on main because the test monkeypatches tools.terminal_tool.cleanup_vm, but AIAgent.close() calls the cleanup_vm symbol imported into run_agent.py at module import time.

Fix Action

Fix / Workaround

Bug Description

tests/gateway/test_agent_cache.py::TestAgentCacheIdleResume::test_close_vs_release_full_teardown_difference fails on main because the test monkeypatches tools.terminal_tool.cleanup_vm, but AIAgent.close() calls the cleanup_vm symbol imported into run_agent.py at module import time.

Affected files/lines

  • tests/gateway/test_agent_cache.py:972-986 patches _tt.cleanup_vm and expects agent_b.close() to append "hard-session".
  • run_agent.py:73 imports cleanup_vm directly: from tools.terminal_tool import cleanup_vm, ....
  • run_agent.py:3977-3980 calls the imported cleanup_vm(task_id) symbol inside AIAgent.close().

Why this is a bug

The regression test is intended to pin the resource-lifecycle contract that release_clients() is soft eviction while close() performs hard teardown. However, it currently patches the wrong binding, so the test fails even though close() does call its local imported cleanup_vm symbol. This leaves the teardown contract test broken/noisy and can mask real regressions in agent-cache cleanup behavior.

PR fix notes

PR #15502: fix: patch correct module binding in test_release_clients_does_not_touch_terminal_or_browser

Description (problem / solution / changelog)

The test test_release_clients_does_not_touch_terminal_or_browser patches tools.terminal_tool.cleanup_vm and tools.browser_tool.cleanup_browser, but the production code in run_agent.py uses module-level names imported at the top of the file:

from tools.terminal_tool import cleanup_vm
from tools.browser_tool import cleanup_browser

So release_clients() calls cleanup_vm / cleanup_browser resolved in the run_agent namespace — not the original tools.* modules. The monkeypatches on _tt.cleanup_vm / _bt.cleanup_browser would never intercept those calls.

The test currently passes only because release_clients() does not invoke either function. If a future change added such a call, the existing patches would silently miss it.

Fix: Patch run_agent.cleanup_vm and run_agent.cleanup_browser instead, consistent with the approach already used in test_close_vs_release_full_teardown_difference in the same file.

All 5 tests in TestAgentCacheIdleResume pass.

Closes #15489

Changed files

  • tests/gateway/test_agent_cache.py (modified, +10/-8)

Code Example

/Users/genie/.hermes/hermes-agent/venv/bin/python -m pytest tests/gateway/test_agent_cache.py::TestAgentCacheIdleResume::test_close_vs_release_full_teardown_difference -q

---

E       AssertionError: assert 'hard-session' in []

---

from run_agent import AIAgent
import run_agent
from tools import terminal_tool as _tt

vm=[]
orig_ra=run_agent.cleanup_vm
orig_tt=_tt.cleanup_vm
try:
    _tt.cleanup_vm = lambda tid: vm.append(('tt', tid))
    a = AIAgent(..., session_id='hard-session')
    a.close()
    assert vm == []  # test's current patch target misses run_agent.cleanup_vm
finally:
    _tt.cleanup_vm = orig_tt
    run_agent.cleanup_vm = orig_ra

vm=[]
try:
    run_agent.cleanup_vm = lambda tid: vm.append(('run_agent', tid))
    a = AIAgent(..., session_id='hard-session')
    a.close()
    assert vm == [('run_agent', 'hard-session')]
finally:
    run_agent.cleanup_vm = orig_ra
RAW_BUFFERClick to expand / collapse

Bug Description

tests/gateway/test_agent_cache.py::TestAgentCacheIdleResume::test_close_vs_release_full_teardown_difference fails on main because the test monkeypatches tools.terminal_tool.cleanup_vm, but AIAgent.close() calls the cleanup_vm symbol imported into run_agent.py at module import time.

Affected files/lines

  • tests/gateway/test_agent_cache.py:972-986 patches _tt.cleanup_vm and expects agent_b.close() to append "hard-session".
  • run_agent.py:73 imports cleanup_vm directly: from tools.terminal_tool import cleanup_vm, ....
  • run_agent.py:3977-3980 calls the imported cleanup_vm(task_id) symbol inside AIAgent.close().

Why this is a bug

The regression test is intended to pin the resource-lifecycle contract that release_clients() is soft eviction while close() performs hard teardown. However, it currently patches the wrong binding, so the test fails even though close() does call its local imported cleanup_vm symbol. This leaves the teardown contract test broken/noisy and can mask real regressions in agent-cache cleanup behavior.

Minimal reproduction

From repo root with the venv active:

/Users/genie/.hermes/hermes-agent/venv/bin/python -m pytest tests/gateway/test_agent_cache.py::TestAgentCacheIdleResume::test_close_vs_release_full_teardown_difference -q

Observed failure:

E       AssertionError: assert 'hard-session' in []

Narrow binding check:

from run_agent import AIAgent
import run_agent
from tools import terminal_tool as _tt

vm=[]
orig_ra=run_agent.cleanup_vm
orig_tt=_tt.cleanup_vm
try:
    _tt.cleanup_vm = lambda tid: vm.append(('tt', tid))
    a = AIAgent(..., session_id='hard-session')
    a.close()
    assert vm == []  # test's current patch target misses run_agent.cleanup_vm
finally:
    _tt.cleanup_vm = orig_tt
    run_agent.cleanup_vm = orig_ra

vm=[]
try:
    run_agent.cleanup_vm = lambda tid: vm.append(('run_agent', tid))
    a = AIAgent(..., session_id='hard-session')
    a.close()
    assert vm == [('run_agent', 'hard-session')]
finally:
    run_agent.cleanup_vm = orig_ra

Expected vs actual

  • Expected: the test should patch the symbol actually used by AIAgent.close() and pass when close() performs hard teardown but release_clients() does not.
  • Actual: the test patches tools.terminal_tool.cleanup_vm; run_agent.cleanup_vm remains bound to the original function, so vm_calls stays empty and the test fails.

Suggested investigation direction

Patch run_agent.cleanup_vm in this test (prefer monkeypatch.setattr(run_agent, "cleanup_vm", ...)) instead of mutating tools.terminal_tool.cleanup_vm. Consider similarly checking whether cleanup_browser/process-registry teardown assertions patch the exact imported symbol when they are testing AIAgent.close().

extent analysis

TL;DR

Patch run_agent.cleanup_vm instead of tools.terminal_tool.cleanup_vm to fix the test failure.

Guidance

  • Identify the correct symbol to patch: run_agent.cleanup_vm is the symbol actually used by AIAgent.close().
  • Use monkeypatch.setattr(run_agent, "cleanup_vm", ...) to patch the correct symbol.
  • Verify that the test passes after patching the correct symbol.
  • Review similar tests to ensure they are patching the correct symbols, such as cleanup_browser and process-registry teardown assertions.

Example

monkeypatch.setattr(run_agent, "cleanup_vm", lambda tid: vm.append(('run_agent', tid)))

Notes

This fix assumes that the test is intended to verify the behavior of AIAgent.close() and that patching run_agent.cleanup_vm is the correct way to test this behavior.

Recommendation

Apply workaround: patch run_agent.cleanup_vm instead of tools.terminal_tool.cleanup_vm to fix the test failure, as this is the symbol actually used by AIAgent.close().

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING