atlas-iac/dockerfiles/hermes-webui-brand-patch.py
2026-08-23 19:22:26 -03:00

119 lines
4.4 KiB
Python

#!/usr/bin/env python3
"""Apply fail-closed Hermes identity and PWA patches to pinned WebUI source."""
from __future__ import annotations
import os
from pathlib import Path
ROOT = Path(os.environ.get("HERMES_WEBUI_PATCH_ROOT", "/opt/hermes-webui"))
def replace_exact(path: Path, before: str, after: str, count: int = 1) -> None:
"""Replace one exact upstream fragment and reject pin drift."""
source = path.read_text(encoding="utf-8")
if source.count(before) != count:
raise SystemExit(
f"Hermes brand patch context changed in {path}: {before[:80]!r}"
)
path.write_text(source.replace(before, after, count), encoding="utf-8")
def replace_between_exact(path: Path, start: str, end: str, after: str) -> None:
"""Replace one uniquely bounded upstream region and reject ambiguous input."""
source = path.read_text(encoding="utf-8")
if source.count(start) != 1 or source.count(end) != 1:
raise SystemExit(
f"Hermes brand patch context changed in {path}: {start[:80]!r}"
)
start_index = source.index(start)
end_index = source.index(end, start_index)
path.write_text(source[:start_index] + after + source[end_index:], encoding="utf-8")
index = ROOT / "static/index.html"
replace_exact(index, "<title>Hermes</title>", "<title>Hermes Chat</title>")
replace_exact(
index,
"""<link rel="icon" type="image/svg+xml" href="static/favicon.svg">
<link rel="icon" type="image/png" sizes="32x32" href="static/favicon-32.png">
<link rel="shortcut icon" href="static/favicon.ico">""",
"""<link rel="icon" type="image/x-icon" href="static/hermes-agent.ico">
<link rel="icon" type="image/png" sizes="192x192" href="static/hermes-agent-192.png">
<link rel="icon" type="image/png" sizes="512x512" href="static/hermes-agent-512.png">""",
)
replace_exact(
index,
'<meta name="apple-mobile-web-app-title" content="Hermes">',
'<meta name="apple-mobile-web-app-title" content="Hermes Chat">',
)
replace_exact(
index,
'<link rel="apple-touch-icon" sizes="512x512" href="static/apple-touch-icon.png">',
'<link rel="apple-touch-icon" sizes="192x192" href="static/hermes-agent-192.png">',
)
replace_exact(
index,
'<meta name="theme-color" content="#FAF7F0" media="(prefers-color-scheme: light)">',
'<meta name="theme-color" content="#E8F1F2" media="(prefers-color-scheme: light)">',
)
replace_exact(
index,
'<meta name="theme-color" content="#141425" media="(prefers-color-scheme: dark)">',
'<meta name="theme-color" content="#0D1420" media="(prefers-color-scheme: dark)">',
)
replace_exact(
index,
'<meta name="theme-color" id="hermes-theme-color" content="#0D0D1A">',
'<meta name="theme-color" id="hermes-theme-color" content="#0D1420">',
)
replace_exact(
index,
"var c=t==='dark'?'#141425':'#FAF7F0';",
"var c=t==='dark'?'#0D1420':'#E8F1F2';",
)
replace_exact(
index,
'<link id="voiceInstrumentStyles" rel="stylesheet" href="static/atlas-voice.css?v=__WEBUI_VERSION__">',
'<link id="voiceInstrumentStyles" rel="stylesheet" href="static/atlas-voice.css?v=__WEBUI_VERSION__">\n'
'<link id="hermesBrandStyles" rel="stylesheet" href="static/hermes-brand.css?v=__WEBUI_VERSION__">',
)
replace_between_exact(
index,
' <span class="app-titlebar-icon" aria-hidden="true">\n',
' <span class="app-titlebar-title" id="appTitlebarTitle">Hermes</span>',
' <span class="app-titlebar-icon" aria-hidden="true">\n'
' <img src="static/hermes-agent-192.png" alt="">\n'
" </span>\n",
)
replace_exact(
index,
' <span class="app-titlebar-title" id="appTitlebarTitle">Hermes</span>',
' <span class="app-titlebar-title" id="appTitlebarTitle">Hermes Chat</span>',
)
replace_between_exact(
index,
' <div class="empty-logo"><svg',
' <h2 data-i18n="empty_title">',
' <div class="empty-logo">\n'
' <img class="hermes-agent-portrait" '
'src="static/hermes-agent-512.png" alt="Hermes Agent">\n'
' </div>\n',
)
service_worker = ROOT / "static/sw.js"
replace_exact(
service_worker,
" './static/style.css' + VQ,\n",
" './static/style.css' + VQ,\n './static/hermes-brand.css' + VQ,\n",
)
replace_exact(
service_worker,
" './static/favicon.svg',\n './static/favicon-32.png',\n './manifest.json',\n",
" './static/hermes-agent.ico',\n"
" './static/hermes-agent-192.png',\n"
" './static/hermes-agent-512.png',\n"
" './manifest.json',\n",
)