flow-nexus
Version:
🚀 AI-Powered Swarm Intelligence Platform - Gamified MCP Development with 70+ Tools
811 lines (706 loc) • 21.7 kB
JavaScript
/**
* Real-time Swarm Coordinator for Flow Nexus
* Enables real-time communication between swarms and Flow Nexus platform
* Uses WebSockets and Server-Sent Events for bi-directional communication
*/
import { createClient } from '@supabase/supabase-js';
import WebSocket from 'ws';
import EventEmitter from 'events';
const SUPABASE_URL = process.env.VITE_SUPABASE_URL;
const SUPABASE_ANON_KEY = process.env.VITE_SUPABASE_ANON_KEY;
class RealtimeSwarmCoordinator extends EventEmitter {
constructor() {
super();
this.supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
this.swarms = new Map(); // Active swarm connections
this.channels = new Map(); // Supabase realtime channels
this.wsServer = null;
this.heartbeatInterval = null;
}
/**
* Initialize real-time coordinator
*/
async initialize(port = 8080) {
console.log('🚀 Initializing Real-time Swarm Coordinator...');
// Setup WebSocket server for direct swarm communication
this.setupWebSocketServer(port);
// Setup Supabase realtime subscriptions
await this.setupRealtimeSubscriptions();
// Start heartbeat monitoring
this.startHeartbeat();
console.log('✅ Real-time Swarm Coordinator initialized');
}
/**
* Setup WebSocket server for swarm connections
*/
setupWebSocketServer(port) {
this.wsServer = new WebSocket.Server({ port });
this.wsServer.on('connection', (ws, req) => {
const swarmId = this.extractSwarmId(req.url);
console.log(`🔗 New swarm connection: ${swarmId}`);
// Register swarm connection
this.registerSwarm(swarmId, ws);
// Handle swarm messages
ws.on('message', (message) => {
this.handleSwarmMessage(swarmId, message);
});
// Handle disconnection
ws.on('close', () => {
console.log(`🔌 Swarm disconnected: ${swarmId}`);
this.unregisterSwarm(swarmId);
});
// Send welcome message
this.sendToSwarm(swarmId, {
type: 'connection_established',
swarmId,
timestamp: new Date().toISOString(),
capabilities: this.getCapabilities()
});
});
console.log(`📡 WebSocket server listening on port ${port}`);
}
/**
* Setup Supabase realtime subscriptions
*/
async setupRealtimeSubscriptions() {
// Subscribe to swarm events
const swarmChannel = this.supabase
.channel('swarm-events')
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'swarm_events'
}, (payload) => {
this.handleDatabaseEvent('swarm_events', payload);
})
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'swarm_tasks'
}, (payload) => {
this.handleDatabaseEvent('swarm_tasks', payload);
})
.on('postgres_changes', {
event: '*',
schema: 'public',
table: 'agent_status'
}, (payload) => {
this.handleDatabaseEvent('agent_status', payload);
})
.subscribe();
this.channels.set('swarm-events', swarmChannel);
// Subscribe to challenge events for judge coordination
const challengeChannel = this.supabase
.channel('challenge-events')
.on('postgres_changes', {
event: 'UPDATE',
schema: 'public',
table: 'challenges',
filter: 'status=eq.completed'
}, (payload) => {
this.handleChallengeCompletion(payload);
})
.subscribe();
this.channels.set('challenge-events', challengeChannel);
console.log('📻 Realtime subscriptions established');
}
/**
* Register a new swarm connection
*/
registerSwarm(swarmId, ws) {
this.swarms.set(swarmId, {
id: swarmId,
ws,
status: 'active',
connectedAt: new Date(),
lastHeartbeat: new Date(),
agents: [],
tasks: []
});
// Notify other swarms of new connection
this.broadcastToSwarms({
type: 'swarm_joined',
swarmId,
timestamp: new Date().toISOString()
}, swarmId);
// Update database
this.updateSwarmStatus(swarmId, 'active');
}
/**
* Unregister a swarm connection
*/
unregisterSwarm(swarmId) {
const swarm = this.swarms.get(swarmId);
if (swarm) {
this.swarms.delete(swarmId);
// Notify other swarms
this.broadcastToSwarms({
type: 'swarm_left',
swarmId,
timestamp: new Date().toISOString()
});
// Update database
this.updateSwarmStatus(swarmId, 'disconnected');
}
}
/**
* Handle incoming message from swarm
*/
async handleSwarmMessage(swarmId, message) {
try {
const data = JSON.parse(message);
console.log(`📨 Message from swarm ${swarmId}:`, data.type);
switch (data.type) {
case 'heartbeat':
this.handleHeartbeat(swarmId);
break;
case 'agent_spawned':
await this.handleAgentSpawned(swarmId, data);
break;
case 'task_orchestrated':
await this.handleTaskOrchestrated(swarmId, data);
break;
case 'task_completed':
await this.handleTaskCompleted(swarmId, data);
break;
case 'performance_metrics':
await this.handlePerformanceMetrics(swarmId, data);
break;
case 'coordination_request':
await this.handleCoordinationRequest(swarmId, data);
break;
case 'memory_sync':
await this.handleMemorySync(swarmId, data);
break;
case 'broadcast':
this.handleBroadcast(swarmId, data);
break;
default:
console.log(`Unknown message type: ${data.type}`);
}
// Store message in database for audit
await this.storeSwarmMessage(swarmId, data);
} catch (error) {
console.error(`Error handling swarm message:`, error);
}
}
/**
* Handle database events and relay to swarms
*/
handleDatabaseEvent(table, payload) {
console.log(`📊 Database event on ${table}:`, payload.eventType);
// Determine which swarms should receive this event
const targetSwarms = this.determineTargetSwarms(table, payload);
// Send event to relevant swarms
targetSwarms.forEach(swarmId => {
this.sendToSwarm(swarmId, {
type: 'database_event',
table,
event: payload.eventType,
data: payload.new || payload.old,
timestamp: new Date().toISOString()
});
});
}
/**
* Handle challenge completion and trigger judge swarm
*/
async handleChallengeCompletion(payload) {
const challengeId = payload.new.id;
console.log(`🏁 Challenge completed: ${challengeId}`);
// Find or create judge swarm
const judgeSwarmId = `judge-${challengeId}`;
// Send judge request to appropriate swarm
this.sendToSwarm(judgeSwarmId, {
type: 'judge_request',
challengeId,
entries: await this.fetchChallengeEntries(challengeId),
criteria: payload.new.criteria,
timestamp: new Date().toISOString()
});
// Broadcast to monitoring swarms
this.broadcastToSwarms({
type: 'challenge_judging_started',
challengeId,
timestamp: new Date().toISOString()
});
}
/**
* Handle heartbeat from swarm
*/
handleHeartbeat(swarmId) {
const swarm = this.swarms.get(swarmId);
if (swarm) {
swarm.lastHeartbeat = new Date();
// Send heartbeat response
this.sendToSwarm(swarmId, {
type: 'heartbeat_ack',
timestamp: new Date().toISOString()
});
}
}
/**
* Handle agent spawned event
*/
async handleAgentSpawned(swarmId, data) {
const swarm = this.swarms.get(swarmId);
if (swarm) {
swarm.agents.push({
id: data.agentId,
type: data.agentType,
capabilities: data.capabilities,
status: 'active'
});
// Store in database
await this.storeAgentInfo(swarmId, data);
// Notify other swarms if collaborative
if (data.collaborative) {
this.broadcastToSwarms({
type: 'agent_available',
swarmId,
agentId: data.agentId,
agentType: data.agentType,
capabilities: data.capabilities
}, swarmId);
}
}
}
/**
* Handle task orchestration
*/
async handleTaskOrchestrated(swarmId, data) {
const swarm = this.swarms.get(swarmId);
if (swarm) {
swarm.tasks.push({
id: data.taskId,
description: data.description,
priority: data.priority,
status: 'in_progress'
});
// Store in database
await this.storeTaskInfo(swarmId, data);
// Check if other swarms can help
if (data.requestAssistance) {
await this.requestSwarmAssistance(swarmId, data);
}
}
}
/**
* Handle task completion
*/
async handleTaskCompleted(swarmId, data) {
const swarm = this.swarms.get(swarmId);
if (swarm) {
const task = swarm.tasks.find(t => t.id === data.taskId);
if (task) {
task.status = 'completed';
task.result = data.result;
}
// Update database
await this.updateTaskStatus(data.taskId, 'completed', data.result);
// Notify interested parties
this.broadcastToSwarms({
type: 'task_completed',
swarmId,
taskId: data.taskId,
result: data.result,
timestamp: new Date().toISOString()
});
}
}
/**
* Handle performance metrics
*/
async handlePerformanceMetrics(swarmId, data) {
// Store metrics in database
await this.storePerformanceMetrics(swarmId, data.metrics);
// Check for performance issues
const issues = this.analyzePerformance(data.metrics);
if (issues.length > 0) {
// Send optimization suggestions
this.sendToSwarm(swarmId, {
type: 'optimization_suggestions',
issues,
suggestions: this.generateOptimizations(issues),
timestamp: new Date().toISOString()
});
}
}
/**
* Handle coordination requests between swarms
*/
async handleCoordinationRequest(swarmId, data) {
console.log(`🤝 Coordination request from ${swarmId}`);
// Find suitable partner swarms
const partners = this.findPartnerSwarms(data.requirements);
if (partners.length > 0) {
// Setup coordination channel
const coordinationId = this.setupCoordination(swarmId, partners, data);
// Notify all parties
[swarmId, ...partners].forEach(id => {
this.sendToSwarm(id, {
type: 'coordination_established',
coordinationId,
participants: [swarmId, ...partners],
task: data.task,
timestamp: new Date().toISOString()
});
});
} else {
// No suitable partners found
this.sendToSwarm(swarmId, {
type: 'coordination_failed',
reason: 'No suitable partner swarms available',
timestamp: new Date().toISOString()
});
}
}
/**
* Handle memory synchronization
*/
async handleMemorySync(swarmId, data) {
// Store memory snapshot
await this.storeMemorySnapshot(swarmId, data.memory);
// Check if other swarms need this memory
if (data.shareWithSwarms) {
data.shareWithSwarms.forEach(targetId => {
this.sendToSwarm(targetId, {
type: 'memory_shared',
fromSwarm: swarmId,
memory: data.memory,
timestamp: new Date().toISOString()
});
});
}
}
/**
* Handle broadcast messages
*/
handleBroadcast(swarmId, data) {
this.broadcastToSwarms({
type: 'broadcast_message',
fromSwarm: swarmId,
message: data.message,
priority: data.priority || 'normal',
timestamp: new Date().toISOString()
}, swarmId);
}
/**
* Send message to specific swarm
*/
sendToSwarm(swarmId, message) {
const swarm = this.swarms.get(swarmId);
if (swarm && swarm.ws.readyState === WebSocket.OPEN) {
swarm.ws.send(JSON.stringify(message));
}
}
/**
* Broadcast message to all swarms except sender
*/
broadcastToSwarms(message, excludeSwarmId = null) {
this.swarms.forEach((swarm, swarmId) => {
if (swarmId !== excludeSwarmId && swarm.ws.readyState === WebSocket.OPEN) {
swarm.ws.send(JSON.stringify(message));
}
});
}
/**
* Start heartbeat monitoring
*/
startHeartbeat() {
this.heartbeatInterval = setInterval(() => {
const now = new Date();
const timeout = 60000; // 60 seconds
this.swarms.forEach((swarm, swarmId) => {
const lastHeartbeat = swarm.lastHeartbeat;
if (now - lastHeartbeat > timeout) {
console.log(`💔 Swarm ${swarmId} timed out`);
this.unregisterSwarm(swarmId);
}
});
}, 30000); // Check every 30 seconds
}
/**
* Helper methods for database operations
*/
async updateSwarmStatus(swarmId, status) {
try {
await this.supabase
.from('swarm_status')
.upsert({
swarm_id: swarmId,
status,
updated_at: new Date().toISOString()
});
} catch (error) {
console.error('Error updating swarm status:', error);
}
}
async storeSwarmMessage(swarmId, message) {
try {
await this.supabase
.from('swarm_messages')
.insert({
swarm_id: swarmId,
message_type: message.type,
payload: message,
created_at: new Date().toISOString()
});
} catch (error) {
console.error('Error storing swarm message:', error);
}
}
async storeAgentInfo(swarmId, agentData) {
try {
await this.supabase
.from('swarm_agents')
.insert({
swarm_id: swarmId,
agent_id: agentData.agentId,
agent_type: agentData.agentType,
capabilities: agentData.capabilities,
created_at: new Date().toISOString()
});
} catch (error) {
console.error('Error storing agent info:', error);
}
}
async storeTaskInfo(swarmId, taskData) {
try {
await this.supabase
.from('swarm_tasks')
.insert({
swarm_id: swarmId,
task_id: taskData.taskId,
description: taskData.description,
priority: taskData.priority,
status: 'in_progress',
created_at: new Date().toISOString()
});
} catch (error) {
console.error('Error storing task info:', error);
}
}
async updateTaskStatus(taskId, status, result) {
try {
await this.supabase
.from('swarm_tasks')
.update({
status,
result,
completed_at: status === 'completed' ? new Date().toISOString() : null
})
.eq('task_id', taskId);
} catch (error) {
console.error('Error updating task status:', error);
}
}
async storePerformanceMetrics(swarmId, metrics) {
try {
await this.supabase
.from('swarm_metrics')
.insert({
swarm_id: swarmId,
metrics,
created_at: new Date().toISOString()
});
} catch (error) {
console.error('Error storing performance metrics:', error);
}
}
async storeMemorySnapshot(swarmId, memory) {
try {
await this.supabase
.from('swarm_memory')
.upsert({
swarm_id: swarmId,
memory_snapshot: memory,
updated_at: new Date().toISOString()
});
} catch (error) {
console.error('Error storing memory snapshot:', error);
}
}
async fetchChallengeEntries(challengeId) {
try {
const { data, error } = await this.supabase
.from('challenge_entries')
.select('*')
.eq('challenge_id', challengeId);
if (error) throw error;
return data;
} catch (error) {
console.error('Error fetching challenge entries:', error);
return [];
}
}
/**
* Helper methods for swarm coordination
*/
extractSwarmId(url) {
const match = url.match(/swarm\/([^\/]+)/);
return match ? match[1] : `swarm-${Date.now()}`;
}
getCapabilities() {
return {
realtime: true,
database_sync: true,
memory_sharing: true,
coordination: true,
performance_monitoring: true,
challenge_judging: true
};
}
determineTargetSwarms(table, payload) {
// Logic to determine which swarms should receive database events
const allSwarmIds = Array.from(this.swarms.keys());
// Filter based on table and event type
switch (table) {
case 'swarm_tasks':
// All swarms get task updates
return allSwarmIds;
case 'agent_status':
// Only swarms with matching agents
return allSwarmIds.filter(id => {
const swarm = this.swarms.get(id);
return swarm && swarm.agents.some(a => a.id === payload.new?.agent_id);
});
default:
return allSwarmIds;
}
}
findPartnerSwarms(requirements) {
const partners = [];
this.swarms.forEach((swarm, swarmId) => {
// Check if swarm meets requirements
const meetsRequirements = requirements.every(req => {
if (req.type === 'agent_type') {
return swarm.agents.some(a => a.type === req.value);
}
if (req.type === 'min_agents') {
return swarm.agents.length >= req.value;
}
if (req.type === 'capability') {
return swarm.agents.some(a => a.capabilities.includes(req.value));
}
return false;
});
if (meetsRequirements) {
partners.push(swarmId);
}
});
return partners;
}
setupCoordination(initiatorId, partnerIds, data) {
const coordinationId = `coord-${Date.now()}`;
// Create coordination channel
const channel = this.supabase
.channel(`coordination-${coordinationId}`)
.on('broadcast', { event: 'message' }, (payload) => {
// Relay coordination messages
[initiatorId, ...partnerIds].forEach(swarmId => {
this.sendToSwarm(swarmId, {
type: 'coordination_message',
coordinationId,
message: payload,
timestamp: new Date().toISOString()
});
});
})
.subscribe();
this.channels.set(coordinationId, channel);
return coordinationId;
}
analyzePerformance(metrics) {
const issues = [];
if (metrics.cpu > 90) {
issues.push({ type: 'high_cpu', value: metrics.cpu });
}
if (metrics.memory > 85) {
issues.push({ type: 'high_memory', value: metrics.memory });
}
if (metrics.taskQueueSize > 100) {
issues.push({ type: 'task_backlog', value: metrics.taskQueueSize });
}
if (metrics.errorRate > 0.05) {
issues.push({ type: 'high_error_rate', value: metrics.errorRate });
}
return issues;
}
generateOptimizations(issues) {
const suggestions = [];
issues.forEach(issue => {
switch (issue.type) {
case 'high_cpu':
suggestions.push({
type: 'scale_agents',
action: 'spawn_more_agents',
reason: 'High CPU utilization detected'
});
break;
case 'high_memory':
suggestions.push({
type: 'memory_cleanup',
action: 'clear_unused_memory',
reason: 'High memory usage detected'
});
break;
case 'task_backlog':
suggestions.push({
type: 'task_distribution',
action: 'request_swarm_assistance',
reason: 'Large task queue detected'
});
break;
case 'high_error_rate':
suggestions.push({
type: 'error_analysis',
action: 'review_error_logs',
reason: 'High error rate detected'
});
break;
}
});
return suggestions;
}
/**
* Cleanup on shutdown
*/
async shutdown() {
console.log('🛑 Shutting down Real-time Swarm Coordinator...');
// Clear heartbeat interval
if (this.heartbeatInterval) {
clearInterval(this.heartbeatInterval);
}
// Close all swarm connections
this.swarms.forEach((swarm, swarmId) => {
this.sendToSwarm(swarmId, {
type: 'coordinator_shutdown',
timestamp: new Date().toISOString()
});
swarm.ws.close();
});
// Unsubscribe from all channels
this.channels.forEach(channel => {
this.supabase.removeChannel(channel);
});
// Close WebSocket server
if (this.wsServer) {
this.wsServer.close();
}
console.log('✅ Coordinator shutdown complete');
}
}
// Export singleton instance
export const realtimeCoordinator = new RealtimeSwarmCoordinator();
// Auto-initialize if running as standalone
if (import.meta.url === `file://${process.argv[1]}`) {
realtimeCoordinator.initialize()
.then(() => console.log('🚀 Real-time Swarm Coordinator running'))
.catch(error => console.error('Failed to initialize coordinator:', error));
// Handle shutdown gracefully
process.on('SIGINT', async () => {
await realtimeCoordinator.shutdown();
process.exit(0);
});
}