Relay 0.9 discovers user and system plugins.toml files outside the Hermes home, so an exporter or middleware can apply to every Hermes session without any Hermes setting naming it. Hermes now says which files apply. The startup line that reports an active plugin host lists the files the activation loaded. `hermes doctor` gains a NeMo Relay Plugins section: it resolves the same layers through Relay's validator, which loads no plugin code and leaves the process-wide host alone, then lists each file, whether anything is enabled, and any error or warning Relay reports. A configuration Relay would reject counts as a doctor issue. Validation cannot load dynamic plugins, so a warning marks the row without counting as an issue. The docs give the user and system file locations for each platform and point to `hermes doctor`.
51 lines
2.2 KiB
Python
51 lines
2.2 KiB
Python
"""``hermes doctor`` names the Relay plugin files the runtime actually loads.
|
|
|
|
Relay discovers user and system ``plugins.toml`` files outside the Hermes home, so doctor is the one
|
|
Hermes surface that shows a user which files apply. It must agree with what initialization loads.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from agent import relay_runtime
|
|
from hermes_cli.doctor_config import _check_relay_plugins
|
|
|
|
ENABLED_OBSERVABILITY = (
|
|
"version = 1\n\n[[components]]\nkind = \"observability\"\nenabled = true\n\n[components.config]\nversion = 4\n"
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("explicit", [False, True], ids=["discovered", "explicit"])
|
|
def test_doctor_lists_the_files_the_runtime_loads(tmp_path, monkeypatch, capsys, explicit):
|
|
relay = pytest.importorskip("nemo_relay")
|
|
if getattr(relay, "_native", None) is None:
|
|
pytest.skip("NeMo Relay native binding is unavailable on this platform")
|
|
user_config = tmp_path / "xdg" / "nemo-relay" / "plugins.toml"
|
|
user_config.parent.mkdir(parents=True)
|
|
user_config.write_text(ENABLED_OBSERVABILITY, encoding="utf-8")
|
|
monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / "xdg"))
|
|
monkeypatch.setenv("ProgramData", str(tmp_path / "programdata"))
|
|
if explicit:
|
|
selected = tmp_path / "selected.toml"
|
|
selected.write_text(ENABLED_OBSERVABILITY, encoding="utf-8")
|
|
monkeypatch.setenv(relay_runtime.RELAY_PLUGINS_CONFIG_ENV, str(selected))
|
|
else:
|
|
monkeypatch.delenv(relay_runtime.RELAY_PLUGINS_CONFIG_ENV, raising=False)
|
|
|
|
_check_relay_plugins(False)
|
|
doctor_output = capsys.readouterr().out
|
|
|
|
relay_runtime._reset_for_tests()
|
|
host = relay_runtime.RelayRuntime(relay=relay, profile_key="profile")
|
|
try:
|
|
assert host._plugin_configuration_state is relay_runtime._RelayPluginConfigurationState.ACTIVE
|
|
loaded = relay_runtime._activation_config_paths(relay_runtime._PLUGIN_CONFIGURATION._activation)
|
|
finally:
|
|
host.shutdown()
|
|
relay_runtime._reset_for_tests()
|
|
|
|
assert (str(user_config) in loaded) is not explicit
|
|
assert "Relay plugins enabled" in doctor_output
|
|
assert all(path in doctor_output for path in loaded)
|
|
if explicit:
|
|
assert str(user_config) not in doctor_output
|