/** * Agent Chat 独立服务器 * * 只启动 Agent Chat API,不依赖主服务器的其他模块。 * 用法: node server/agent-server.js */ const express = require('express'); const cors = require('cors'); const agentChatRoute = require('./routes/agent-chat'); const app = express(); const PORT = 3000; app.use(cors({ origin: ['http://localhost:5173'], credentials: true })); // ── 控制字符净化中间件 ── // Agent 通过 curl 发送的 JSON body 可能包含原始控制字符, // 导致 body-parser 的 JSON.parse 失败 app.use((req, res, next) => { if (req.headers['content-type']?.includes('application/json')) { let rawBody = ''; req.on('data', chunk => rawBody += chunk); req.on('end', () => { if (!rawBody) return next(); try { req.body = JSON.parse(rawBody); req._bodyParsed = true; next(); } catch (e) { try { // eslint-disable-next-line no-control-regex const cleaned = rawBody.replace(/[\x00-\x1F\x7F]/g, (ch) => { if (ch === '\n') return '\\n'; if (ch === '\r') return '\\r'; if (ch === '\t') return '\\t'; return ''; }); req.body = JSON.parse(cleaned); req._bodyParsed = true; console.log(`[BodySanitizer] ⚠️ 已净化请求体控制字符 (${req.path})`); next(); } catch (e2) { res.status(400).json({ error: 'Invalid JSON: ' + e2.message }); } } }); } else { next(); } }); // express.json() 仅处理未被上面中间件处理的请求(非 JSON content-type 等) app.use((req, res, next) => { if (req._bodyParsed) return next(); express.json()(req, res, next); }); // Agent Chat API app.use('/api/agent', agentChatRoute); // Company API app.use('/api/company', require('./routes/company')); app.use('/api/goals', require('./routes/goals')); // Health app.get('/api/health', (req, res) => res.json({ status: 'ok', service: 'agent-chat' })); app.listen(PORT, '0.0.0.0', () => { console.log(`🧬 Agent Chat Server: http://localhost:${PORT}`); console.log(` API: http://localhost:${PORT}/api/agent/list`); console.log(` Chat: http://localhost:5173/agent/innovator-001`); });