重构: Coordinator 接入 agentic loop + audit 拆分(approval/record)

- audit/approval.rs: 审批门控(风险分类+自动执行+挂起审批)

- audit/record.rs: 审计记录写入+历史查询

- coordinator.rs: 移除 deprecated,正式作为 P0 骨架可用

- run_agentic_loop: plan_execution_enabled 时 Coordinator 分解意图→记录 Plan

- audit/mod.rs 从 ~500 行精简至 ~200 行(编排层)
This commit is contained in:
2026-07-01 14:29:34 +08:00
parent a9ee9b1f74
commit fa410e6843
11 changed files with 1234 additions and 523 deletions

View File

@@ -1,68 +1,12 @@
//! 工具调用审计记录写/回填(audit_tool_call 写入 + audit_finalize 审批后状态回填)
//! 审批后审计记录状态回填(audit_finalize)
//!
//! 第二批从 audit/mod.rs 抽出(行为零变更,纯 fn 搬迁)。re-export 经 audit/mod.rs
//! `pub use finalize::{audit_tool_call, audit_finalize};` 保持 `commands::ai::audit::*`
//! 路径透明(调用方零变更)。
use df_ai::ai_tools::RiskLevel;
use df_storage::crud::AiToolExecutionRepo;
use df_storage::models::AiToolExecutionRecord;
use df_types::types::new_id;
//! `audit_tool_call` 已移至 record.rs审计记录写入操作归 audit record 子模块)。
//! re-export 经 audit/mod.rs `pub(crate) use finalize::audit_finalize;` 保持
//! `commands::ai::audit::*` 路径透明(调用方零变更)。
use crate::commands::now_millis;
use crate::state::AppState;
use super::risk_str;
/// 写一条工具执行审计记录insert 失败不阻断主流程,故 `let _ =`
///
/// `decided_by` 有值auto/human= 已决策执行 → 记 executed_at
/// `None`pending 待审批)→ executed_at 留空,待 audit_finalize 回填。
pub(crate) async fn audit_tool_call(
repo: &AiToolExecutionRepo,
conv_id: &str,
tool_call_id: &str,
tool_name: &str,
arguments: &str,
status: &str,
risk_level: RiskLevel,
result: Option<String>,
decided_by: Option<&str>,
message_id: Option<&str>,
) {
let executed_at = if decided_by.is_some() { Some(now_millis()) } else { None };
if let Err(e) = repo
.insert(AiToolExecutionRecord {
id: new_id(),
conversation_id: Some(conv_id.to_string()),
// F-260619-04 P1 消息级溯源:message_id 由调用方(process_tool_calls)从
// ContextManager 取当前 assistant 消息 id 传入(LLM 返回带 tool_calls 的
// assistant 消息已 push 到 per_conv.messages,入口取末条 assistant id)。
// None 表示无 assistant 消息(异常路径/老数据无 id),展示侧兼容。
message_id: message_id.map(|s| s.to_string()),
tool_call_id: tool_call_id.to_string(),
tool_name: tool_name.to_string(),
arguments: arguments.to_string(),
result,
status: status.to_string(),
risk_level: risk_str(risk_level).to_string(),
requested_at: now_millis(),
executed_at,
decided_by: decided_by.map(|s| s.to_string()),
})
.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
///
/// 走专用 find_by_tool_call_id —— 通用 query 宏硬编码 ORDER BY created_at DESC