修复: B-260617-01 run_workflow审批执行(抽取run_workflow_inner+ai_approve后端分支)

This commit is contained in:
2026-06-17 01:39:28 +08:00
parent f2a56b6982
commit e23b316faf
4 changed files with 129 additions and 17 deletions

View File

@@ -529,30 +529,34 @@ pub fn build_ai_tool_registry(db: &Arc<Database>) -> AiToolRegistry {
// 实施路径文档 §三 列为阶段3 必做项(tool_registry.rs 此前无此工具连空壳都没有)。
// 描述明确按任务 target_status 推进对应工作流(含 AiNode 自审 / HumanNode 核对闸门)。
//
// handler 约束说明:run_workflow 真正执行需要 AppHandle(转发 workflow-event 到前端) +
// AppState(registry 构建 DAG / event_bus 订阅 / workflows Repo 落库 / workflow_state_registry
// 注销)等 Tauri 注入态,这些在 tool handler(仅持 db: Arc<Database>)中无法构造。
// 现阶段仅注册 ToolDefinition(schema + risk + 描述)让 LLM 知晓此能力并产出 tool_call;
// 真正触发须走 Tauri IPC(经 invoke_handler 注册的 run_workflow 命令,持有完整 State)。
// handler 显式报错引导走 IPC,避免在 handler 内重放 DAG 执行引擎(违反单一执行路径原则)。
// 后续若需 AI 直驱完整工作流,需扩展 build_ai_tool_registry 注入 AppState 句柄(改 state.rs,
// 留待推进链后续批次)。
// handler 约束说明(B-260617-01 更新):run_workflow 真正执行需要 AppHandle(转发 workflow-event
// 到前端) + AppState(registry 构建 DAG / event_bus 订阅 / workflows Repo 落库 /
// workflow_state_registry 注销),这些在 tool handler(仅持 db: Arc<Database>)中无法构造。
//
// **执行路径(单一)**:run_workflow 是 High risk → 始终经 audit.rs:process_tool_calls 进 pending
// → ai_approve 审批 → commands.rs ai_approve 内识别 run_workflow 分支调
// execute_run_workflow_for_tool(mod.rs)→ workflow.rs::run_workflow_inner(持完整 State)真正执行。
// 故本 handler 经 ai_tools.execute 调用的路径在正常流程下不可达(dead code 防御):
// 仅当未来出现"不经 ai_approve 直接 execute run_workflow"的异常调用方时,本 Err 作为防御兜底
// 返回明确错误,而非静默 panic。LLM 误判重试同 tool_call 时,High risk 去重缓存
// (audit.rs:find_cached_high_risk_result)会复用旧 tool_result 跳过审批,断重试循环。
registry.register(
"run_workflow", "按任务 target_status 推进对应工作流(含 AiNode 自审 / HumanNode 核对闸门)。参数 task_id + target_status 同时提供才联动任务推进(完成后按 target_status 推进任务,失败按退回态回滚)。属高风险操作(触发工作流引擎执行),须人工批准",
"run_workflow", "按任务 target_status 推进对应工作流(含 AiNode 自审 / HumanNode 核对闸门)。参数 task_id + target_status 同时提供才联动任务推进(完成后按 target_status 推进任务,失败按退回态回滚)。属高风险操作(触发工作流引擎执行),须人工批准。审批通过后由后端直接执行工作流引擎并联动推进任务,返回 execution_id",
df_ai::ai_tools::object_schema(vec![("task_id", "string", true), ("target_status", "string", true)]),
RiskLevel::High,
{ let db = db.clone(); Box::new(move |args: serde_json::Value| {
let _db = db.clone();
{ let _db = db.clone(); Box::new(move |args: serde_json::Value| {
Box::pin(async move {
let task_id = args["task_id"].as_str().ok_or_else(|| anyhow::anyhow!("缺少 task_id"))?;
let target_status = args["target_status"].as_str()
.ok_or_else(|| anyhow::anyhow!("缺少 target_status"))?;
// handler 无法访问 AppHandle/State(registry/event_bus/workflows Repo),
// 真正执行须走 run_workflow Tauri IPC(持有完整 State)。
// 这里返回明确错误引导前端走 IPC,而非在 handler 内重放 DAG 引擎
// 防御兜底(正常流程不可达):run_workflow 经 ai_approve 分支执行,不经此 handler。
// 误入此路径说明调用方异常(非 ai_approve 直接 execute),返回明确错误勿盲目重试
// (对齐 run_command 超时标注模式 L700-712),High risk 去重缓存会断 LLM 重试循环
Err(anyhow::anyhow!(
"run_workflow 工具需经 Tauri IPC 执行(持有 AppHandle/State),handler 无 State 句柄。\
请前端收到此 tool_call 后转调 invoke('run_workflow', {{ task_id: {}, target_status: {} }})。",
"run_workflow 须经人工审批后由后端 ai_approve 分支执行(转调 run_workflow_inner,\
持完整 State)。本 handler 经 ai_tools.execute 调用属异常路径(无 AppHandle/State),\
勿盲目重试同调用(task_id={}, target_status={});\
若需推进任务,重新发起 run_workflow tool_call 走审批流程。",
task_id, target_status
))
})