新增: spawn_agent 子代理派发与级联取消

- 纯内存子会话隔离上下文,一轮回传结论报告
- 白名单钳制低风险并恒剔 spawn_agent 防递归
- 子代理策略下高风险自动拒绝,不挂审批防卡死
- 轮数令牌挂钟三重熔断
- 父停止与删会话级联取消子代理
- AiAgentFinished 事件挂父会话
This commit is contained in:
lxy
2026-10-01 19:35:21 +08:00
parent 524120b110
commit 2187ffe173
13 changed files with 1407 additions and 21 deletions
+32 -2
View File
@@ -244,6 +244,14 @@ pub struct AppState {
/// workspace_root 始终在白名单(向后兼容)。
/// Phase B 将扩展为 persistent + session(会话临时授权) + 弹窗挂起。
pub allowed_dirs: Arc<RwLock<AllowedDirs>>,
/// spawn_agent 级联取消注册表(parent conv_id → children child conv_ids)。
///
/// spawn 前注册、子循环结束注销(tools/spawn_agent.rs);父会话被停止/强制发送/删除时,
/// ai_chat_stop / ai_chat_force_send / ai_conversation_delete 遍历 children 置
/// stop_flag + notify 级联取消(子循环停止检查点兼查 own_stop/父 stop/父条目消失)。
/// 与 SpawnAgentCtx.sub_agents 共享同一 Arc(state.rs init 提前构建)。
pub sub_agent_registry:
crate::commands::ai::agentic::sub_agent::SubAgentRegistry,
// ── 跨端隧道(Phase3 Layer1)──
/// 桌面端出站 WS 隧道客户端,连 df-relay(/ws/device)透传 ai_event_bus → miniapp
/// + 转发 miniapp 下行指令 → remote_bridge。lib.rs setup spawn task 解析
@@ -337,9 +345,26 @@ impl AppState {
gateway_url: std::env::var("DF_LOCAL_PROXY_BASE")
.unwrap_or_else(|_| "http://127.0.0.1:8899".to_string()),
};
// spawn_agent(2026-10-01):子代理派发工具 ctx 提前构建(同 get_app_config 绕 AppState
// 自引用先例)。session/conv_states/sub_agents 三个 Arc 先建,下方 state struct 字段
// 复用同一实例(级联取消注册表三方共享:AppState / SpawnAgentCtx / 级联入口)。
let ai_session = Arc::new(Mutex::new(AiSession::new()));
let conv_states = Arc::new(crate::commands::ai::agentic::conv_state::ConvStateStore::new());
let sub_agent_registry = crate::commands::ai::agentic::sub_agent::new_registry();
let spawn_agent_ctx = crate::commands::ai::tools::spawn_agent::SpawnAgentCtx {
session: ai_session.clone(),
conv_states: conv_states.clone(),
llm_concurrency: llm_concurrency.clone(),
db: db.clone(),
sub_agents: sub_agent_registry.clone(),
};
let ai_tools = Arc::new(crate::commands::ai::build_ai_tool_registry(
&db, &allowed_dirs, data_dir.clone(), get_app_config_ctx, local_proxy_ctx,
spawn_agent_ctx,
));
// spawn_agent 白名单钳制需要注册表自身 Arc,注册期无法捕获(自引用),
// 构建完成后回注进程级 OnceLock(handler 运行期读取)。
crate::commands::ai::tools::spawn_agent::init_global_tool_registry(ai_tools.clone());
// Input Augmentation 层(核心设计2):ResolverRegistry 启动期注册四 resolver。
// resolver 持 Arc<Database>(非 AppState,避免循环依赖:AppState 持 Arc<ResolverRegistry>),
// 在 struct 字段 `db` move 前 clone 注入,与 build_ai_tool_registry 同侧。
@@ -364,11 +389,13 @@ impl AppState {
ai_conversations: AiConversationRepo::new(&db),
ai_messages: AiMessageRepo::new(&db),
ai_tool_executions: AiToolExecutionRepo::new(&db),
ai_session: Arc::new(Mutex::new(AiSession::new())),
// 复用上方提前构建的 Arc(spawn_agent ctx 注入同一实例,共享底层会话状态)
ai_session,
// L3 批2b:AI 事件总线入 AppState(独立于工作流 event_bus)。emit 双写留批3。
ai_event_bus: crate::commands::ai::event_bus::EventBus::new(),
// B-Phase1: ConvStateStore 无锁存储(空构造;双轨期无写点,B-Phase2 写侧切入)。
conv_states: Arc::new(crate::commands::ai::agentic::conv_state::ConvStateStore::new()),
// 复用上方提前构建的 Arc(spawn_agent ctx 注入同一实例)。
conv_states,
// Phase3 Layer1:tunnel 客户端未连接实例,lib.rs setup 内 connect
tunnel: std::sync::Arc::new(df_tunnel::WsTunnelClient::new()),
knowledge: KnowledgeRepo::new(&db),
@@ -384,6 +411,9 @@ impl AppState {
workflow_state_registry: Arc::new(Mutex::new(HashMap::new())),
// F-260619-03 Phase A: 与 ai_tools registry 共享同一 Arc(构建时注入同一句柄)
allowed_dirs: allowed_dirs.clone(),
// spawn_agent 级联取消注册表(parent→children):ai_chat_stop / ai_chat_force_send /
// ai_conversation_delete 命中父 conv 时遍历 children 置 stop_flag,与 SpawnAgentCtx 共享。
sub_agent_registry,
db,
event_bus: EventBus::new(),
registry,