Kraft102's picture
Deploy backend fix v2.1.0
1d28c11
// 🐝 TELEPATHY: NeuralBus.ts
// Ansvarlig for 0ms kommunikation mellem agenter og frontend.
// Real-time event streaming via WebSockets
import { Server as SocketIOServer, Socket } from 'socket.io';
import { Server as HttpServer } from 'http';
export interface ThoughtEvent {
agent: string;
timestamp: number;
thought: string;
context: Record<string, unknown>;
type?: 'INFO' | 'WARNING' | 'ERROR' | 'SUCCESS' | 'THOUGHT';
}
export interface AgentInfo {
id: string;
name: string;
connectedAt: Date;
lastActivity: Date;
}
export class NeuralBus {
private static instance: NeuralBus;
private io: SocketIOServer | null = null;
private connectedAgents = new Map<string, AgentInfo>();
private thoughtHistory: ThoughtEvent[] = [];
private maxHistorySize = 1000;
private constructor() {
console.log('🐝 [HIVE] Neural Bus Initializing...');
}
public static getInstance(): NeuralBus {
if (!NeuralBus.instance) {
NeuralBus.instance = new NeuralBus();
}
return NeuralBus.instance;
}
public attach(httpServer: HttpServer): void {
this.io = new SocketIOServer(httpServer, {
cors: {
origin: "*",
methods: ["GET", "POST"]
},
pingTimeout: 60000,
pingInterval: 25000
});
console.log('🐝 [HIVE] Neural Telepathy Bus Online');
this.io.on('connection', (socket: Socket) => {
const agentName = socket.handshake.query.agent as string || `Agent-${socket.id.slice(0, 6)}`;
// Register agent
this.connectedAgents.set(socket.id, {
id: socket.id,
name: agentName,
connectedAt: new Date(),
lastActivity: new Date()
});
console.log(`🐝 [HIVE] Agent Connected: ${agentName} (${socket.id})`);
// Notify all agents of new connection
this.io?.emit('AGENT_JOINED', {
agent: agentName,
totalAgents: this.connectedAgents.size
});
// Handle incoming thoughts
socket.on('THOUGHT', (data: Partial<ThoughtEvent>) => {
const thought: ThoughtEvent = {
agent: agentName,
timestamp: Date.now(),
thought: data.thought || '',
context: data.context || {},
type: data.type || 'THOUGHT'
};
this.recordThought(thought);
socket.broadcast.emit('THOUGHT_STREAM', thought);
// Update activity
const agent = this.connectedAgents.get(socket.id);
if (agent) agent.lastActivity = new Date();
});
// Handle queries
socket.on('QUERY', async (data: { type: string; payload: unknown }, callback) => {
const response = await this.handleQuery(data.type, data.payload);
if (callback) callback(response);
});
// Handle disconnection
socket.on('disconnect', () => {
const agent = this.connectedAgents.get(socket.id);
this.connectedAgents.delete(socket.id);
console.log(`🐝 [HIVE] Agent Disconnected: ${agent?.name || socket.id}`);
this.io?.emit('AGENT_LEFT', {
agent: agent?.name,
totalAgents: this.connectedAgents.size
});
});
});
}
private recordThought(thought: ThoughtEvent): void {
this.thoughtHistory.push(thought);
// Trim history if too large
if (this.thoughtHistory.length > this.maxHistorySize) {
this.thoughtHistory = this.thoughtHistory.slice(-this.maxHistorySize);
}
}
private async handleQuery(type: string, payload: unknown): Promise<unknown> {
switch (type) {
case 'GET_AGENTS':
return Array.from(this.connectedAgents.values());
case 'GET_HISTORY':
const count = (payload as { count?: number })?.count || 50;
return this.thoughtHistory.slice(-count);
case 'GET_STATS':
return this.getStats();
default:
return { error: 'Unknown query type' };
}
}
// Public API for emitting thoughts from server-side
public emitThought(agent: string, thought: string, context: Record<string, unknown> = {}, type: ThoughtEvent['type'] = 'INFO'): void {
if (this.io) {
const event: ThoughtEvent = {
agent,
timestamp: Date.now(),
thought,
context,
type
};
this.recordThought(event);
this.io.emit('THOUGHT_STREAM', event);
}
}
public emitToAgent(agentId: string, event: string, data: unknown): void {
if (this.io) {
this.io.to(agentId).emit(event, data);
}
}
public broadcast(event: string, data: unknown): void {
if (this.io) {
this.io.emit(event, data);
}
}
public getStats() {
return {
connectedAgents: this.connectedAgents.size,
agents: Array.from(this.connectedAgents.values()).map(a => ({
name: a.name,
connectedAt: a.connectedAt,
lastActivity: a.lastActivity
})),
thoughtsRecorded: this.thoughtHistory.length,
isOnline: this.io !== null
};
}
public getRecentThoughts(count: number = 50): ThoughtEvent[] {
return this.thoughtHistory.slice(-count);
}
}
export const neuralBus = NeuralBus.getInstance();