fix: address PR #12 review comments on refactored tool files

- Add 'logs' to _DOCKER_SUBACTIONS so the validation guard passes through
  to the informative ToolError rather than a generic 'Invalid action' (P1)
- Add inline comments to _SYSTEM_QUERIES explaining that 'network' and
  'variables' share the vars root field but fetch different subfields (P3)
- Process system/server response into a structured summary dict instead
  of returning raw GraphQL data directly (P3)
This commit is contained in:
Jacob Magar 2026-04-06 15:24:16 -04:00
parent a0d23b8661
commit f4adb4e8b9
2 changed files with 29 additions and 2 deletions

View file

@ -31,7 +31,10 @@ _DOCKER_MUTATIONS: dict[str, str] = {
"stop": "mutation StopContainer($id: PrefixedID!) { docker { stop(id: $id) { id names state status } } }",
}
_DOCKER_SUBACTIONS: set[str] = set(_DOCKER_QUERIES) | set(_DOCKER_MUTATIONS) | {"restart"}
# "logs" has no GraphQL query (field removed in Unraid 7.2.x) but is still a
# recognised subaction so validation passes and the informative ToolError below
# is returned rather than a generic "Invalid action" message.
_DOCKER_SUBACTIONS: set[str] = set(_DOCKER_QUERIES) | set(_DOCKER_MUTATIONS) | {"restart", "logs"}
_DOCKER_NEEDS_CONTAINER_ID = {"start", "stop", "details", "restart"}
_DOCKER_ID_PATTERN = re.compile(r"^[a-f0-9]{64}(:[a-z0-9]+)?$", re.IGNORECASE)
_DOCKER_SHORT_ID_PATTERN = re.compile(r"^[a-f0-9]{12,63}$", re.IGNORECASE)
@ -131,6 +134,13 @@ async def _handle_docker(
return dict(net)
raise ToolError(f"Network '{network_id}' not found.")
if subaction == "logs":
raise ToolError(
"Container logs are not available via the Unraid GraphQL API. "
"Use the Unraid terminal or SSH to run: "
f"`docker logs {container_id or '<container_id>'} --tail 100`"
)
if subaction == "restart":
actual_id = await _resolve_container_id(container_id or "", strict=True)
stop_data = await _client.make_graphql_request(

View file

@ -43,6 +43,8 @@ _SYSTEM_QUERIES: dict[str, str] = {
}
}
""",
# Uses the vars root field — returns only the network-access subset
# (port, portssl, localTld, useSsl) alongside servers for URL construction.
"network": """
query GetNetworkInfo {
servers { id name status wanip lanip localurl remoteurl }
@ -54,6 +56,9 @@ _SYSTEM_QUERIES: dict[str, str] = {
registration { id type keyFile { location } state expiration updateExpiration }
}
""",
# Uses the vars root field — returns a broad subset of system variables.
# Shares the same GraphQL root as "network" but requests a different field
# set; no overlap occurs because GraphQL returns only the requested subfields.
"variables": """
query GetSelectiveUnraidVariables {
vars {
@ -206,7 +211,19 @@ async def _handle_system(subaction: str, device_id: str | None) -> dict[str, Any
values = settings["unified"].get("values") or {}
return dict(values) if isinstance(values, dict) else {"raw": values}
if subaction == "server":
return data
info = data.get("info") or {}
summary: dict[str, Any] = {}
if info.get("os"):
summary["hostname"] = info["os"].get("hostname")
summary["uptime"] = info["os"].get("uptime")
if info.get("versions") and info["versions"].get("core"):
summary["unraid_version"] = info["versions"]["core"].get("unraid")
summary["machine_id"] = info.get("machineId")
summary["time"] = info.get("time")
array = data.get("array") or {}
summary["array_state"] = array.get("state")
summary["online"] = data.get("online")
return summary
if subaction == "network":
servers_data = data.get("servers") or []
vars_data = data.get("vars") or {}