From b095d3a73f72aa6509b1d03039bd36dbd3f86b11 Mon Sep 17 00:00:00 2001 From: yibo Date: Mon, 13 Apr 2026 12:23:43 +0800 Subject: [PATCH] perf: reuse existing session for task callbacks to save ~30K tokens/callback --- server/routes/agent-chat.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/server/routes/agent-chat.js b/server/routes/agent-chat.js index 0d5b4c2..8f2087a 100644 --- a/server/routes/agent-chat.js +++ b/server/routes/agent-chat.js @@ -665,10 +665,25 @@ async function getOrCreateProtocol(agentId, convId) { const protocol = new ClaudeCliProtocol({ name: identity.name }, cliOptions); + const releaseLock = () => { + const lock = agentChatLocks.get(agentId); + if (lock && lock.convId === convId) { + agentChatLocks.delete(agentId); + console.log(`[AgentChat] 🔓 ${identity.name} 锁已释放 (conv: ${convId})`); + } + }; + // 绑定错误监听器,防止 EventEmitter 抛出未捕获异常导致整个 Node 进程奔溃 (例如 spawn claude ENOENT) protocol.on('error', (err) => { console.error(`[AgentChat] 🚨 ${identity.name} 协议级异常:`, err.message); sessions.delete(key); // 下次提问将重建进程 + releaseLock(); + }); + + protocol.on('disconnected', ({ code, signal }) => { + sessions.delete(key); + releaseLock(); + console.log(`[AgentChat] 💤 ${identity.name} 会话断开 (code=${code}, signal=${signal})`); }); await protocol.connect(null, agentDir); @@ -1733,7 +1748,16 @@ router.post('/task/report', (req, res) => { try { // 读取 task 元数据获取上下文 const taskMeta = loadTaskMeta(taskId); - const callbackConvId = `callback-${taskId}`; + + // 💰 Token 优化:尝试复用目标 Agent 的已有 session,避免创建新 CLI 进程 + let callbackConvId = `callback-${taskId}`; + for (const [key, entry] of sessions.entries()) { + if (key.startsWith(`${to}:`) && entry.protocol.isConnected) { + callbackConvId = entry.convId; + console.log(`[TaskCallback] ♻️ 复用 ${to} 已有 session: ${callbackConvId}`); + break; + } + } const statusText = status === 'done' ? '✅ 已完成' : '❌ 失败'; const callbackMessage = `[TASK_CALLBACK]\n任务编号: ${taskId}\n执行者: ${from}\n状态: ${statusText}\n摘要: ${summary || '(无摘要)'}\n产出文件: ${outputs.length > 0 ? outputs.join(', ') : '(无)'}\n${taskMeta ? `原始任务: ${taskMeta.task}` : ''}\n\n**去重提醒**:在 dispatch 任何新任务前,请务必先检查目标 Agent 的 todo.md 和全局任务状态。如果同一目标已有相似任务在进行中,直接跳过即可,绝对禁止重复分发。\n\n请检查上述任务的执行结果,然后根据你的 plan.md 继续执行下一步计划。`; -- libgit2 0.21.4