Chrome 浏览器扩展 + DeepSeek Harness 插件,让 AI Agent 直接操控你的真实浏览器。
50.5/100
综合分
42
GitHub 星标
1,592
npm 周下载
—/5
用户评分
数据截至 2026/10/25 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add @angelky7/dsh-browser-controlnpm 源 · @angelky7/dsh-browser-control 的发布者账号已校验与本仓库一致
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · browser
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 9 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包@angelky7/dsh-browser-control @ 1.2.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 22:55:41
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件
查看扫描证据(共 20 处,展示前 20 条)
- 写入本地文件lib/index.js:248
await mkdir(options.shotsDir, { recursive: true }); - 读取本地文件lib/index.js:249
const shotsEntries = await readdir(options.shotsDir, { withFileTypes: true }); - 删除本地文件lib/index.js:253
await rm(path.join(options.shotsDir, entry.name)); - 读取本地文件lib/index.js:257
const scratchEntries = await readdir(scratchDir, { withFileTypes: true }).catch(() => []); - 删除本地文件lib/index.js:261
await rm(path.join(scratchDir, entry.name)); - 写入本地文件lib/index.js:1180
await mkdir(dir, { recursive: true }); - 写入本地文件lib/index.js:1185
await writeFile(file, buffer); - 写入本地文件lib/index.js:1202
await mkdir(path.dirname(file), { recursive: true }); - 写入本地文件lib/index.js:1204
await mkdir(dir, { recursive: true }); - 写入本地文件lib/index.js:1211
await writeFile(file, buffer); - 写入本地文件lib/types/index.js:296
await mkdir(dir, { recursive: true }); - 写入本地文件lib/types/index.js:301
await writeFile(file, buffer); - 写入本地文件lib/types/index.js:319
await mkdir(path.dirname(file), { recursive: true }); - 写入本地文件lib/types/index.js:322
await mkdir(dir, { recursive: true }); - 写入本地文件lib/types/index.js:329
await writeFile(file, buffer); - 写入本地文件lib/types/server.js:56
await mkdir(options.shotsDir, { recursive: true }); - 读取本地文件lib/types/server.js:57
const shotsEntries = await readdir(options.shotsDir, { withFileTypes: true }); - 删除本地文件lib/types/server.js:62
await rm(path.join(options.shotsDir, entry.name)); - 读取本地文件lib/types/server.js:66
const scratchEntries = await readdir(scratchDir, { withFileTypes: true }).catch(() => []); - 删除本地文件lib/types/server.js:71
await rm(path.join(scratchDir, entry.name));
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/dsh-invariants@deepseek-ai/dsh-settings@deepseek-ai/dsh-tools给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
界面预览
1 张 · 点击查看大图功能亮点
- AI操控真实浏览器
最近更新
在 GitHub 查看全部 →v1.2.02026-10-30
· v1.2.0
新工具 browser_cookies(读/设/删 cookie,roadmap 1.1.0 第 3 条,零新权限)。
这一版改了 extension/——扩展必须重装(新增了 cookie 三条命令);插件也要更新到 1.2.0。
· browser_cookies
action: "get" | "set" | "remove",用途是复制登录态、清理站点状态、跨标签共享会话——BrowserSkill 明确没有的能力。
· 三条扩展命令,不是一条带 action:cookies.get / cookies.set / cookies.remove。写/读分类与只读闸门都按命令名判,三条各有名字,对账台才盯得住。
· get:Network.getCookies(urls:[tab.url]),只回这一页可见域的 cookie(count === total);domain 参数做子串过滤、大小写不敏感。值原样进模型可见文本——cookie 值就是凭据(session token 也在里面),这是这条工具的定义(复制登录态靠它),不是副作用;SECURITY.md 中英都已写明「敏感级别等同页面密码」。
· set:需要 url 或 domain 锚点(都缺直接报错,一次 CDP 都不发);sameSite 只收 Strict/Lax/None;expires 是 Unix 秒、省略即会话 cookie。浏览器拒绝(success:false)时如实报错并给常见原因(Secure 配了 http 锚点、domain 与页面不同源、SameSite=None 没开 secure),不假装成功。
· remove:CDP 的 deleteCookies 不回执删没删到——按同一片可见范围复查一次,remaining 如实报(>0 时 left 列出还剩哪颗在哪个域);复查失败报 remainingChecked:false,不假装删干净。
· 分类按既定判据:cookies.set / cookies.remove 是幂等的(重设同一颗、重复删同一颗,结果不变),所以 effectState 按「重试会不会造成额外损害」算只读;但它们改浏览器状态,所以只读档(readOnly: true)拒。cookies.get 进只读白名单(读浏览器状态,无副作用)。
· 工具面按 action 分发到三条命令,三条各写一个字面量调用点——verify_surface 对账的是 controller.execute('命令名') 字面量,动态拼名字会让「扩展实现了但 agent 拿不到」那条断言瞎掉(实现时它当场抓到了第一版)。
· 验证
· npm run verify 575 项断言,exit 0(548 → +20 cookie 行为台、+3 策略成对断言、+2 render 契约、+2 数量对账)。
· 新台 verify_cookies.mjs(20 项):假件按真 CDP 响应形状回(Network.getCookies 的 cookies 在顶层,不是 Runtime.evaluate 那种 {result:{value}} 信封——套错信封的假件测不出真行为),断言 CDP 参数逐字段透传、锚点缺失零 CDP 派发、浏览器拒绝不假成功、同名多颗只删锚点匹配的那颗、复查失败不假报删干净。
· verify_render_contract 铺满 22 条工具:cookie 的名字与值都必须出现在模型可见文本里(不许只报「N cookies」的计数——那是 render 只写摘要的老毛病)。
· 变异测试:把 cookies.get 踢出只读白名单 → policy 红;remove 复查造假(永远报 remaining:0)→ 2 红(正好暴露「还剩 .shop.test 那颗」被谎报成删干净)。
· 安装
dsh plugin --profile web add @angelky7/dsh-browser-control@1.2.0
· 撞上 ERR_PNPM_NO_MATCHING_VERSION(镜像滞后)时,这一次显式走官方源:
dsh plugin --profile web add @angelky7/dsh-browser-control@1.2.0 --registry=
ERR_PNPM_NO_MATURE_MATCHING_VERSION 是 24 小时包龄闸门,不是包坏了——判别见 README。
扩展:解压 DSH-Browser-Control-v1.2.0.zip → chrome://extensions → 开发者模式 → 移除旧版(或点扩展卡片上的刷新)
v1.1.02026-10-24
· v1.1.0
这一版只做一件事:npm 包名随账号改名迁移。插件代码、扩展代码与 v1.0.19 完全相同,没有功能变更。
· 包名变更
GitHub 账号已由 caob23 改名为 angelky7,而 npm 的用户名无法修改,因此新建同名组织 angelky7 承接 scope。
| | 旧 | 新 |
|---|---|---|
| npm 包名 | @caob23/dsh-browser-control | @angelky7/dsh-browser-control |
| 安装命令 | dsh plugin --profile web add @caob23/dsh-browser-control | dsh plugin --profile web add @angelky7/dsh-browser-control |
· 旧包在 npm 上保留,但已 npm deprecate,安装时会提示去向
· 也评估过去掉 scope 的 dsh-browser-control、dsh-browser-bridge 等名字,均已被他人占用,最终回到带 scope 的方案
· 升级步骤(装过旧版的用户)
dsh plugin --profile web remove @caob23/dsh-browser-control
dsh plugin --profile web add @angelky7/dsh-browser-control
profile 覆盖层里手写过 name: '@caob23/dsh-browser-control' 的配置需一并更新;只写 id 的不受影响(宿主合并按 id 认)。
· 扩展不用重装
extension/ 未改动,DSH-Browser-Control-v1.0.19.zip 仍是当前版本,继续用它即可。
· 安装
dsh plugin --profile web add @angelky7/dsh-browser-control@1.1.0
· 撞上 ERR_PNPM_NO_MATCHING_VERSION(镜像滞后)时,这一次显式走官方源:
dsh plugin --profile web add @angelky7/dsh-browser-control@1.1.0 --registry=
ERR_PNPM_NO_MATURE_MATCHING_VERSION 是你机器上的 24 小时新包门槛,不是包坏了——判别与三条绕法见 README。
· 资产
| 资产 | 说明 |
|---|---|
| dsh-browser-control-plugin-v1.1.0.zip | 插件离线包;解压后 dsh plugin --profile web add file: |
扩展资产不重复发布,仍见 v1.0.19。
· 资产校验和
| 资产 | 大小 | SHA-256 | MD5 |
|---|---|---|---|
| dsh-browser-control-plugin-v1.1.0.zip | 113 341 B | 2af8aadf04071f399c00ccf5dfb1356aeea9849baf6cdb4c2938a9c4046c789d | 2c2d4fd7b83ee48e1f38ccd71820f519 |
发布前本地解包复验:zip 头 504b0304、CRC 全过、无反斜杠条目、含 package.json 与 cordis.patch.yml、package.json 的 name 为 @angelky7/dsh-browser-control。
v1.0.192026-10-20
· v1.0.19
一个外部 PR 带来新工具 browser_hold(接管浮层),加上合并后复审抓到的四处问题。这一版改了 extension/,扩展必须重装。
· 1. 接管浮层:browser_hold(合并 PR #18,@long-arm-ape)
给某个标签页加一层可撤销的提示层:页面变暗,中间一张卡片写明模型在做什么,挡住误触。定位是告知 + 防误触的软层,不是安全边界——桥的 token 模型读得到也改得动;真正能冻住浏览器的是 v1.0.18 的弹窗「锁定」。
· 标题由扩展写死(DSH Browser Control),调用方只能给正文 note(压平换行、截到 400 字符)。否则模型能写一句系统口吻的话冒充提示。
· 关掉 = 用户接管,不拦模型:双击任意处 / 连按两下 Esc / 按住 Esc ≈0.6 秒。关掉之后模型照常操作这一页。
· 卡片上的「中止模型操作」才拦:两次点击确认(第二次 3 秒内),之后 click / input / press / nav 在扩展的 runCommand 入口被拒,零 CDP 派发。模型要恢复必须先与用户确认,再调 browser_hold action=off——那一步等于「确认继续」。
· 状态在 chrome.storage.session、按 tabId 记:活过 service worker 回收(内存标志 30 秒就丢,那正是浮层「以为挡着、其实没挡」的失败方式),不落盘,浏览器关掉即清。
· 盖不住就如实说:covered:false + reason(error-page / browser-page / devtools / inject-failed)。已知盖不住:严格 CSP、全屏、跨源 iframe、PDF 阅读器、原生弹窗。
· 导航即消失:页面换了浮层就没了,此时命令放行、存储里那条顺手清掉、status 如实报 active:false。
· 模型的错误面也接上了同一套线协议:中止拒绝的前缀 browser-hold-aborted: → code=held_by_user、effectState=not_started,提示指向 browser_hold action=off,而不是「换个选择器重试」。
· 2. 合并后复审抓到的四处
1. 模型自己的点击被自己的浮层吃掉。 浮层全屏、z-index 最大,click 按坐标派发先命中的是它——页面什么都没发生,结果只轻描淡写一句 hitVerified:false;更糟的是同一坐标连点两下会被浮层的「双击接管」逻辑当成用户操作,以用户的名义把浮层关掉。现在命中到自己那层时临时把宿主设成 pointer-events:none、重测命中点、派发完在 finally 里恢复,结果带 bypassedOwnOverlay:true。浮层挡的是人,不是模型。
2. AX 快照把浮层自己编进去了。 卡片上的「中止模型操作」是标准 button,会进无障碍树:模型读到的快照里就有自己挂的提示语,甚至能按 ref 点到它。现在 stamping 函数遇到 [data-dsh-hold] 子树直接跳过:不占 ref、不计入 total(ax.ownOverlay 单独计数)。DOM 模式原本就排除了,这次补齐 AX 模式。
3. hold on 会把「中止」静默清掉。 模型被拦一次之后只要再 on 一次就绕过去了,既不用问用户也不必说「继续」。现在中止期间 hold on 被拒,只有 off 能解。
4. 只读档把 hold status 也拒了。 status 只读(读 session 条目 + 探一下页面那层还在不在),不是写操作;「只读」不该连看一眼浮层状态都不让。闸门改为按动作判:policyRefusal(command, flags, params),on / off 仍拒、status 放行。
· 3. 验证
· npm run verify 548 项断言,exit 0(535 来自 PR #18 与合并,+13 是本轮的台子):浮层台 44→52、AX 台 18→22、策略台 41→42。
· 点击旁路那条不是断言假件返回值:台子里有一台真的执行定位表达式的假 DOM,浮层在场时 elementFromPoint 先返回宿主,宿主 pointer-events:none 之后才返回目标。
· 四处修法各自做过变异测试:摘掉 AX 排除 → 4 项红(快照里真的出现「中止模型操作」);去掉 pointer-events 旁路 → 2 项红(hitVerified:false, hitInstead:"div");去掉中止检查 → 2 项红(hold on 成
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。
README
由 DeepSeek 最新模型翻译生成DSH Browser Control
简体中文 · English
Chrome 浏览器扩展 + DeepSeek Harness 插件,让 AI 智能体像人一样操控你的真实浏览器。
这是什么
不是无头浏览器,不是 Puppeteer——是你的真实 Chrome,带着你的登录态、你的 cookies。AI 通过 Chrome DevTools Protocol 驱动标签页,你可以在屏幕上看到每一步操作。
你对 AI 说一句话 ↓ Agent 调用 browser_* 工具 ↓ DSH 插件(WebSocket 桥) ↓ Chrome 扩展(CDP 驱动) ↓ 你的真实浏览器执行操作 ↓ 结果返回给 Agent
和 MCP 浏览器方案的区别
市面上已经有 Playwright MCP、Puppeteer MCP、browser-use 等,它们的共同点:启动一个自己下载的全新浏览器实例。
展开完整文档(README 剩余 1 节)
DSH Browser Control
简体中文 · English
Chrome 浏览器扩展 + DeepSeek Harness 插件,让 AI 智能体像人一样操控你的真实浏览器。
这是什么
不是无头浏览器,不是 Puppeteer——是你的真实 Chrome,带着你的登录态、你的 cookies。AI 通过 Chrome DevTools Protocol 驱动标签页,你可以在屏幕上看到每一步操作。
你对 AI 说一句话 ↓ Agent 调用 browser_* 工具 ↓ DSH 插件(WebSocket 桥) ↓ Chrome 扩展(CDP 驱动) ↓ 你的真实浏览器执行操作 ↓ 结果返回给 Agent
和 MCP 浏览器方案的区别
市面上已经有 Playwright MCP、Puppeteer MCP、browser-use 等,它们的共同点:启动一个自己下载的全新浏览器实例。本项目走的是另一条路:
| | 本项目 | Playwright / Puppeteer MCP |
| 浏览器 | 你正在用的真实 Chrome | 自动下载的独立实例 |
| 登录态 / Cookies | ✅ 全部继承,无需重新登录 | ❌ 每次全新 profile |
| 过验证码 / 扫码登录 | 你的会话已经登录,基本不遇到 | 经常卡在登录墙 |
| 可见性 | 屏幕上实时可见,agent 新建的标签自动归进 DSH 分组,随时鼠标接管 | 无头运行或独立窗口 |
| 环境依赖 | 无需 Node / npx / Python | 需要 npx 或 uvx 运行时 |
| 接入方式 | 加载扩展 + 设置页开关 | 编辑 MCP 客户端 JSON 配置 |
| 磁盘占用 | 复用现有 Chrome,零新增 | 额外下载数百 MB 浏览器 |
| 集成深度 | dsh 原生插件(状态页 / 清理按钮;设置页卡片由宿主版本决定,见下) | 通用 MCP server |
一句话:要 AI 用「你自己的」浏览器干活(已登录的 B 站、知乎、淘宝后台),用本项目;要做跨浏览器、跨应用的通用自动化测试,用 MCP。
下载
| 文件 | 说明 |
| DSH-Browser-Control-v1.0.19.zip | Chrome 扩展(解压后加载;扩展自 v1.0.19 起未变更,v1.1.0 只是包名迁移,扩展仍用这一版) |
| dsh-browser-control-plugin-v1.1.0.zip | dsh 插件(离线兜底,在线装直接用方式 A/B) |
安装 Chrome 扩展(30 秒)
下载 zip → 解压到固定文件夹(别删)→ Chrome 打开 chrome://extensions → 开启「开发者模式」→ 点「加载已解压的扩展程序」→ 选解压后的文件夹。
工具栏出现鲸鱼图标 → 绿点呼吸 = 已连接。需要 Chrome 116+。
安装 dsh 插件
📦 本包是 bundle 包(package.json 中 dsh.bundle.patch 指向 cordis.patch.yml)。dsh plugin 安装成功后会自动把它加入 profile 的 dsh.profile.bundles,重启即加载。
前置:dsh plugin 转发给 pnpm,需要 pnpm 在 PATH 上;首次使用会自动初始化目标 profile。
方式 A:从 npm 安装(推荐)
通过 dsh plugin 从 npm registry 安装并自动注册到 profile
dsh plugin --profile web add @angelky7/dsh-browser-control
如果自行管理 profile 的 node_modules,也可以在对应目录中直接使用 npm 安装:
npm install @angelky7/dsh-browser-control
刚发布的新版本可能一时装不上,那不是插件坏了。 dsh plugin add 会把依赖钉成确切版本号,而 pnpm 用的是你自己配置的源——国内默认常常是 registry.npmmirror.com,它同步官方源有延迟(实测 1.0.10 在官方源已发布时,镜像的 latest 还停在 1.0.8)。撞上 ERR_PNPM_NO_MATCHING_VERSION ... while fetching it from https://registry.npmmirror.com/ 时有三条路:
1. 这一次显式走官方源:dsh plugin --profile web add @angelky7/dsh-browser-control@<版本> --registry=https://registry.npmjs.org/
2. 用 Release 里的离线包 dsh-browser-control-plugin-v<版本>.zip,解压后 dsh plugin --profile web add file:<解压目录>
3. 等镜像同步后重试原命令:curl -s https://registry.npmmirror.com/@angelky7/dsh-browser-control,看到该版本、且 dist-tags.latest 也跟上即可
另一种装不上长得像、原因完全不同,别改 registry。 dsh 的 profile 自带 24 小时「包龄」供应链闸门(node_modules/.pnpm-workspace-state-v1.json 里的 minimumReleaseAge: 1440)。发布未满 24 小时的版本被它拦下时报的是 ERR_PNPM_NO_MATURE_MATCHING_VERSION,而且报文里会直接写 was published at …, within the minimumReleaseAge cutoff (…)——版本是存在的,只是太新。这种只有等满 cutoff 时刻这一条路(改 registry、离线包都不必)。两个码的判据:NO_MATCHING_VERSION = 你配置的源里没有这个版本;NO_MATURE_MATCHING_VERSION = 有,但没满 24 小时。
方式 B:从 GitHub 或本地目录安装
直接从 GitHub 安装
dsh plugin --profile web add "github:angelky7/dsh-browser-control#v1.1.0"
本地目录调试(注意:必须显式 file: 前缀)
dsh plugin --profile web add "file:D:\path\to\dsh-browser-control"
重启 DSH 后生效。卸载:
dsh plugin --profile web remove @angelky7/dsh-browser-control
⚠️ 本地目录请用 file: 前缀。裸路径 / 相对路径会被 pnpm 当作 link: 协议,在 hoisted 布局下不会物化到 node_modules 顶层,导致启动时无法解析该包。
安装并重启后,桥接默认开启(v1.0.6+),不需要再去设置里手动启用。状态页 http://127.0.0.1:9777/ 可看到服务已监听。
想关掉默认开启:在你的 profile 覆盖层 $DSH_HOME/profiles/<名字>/cordis.patch.yml 里写
- id: browser-bridge + config: { enabled: false } 即可(写法见 dsh-config/README.md)。
注意包内 cordis.patch.yml 里那份 enabled: true 不要改回 false —— 那会盖掉 schema 默认值,表现为装上后 9777 无人监听(issue #4)。
方式 C:复制进 harness 源码树(旧方式,v1.0.2 及以前)
git clone https://github.com/angelky7/dsh-browser-control.git
cd dsh-browser-control
git checkout v1.0.2 # 旧布局在 v1.0.2 tag
./install.sh /你的路径/deepseek-harness
脚本只负责把插件文件复制到位,完成后仍需手动改三处配置,改完重启 dsh 才会生效:
下载 dsh-browser-bridge-plugin-v1.0.2.zip,解压到 deepseek-harness 的 packages/web/browser-bridge/。
然后补充三处配置:
1. packages/bundle/base/package.json 的 dependencies 加:
"@deepseek-ai/dsh-browser-bridge": "workspace:^"
2. cordis.patch.yml 的 plugins 列表加:
- id: browser-bridgeyaml
name: '@deepseek-ai/dsh-browser-bridge'
config:
enabled: false
3. 在 tsconfig.host.json 的 references 里加上: json { "path": "./packages/web/browser-bridge" }
重启 dsh。详细说明见 dsh-config/README.md(注意这条路径针对 v1.0.2 及以前的旧布局,当时默认就是 enabled: false)。
使用
1. 装好即默认开启(v1.0.6+),不需要手动启用
2. Chrome 扩展自动连接(端口 9777,Token 默认 dsh-local)
3. 对话说自然语言,智能体自动操控浏览器
「设置 → 插件」里有没有这张卡片,取决于宿主版本(issue #5)
npm 发布的 bundle 只含宿主侧 lib/index.js,没有浏览器端模块,所以卡片不是插件自己画的:
| 宿主 | 设置页 | 改配置的办法 |
| dsh 0.1.7+ / 0.2.x(dsh-settings 0.1.7-rc.2 起) | 有——宿主按插件自身 Config schema 自动投影出这一节 | 设置页,或配置档覆盖层 |
| dsh 0.1.2 及更早 | 没有条目(没有客户端半区认领命名空间,宿主就不渲染) | 只能改配置档覆盖层 $DSH_HOME/profiles/<名字>/cordis.patch.yml |
两边都能改的就是配置文件,写法见 dsh-config/README.md。
访问 http://127.0.0.1:9777/ 查看连接状态。
不想让它点,只想让它看:只读档与脚本开关
在配置档覆盖层里给 browser-bridge 配两项(完整写法见 dsh-config/README.md): yaml config: readOnly: true # 只读:点击/输入/按键/导航/滚动/标签页操作/视口模拟全拒 allowScript: false # 再把 browser_evaluate(在页面里跑任意 JS)关掉
被拦的命令不会发到浏览器(零副作用),错误码 blocked_by_policy,文案写明改哪个字段。
注意 readOnly 单独打开不等于拿掉了任意脚本能力:browser_evaluate 能做其它工具能做的所有事,所以「能不能执行脚本」是单独一项。这两个开关只管模型那条工具面,HTTP 面(带 token)不受影响。
智能体开的标签长什么样(自动归进 DSH 分组)
智能体新建的标签页会自动收进当前窗口的一个 DSH 蓝色标签分组里(每个窗口一组),所以你扫一眼就知道哪些页面是机器开的、哪些是自己开的,事后也能一把清掉:
- browser_tabs action: "ungroup" 拆掉本窗口的组(带 windowId 只拆那一个窗口,不带则所有窗口)——只拆标签归属,不关标签。
- browser_tabs action: "open" 加 group: false 可以显式让新标签留在组外;action: "group" 能把早就存在的散标签拉进来。
- 归组是锦上添花:Chrome 版本太旧、权限没给、或刚建标签就被用户拖动导致失败时,开标签本身照常成功,结果里带 grouped: false 和原因。分组动作不改页面内容,重试安全。
- browser_tabs action: "close" 一次可以关一个(tabId)或一批(tabIds);一批在链路上只发一条命令。结果把每个 id 的去向都写出来:closed / alreadyGone(早就没了=幂等成功,重试安全)/ failed(带原因)——部分失败不会被吞掉,单数与批量同一个形状。
一键冻结:扩展弹窗里的「锁定」
点扩展图标,按钮行中间那个「锁定」,单击即生效:此后扩展对模型拒绝一切浏览器操作(点击、输入、按键、导航、执行脚本全拦),而 WebSocket 连接照常——调用方看到的是「连得上但被冻结」,不是掉线,所以不会误当作网络问题去重试。
- 解锁只有一条路:在同一个弹窗里点「已锁定」。桥接侧没有任何解锁命令,模型的工具面里也没有。
- 冻结状态落在 chrome.storage.local,所以 MV3 把 service worker 回收掉也不会「自己解冻」。
- 万一读不出这个状态,扩展按「已冻结」处理(fail-closed):一个以为锁着、其实没锁的 panic switch 等于没有。这时拒绝文案与弹窗都会写「锁状态读不出来」,不会说成「已被用户锁定」,而你照样能在弹窗里点一下把状态写明确。
- 图标徽标在上锁期间显示红色 LOCK,不会继续显示绿色的 ON 骗人。
- 为什么客户端而不是桥接侧管这件事:桥的 token 就写在配置档的 cordis.patch.yml 里,模型读得到也改得动;把「冻结」放在浏览器里、且只留一个人工通道,才真的挡得住。
用脚本直连 HTTP(curl 等)
/api/command 与 /api/cleanup 现在要求 Token,用的就是扩展连 WS 时那个值: bash
curl -X POST http://127.0.0.1:9777/api/command \
-H 'Authorization: Bearer <你的 token>' \
-H 'Content-Type: application/json' \
-d '{"command":"nav","params":{"url":"https://example.com"}}'
也可以写 ?token=<你的 token> 或 X-Token: <你的 token>。不带、或带错,一律 401;/ 与 /api/status 仍是免鉴权的只读信息。之前「不带 Token 也能调通命令面」的行为已经失效(issue #3 / #6)。状态页上的清理按钮会要求你把 Token 输一次,只记在浏览器会话里。
工具清单
| 工具 | 功能 |
| browser_navigate | 导航到 URL |
| browser_read | 读取页面文本/HTML,正文直接给模型(offset/limit 窗口,长文分页) |
| browser_snapshot | 页面快照 → 逐条列出 ref 的交互树(mode:"ax" 走 Chrome 无障碍树,拿 role + 可访问名) |
| browser_click | 点击元素(by ref / selector) |
| browser_type | 在输入框填入文本 |
| browser_press | 模拟键盘按键(回车、Tab、方向键,以及 "Ctrl+A" / "Shift+ArrowRight" 这类组合键;一次按键只插入一次) |
| browser_scroll | 滚动页面 |
| browser_wait | 等元素出现 / 等文本出现 / 等条件为真(最长 120 秒,v1.0.9+) |
| browser_find | 按 CSS 选择器查元素,返回数量与位置尺寸(只读,v1.0.9+) |
| browser_dialog | 读改原生弹窗应答策略 accept/dismiss/manual,并回最近弹窗记录(v1.0.9+) |
| browser_hold | 在某个标签页上加/撤一层可取消的接管浮层(告知用户 + 防误触);covered:false 时说明盖不住的原因。软层,不是安全边界 |
| browser_tabs | 标签页管理(列表/新建/关闭/切换/归组/拆组;见「智能体开的标签长什么样」) |
| browser_evaluate | 执行任意 JS |
| browser_screenshot | 截取页面截图 |
| browser_console_log | 抓取页面 console 日志并逐条给出正文(v1.0.7+) |
| browser_network_log | 抓取 HTTP 请求/响应并逐条给出方法/状态/URL(v1.0.7+) |
| browser_network_clear | 单独清空网络日志缓冲(v1.0.7+) |
| browser_pdf | 当前页导出 PDF(v1.0.7+) |
| browser_emulate | 切设备视口(移动 / 桌面 / 自定义,v1.0.7+) |
| browser_cleanup | 清理临时文件 |
| browser_info | 报告实际连上的浏览器与扩展版本(排障先跑它,v1.0.9+) |
共 21 个工具。browser_wait / browser_find / browser_dialog / browser_info 在 v1.0.8 及以前是「扩展里已实现、但没注册成工具」,智能体调不到;browser_network_clear 则是代码里有、这张表漏了。这四条现在由 verify/verify_surface.mjs 做三方对账(扩展命令表 ↔ 插件调用 ↔ 文档表 ↔ 构建产物),漂移会直接让 npm run verify 失败。
架构
Chrome 浏览器 └─ DSH Browser Control 扩展 (MV3) └─ chrome.debugger (CDP) └─ WebSocket ──────→ DSH 插件 (browser-bridge) └─ browser_* 工具 → Agent
关键设计:
- 扩展主动外连桥(不需要 native messaging host)
- 默认开启(v1.0.6+),装上即监听,不需要手动启用
- 持久 debugger 附着——控制期间横幅始终显示
- 仅监听 127.0.0.1;命令面(WS 与 HTTP)共用同一个 Token,跨源一律不放行
- 协议版本独立于版本号:帧契约变了才升,不匹配时状态页直接写出该升级哪一侧
已验证
| 场景 | 结果 |
| 百度搜索 → 提取结果标题 | ✅(1.0.x 时期实机) |
| B 站搜索用户 → 发私信 | ✅(1.0.x 时期实机) |
| B 站搜索 → 统计视频卡片 + 截图 | ✅(1.0.x 时期实机) |
| 实测台 npm run verify:配置解析、三种宿主形状、HTTP 鉴权与升级来源、发布产物行为 | ✅ 2026-10-10,见 verify/README.md |
| 实测台 verify_tab_groups:智能体标签归组的建组 / 复用 / 退避重试 / 缓存失效 / 按窗口拆组 / 无权限降级 | ✅ 2026-10-11,node:vm + 有状态假 chrome.tabs/chrome.tabGroups,未在真实 Chrome 里重跑 |
| 实测台 verify_extension_e2e:真桥 + 真扩展代码 + 真 WebSocket 端到端(帧契约、命令可达、错误分类) | ✅ 2026-10-11,只有 chrome.* 是假的;视觉与真实 CDP 行为仍需实机确认 |
| 实测台 verify_cdp_retry:CDP 会话被抢走后的恢复 / 重放不许把副作用做两遍 / 重试有界(6 场景) | ✅ 2026-10-11,真实 background.js + 有状态假 chrome.debugger;另用合并预览文件交叉验证过 |
| 实测台 verify_render_contract:每条工具的真实返回值同时喂给宿主的输出校验器与它自己的 render,断言「模型可见文本里有这次调用真正要的数据」 | ✅ 2026-10-12,真桥 + 假扩展 + 宿主 validateJsonSchemaValue;这一层此前零覆盖,所以两类缺陷活了 12 / 5 个版本 |
| 真实宿主 × 真实浏览器:本机 dsh 0.2.0-rc.2 用隔离 DSH_HOME 挂载本插件,用户的真实 Chrome 连上桥,9 条只读工具全部走真实代码路径 | ✅ 2026-10-12,Chrome 153 + 扩展 1.0.10:browser_read 交出 1341 字符真实正文、browser_snapshot 交出 14 条带 ref 的清单、输出 schema 零违规;也正是这一跑发现了旧扩展会静默忽略 mode:"ax"(本机扩展是 1.0.10,早于 AX 快照的 1.0.11)——已改成插件侧显式回报 axFallback |
| tsc --noEmit + publint | ✅ 2026-10-10 |
仓库自 v1.0.4 起不再有单测目录,上面三条浏览器场景是历史实机记录,本版未重跑;本版结论都来自 verify/ 里可重复执行的实测台。
更新日志
见 CHANGELOG.md。
许可证 · License
本项目采用 GNU Affero General Public License v3.0 (AGPL-3.0)。
- 个人 / 学术 / 非商业用途:完全免费,在遵守 AGPL-3.0 的前提下自由使用、修改、分发
- 企业 / 商业用途:AGPL-3.0 要求通过网络使用本软件也构成"分发",必须公开衍生代码。若企业在闭源产品中嵌入、基于本项目构建 SaaS 服务而不愿开源,需要联系作者获取商业许可(另行协商授权条款)
- 商业许可咨询:GitHub Issues 或邮箱 caob2333@outlook.com
完整许可证文本见 LICENSE 文件(AGPL-3.0)。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
angelky7/dsh-browser-control
Chrome 浏览器扩展 + DeepSeek Harness 插件,让 AI Agent 直接操控你的真实浏览器。
相关插件 · 浏览器
智能体插件框架deepseek-ai/deepseek-harness
DeepSeek Harnessdsh是由 DeepSeek AI 开发的开源 agent harness智能体框架。
★ 270,422已汉化DSH
71.9
多设备 Agent 看板YaoApp/yao
✨ 所有 Agent 和工作区集中管理,覆盖你的每一台设备。任务看板追踪进度,桌面端、移动端、浏览器、API…
★ 8,147已汉化DSH
71.2
可扩展侧边栏工作台omdsh-dev/DSH-better-sidebar
DSH 的双工作台:原生右侧栏 + 自绘底部面板,并把 ctx.betterSidebar 服务开放给所有插件
★ 4,761已汉化DSH
71.1
浏览器自动化桥Tencent/BrowserSkill
你的 Agent。你的浏览器。连接,就能协作。
★ 9,928已汉化DSH
71
AI 小说创作工作台EthanYoQ/AI-Novel-Writer
AI 小说作家 / AI Novel Writer
★ 1,591已汉化DSH
70.7
智能体浏览器引擎platonai/Browser4
DeepSeek Harness 集成
★ 1,175已汉化DSH
70.4