- Add Mistral AI integration for agent responses - Create mistralClient service with agent-specific prompts - Support for architect, backend engineer, frontend engineer, and designer roles - Automatic JSON response parsing and validation - Implement WebSocket real-time communication - Update orchestrator with WebSocket broadcasting - Add client subscription system for debate updates - Real-time agent response streaming - Add consensus and voting system - Calculate weighted consensus with architect priority - Confidence-based voting mechanism - Auto-complete debates when consensus reached - Integrate Mermaid diagram rendering - Support for embedded diagrams in agent responses - Client-side Mermaid.js integration - Auto-render diagrams on response updates - Update frontend for real-time experience - WebSocket composable for reactive updates - Live status messages and response streaming - Loading states and consensus display
91 lines
2.3 KiB
JavaScript
91 lines
2.3 KiB
JavaScript
import express from 'express';
|
|
import cors from 'cors';
|
|
import helmet from 'helmet';
|
|
import dotenv from 'dotenv';
|
|
import { createServer } from 'http';
|
|
import { WebSocketServer } from 'ws';
|
|
import rateLimit from 'express-rate-limit';
|
|
import { parse } from 'url';
|
|
import db from './db/schema.js';
|
|
import debateRoutes from './routes/debate.js';
|
|
import orchestrator from './services/orchestrator.js';
|
|
|
|
dotenv.config();
|
|
|
|
const app = express();
|
|
const server = createServer(app);
|
|
const wss = new WebSocketServer({ server });
|
|
|
|
const PORT = process.env.PORT || 3000;
|
|
|
|
// Middleware
|
|
app.use(helmet());
|
|
app.use(cors({
|
|
origin: process.env.FRONTEND_URL || 'http://localhost:5173',
|
|
credentials: true
|
|
}));
|
|
app.use(express.json());
|
|
|
|
// Rate limiting
|
|
const limiter = rateLimit({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 10 // 10 requests per minute
|
|
});
|
|
app.use('/api', limiter);
|
|
|
|
// WebSocket connection handling
|
|
wss.on('connection', (ws, req) => {
|
|
const { query } = parse(req.url, true);
|
|
const debateId = query.debateId ? parseInt(query.debateId) : null;
|
|
|
|
console.log('New WebSocket connection established', debateId ? `for debate ${debateId}` : '');
|
|
|
|
if (debateId) {
|
|
orchestrator.registerWSClient(debateId, ws);
|
|
|
|
ws.send(JSON.stringify({
|
|
type: 'connected',
|
|
debateId,
|
|
message: 'Connected to debate updates'
|
|
}));
|
|
}
|
|
|
|
ws.on('message', (message) => {
|
|
try {
|
|
const data = JSON.parse(message.toString());
|
|
console.log('Received:', data);
|
|
|
|
// Handle subscribe to debate
|
|
if (data.type === 'subscribe' && data.debateId) {
|
|
orchestrator.registerWSClient(parseInt(data.debateId), ws);
|
|
ws.send(JSON.stringify({
|
|
type: 'subscribed',
|
|
debateId: data.debateId
|
|
}));
|
|
}
|
|
} catch (error) {
|
|
console.error('WebSocket message error:', error);
|
|
}
|
|
});
|
|
|
|
ws.on('close', () => {
|
|
if (debateId) {
|
|
orchestrator.unregisterWSClient(debateId, ws);
|
|
}
|
|
console.log('WebSocket connection closed');
|
|
});
|
|
});
|
|
|
|
// Routes
|
|
app.get('/api/health', (req, res) => {
|
|
res.json({ status: 'ok', message: 'Agora AI Backend is running' });
|
|
});
|
|
|
|
app.use('/api/debate', debateRoutes);
|
|
|
|
// Start server
|
|
server.listen(PORT, () => {
|
|
console.log(`Agora AI Backend running on port ${PORT}`);
|
|
console.log(`WebSocket server ready`);
|
|
});
|