Loading...
diff --git a/cmd/web-ui/static/app.js b/cmd/web-ui/static/app.js index bc213bb..c62c918 100644 --- a/cmd/web-ui/static/app.js +++ b/cmd/web-ui/static/app.js @@ -48,6 +48,7 @@ let sessionsUnsubscribe = null; let openclawState = { instances: {} }; let openclawUnsubscribe = null; + let infraUnsubscribe = null; let swarmState = { services: {} }; // keyed by service name let agentsState = createAgentsState(); let agentsUnsubscribe = null; @@ -111,6 +112,10 @@ openclawUnsubscribe(); openclawUnsubscribe = null; } + if (infraUnsubscribe) { + infraUnsubscribe(); + infraUnsubscribe = null; + } if (agentsUnsubscribe) { agentsUnsubscribe(); agentsUnsubscribe = null; @@ -151,8 +156,8 @@ renderSessions(); } else if (path.startsWith('/agents')) { renderAgents(); - } else if (path.startsWith('/openclaw')) { - renderOpenClaw(); + } else if (path.startsWith('/infrastructure')) { + renderInfrastructure(); } else if (path.startsWith('/sessions/')) { renderSession(path.split('/sessions/')[1]); } else if (path.startsWith('/runs/')) { @@ -662,40 +667,54 @@ }); } - async function renderOpenClaw() { - app.innerHTML = '
Loading...
'; + async function renderInfrastructure() { + app.innerHTML = 'Loading...
'; - openclawUnsubscribe = subscribeWS(handleOpenClawWS); + infraUnsubscribe = subscribeWS(handleInfraWS); try { - const data = await api('/v1/events?event_type=openclaw.snapshot&limit=100'); - mergeOpenClawEvents(data.events || []); - if (isCurrentPath('/openclaw')) { - renderOpenClawGrid(); + const [ocData, swarmData] = await Promise.all([ + api('/v1/events?event_type=openclaw.snapshot&limit=100'), + api('/v1/events?event_type=swarm.snapshot&limit=10').catch(() => ({ events: [] })), + ]); + + mergeOpenClawEvents(ocData.events || []); + for (const evt of swarmData.events || []) mergeSwarmSnapshot(evt); + + if (isCurrentPath('/infrastructure')) { + renderInfraGrid(); } } catch (e) { - if (isCurrentPath('/openclaw')) { - app.innerHTML = `Error loading: ${escapeHTML(e.message)}
`; + if (isCurrentPath('/infrastructure')) { + app.innerHTML = `Error: ${escapeHTML(e.message)}
`; } } } - function handleOpenClawWS(msg) { - if (msg.type !== 'message') { + function handleInfraWS(msg) { + if (msg.type !== 'message') return; + + const eventType = getEnvelopeType(msg.data); + + if (eventType === 'openclaw.snapshot') { + mergeOpenClawEvents([msg.data]); + if (isCurrentPath('/infrastructure')) renderInfraGrid(); + if (isCurrentPath('/agents')) renderAgentVMStrip(); return; } - if (getEnvelopeType(msg.data) !== 'openclaw.snapshot') { + if (eventType === 'swarm.snapshot') { + mergeSwarmSnapshot(msg.data); + if (isCurrentPath('/infrastructure')) renderInfraGrid(); + renderSwarmStrip_dash(); return; } - mergeOpenClawEvents([msg.data]); - - if (isCurrentPath('/openclaw')) { - renderOpenClawGrid(); - } - if (isCurrentPath('/agents')) { - renderAgentVMStrip(); + if (eventType === 'swarm.service.snapshot') { + mergeSwarmServiceSnapshot(msg.data); + if (isCurrentPath('/infrastructure')) renderInfraGrid(); + renderSwarmStrip_dash(); + return; } } @@ -730,71 +749,231 @@ if (svc && svc.name) swarmState.services[svc.name] = svc; } - function renderOpenClawGrid() { - const names = Object.keys(openclawState.instances).sort(); - - if (names.length === 0) { - app.innerHTML = ` -No OpenClaw instances found
- `; - return; - } + function renderInfraGrid() { + const vmNames = Object.keys(openclawState.instances).sort(); + const services = Object.values(swarmState.services); app.innerHTML = `| Host | ${escapeHTML(inst.host || '-')} |
| Domain | ${escapeHTML(inst.domain || '-')} |
| vCPUs | ${host.vcpus || '-'} |
| Memory | ${escapeHTML(formatBytes(host.memory_kib ? host.memory_kib * 1024 : 0) || '-')} |
| Disk | ${escapeHTML(formatBytes(host.disk_actual_bytes) || '-')} |
| Autostart | ${host.autostart ? 'Yes' : 'No'} |
| Gateway | ${guest.service_active ? 'Active' : 'Inactive'} |
| HTTP | ${guest.http_status || 'N/A'} |
| Version | ${escapeHTML(guest.version || '-')} |
| Guest Mem | ${guest.memory_percent !== undefined ? guest.memory_percent.toFixed(1) : '-'}% |
| Guest Disk | ${guest.disk_percent !== undefined ? guest.disk_percent.toFixed(1) : '-'}% |
| Load | ${guest.load_average !== undefined ? guest.load_average.toFixed(2) : '-'} |
| Uptime | ${escapeHTML(guest.service_uptime || '-')} |
VMs
+ ${vmNames.length === 0 + ? 'No VM data
' + : `Services
+ ${services.length === 0 + ? 'No swarm service data
' + : `| Host | ${escapeHTML(inst.host || '-')} |
| Domain | ${escapeHTML(inst.domain || '-')} |
| vCPUs | ${host.vcpus || '-'} |
| Memory | ${escapeHTML(formatBytes(host.memory_kib ? host.memory_kib * 1024 : 0) || '-')} |
| Disk | ${escapeHTML(formatBytes(host.disk_actual_bytes) || '-')} |
| Autostart | ${host.autostart ? 'Yes' : 'No'} |
| Gateway | ${guest.service_active ? 'Active' : 'Inactive'} |
| HTTP | ${guest.http_status || 'N/A'} |
| Version | ${escapeHTML(guest.version || '-')} |
| Guest Mem | ${guest.memory_percent !== undefined ? guest.memory_percent.toFixed(1) : '-'}% |
| Guest Disk | ${guest.disk_percent !== undefined ? guest.disk_percent.toFixed(1) : '-'}% |
| Load | ${guest.load_average !== undefined ? guest.load_average.toFixed(2) : '-'} |
| Uptime | ${escapeHTML(guest.service_uptime || '-')} |
Loading...