主题
工具调度与执行系统
本文引用的源码文件
本文引用的文件
更新摘要
变更内容
- 新增“畸形 JSON 信封容错处理”章节,详细说明预筛选器对 AI 模型返回的 {type,data} 信封的增强错误处理机制
- 更新“参数验证与执行路由”章节,补充 answer 信封容错恢复逻辑
- 完善“错误处理与审计日志”章节,增加内部协议数据防护说明
- 更新相关流程图和架构图,反映新的错误处理路径
目录
引言
本文件面向"工具调度与执行系统",覆盖扩展端(Chrome MV3 background)与 Agent 端(Node.js 本地代理)之间的工具发现、注册、预筛选、路由、执行、权限控制、互斥锁、并行优化、生命周期管理、错误处理与审计日志。文档以版本 2.3.1 为基准,强调两端通信契约、SW 生命周期约束、Agent 进程重启后接口生效等运行时前提。
最新更新:增强了工具预筛选系统的 JSON 信封错误处理能力,防止 AI 模型返回的畸形内部协议数据泄露到用户界面。
项目结构
系统由两部分组成:
- 扩展端 background:负责 ReAct 循环、工具定义聚合、MCP/RAG 动态注册、工具预筛选、执行路由、确认与澄清交互、定时任务编排。
- Agent 端 server:提供 HTTP + WebSocket 服务,承载命令执行、文件操作、搜索、RAG、MCP 工具注册与调用、Skill 注册与执行、安全沙箱与审计。
graph TB subgraph "扩展端 Background" S["scheduler.js<br/>定时任务编排"] T["tool-executor.js<br/>工具注册/执行/MCP/RAG"] P["tool-preselector.js<br/>工具预筛选"] R["react-loop.js<br/>ReAct 推理循环"] C["constants.js<br/>内置工具/分类/开关"] A["activity-store.js<br/>审计与统计"] end subgraph "Agent 端 Server" SV["server.js<br/>HTTP+WS 路由/认证/CORS"] EX["executor.js<br/>命令执行/超时策略"] SEC["security.js<br/>路径/命令安全"] MCP["mcp/registry.js<br/>MCP 工具注册表"] SK["skill/registry.js<br/>Skill 注册表"] end S --> R R --> T R --> P T --> |HTTP/WS| SV SV --> EX SV --> SEC SV --> MCP SV --> SK
图表来源
- src/background/scheduler.js#L1-L120
- src/background/tool-executor.js#L448-L778
- src/background/tool-preselector.js#L273-L432
- src/background/react-loop.js#L1-L120
- agent/src/server.js#L388-L548
- agent/src/executor.js#L165-L275
- agent/src/security.js#L109-L200
- agent/src/mcp/registry.js#L26-L108
- agent/src/skill/registry.js#L134-L189
章节来源
核心组件
- 工具定义与执行器:集中维护 RAW_TOOLS、BUILTIN_TOOLS、TOOL_EXECUTION_MAP、PARALLELIZABLE_TOOLS、CONFIRMATION_REQUIRED_TOOLS,并实现 MCP/RAG 工具的动态注入与清理。
- 工具预筛选:在工具数量超过阈值时,通过一次轻量 LLM 调用判断是否需要工具及具体工具集合,支持直接回答模式。新增:增强的 JSON 信封错误处理和内部协议数据防护。
- ReAct 推理循环:统一协调消息流、工具调用、子任务规划、并行执行、超时与中断、完成度校验与反思。
- 定时任务调度:基于 chrome.alarms 的 cron/间隔/一次性任务,复用会话、选择模型与工具集、网页上下文注入。
- Agent 服务端:HTTP 路由、CORS 白名单、认证鉴权、命令执行、文件上传、状态与健康检查。
- 命令执行器:跨平台 shell 选择、输出缓冲限制、WebSocket 流式输出、超时预算与延长策略、进程组终止。
- MCP/Skill 注册表:启动连接 MCP Server、扁平化工具列表、按服务启用状态过滤;Skill 扫描、加载、启用状态持久化。
- 安全模块:路径规范化、硬阻止目录、白名单前缀匹配、符号链接 realpath 校验、工作目录放行。
- 审计与统计:内存权威态、防抖落盘、关键审计即时刷、工具使用统计聚合。
章节来源
- src/background/constants.js#L87-L171
- src/background/tool-executor.js#L448-L778
- src/background/tool-preselector.js#L273-L432
- src/background/react-loop.js#L1-L120
- src/background/scheduler.js#L279-L433
- agent/src/server.js#L388-L548
- agent/src/executor.js#L165-L275
- agent/src/security.js#L109-L200
- src/background/activity-store.js#L1-L123
架构总览
下图展示从用户意图到工具执行的端到端流程,包括预筛选、ReAct 循环、工具路由、Agent 命令执行与安全校验。
sequenceDiagram
participant User as "用户"
participant SW as "Background (SW)"
participant RL as "ReAct 循环"
participant PS as "工具预筛选"
participant TE as "工具执行器"
participant AG as "Agent Server"
participant EX as "命令执行器"
participant SEC as "安全模块"
User->>SW : 发送对话/定时任务
SW->>RL : 构建 messages / model / tools
RL->>PS : preselectTools(messages, tools)
alt 工具数 <= 阈值或 API 失败
PS-->>RL : 返回全部工具或直接回答
else 工具数 > 阈值
PS->>AG : 轻量 LLM 请求(预筛选)
AG-->>PS : JSON {type : "tools"/"answer"}
PS->>PS : JSON 信封解析与容错处理
PS-->>RL : 返回选定工具或答案
end
RL->>TE : executeTool(toolId, args)
TE->>AG : HTTP/WS 调用(含认证/CORS)
AG->>SEC : checkPath/checkCommand
SEC-->>AG : 允许/拒绝
AG->>EX : spawn(shell, command)
EX-->>AG : stdout/stderr/exit
AG-->>TE : 结果
TE-->>RL : 工具结果/审计/统计
RL-->>SW : 最终内容/executionLog
图表来源
- src/background/tool-preselector.js#L273-L432
- src/background/react-loop.js#L1-L120
- src/background/tool-executor.js#L448-L778
- agent/src/server.js#L388-L548
- agent/src/security.js#L109-L200
- agent/src/executor.js#L165-L275
详细组件分析
工具定义与注册机制
- 内置工具:常量文件中聚合浏览器、标签页、存储、媒体、AI、Agent、记忆、调试等工具,派生 BUILTIN_TOOLS、分类映射、执行位置映射、可并行集合、需确认集合。
- MCP 工具:扩展端通过 loadMcpTools 拉取 Agent 端已连接 MCP Server 的工具列表,压缩 schema,去重注入 RAW_TOOLS/BUILTIN_TOOLS,重建 BG_HANDLERS,并暴露 mcpToolIds 与 mcpToolMetaMap 用于服务级开关与强制下发。
- RAG 工具:知识库检索与导入工具在 tool-executor 中动态注册,包含停用库提示、参数校验、禁用库消息生成。
- 生命周期:loadMcpTools/unloadMcpTools 使用互斥锁防止并发;rebuildBgHandlers 同步更新 PARALLELIZABLE_TOOLS 与 CONFIRMATION_REQUIRED_TOOLS。
flowchart TD Start(["开始"]) --> CheckGlobal["检查全局 MCP 开关"] CheckGlobal --> |关闭| ReturnZero["返回 0"] CheckGlobal --> |开启| CleanPrev["清理上次注册的 MCP 工具"] CleanPrev --> FetchAll["并行获取工具列表与服务状态"] FetchAll --> FilterDisabled["过滤已禁用服务器"] FilterDisabled --> BuildDefs["构造 rawToolDef 并压缩 schema"] BuildDefs --> Inject["注入 RAW_TOOLS/BUILTIN_TOOLS/TOOL_EXECUTION_MAP"] Inject --> Handlers["注册 TOOL_HANDLERS 并重建 BG_HANDLERS"] Handlers --> Persist["持久化 mcpTools 供 UI 显示"] Persist --> End(["结束"])
图表来源
章节来源
- src/background/constants.js#L87-L149
- src/background/tool-executor.js#L448-L778
- agent/src/mcp/registry.js#L26-L108
参数验证与执行路由
- 参数解析:工具参数在 react-loop 侧进行防御性解析(string/object),tool-helpers 提供 tryParseToolArgs。
- 路由分发:根据 TOOL_EXECUTION_MAP 决定 background 或 agent 执行;background 工具走 BG_HANDLERS,agent 工具经 local-agent-client 转发。
- 确认与澄清:requiresConfirmation 工具进入确认流程;plan_task 触发子任务规划,必要时暂停本轮其他工具调用。
- 网络访问控制:内网地址访问受 networkAccessEnabled 与 allowedNetworkHosts 控制,拒绝未授权主机。
flowchart TD
Entry(["executeTool 入口"]) --> ParseArgs["解析 tool_call.arguments"]
ParseArgs --> RouteCheck{"execution 类型?"}
RouteCheck --> |background| BGHandler["BG_HANDLERS[toolId]"]
RouteCheck --> |agent| AgentClient["local-agent-client 转发"]
BGHandler --> ConfirmCheck{"requiresConfirmation?"}
ConfirmCheck --> |是| ConfirmFlow["requestToolConfirmation/hasLoopApproval"]
ConfirmCheck --> |否| ExecBG["执行 background 工具"]
AgentClient --> NetGate["decideNetworkAccess 内网白名单"]
NetGate --> ExecAgent["执行 Agent 能力(文件/命令/搜索/RAG)"]
ConfirmFlow --> ExecBG
ExecBG --> Audit["appendAuditLog/recordToolStats"]
ExecAgent --> Audit
Audit --> Result(["返回 {success,content,tool_call_id}"])
图表来源
- src/background/react-loop.js#L242-L250
- src/background/constants.js#L132-L149
- src/background/tool-executor.js#L448-L778
章节来源
- src/background/react-loop.js#L242-L250
- src/background/constants.js#L132-L149
- src/background/tool-executor.js#L448-L778
工具预筛选算法与 JSON 信封容错处理
- 触发条件:当工具总数超过 PRESELECT_MIN_TOOL_COUNT(默认 10)时启用。
- 输入:messages、model、tools、apiParams、callCount、mustKeepToolIds。
- 过程:
- 提取最后一条 user 消息作为问题,截取最近 4 条 user/assistant 历史。
- 构建系统提示词,列出工具名、前 3 个参数名与描述。
- 调用 LLM 返回 JSON {type:"answer"/"tools", data:...}。
- 新增:JSON 信封解析与容错处理:
- 优先尝试标准 JSON.parse 解析新格式
- 解析失败时尝试 recoverAnswerEnvelopeData 容错恢复 answer 信封
- 检测 looksLikePreselectEnvelope 识别畸形内部协议信封
- 对畸形信封进行安全防护,不向用户暴露内部协议数据
- 若 type=answer,直接返回答案;若 tools 为空则回退全部工具。
- 大小写不敏感匹配工具名,追加原型工具(proto_)与强制保留工具(/ 指定 MCP 服务)。
- 异常处理:API 失败、JSON 解析失败均回退全部工具,记录 executionLog。
更新 新增了三层 JSON 信封错误处理机制:
flowchart TD
Start(["preselectTools"]) --> Threshold{"工具数 <= 阈值?"}
Threshold --> |是| Skip["跳过预筛选,返回全部工具"]
Threshold --> |否| Extract["提取最后 user 消息与历史"]
Extract --> Prompt["构建预筛选提示词"]
Prompt --> CallLLM["调用 LLM(response_format=json_object)"]
CallLLM --> Parse["parsePreselectResponse 解析"]
Parse --> TryJSON["尝试 JSON.parse 新格式"]
TryJSON --> |成功| TypeCheck{"type 字段检查"}
TypeCheck --> |answer| DirectAnswer["直接返回答案"]
TypeCheck --> |tools| Match["大小写不敏感匹配工具名"]
TryJSON --> |失败| Recover["recoverAnswerEnvelopeData 容错恢复"]
Recover --> |成功| DirectAnswer
Recover --> |失败| OldFormat["extractToolListFromResponse 旧格式"]
OldFormat --> |成功| Match
OldFormat --> |失败| EnvelopeCheck["looksLikePreselectEnvelope 检测"]
EnvelopeCheck --> |是| Malformed["标记为畸形信封,回退全量工具"]
EnvelopeCheck --> |否| PureText["当作纯文本回答"]
Match --> FallbackProto{"是否包含 proto_ ?"}
FallbackProto --> |是| AddProto["追加 preview_ui 工具"]
FallbackProto --> |否| KeepForced{"是否有 mustKeepToolIds ?"}
AddProto --> KeepForced
KeepForced --> |有| MergeForced["合并强制保留工具"]
KeepForced --> |无| Finalize["返回选定工具"]
MergeForced --> Finalize
CallLLM --> |失败| FallbackAll["回退全部工具"]
图表来源
章节来源
- src/background/tool-preselector.js#L273-L432
- src/background/tool-preselector.js#L118-L187
- src/background/constants.js#L24-L26
并行执行优化与互斥锁
- 并行工具集合:PARALLELIZABLE_TOOLS 由 RAW_TOOLS 自动派生,MCP 工具默认 parallelizable=true。
- 互斥锁:MCP/RAG 工具加载使用 Promise 互斥锁,防止 load/unload 并发;rebuildBgHandlers 确保集合一致性。
- 并发控制:ReAct 循环对 plan_task 的子任务支持 sequential/parallel/dependency 策略,配合 loop-detector 检测重复无效操作、振荡、无进展滚动等。
classDiagram
class ToolExecutor {
+loadMcpTools()
+unloadMcpTools()
+mergeForcedMcpTools(selectedTools, fullTools, serverIds)
-mcpLoadLock
-mcpToolIds
-mcpToolMetaMap
+rebuildBgHandlers()
}
class Constants {
+RAW_TOOLS
+PARALLELIZABLE_TOOLS
+CONFIRMATION_REQUIRED_TOOLS
}
class ReactLoop {
+executeTool()
+handleSubtasks()
-loopDetector
}
ToolExecutor --> Constants : "读取/派生"
ReactLoop --> ToolExecutor : "调用/路由"
图表来源
- src/background/tool-executor.js#L551-L778
- src/background/constants.js#L132-L149
- src/background/react-loop.js#L1-L120
章节来源
- src/background/tool-executor.js#L551-L778
- src/background/constants.js#L132-L149
- src/background/react-loop.js#L1-L120
工具生命周期管理
- 启动阶段:
- 扩展端:constants 聚合内置工具;tool-executor 初始化 MCP/RAG 动态注册。
- Agent 端:server 启动 HTTP/WS,初始化 MCP/Skill 注册表,检测 RAG 可用性。
- 运行阶段:
- MCP 工具按需拉取,按服务器启用状态过滤;RAG 工具随知识库启用状态变化。
- Skill 注册表扫描文件系统与内置技能,恢复启用状态。
- 关闭阶段:
- MCP 注册表断开所有连接;Skill 注册表停止周期任务;Activity Store 尽力刷盘。
stateDiagram-v2 [*] --> Initialized Initialized --> MCPConnected : "initializeMcpRegistry()" Initialized --> SkillsLoaded : "initializeSkillRegistry()" MCPConnected --> Running : "getMcpTools()/callMcpTool()" SkillsLoaded --> Running : "getSkillList()/runSkill()" Running --> Shutdown : "shutdownMcpRegistry()/stopPeriodicCleanup()" Shutdown --> [*]
图表来源
- agent/src/mcp/registry.js#L26-L108
- agent/src/skill/registry.js#L134-L189
- agent/src/server.js#L388-L548
章节来源
- agent/src/mcp/registry.js#L26-L108
- agent/src/skill/registry.js#L134-L189
- agent/src/server.js#L388-L548
错误处理与审计日志
- 错误处理:
- 预筛选 API 失败回退全部工具;MCP 拉取失败记录警告;命令执行超时/退出码错误上报。
- 新增:畸形 JSON 信封防护:检测到 {type,data} 格式的畸形信封时,不会将内部协议数据透传给用户界面,而是记录警告并回退到全量工具模式。
- ReAct 循环检测无限循环、重复无效操作、振荡、无进展滚动,暂停任务并提示补充指导。
- 审计日志:
- appendAuditLog 追加敏感操作审计,关键操作即时落盘,普通操作防抖合并。
- recordToolStats 累加工具调用次数、成功次数、总时长、最近使用时间。
更新 增强了错误处理的层次性和安全性:
flowchart TD
Op["工具执行"] --> Audit["appendAuditLog(category,action,details)"]
Audit --> Urgent{"是否关键审计?"}
Urgent --> |是| FlushNow["立即 flushActivityStoreNow()"]
Urgent --> |否| Debounce["scheduleFlush() 防抖落盘"]
Op --> Stats["recordToolStats(toolName,result,duration)"]
Stats --> Debounce
JsonError["JSON 信封解析失败"] --> EnvelopeCheck["looksLikePreselectEnvelope 检测"]
EnvelopeCheck --> |是| InternalProtocol["标记为内部协议,安全防护"]
EnvelopeCheck --> |否| PureText["视为纯文本"]
InternalProtocol --> Fallback["回退全量工具,记录警告"]
图表来源
- src/background/activity-store.js#L46-L123
- src/background/tool-preselector.js#L342-L432
- src/background/tool-preselector.js#L473-L481
- src/background/react-loop.js#L46-L98
章节来源
- src/background/activity-store.js#L46-L123
- src/background/tool-preselector.js#L342-L432
- src/background/tool-preselector.js#L473-L481
- src/background/react-loop.js#L46-L98
定时任务调度与执行
- 闹钟注册:基于 chrome.alarms,支持 interval/cron/once,启动时重建缺失报警,清理孤儿报警。
- 执行编排:解析宿主会话、选择模型与工具集、可选网页上下文、构建 systemPrompt 与 userMessage、调用 reactLoop 或 callApiNonStream。
- 结果写入:追加用户消息与助手消息,记录 executionLog,通知侧边栏刷新会话与任务状态。
sequenceDiagram
participant Alarm as "chrome.alarms"
participant Sched as "scheduler.runTask"
participant Session as "会话管理"
participant RL as "ReAct 循环"
participant DB as "IndexedDB"
Alarm->>Sched : onAlarm(taskId)
Sched->>Session : resolveHostSession(task)
Sched->>Sched : pick model/tools/temperature/topP
Sched->>Sched : extractPageContext(url)
Sched->>RL : reactLoop(messages,model,tools,...)
RL-->>Sched : result{content,executionLog}
Sched->>DB : appendRunMessages(sessionId,task,content,log,pageMeta)
Sched-->>Alarm : schedule next run
图表来源
章节来源
依赖关系分析
- 扩展端内部依赖:
- scheduler 依赖 tool-executor、react-loop、storage/db、notifier、i18n。
- tool-executor 依赖 constants、local-agent-client、stream-controller、activity-store、network-scope、tool-memory、tool-debugger、snapshot-orchestrator、notifier、react-loop。
- tool-preselector 依赖 config、constants、token-counter、i18n。
- react-loop 依赖 state、config、constants、token-counter、stream-controller、db、logger、i18n、untrusted-content、notifier、loop-detector、local-agent-client、subagent-depth、sw-heartbeat、auto-resume、trim-fallback、completion-verifier。
- Agent 端内部依赖:
- server 依赖 auth、security、executor、trash、search、rag/detect、memory/routes、process-tree、mcp/registry、skill/registry、i18n。
- executor 依赖 config、i18n。
- security 依赖 config、i18n。
- mcp/registry 依赖 client、mcp-config、i18n。
- skill/registry 依赖 loader、executor、fs、path、i18n。
graph LR Scheduler["scheduler.js"] --> ToolExecutor["tool-executor.js"] Scheduler --> ReactLoop["react-loop.js"] ToolExecutor --> Constants["constants.js"] ToolExecutor --> LocalAgent["local-agent-client.js"] ToolExecutor --> ActivityStore["activity-store.js"] Preselector["tool-preselector.js"] --> Constants ReactLoop --> State["state.js"] ReactLoop --> TokenCounter["token-counter.js"] Server["server.js"] --> Security["security.js"] Server --> Executor["executor.js"] Server --> McpReg["mcp/registry.js"] Server --> SkillReg["skill/registry.js"]
图表来源
- src/background/scheduler.js#L1-L20
- src/background/tool-executor.js#L1-L22
- src/background/tool-preselector.js#L1-L8
- src/background/react-loop.js#L1-L20
- agent/src/server.js#L1-L56
章节来源
- src/background/scheduler.js#L1-L20
- src/background/tool-executor.js#L1-L22
- src/background/tool-preselector.js#L1-L8
- src/background/react-loop.js#L1-L20
- agent/src/server.js#L1-L56
性能与并发
- 预筛选阈值固定为 10,避免小工具集不必要的 LLM 调用。
- MCP/RAG 工具加载使用互斥锁,防止并发导致集合不一致。
- 命令执行采用流式输出与输出缓冲上限(5MB),防止内存无限增长。
- 超时策略:Agent 端 decideTimeoutAction 根据期内输出决定是否延长,最多延长 5 次,总预算封顶 600s。
- Activity Store 防抖合并落盘,关键审计即时刷,减少 storage.local 频繁写开销。
- 新增:JSON 信封解析的性能考虑:容错恢复函数使用正则表达式进行边界定位,避免复杂的字符串处理影响性能。
章节来源
- src/background/constants.js#L24-L26
- src/background/tool-executor.js#L551-L778
- agent/src/executor.js#L96-L114
- agent/src/executor.js#L165-L186
- src/background/activity-store.js#L54-L82
故障排查指南
- 定时任务不执行:
- 检查 chrome.alarms 是否重建(rehydrateAlarms),任务是否 enabled,cron/interval 是否合法。
- 参考 src/background/scheduler.js#L70-L124。
- 工具预筛选失效:
- 检查工具数量是否超过阈值,LLM API 是否可用,JSON 解析是否成功。
- 新增:检查畸形 JSON 信封:如果看到"预筛选返回的 JSON 格式非法且无法恢复"错误,说明 AI 模型返回了不符合预期的内部协议数据,系统已自动防护并回退到全量工具模式。
- 参考 src/background/tool-preselector.js#L273-L432。
- MCP 工具未加载:
- 检查全局 MCP 开关、Agent 连通性、服务器启用状态、schema 压缩是否截断过多参数。
- 参考 src/background/tool-executor.js#L551-L651、agent/src/mcp/registry.js#L26-L108。
- 命令执行超时:
- 检查 decideTimeoutAction 策略、输出是否在期内产生、是否达到最大延长次数。
- 参考 agent/src/executor.js#L165-L186。
- 审计日志丢失:
- 检查是否关键审计(cookie_write/page_data_clear/file_delete/command_exec 拒绝/取消),否则可能因防抖延迟可见。
- 参考 src/background/activity-store.js#L46-L123。
章节来源
- src/background/scheduler.js#L70-L124
- src/background/tool-preselector.js#L273-L432
- src/background/tool-executor.js#L551-L651
- agent/src/mcp/registry.js#L26-L108
- agent/src/executor.js#L165-L186
- src/background/activity-store.js#L46-L123
结论
本系统通过扩展端与 Agent 端的清晰分工,实现了工具定义的集中管理、动态发现与注册、语义预筛选、安全路由与执行、并行优化与互斥保护、完整生命周期管理与审计追踪。最新版本增强了 JSON 信封的错误处理能力,有效防止了 AI 模型返回的内部协议数据泄露到用户界面,提升了系统的安全性和健壮性。建议在开发新工具时遵循现有分类、执行位置、确认标记与 schema 压缩规范,并在 Agent 端实现安全校验与流式输出,以确保系统稳定性与可观测性。
附录:工具开发与最佳实践
- 工具定义:
- 在 tools/ 目录下新增工具文件,导出工具数组,并在 constants.js 中聚合。
- 明确 category、execution、parallelizable、requiresConfirmation、confirmationActions。
- 参数验证:
- 在工具 handler 中进行参数必填校验,返回结构化错误信息。
- 使用 i18n 文案,避免硬编码中文。
- 安全校验:
- Agent 端工具涉及文件/命令时,必须调用 security.checkPath/checkCommand。
- 内网访问需通过 decideNetworkAccess 白名单校验。
- 并发与超时:
- 可并行工具标记 parallelizable=true,避免阻塞主循环。
- 长耗时工具应实现流式输出与超时控制,遵循 decideTimeoutAction 策略。
- 审计与统计:
- 敏感操作调用 appendAuditLog,关键操作即时落盘。
- 所有工具执行调用 recordToolStats 记录使用统计。
- 测试建议:
- 扩展端使用 vitest 单测,Agent 端使用 node --test 限定 test/unit 目录。
- 修改后统一执行 npm run build:silent 验证构建。
- 新增:JSON 信封处理最佳实践:
- 确保 AI 模型返回符合预期的 {type,data} 格式信封。
- 如果出现畸形信封,系统会自动防护并记录警告,无需手动干预。
- 在调试时关注 executionLog 中的 reasonMalformedEnvelope 错误信息。
章节来源