重构: F-09批2 调用方迁移per-conv(双写桥接共存期)
- agentic.rs: GeneratingGuard加conv_id + 三处退出校验改conv存在性(决策e) + stop_flag/notify/messages/iteration per-conv + try_continue加conv_id参数 - commands.rs: IPC写路径双写桥接(per_conv新真相源+顶层双写,批4删) + ai_is_generating读per_conv fallback顶层 - audit/conversation/title/knowledge_inject/lib.rs: per_conv读写迁移 - conv()/conv_read()去allow(批2有调用方) 共存期双写: per_conv主+顶层双写兼容批4前IPC,批4签名改后删顶层 主代兜底: cargo check --workspace 0 + test 96 passed + grep三处退出/GeneratingGuard/双写印证
This commit is contained in:
@@ -444,8 +444,12 @@ pub(crate) fn emit_data_changed(app_handle: &AppHandle, tool_name: &str) {
|
||||
/// - 返回 None 表示无缓存命中(走原审批流程)。
|
||||
///
|
||||
/// `session` 只读扫描 messages(不写),调用方据返回值决定是否跳过 insert pending。
|
||||
///
|
||||
/// F-260616-09 B 批2:经 `conv_id` 索引 per_conv.messages(顶层 messages 批2 后是死字段)。
|
||||
/// conv_id 来源:process_tool_calls 入参 → 由 agentic.rs run_agentic_loop 入参透传。
|
||||
async fn find_cached_high_risk_result(
|
||||
session: &AiSession,
|
||||
conv_id: &str,
|
||||
audit_repo: &AiToolExecutionRepo,
|
||||
tool_name: &str,
|
||||
args: &serde_json::Value,
|
||||
@@ -455,9 +459,12 @@ async fn find_cached_high_risk_result(
|
||||
// 规范化新调用的 args 为可比字符串(排序键,键序无关)
|
||||
let new_args_key = canonical_args_key(args);
|
||||
|
||||
// F-260616-09 B 批2:读 per_conv.messages。process_tool_calls 调用前 loop 入口已桥接建立 per_conv,
|
||||
// 故 conv_read 必命中;防御性 None 时返 None(无缓存命中,走原审批流程)。
|
||||
let conv = session.conv_read(conv_id)?;
|
||||
// ContextManager::iter 返回 impl Iterator(非 DoubleEnded),collect 成 Vec 再反向遍历。
|
||||
// 单对话消息量小(百级),collect 开销可忽略。
|
||||
let msgs: Vec<&ChatMessage> = session.messages.iter().collect();
|
||||
let msgs: Vec<&ChatMessage> = conv.messages.iter().collect();
|
||||
|
||||
// 1) 反向扫描 assistant tool_calls,找最近一条同名同参的 High 工具调用 → 拿到旧 tool_call_id
|
||||
// 反向:循环是「最近一次超时→重试」,命中通常是末尾附近,反向先停省全扫。
|
||||
@@ -629,7 +636,8 @@ pub(crate) async fn process_tool_calls(
|
||||
// (用户信任同目录同类操作,但仍要看每次的真实结果)。
|
||||
let trust_hit = super::trust_key_for(&draft.name, &args)
|
||||
.and_then(|key| {
|
||||
if session.session_trust.contains(&key) {
|
||||
// F-260616-09 B 批2:读 per_conv.session_trust(conv_id 来源:本函数入参)。
|
||||
if session.conv_read(conv_id).map(|c| c.session_trust.contains(&key)).unwrap_or(false) {
|
||||
Some(key)
|
||||
} else {
|
||||
None
|
||||
@@ -660,14 +668,15 @@ pub(crate) async fn process_tool_calls(
|
||||
}
|
||||
// F-05:仅 High 查去重缓存;Med 保持原审批流程
|
||||
if matches!(risk_level, RiskLevel::High) {
|
||||
if let Some((cached, status)) = find_cached_high_risk_result(session, &audit_repo, &draft.name, &args).await {
|
||||
if let Some((cached, status)) = find_cached_high_risk_result(session, conv_id, &audit_repo, &draft.name, &args).await {
|
||||
// 命中:把缓存结果作为新 tool_call_id 的 tool_result 回传,跳过审批
|
||||
tracing::info!(
|
||||
tool = %draft.name,
|
||||
new_tool_call_id = %draft.id,
|
||||
"[F-05] 高危工具去重命中:LLM 重试同命令,复用缓存结果跳过审批(断循环)"
|
||||
);
|
||||
session.messages.push(ChatMessage::tool_result(&draft.id, &cached));
|
||||
// F-260616-09 B 批2:写 per_conv.messages(conv_id 来源:本函数入参)。
|
||||
session.conv(conv_id).messages.push(ChatMessage::tool_result(&draft.id, &cached));
|
||||
let _ = app_handle.emit("ai-chat-event", AiChatEvent::AiToolCallCompleted {
|
||||
id: draft.id.clone(),
|
||||
result: serde_json::Value::String(cached.clone()),
|
||||
@@ -696,7 +705,7 @@ pub(crate) async fn process_tool_calls(
|
||||
recovered: false,
|
||||
diff: approval_diff.clone(),
|
||||
});
|
||||
session.messages.push(ChatMessage::tool_result(&draft.id, PENDING_APPROVAL_PLACEHOLDER));
|
||||
session.conv(conv_id).messages.push(ChatMessage::tool_result(&draft.id, PENDING_APPROVAL_PLACEHOLDER));
|
||||
let reason = build_approval_reason(&draft.name, &args, risk_level, db).await;
|
||||
let _ = app_handle.emit("ai-chat-event", AiChatEvent::AiApprovalRequired {
|
||||
id: draft.id.clone(),
|
||||
@@ -757,7 +766,8 @@ pub(crate) async fn process_tool_calls(
|
||||
Ok(c) => ("completed", c),
|
||||
Err(c) => ("failed", c),
|
||||
};
|
||||
session.messages.push(ChatMessage::tool_result(&draft.id, content.clone()));
|
||||
// F-260616-09 B 批2:写 per_conv.messages。
|
||||
session.conv(conv_id).messages.push(ChatMessage::tool_result(&draft.id, content.clone()));
|
||||
// 审计:trust 放行仍记一条(decided_by=auto_trust),留痕可追溯
|
||||
audit_tool_call(&audit_repo, conv_id, &draft.id, &draft.name, &draft.args, status, risk_level, Some(content), Some("auto_trust")).await;
|
||||
}
|
||||
@@ -810,7 +820,8 @@ pub(crate) async fn process_tool_calls(
|
||||
Ok(c) => ("completed", c),
|
||||
Err(c) => ("failed", c),
|
||||
};
|
||||
session.messages.push(ChatMessage::tool_result(&draft.id, content.clone()));
|
||||
// F-260616-09 B 批2:写 per_conv.messages。
|
||||
session.conv(conv_id).messages.push(ChatMessage::tool_result(&draft.id, content.clone()));
|
||||
audit_tool_call(&audit_repo, conv_id, &draft.id, &draft.name, &draft.args, status, RiskLevel::Low, Some(content), Some("auto")).await;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user