新增: 任务工作流 AiAgentNode 直连会话编排

- ai 节点 mode agent 开关派发,默认旧路径零回归
- 完成通知桥注册触发,收敛出口单点投递报告
- 节点超时取消兜底,结果落任务产出
- 会话编排走独立新会话,不劫持活跃面板
This commit is contained in:
lxy
2026-10-01 19:35:22 +08:00
parent 7dcbdb1feb
commit bf0db10ef7
6 changed files with 513 additions and 11 deletions
+23 -6
View File
@@ -37,14 +37,17 @@ pub fn template_for(target_status: &str) -> Option<DagDef> {
/// todo → in_progress:单 AiNode 执行任务。
///
/// 拓扑:1 个 ai 节点。完成回调(②-3)推进 status 到 in_progress。
///
/// mode:"agent" → ai 节点工厂构造 AiAgentNode(直连 agentic 会话编排执行,多轮工具
/// 调用后取最终报告);缺省/"ask" 走旧 AiNode(单次补全,旧调用方零回归)。
/// 其余运行时参数(prompt/provider/task_id)仍由 run_workflow 全局 config 注入
/// (④-1 deep_merge 合并),模板只描述拓扑 + 执行模式。
fn in_progress_template() -> DagDef {
let mut dag = DagDef::new();
// config 留空:prompt / provider / task_id 均由 run_workflow 全局 config 注入
// (④-1 deep_merge 合并),模板只描述拓扑。
dag.add_node(
"ai_execute",
"ai",
serde_json::json!({}),
serde_json::json!({ "mode": "agent" }),
);
dag
}
@@ -120,10 +123,24 @@ mod tests {
assert!(dag.edges.is_empty(), "in_progress: 无边");
let node = dag.nodes.get("ai_execute").expect("ai_execute 节点存在");
assert_eq!(node.node_type, "ai");
// config 留空(运行时注入)
// mode:"agent" → 工作流编排执行(AiAgentNode 直连 agentic 会话);
// 其余运行时参数仍留空(由 run_workflow 全局 config 注入)。
assert_eq!(
node.config.get("mode").and_then(|v| v.as_str()),
Some("agent"),
"ai_execute 应以 mode=agent 走编排节点"
);
let non_mode_keys: Vec<&String> = node
.config
.as_object()
.expect("config 应为对象")
.keys()
.filter(|k| *k != "mode")
.collect();
assert!(
node.config.as_object().map(|o| o.is_empty()).unwrap_or(true),
"ai_execute config 应为空对象"
non_mode_keys.is_empty(),
"ai_execute 除 mode 外 config 应留空(运行时注入),实际: {:?}",
non_mode_keys
);
}