Merge pull request #29724 from bbednarski9/bbednarski/nmf-41B-nemoflow-plugin

feat(middleware): add adaptive middleware to hermes-agent, consumed by NeMo-Relay
This commit is contained in:
kshitij 2026-06-06 10:46:41 -07:00 committed by GitHub
commit d4a7bfd3aa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 2170 additions and 151 deletions

View file

@ -18,8 +18,15 @@ from hermes_cli.plugins import (
get_plugin_command_handler,
get_plugin_commands,
get_pre_tool_call_block_message,
has_middleware,
resolve_plugin_command_result,
)
from hermes_cli.middleware import (
VALID_MIDDLEWARE,
apply_llm_request_middleware,
apply_tool_request_middleware,
run_tool_execution_middleware,
)
# ── Helpers ────────────────────────────────────────────────────────────────
@ -96,6 +103,223 @@ class TestPluginDiscovery:
assert "hello_plugin" in mgr._plugins
assert mgr._plugins["hello_plugin"].enabled
def test_plugin_can_register_and_invoke_middleware(self, tmp_path, monkeypatch):
plugins_dir = tmp_path / "hermes_test" / "plugins"
_make_plugin_dir(
plugins_dir,
"mw_plugin",
register_body=(
"ctx.register_middleware('llm_request', "
"lambda **kw: {'request': {**kw['request'], 'mw': True}})\n"
" ctx.register_middleware('tool_request', "
"lambda **kw: {'args': {**kw['args'], 'mw': True}})"
),
)
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes_test"))
mgr = PluginManager()
mgr.discover_and_load()
assert "llm_request" in VALID_MIDDLEWARE
assert "tool_request" in VALID_MIDDLEWARE
assert set(mgr._plugins["mw_plugin"].middleware_registered) == {"llm_request", "tool_request"}
assert mgr.invoke_middleware("llm_request", request={"messages": []}) == [
{"request": {"messages": [], "mw": True}}
]
assert mgr.invoke_middleware("tool_request", args={"path": "README.md"}) == [
{"args": {"path": "README.md", "mw": True}}
]
assert mgr.has_middleware("llm_request") is True
def test_execution_middleware_does_not_retry_downstream_failure(self, monkeypatch):
calls = []
def middleware(**kwargs):
return kwargs["next_call"](kwargs["args"])
manager = types.SimpleNamespace(_middleware={"tool_execution": [middleware]})
monkeypatch.setattr("hermes_cli.plugins.get_plugin_manager", lambda: manager)
def terminal(args):
calls.append(args)
raise RuntimeError("tool failed")
with pytest.raises(RuntimeError, match="tool failed"):
run_tool_execution_middleware("terminal", {"command": "false"}, terminal)
assert calls == [{"command": "false"}]
def test_middleware_helpers_skip_no_listener_work(self, monkeypatch):
manager = types.SimpleNamespace(_middleware={})
monkeypatch.setattr("hermes_cli.plugins.get_plugin_manager", lambda: manager)
request = {"messages": []}
args = {"path": "README.md"}
llm_result = apply_llm_request_middleware(request)
tool_result = apply_tool_request_middleware("read_file", args)
assert llm_result.payload is request
assert llm_result.original_payload is request
assert llm_result.changed is False
assert llm_result.trace == []
assert tool_result.payload is args
assert tool_result.original_payload is args
assert tool_result.changed is False
assert tool_result.trace == []
assert run_tool_execution_middleware("terminal", args, lambda payload: payload) is args
assert has_middleware("tool_request") is False
def test_request_middleware_changed_tracks_trace_not_deep_equality(self, monkeypatch):
def same_payload_middleware(**kwargs):
return {"args": kwargs["args"], "source": "same-payload"}
manager = types.SimpleNamespace(
_middleware={"tool_request": [same_payload_middleware]},
invoke_middleware=lambda kind, **kwargs: [same_payload_middleware(**kwargs)],
)
monkeypatch.setattr("hermes_cli.plugins.get_plugin_manager", lambda: manager)
args = {"path": "README.md"}
result = apply_tool_request_middleware("read_file", args)
assert result.payload == args
assert result.original_payload == args
assert result.changed is True
assert result.trace == [{"source": "same-payload"}]
def test_execution_middleware_post_next_call_error_does_not_retry(self, monkeypatch):
calls = []
def middleware(**kwargs):
result = kwargs["next_call"](kwargs["args"])
raise RuntimeError(f"post-processing failed after {result}")
manager = types.SimpleNamespace(_middleware={"tool_execution": [middleware]})
monkeypatch.setattr("hermes_cli.plugins.get_plugin_manager", lambda: manager)
def terminal(args):
calls.append(args)
return "terminal-result"
result = run_tool_execution_middleware("terminal", {"command": "printf ok"}, terminal)
assert result == "terminal-result"
assert calls == [{"command": "printf ok"}]
def test_execution_middleware_pre_next_call_error_fails_open_to_remaining_chain(self, monkeypatch):
calls = []
def failing_middleware(**kwargs):
calls.append("failing")
raise RuntimeError("middleware setup failed")
def downstream_middleware(**kwargs):
calls.append("downstream")
return kwargs["next_call"]({**kwargs["args"], "rewritten": True})
manager = types.SimpleNamespace(_middleware={"tool_execution": [failing_middleware, downstream_middleware]})
monkeypatch.setattr("hermes_cli.plugins.get_plugin_manager", lambda: manager)
def terminal(args):
calls.append(("terminal", args))
return args
result = run_tool_execution_middleware("terminal", {"command": "printf ok"}, terminal)
assert result == {"command": "printf ok", "rewritten": True}
assert calls == ["failing", "downstream", ("terminal", {"command": "printf ok", "rewritten": True})]
def test_execution_middleware_translated_downstream_failure_is_not_masked(self, monkeypatch):
calls = []
def middleware(**kwargs):
try:
return kwargs["next_call"](kwargs["args"])
except Exception as exc:
raise RuntimeError(f"translated downstream failure: {exc}") from exc
manager = types.SimpleNamespace(_middleware={"tool_execution": [middleware]})
monkeypatch.setattr("hermes_cli.plugins.get_plugin_manager", lambda: manager)
def terminal(args):
calls.append(args)
raise RuntimeError("terminal failed")
with pytest.raises(RuntimeError, match="translated downstream failure: terminal failed"):
run_tool_execution_middleware("terminal", {"command": "false"}, terminal)
assert calls == [{"command": "false"}]
def test_execution_middleware_downstream_base_exception_is_not_wrapped(self, monkeypatch):
calls = []
def middleware(**kwargs):
try:
return kwargs["next_call"](kwargs["args"])
except Exception as exc:
raise RuntimeError(f"middleware should not catch base exception: {exc}") from exc
manager = types.SimpleNamespace(_middleware={"tool_execution": [middleware]})
monkeypatch.setattr("hermes_cli.plugins.get_plugin_manager", lambda: manager)
def terminal(args):
calls.append(args)
raise KeyboardInterrupt()
with pytest.raises(KeyboardInterrupt):
run_tool_execution_middleware("terminal", {"command": "interrupt"}, terminal)
assert calls == [{"command": "interrupt"}]
def test_execution_middleware_double_next_call_does_not_run_terminal_twice(self, monkeypatch):
calls = []
def middleware(**kwargs):
first = kwargs["next_call"](kwargs["args"])
# Deliberate misuse: a second next_call() must not re-run the
# downstream tool. The chain surfaces it as an error and preserves
# the first (successful) downstream result.
kwargs["next_call"](kwargs["args"])
return first
manager = types.SimpleNamespace(_middleware={"tool_execution": [middleware]})
monkeypatch.setattr("hermes_cli.plugins.get_plugin_manager", lambda: manager)
def terminal(args):
calls.append(args)
return "terminal-result"
result = run_tool_execution_middleware("terminal", {"command": "printf ok"}, terminal)
assert result == "terminal-result"
assert calls == [{"command": "printf ok"}]
def test_request_middleware_tolerates_non_deepcopyable_payload(self, monkeypatch):
import threading
recorded = {}
def middleware(**kwargs):
recorded["args"] = kwargs["args"]
return None
manager = types.SimpleNamespace(
_middleware={"tool_request": [middleware]},
invoke_middleware=lambda kind, **kwargs: [middleware(**kwargs)],
)
monkeypatch.setattr("hermes_cli.plugins.get_plugin_manager", lambda: manager)
# threading.Lock is not deepcopyable; a hard deepcopy would raise.
args = {"command": "noop", "lock": threading.Lock()}
result = apply_tool_request_middleware("terminal", args)
# Middleware ran (payload was copied via the shallow fallback) and the
# non-deepcopyable member is shared by reference rather than aborting.
assert recorded["args"]["command"] == "noop"
assert result.payload["command"] == "noop"
assert result.payload["lock"] is args["lock"]
def test_discover_project_plugins(self, tmp_path, monkeypatch):
"""Plugins in ./.hermes/plugins/ are discovered."""
project_dir = tmp_path / "project"