Commit d48457acbe2d7e66651417d523e3705a11f00663
1 parent
9e586563
fix(auth): selfChat 自环唤醒漏带内部令牌,7 处调用全部静默 401
router.use(requireAuthOrInternal) 之后,agent-chat.js 自己的 selfChat() helper (TaskDispatch/TaskCallback/TaskTransition ×2/TaskReject/HumanRequest 共 7 处 调用)一直在用裸 http.request 自己打自己的 /api/agent/:id/chat,没带 x-internal-token,全部被 401 挡住——而且 chatRes 回调之前不看 statusCode, 401 也照样打印"✅ 已唤醒",症状是静默的(跟 claude-cli-session-leak.md 一个模式)。 实测复现:真实 dispatch 一个任务给 org-innovator,目标 agent 从未收到消息, 任务卡在 dispatched 状态没人执行。 修法:selfChat 加 x-internal-token header(跟 company.js/task-settle.js 的 自环调用同一套机制),并且真的检查 chatRes.statusCode,非 2xx 打日志说明失败, 不再假装成功。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Showing
1 changed file
with
19 additions
and
4 deletions
server/routes/agent-chat.js
| ... | ... | @@ -30,7 +30,7 @@ const companyService = new CompanyService(); |
| 30 | 30 | // 交付物归宿只有一份推导(28 §4.4),公司环境上下文与执行链路的运行时坐标共用它 |
| 31 | 31 | const { companyWorkspaceDir } = require('../src/core/prompt-builder'); |
| 32 | 32 | const systemConfig = require('../config'); |
| 33 | -const { requireAuthOrInternal } = require('../middleware/jwt-auth'); | |
| 33 | +const { requireAuthOrInternal, INTERNAL_TOKEN, INTERNAL_TOKEN_HEADER } = require('../middleware/jwt-auth'); | |
| 34 | 34 | const router = express.Router(); |
| 35 | 35 | |
| 36 | 36 | // 38 号文档 Phase 1:全站要求登录,但这个文件同时承接三处服务端自环调用 |
| ... | ... | @@ -80,10 +80,25 @@ function selfChat(req, agentId, message, conversationId, label = 'SelfChat') { |
| 80 | 80 | port: req?.socket?.localPort || systemConfig.port, |
| 81 | 81 | path: `/api/agent/${agentId}/chat`, |
| 82 | 82 | method: 'POST', |
| 83 | - headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) }, | |
| 83 | + // 本文件顶部 router.use(requireAuthOrInternal) 之后,这条自环 fetch 也要带内部令牌, | |
| 84 | + // 否则 401——之前漏了这一处,TaskDispatch/TaskCallback/TaskTransition/TaskReject/ | |
| 85 | + // HumanRequest 全部 7 个调用点静默失败(下面 chatRes 分支之前不看 statusCode, | |
| 86 | + // 401 也照样打印"✅ 已唤醒",症状跟 claude-cli-session-leak.md 那次一样是静默的)。 | |
| 87 | + headers: { | |
| 88 | + 'Content-Type': 'application/json', | |
| 89 | + 'Content-Length': Buffer.byteLength(postData), | |
| 90 | + [INTERNAL_TOKEN_HEADER]: INTERNAL_TOKEN, | |
| 91 | + }, | |
| 84 | 92 | }, (chatRes) => { |
| 85 | - chatRes.on('data', () => {}); | |
| 86 | - chatRes.on('end', () => console.log(`[${label}] ✅ 已唤醒 ${agentId} (conv: ${conversationId})`)); | |
| 93 | + let body = ''; | |
| 94 | + chatRes.on('data', (c) => { body += c; }); | |
| 95 | + chatRes.on('end', () => { | |
| 96 | + if (chatRes.statusCode >= 400) { | |
| 97 | + console.error(`[${label}] ❌ 唤醒 ${agentId} 失败: HTTP ${chatRes.statusCode} ${body.slice(0, 200)} (conv: ${conversationId})`); | |
| 98 | + } else { | |
| 99 | + console.log(`[${label}] ✅ 已唤醒 ${agentId} (conv: ${conversationId})`); | |
| 100 | + } | |
| 101 | + }); | |
| 87 | 102 | }); |
| 88 | 103 | chatReq.on('error', (err) => console.error(`[${label}] ❌ 回调失败: ${err.message}`)); |
| 89 | 104 | chatReq.write(postData); | ... | ... |