agent-server.js
2.83 KB
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
/**
* 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' }));
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`);
});