Some checks failed
plugin-tests / test (push) Failing after 6s
Per sot/03-PROTOCOLS/CORTEX-OS-UMBRELLA-VIZ-PRD.md. Living-graph panel
inside hermes-webui consuming curator-maintained graph/umbrella.json
(UI-stable v1.0 schema emitted by curator-planb sweep.py v0.2).
routes/umbrella.py — 3 endpoints:
GET /umbrella → redirect to static panel HTML
GET /api/umbrella → graph/umbrella.json contents
GET /api/umbrella/doc?path=X → markdown body for a node's source_path
(path-traversal guarded; 50KB cap)
static/umbrella.{html,css,js} — Cytoscape.js v3.30.2 (CDN) render:
- 8 node types: doc/profile/skill/mcp_server/sovereign_api/cortex_tool/
external_dep/credential — each gets distinct color + shape
- 5 edge types: depends_on/governs/consumes/produces/supersedes
- filter chips (toggle node type visibility)
- layout switcher (force/tier/concentric)
- search (dim non-matching nodes)
- click node → side panel w/ frontmatter + markdown body + in/out edges
- edge-list buttons jump between connected nodes
Plan B brand-aligned dark theme; DESIGN.md 8-property subset
(backgroundColor/textColor/typography/rounded/padding/size/height/width).
svrnty_nav.js bundled (sidebar nav integration — non-umbrella scope).
CONNECTION-MAP.md regenerated via scripts/ast-connection-map.py.
plugin.py route-list extended w/ "umbrella" + injects umbrella assets via
the standard static dir registration.
Module import: ✓ (python3 -c "import routes.umbrella" clean).
Graph artifact verified: 81 nodes / 120 edges live in graph/umbrella.json.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
78 lines
3.6 KiB
Python
78 lines
3.6 KiB
Python
"""svrnty-hermes-webui-plugin — entry point.
|
|
|
|
Called by hermes-webui's plugin loader at startup (after the env var
|
|
HERMES_WEBUI_PYTHON_PLUGIN points the loader at this module).
|
|
|
|
The loader passes a single `api` argument exposing 6 methods (see CLAUDE.md +
|
|
protocol PRD §5.1). This module's job is to wire every route + static dir +
|
|
asset injection that defines the Svrnty surface on hermes-webui.
|
|
|
|
Keep this file thin. Route logic lives in `routes/<feature>.py`. Static lives
|
|
in `static/`. The map of every upstream dependency is in CONNECTION-MAP.md
|
|
(AST-generated by scripts/ast-connection-map.py).
|
|
"""
|
|
import os
|
|
from pathlib import Path
|
|
|
|
# Static + asset URL prefix (per protocol §12, decision Q5: /plugins/svrnty/<asset>)
|
|
STATIC_PREFIX = "svrnty"
|
|
STATIC_DIR = Path(__file__).resolve().parent / "static"
|
|
|
|
|
|
def register(api):
|
|
"""Wire every Svrnty modification to hermes-webui.
|
|
|
|
`api` is the loader-provided extension surface (6 methods). Treat it as the
|
|
ONLY public contract. Touching anything else in hermes-webui requires a
|
|
`CONNECTION-MAP.md` forced-internal entry with justification.
|
|
"""
|
|
log = api.logger("svrnty.plugin")
|
|
log.info("svrnty-hermes-webui-plugin: registering")
|
|
|
|
# Brand skin: serve static dir + inject CSS/JS into every page load.
|
|
if STATIC_DIR.exists():
|
|
api.register_static(STATIC_PREFIX, str(STATIC_DIR))
|
|
api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/app.css")
|
|
api.inject_script(f"/plugins/{STATIC_PREFIX}/app.js")
|
|
# Sidebar nav glue — MUST load before tool panel scripts so its
|
|
# switchPanel wrap is in place when panels listen for it.
|
|
api.inject_script(f"/plugins/{STATIC_PREFIX}/svrnty_nav.js")
|
|
# Adwright tool panel — content mounts into <main>, visibility keyed
|
|
# off main.svrnty-showing-adwright (set by svrnty_nav.js wrapper).
|
|
api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/adwright.css")
|
|
api.inject_script(f"/plugins/{STATIC_PREFIX}/adwright.js")
|
|
# BTE Command Center panel — same pattern (main.svrnty-showing-bte).
|
|
api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/bte.css")
|
|
api.inject_script(f"/plugins/{STATIC_PREFIX}/bte.js")
|
|
log.info("static + assets wired at /plugins/%s/", STATIC_PREFIX)
|
|
|
|
# Routes — each feature lives in its own module under routes/.
|
|
# Phase 2 will populate these. Import-and-register pattern; failures are
|
|
# logged but don't take down the rest of the plugin.
|
|
for route_module in _phase2_routes():
|
|
try:
|
|
mod = __import__(f"routes.{route_module}", fromlist=["register"])
|
|
mod.register(api)
|
|
log.info("route module loaded: %s", route_module)
|
|
except ImportError as e:
|
|
log.warning("route module %s not yet implemented (Phase 2): %s", route_module, e)
|
|
except Exception as e:
|
|
log.error("route module %s failed to register: %s", route_module, e)
|
|
|
|
log.info("svrnty-hermes-webui-plugin: registration complete")
|
|
|
|
|
|
def _phase2_routes():
|
|
"""Routes to attempt loading. Returns module names under routes/.
|
|
|
|
Phase 2 migrates the existing fork commits into these modules. Until then,
|
|
ImportError is logged + swallowed so the plugin loads cleanly.
|
|
"""
|
|
return [
|
|
"transcribe", # P2.A — STT + voice-message audio processor ✓
|
|
"vault_status", # P2.B — vault connections status ✓
|
|
"adwright", # P2.C — Adwright tool panel routes (PRD §5+§6) ✓
|
|
"bte_proxy", # P2.D — BTE Command Center same-origin proxy (PRD §3) ✓
|
|
"umbrella", # P2.E — cortex-os umbrella graph viz (UMBRELLA-VIZ-PRD) ✓
|
|
]
|