From 2497ec5126fa936205f6551ff91e406fc5992bcd Mon Sep 17 00:00:00 2001
From: Teknium <127238744+teknium1@users.noreply.github.com>
Date: Wed, 2 Sep 2026 15:33:48 -0700
Subject: [PATCH 01/14] refactor(web_server): extract dashboard
SPA/theme/plugin-hub cluster to web_server_dashboard
---
hermes_cli/web_server.py | 1076 +--------------------------
hermes_cli/web_server_dashboard.py | 1096 ++++++++++++++++++++++++++++
2 files changed, 1112 insertions(+), 1060 deletions(-)
create mode 100644 hermes_cli/web_server_dashboard.py
diff --git a/hermes_cli/web_server.py b/hermes_cli/web_server.py
index a6a37e655e..d186ce559b 100644
--- a/hermes_cli/web_server.py
+++ b/hermes_cli/web_server.py
@@ -21,7 +21,6 @@ from datetime import datetime, timezone
import hashlib
import hmac
import inspect
-import importlib.util
import ipaddress
import json
import logging
@@ -80,7 +79,6 @@ from gateway.status import ( # noqa: F401 — late-bound by web_routers/status
get_runtime_status_running_pid,
read_runtime_status,
)
-from utils import env_var_enabled
try:
from fastapi import FastAPI, HTTPException, Request, WebSocket, WebSocketDisconnect
@@ -99,8 +97,7 @@ except ImportError:
FastAPI, HTTPException, Request, WebSocket, WebSocketDisconnect,
)
from fastapi.middleware.cors import CORSMiddleware
- from fastapi.responses import FileResponse, HTMLResponse, JSONResponse, Response
- from fastapi.staticfiles import StaticFiles
+ from fastapi.responses import JSONResponse
from starlette.concurrency import run_in_threadpool
except Exception:
raise SystemExit(
@@ -7754,569 +7751,21 @@ def _get_console_executor() -> concurrent.futures.ThreadPoolExecutor:
return _console_executor
-def _normalise_prefix(raw: Optional[str]) -> str:
- """Normalise an X-Forwarded-Prefix header value.
-
- Thin re-export of :func:`hermes_cli.dashboard_auth.prefix.normalise_prefix`
- — the single source of truth lives in the dashboard_auth package so
- the gate middleware, the OAuth routes, the cookie helpers, and the
- SPA mount all agree on validation rules.
- """
- from hermes_cli.dashboard_auth.prefix import normalise_prefix
- return normalise_prefix(raw)
-
-
-def _render_active_theme_bootstrap_css() -> str:
- """Critical-CSS shim for the active user theme.
-
- Returns a ```` escape — current values are well-known
- # hex/font strings, but this keeps the helper safe if it is
- # later extended to ship user-authored CSS literals.
- def _esc(s: str) -> str:
- return str(s).replace("", "<\\/")
- # Variable names MUST match what the bundle actually consumes:
- # - ``--background-base`` / ``--midground-base`` come from
- # ``layerVars()`` in ``web/src/themes/context.tsx``.
- # - ``--theme-font-sans`` / ``--theme-base-size`` come from
- # ``typographyVars()`` there, and ``index.css`` applies them
- # via ``html{font-family:var(--theme-font-sans);
- # font-size:var(--theme-base-size)}``.
- # The ``html,body`` canvas rule references the SAME variables
- # instead of literal values so runtime theme switches stay
- # live: ``applyTheme()`` writes these vars as inline styles on
- # ``documentElement``, which outrank this stylesheet block in
- # the cascade — the rule below re-resolves automatically and
- # never goes stale when the user picks a different theme.
- return (
- '"
- )
- return ""
- except Exception:
- _log.debug("theme bootstrap render failed", exc_info=True)
- return ""
-
-
-# Hashed bundle assets (``/assets/-.``) are immutable
-# by construction: any content change produces a new filename, and the entry
-# point (index.html) is served ``no-store`` so it always references the
-# current hashes. A year-long immutable cache lets browsers skip even the
-# revalidation round-trip on every dashboard load.
-_IMMUTABLE_ASSET_CACHE_CONTROL = "public, max-age=31536000, immutable"
-
-
-def mount_spa(application: FastAPI):
- """Mount the built SPA. Falls back to index.html for client-side routing.
-
- The session token is injected into index.html via a ``"
- "Headless backend (hermes serve): web UI disabled — use "
- "`hermes dashboard` for the browser UI."
- "