news 2026/9/12 15:23:51

oh-my-pi Browser Relay 实战:让 omp 通过 Chrome 扩展驱动你现有的浏览器标签页

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
oh-my-pi Browser Relay 实战:让 omp 通过 Chrome 扩展驱动你现有的浏览器标签页

oh-my-pi Browser Relay 实战:让 omp 通过 Chrome 扩展驱动你现有的浏览器标签页

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

本文聚焦 oh-my-pi(omp)项目中的@oh-my-pi/browser-relay组件,讲解它如何通过一个 Chrome MV3 扩展与本地 CDP Relay 服务,让 Eval 的browserAPI 直接驱动你现有的Chrome 标签页(包括已登录会话),而无需重启浏览器或手动暴露调试端口。读完本文,你将掌握 browser relay 的架构原理、安装步骤、两种 opt-in 配置方式(app.relaybrowser.relay)、omp browser-relay的常用参数,以及它的安全边界与开发验证方法。

为什么需要 Browser Relay:Chrome 136 之后的新约束

传统上,让自动化工具驱动 Chrome 的做法是携带--remote-debugging-port重启浏览器。但根据 browser-relay 包 README 的说明,Chrome 136+ 会拒绝在默认 profile 上使用该启动参数,这使得"复用已登录、已配置好的日常浏览器"这条路基本被堵死。

@oh-my-pi/browser-relay的解法是绕开启动参数,改用 Chrome 官方支持的扩展机制:

  • 浏览器侧:一个Chrome MV3 扩展,通过chrome.debuggerAPI 附加到标签页并收发 CDP 命令;
  • 进程侧:一个随 omp CLI 分发的relay 服务器omp browser-relay,源码位于 packages/coding-agent/src/tools/browser/relay/),对外伪装成 Chrome 的 CDP discovery endpoint,供 omp 的 browser 工具(基于 puppeteer)以普通browserURL方式连接。

这套组合的首次发布记录在 CHANGELOG.md 的17.2.5(2026-08-03)条目中:MV3 扩展使 omp browser tool 能够通过chrome.debugger附加并驱动现有浏览器标签页,同时引入了自动、健壮的标签页管理能力——将 agent 正在驱动的标签页归入每个窗口专属的 "omp" 标签组,并在断开连接时干净地解散该分组。

整体架构:扩展、中继服务与多路复用

relay 架构由三个角色组成,它们的分工在 server.ts 的模块注释中定义得非常清晰:

端点角色
GET /json/version伪装 Chrome 的 CDP discovery 握手;扩展连接完成后返回 200 及webSocketDebuggerUrl,尚未连接时返回 503(客户端如waitForCdp会持续轮询)
GET /jsonGET /json/list可附加的页面目标列表(调试辅助)
WS /cdp下游 CDP 客户端(puppeteer)接入点
WS /extChrome 扩展接入点(配置 token 时做门控)

关键难点在于:Chrome 每个标签页只允许一个chrome.debugger附加,而 omp 的 browser 工具会为每个被驱动的标签页建立两条 puppeteer 连接(一条 supervisor、一条 tab worker)。relay 的 bridge 在 bridge.ts 中解决了这一冲突:它通过扩展在每个标签页上只维护一个chrome.debugger附加,再用派发的会话 ID 把所有下游连接复用到这条通道上。同时,chrome.debugger本身不暴露浏览器级 target 和Target.*层级,bridge 负责合成这部分表面(参考了 puppeteer-core 的cdp/ExtensionTransport.ts)。

从源码结构看,扩展与 relay 之间的线协议定义在 protocol.ts:扩展主动拨号到ws://127.0.0.1:<port>/ext,交换 JSON 消息。relay 通过带编号的 RPC 驱动扩展,扩展则把标签页生命周期事件与chrome.debugger事件实时推送回去。

安装:一条命令 + 开发者模式加载

扩展的安装分两步,均在 README.md 中有明确说明:

  1. 运行omp browser-relay install,该命令会把打包好的扩展写入~/.omp/browser-relay/extension
  2. 打开chrome://extensions,开启Developer mode,点击Load unpacked选择上述目录加载。

也可以直接从发布资产中获取omp-browser-relay-extension.zip解压加载。扩展的清单文件位于 extension/manifest.json,声明了debuggertabstabGroupsstoragealarms五个权限,并提供了独立设置页options.html(点击工具栏图标即可打开设置)。

两种 Opt-in 方式:单次调用与全局默认

18.0.7(2026-08-26)这一版的 CHANGELOG 专门澄清了两个 opt-in 路径的范围差异,这是配置 relay 最容易混淆的地方:

方式一:按调用启用(per-call)

在 Eval 的browser.open(...)中传入app: { relay: true }。这种方式只对这一次调用生效,不持久化任何状态,其他调用和会话的默认行为保持不变。适合偶尔需要操作真实浏览器、不想改变全局行为的场景。

方式二:设为默认(as the default)

运行omp config set browser.relay true,relay 会成为该 profile 下所有会话、所有项目的默认驱动方式。需要特别注意的是优先级关系:项目级设置、环境变量PI_BROWSER_RELAY、以及显式的app选择(方式一)仍然优先于这个默认值。

一旦启用,任何会话里普通的browser.open(...)调用都会驱动你的真实浏览器——包括你没有正在观看的后台会话。这里有一个值得留意的副作用(README 原话):如果不带app.target,这样的调用会采纳当前可见的标签页;而如果调用携带了url,它会把这个标签页导航离开你正在阅读的内容。因此在开启默认模式前,请确认这对你的日常浏览体验是可接受的。

目标选择与 "omp" 标签组

选择哪个标签页:通过app.target按 URL/title 的子串匹配来指定具体标签页;不提供时,omp 采纳当前可见的标签页且不抢焦点。对应到 relay 协议层,扩展在 background.ts 中通过activateTabRPC 实现焦点与激活切换。

标签页分组管理:这正是 CHANGELOG 17.2.5 提到的"自动、健壮的标签页管理"。omp正在主动驱动的标签页会被收集进每个窗口的"omp" 标签组(青色),当 omp 释放该标签页时分组被解除,断开连接时分组合部解散。其余标签页、固定标签页(pinned)、你自己创建的组、以及你手动拖出的标签页都不会被触碰。可以在omp browser-relay时加--no-group禁用该行为。

分组逻辑的健壮性在源码里有充分体现:

  • 扩展端把"查询→分组→设标题"这一非原子序列串行化(enqueueGroupOp,见 background.ts),避免并发竞态产生重复的 "omp" 组,并会"愈合"历史竞态留下的同标题重复组;
  • 固定标签页永远不会被分组(Chrome 分组会静默取消固定);
  • relay 端通过groupOptOut机制尊重用户意愿:如果你手动把标签页拖出 omp 组,relay不会再把它组回去,也不会与用户对抗(见 bridge.ts 的#onTabUpsert逻辑)。

自动启动:全局 daemon broker 与租约机制

不需要手动运行 relay——当 Eval 的 browser API 第一次需要它时,relay 会在 omp 的profile 无关的全局 daemon broker下自动启动。实现细节在 daemon.ts:

  • 由于 MV3 扩展只能向外拨号(service worker 无法监听 socket),必须有一个原生进程持有 relay 端口,这个进程就由 broker 拉起;
  • 每个 relay consumer 都持有 broker 租约(lease),因此一个项目退出不会中断另一个项目;只有当所有项目的最后一个 consumer 退出后,服务才会停止;
  • 如果某个 relay 已经手动占用了端口,consumer 会采纳现成的服务而不会争夺绑定;
  • 启动是幂等且可自愈的:先探测http://<cdpUrl>/json/version,若返回 503(等待扩展)或 2xx 即视为就绪;发现"记录在案但无响应"的僵死 daemon 会替换重启,跨进程启动竞争则通过最多 3 轮"探测→描述→启动"收敛。

扩展连接后,工具栏 badge 会显示on(对应源码中 background.ts 的setBadge:绿色 "on" / 灰色 "off")。

omp browser-relay命令行参数

该命令在 cli-reference.md 中登记为:"运行 Eval 的 browser API 用来驱动你自己的 Chrome 标签页的本地 CDP relay"。日常使用中你通常不需要手动运行它,只在以下三种情况才需要:

参数作用
--token <secret>/ext端点设置共享密钥,扩展在设置页中填入相同 token 后以?token=形式携带;用于防止本机不可信进程驱动你的已登录浏览器
--no-group禁用 "omp" 标签组分组行为
--port <port>指定非默认端口(扩展默认连接 9224,见 background.ts)

relay 服务器只绑定loopback(127.0.0.1),并在握手层做了两道防线(见 server.ts):/cdp拒绝带Origin头的升级请求(防止网页驱动 relay),/ext只接受chrome-extension://来源并校验 token。

扩展内部实现:一个"哑管道"式的 MV3 Service Worker

扩展的设计哲学在 background.ts 的注释里写得很直白:按设计保持哑管道(dumb pipe),所有 CDP 编排逻辑都放在 relay 服务器侧。service worker 只做三件事:

  1. 保持一条到 relay 的 WebSocket;
  2. 执行 relay 下发的 RPC(attachdetachsendcreateTabremoveTabactivateTabgroupungroup,对应 protocol.ts);
  3. chrome.debugger事件和标签页增删改事件流式推回。

针对 MV3 service worker 的生命周期问题,扩展做了三重保活与恢复设计:

  • 连接期间:打开状态的 WebSocket 本身 + 每 20 秒一次的ping(Chrome 116+ 支持);
  • 断开被回收后:chrome.alarms每 0.5 分钟触发一次connect()重新拨号(background.ts);
  • 重连采用指数退避(1 秒起步、上限 10 秒),并对 relay 主动发起的 detach 与用户取消(如关闭调试 infobar)做了区分,避免把替换 socket 误判为用户操作;
  • 分组标题写入chrome.storage.session,即使 service worker 重启后仍能正确解散 omp 组;
  • 监听chrome.storage.local变化:设置页修改端口/token 后立即断开并用新参数重拨。

每次连接时,扩展通过hello消息上报浏览器版本、全量标签页快照和当前已附加的标签页 ID,relay 据此做状态对账,并在 service worker 重启丢失附加后尽力恢复持有会话的标签页附加(见 bridge.ts)。

协议与多路复用细节

对下游 puppeteer 客户端而言,bridge 模拟了这些行为(详见 bridge.ts):

  • Browser.getVersionTarget.getBrowserContexts等浏览器级命令由 bridge 直接应答;
  • Target.setDiscoverTargets/Target.setAutoAttach/Target.attachToTarget/Target.createTarget/Target.closeTarget/Target.activateTarget等被转译为对扩展的 RPC;
  • Browser.close会被拒绝并忽略——relay 绝不关闭用户的真实浏览器;
  • 会话 ID 有明确命名空间:ST<tab>.<conn>.<n>为 minted tab 伪会话(仅用于满足 Target 层级)、SP<tab>.<conn>.<n>为 minted page 伪会话(转发到标签页根 debugger 会话)、OOPIF/worker 等真实子会话则原样透传;
  • Runtime 域做了状态机管理(default/enabled/disabled),保证多个下游连接共享一个根Runtime.enable循环,并对新启用者重放已存在的 execution context。

限制与安全边界

以下是官方 README 明确列出的限制,使用前务必知晓:

  • chrome://、DevTools、Web Store 以及其他扩展页面不可附加,对 agent 完全隐藏(对应 bridge.ts 中的不合法 URL 正则);
  • 只要有任何标签页被附加,Chrome 就会显示 "is debugging this browser" 的提示条;关闭该提示条会分离标签页,直到该标签页再次导航才会恢复;
  • 打开了 DevTools 的标签页无法附加(每个标签页只允许一个 debugger,这正是 relay 要为自身客户端做多路复用的原因);
  • 安全上,任何能访问 relay 端口的东西都能驱动你的已登录浏览器,因此 relay 只绑定 loopback;若本机存在不可信进程,请务必使用--token

开发与验证:构建与端到端冒烟

对于想参与开发或自行验证的读者,package.json 与 README 的 Development 一节给出了两条命令:

  • bun run build:将扩展打包到dist/extension/,压缩出用于发布的 zip,并重新生成 omp CLI 内嵌的安装资产(位于 packages/coding-agent/src/tools/browser/relay/extension-assets/),这些资产需要提交;
  • bun scripts/smoke.ts [relay-url] [target-substring]:端到端冒烟测试,完整复刻 omp 的 supervisor + tab worker 双连接模式:先通过browserURL建立 supervisor 连接并发现目标,再通过browserWSEndpoint建立 worker 连接按 ID 采纳目标,随后依次执行evaluatePage.getFrameTree(额外 CDP 会话)、goto导航、screenshot截图,以及Target.createTarget/closeTarget新建与关闭标签页的路径,最后断开两条连接并打印SMOKE OK

结合 CHANGELOG.md 的演进记录可以看到,browser relay 从 17.2.5 的"首版 MV3 扩展 + omp 标签组管理",到 18.0.7 的"opt-in 路径范围澄清",其核心价值始终稳定:让 coding agent 安全、可配置地接管你日常使用的真实浏览器,而不是在隔离环境里另起炉灶。

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 15:22:38

AI如何用多模态技术重构学术PPT制作

1. 项目概述&#xff1a;AI如何重构学术汇报体验虎贲等考AI PPT功能正在颠覆传统学术汇报的制作模式。这个工具的核心价值在于将复杂的学术内容结构化、可视化&#xff0c;同时大幅降低制作门槛。想象一下&#xff0c;以往需要花费数小时调整格式、设计排版的PPT&#xff0c;现…

作者头像 李华
网站建设 2026/9/12 15:21:44

前端UMD模块方案:实现跨环境兼容的JavaScript库

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 15:19:56

预训练模型微调:知识迁移与高效实践

1. 预训练与微调的技术演进脉络预训练语言模型的发展经历了从静态词向量到动态上下文表示的重大跨越。早期的Word2Vec、GloVe等模型只能生成静态词向量&#xff0c;无法处理一词多义现象。2018年诞生的BERT首次展示了大规模预训练的威力&#xff0c;通过掩码语言建模&#xff0…

作者头像 李华
网站建设 2026/9/12 15:18:21

H3502高压降压芯片:100V输入高频小体积电源设计指南

1. 项目概述&#xff1a;为什么H3502在高压降压场景中成了“小体积高频方案”的代名词 我第一次在工业现场看到H3502&#xff0c;是在一台户外光伏汇流箱的辅助电源板上——输入电压标称96V&#xff08;实测波动范围85–105V&#xff09;&#xff0c;要稳定输出12V/2A给PLC和无…

作者头像 李华
网站建设 2026/9/12 15:17:08

PHP闭包、生成器与属性三大特性深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 15:14:07

SSM二手车交易网站毕业设计:从启动到权限隔离的完整实战解析

简介&#xff1a;基于SSM框架的Java毕业设计项目——二手车交易网站完整源码包&#xff0c;面向计算机专业毕业生和Java Web开发者&#xff0c;可作为毕业设计选题、系统开发参考或项目实训。系统采用JSPJavaMySQL开发&#xff0c;B/S架构&#xff0c;设计有管理员、用户和前台…

作者头像 李华