Files
2026-07-13 13:12:00 +08:00

77 lines
2.5 KiB
Python

"""Tests for the Hermes pre_tool_call policy hook's relay-tool skip.
Omnigent relay tools (surfaced into Hermes as ``mcp_omnigent_*``) are gated when
the relay dispatches them back through the server's tool path. The hook must NOT
gate them a second time (that parks a duplicate approval card whose long-poll
hangs, wedging the turn). Hermes' own tools are still gated here.
"""
from __future__ import annotations
import io
import json
import pytest
from omnigent.inner import hermes_policy_hook
@pytest.fixture
def wired_env(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("_OMNIGENT_SERVER_URL", "http://localhost:6767")
monkeypatch.setenv("_OMNIGENT_SESSION_ID", "conv_test")
def _run(monkeypatch: pytest.MonkeyPatch, tool_name: str) -> tuple[dict, bool]:
"""Run the hook with *tool_name*; return (stdout_json, server_was_called)."""
called = {"hit": False}
def _spy(*_args, **_kwargs):
called["hit"] = True
class _R:
def json(self) -> dict:
return {"result": "POLICY_ACTION_ALLOW"}
return _R()
monkeypatch.setattr("omnigent.native_policy_hook.post_evaluate_with_retry", _spy, raising=True)
monkeypatch.setattr(
"sys.stdin",
io.StringIO(json.dumps({"tool_name": tool_name, "tool_input": {}})),
)
out = io.StringIO()
monkeypatch.setattr("sys.stdout", out)
hermes_policy_hook.main()
return json.loads(out.getvalue() or "{}"), called["hit"]
@pytest.mark.parametrize(
"tool_name",
[
"mcp_omnigent_sys_session_get_info", # hermes single-underscore form
"mcp_omnigent_sys_os_write",
"mcp__omnigent__list_comments", # native double-underscore form
],
)
def test_relay_tools_are_skipped(
monkeypatch: pytest.MonkeyPatch, wired_env: None, tool_name: str
) -> None:
result, server_called = _run(monkeypatch, tool_name)
# Allow (empty object) WITHOUT hitting /policies/evaluate — the dispatch
# gate is the single authoritative gate for these tools.
assert result == {}
assert server_called is False
@pytest.mark.parametrize(
"tool_name", ["terminal", "str_replace_editor", "mcp_github_create_issue"]
)
def test_native_and_other_mcp_tools_are_still_gated(
monkeypatch: pytest.MonkeyPatch, wired_env: None, tool_name: str
) -> None:
_result, server_called = _run(monkeypatch, tool_name)
# Hermes' own tools (and non-Omnigent MCP servers) do NOT round-trip the
# relay, so the hook stays their policy gate.
assert server_called is True