主题
消息通信机制
本文引用的源码文件
本文引用的文件
目录
- 引言
- 项目结构与通信边界
- Chrome 扩展消息模型:sendMessage 与 onMessage
- Content Script 到 Background Service Worker 的消息路由表
- 扩展端与 Agent 端的 HTTP/WebSocket 通信契约
- 从网页脚本调用后台功能的端到端流程
- 超时、重试与连接状态管理
- 架构总览图
- 故障排查指南
- 结论
引言
本文面向 Chrome Extension(Manifest V3,版本 2.3.1)与独立本地 Agent(Node.js,版本 2.3.1)的双进程架构,系统性说明以下能力:
chrome.runtime.sendMessage与chrome.runtime.onMessage的同步/异步使用方式。- Content Script 中基于 Map 的消息路由表结构及 O(1) 分发逻辑。
- Background Service Worker 作为扩展内部消息中枢的职责。
- 扩展端通过
local-agent-client.js与 Agent 端server.js之间的 HTTP 与 WebSocket 契约。 - 消息超时、可达性缓存、SW 保活、Agent 重启等运行时约束。
- 实际代码路径引用,便于读者直接定位实现。
本项目是双进程架构:Chrome 扩展端位于 src/,Agent 端入口为 agent/src/server.js。两端版本号保持同步,文档以 2.3.1 为准。Agent 源码修改后必须重启进程,新接口才生效。
项目结构与通信边界
扩展端按 MV3 Service Worker 组织,核心通信边界如下:
- 网页脚本 / Content Script:运行在页面上下文中,负责 DOM 操作、页面信息提取、用户交互。
- Background Service Worker:扩展全局上下文,负责消息路由、工具调度、Agent 客户端封装、侧边栏控制、定时任务等。
- Side Panel / Options / Offscreen:扩展 UI 层,通过
chrome.runtime.sendMessage与 Background 通信。 - Agent 服务:独立 Node.js 进程,提供文件系统、命令执行、Skill、MCP、RAG 等能力,暴露 HTTP API 与 WebSocket。
graph TB WebPage["网页脚本"] --> ContentScript["Content Script<br/>src/content/index.js"] ContentScript --> Background["Background Service Worker<br/>src/background/index.js"] SidePanel["Side Panel / Options"] --> Background Background --> AgentClient["Agent 客户端<br/>src/background/local-agent-client.js"] AgentClient --> AgentServer["Agent 服务端<br/>agent/src/server.js"]
图表来源
- src/content/index.js#L74-L193
- src/background/index.js#L920-L1844
- src/background/local-agent-client.js#L399-L443
- agent/src/server.js#L417-L553
章节来源
Chrome 扩展消息模型:sendMessage 与 onMessage
同步消息
当接收方在 onMessage 处理器中直接调用 sendResponse(result) 并返回 undefined 时,发送方的回调立即拿到结果。适用于轻量、无网络 IO 的操作。
示例路径:
- Content Script 同步处理简单查询类消息。
- Background 向 Side Panel 或 Options 广播状态变更。
参考实现位置:
异步消息
当处理器返回 true,或通过 Promise 调用 sendResponse,表示消息通道保持开放,后续再回复。适用于:
- 需要等待 DOM 操作完成。
- 需要等待网络请求或子任务完成。
- 需要维持长连接(如 keepalive port)。
参考实现位置:
关键行为总结
| 场景 | 发送方 | 接收方 | 返回值约定 |
|---|---|---|---|
| 轻量同步响应 | chrome.runtime.sendMessage(msg, cb) | onMessage 中直接 sendResponse(data) | 同步返回 |
| 异步响应 | chrome.runtime.sendMessage(msg, cb) | onMessage 中 Promise.then(sendResponse) 并返回 true | 延迟回复 |
| 长连接 | chrome.runtime.connect(portName) | onConnect 监听端口 | 双向 postMessage |
| 跨 Tab 定向 | chrome.tabs.sendMessage(tabId, msg) | 目标 Tab 的 Content Script onMessage | 同 sendMessage |
章节来源
Content Script 到 Background Service Worker 的消息路由表
Content Script 使用一个集中式 HANDLERS Map,将 message.type 映射到具体处理器函数。该设计具备以下特点:
- O(1) 查找:通过对象键直接定位处理器。
- 分类清晰:页面读取、页面交互、表单输入、信息提取、媒体输出、异步工具等分组明确。
- 异步标记集合:
ASYNC_HANDLERS声明哪些类型需要保持消息通道开放。 - 顶层帧限制:
TOP_FRAME_ONLY_TYPES避免 iframe 抢占响应。
flowchart TD
Start["收到 chrome.runtime.onMessage"] --> CheckTop["是否 TOP_FRAME_ONLY 且非顶层帧?"]
CheckTop --> |是| Ignore["忽略消息"]
CheckTop --> |否| Lookup["HANDLERS[message.type]"]
Lookup --> Found{"找到处理器?"}
Found --> |否| Exit["不处理"]
Found --> |是| CallHandler["调用 handler(message)"]
CallHandler --> AsyncCheck{"是否 ASYNC_HANDLERS 或返回 Promise?"}
AsyncCheck --> |是| KeepOpen["return true<br/>Promise.then(sendResponse)"]
AsyncCheck --> |否| SyncReply["sendResponse(result)"]
图表来源
路由表分类摘要
| 类别 | 典型 message.type | 职责 |
|---|---|---|
| 页面读取 | GET_PAGE_TEXT、GET_FULL_HTML、QUERY_ELEMENTS、GET_SELECTED_CONTENT | 获取文本、HTML、可交互元素、选区内容 |
| 页面交互 | INTERACT_ELEMENT、FILL_FORM、SCROLL_TO | 点击、填表、滚动 |
| 表单输入 | KEYBOARD_INPUT、FILE_UPLOAD | 键盘输入、文件上传 |
| 信息提取 | EXTRACT_TABLE、EXTRACT_METADATA、EXTRACT_LINKS、EXTRACT_FORMS、EXTRACT_IMAGES、SEARCH_IN_PAGE、IFRAME_CONTENT、SCROLL_COLLECT | 结构化数据抽取 |
| 媒体输出 | MANAGE_STORAGE、INJECT_CSS | 存储管理与样式注入 |
| 异步工具 | COPY_TO_CLIPBOARD、PASTE_FROM_CLIPBOARD、WAIT_ELEMENT、SELECT_DROPDOWN、QRCODE、START_REGION_SELECTION | 需要等待或 UI 交互的工具 |
章节来源
扩展端与 Agent 端的 HTTP/WebSocket 通信契约
总体契约
扩展端通过 local-agent-client.js 统一封装对 Agent 的 HTTP 与 WebSocket 调用;Agent 端由 server.js 提供 HTTP Router 与 WebSocket 支持。所有需认证的请求携带 Authorization: Bearer <token>。
sequenceDiagram
participant BG as "Background Service Worker"
participant Client as "local-agent-client.js"
participant Agent as "agent/src/server.js"
BG->>Client : 调用 execCommand / readFile / getMcpTools 等
Client->>Client : agentRequest(path, body, method, timeoutMs)
Client->>Agent : fetch(url, { Authorization : Bearer token })
Agent-->>Client : JSON { success, ... }
Client-->>BG : 返回结果或错误
图表来源
HTTP 端点分类
| 领域 | 端点 | 方法 | 说明 |
|---|---|---|---|
| 配对与会话 | /api/pair | POST | 扩展与 Agent 配对,返回 token |
| 健康检查 | /api/status | GET | 返回版本、平台、RAG 可用性等 |
| 详细状态 | /api/status/detail | GET | 工作目录、资源使用、进程列表等 |
| 文件系统 | /api/fs/read、/api/fs/write、/api/fs/list、/api/fs/delete、/api/fs/search_files、/api/fs/search_content | POST | 文件读写、目录浏览、搜索 |
| 文件上传 | /api/files/upload | POST | multipart/form-data 上传 |
| 命令执行 | /api/exec | POST | 启动命令,支持 wait、timeoutMs |
| 命令停止 | /api/exec/stop | POST | 停止运行中的命令 |
| MCP | /api/mcp/tools、/api/mcp/call、/api/mcp/servers/* | GET/POST/DELETE/PUT | MCP 工具与服务端管理 |
| Skill | /api/skill/* | GET/POST/DELETE | Skill 列表、详情、执行、导入、启用/禁用 |
| Agent 管理 | /api/agent/restart、/api/agent/update、/api/shutdown | POST | 重启、更新、关闭 |
章节来源
WebSocket 契约
WebSocket 用于命令执行的实时输出流。扩展端通过 createExecWebSocket(wsUrl, onMessage, onClose, onError) 建立连接,Token 通过 URL 参数附加。
关键点:
- Token 从当前活跃 Agent 配置中获取。
- 若 Agent 已知不可达,直接走错误回调,避免无效连接。
- 空闲超时由调用方统一管理,避免双重超时冲突。
- 连接成功 resolve WebSocket 实例,失败 reject 并触发 onError。
sequenceDiagram participant Executor as "tool-executor.js" participant Client as "local-agent-client.js" participant WS as "WebSocket" participant Agent as "agent/src/server.js" Executor->>Client : createExecWebSocket(wsUrl, onMessage, onClose, onError) Client->>Client : 校验 connected 与 reachability Client->>WS : new WebSocket(authenticatedUrl) WS-->>Client : onopen → resolve(ws) WS-->>Executor : onmessage(JSON) WS-->>Executor : onclose → onClose() WS-->>Executor : onerror → onError(error)
图表来源
认证与安全
- Agent 端对大多数接口要求
Authorization: Bearer <token>。 - CORS 仅放行
chrome-extension://来源。 - 配对接口
/api/pair无需认证,但会记录 extensionId。 - 心跳接口
/api/heartbeat刷新在线状态,不返回敏感信息。
章节来源
- agent/src/server.js#L235-L266
- agent/src/server.js#L471-L553
- src/background/local-agent-client.js#L399-L443
从网页脚本调用后台功能的端到端流程
以“从网页截图”为例,展示完整链路:
sequenceDiagram
participant Page as "网页脚本"
participant Content as "Content Script"
participant BG as "Background Service Worker"
participant Panel as "Side Panel"
Page->>Content : 快捷键触发 CAPTURE_TAB_FROM_PAGE
Content->>BG : chrome.runtime.sendMessage({ type : 'CAPTURE_TAB_FROM_PAGE' })
BG->>BG : 执行截图逻辑
BG-->>Panel : chrome.runtime.sendMessage({ type : 'SCREENSHOT_RESULT', dataUrl, mode })
图表来源
另一个常见流程是“选项页通知 Background 打开/关闭”:
sequenceDiagram
participant Options as "Options 页面"
participant BG as "Background Service Worker"
Options->>BG : chrome.runtime.sendMessage({ type : 'OPTIONS_PAGE_OPEN' })
BG->>BG : 设置 _optionsPageOpen = true
BG-->>Options : 可选状态广播
Options->>BG : chrome.runtime.sendMessage({ type : 'OPTIONS_PAGE_CLOSED' })
BG->>BG : 设置 _optionsPageOpen = false
图表来源
章节来源
超时、重试与连接状态管理
消息超时
- HTTP 请求通过
AbortController实现超时,默认 60 秒,部分接口(如下载)延长至 120 秒。 - WebSocket 空闲超时由调用方统一管理,避免与连接层双重超时冲突。
参考实现位置:
重试机制
- 代码未实现自动重试循环,而是通过可达性缓存快速失败,避免阻塞。
- 用户可通过“触发健康检查”手动刷新状态。
参考实现位置:
连接状态管理
- Background 维护
_agentReachability内存缓存,按 agentId 区分可达性。 - SW 保活通过 side panel 的 keepalive port 防止被系统回收。
- Agent 重启/更新后需重新配对或刷新 token。
参考实现位置:
- src/background/local-agent-client.js#L101-L127
- src/background/index.js#L140-L218
- agent/src/server.js#L555-L603
章节来源
- src/background/local-agent-client.js#L405-L442
- src/background/local-agent-client.js#L662-L728
- src/background/index.js#L140-L218
- agent/src/server.js#L555-L603
架构总览图
classDiagram
class ContentScript {
+HANDLERS Map
+ASYNC_HANDLERS Set
+TOP_FRAME_ONLY_TYPES Set
+onMessage(message, sender, sendResponse)
}
class BackgroundServiceWorker {
+onMessage(message, sender, sendResponse)
+keepalivePort(sessionId)
+sidePanelControl()
+agentHealthCheck()
}
class LocalAgentClient {
+agentRequest(path, body, method, timeoutMs)
+agentGet(path, timeoutMs)
+createExecWebSocket(wsUrl, onMessage, onClose, onError)
+getAgentConfig()
}
class AgentServer {
+httpServer(req, res)
+wsServer(connection)
+authMiddleware(token)
+corsFilter(origin)
}
ContentScript --> BackgroundServiceWorker : "chrome.runtime.sendMessage"
BackgroundServiceWorker --> LocalAgentClient : "HTTP/WebSocket"
LocalAgentClient --> AgentServer : "fetch + WebSocket"
图表来源
- src/content/index.js#L74-L193
- src/background/index.js#L920-L1844
- src/background/local-agent-client.js#L399-L728
- agent/src/server.js#L417-L749
故障排查指南
常见问题
| 问题 | 可能原因 | 排查建议 |
|---|---|---|
| Content Script 消息无响应 | 非顶层帧拦截、handler 未注册、异步未 return true | 检查 TOP_FRAME_ONLY_TYPES 与 ASYNC_HANDLERS |
| Background 被系统回收 | SW 空闲终止、无 keepalive | 确认 side panel 保活连接存在 |
| Agent 请求超时 | 网络不可达、Agent 未启动、token 失效 | 检查 /api/status 与 Authorization 头 |
| WebSocket 连接失败 | Agent 重启、token 过期、地址替换异常 | 查看 createExecWebSocket 日志与 reachable 缓存 |
| 大消息截断 | chrome.runtime.sendMessage 单条最大 64MiB | 使用日志截断逻辑或分片传输 |
关键日志位置
- Background:
[Background]前缀日志。 - Agent:
[Agent]前缀日志。 - AgentClient:
[AgentClient]前缀日志。
章节来源
- src/content/index.js#L209-L247
- src/background/index.js#L140-L218
- src/background/local-agent-client.js#L405-L442
- agent/src/server.js#L417-L425
结论
本项目的消息通信机制围绕三层展开:
- 扩展内部:Content Script 通过集中式路由表与 Background Service Worker 通信,支持同步与异步模式。
- 扩展与 Agent:Background 通过
local-agent-client.js封装 HTTP 与 WebSocket,统一认证、超时与可达性管理。 - Agent 服务端:提供 RESTful API 与实时命令输出流,支持文件、命令、Skill、MCP、RAG 等能力。
在实际使用中,应重点关注:
- 消息类型定义与路由一致性。
- 异步处理器正确返回
true或使用 Promise。 - Agent 连接状态与 token 有效性。
- SW 生命周期与保活机制。
- 大消息截断与性能优化。