"""The host_agent plugin's MCP tools.""" from datetime import datetime, timedelta, timezone from types import SimpleNamespace as NS from unittest.mock import MagicMock import plugins.host_agent as agent_plugin from plugins.host_agent.mcp_tools import agent_state NOW = datetime(2026, 10, 6, 12, 0, tzinfo=timezone.utc) def test_agent_state(): assert agent_state(NS(last_seen_at=None), NOW, 180) == "pending" assert agent_state(NS(last_seen_at=NOW - timedelta(seconds=60)), NOW, 180) == "reporting" assert agent_state(NS(last_seen_at=NOW - timedelta(minutes=10)), NOW, 180) == "stale" def test_plugin_exposes_the_mcp_hooks(): reg = MagicMock() agent_plugin.register_mcp_tools(reg) assert [c.args[0].__name__ for c in reg.call_args_list] == [ "list_agents", "list_maintenance_plans", "get_maintenance_job", "run_maintenance"] roles = {c.args[0].__name__: c.kwargs["role"] for c in reg.call_args_list} assert roles["run_maintenance"].value == "admin" # as Update now on the page assert roles["get_maintenance_job"].value == "viewer" assert callable(agent_plugin.mcp_overview) def test_a_job_row_says_what_it_did_and_when_it_gives_up(): from plugins.host_agent.mcp_tools import _job_row job = NS(id="j1", host_id="h1", state="rebooting", state_at=NOW - timedelta(minutes=5), reboot_policy="if_required", packages=12, reboot_needed=True, back_at=None, node_id="n1", drain_host_id="h2", detail=None, created_by=None, run_id="r1", created_at=NOW - timedelta(minutes=20), finished_at=None, drained_at=NOW - timedelta(minutes=11), docker_update=False, checked={"pending": 12, "docker_packages": [], "containers": []}) row = _job_row(job, {"h1": "web-1", "h2": "mgr-1"}, NOW) assert (row["host"], row["drained_by"], row["label"], row["active"]) == ( "web-1", "mgr-1", "Rebooting", True) assert row["started_by"] == "maintenance plan" and row["state_age_s"] == 300 assert row["gives_up_at"] == (NOW + timedelta(minutes=25)).isoformat().replace("+00:00", "Z") done = NS(**{**job.__dict__, "state": "done", "back_at": NOW, "finished_at": NOW, "created_by": "u1", "run_id": None}) row = _job_row(done, {"h1": "web-1", "u1": "alice"}, NOW) assert row["summary"] == "Done: 12 packages updated, rebooted" assert row["started_by"] == "alice" and row["gives_up_at"] is None and not row["active"]