Spaces:
Sleeping
Sleeping
File size: 4,369 Bytes
ccb6b75 0dc8aef ccb6b75 ca1b6c1 ccb6b75 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | import http from 'http';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import HumanBehaviorEngine from './index.js';
import logger from './utils/logger.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PORT = parseInt(process.env.PORT) || 7860;
const publicDir = path.join(__dirname, '..', 'public');
const engine = new HumanBehaviorEngine();
let isRunning = false;
const mimeTypes = {
'.html': 'text/html',
'.js': 'application/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.svg': 'image/svg+xml',
};
function serveStatic(res, filePath) {
const ext = path.extname(filePath);
const contentType = mimeTypes[ext] || 'application/octet-stream';
fs.readFile(filePath, (err, content) => {
if (err) {
res.writeHead(404);
res.end(JSON.stringify({ error: 'not_found' }));
return;
}
res.writeHead(200, { 'Content-Type': contentType });
res.end(content);
});
}
async function startEngine() {
if (isRunning) return { status: 'already_running' };
isRunning = true;
await engine.start();
return { status: 'started' };
}
async function stopEngine() {
isRunning = false;
await engine.stop();
return { status: 'stopped' };
}
async function getStatus() {
return await engine.getStatus();
}
const server = http.createServer(async (req, res) => {
const url = new URL(req.url, `http://${req.headers.host}`);
res.setHeader('Access-Control-Allow-Origin', '*');
if (req.method === 'GET' && url.pathname === '/health') {
res.setHeader('Content-Type', 'application/json');
res.writeHead(200);
res.end(JSON.stringify({ status: 'ok', uptime: process.uptime() }));
return;
}
if (req.method === 'GET' && url.pathname === '/status') {
res.setHeader('Content-Type', 'application/json');
try {
const status = await getStatus();
res.writeHead(200);
res.end(JSON.stringify(status));
} catch (e) {
res.writeHead(500);
res.end(JSON.stringify({ error: e.message }));
}
return;
}
if (req.method === 'POST' && url.pathname === '/start') {
res.setHeader('Content-Type', 'application/json');
try {
const result = await startEngine();
res.writeHead(200);
res.end(JSON.stringify(result));
} catch (e) {
res.writeHead(500);
res.end(JSON.stringify({ error: e.message }));
}
return;
}
if (req.method === 'POST' && url.pathname === '/stop') {
res.setHeader('Content-Type', 'application/json');
try {
const result = await stopEngine();
res.writeHead(200);
res.end(JSON.stringify(result));
} catch (e) {
res.writeHead(500);
res.end(JSON.stringify({ error: e.message }));
}
return;
}
if (req.method === 'POST' && url.pathname === '/cycle') {
res.setHeader('Content-Type', 'application/json');
try {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error('Cycle timed out after 60s')), 60000)
);
await Promise.race([engine.runOnce(), timeout]);
res.writeHead(200);
res.end(JSON.stringify({ status: 'cycle_complete' }));
} catch (e) {
res.writeHead(500);
res.end(JSON.stringify({ error: e.message }));
}
return;
}
if (req.method === 'GET') {
if (url.pathname === '/' || url.pathname === '/index.html') {
serveStatic(res, path.join(publicDir, 'index.html'));
return;
}
const filePath = path.join(publicDir, url.pathname);
if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
serveStatic(res, filePath);
return;
}
}
res.setHeader('Content-Type', 'application/json');
res.writeHead(404);
res.end(JSON.stringify({ error: 'not_found' }));
});
server.listen(PORT, '0.0.0.0', () => {
logger.info(`Cloud server listening on port ${PORT}`);
logger.info(`Dashboard: http://localhost:${PORT}`);
logger.info('Auto-starting simulator...');
startEngine().catch(e => logger.error(`Auto-start failed: ${e.message}`));
});
process.on('SIGTERM', async () => {
logger.info('SIGTERM received, stopping engine...');
await stopEngine();
process.exit(0);
});
process.on('SIGINT', async () => {
logger.info('SIGINT received, stopping engine...');
await stopEngine();
process.exit(0);
});
|