主题
工具执行框架
本文引用的源码文件
本文引用的文件
- src/background/tool-executor.js
- src/background/constants.js
- src/background/tool-preselector.js
- src/background/tool-helpers.js
- src/background/react-loop.js
- src/background/agent-dispatcher.js
- agent/src/executor.js
- agent/src/security.js
- agent/src/server.js
- src/background/index.js
- src/options/toolbox-config.js
- src/side_panel/tool-panel.js
目录
引言
本文件面向“工具执行框架”的完整技术文档,覆盖以下目标:
- 工具定义与注册机制:内置工具、MCP 动态工具、RAG 知识库工具的元数据、参数压缩与注入。
- 工具调度算法:意图识别、工具预筛选、优先级排序、执行策略(顺序/并行/子任务)。
- 并行执行框架:任务分发、结果聚合、并发控制、资源管理。
- 错误处理机制:异常捕获、重试策略、降级处理、审计日志。
- 工具辅助函数库:参数解析修复、结果规范化、Content Script 通信等。
- Agent 端命令执行与安全分级:Shell 选择、超时预算、进程生命周期、黑白灰名单。
- 工具开发指南:新工具接入流程、测试建议、部署注意事项。
项目结构
扩展端 Background 负责工具注册、调度、并行执行、用户交互确认、截图与视觉分析、Agent 客户端调用;Agent 端提供命令执行、文件沙箱、搜索、RAG、MCP 能力。
graph TB subgraph "扩展端 Background" TE["tool-executor.js<br/>工具注册/调度/执行"] CONST["constants.js<br/>默认配置/工具集合"] PRE["tool-preselector.js<br/>工具预筛选"] HELP["tool-helpers.js<br/>参数解析/结果规范"] LOOP["react-loop.js<br/>ReAct 循环/并行分组"] DISPATCH["agent-dispatcher.js<br/>子代理派发"] IDX["background/index.js<br/>消息路由/MCP 缓存"] OPT["options/toolbox-config.js<br/>设置页 MCP 通知"] PANEL["side_panel/tool-panel.js<br/>侧边栏工具列表"] end subgraph "Agent 端" SRV["server.js<br/>HTTP+WebSocket 路由"] EXE["executor.js<br/>命令执行/超时策略"] SEC["security.js<br/>路径沙箱/命令分级"] end TE --> CONST TE --> PRE TE --> HELP TE --> LOOP TE --> DISPATCH TE --> IDX OPT --> IDX PANEL --> IDX TE --> SRV SRV --> EXE SRV --> SEC
图表来源
- src/background/tool-executor.js#L547-L684
- src/background/constants.js#L87-L149
- src/background/tool-preselector.js#L260-L432
- src/background/tool-helpers.js#L216-L361
- src/background/react-loop.js#L2253-L2281
- src/background/agent-dispatcher.js#L85-L115
- agent/src/server.js#L1-L56
- agent/src/executor.js#L198-L386
- agent/src/security.js#L685-L758
- src/background/index.js#L1196-L1231
- src/options/toolbox-config.js#L27-L66
- src/side_panel/tool-panel.js#L81-L115
章节来源
- src/background/tool-executor.js#L547-L684
- src/background/constants.js#L87-L149
- src/background/tool-preselector.js#L260-L432
- src/background/tool-helpers.js#L216-L361
- src/background/react-loop.js#L2253-L2281
- src/background/agent-dispatcher.js#L85-L115
- agent/src/server.js#L1-L56
- agent/src/executor.js#L198-L386
- agent/src/security.js#L685-L758
- src/background/index.js#L1196-L1231
- src/options/toolbox-config.js#L27-L66
- src/side_panel/tool-panel.js#L81-L115
核心组件
- 工具注册中心:集中维护 RAW_TOOLS、BUILTIN_TOOLS、TOOL_EXECUTION_MAP、PARALLELIZABLE_TOOLS、CONFIRMATION_REQUIRED_TOOLS,并支持 MCP/RAG 动态注入。
- 工具预筛选器:通过轻量 LLM 调用判断是否需要工具,直接回答或返回候选工具集。
- 工具执行器:统一入口,负责参数校验、权限检查、环境选择、执行、流式输出、超时控制、审计记录。
- ReAct 循环与并行分组:将多工具调用分组为并行组与顺序组,支持 plan_task 子任务拆分与失败回滚。
- Agent 命令执行器:跨平台 Shell 选择、安全环境变量、流式 stdout/stderr、超时预算与强制终止。
- 安全网关:路径白名单/硬阻止、命令黑白灰名单、链式命令拆分与内联载荷检测。
章节来源
- src/background/constants.js#L87-L149
- src/background/tool-executor.js#L547-L684
- src/background/tool-executor.js#L940-L1035
- src/background/tool-preselector.js#L260-L432
- src/background/react-loop.js#L2253-L2281
- agent/src/executor.js#L198-L386
- agent/src/security.js#L685-L758
架构总览
工具执行框架采用“扩展端调度 + Agent 端执行”的双进程模型:
- 扩展端负责工具发现、参数校验、权限与网络访问控制、用户确认、并行调度、结果聚合与审计。
- Agent 端负责命令执行、文件读写、搜索、RAG、MCP 工具调用,并提供 WebSocket 流式输出。
sequenceDiagram participant UI as "侧边面板/设置页" participant BG as "Background(tool-executor)" participant AG as "Agent(server.js)" participant EX as "Executor(executor.js)" participant SEC as "Security(security.js)" UI->>BG : 获取可用工具(getTools) BG->>AG : 查询 MCP/RAG 状态 AG-->>BG : 返回工具/能力 BG-->>UI : 返回工具清单(含元数据) UI->>BG : 触发工具调用 BG->>BG : 参数解析/校验/权限检查 BG->>AG : HTTP/WebSocket 调用 AG->>SEC : 命令/路径安全检查 SEC-->>AG : 允许/拒绝 AG->>EX : 执行命令(流式输出) EX-->>AG : stdout/stderr/exit AG-->>BG : 结果/流式片段 BG-->>UI : 聚合结果/审计日志
图表来源
- src/background/tool-executor.js#L1100-L1307
- src/background/tool-executor.js#L547-L684
- src/background/tool-executor.js#L940-L1035
- agent/src/server.js#L1-L56
- agent/src/executor.js#L198-L386
- agent/src/security.js#L685-L758
详细组件分析
工具定义与注册机制
- 内置工具:由 constants.js 汇总各模块工具数组,派生 BUILTIN_TOOLS、分类映射、并行/确认标记。
- MCP 动态工具:loadMcpTools 从 Agent 拉取工具列表,压缩 schema,注入 RAW_TOOLS/BUILTIN_TOOLS/TOOL_HANDLERS,并通过 rebuildBgHandlers 同步 BG_HANDLERS 与 PARALLELIZABLE_TOOLS/CONFIRMATION_REQUIRED_TOOLS。
- RAG 知识库工具:loadRagTools 在 ragEnabled=true 且 Agent 支持 RAG 时动态注册 knowledge_search/ingest/list。
- 服务级开关:MCP 工具按 serverId 关闭/排除/强制下发;RAG 工具随全局开关与 Agent 能力切换。
flowchart TD
Start(["启动/设置变更"]) --> CheckMCP{"MCP 已启用?"}
CheckMCP --> |否| SkipMCP["跳过加载"]
CheckMCP --> |是| FetchMCP["拉取 MCP 工具列表"]
FetchMCP --> Compress["压缩 schema/描述"]
Compress --> Inject["注入 RAW_TOOLS/BUILTIN_TOOLS/Handlers"]
Inject --> Rebuild["rebuildBgHandlers()"]
Rebuild --> DoneMCP["完成"]
Start --> CheckRAG{"RAG 已启用且 Agent 支持?"}
CheckRAG --> |否| SkipRAG["跳过加载"]
CheckRAG --> |是| LoadRAG["注册 knowledge_* 工具"]
LoadRAG --> SyncStorage["同步到 storage"]
SyncStorage --> DoneRAG["完成"]
图表来源
- src/background/tool-executor.js#L547-L684
- src/background/tool-executor.js#L940-L1035
- src/background/constants.js#L87-L149
章节来源
- src/background/constants.js#L87-L149
- src/background/tool-executor.js#L547-L684
- src/background/tool-executor.js#L940-L1035
工具元数据、参数验证与执行环境
- 元数据:id、category、execution、parallelizable、requiresConfirmation、function.name/description/parameters。
- 参数验证:tryParseToolArgs 两阶段解析(标准 JSON.parse + 修复),autoCompleteJson、fixArrayObjectMismatch、repairByParsePosition 提升鲁棒性。
- 执行环境:根据 execution 字段决定 background 执行;Agent 命令走 executor.js,带安全环境与 Shell 选择。
classDiagram
class ToolDefinition {
+string id
+string category
+string execution
+boolean parallelizable
+boolean requiresConfirmation
+Function function
}
class ParameterParser {
+tryParseToolArgs(argsStr) Object
+autoCompleteJson(str) string
+fixArrayObjectMismatch(str) string
}
class ResultNormalizer {
+makeResult(success, content, extra) Object
+normalizeToolResult(result, toolCallId) Object
}
ToolDefinition <.. ParameterParser : "参数解析"
ToolDefinition <.. ResultNormalizer : "结果规范化"
图表来源
章节来源
工具调度算法:意图识别、预筛选、优先级与执行策略
- 意图识别:preselectTools 调用 LLM 判断是否直接回答或需要工具;若无需工具则直接返回答案,减少二次调用。
- 预筛选阈值:当工具数量超过 PRESELECT_MIN_TOOL_COUNT 时才启用预筛选;否则直接使用全量工具。
- 优先级与过滤:按工具名匹配返回的工具 ID;必要时追加原型工具或强制保留工具(如 / 手动指定 MCP 服务)。
- 执行策略:ReAct 循环中按并行组与顺序组执行;plan_task 可拆分子任务,支持 stop/continue/skip 失败策略与并行子任务池。
flowchart TD
A["收到用户问题"] --> B{"工具数 > 阈值?"}
B --> |否| C["使用全部工具"]
B --> |是| D["构建预筛选提示词"]
D --> E["调用 LLM 预筛选"]
E --> F{"返回类型"}
F --> |answer| G["直接回答(不二次调用)"]
F --> |tools| H["匹配工具ID并过滤"]
H --> I["必要时追加原型/强制工具"]
I --> J["进入执行阶段"]
C --> J
图表来源
- src/background/tool-preselector.js#L78-L98
- src/background/tool-preselector.js#L260-L432
- src/background/constants.js#L24-L26
章节来源
- src/background/tool-preselector.js#L78-L98
- src/background/tool-preselector.js#L260-L432
- src/background/constants.js#L24-L26
- src/background/react-loop.js#L2253-L2281
并行执行框架:任务分发、结果聚合、并发控制与资源管理
- 并行分组:同一轮工具调用被划分为多个并行组;组内 Promise.all 并发执行,组间顺序执行。
- 子任务并行:dispatchSubtasksParallel 支持最大并发限制,按原始顺序聚合结果,支持取消与回滚。
- 资源管理:每个子任务执行前检查取消状态;plan_task 处理后中断同轮后续工具;失败策略支持 stop/continue/skip。
sequenceDiagram participant RL as "ReAct Loop" participant PG as "并行分组器" participant EC as "单工具执行器" participant ST as "子任务调度" RL->>PG : 分组工具调用 PG->>EC : 组内并行执行(Promise.all) EC-->>PG : 单个结果(可能含 planTaskHandled) PG-->>RL : 组结果聚合 RL->>ST : 子任务(顺序/并行) ST-->>RL : 结果(含失败策略/回滚)
图表来源
章节来源
权限检查与环境选择
- 路径沙箱:checkPath 对 workdir/allowedPaths 做前缀校验与 realpath 防符号链接绕过,硬阻止敏感目录。
- 命令分级:checkCommand 对整串与子段进行黑名单/灰名单判定,支持 force 模式;链式命令拆分、解释器内联载荷、$( )/反引号替换检测。
- Shell 选择:pickShell 根据平台与环境变量选择 bash/zsh/cmd/powershell,Windows 原生控制台程序避免 detached 弹窗。
flowchart TD
S["输入命令/路径"] --> P1["路径归一化/展开~"]
P1 --> P2{"命中硬阻止?"}
P2 --> |是| DENY["拒绝"]
P2 --> |否| P3{"workdir/allowedPaths 前缀匹配?"}
P3 --> |否| DENY
P3 --> |是| P4["realpath 校验/再次前缀检查"]
P4 --> ALLOW["允许"]
S --> C1["收集子命令范围(链式/内联/替换)"]
C1 --> C2{"命中黑名单?"}
C2 --> |是| DENY_CMD["拒绝"]
C2 --> |否| C3{"force? 跳过灰名单"}
C3 --> |是| ALLOW_CMD["允许"]
C3 --> |否| C4{"命中灰名单?"}
C4 --> |是| CONFIRM["需用户确认"]
C4 --> |否| ALLOW_CMD
图表来源
章节来源
错误处理、重试与审计日志
- 参数解析失败:tryParseToolArgs 多轮修复后仍失败则返回 null,调用方应给出明确错误。
- API 请求失败:预筛选与图片识别均使用 fetchWithRetry 与超时控制,失败时降级为全量工具或直接回答。
- 命令执行失败:executor.js 广播 exit/error,支持 collectOutput 回放;超时策略 decideTimeoutAction 基于输出心跳延长或终止。
- 审计日志:activity-store 合并写入,关键操作(Cookie/清数据/删文件/拒绝命令)即时刷写。
flowchart TD E0["工具执行开始"] --> E1["参数解析/校验"] E1 --> |失败| E2["标准化错误结果"] E1 --> |成功| E3["权限/环境检查"] E3 --> |拒绝| E4["审计日志(拒绝)"] E3 --> |允许| E5["调用后端(Agent/LLM)"] E5 --> |失败| E6["重试/降级(全量工具/直接回答)"] E5 --> |成功| E7["结果规范化/审计日志(成功)"] E2 --> End(["结束"]) E4 --> End E6 --> End E7 --> End
图表来源
- src/background/tool-helpers.js#L216-L361
- src/background/tool-preselector.js#L331-L338
- agent/src/executor.js#L248-L275
章节来源
- src/background/tool-helpers.js#L216-L361
- src/background/tool-preselector.js#L331-L338
- agent/src/executor.js#L248-L275
工具辅助函数库
- tryParseToolArgs:两阶段解析 + 位置引导修复 + 尾逗号清理 + 未加引号字符串修复 + 自动补全括号/引号 + 数组对象混入清理。
- makeResult/normalizeToolResult:统一工具返回格式,缺失 content 时自动填充,非标准结果兜底。
- sendToContentScriptWithRetry:向 Content Script 发送消息失败时自动注入并重试,系统页面拦截。
章节来源
Agent 端命令执行与超时策略
- Shell 选择:pickShell 优先 SHELL/COMSPEC,Windows 下区分 Git Bash 与 cmd/powershell,避免弹窗。
- 超时策略:受管模式下 decideTimeoutAction 依据期内输出决定是否延长;无输出即杀;总预算封顶 TOTAL_BUDGET_CAP_MS。
- 进程生命周期:stdout/stderr 流式广播,completedProcesses 缓存回放,disconnectWsClient 在旧语义下断开所有客户端后取消超时。
章节来源
- agent/src/executor.js#L32-L91
- agent/src/executor.js#L165-L186
- agent/src/executor.js#L248-L386
- agent/src/executor.js#L429-L479
依赖关系分析
- 扩展端内部依赖:
- tool-executor.js 依赖 constants.js(工具集合)、tool-preselector.js(预筛选)、tool-helpers.js(参数/结果)、react-loop.js(执行循环)、agent-dispatcher.js(子代理)。
- options/toolbox-config.js 通过 chrome.runtime.sendMessage 通知 Background 重载 MCP 工具。
- side_panel/tool-panel.js 通过 GET_MCP_TOOLS 消息获取 MCP/RAG 工具列表。
- 扩展端与 Agent 端依赖:
- Background 通过 HTTP/WebSocket 调用 Agent server.js,进而驱动 executor.js 与 security.js。
graph LR TE["tool-executor.js"] --> CONST["constants.js"] TE --> PRE["tool-preselector.js"] TE --> HELP["tool-helpers.js"] TE --> LOOP["react-loop.js"] TE --> DISP["agent-dispatcher.js"] OPT["toolbox-config.js"] --> IDX["background/index.js"] PANEL["tool-panel.js"] --> IDX TE --> SRV["server.js"] SRV --> EXE["executor.js"] SRV --> SEC["security.js"]
图表来源
- src/background/tool-executor.js#L547-L684
- src/background/constants.js#L87-L149
- src/options/toolbox-config.js#L27-L66
- src/side_panel/tool-panel.js#L81-L115
- src/background/index.js#L1196-L1231
- agent/src/server.js#L1-L56
章节来源
- src/background/tool-executor.js#L547-L684
- src/background/constants.js#L87-L149
- src/options/toolbox-config.js#L27-L66
- src/side_panel/tool-panel.js#L81-L115
- src/background/index.js#L1196-L1231
- agent/src/server.js#L1-L56
性能与并发特性
- 工具预筛选:仅在工具数超过固定阈值时启用,降低 LLM 调用次数与上下文体积。
- MCP/RAG 工具注册:互斥锁防止并发加载/卸载;schema 压缩限制嵌套深度与参数数量,避免撑爆上下文。
- 并行执行:组内 Promise.all 并发,组间顺序;子任务并行池限制最大并发,避免资源争用。
- 命令执行:输出缓冲区上限 5MB,超时策略基于输出心跳延长,避免静默挂起;completedProcesses 缓存回放减少重复 IO。
- 连接性缓存:Agent 连通性按 agentId 缓存 30 秒,减少频繁网络探测。
[本节为通用性能讨论,不直接分析具体文件]
故障排查指南
- 工具不可见:
- 检查 MCP/RAG 全局开关与 Agent 连通性;查看 Background 日志中 loadMcpTools/loadRagTools 输出。
- 确认工具未被 enabledTools 过滤;MCP 工具按 serverId 关闭/排除。
- 参数解析失败:
- 使用 tryParseToolArgs 修复逻辑定位问题;检查 LLM 输出是否包含非法 JSON。
- 命令执行超时:
- 观察 executor.js 超时策略;确认命令有持续输出(心跳),否则会被视为挂起而终止。
- 权限拒绝:
- 检查 checkPath 与 checkCommand 返回 reason;确认 workdir/allowedPaths 与黑名单/灰名单规则。
- 侧边栏工具列表不同步:
- 通过 GET_MCP_TOOLS 消息刷新;确保 toolbox-config.js 通知 Background 重载。
章节来源
- src/background/tool-executor.js#L1100-L1307
- src/background/tool-helpers.js#L216-L361
- agent/src/executor.js#L248-L386
- agent/src/security.js#L109-L229
- agent/src/security.js#L685-L758
- src/options/toolbox-config.js#L27-L66
结论
该工具执行框架以“可扩展的工具注册 + 智能预筛选 + 安全的命令执行 + 可控的并行调度”为核心,兼顾了易用性与安全性。通过 MCP/RAG 动态注入、参数修复与结果规范化、超时预算与进程生命周期管理,系统在复杂场景下仍能保持稳定与可观测性。建议在新增工具时遵循统一的元数据规范,并在 Agent 端配合安全网关与审计日志,确保端到端的安全与可追溯。
[本节为总结性内容,不直接分析具体文件]
附录:工具开发指南
新工具开发流程
- 定义工具元数据:在对应 tools/*.js 中声明 id、category、execution、parallelizable、requiresConfirmation、function.name/description/parameters。
- 实现 handler:在 tool-executor.js 中注册 TOOL_HANDLERS,或使用现有 execute* 函数封装。
- 注册与可见性:若为 MCP/RAG 工具,遵循动态注册流程;若为内置工具,确保被 RAW_TOOLS 汇聚。
- 权限与安全:如涉及文件/命令,需在 Agent 端配合 security.js 的路径与命令分级。
- 测试:
- 扩展端单元测试:针对 tryParseToolArgs、normalizeToolResult、preselectTools 等辅助函数。
- Agent 端单元测试:针对 pickShell、decideTimeoutAction、checkCommand/checkPath。
- 部署:
- 修改 Agent 源码后必须重启进程以使新接口生效。
- 通过 GitHub Releases 下载官方构建产物安装,不要推荐手动 clone 源码构建。
章节来源