#!/usr/bin/env node /** * BlackRoad OS - Live Agent Dashboard Server * * Connects to: * - Raspberry Pi fleet via SSH (alice, aria, octavia, lucidia) * - DigitalOcean Droplet (shellfish) for NATS * - GitHub API for repo/PR data * - Streams real-time data to dashboard via WebSocket */ const WebSocket = require('ws'); const { spawn } = require('child_process'); const http = require('http'); const fs = require('fs'); const path = require('path'); // Configuration const PI_NODES = [ { id: 'alice', host: '192.168.4.49', user: 'pi', hailo: true }, { id: 'aria', host: '192.168.4.82', user: 'pi', hailo: true }, { id: 'octavia', host: '192.168.4.81', user: 'pi', hailo: true }, { id: 'lucidia', host: '192.168.4.38', user: 'pi', hailo: true } ]; const CLOUD_NODES = [ { id: 'shellfish', host: '174.138.44.45', user: 'pi', role: 'NATS Hub' } ]; const LOGICAL_AGENTS = [ { id: 'cecilia', type: 'Repository Enhancer', runningOn: 'aria', hash: 'c08eb525' }, { id: 'cadence', type: 'UX Core', runningOn: 'alice', hash: '37bf3efd' }, { id: 'silas', type: 'Systems Core', runningOn: 'octavia', hash: '453ecfd1' }, { id: 'willow', type: 'Architect', runningOn: 'lucidia', hash: 'dc6fd280' } ]; // WebSocket Server const server = http.createServer((req, res) => { if (req.url === '/') { fs.readFile(path.join(__dirname, 'blackroad-brady-bunch-dashboard.html'), (err, data) => { if (err) { res.writeHead(404); res.end('Dashboard not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(data); }); } else { res.writeHead(404); res.end(); } }); const wss = new WebSocket.Server({ server }); // SSH Command Executor function sshCommand(node, command) { return new Promise((resolve, reject) => { const ssh = spawn('ssh', [ '-o', 'ConnectTimeout=5', '-o', 'StrictHostKeyChecking=no', `${node.user}@${node.host}`, command ]); let output = ''; let error = ''; ssh.stdout.on('data', (data) => { output += data.toString(); }); ssh.stderr.on('data', (data) => { error += data.toString(); }); ssh.on('close', (code) => { if (code === 0) { resolve(output.trim()); } else { reject(new Error(error || `SSH command failed with code ${code}`)); } }); // Timeout after 10 seconds setTimeout(() => { ssh.kill(); reject(new Error('SSH command timeout')); }, 10000); }); } // Get system stats from a node async function getNodeStats(node) { try { const [hostname, uptime, memory, disk, temp, cpu] = await Promise.all([ sshCommand(node, 'hostname'), sshCommand(node, 'uptime -p'), sshCommand(node, "free -h | awk '/^Mem/ {print $3\"/\"$2}'"), sshCommand(node, "df -h | awk '/\\/dev\\/nvme0n1/ {print $4}' || echo 'N/A'"), sshCommand(node, "vcgencmd measure_temp 2>/dev/null || echo 'temp=N/A'"), sshCommand(node, "top -bn1 | awk '/^%Cpu/ {print 100-$8\"%\"}'") ]); return { id: node.id, hostname: hostname, uptime: uptime, memory: memory, diskFree: disk !== 'N/A' ? disk : 'N/A', temp: temp.replace('temp=', '').replace("'C", '°C'), cpu: cpu, hailo: node.hailo ? '26 TOPS' : 'N/A', timestamp: Date.now() }; } catch (error) { console.error(`Error getting stats for ${node.id}:`, error.message); return { id: node.id, error: error.message, timestamp: Date.now() }; } } // Get Hailo-8 specific stats (if available) async function getHailoStats(node) { try { // Try to get Hailo-8 utilization const hailoInfo = await sshCommand(node, "hailortcli scan 2>/dev/null || echo 'Hailo CLI not available'" ); return hailoInfo; } catch (error) { return 'Hailo-8: Not accessible'; } } // Check NATS connection on shellfish async function checkNATS(node) { try { const natsStatus = await sshCommand(node, "systemctl is-active nats-server 2>/dev/null || docker ps | grep nats || echo 'NATS not found'" ); return natsStatus; } catch (error) { return 'NATS: Unknown'; } } // Generate simulated activity based on agent type function generateActivity(agent) { const activities = { cecilia: [ 'Enhanced repository documentation', 'Fixed TypeScript type errors', 'Updated dependencies to latest', 'Merged PR #' + Math.floor(Math.random() * 1000), 'Created branch: feature/enhancement-' + Math.floor(Math.random() * 100) ], cadence: [ 'Applied BlackRoad design system', 'Updated Golden Ratio spacing', 'Optimized component rendering', 'Fixed responsive breakpoints', 'Deployed to Cloudflare Pages' ], silas: [ 'Container health check: passed', 'System uptime: 99.9%', 'Resource allocation optimized', 'Zero Trust validation: OK', 'Prometheus metrics updated' ], willow: [ 'Dashboard metrics collected', 'WebSocket connection stable', 'Memory system synced', 'Roadchain integrity verified', 'Real-time pipeline active' ] }; return activities[agent.id] ? activities[agent.id][Math.floor(Math.random() * activities[agent.id].length)] : 'Processing task...'; } // Broadcast to all connected clients function broadcast(data) { const message = JSON.stringify(data); wss.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(message); } }); } // Monitor nodes continuously async function monitorNodes() { console.log('šŸ” Starting node monitoring...'); // Monitor physical Pi nodes for (const node of PI_NODES) { (async () => { while (true) { const stats = await getNodeStats(node); broadcast({ type: 'node_stats', data: stats }); // Add activity log broadcast({ type: 'activity', agentId: node.id, message: `CPU: ${stats.cpu || 'N/A'}, Memory: ${stats.memory || 'N/A'}, Temp: ${stats.temp || 'N/A'}`, level: 'info' }); await new Promise(resolve => setTimeout(resolve, 10000)); // Every 10 seconds } })(); } // Monitor shellfish (NATS hub) (async () => { while (true) { const stats = await getNodeStats(CLOUD_NODES[0]); const natsStatus = await checkNATS(CLOUD_NODES[0]); broadcast({ type: 'node_stats', data: { ...stats, nats: natsStatus } }); broadcast({ type: 'activity', agentId: 'shellfish', message: `NATS: ${natsStatus.includes('active') ? 'Active' : 'Checking...'}`, level: 'success' }); await new Promise(resolve => setTimeout(resolve, 15000)); // Every 15 seconds } })(); // Monitor logical agents setInterval(() => { LOGICAL_AGENTS.forEach(agent => { const activity = generateActivity(agent); broadcast({ type: 'activity', agentId: agent.id, message: activity, level: Math.random() > 0.8 ? 'success' : 'info' }); }); }, 5000); // Every 5 seconds } // Handle WebSocket connections wss.on('connection', (ws) => { console.log('šŸ”Œ Client connected'); ws.send(JSON.stringify({ type: 'welcome', message: 'Connected to BlackRoad OS Live Dashboard', timestamp: Date.now() })); ws.on('close', () => { console.log('šŸ”Œ Client disconnected'); }); ws.on('error', (error) => { console.error('WebSocket error:', error); }); }); // Start server const PORT = process.env.PORT || 3000; server.listen(PORT, () => { console.log(` ╔════════════════════════════════════════════════════════════╗ ā•‘ šŸ–¤šŸ›£ļø BlackRoad OS - Live Dashboard Server šŸ–¤šŸ›£ļø ā•‘ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā• šŸ“” Server running on: http://localhost:${PORT} šŸ”Œ WebSocket ready for connections Monitoring Nodes: ${PI_NODES.map(n => ` • ${n.id} (${n.host})`).join('\n')} ${CLOUD_NODES.map(n => ` • ${n.id} (${n.host})`).join('\n')} Logical Agents: ${LOGICAL_AGENTS.map(a => ` • ${a.id} on ${a.runningOn}`).join('\n')} šŸš€ Starting real-time monitoring... `); // Start monitoring monitorNodes(); }); // Graceful shutdown process.on('SIGINT', () => { console.log('\n\nšŸ›‘ Shutting down gracefully...'); wss.clients.forEach((client) => { client.close(); }); server.close(() => { console.log('āœ… Server closed'); process.exit(0); }); });