/** * 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 config = require('./config'); const PORT = process.env.PORT || config.port || 3010; 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) { req.body = {}; req._bodyParsed = true; 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/okr', require('./routes/okr')); app.use('/api/goals', require('./routes/okr')); // 向后兼容别名(27-NAMING 六) app.use('/api/tasks', require('./routes/tasks')); app.use('/api/devloop', require('./routes/devloop')); app.use('/api/graph-runs', require('./routes/graph-run')); // P3 图执行(T6) app.use('/api/company', require('./routes/graph-run').companyRouter); // GET /:cid/graph-runs app.use('/public', require('express').static(require('path').join(__dirname, 'public'))); // Health app.get('/api/health', (req, res) => res.json({ status: 'ok', service: 'agent-chat' })); // Graph agent 元数据对齐(P3B W1)——与 server/index.js 的 start() 同一步,理由见那里的注释 require('./services/graph-seed-service').runStartupSeedSafely(); 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`); });