mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
Second, deeper pass over tools/gateway/hermes_cli plus first pass over the trees wave 1 missed (acp, acp_adapter, skills, computer_use, docker, dashboard, conformance, monitoring, secret_sources, hermes_state, providers). Same rubric as wave 1 (AGENTS.md test policy); security, alternation/caching invariants, issue-number regressions, and E2E kept. Real test-quality fixes found and rooted out along the way: - tests/tools/test_command_guards.py made real auxiliary-LLM HTTPS calls (DEFAULT_CONFIG smart-approval leaked in) — pinned approval mode=manual via autouse fixture: 17.4s → 0.4s. - test_model_switch_custom_providers.py / test_user_providers_model_switch.py silently probed live provider catalogs (~2s/test) — stubbed cached_provider_model_ids/provider_model_ids/fetch_api_models. - test_telegram_noise_filter.py: 15-platform copy-paste matrix over shared gateway.run logic → 3 representative platforms (55s → 3.9s). - test_gateway_shutdown.py: stop()'s 5s interrupt-deadline loop spun on MagicMock agents — interrupt.side_effect now clears _running_agents (22s → 1.0s). - test_gateway_inactivity_timeout.py poll-harness timings shrunk 3-5x (24s → 1.1s); test_mcp_stability.py backoff/SIGTERM-grace sleeps patched (15.4s → 2.5s); test_async_delegation.py negative-drain wait 5s → 0.5s. - test_telegram_init_deadline.py: loop-block margin restored to 1.0s with rationale comment — the watchdog-dump assertion needs the loop blocked well past deadline+grace under parallel load (flaked once in the 40-worker verification run at a 0.2s margin). Verification: full hermetic suite via scripts/run_tests.sh — 2,438 files, 21,718 tests passed, 0 failed, 293.9s wall. Suite totals vs original baseline: 46,820 → 19,757 test functions (−57.8%), wall 583.5s → 293.9s (−50%), subprocess CPU 13,564s → 11,623s.
53 lines
1.9 KiB
Python
53 lines
1.9 KiB
Python
"""Tests for the TUI-hot-path mouse-residue suppression.
|
||
|
||
The Python launcher (`hermes --tui …`) has a ~100–300ms cold-start window
|
||
where stdin is still in cooked + echo mode. If a previous Hermes session
|
||
left DEC mouse-tracking asserted, any mouse motion during that window
|
||
echoes literal ``^[[<…M`` text into the user's scrollback.
|
||
|
||
`_suppress_mouse_residue_early()` writes the disable sequence to stdout
|
||
before the heavy imports so the terminal stops emitting events ASAP.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import sys
|
||
from unittest.mock import patch
|
||
|
||
# Importing the module triggers `_suppress_mouse_residue_early()` at module
|
||
# scope. Under the test runner argv (`pytest …`) it's a no-op, but we import
|
||
# at file scope so individual tests don't race the import side-effect with
|
||
# their `patch("os.write")` context.
|
||
from hermes_cli.main import _suppress_mouse_residue_early
|
||
|
||
EXPECTED = (
|
||
b"\x1b[?1003l\x1b[?1002l\x1b[?1001l\x1b[?1000l\x1b[?9l"
|
||
b"\x1b[?1006l\x1b[?1005l\x1b[?1015l\x1b[?1016l\x1b[?2029l"
|
||
)
|
||
|
||
|
||
class TestEarlyMouseDisable:
|
||
|
||
|
||
def test_respects_diagnostic_escape_hatch(self, monkeypatch):
|
||
monkeypatch.setattr(sys, "argv", ["hermes", "--tui"])
|
||
monkeypatch.delenv("HERMES_TUI", raising=False)
|
||
monkeypatch.setenv("HERMES_TUI_NO_EARLY_DISABLE", "1")
|
||
|
||
with patch("os.write") as mock_write:
|
||
_suppress_mouse_residue_early()
|
||
|
||
mock_write.assert_not_called()
|
||
|
||
|
||
def test_oserror_is_swallowed(self, monkeypatch):
|
||
monkeypatch.setattr(sys, "argv", ["hermes", "--tui"])
|
||
monkeypatch.delenv("HERMES_TUI", raising=False)
|
||
monkeypatch.delenv("HERMES_TUI_NO_EARLY_DISABLE", raising=False)
|
||
|
||
def boom(*_a, **_k):
|
||
raise OSError("stdout closed")
|
||
|
||
with patch("os.isatty", return_value=True), patch("os.write", side_effect=boom):
|
||
# Must not propagate — startup hot path can never break.
|
||
_suppress_mouse_residue_early()
|