主题
消息流与工具调用
本文引用的源码文件
本文引用的文件
- src/background/index.js
- src/background/local-agent-client.js
- src/background/tool-executor.js
- src/background/tool-preselector.js
- src/background/react-loop.js
- src/background/stream-controller.js
- src/side_panel/chat-streaming.js
- src/side_panel/chat-manager.js
- agent/src/server.js
- agent/src/executor.js
- src/shared/tools.js
- src/background/constants.js
更新摘要
变更内容
- 增强了工具预筛选器的 JSON 信封恢复机制,新增
recoverAnswerEnvelopeData和looksLikePreselectEnvelope函数 - 改进了对 AI 模型响应不一致的容错处理能力
- 更新了工具预筛选算法以支持新的 JSON 格式并增强向后兼容性
- 完善了错误处理和降级策略
目录
引言
本文面向"从用户输入到 LLM 响应"的完整消息流转,重点解释 Chrome 扩展端(Manifest V3 Service Worker)与独立本地 Agent 服务之间的 HTTP/WebSocket 通信契约、ReAct 推理循环中的思考-行动-观察序列、工具参数校验与结果聚合、工具预筛选算法、并行执行优化、超时控制、消息去重、重试策略与性能监控指标。文档同时给出时序图、工具调用状态图和错误传播路径,帮助读者在理解整体架构的同时定位具体实现位置。
项目结构
本项目采用双进程架构:
- Chrome 扩展端(src/):Service Worker 入口 background/index.js,负责 ReAct 循环、工具调度、侧边栏 UI 状态、保活与自动续跑。
- 本地 Agent 端(agent/src/):Node.js 服务 agent/src/server.js,提供文件系统、命令执行、MCP 工具注册、RAG 等能力,并通过 WebSocket 推送命令输出。
graph TB subgraph "Chrome 扩展端" SW["Service Worker<br/>background/index.js"] RL["ReAct 循环<br/>background/react-loop.js"] TE["工具执行器<br/>background/tool-executor.js"] PS["工具预筛选<br/>background/tool-preselector.js"] SC["流式控制器<br/>background/stream-controller.js"] AC["Agent 客户端<br/>background/local-agent-client.js"] SP["侧边栏 UI<br/>side_panel/chat-manager.js / chat-streaming.js"] end subgraph "本地 Agent 端" AGS["HTTP + WebSocket 服务器<br/>agent/src/server.js"] EXE["命令执行器<br/>agent/src/executor.js"] end SP --> SW SW --> RL RL --> PS RL --> TE TE --> AC AC --> AGS AGS --> EXE RL --> SC SC --> SP
图示来源
- src/background/index.js#L1-L120
- src/background/react-loop.js#L728-L760
- src/background/tool-executor.js#L547-L651
- src/background/tool-preselector.js#L273-L432
- src/background/stream-controller.js#L36-L280
- src/background/local-agent-client.js#L399-L443
- agent/src/server.js#L388-L425
- agent/src/executor.js#L198-L386
章节来源
核心组件
- ReAct 推理循环:background/react-loop.js 维护多轮迭代、流式解析、工具调用、循环检测、子任务计划与恢复。
- 工具执行器:background/tool-executor.js 统一工具定义、动态 MCP/RAG 工具注入、并行执行、确认门控、审计日志。
- 工具预筛选:background/tool-preselector.js 通过轻量模型调用判断是否需要工具及选择哪些工具,减少上下文压力,新增 JSON 信封恢复机制。
- Agent 客户端:background/local-agent-client.js 封装 HTTP/WebSocket 认证、请求超时、可达性缓存、MCP/RAG API。
- 流式控制器:background/stream-controller.js 解析 SSE、节流发送、tool_calls 累积、usage 提取、空闲超时保护。
- 侧边栏 UI:side_panel/chat-manager.js 与 chat-streaming.js 负责消息渲染、流式更新、工具卡片、执行日志面板。
- Agent 服务端:agent/src/server.js 提供 REST 路由、CORS、认证、文件上传、命令执行、MCP/RAG 集成。
- 命令执行器:agent/src/executor.js 管理子进程、流式 stdout/stderr、超时策略、进程组终止。
章节来源
- src/background/react-loop.js#L728-L800
- src/background/tool-executor.js#L448-L651
- src/background/tool-preselector.js#L273-L432
- src/background/local-agent-client.js#L399-L443
- src/background/stream-controller.js#L36-L280
- src/side_panel/chat-manager.js#L54-L83
- src/side_panel/chat-streaming.js#L677-L726
- agent/src/server.js#L388-L425
- agent/src/executor.js#L198-L386
架构总览
下图展示一次典型请求从侧边栏发起,经过 Service Worker、ReAct 循环、工具执行、Agent 服务、命令执行,再返回流式响应的完整链路。
sequenceDiagram
participant UI as "侧边栏 UI<br/>chat-manager.js / chat-streaming.js"
participant SW as "Service Worker<br/>index.js"
participant RL as "ReAct 循环<br/>react-loop.js"
participant PS as "工具预筛选<br/>tool-preselector.js"
participant TE as "工具执行器<br/>tool-executor.js"
participant AC as "Agent 客户端<br/>local-agent-client.js"
participant AGS as "Agent 服务器<br/>server.js"
participant EXE as "命令执行器<br/>executor.js"
UI->>SW : 发送 CALL_API / 启动 ReAct
SW->>RL : reactLoop(messages, model, tools, ...)
RL->>PS : preselectTools(可选)
PS-->>RL : 直接回答 或 选定工具集
RL->>TE : executeTool(toolName, args)
TE->>AC : agentRequest('/api/...') 或 createExecWebSocket()
AC->>AGS : HTTP POST /api/fs|/api/exec|/api/mcp/call
AGS->>EXE : spawn 子进程 / 流式输出
EXE-->>AGS : stdout/stderr/exit
AGS-->>AC : JSON 响应 或 WS 事件
AC-->>TE : {success, content/error}
TE-->>RL : 工具结果
RL->>SC : StreamController.feedLine()
SC-->>UI : STREAM_START / STREAM_CHUNK / STREAM_TOOL_CALL / STREAM_DONE
图示来源
- src/background/react-loop.js#L728-L800
- src/background/tool-preselector.js#L273-L432
- src/background/tool-executor.js#L547-L651
- src/background/local-agent-client.js#L399-L443
- agent/src/server.js#L388-L425
- agent/src/executor.js#L198-L386
- src/background/stream-controller.js#L36-L280
详细组件分析
ReAct 推理循环:思考-行动-观察
ReAct 循环是消息流的核心编排器:
- 每轮先构建系统提示与历史,调用 LLM 获取内容增量或 tool_calls。
- 若检测到 tool_calls,立即通知前端显示工具卡片,随后按顺序或并行执行工具,将结果作为 observation 回注消息。
- 支持子任务 plan_task 拆分、循环检测、反思评估、checkpoint 持久化与自动续跑。
flowchart TD
Start(["进入 reactLoopImpl"]) --> BuildCtx["构建消息上下文<br/>含历史/压缩/引用"]
BuildCtx --> CallLLM["调用 LLMSSE 流式"]
CallLLM --> HasTool{"是否包含 tool_calls?"}
HasTool --> |否| EmitContent["输出文本/推理内容"]
EmitContent --> NextIter["下一轮迭代"]
HasTool --> |是| ExecTools["执行工具串行/并行"]
ExecTools --> Observe["收集工具结果并追加为 tool 消息"]
Observe --> NextIter
NextIter --> LoopCheck{"达到最大迭代/超时/循环检测?"}
LoopCheck --> |是| Finish(["结束并保存 checkpoint/清理"])
LoopCheck --> |否| CallLLM
图示来源
章节来源
工具预筛选算法
当工具数量超过固定阈值时,预筛选会调用轻量模型决定"直接回答"还是"需要工具",并返回候选工具名列表;若无法解析或结果为空,则回退为全量工具。新增的 JSON 信封恢复机制显著提升了容错能力。
flowchart TD
A["收到 messages/tools"] --> B{"工具数 > PRESELECT_MIN_TOOL_COUNT?"}
B --> |否| Skip["跳过预筛选,使用全部工具"]
B --> |是| Extract["提取最近用户问题与历史上下文"]
Extract --> Prompt["构建预筛选 prompt"]
Prompt --> ModelCall["调用模型response_format=json_object"]
ModelCall --> Parse["解析 JSON:answer 或 tools"]
Parse --> |answer| Direct["直接回答,不二次调用"]
Parse --> |tools| Match["按名称匹配工具集合"]
Match --> Fallback{"匹配为空?"}
Fallback --> |是| AllTools["回退为全部工具"]
Fallback --> |否| Selected["返回筛选后的工具集"]
更新 新增了 JSON 信封恢复机制,包括 recoverAnswerEnvelopeData 和 looksLikePreselectEnvelope 函数,用于处理 AI 模型响应不一致的情况。
图示来源
章节来源
JSON 信封恢复机制
新增功能 工具预筛选器现在具备强大的 JSON 信封恢复能力,能够处理 AI 模型响应中的格式错误:
flowchart TD RawText["原始模型响应"] --> TryParse["尝试 JSON.parse"] TryParse --> |成功| ValidJSON["有效 JSON 对象"] TryParse --> |失败| CheckEnvelope["检查是否为预筛选信封"] CheckEnvelope --> |是| RecoverData["recoverAnswerEnvelopeData 恢复数据"] CheckEnvelope --> |否| Fallback["回退到旧格式提取"] RecoverData --> |成功| AnswerType["返回 answer 类型"] RecoverData --> |失败| Malformed["标记为畸形信封"] ValidJSON --> ProcessType["处理 type/data 字段"] ProcessType --> AnswerOrTools["answer 或 tools 类型"]
新增的关键函数:
looksLikePreselectEnvelope(text):检测文本是否像{type,data}预筛选信封但 JSON.parse 已失败recoverAnswerEnvelopeData(text):从格式错误的信封中提取 data 字符串内容,支持反转义常见序列
章节来源
工具参数验证与结果聚合
- 参数解析:工具 handler 中通过 tryParseToolArgs 等辅助函数解析 arguments,兼容字符串与对象两种格式。
- 安全校验:网络访问受内网白名单限制;敏感操作需用户确认;命令执行走 Agent 端安全检查与安全环境变量白名单。
- 结果聚合:工具执行结果以 tool 消息追加到当前会话;执行日志节点记录成功/失败、耗时、stdout/stderr 摘要;子任务失败时生成部分产出摘要供父任务继续。
flowchart TD Args["工具入参arguments"] --> Parse["解析与类型转换"] Parse --> Validate["业务校验/安全门控"] Validate --> |通过| Execute["执行工具浏览器/Agent/MCP/RAG"] Validate --> |拒绝| Error["返回错误结果"] Execute --> Result["标准化结果content/error"] Result --> Log["写入执行日志节点"] Log --> Append["追加为 tool 消息"]
图示来源
- src/background/tool-executor.js#L1-L23
- src/background/react-loop.js#L452-L541
- agent/src/executor.js#L118-L156
章节来源
- src/background/tool-executor.js#L1-L23
- src/background/react-loop.js#L452-L541
- agent/src/executor.js#L118-L156
Chrome 扩展端与 Agent 服务的通信协议
- HTTP 认证:所有需认证的请求携带 Authorization: Bearer <token>,Token 由配对流程获得并加密存储。
- 主要端点:/api/pair、/api/status、/api/fs/、/api/exec、/api/mcp/、/api/skill/、/api/rag/、/api/files/upload。
- WebSocket:/api/exec 可建立 WS 连接,实时推送 stdout/stderr/exit;Token 通过查询参数传递。
- CORS:仅允许 chrome-extension:// 来源跨域读取响应,防止恶意网页窃取无认证接口数据。
sequenceDiagram
participant AC as "Agent 客户端<br/>local-agent-client.js"
participant AGS as "Agent 服务器<br/>server.js"
AC->>AGS : POST /api/pair {code, extensionId}
AGS-->>AC : {success, token}
AC->>AGS : GET /api/status (无认证)
AGS-->>AC : {version, platform, ragAvailable}
AC->>AGS : POST /api/fs/read/write/list/delete/search (Bearer Token)
AGS-->>AC : {success, content/error}
AC->>AGS : POST /api/exec (Bearer Token)
AGS-->>AC : {execId}
AC->>AGS : ws : //host : port?token=...
AGS-->>AC : {type : stdout|stderr|exit|error}
图示来源
- src/background/local-agent-client.js#L40-L94
- src/background/local-agent-client.js#L399-L443
- src/background/local-agent-client.js#L662-L728
- agent/src/server.js#L471-L548
- agent/src/server.js#L751-L800
章节来源
- src/background/local-agent-client.js#L40-L94
- src/background/local-agent-client.js#L399-L443
- src/background/local-agent-client.js#L662-L728
- agent/src/server.js#L471-L548
- agent/src/server.js#L751-L800
工具调用状态图
工具调用经历创建、等待确认(可选)、执行、流式输出、完成/失败、取消/超时等状态。
stateDiagram-v2 [*] --> 待执行 待执行 --> 等待确认 : requiresConfirmation=true 等待确认 --> 已确认 : 用户同意 等待确认 --> 已拒绝 : 用户拒绝/超时/面板关闭 待执行 --> 执行中 : 无需确认 或 已确认 执行中 --> 流式输出 : stdout/stderr 开始 流式输出 --> 已完成 : exitCode=0 流式输出 --> 已失败 : exitCode!=0 或异常 执行中 --> 已取消 : 用户停止/会话取消 执行中 --> 已超时 : 代理端预算耗尽/扩展端保险上限 已确认 --> 已取消 已拒绝 --> [*] 已完成 --> [*] 已失败 --> [*] 已取消 --> [*] 已超时 --> [*]
图示来源
- src/background/tool-executor.js#L438-L446
- src/background/react-loop.js#L285-L450
- agent/src/executor.js#L198-L386
章节来源
- src/background/tool-executor.js#L438-L446
- src/background/react-loop.js#L285-L450
- agent/src/executor.js#L198-L386
错误传播路径
- 扩展端 fetch 超时/网络错误:local-agent-client.js 返回 success=false 与本地化错误文案,并附加 httpStatus 区分 404 与离线。
- Agent 端认证失败:server.js 返回 401/403,security 模块记录审计日志。
- 命令执行失败:executor.js 广播 error/exit,扩展端根据 exitCode/killed/timedOut 构造用户可见结果。
- 流式空闲超时:stream-controller.js 抛出 StreamIdleTimeout,react-loop.js 捕获后中断并提示重试。
- 新增 工具预筛选 JSON 信封恢复失败:回退为全量工具,避免将畸形信封透传给 UI。
flowchart TD NetErr["网络/超时错误"] --> ClientErr["local-agent-client 返回错误"] AuthFail["认证失败"] --> ServerErr["server.js 返回 401/403"] ExecErr["命令异常"] --> WSErr["WS 广播 error/exit"] IdleTO["流式空闲超时"] --> StreamErr["stream-controller 抛出异常"] MalformedJSON["预筛选 JSON 信封恢复失败"] --> Fallback["回退全量工具"] ClientErr --> UI["侧边栏显示错误"] ServerErr --> UI WSErr --> UI StreamErr --> UI Fallback --> UI
图示来源
- src/background/local-agent-client.js#L399-L443
- agent/src/server.js#L537-L548
- agent/src/executor.js#L326-L383
- src/background/stream-controller.js#L391-L409
- src/background/tool-preselector.js#L474-L477
章节来源
- src/background/local-agent-client.js#L399-L443
- agent/src/server.js#L537-L548
- agent/src/executor.js#L326-L383
- src/background/stream-controller.js#L391-L409
依赖关系分析
- background/index.js 作为 Service Worker 入口,协调 keepalive、自动续跑、侧边栏可见性、定时任务与 checkpoint 清理。
- background/react-loop.js 依赖 tool-executor.js 获取工具与执行工具,依赖 stream-controller.js 解析 SSE,依赖 local-agent-client.js 进行 Agent 通信。
- background/tool-executor.js 动态注入 MCP/RAG 工具,维护 PARALLELIZABLE_TOOLS 与 CONFIRMATION_REQUIRED_TOOLS。
- background/tool-preselector.js 提供增强的 JSON 信封恢复能力,处理 AI 模型响应不一致的情况。
- side_panel/chat-manager.js 与 chat-streaming.js 消费 STREAM_* 消息,渲染思考过程、工具卡片与执行日志。
- agent/src/server.js 作为 HTTP+WebSocket 网关,分发到 executor.js、mcp registry、skill registry、memory routes、rag detect/install。
graph LR Index["background/index.js"] --> ReactLoop["background/react-loop.js"] ReactLoop --> ToolExec["background/tool-executor.js"] ReactLoop --> StreamCtrl["background/stream-controller.js"] ToolExec --> LocalAgent["background/local-agent-client.js"] LocalAgent --> AgentServer["agent/src/server.js"] AgentServer --> Executor["agent/src/executor.js"] ToolPreselector["background/tool-preselector.js"] --> Index ChatMgr["side_panel/chat-manager.js"] --> ChatStream["side_panel/chat-streaming.js"] ChatStream --> ReactLoop
图示来源
- src/background/index.js#L1-L120
- src/background/react-loop.js#L728-L800
- src/background/tool-executor.js#L547-L651
- src/background/local-agent-client.js#L399-L443
- agent/src/server.js#L388-L425
- agent/src/executor.js#L198-L386
- src/side_panel/chat-manager.js#L54-L83
- src/side_panel/chat-streaming.js#L677-L726
章节来源
- src/background/index.js#L1-L120
- src/background/react-loop.js#L728-L800
- src/background/tool-executor.js#L547-L651
- src/background/local-agent-client.js#L399-L443
- agent/src/server.js#L388-L425
- agent/src/executor.js#L198-L386
- src/side_panel/chat-manager.js#L54-L83
- src/side_panel/chat-streaming.js#L677-L726
性能与并发优化
- 工具预筛选:当工具数量超过 PRESELECT_MIN_TOOL_COUNT(默认 10)时触发,减少 LLM 上下文压力与无效工具调用。
- 并行执行:PARALLELIZABLE_TOOLS 标记的工具可并行执行,提升吞吐;CONFIRMATION_REQUIRED_TOOLS 强制串行确认。
- 流式节流:StreamController 的 streamChunkDelay 控制字符级渲染频率,避免 UI 抖动。
- 空闲超时:STREAM_IDLE_TIMEOUT_MS 防止流式数据卡住;Agent 命令执行采用"有输出才延长"的策略,静默即杀。
- 消息去重:tool_call.id 唯一键与 inFlightConfirmKeys 防止重复确认;completedProcesses 缓存回放避免重复输出。
- 重试策略:fetchWithRetry 支持指数退避;preselectTools 与 react-loop 对 API 失败进行降级处理。
- 新增 JSON 信封恢复:显著提升对 AI 模型响应不一致的容错能力,减少因格式错误导致的失败率。
章节来源
- src/background/constants.js#L24-L26
- src/background/constants.js#L132-L149
- src/background/stream-controller.js#L36-L280
- agent/src/executor.js#L165-L186
- src/background/tool-preselector.js#L273-L432
故障排查指南
- Service Worker 生命周期:keepalive port 用于保活;SW 重启后通过 SW_RESTARTED 通知侧边栏,支持从 checkpoint 恢复。
- 配对与连通性:pair 失败、代理未配对、代理服务未连接等错误由 local-agent-client.js 本地化提示;可达性缓存避免频繁探测。
- 命令执行超时:executor.js 的 decideTimeoutAction 基于输出心跳延长预算;扩展端 toolTimeout 为保险上限。
- 流式卡顿:STREAM_IDLE_TIMEOUT_MS 触发空闲超时;检查网络与服务提供商稳定性。
- 侧边栏不可见:isPanelVisibleToUser 与焦点镜像确保通知可见性;快捷键 toggle 需手势上下文。
- 新增 工具预筛选 JSON 信封错误:检查 AI 模型响应格式,查看 recoverAnswerEnvelopeData 是否能成功恢复数据。
章节来源
- src/background/index.js#L140-L218
- src/background/local-agent-client.js#L275-L330
- agent/src/executor.js#L165-L186
- src/background/stream-controller.js#L287-L409
结论
本方案通过 ReAct 循环编排思考-行动-观察序列,结合工具预筛选、并行执行、流式输出与严格的超时控制,实现了从用户输入到 LLM 响应的稳定、可观测、可扩展的消息流。新增的 JSON 信封恢复机制显著提升了系统的鲁棒性,能够有效处理 AI 模型响应不一致的问题。Chrome 扩展端与 Agent 服务之间通过带认证的 HTTP/WebSocket 协议交互,支持文件、命令、MCP 工具与 RAG 能力。错误传播路径清晰,具备自动续跑、消息去重与重试机制,适合复杂自动化场景。
附录:协议与状态定义
- HTTP 端点:/api/pair、/api/status、/api/fs/、/api/exec、/api/mcp/、/api/skill/、/api/rag/、/api/files/upload。
- WebSocket:/api/exec 建立连接,推送 stdout/stderr/exit/error。
- 认证:Authorization: Bearer <token>;配对码一次性认证。
- 工具状态:待执行 → 等待确认 → 执行中 → 流式输出 → 已完成/已失败/已取消/已超时。
- 新增 预筛选响应格式:支持
{type: "answer", data: "..."}和{type: "tools", data: [...]}新格式,以及向后兼容的旧格式。
章节来源