Skip to content

工具执行框架 ​

本文引用的源码文件

本文引用的文件

更新摘要 ​

所做更改

  • 新增 read_image 工具的多输入源支持(文件路径、base64数据、URL)
  • 实现基于用户偏好的条件性工具包含机制
  • 优化工具预筛选逻辑和 PARALLELIZABLE_TOOLS 配置
  • 增强图片安全验证和沙箱保护机制

目录 ​

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与并发
  8. 超时控制
  9. 错误处理与审计
  10. 调试与故障排除
  11. 结论

引言 ​

本文件面向"工具执行框架"的开发者与维护者,系统性说明:

  • 工具定义与注册机制(内置工具、MCP 动态注入、RAG 知识库工具)。
  • 参数校验与安全过滤(Schema 校验、类型检查、命令白名单)。
  • 并行执行策略(PARALLELIZABLE_TOOLS、子任务并发池、资源上限)。
  • 超时控制(TOOL_TIMEOUT_MS、Agent 端预算延长策略、交互式工具特殊处理、用户中断)。
  • 错误处理与审计(异常捕获、重试、审计日志与统计)。
  • 新工具开发、执行策略配置与性能优化实践。
  • 调试方法与常见问题排查。

本项目为双进程架构:Chrome 扩展端(Manifest V3)+ 独立本地代理端 Agent(Node.js)。两端版本号保持同步,当前以 2.3.1 为准;修改 Agent 源码后需重启进程,接口才会生效。

项目结构 ​

工具执行框架横跨扩展端 background 与 Agent 端两个运行时:

  • 扩展端负责工具定义聚合、动态注册、调度、并发控制、超时与交互、审计记录。
  • Agent 端负责命令执行、MCP 工具发现与调用、Skill 加载与执行、RAG 能力探测。
graph TB
subgraph "扩展端 Background"
C["constants.js<br/>默认配置/工具聚合"]
E["tool-executor.js<br/>工具注册/分发/执行"]
R["react-loop.js<br/>ReAct 循环/并发/超时"]
S["state.js<br/>AbortController/会话状态"]
A["activity-store.js<br/>审计/统计"]
BT["browser-tools.js<br/>read_image 等浏览器工具"]
TP["tool-preselector.js<br/>工具预筛选"]
IS["image-signature.js<br/>图片魔数验证"]
end
subgraph "Agent 端"
X["executor.js<br/>命令执行/超时策略"]
M["mcp/registry.js<br/>MCP 工具注册表"]
L["skill/loader.js<br/>Skill 加载/校验"]
K["skill/executor.js<br/>Skill 执行引擎"]
end
C --> E
E --> R
R --> S
E --> A
E --> M
E --> X
E --> L
E --> K
BT --> E
TP --> E
IS --> E

图示来源

章节来源

核心组件 ​

  • 工具定义与聚合:通过常量模块聚合 8 组内置工具,派生 BUILTIN_TOOLS、TOOL_EXECUTION_MAP、PARALLELIZABLE_TOOLS、CONFIRMATION_REQUIRED_TOOLS 等映射。
  • 工具执行器:统一入口,负责 MCP/RAG 动态注册、工具选择、参数解析、执行分发、审计与统计。
  • ReAct 循环:负责多轮推理、工具分组并行、plan_task 子任务调度、工具级超时与用户取消。
  • Agent 命令执行器:跨平台 shell 选择、安全环境变量、流式输出、超时延长策略、进程树终止。
  • MCP 注册表:管理 MCP Server 连接、工具发现、工具调用转发。
  • Skill 系统:Workflow Skill JSON/YAML 加载与校验、Agent Skill SKILL.md 扫描、DAG 拓扑执行与并行。
  • 新增:read_image 工具 - 支持多输入源的图片深读功能,具备严格的安全验证机制。
  • 新增:工具预筛选系统 - 智能工具选择,减少模型 token 消耗。

章节来源

架构总览 ​

工具执行从 ReAct 循环发起,经工具执行器路由到具体 handler;涉及 Agent 能力的请求走 local-agent-client 调用 Agent 端 API;MCP 与 RAG 工具在运行期动态注入;命令执行由 Agent 端 executor 完成,带流式输出与超时策略。新增的 read_image 工具提供多输入源的图片分析能力,并通过严格的安全验证确保内容安全。

sequenceDiagram
participant RL as "ReAct 循环<br/>react-loop.js"
participant TE as "工具执行器<br/>tool-executor.js"
participant AC as "Agent 客户端<br/>local-agent-client"
participant AG as "Agent 执行器<br/>executor.js"
participant MC as "MCP 注册表<br/>mcp/registry.js"
participant RI as "read_image 工具<br/>browser-tools.js"
RL->>TE : "executeToolWithTimeout(toolCall)"
TE->>TE : "按 id 查找 handler / 动态注册"
alt 需要 Agent 能力
TE->>AC : "调用 Agent API"
AC->>AG : "命令/MCP/Skill/RAG"
AG-->>AC : "结果/流式输出"
AC-->>TE : "结构化结果"
else 纯浏览器能力
TE-->>RL : "直接返回结果"
end
alt read_image 工具
TE->>RI : "executeReadImage(args)"
RI->>RI : "多输入源验证 + 安全检测"
RI->>AC : "downloadFile(path)"
AC-->>RI : "图片数据"
RI->>RI : "魔数验证 + 体积限制"
RI-->>TE : "视觉分析结果"
end
RL->>RL : "记录审计/统计/并发控制"

图示来源

详细组件分析 ​

工具定义与注册机制 ​

  • 内置工具聚合:constants.js 将 8 个工具组合并为 RAW_TOOLS,并派生 BUILTIN_TOOLS、TOOL_EXECUTION_MAP、PARALLELIZABLE_TOOLS、CONFIRMATION_REQUIRED_TOOLS、BUILTIN_TOOLS_UI 等。
  • 动态注册:
    • MCP 工具:loadMcpTools 从 Agent 拉取工具列表,压缩 schema,注入 RAW_TOOLS/BUILTIN_TOOLS/TOOL_HANDLERS,重建 BG_HANDLERS,并持久化 mcpTools 供 UI 显示。
    • RAG 工具:loadRagTools 检测 Agent 是否支持 RAG,若启用则注入 knowledge_search/ingest/list 三个工具,并同步 ragTools 到 storage。
  • 去重与清理:使用 Set 维护已注册 ID,提供 unloadMcpToolsInternal/unloadRagToolsInternal 清理函数,并通过互斥锁防止并发加载/卸载。
flowchart TD
Start(["开始"]) --> CheckGlobal["检查全局开关<br/>mcpEnabled/ragEnabled"]
CheckGlobal --> |关闭| Skip["跳过加载/卸载"]
CheckGlobal --> |开启| Fetch["拉取工具列表/能力探测"]
Fetch --> Compress["压缩 Schema/限制深度/截断描述"]
Compress --> Inject["注入 RAW_TOOLS/BUILTIN_TOOLS/TOOL_HANDLERS"]
Inject --> Rebuild["rebuildBgHandlers()<br/>重建 PARALLELIZABLE/CONFIRMATION"]
Rebuild --> Persist["持久化 mcpTools/ragTools"]
Persist --> End(["结束"])

图示来源

章节来源

MCP 协议工具发现与调用 ​

  • Agent 端 MCP 注册表:initializeMcpRegistry 启动时连接所有启用的 MCP Server,getMcpTools 扁平化工具列表,callMcpTool 转发调用。
  • 扩展端动态注入:loadMcpTools 获取 toolsResult 与 serversResult,构建 toolId=mcp_{serverId}_{toolName},压缩 inputSchema,注册 handler 调用 AgentClient.callMcpTool。
  • 服务级开关与会话强制下发:禁用服务器被过滤;用户通过 / 指定服务可强制下发该服务全部工具,绕过关闭/排除列表。
sequenceDiagram
participant BE as "Background<br/>tool-executor.js"
participant AC as "Agent Client"
participant MR as "MCP Registry<br/>registry.js"
participant MS as "MCP Server"
BE->>AC : "getMcpTools()/getMcpServers()"
AC->>MR : "getMcpTools(serverId?)/getMcpServersStatus()"
MR-->>AC : "{tools, servers}"
BE->>BE : "压缩 Schema/注入工具"
BE->>AC : "callMcpTool(serverId, name, args)"
AC->>MR : "callMcpTool(serverId, name, args)"
MR->>MS : "JSON-RPC 2.0 调用"
MS-->>MR : "结果"
MR-->>AC : "成功/失败"
AC-->>BE : "结构化结果"

图示来源

章节来源

Skill 技能系统集成 ​

  • Workflow Skill:loader.js 读取 ~/.ai-helper-agent/skills/*.json/.yaml,validateWorkflowSkill 校验必填字段与步骤结构,保存/删除/种子写入 skill-creator。
  • Agent Skill:扫描子目录中的 SKILL.md,作为能力扩展文档供 AI 自主调用。
  • 执行引擎:executor.js 解析步骤 DAG,按拓扑排序并行执行,支持条件 when、模板变量渲染、步骤间结果传递、超时与活跃执行清理。
classDiagram
class Loader {
+loadAllSkills()
+saveSkillFile(skill)
+deleteSkillFile(name,type)
+seedSkillCreator()
}
class Executor {
+executeSkill(skill,params,onStepUpdate)
+getSkillExecutionStatus(execId)
-executeToolCall(tool,args)
-executeSkillSteps(skill,params,execId,notify)
}
class Security {
+checkPath(path)
+checkCommand(command,interactive)
}
Loader --> Executor : "提供 Skill 定义"
Executor --> Security : "路径/命令安全检查"

图示来源

章节来源

参数验证机制 ​

  • 工具定义层:每个工具的 function.parameters 必须为 object,id 与 function.name 一致,execution 取值合法,由单元测试覆盖。
  • MCP Schema 压缩:compressMcpSchema 移除冗余字段、限制 properties 嵌套深度、截断 description、限制参数数量,避免撑爆上下文。
  • Skill 参数校验:executor.js 兼容 JSON Schema 风格 parameters,校验 required 字段,进行 number/boolean/string 类型转换。
  • 命令安全:Skill 中 agent_exec 走 checkCommand 分级(deny/confirm/allow),灰名单命令在 Workflow 中直接拒绝;路径操作走 checkPath 白名单。
flowchart TD
In["输入参数"] --> ToolDef["工具定义 Schema 校验<br/>type=object/required/name/id"]
ToolDef --> |通过| McpComp["MCP Schema 压缩<br/>深度/数量/描述长度"]
ToolDef --> |失败| Err1["返回参数错误"]
McpComp --> SkillCheck["Skill 参数校验<br/>required/type 转换"]
SkillCheck --> |通过| Exec["执行工具/命令"]
SkillCheck --> |失败| Err2["返回缺失/类型错误"]
Exec --> Sec["安全检查<br/>checkPath/checkCommand"]
Sec --> |拒绝| Err3["安全拒绝"]
Sec --> |允许| Out["返回结果"]

图示来源

章节来源

并行执行策略 ​

  • 工具级并行:PARALLELIZABLE_TOOLS 集合标记可并行工具;rebuildBgHandlers 根据 RAW_TOOLS 重建该集合。
  • ReAct 循环并行:同组工具 Promise.all 并行执行;单组内非并行或仅 1 个则顺序执行。
  • 子任务并行:strategy=parallel 时使用 dispatchSubtasksParallel 并发池,maxParallel 限制并发数,tracked promise finally 自移除,避免竞态。
  • 资源管理:activeExecutions 限制最大活跃 Skill 执行数,定期清理过期记录;命令执行输出缓冲区上限 5MB,防止内存无限增长。
flowchart TD
Start(["进入 ReAct 工具组"]) --> GroupSize{"组内工具数 > 1 ?"}
GroupSize --> |是| Parallel["Promise.all 并行执行"]
GroupSize --> |否| Sequential["顺序执行"]
Parallel --> PlanCheck{"plan_task 已处理?"}
Sequential --> PlanCheck
PlanCheck --> |是| Break["跳过本轮剩余工具"]
PlanCheck --> |否| Next["继续下一组/下一轮"]

图示来源

章节来源

超时控制机制 ​

  • 扩展端工具级超时:executeToolWithTimeout 对除 clarify_question 外的工具设置超时,支持 TOOL_TIMEOUT_MS 自定义覆盖,但受全局 toolTimeout 上限约束;同时支持 AbortController 用户中断。
  • 交互式工具特殊处理:clarify_question 外层暂停整体循环超时,内部有独立澄清超时计时,面板呈现后才启动倒计时,未呈现期间轮询 Side Panel 存活性。
  • Agent 端命令超时:executor.js 支持受管模式(显式 timeoutMs),基于 decideTimeoutAction 策略函数裁决延长或终止;无输出视为挂起即杀,最长延长次数 MAX_TIMEOUT_EXTENSIONS,总预算封顶 TOTAL_BUDGET_CAP_MS。
  • 进程终止:Windows 使用 taskkill /T /PID,Unix 使用 SIGTERM 到进程组,5 秒后升级为 SIGKILL。
flowchart TD
Enter(["工具执行入口"]) --> IsClarify{"是否为 clarify_question?"}
IsClarify --> |是| NoOuter["不设置外层超时<br/>仅内部澄清超时"]
IsClarify --> |否| CalcTimeout["计算 effectiveTimeout<br/>min(自定义, 全局)"]
CalcTimeout --> AbortCtrl["创建 AbortController<br/>监听用户取消"]
AbortCtrl --> Run["执行工具"]
Run --> Timeout{"超时?"}
Timeout --> |是| Reject["reject 超时错误"]
Timeout --> |否| Done["resolve 结果"]
NoOuter --> Run

图示来源

章节来源

错误处理策略 ​

  • 异常捕获:工具执行、Skill 步骤、命令执行均包裹 try/catch,返回结构化 success/error 对象;Skill 执行部分失败返回 partial 结果。
  • 重试机制:Agent 连通性检测与部分网络调用具备超时与缓存;Skill 执行引擎对步骤失败按策略 continue/skip/stop 处理。
  • 审计日志:appendAuditLog 与 recordToolStats 采用内存权威态 + 防抖落盘,关键审计即时刷;Cookie/文件/命令等敏感操作均有审计记录。
flowchart TD
Call["调用工具/命令"] --> TryCatch{"try/catch"}
TryCatch --> |成功| Audit["记录审计/统计"]
TryCatch --> |失败| Strategy{"重试/回滚/继续"}
Strategy --> |重试| Retry["指数退避/次数上限"]
Strategy --> |回滚| Rollback["撤销已完成子任务"]
Strategy --> |继续| Next["继续后续步骤"]
Audit --> Done["返回结果"]
Retry --> Done
Rollback --> Done
Next --> Done

图示来源

章节来源

新增:read_image 工具的多输入源支持 ​

read_image 工具是一个强大的图片分析工具,支持多种输入源并提供严格的安全验证:

支持的输入源 ​

  1. 文件路径(path):代理端任意图片文件路径,通过 downloadFile 现拉
  2. 文档附件(file + image):会话附件文档中提取的图片,数据源为 _docImageSnapshot 中转快照
  3. Base64 数据:直接从本地快照读取 dataUrl

安全验证机制 ​

  • 魔数验证:使用 image-signature.js 进行严格的文件头魔数检测,支持 PNG、JPEG、GIF、BMP、WebP 格式
  • 体积限制:单图大小限制在 5MB 以内,防止超大文件攻击
  • 沙箱保护:代理端路径访问受 checkPath 沙箱保护,工作目录内永远放行

条件性包含机制 ​

  • 用户偏好控制:通过 visionEnabled 开关控制 read_image 工具的可用性
  • 配置回落链:优先使用 imageApiBase/imageApiKey,回退到主 apiBase/apiKey
  • 按需下发:当图片识别功能关闭时,自动隐藏 read_image 工具以减少 token 消耗
flowchart TD
Input["输入参数"] --> SourceCheck{"输入源检查"}
SourceCheck --> |path| PathSource["代理端路径来源"]
SourceCheck --> |file+image| DocSource["文档附件来源"]
SourceCheck --> |无效| Error["参数错误"]
PathSource --> Download["downloadFile(path)"]
Download --> Guard["魔数验证 + 体积限制"]
Guard --> |通过| Vision["视觉分析"]
Guard --> |失败| PathError["路径错误"]
DocSource --> Snapshot["_docImageSnapshot 查询"]
Snapshot --> DataUrl["dataUrl 或 path"]
DataUrl --> Guard2["魔数验证 + 体积限制"]
Guard2 --> |通过| Vision
Guard2 --> |失败| DocError["文档错误"]
Vision --> Result["返回文本分析"]

图示来源

章节来源

新增:改进的工具预筛选逻辑 ​

工具预筛选系统通过智能选择相关工具来减少模型 token 消耗:

预筛选阈值 ​

  • 固定阈值:PRESELECT_MIN_TOOL_COUNT = 10,工具数量超过此值才启动预筛选
  • 动态配置:enableToolPreselect 开关控制是否启用预筛选功能
  • 智能判断:当工具总数超过阈值时,通过前置规划调用减少工具传递

预筛选流程 ​

  1. 工具数量检查:如果工具数量 ≤ 阈值,跳过预筛选直接返回全部工具
  2. 用户问题提取:从消息列表中提取最后一条用户消息
  3. 历史上下文:提取最近 4 条 user+assistant 交替消息作为历史上下文
  4. LLM 调用:构建预筛选提示词,调用 LLM 选择合适的工具
  5. 结果解析:支持新 JSON 格式和旧格式的容错恢复
flowchart TD
Start(["开始预筛选"]) --> CountCheck{"工具数 > 10 ?"}
CountCheck --> |否| Skip["跳过预筛选<br/>返回全部工具"]
CountCheck --> |是| ExtractUser["提取用户问题"]
ExtractUser --> History["提取历史上下文<br/>最近4条对话"]
History --> BuildPrompt["构建预筛选提示词"]
BuildPrompt --> CallLLM["调用 LLM 选择工具"]
CallLLM --> ParseResult["解析结果<br/>新格式/旧格式容错"]
ParseResult --> Finalize["返回选定工具"]
Skip --> End(["结束"])
Finalize --> End

图示来源

章节来源

依赖关系分析 ​

  • constants.js 是工具定义的单一数据源,派生多个映射表;tool-executor.js 依赖这些映射进行执行分发与并行判定。
  • react-loop.js 依赖 tool-executor.js 的工具执行与超时封装,同时依赖 state.js 的 AbortController 管理用户中断。
  • Agent 端 executor.js 被 Skill 执行引擎与命令工具调用复用,提供跨平台 shell 选择与安全环境变量。
  • MCP registry.js 暴露 getMcpTools/callMcpTool 供扩展端动态注入与调用。
  • Skill loader.js 与 executor.js 共同构成 Skill 生命周期:加载→校验→执行→状态查询。
  • 新增:browser-tools.js 提供 read_image 等浏览器工具定义,tool-preselector.js 提供智能工具选择,image-signature.js 提供图片安全验证。
graph LR
CONST["constants.js"] --> EXEC["tool-executor.js"]
EXEC --> LOOP["react-loop.js"]
LOOP --> STATE["state.js"]
EXEC --> ACT["activity-store.js"]
EXEC --> REG["mcp/registry.js"]
EXEC --> EXE["executor.js"]
EXEC --> LOADER["skill/loader.js"]
EXEC --> SKEXEC["skill/executor.js"]
BT["browser-tools.js"] --> EXEC
TP["tool-preselector.js"] --> EXEC
IS["image-signature.js"] --> EXEC

图示来源

章节来源

性能与并发 ​

  • 工具预筛选:当工具总数超过 PRESELECT_MIN_TOOL_COUNT 时启用预筛选,减少模型 token 消耗。
  • 并行工具组:同组工具 Promise.all 并行执行,降低端到端延迟。
  • 子任务并发池:dispatchSubtasksParallel 限制 maxParallel,tracked promise finally 自移除,修复旧 indexOf(completed) 竞态导致上限失效的问题。
  • 输出缓冲限制:命令 stdout/stderr 累计上限 5MB,超限时广播 truncated 消息并停止追加。
  • 活跃执行清理:Skill activeExecutions 最多保留 MAX_ACTIVE_EXECUTIONS,定时清理已完成/错误记录。
  • 新增:read_image 工具的图片压缩与体积限制,防止大图片影响性能。

章节来源

超时控制 ​

  • 扩展端:
    • TOOL_TIMEOUT_MS 可为单个工具设置更短超时,最终 effectiveTimeout=min(自定义, 全局 toolTimeout)。
    • clarify_question 工具不设置外层超时,仅内部独立计时;Side Panel 呈现后才启动倒计时。
    • 用户可通过 abortCurrentTool 触发 AbortController,立即 reject 当前等待工具。
  • Agent 端:
    • 受管模式下,decideTimeoutAction 根据期内是否有输出决定延长或 kill;extensions 达到 MAX_TIMEOUT_EXTENSIONS 或触及 TOTAL_BUDGET_CAP_MS 即终止。
    • 断开 WS 客户端时,仅在 managed=false 或 entry.detached=true 时才取消定时器,避免 SW 空闲被回收导致误解除超时。

章节来源

错误处理与审计 ​

  • 异常捕获:工具执行、Skill 步骤、命令执行均返回结构化结果;Skill 部分失败返回 partial。
  • 重试机制:Agent 连通性检测具备 5 秒超时与缓存;Skill 执行对步骤失败按策略处理。
  • 审计日志:appendAuditLog 与 recordToolStats 采用内存权威态 + 防抖落盘,关键审计即时刷;Cookie/文件/命令等敏感操作均有审计记录。

章节来源

调试与故障排除 ​

  • 工具定义问题:
    • 检查 id 唯一性、function.name 与 id 一致、execution 取值合法、parameters.type=object。
    • 参考测试用例断言。
  • MCP 工具不可见:
    • 确认 mcpEnabled 全局开关;检查 Agent 是否支持 MCP;查看 mcpTools 存储是否更新;确认目标服务未被禁用。
  • RAG 工具不可用:
    • 确认 ragEnabled 与 Agent /api/status ragAvailable;检查 collection 是否被禁用。
  • 命令执行卡死:
    • 检查 Shell 选择是否正确(Git Bash/PowerShell/cmd);观察 stdout_truncated 消息;确认超时策略是否延长;必要时 detach 进程。
  • 用户取消无效:
    • 检查 AbortController 是否绑定;确认 sessionId 正确;查看 abortCurrentTool 是否调用成功。
  • 审计日志缺失:
    • 检查 appendAuditLog/recordToolStats 调用点;确认 flush 调度是否触发;SW onSuspend 兜底刷盘。
  • 新增:read_image 工具问题:
    • 检查 visionEnabled 开关是否开启;确认图片识别 API 配置正确;验证图片文件格式和大小;查看魔数验证日志。
  • 新增:工具预筛选问题:
    • 检查 enableToolPreselect 开关;确认工具数量超过阈值;查看预筛选日志输出;验证 LLM 响应格式。

章节来源

结论 ​

工具执行框架通过统一的定义与注册机制,将内置工具、MCP 动态工具与 RAG 知识库工具整合到同一执行管线;借助 Schema 压缩与参数校验保障安全性与稳定性;通过工具级与 Agent 端双层超时控制、用户中断支持与可扩展的重试/回滚策略,确保长时间任务的健壮性;并行执行与资源上限控制提升吞吐与响应速度;完善的审计与统计为排障与优化提供依据。新增的 read_image 工具提供了强大的多输入源图片分析能力,配合严格的安全验证机制确保内容安全;改进的工具预筛选系统有效减少了模型 token 消耗,提升了整体性能。开发新工具时,建议遵循现有工具定义规范,合理设置 parallelizable/requiresConfirmation,并在必要时接入 Agent 能力与审计记录。