Bundle
dsh-plugin-chrome
DeepSeek Harness 浏览器可视化插件:为每个会话打开一个可见的真实 Chrome 窗口,Agent 通过 chrome_* 工具集操作浏览器,用户在 Web GUI 的「Chrome」标签页实时观看画面流并手动接管控制。
- Source
- jiaererw
- stars
- 4 stars
- License
- MIT
- Updated
- Updated 11 days ago
Readme
# dsh-plugin-chrome
> A DeepSeek Harness browser visualization plugin: opens a **real, visible Chrome window** per session, lets the agent drive the browser through the `chrome_*` tool suite, and streams the **live view** into a Chrome tab in the Web GUI — take over manually at any time.
| | |
|---|---|
|  |  |
[](https://github.com/jiaererw/dsh-plugin-chrome/stargazers)
[](LICENSE)
[中文文档](README.zh.md)
## Contents
- [Features](#features)
- [Install](#install)
- [Usage](#usage)
- [Configuration](#configuration)
- [FAQ](#faq)
- [Development](#development)
- [License](#license)
## Features
- **A visible window per session**: every DSH session gets its own Chrome window (a real window, not headless). Watch every agent action as it happens; the window uses an isolated user-data-dir, so it never mixes with your daily browser.
- **Live view**: the Chrome tab in the Web GUI streams the window through Chrome screencast (smooth while pages are active). A screenshot heartbeat keeps idle pages from freezing — a forced frame about every 2 seconds once the stream has been silent for 3 seconds.
- **Complete agent tool suite** (16 tools): `chrome_open` / `chrome_status` / `chrome_close` / `chrome_navigate` / `chrome_tabs` / `chrome_snapshot` / `chrome_screenshot` / `chrome_click` / `chrome_click_at` / `chrome_fill` / `chrome_type` / `chrome_press_key` / `chrome_hover` / `chrome_scroll` / `chrome_evaluate` / `chrome_wait`. `chrome_tabs` covers list / new / close / select, and snapshots, screenshots and clicks always act on the selected tab.
- **Accessibility-tree snapshots**: `chrome_snapshot` returns a compact a11y tree with stable element uids; clicks and fills target uids directly — far lighter than DOM dumps and robust against fragile selectors.
- **Dual-channel screenshots**: `chrome_screenshot` sends the image into the model context (as an image block) AND saves it to the session's screenshot history shown in the panel — history entries keep title/URL/size metadata across restarts. (Running a text-only model? See the FAQ.)
- **Security-minded**: CDP never exposes a fixed port; the Web API rejects cross-site requests (Sec-Fetch-Site) and whitelist-validates sessionId; browser data is isolated per session.
- **Resource governance**: idle windows auto-close (default 10 min, configurable), `chrome_close` closes explicitly, and plugin unload / host shutdown closes every window it opened.
## Install
> Prerequisites: DeepSeek Harness (DSH) installed, and Chrome or Edge on the machine.
```sh
# Option 1: install from GitHub (recommended)
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:jiaererw/dsh-plugin-chrome
# Option 2: local path (development)
npx -p @deepseek-ai/dsh dsh plugin --profile web add D:/harness/dsh-plugin-chrome
```
Restart DSH after installing — a **Chrome** tab appears at the top of every conversation.
> If your profile's `cordis.patch.yml` still carries an old manual mount line for `dsh-plugin-chrome` (from local development), remove it before installing through the CLI to avoid double-mounting.
## Usage
### For the agent (tools)
The agent gets the `chrome_*` suite automatically. Just ask it:
> Open Chrome, go to https://example.com, take a screenshot, then click the "Login" button and fill in the username.
The agent will: `chrome_open` → `chrome_navigate` → `chrome_screenshot` (sees the image) → `chrome_snapshot` (gets uids) → `chrome_click` / `chrome_fill`.
### For you (visualization)
1. Open the **Chrome** tab at the top of the conversation:
- **Live view**: continuously shows the window. Native screencast frames flow while the page changes; a heartbeat fallback force-captures idle pages (about one frame every 2 seconds) so the picture never freezes.
- **Tab management**: create, switch or close tabs from the side list, in sync with the real window.
- **Manual takeover**: click around in the Chrome window yourself at any time — the agent sees your changes on its next tool call.
2. **Screenshot history**: every `chrome_screenshot` is stored in the panel; click a thumbnail to enlarge.
### Window lifecycle & resilience
- **Lazy start**: Chrome launches only on the first `chrome_*` call (or the panel's Open button).
- **Orphan adoption**: if DSH died and left a Chrome behind (profile locked), the plugin reconnects through `DevToolsActivePort` and takes the window over instead of failing (the same autoConnect idea as chrome-devtools-mcp).
- **Idle reaping**: a window idle past `idleTimeoutMs` (default 10 min) closes automatically — never while a Web UI viewer is watching.
- **Auto tab recovery**: every operation makes sure a usable tab exists, so a window full of `chrome://` internal pages never dead-ends.
## Configuration
Override the plugin row in the profile's `cordis.patch.yml` (config is replaced wholesale):
```yaml
- id: dsh-plugin-chrome
config:
headless: false # keep false — a visible window is the point
executablePath: '' # empty auto-detects Chrome/Edge; or set an absolute path
idleTimeoutMs: 600000 # idle auto-close (0 disables)
windowWidth: 1280
windowHeight: 900
screencastFrameSkip: 4 # live-view frame decimation (1 = smoothest)
screencastQuality: 70 # JPEG quality 1-100
maxSnapshotText: 60000 # max chars per snapshot
maxTabs: 16
extraArgs: '' # extra Chrome launch flags
```
Data directory (browser profiles & screenshots): `~/.dsh/data/dsh-plugin-chrome/sessions/<sessionId>/` (override with `dataRoot`).
## FAQ
- **The Chrome tab shows nothing**: check the window is running (status dot at the top); the first launch takes a few seconds. Idle pages get a forced frame about every 2 seconds via the heartbeat (after 3 seconds without a real frame); activity raises the frame rate automatically.
- **Agent says "unknown uid"**: the page changed — have it re-run `chrome_snapshot`.
- **I closed the window myself**: the panel shows "window closed"; any next `chrome_*` call or the Open button relaunches it.
- **Login state**: each session uses an isolated profile, so logins don't carry over from your daily browser — that's by design. To log in somewhere, let the agent complete the login (it persists for the session).
- **Chrome stays open after DSH is killed**: the orphan window is adopted on the next session call (or close it by hand); a clean DSH shutdown closes its windows.
- **Screenshots stop a text-only model from responding**: `chrome_screenshot` delivers the picture as an image block into the conversation history. If the session's model does not accept images, every following turn is rejected with `UNSUPPORTED_CONTENT: does not accept image input` and the session no longer responds — retrying doesn't help. Use a vision-capable model for sessions that screenshot, or avoid `chrome_screenshot` there.
- **Install blocked by pnpm (strict-dep-builds)**: add `dsh-plugin-chrome: true` to `allowBuilds` in the profile's `pnpm-workspace.yaml` and retry the install.
## Development
```sh
npm install
npm run typecheck # host + client programs
npm test # vitest unit tests
npm run test:e2e # real-Chrome end-to-end smoke (pops a visible window)
npm run build # lib/index.js + lib/index.d.ts (host), lib/client.js + lib/client.d.ts (client bundle)
npm run watch # continuous build; client changes hot-reload, host changes need a DSH restart
```
Architecture: the host half (cordis plugin) drives the local Chrome through puppeteer-core, registers the `chrome_*` tools and the `/dsh-chrome/*` HTTP/WS API; the client half (browser bundle) registers the Chrome tab on `conversation.view` and consumes the API and the frame stream. The picture = native Chrome screencast (active pages) + screenshot heartbeat (idle fallback). The control layer borrows proven designs from [chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp) (CDP control, a11y snapshots with uid lookup, wait discipline, autoConnect adoption) and [mcp-chrome](https://github.com/hangwin/mcp-chrome) (screenshot compression, CDP coordinate input, session refcounting).
## License
MIT
Install
dsh plugin --profile web add github:jiaererw/dsh-plugin-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-plugin-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.