feat(diagnostic): Host-Agenten in der Satelliten-Flotte anzeigen (Phase E)

Diagnostic-Server trackt host_hello/host_ping (hosts-Map), broadcastet
host_update und beantwortet die host_list-Action. UI: neues Panel
"Host-Agenten" im Satelliten-Tab — zeigt Name/OS/Caps/online + ob
CONTROL_ENABLED. Reine Sichtbarkeit; Steuerung laeuft ueber ARIA.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-09-24 16:12:50 +02:00
co-authored by Claude Opus 4.8
parent c7761284c7
commit 74fcf7fd03
2 changed files with 76 additions and 0 deletions
+35
View File
@@ -550,6 +550,21 @@ function broadcastSatellites() {
broadcast({ type: "sat_update", satellites: satelliteList() });
}
// ── Host-Agenten: Direktzugriff auf einen Rechner ────────────────
const hosts = new Map(); // hostId → {hostId, name, os, caps, control, last_seen}
function hostList() {
const now = Date.now();
return Array.from(hosts.values()).map(h => ({
hostId: h.hostId, name: h.name, os: h.os, caps: h.caps, control: h.control,
online: (now - (h.last_seen || 0)) < 300000,
}));
}
function broadcastHosts() {
broadcast({ type: "host_update", hosts: hostList() });
}
// ── Compute-Fleet: GPU-Worker (voxtral/whisper/f5tts/llm) ──────────
// Worker melden sich per worker_hello + halten sich per worker_ping (busy) frisch.
const workers = new Map(); // instanceId → {instanceId, service, node, gpus, model, busy, last_seen}
@@ -1065,6 +1080,21 @@ function connectRVS(forcePlain) {
});
broadcastSatellites();
}
} else if (msg.type === "host_hello") {
// Ein Host-Agent (Direktzugriff auf einen Rechner) meldet sich.
const p = msg.payload || {};
if (p.hostId) {
const wasKnown = hosts.has(p.hostId);
hosts.set(p.hostId, {
hostId: p.hostId, name: p.name || p.hostId, os: p.os || "",
caps: p.caps || [], control: !!p.control, last_seen: Date.now(),
});
if (!wasKnown) broadcastHosts();
else hosts.get(p.hostId).last_seen = Date.now();
}
} else if (msg.type === "host_ping") {
const p = msg.payload || {};
if (p.hostId && hosts.has(p.hostId)) hosts.get(p.hostId).last_seen = Date.now();
} else if (msg.type === "sat_devices") {
// Antwort eines Satelliten auf sat_discover → Geraeteliste an Browser.
const p = msg.payload || {};
@@ -2721,6 +2751,8 @@ wss.on("connection", (ws) => {
if (currentDiskStatus) ws.send(JSON.stringify(currentDiskStatus));
// Aktuell bekannte Satelliten mitgeben (RVS replayt sat_hello nicht).
ws.send(JSON.stringify({ type: "sat_update", satellites: satelliteList() }));
// Aktuell bekannte Host-Agenten mitgeben.
ws.send(JSON.stringify({ type: "host_update", hosts: hostList() }));
// Aktuell bekannte Compute-Worker mitgeben (RVS replayt worker_hello nicht).
ws.send(JSON.stringify({ type: "worker_update", workers: workerList() }));
@@ -2754,6 +2786,9 @@ wss.on("connection", (ws) => {
} else if (msg.action === "sat_list") {
// Browser will die aktuelle Satelliten-Liste.
ws.send(JSON.stringify({ type: "sat_update", satellites: satelliteList() }));
} else if (msg.action === "host_list") {
// Browser will die aktuelle Host-Agenten-Liste.
ws.send(JSON.stringify({ type: "host_update", hosts: hostList() }));
} else if (msg.action === "worker_list") {
// Browser will die aktuelle Compute-Flotte.
ws.send(JSON.stringify({ type: "worker_update", workers: workerList() }));