Bundle
dsh-chrome
Chrome profile bridge for DeepSeek Harness: control the user's existing signed-in Chrome through the chrome_repl tool, a local HTTP bridge, and the companion WanJuan Chrome extension.
- Source
- YJSoooooo
- stars
- 2 stars
- License
- MIT
- Updated
- Updated 10 days ago
Readme
# dsh-chrome
> 让 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 直接使用你已经登录的 Chrome。
`dsh-chrome` 是一个面向 DeepSeek Harness 的 Chrome 控制插件。它把 `chrome_repl` 工具、`control-chrome` Skill、通用审批和 `/chrome` 管理命令打包成可安装的 DSH Bundle,让 Agent 能在用户授权后复用真实 Chrome Profile 中的登录态、标签页和扩展环境。
适合这些任务:操作登录后的后台、复用当前网页、检查页面状态、点击和输入、截图、上传文件、验证 Web UI,以及读取虚拟列表或无限滚动内容。
> [!TIP]
> **用自然语言,不要用 `/chrome`。** `/chrome` 只是桥的管理开关(授权、诊断),它不接受自然语言;真正的浏览器任务直接说人话即可 —— 比如「看下我 Chrome 里开了几个 tab」。详见[两种入口](#两种入口不要混用)。
> [!IMPORTANT]
> 本项目是非官方社区插件,与 DeepSeek AI、DeepSeek Harness 和万卷 Work 均无官方隶属或背书关系。DeepSeek Harness 当前仍处于开发者预览阶段,可能发生破坏性变更;本项目目前适配 `@deepseek-ai/dsh-* >= 0.1.0-rc.6`。
## 为什么是 dsh-chrome
DeepSeek Harness 采用“一切皆插件”的架构。`dsh-chrome` 沿用这套机制,不修改 Agent Loop:
- 通过 `ctx.tools` 注册原生 `chrome_repl` 工具;
- 通过 `ctx.skills` 注册内置 `control-chrome` Skill;
- 通过 `tools/pre-execute` 接入 DSH 通用审批;
- 通过 `ctx.commands` 提供完整 `/chrome` 文本命令;
- 通过 `dsh.bundle.patch` 安装到 `web` 或其他 Profile;
- 通过 `SessionId` 隔离不同 Agent 的授权、REPL binding 和浏览器任务。
它控制的不是一个空白自动化浏览器,而是用户正在使用的 Chrome。Agent 可以复用现有登录态,但每次调用仍受 DSH 审批或显式限时授权约束。
## 功能
- **真实 Chrome Profile**:复用现有登录态、标签页和浏览器环境。
- **受限 JavaScript REPL**:持久保存变量,但不暴露 Node.js、文件系统、进程、网络全局或任意 `eval`。
- **观察—操作—验证**:支持 snapshot、find、inspect、click、fill、press、scroll、evaluate、screenshot、upload、console 和 network。
- **用户标签保护**:接管用户已有标签页不会移动、分组或关闭它。
- **任务级标签清理**:Agent 创建的普通研究标签页在当前 Turn 结束后自动关闭。
- **明确交付**:`markHandoff()` 和 `markDeliverable()` 可以保留需要交给用户的标签页。
- **通用审批**:默认每次 `chrome_repl` 调用进入 DSH 审批;也可以用 `/chrome authorize` 建立当前 Session 的限时授权。
- **多 Session 隔离**:同一进程内的多个 Agent 分别持有状态,共享机器级 Bridge 而不共享 REPL binding。
- **故障恢复**:Bridge owner 退出后,其他进程可以接管端口;失败的 Tab finalization 会在后续连接或调用时重试。
## 快速开始
### 1. 准备环境
- Node.js `^22.19` 或 `>=24`
- `pnpm`(DSH 的 Profile 插件命令会调用它)
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
- Chrome,以及[万卷 Work for Chrome](https://chromewebstore.google.com/detail/mafhfhekcinjbileflfmdfmlojjodjek) 扩展
DeepSeek Harness 官方 Web UI 可以直接这样启动:
```sh
npx @deepseek-ai/dsh web
```
### 2. 构建并安装本地插件
在 `dsh-chrome` 目录执行:
```sh
pnpm install
pnpm run build
npx @deepseek-ai/dsh plugin --profile web add .
```
`dsh-chrome` 的 `package.json` 声明了 `dsh.bundle.patch`。安装成功后,它会自动加入 `web` Profile 的 Bundle 层。
然后重新启动 Web UI:
```sh
npx @deepseek-ai/dsh web
```
### 3. 检查 Chrome 连接
确保 Chrome 正在运行且万卷扩展已启用,然后在 DSH 会话中执行:
```text
/chrome doctor
```
看到 `Chrome is connected` 后即可使用。无需手写 `chrome_repl`:直接用自然语言描述任务,Agent 会在需要时加载 Skill 并调用工具。
```text
打开我 Chrome 里已经登录的后台,检查今天有没有失败任务。
```
```text
用 Chrome 打开本地页面,检查表单布局并截图。
```
```text
找到我已经打开的文档页面,把标题改成“周报”,保存后确认结果。
```
## 授权模型
默认情况下,每次 `chrome_repl` 调用都会通过 DSH 通用审批询问用户。这是推荐设置,因为工具操作的是带真实登录态的浏览器。
如果一个任务需要连续调用,可以给当前 Session 一个限时授权:
```text
/chrome authorize 15m
```
也支持 `30m`、纯分钟数和 `indefinite`。撤销授权:
```text
/chrome revoke
```
显式授权和 background 偏好只保存在当前进程内,不写入 Session Log 或配置文件;重启后需要重新授权。
## 两种入口,不要混用
这是最容易踩的坑。插件提供两个完全不同的入口:
| | `/chrome` 命令 | 自然语言 |
|---|---|---|
| 用途 | 管理桥:授权、诊断、background | 实际操作浏览器 |
| 谁调用 | 你手动输入 | Agent 自动调用 `chrome_repl` |
| 接受自然语言 | **不接受** | 就是自然语言 |
`/chrome` 的子命令是固定白名单(`authorize`/`revoke`/`status`/`doctor`/`onboard`/`background`)。传入其他内容会被拒绝:
```text
❌ /chrome 看下我的 Google 上打开了几个 tab
→ Unknown subcommand '看下我的google'.
✅ 看下我的 Google 上打开了几个 tab
```
补充一点常见误解:`/` 菜单里列出的是**命令**,`chrome_repl` 工具和 `control-chrome` Skill 不会出现在那里 —— 它们由 Agent 按需自动调用,不需要你去点。
## `/chrome` 命令
`/chrome` 只管理 Bridge。真正的浏览器任务应直接用自然语言交给 Agent。
| 命令 | 作用 |
|---|---|
| `/chrome` | 显示连接状态和帮助 |
| `/chrome authorize [15m\|30m\|分钟\|indefinite]` | 为当前 Session 建立显式授权 |
| `/chrome revoke` | 撤销授权并清理当前 Agent-owned 浏览器任务 |
| `/chrome status` | 查看连接、授权和 background 状态 |
| `/chrome doctor` | 执行协议、页面脚本和连接诊断 |
| `/chrome onboard` | 返回配套 Chrome 扩展的商店地址 |
| `/chrome background on` | 后台操作,不主动抢占 Chrome 焦点 |
| `/chrome background off` | 操作时将 Chrome 带到前台,便于观察 |
| `/chrome background toggle` | 切换 background 模式 |
| `/chrome background status` | 查看 background 模式 |
## `chrome_repl` 概览
Agent 首次使用时会初始化持久 binding:
```js
const chrome = await browser.get("chrome")
await chrome.nameSession("🔎 检查管理后台")
```
使用用户已有标签页:
```js
const openTabs = await chrome.user.openTabs({ urlIncludes: "example.com", limit: 5 })
const tab = await chrome.user.claimTab(openTabs[0])
await tab.snapshot()
```
创建当前 Turn 独享的标签页:
```js
const tab = await chrome.tabs.open("https://example.com")
await tab.find("登录按钮")
await tab.click({ uid: "el-12", includeSnapshot: true })
```
外层 `chrome_repl` 是受限语法环境;完整页面 JavaScript 应放在 `tab.evaluate()` 中执行。更完整的操作规范位于 [control-chrome Skill](skills/control-chrome/SKILL.md)。
## 标签页生命周期
`dsh-chrome` 区分两种标签页:
| 类型 | 来源 | Turn 结束时 |
|---|---|---|
| 用户标签页 | `chrome.user.claimTab()` | 释放控制权;不移动、不分组、不关闭 |
| Agent-created 标签页 | `chrome.tabs.open/create()` | 默认关闭 |
需要保留 Agent-created 标签页时,必须显式标记:
```js
await tab.markHandoff() // 用户还需要继续操作
await tab.markDeliverable() // 标签页本身就是交付物
```
普通搜索、资料阅读和临时验证页面不应保留。
## 架构
```mermaid
flowchart LR
A["DeepSeek Harness Agent"] --> T["chrome_repl Tool"]
S["control-chrome Skill"] --> A
P["DSH Approval"] --> T
C["/chrome Commands"] --> R["Per-Session Controller"]
T --> R
R --> B["127.0.0.1:17318 Bridge"]
B --> E["WanJuan Chrome Extension"]
E --> X["User's signed-in Chrome"]
C -.命令输入投影.-> W["dist/client.js (Web GUI)"]
```
代码分为三层:
- `src/kernel/`:Bridge、协议握手、Chrome API、格式化和 Restricted REPL,不依赖 DSH UI。
- `src/adapter/`:工具、Skill、审批、命令、生命周期和 per-Session Controller。
- `src/client/`:浏览器半侧,把 `/chrome` 的命令输入投影成一个会话节点(见下)。
Bridge 是机器级共享连接:第一个进程监听 `127.0.0.1:17318`,后续进程以 client 模式转发;Agent 的授权、binding、任务 key、保留标签页和 pending finalization 则按 Session 隔离。
### 命令输出可见性
DSH 刻意让「控制类命令」在全新会话里保留 Hero 页 —— 通用 `command` 节点不会激活会话,因此在一个还没有任何内容的新会话里执行 `/chrome status`,结果会被隐藏。
`src/client/` 通过注册一个 feature-owned Conversation Definition 解决这个问题:它把 `/chrome` 的输入投影成 `chrome-command-input` 节点(不是 `command`),从而激活会话、让结果一并显示。这与官方 `/goal` 的做法一致。完整说明见 [docs/command-input-projection.md](docs/command-input-projection.md)。
> [!NOTE]
> 客户端半侧是 closure-factory bundle(`dist/client.js`),由 `dsh.client` 声明下发。DSH 的客户端注册表会缓存「无客户端」的判定直到进程结束,所以**首次加入客户端半侧后必须重启 `dsh web`**,仅重新构建无效。
## 配置
默认 Bundle 配置:
```yaml
- id: chrome-profile-bridge
name: dsh-chrome
config:
host: 127.0.0.1
port: 17318
```
可以在 Profile 的 `cordis.patch.yml` 中覆盖该行。DSH Patch 会整体替换 `config`,因此覆盖时请同时保留 `host` 和 `port`。
配套商店扩展固定访问 `127.0.0.1:17318`。除非同时维护并重新构建 Chrome 扩展,否则不要修改端口,也不要把 Bridge 绑定到非 loopback 地址。
## 安全边界
- `chrome_repl` 能操作真实登录态,首次使用应保留 DSH 审批。
- Restricted REPL 限制的是模型可执行语法,不是浏览器权限沙箱;`tab.evaluate()` 仍在目标页面内执行 JavaScript。
- Bridge 只应监听 loopback。它信任本机进程转发,不能作为跨机器或不受信任多用户服务暴露。
- 用户已有标签页的破坏性 `close/group/ungroup` 操作会被拒绝。
- 不应读取 Cookie、密码、Profile 文件或与任务无关的标签页。
- 写入、提交、上传等副作用操作失败后必须先检查实际页面状态,不能盲目重试。
- 截图默认写入当前工作区的 `.dsh/chrome-screenshots/`。
## 开发与验证
```sh
pnpm run test # vitest,8 个测试文件
pnpm run typecheck # 同时检查 node 半侧与 client 半侧
pnpm run build # tsc 产出 dist/,再用 esbuild 产出 dist/client.js
pnpm run build:client # 只重建浏览器半侧
```
修改 `src/client/` 后,重建并**重启** `dsh web`,然后刷新页面 —— GUI 加载的是 `dist/client.js`,不是源码。
连接真实 Chrome 的端到端验证:
```sh
node scripts/e2e-verify.mjs
```
该脚本需要已连接的配套扩展,会打开一个临时百度标签页,验证导航、页面执行、snapshot 和 Turn finalization,最后自动清理 Agent-created 标签页。
测试重点覆盖:Bridge 长轮询与多进程共享、握手兼容性、配置校验、受限 REPL、Chrome API、审批组合、多 Session 隔离、Turn 清理、finalization 重试,以及插件装载/卸载。
## 当前限制
- 没有独立 Web 设置页;连接诊断、授权和 background 设置通过 `/chrome` 完成。
- 授权和 background 偏好是当前 Session 的进程内状态,重启后不恢复。
- 当前仅兼容固定 ID 和协议的万卷 Chrome 商店扩展。
- Chrome 原生对话框、系统级文件选择器和部分 `chrome://` 页面仍需要用户处理。
- DeepSeek Harness 处于开发者预览阶段;升级 DSH 后应重新运行插件组合测试。
## DeepSeek Harness 生态
- [DeepSeek Harness 中文 README](https://github.com/deepseek-ai/deepseek-harness/blob/master/README.zh.md)
- [DeepSeek Harness 插件开发文档](https://github.com/deepseek-ai/deepseek-harness/tree/master/docs/user/develop)
- [GitHub `dsh-plugin` Topic](https://github.com/topics/dsh-plugin)
如果把本项目发布到 GitHub,建议为仓库添加 `dsh-plugin`、`deepseek-harness`、`chrome-extension`、`browser-automation` 和 `agent-tools` Topics,方便 DeepSeek Harness 用户发现。
## License
MIT
Install
dsh plugin --profile web add github:YJSoooooo/dsh-chrome
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-chrome from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.