修复: B-21工具卡重复治本(audit tc_list按id去重保证emit唯一)

This commit is contained in:
2026-06-17 02:26:22 +08:00
parent 2d02cff7a6
commit 247dc5da4a

View File

@@ -1,6 +1,6 @@
//! 工具调用审计 + pending 审批恢复 + 工具调用处理 //! 工具调用审计 + pending 审批恢复 + 工具调用处理
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use std::sync::Arc; use std::sync::Arc;
use serde::Serialize; use serde::Serialize;
@@ -531,6 +531,13 @@ pub(crate) async fn process_tool_calls(
) -> usize { ) -> usize {
let mut tc_list: Vec<_> = tool_calls_acc.into_iter().collect(); let mut tc_list: Vec<_> = tool_calls_acc.into_iter().collect();
tc_list.sort_unstable_by_key(|(i, _)| *i); 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<String> = HashSet::new();
tc_list.retain(|(_, draft)| seen_ids.insert(draft.id.clone()));
let mut pending_count = 0usize; let mut pending_count = 0usize;
let audit_repo = AiToolExecutionRepo::new(db); let audit_repo = AiToolExecutionRepo::new(db);