From 74fcf7fd03c8bb9e86861994f0cb349a08c58f9f Mon Sep 17 00:00:00 2001 From: duffyduck Date: Thu, 24 Sep 2026 16:12:50 +0200 Subject: [PATCH] feat(diagnostic): Host-Agenten in der Satelliten-Flotte anzeigen (Phase E) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- diagnostic/index.html | 41 +++++++++++++++++++++++++++++++++++++++++ diagnostic/server.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/diagnostic/index.html b/diagnostic/index.html index fc773a5..903f7e0 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -1467,6 +1467,22 @@
(Lade...)
+
+

Host-Agenten ๐Ÿ’ป

+ +
+
+

+ Agenten, die DIREKT auf einem Rechner laufen (Binary + .env) und + sich ausgehend mit RVS verbinden โ€” ARIA steuert den Rechner damit auch + hinter NAT/Firewall. ARIA nutzt sie ueber host_exec & Co.; + Setup siehe host-agent/README. +

+
+
+
(Lade...)
+
+

Compute-Flotte ๐Ÿ–ฅ๏ธ

@@ -2138,6 +2154,7 @@ satellites.forEach(s => { if (s.online !== false) requestSatCreds(s.id); }); return; } + if (msg.type === 'host_update') { hosts = msg.hosts || []; renderHosts(); return; } if (msg.type === 'sat_creds_list_result') { const p = msg.payload || msg; const sat = p.satellite || ''; @@ -4426,6 +4443,7 @@ loadTriggers(); } else if (tab === 'satellites') { requestSatellites(); + requestHosts(); requestWorkers(); } } @@ -4557,6 +4575,29 @@ function requestSatCreds(id) { send({ action: 'sat_creds_list', satellite: id }); } + let hosts = []; // [{hostId, name, os, caps, control, online}] + function requestHosts() { send({ action: 'host_list' }); } + function renderHosts() { + const box = document.getElementById('host-list'); + if (!box) return; + if (!hosts.length) { + box.innerHTML = 'Kein Host-Agent verbunden. ' + + 'Baue die Binary (host-agent/build.sh), leg eine .env ' + + 'daneben und starte sie auf dem Ziel-Rechner.'; + return; + } + box.innerHTML = hosts.map(h => { + const dot = h.online ? '#34C759' : '#FF3B30'; + const caps = (h.caps || []).join(', ') || 'โ€”'; + const ctrl = h.control ? 'steuerbar' : 'CONTROL_ENABLED=false'; + return '
' + + '
' + + '๐Ÿ’ป ' + escapeHtml(h.name || h.hostId) + ' ' + + 'id=' + escapeHtml(h.hostId) + '
' + + '
' + escapeHtml(h.os || '') + ' ยท kann: ' + escapeHtml(caps) + ' ยท ' + ctrl + '
' + + '
'; + }).join(''); + } function scanSatellite(id) { satScanning = id; renderSatellites(); diff --git a/diagnostic/server.js b/diagnostic/server.js index 69fb485..e353878 100644 --- a/diagnostic/server.js +++ b/diagnostic/server.js @@ -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() }));