From 247dc5da4afe646029f32bae494e4cd17f185370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Wed, 17 Jun 2026 02:26:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20B-21=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E5=8D=A1=E9=87=8D=E5=A4=8D=E6=B2=BB=E6=9C=AC(audit=20tc=5Flist?= =?UTF-8?q?=E6=8C=89id=E5=8E=BB=E9=87=8D=E4=BF=9D=E8=AF=81emit=E5=94=AF?= =?UTF-8?q?=E4=B8=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/commands/ai/audit.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/commands/ai/audit.rs b/src-tauri/src/commands/ai/audit.rs index 7dda5de..8c31226 100644 --- a/src-tauri/src/commands/ai/audit.rs +++ b/src-tauri/src/commands/ai/audit.rs @@ -1,6 +1,6 @@ //! 工具调用审计 + pending 审批恢复 + 工具调用处理 -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use serde::Serialize; @@ -531,6 +531,13 @@ pub(crate) async fn process_tool_calls( ) -> usize { let mut tc_list: Vec<_> = tool_calls_acc.into_iter().collect(); tc_list.sort_unstable_by_key(|(i, _)| *i); + // B-260616-21 治本兜底:LLM 异常复用同 tool_use.id(stream_recv 按 content_block index 分桶, + // 同 id 不同 index draft 可并存 → 每 draft emit AiToolCallStarted 致同 id emit 两次 → 前端 push 两卡, + // Completed 按 id 只 update 首张 → 次张残留 running 0行)。process 层按 id 去重——同 id 保留 + // 最小 index 的首个,丢弃后续,保证 emit Started 的 id 唯一。前端 useAiEvents.ts:205 findToolCall + // 守卫双保险。详 docs/02-架构设计/B-260616-21排查方案-2026-06-16.md。 + let mut seen_ids: HashSet = HashSet::new(); + tc_list.retain(|(_, draft)| seen_ids.insert(draft.id.clone())); let mut pending_count = 0usize; let audit_repo = AiToolExecutionRepo::new(db);