From a7dbd50a4dfeefa0ae03512052817290e5d08a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Wed, 24 Jun 2026 17:18:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20aichat=20P2=E7=A1=AE?= =?UTF-8?q?=E5=AE=9A=E6=80=A7bug=E6=89=B9(audit=E5=90=9E=E9=94=99=E8=90=BD?= =?UTF-8?q?=E6=97=A5=E5=BF=97+switch/delete=E5=8D=A0=E4=BD=8D=E7=BB=88?= =?UTF-8?q?=E6=80=81=E5=8C=96)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit finalize: audit_tool_call insert 用 let _ = 吞 DB 错改 match Err tracing::error(对齐 audit_finalize:82模式,控制流不变不阻断,审计写失败落日志可确诊) conversation+chat: switch/delete retain pending 前补 finalize_pending_placeholders 占位终态化(对齐 stop/clear/force_send,防占位 tool_result 残留下次发送喂 LLM);chat.rs finalize_pending_placeholders 可见性 fn→pub(crate) cargo check --workspace 零错 --- src-tauri/src/commands/ai/audit/finalize.rs | 13 +++++++++++-- src-tauri/src/commands/ai/commands/chat.rs | 2 +- src-tauri/src/commands/ai/commands/conversation.rs | 8 ++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/commands/ai/audit/finalize.rs b/src-tauri/src/commands/ai/audit/finalize.rs index fb32c9b..05a913b 100644 --- a/src-tauri/src/commands/ai/audit/finalize.rs +++ b/src-tauri/src/commands/ai/audit/finalize.rs @@ -32,7 +32,7 @@ pub(crate) async fn audit_tool_call( message_id: Option<&str>, ) { let executed_at = if decided_by.is_some() { Some(now_millis()) } else { None }; - let _ = repo + if let Err(e) = repo .insert(AiToolExecutionRecord { id: new_id(), conversation_id: Some(conv_id.to_string()), @@ -51,7 +51,16 @@ pub(crate) async fn audit_tool_call( executed_at, decided_by: decided_by.map(|s| s.to_string()), }) - .await; + .await + { + tracing::error!( + "audit_tool_call: 写审计记录失败(conv={}, tool_call_id={}, tool={}): {}", + conv_id, + tool_call_id, + tool_name, + e + ); + } } /// 审批后更新审计记录状态(按 tool_call_id 定位 pending 记录,回填 status/decided_by=human/executed_at/result) diff --git a/src-tauri/src/commands/ai/commands/chat.rs b/src-tauri/src/commands/ai/commands/chat.rs index 85a8150..6e4c5cc 100644 --- a/src-tauri/src/commands/ai/commands/chat.rs +++ b/src-tauri/src/commands/ai/commands/chat.rs @@ -51,7 +51,7 @@ use super::super::{AiChatEvent, ApprovalKind, SessionState}; /// 终态化策略:每条 pending 审批按其自身 `conversation_id` 终态化到对应 conv 的 per_conv.messages; /// conv_id 入参作 fallback(审批无 conversation_id 的无主审批 R-9 异常数据,终态化到入参 conv, /// 入参也空则跳过——审计仍记,占位不残留内存因 pending 即将被 clear/retain)。 -fn finalize_pending_placeholders(session: &mut super::super::AiSession, conv_id: &str, final_text: &str) { +pub(crate) fn finalize_pending_placeholders(session: &mut super::super::AiSession, conv_id: &str, final_text: &str) { // SW-260618-02: 先 clone pending 的 tool_call_id(借用在此结束),再可变借 messages。 // 必须整体借 &mut session 在函数体内做 disjoint field borrow —— 调用方若分别传 // &mut messages + &pending 两个引用,函数参数列表不做 disjoint 推断会触发 E0502(2026-06-18 主代修)。 diff --git a/src-tauri/src/commands/ai/commands/conversation.rs b/src-tauri/src/commands/ai/commands/conversation.rs index bfacb1e..ea6d317 100644 --- a/src-tauri/src/commands/ai/commands/conversation.rs +++ b/src-tauri/src/commands/ai/commands/conversation.rs @@ -312,6 +312,10 @@ pub async fn ai_conversation_switch( // 仅清空目标对话自身的挂起审批,保留其他对话的(防 init 重建的内存 HashMap 被清空, // 重启恢复链路:restore_pending_approvals(init 重建) → switchConversation(此处不清目标对话的) // → ai_pending_tool_calls 查询 → ai_approve 落库)。 + // SW-260618-02(7-ipc-approval 配套 stop/clear/force_send 终态化):切走目标 conv 前, + // 先把其 pending 审批占位 tool_result 终态化为"会话已切换",防占位残留下次发送喂给 LLM。 + // 须在 retain 前(遍历即将被丢弃的条目)——chat.rs:44 硬契约,顺序不能反。 + super::chat::finalize_pending_placeholders(&mut *session, &conversation_id, "会话已切换"); // 阶段3a 单真相源合并:单表 retain(kind 不区分,清本 conv 保留其他)。 session.pending_approvals.retain(|_, a| a.conversation_id.as_deref() != Some(&conversation_id)); // 释放 session lock 再做 async provider 查询 + spawn(避免持锁 await DB) @@ -357,6 +361,10 @@ pub async fn ai_conversation_delete( // 删除任意对话(含非活跃)都应清理其积压审批:挂起审批是会话级 HashMap, // 非活跃对话的恢复审批(recovered,conversation_id 指向被删对话)若不 retain 清理, // 会永久残留死审批条目。对齐 ai_conversation_switch 的 retain 口径(仅清目标对话,保留其他)。 + // SW-260618-02(7-ipc-approval 配套 stop/clear/force_send 终态化):删除目标 conv 前, + // 先把其 pending 审批占位 tool_result 终态化为"会话已删除",防占位残留下次发送喂给 LLM。 + // 须在 retain 前(遍历即将被丢弃的条目)——chat.rs:44 硬契约,顺序不能反。 + super::chat::finalize_pending_placeholders(&mut *session, &conversation_id, "会话已删除"); // 阶段3a 单真相源合并:单表 retain(kind 不区分)。 session.pending_approvals.retain(|_, a| a.conversation_id.as_deref() != Some(&conversation_id)); // F-260616-09 B 批4:删除 conv 时移除其 per_conv 条目(设计 §4.1 conv 存在性判据依赖此,