docs/web-ui.md (1315 lines) split into three sub-files: - docs/web-ui/shape.md — shared SPA skeleton, SSE multiplexing, Worker-death self-heal, terminal pane, listener bind, relative paths, atomic repaint, side panel - docs/web-ui/dashboard.md — SW4RM/Y3R/SYST3M/SCH3DUL3S/S3TT1NGS tabs, container row, topology tree, selection bar, approval card, dashboard endpoints + event channel - docs/web-ui/agent.md — header, terminal, composer, inbox, live view, slash commands, per-agent endpoints, stats page docs/web-ui.md replaced with a thin index linking all three. Section anchors in docs (gateway.md, gotchas.md), Rust doc comments (hive-ag3nt/src/web_ui.rs), and nix/templates/weston-vnc.nix updated to point at the correct sub-file. README and CLAUDE.md file-map updated with sub-file links. Inline // comments in frontend source left unchanged (they reference the index which redirects to the right sub-file).
109 lines
4.5 KiB
Nix
109 lines
4.5 KiB
Nix
{
|
|
pkgs,
|
|
lib,
|
|
config,
|
|
...
|
|
}:
|
|
{
|
|
# Optional Weston (Wayland compositor) with the VNC backend,
|
|
# surfaced as a per-agent `hyperhive.gui.enable` option. Imported
|
|
# from harness-base.nix so every sub-agent + the manager sees the
|
|
# option; only those that flip it on get the service.
|
|
#
|
|
# Port allocation, weston bind-address quirk, PAM service name, the
|
|
# Type=simple choice, idle-time=0: all in
|
|
# docs/gotchas.md::Weston VNC compositor.
|
|
# Harness-side WebSocket relay shape: docs/web-ui/agent.md::Per-agent
|
|
# endpoints (`/screen` + `/screen/ws`).
|
|
|
|
options.hyperhive.gui.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Run Weston with the VNC backend as a systemd service, for
|
|
in-browser GUI access via the harness `/screen/ws` WebSocket
|
|
relay. Renders in software (pixman) — no GPU, DRM, or VT
|
|
access, so no extra container capabilities are needed.
|
|
|
|
The VNC port is a deterministic FNV-1a hash of the agent name
|
|
mapped into `[15900, 16799]`, written to
|
|
`/etc/hyperhive/gui.json` at service start so the harness can
|
|
relay connections without a separate config flag. The unit is
|
|
`Type = "simple"` so a misconfigured weston degrades to a
|
|
restart loop instead of blocking `nixos-container update`.
|
|
'';
|
|
};
|
|
|
|
config = lib.mkIf config.hyperhive.gui.enable {
|
|
# neatvnc ≥ 0.9 always calls the PAM auth callback for Apple-DH
|
|
# (type 30), regardless of weston.ini auth-method=none.
|
|
# pam_permit.so accepts the browser's empty Apple-DH credentials.
|
|
# Service name MUST be the literal `weston-remote-access` — that's
|
|
# the string libweston passes to pam_start() in libweston/auth.c.
|
|
security.pam.services."weston-remote-access".text = ''
|
|
auth sufficient pam_permit.so
|
|
account sufficient pam_permit.so
|
|
session sufficient pam_permit.so
|
|
'';
|
|
|
|
systemd.services.weston = {
|
|
description = "Weston Wayland compositor (VNC backend)";
|
|
after = [ "network.target" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
serviceConfig = {
|
|
Type = "simple";
|
|
StateDirectory = "weston";
|
|
Environment = "XDG_RUNTIME_DIR=/run/user/0";
|
|
# Wrapper script: computes the deterministic VNC port, writes
|
|
# /etc/hyperhive/gui.json for the harness, then execs weston.
|
|
# `exec` keeps the PID stable so systemd tracks the weston
|
|
# process correctly under Type=simple.
|
|
ExecStart = pkgs.writeShellScript "weston-vnc" ''
|
|
mkdir -p /run/user/0 && chmod 700 /run/user/0 || true
|
|
|
|
# --- Compute deterministic VNC port via FNV-1a ---
|
|
# Agent name = container hostname with leading `h-` stripped.
|
|
# Read from /etc/hostname (always present in NixOS containers)
|
|
# to avoid depending on `hostname` (lives in pkgs.inetutils,
|
|
# not pkgs.coreutils).
|
|
RAW_HOST=$(${pkgs.coreutils}/bin/cat /etc/hostname)
|
|
AGENT_NAME=$(${pkgs.coreutils}/bin/printf '%s' "$RAW_HOST" \
|
|
| ${pkgs.gnused}/bin/sed 's/^h-//')
|
|
hash=2166136261
|
|
for byte in $(${pkgs.coreutils}/bin/printf '%s' "$AGENT_NAME" \
|
|
| ${pkgs.coreutils}/bin/od -An -tu1 \
|
|
| ${pkgs.coreutils}/bin/tr -s ' \n' ' '); do
|
|
[ -n "$byte" ] || continue
|
|
hash=$(( ((hash ^ byte) * 16777619) & 4294967295 ))
|
|
done
|
|
VNC_PORT=$((15900 + hash % 900))
|
|
|
|
# Marker file the harness reads at startup.
|
|
${pkgs.coreutils}/bin/mkdir -p /etc/hyperhive
|
|
${pkgs.coreutils}/bin/printf '{"vnc_port":%d,"auth":"none"}\n' \
|
|
"$VNC_PORT" > /etc/hyperhive/gui.json || true
|
|
|
|
# --disable-transport-layer-security: skips the VeNCrypt TLS
|
|
# wrapper so plain auth types (incl. Apple-DH type 30) are
|
|
# advertised directly. [core] idle-time=0 disables the
|
|
# compositor's 300s idle/lock screen.
|
|
WESTON_INI=$(${pkgs.coreutils}/bin/mktemp /tmp/weston-XXXXXX.ini)
|
|
${pkgs.coreutils}/bin/printf '[core]\nidle-time=0\n\n[vnc]\nauth-method=none\n' > "$WESTON_INI"
|
|
|
|
exec ${pkgs.weston}/bin/weston \
|
|
--config="$WESTON_INI" \
|
|
--backend=vnc-backend.so \
|
|
--renderer=pixman \
|
|
--port="$VNC_PORT" \
|
|
--disable-transport-layer-security
|
|
'';
|
|
Restart = "on-failure";
|
|
RestartSec = "5s";
|
|
};
|
|
};
|
|
|
|
# weston on the agent's interactive PATH so claude can run Wayland
|
|
# clients / weston-info against the compositor.
|
|
environment.systemPackages = [ pkgs.weston ];
|
|
};
|
|
}
|