新增: 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
+10 -3
View File
@@ -245,6 +245,9 @@ pub enum ToolDomain {
/// 命令执行:run_command(shell 命令)。基本盘成员:读写执行为 agent 基本能力
/// (2026-09-30 用户拍板,不受意图收敛限制),安全由执行层 validate_path/授权/RiskLevel 兜底
Exec,
/// 编排:spawn_agent 子代理派发。基本盘成员:委派是编排类基本能力,
/// 高置信意图收敛下不登记则工具对 LLM 不可见,安全由子代理侧白名单钳制兜底
Agent,
/// 网络:HTTP
Http,
}
@@ -288,6 +291,8 @@ impl ToolDomain {
// 2026-09-30 用户拍板读写执行为 agent 基本能力,不再仅 Debug 暴露;
// 安全由执行层兜底(RiskLevel 审批/授权三道门/路径黑名单),藏工具≠安全。
ToolDomain::Exec => &["run_command"],
// Agent domain:spawn_agent 单列,编排委派基本盘成员(子代理侧白名单钳制兜底安全)。
ToolDomain::Agent => &["spawn_agent"],
ToolDomain::Http => &["http_request"],
// DataReadOnly:Data domain 的只读子集。
// 源于 Code 意图收敛需求:用户在编码场景说"先 list_projects 看下项目结构"
@@ -440,7 +445,8 @@ fn best_in_group(message: &str, group: &[IntentGroup]) -> Option<(Intent, f32)>
/// 上游应走**全量 fallback**(即不过滤工具,交全量给 LLM)。
///
/// 设计(2026-09-30 起):基本盘 + 场景增量。
/// 基本盘 = File + Exec:读、写、执行命令是 agent 基本能力,不受意图收敛限制(用户拍板),
/// 基本盘 = File + Exec + Agent:读、写、执行命令、委派子代理是 agent 基本能力,
/// 不受意图收敛限制(用户拍板),
/// 所有非空子集意图(Code/Debug/File/Project/Task/Idea/Search/Http)都可见。
/// 安全防线在执行层:validate_path 黑名单 + 授权三道门 + RiskLevel 审批,藏工具≠安全;
/// 藏工具只会复现断手(Project 砍 File 致 read_file 不可见、Debug 独占 run_command 致
@@ -451,8 +457,9 @@ fn best_in_group(message: &str, group: &[IntentGroup]) -> Option<(Intent, f32)>
/// (发请求是该意图本名能力,砍掉即复现断手)。
/// 各意图新子集均为旧子集超集,只增不减。
pub fn tool_subset_for(intent: &Intent) -> Vec<&'static str> {
// 基本盘:读写执行(RiskLevel/审批/路径授权兜底,藏工具≠安全);场景增量=业务域收敛减少分心
const BASE_DOMAINS: &[ToolDomain] = &[ToolDomain::File, ToolDomain::Exec];
// 基本盘:读写执行 + 编排委派(RiskLevel/审批/路径授权/子代理白名单钳制兜底,藏工具≠安全);
// 场景增量=业务域收敛减少分心
const BASE_DOMAINS: &[ToolDomain] = &[ToolDomain::File, ToolDomain::Exec, ToolDomain::Agent];
let extra: &[ToolDomain] = match intent {
Intent::Code => &[ToolDomain::Http, ToolDomain::DataReadOnly],
Intent::Debug => &[ToolDomain::Http, ToolDomain::Data],