atlas-iac/dockerfiles/hermes-webui-smoke.py

175 lines
6.2 KiB
Python
Raw Normal View History

2026-08-23 04:42:08 +00:00
#!/usr/bin/env python3
"""Exercise branded PWA responses from a running upstream WebUI server."""
from __future__ import annotations
import json
import re
2026-08-23 04:42:08 +00:00
import sys
from collections.abc import Callable
from typing import Any
from urllib.parse import urljoin
from urllib.request import Request, urlopen
PNG_MAGIC = b"\x89PNG\r\n\x1a\n"
PERSONA_LINKS = (
"static/hermes-agent.ico",
"static/hermes-agent-192.png",
"static/hermes-agent-512.png",
)
HUX_LINKS = (
"static/hux/foundation.js",
"static/hux/runtime/wave_a_contract.js",
"static/hux/runtime/wave_b_runtime.js",
"static/hux/runtime/wave_c_multimodal_onboarding_release.js",
"static/hux/bootstrap.css",
"static/hux/bootstrap.js",
)
2026-08-23 04:42:08 +00:00
def _get(
url: str,
opener: Callable[..., Any],
) -> tuple[bytes, str]:
request = Request(url, headers={"Accept-Encoding": "identity"})
with opener(request, timeout=5) as response:
status = int(getattr(response, "status", 0))
if status != 200:
raise RuntimeError(f"GET {url} returned HTTP {status}")
body = response.read()
final_url = response.geturl()
return body, final_url
def _icon_sources(value: object) -> list[str]:
sources: list[str] = []
if isinstance(value, dict):
icons = value.get("icons")
if isinstance(icons, list):
for icon in icons:
if not isinstance(icon, dict) or not isinstance(icon.get("src"), str):
raise RuntimeError("manifest contains an invalid icon entry")
if icon.get("type") != "image/png":
raise RuntimeError("manifest contains a non-PNG icon")
sources.append(icon["src"])
for child in value.values():
if child is not icons:
sources.extend(_icon_sources(child))
elif isinstance(value, list):
for child in value:
sources.extend(_icon_sources(child))
return sources
def smoke(
base_url: str,
*,
opener: Callable[..., Any] = urlopen,
) -> dict[str, object]:
base_url = base_url.rstrip("/") + "/"
manifest_body, manifest_url = _get(urljoin(base_url, "manifest.json"), opener)
try:
manifest = json.loads(manifest_body)
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise RuntimeError("served /manifest.json is not valid branded JSON") from exc
if manifest.get("name") != "Hermes Chat" or manifest.get("short_name") != "Hermes":
raise RuntimeError("served /manifest.json is not branded for Hermes Chat")
expected = {
"static/hermes-agent-192.png",
"static/hermes-agent-512.png",
}
top_level = manifest.get("icons")
if not isinstance(top_level, list) or {
icon.get("src") for icon in top_level if isinstance(icon, dict)
} != expected:
raise RuntimeError("served /manifest.json has the wrong Hermes icons")
icon_sources = _icon_sources(manifest)
if not icon_sources:
raise RuntimeError("served /manifest.json has no icon URLs")
for source in icon_sources:
icon_body, _icon_url = _get(urljoin(manifest_url, source), opener)
if not icon_body.startswith(PNG_MAGIC):
raise RuntimeError(f"manifest icon is not PNG: {source}")
root_body, _root_url = _get(base_url, opener)
try:
root_html = root_body.decode("utf-8")
except UnicodeDecodeError as exc:
raise RuntimeError("served / is not UTF-8 HTML") from exc
for source in PERSONA_LINKS:
if source not in root_html:
raise RuntimeError(f"served / omitted Hermes persona link: {source}")
if "static/hermes-brand.css" not in root_html:
raise RuntimeError("served / omitted static/hermes-brand.css")
for source in HUX_LINKS:
if source not in root_html:
raise RuntimeError(f"served / omitted HUX browser asset: {source}")
asset_body, _asset_url = _get(urljoin(base_url, source), opener)
if not asset_body or b"<html" in asset_body[:200].lower():
raise RuntimeError(f"served HUX browser asset is invalid: {source}")
version_match = re.search(
r"window\.__HERMES_WEBUI_BUNDLE_VERSION__='([^']+)'",
root_html,
)
if not version_match:
raise RuntimeError("served / omitted the WebUI bundle identity")
client_version = version_match.group(1)
settings_body, _settings_url = _get(
urljoin(base_url, "api/settings"), opener
)
try:
settings = json.loads(settings_body)
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise RuntimeError("served /api/settings is not valid JSON") from exc
server_version = settings.get("webui_bundle_version")
if not isinstance(server_version, str) or server_version != client_version:
raise RuntimeError(
"served WebUI client/server release identities do not match"
)
worker_body, _worker_url = _get(urljoin(base_url, "sw.js"), opener)
try:
worker = worker_body.decode("utf-8")
except UnicodeDecodeError as exc:
raise RuntimeError("served /sw.js is not UTF-8 JavaScript") from exc
if f"hermes-shell-{client_version}" not in worker:
raise RuntimeError("served /sw.js uses a different release identity")
2026-08-23 04:42:08 +00:00
direct_icon, _direct_url = _get(
urljoin(base_url, "static/hermes-agent-192.png"), opener
)
if not direct_icon.startswith(PNG_MAGIC):
raise RuntimeError("served /static/hermes-agent-192.png is not PNG")
return {
"manifest": manifest_url,
"icon_requests": len(icon_sources),
"root": base_url,
"direct_icon": "static/hermes-agent-192.png",
"hux_assets": len(HUX_LINKS),
"release_identity": client_version,
2026-08-23 04:42:08 +00:00
}
def main() -> int:
if len(sys.argv) != 2:
raise SystemExit("usage: hermes-webui-smoke.py BASE_URL")
result = smoke(sys.argv[1])
print(
"Hermes WebUI smoke passed: "
f"manifest={result['manifest']} "
f"icon_requests={result['icon_requests']} "
f"hux_assets={result['hux_assets']} "
f"release_identity={result['release_identity']} "
2026-08-23 04:42:08 +00:00
"root=branded direct_icon=png"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())