diff --git a/packages/core/src/core/agent-message-handler.ts b/packages/core/src/core/agent-message-handler.ts index 4647b71..b8d04f5 100644 --- a/packages/core/src/core/agent-message-handler.ts +++ b/packages/core/src/core/agent-message-handler.ts @@ -225,6 +225,11 @@ export class AgentMessageHandler { ): void { const toolCallId = chunk.toolCallId || `tool-${Date.now()}`; + // 去重:如果该工具调用已经被处理过,跳过 + if (toolStartTimes.has(toolCallId)) { + return; + } + // Doom Loop 检测 this.doomLoopDetector.record(chunk.toolName, chunk.input); @@ -236,7 +241,7 @@ export class AgentMessageHandler { onStream?.(DOOM_LOOP_WARNING); } - // 记录开始时间 + // 记录开始时间(同时作为去重标记) toolStartTimes.set(toolCallId, Date.now()); // 调用回调 diff --git a/packages/core/src/core/agent.ts b/packages/core/src/core/agent.ts index b899516..3c8b1ae 100644 --- a/packages/core/src/core/agent.ts +++ b/packages/core/src/core/agent.ts @@ -193,10 +193,11 @@ export class Agent { this.toolExecutor.setAgentMode(this.modeManager.getCurrentMode()); // 获取工具 + // 注意:不传 onToolStart 给 toVercelTools,因为 streamChat 的 onChunk 已经会触发 + // 如果同时传给两处,会导致前端收到两次 tool_start 事件 const vercelTools = this.toolExecutor.toVercelTools({ sessionId: this.sessionManager?.getSession()?.id || 'default', agentMode: this.modeManager.getCurrentMode(), - onToolStart, onToolEnd, });