117 lines
4.8 KiB
Python
117 lines
4.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Install the inert HUX browser bundle into the pinned Hermes WebUI."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
|
|
PINNED_UPSTREAM_COMMIT = "7a94e34a6d639576576baa9131acf6765f6d2b98"
|
|
ROOT = Path(os.environ.get("HERMES_WEBUI_PATCH_ROOT", "/opt/hermes-webui"))
|
|
|
|
STYLES = (
|
|
"hux/foundation.css",
|
|
"hux/runtime/wave_a_activity_memory.css",
|
|
"hux/runtime/autonomy-privacy.css",
|
|
"hux/runtime/wave_b.css",
|
|
"hux/runtime/wave_c_multimodal_onboarding_release.css",
|
|
"hux/bootstrap.css",
|
|
)
|
|
SCRIPTS = (
|
|
"hux/foundation.js",
|
|
"hux/shell.js",
|
|
"hux/runtime/wave_a_contract.js",
|
|
"hux/runtime/wave_a_activity_memory.js",
|
|
"hux/runtime/autonomy-privacy.js",
|
|
"hux/runtime/wave_b_contract.js",
|
|
"hux/runtime/wave_b_projects_modes.js",
|
|
"hux/runtime/wave_b_artifacts_research.js",
|
|
"hux/runtime/wave_b_runtime.js",
|
|
"hux/runtime/wave_c_multimodal_onboarding_release.js",
|
|
"hux/bootstrap.js",
|
|
)
|
|
|
|
|
|
def _patched_index(source: str) -> str:
|
|
if "id=\"hermesHuxBootstrapStyles\"" in source or "static/hux/bootstrap.js" in source:
|
|
raise SystemExit("Hermes HUX browser patch is already installed")
|
|
if source.count("</head>") != 1 or source.count("</body>") != 1:
|
|
raise SystemExit("Hermes HUX index patch context changed")
|
|
if "const S={session:null" not in (ROOT / "static/ui.js").read_text(encoding="utf-8"):
|
|
raise SystemExit("Hermes HUX trusted session context changed")
|
|
links = "\n".join(
|
|
f'<link rel="stylesheet" href="static/{asset}?v=__WEBUI_VERSION__"'
|
|
+ (' id="hermesHuxBootstrapStyles">' if asset == "hux/bootstrap.css" else ">")
|
|
for asset in STYLES
|
|
)
|
|
scripts = "\n".join(
|
|
f'<script src="static/{asset}?v=__WEBUI_VERSION__" defer></script>'
|
|
for asset in SCRIPTS
|
|
)
|
|
return source.replace("</head>", f"{links}\n</head>", 1).replace(
|
|
"</body>", f"{scripts}\n</body>", 1
|
|
)
|
|
|
|
|
|
def _patched_worker(source: str) -> str:
|
|
if "'./static/hux/bootstrap.js' + VQ" in source:
|
|
raise SystemExit("Hermes HUX service-worker patch is already installed")
|
|
marker = " './static/style.css' + VQ,\n"
|
|
if source.count(marker) != 1:
|
|
raise SystemExit("Hermes HUX service-worker patch context changed")
|
|
entries = "".join(f" './static/{asset}' + VQ,\n" for asset in (*STYLES, *SCRIPTS))
|
|
return source.replace(marker, marker + entries, 1)
|
|
|
|
|
|
def _patched_cancel_stream(source: str) -> str:
|
|
"""Make the existing owner-bound cancel report only backend-confirmed cancellation."""
|
|
replacement = " return Boolean(respOk && respBody && respBody.ok===true && " \
|
|
"respBody.cancelled===true && respBody.stream_id===streamId);\n"
|
|
if replacement in source:
|
|
raise SystemExit("Hermes HUX cancel-result patch is already installed")
|
|
marker = " return respOk;\n}\n\nasync function cancelSessionStream"
|
|
if source.count(marker) != 1:
|
|
raise SystemExit("Hermes HUX cancel-result patch context changed")
|
|
return source.replace(marker, replacement + "}\n\nasync function cancelSessionStream", 1)
|
|
|
|
|
|
def _patched_start_context(source: str) -> str:
|
|
"""Accept only the context attached to the authoritative chat-start reply."""
|
|
marker = " const startData = postStartData || {};\n"
|
|
if "HermesHuxBootstrap.mergeTrustedContext" in source:
|
|
raise SystemExit("Hermes HUX chat-start patch is already installed")
|
|
if source.count(marker) != 1:
|
|
raise SystemExit("Hermes HUX chat-start patch context changed")
|
|
replacement = marker + (
|
|
" if(typeof HermesHuxBootstrap==='object' && S.session){\n"
|
|
" HermesHuxBootstrap.mergeTrustedContext(S.session, startData);\n"
|
|
" }\n"
|
|
)
|
|
return source.replace(marker, replacement, 1)
|
|
|
|
|
|
def apply(root: Path | None = None) -> None:
|
|
"""Patch the index and offline shell after validating every input."""
|
|
global ROOT
|
|
ROOT = root or ROOT
|
|
index = ROOT / "static/index.html"
|
|
worker = ROOT / "static/sw.js"
|
|
boot = ROOT / "static/boot.js"
|
|
messages = ROOT / "static/messages.js"
|
|
for asset in (*STYLES, *SCRIPTS):
|
|
if not (ROOT / "static" / asset).is_file():
|
|
raise SystemExit(f"Hermes HUX browser asset is missing: {asset}")
|
|
patched_index = _patched_index(index.read_text(encoding="utf-8"))
|
|
patched_worker = _patched_worker(worker.read_text(encoding="utf-8"))
|
|
patched_boot = _patched_cancel_stream(boot.read_text(encoding="utf-8"))
|
|
patched_messages = _patched_start_context(messages.read_text(encoding="utf-8"))
|
|
index.write_text(patched_index, encoding="utf-8")
|
|
worker.write_text(patched_worker, encoding="utf-8")
|
|
boot.write_text(patched_boot, encoding="utf-8")
|
|
messages.write_text(patched_messages, encoding="utf-8")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
apply()
|