Skip to content
dsh.fish
Bundle

dsh-browser

Browser capability for DeepSeek Harness: read and operate the user's live browser tabs through a companion Chrome extension.

Source
justwe-bot
License
MIT
Updated
Updated 1 hour ago

Readme

# dsh-browser

`dsh-browser` lets a DeepSeek Harness agent read and operate HTTP/HTTPS Chromium tabs. It uses the normal Harness tool runtime, so browser calls participate in model context, session logging, UI presentation, cancellation, timeout handling, and approval.

The production path has three delivered components:

```text
DeepSeek Harness
  dsh-browser
        |
        | authenticated loopback WebSocket
        v
Native Messaging host
        |
        | Chrome Native Messaging
        v
Chrome/Edge MV3 extension
        |
        v
HTTP/HTTPS tabs and page DOM
```

Direct mode removes the Native Messaging host and lets the extension connect to the loopback WebSocket itself. It is intended for local development and diagnostics, not production installation.

## Delivered Components

| Component | Delivery | Responsibility |
|---|---|---|
| Harness bundle | `dsh-browser` | Mounts the browser provider, approval policy, `browser_*` tools, and DSH Web settings card. |
| Native Messaging host | Local executable plus browser manifest | Verifies the extension ID, forwards framed messages, and authenticates to Harness. |
| Browser extension | Unpacked Chrome/Edge MV3 extension | Observes HTTP/HTTPS pages, displays the control notice, virtual pointer, and tab marker, and executes browser actions. |

The release package bundles the internal `ctx.browser` Service Definition, WebSocket provider, approval policy, tool Consumer, Web settings card, and Native Messaging host. Users install one DSH profile dependency.

## Prerequisites

- Node.js 22.19 or newer, with pnpm available to `dsh plugin`.
- An installed `dsh` CLI compatible with this package's peer dependency range.
- Chrome, Chromium, Edge, or Brave with MV3 and Native Messaging support.

## Production Installation

### 1. Install the Harness plugin

Install the GitHub repository into the Web profile:

```sh
dsh plugin --profile web add github:justwe-bot/dsh-browser
```

The package declares `dsh.bundle.patch`, so `dsh plugin` adds it to the profile's ordered bundle layers. The package also exposes its Web settings client and the Native Messaging installer.

### 2. Prepare the extension and obtain its ID

Copy the packaged extension to a stable directory under `DSH_HOME`:

```sh
dsh plugin --profile web exec dsh-browser-native-install --prepare-extension
```

The command prints the resulting path, normally `$DSH_HOME/browser-extension`.

1. Open `chrome://extensions` or the equivalent page in Edge/Brave.
2. Enable Developer mode.
3. Choose **Load unpacked** and select the directory printed by the preparation command.
4. Copy the 32-character extension ID shown by the browser.

Moving the unpacked extension directory can change its ID. Reinstall the Native host whenever the ID changes.

### 3. Install the Native Messaging host

Run the installed package's Native host installer with the same `DSH_HOME` used by Harness:

```sh
dsh plugin --profile web exec dsh-browser-native-install \
  --extension-id <extension-id> \
  --browser chrome
```

Repeat `--browser` for additional browsers or use `--browser all`. The installer:

- copies the executable into `$DSH_HOME/browser-native-host/`;
- writes a private `$DSH_HOME/browser-native-host.json` containing the bridge URL, token, and allowed extension origin;
- writes the browser-specific NativeMessagingHosts manifest;
- writes `DSH_BROWSER_PORT` and `DSH_BROWSER_AUTH_TOKEN` to the private `$DSH_HOME/browser-native-host.env` launch file.

Remove the installation with:

```sh
dsh plugin --profile web exec dsh-browser-native-install --uninstall --browser chrome
```

### 4. Start Harness

```sh
set -a
source "${DSH_HOME:-$HOME/.dsh}/browser-native-host.env"
set +a
dsh web
```

DSH deliberately rejects startup-sensitive `DSH_*` variables loaded from `$DSH_HOME/.env`; the dedicated file must be sourced into the launching shell. From a DeepSeek Harness source checkout, use `pnpm dsh` in place of `dsh` in these commands.

### 5. Verify the connection

1. Reload the unpacked extension after installing the Native host. The extension connects automatically and keeps retrying after browser, service-worker, host, or Harness restarts.
2. Open the extension popup and confirm that it reports **Connected**.
3. Ask the agent to list browser tabs.

The popup contains only automatic connection state and the extension ID needed by the Native host installer. Installing the extension grants access to every HTTP/HTTPS tab in that browser profile; browser-internal pages, extension pages, and `file:` URLs remain unsupported.

### DSH Web plugin configuration

Open **Settings > Plugins > Plugin configuration > DSH Browser**. The card reports whether the bridge is listening and whether the Edge extension is authenticated, including transport and extension version. It also exposes one live switch for each runtime component:

- **Browser bridge** disconnects the current extension and rejects new extension handshakes while disabled.
- **Browser policy** stops contributing Harness approval decisions while disabled; the extension still limits operations to HTTP/HTTPS pages.
- **Browser tools** removes every `browser_*` registration from the Agent tool directory while disabled.

The settings owners stay mounted so the same card can re-enable a component without changing the profile or restarting DSH. The status route is loopback-only and omits the authentication token, extension installation id, and tab data.

The extension requests broad HTTP/HTTPS injection permission at installation because Chromium host match patterns and `chrome.scripting` are browser-wide capabilities. It also declares `debugger` because `browser_evaluate` uses a temporary CDP `Runtime.evaluate` session. Each command checks that its target still has an HTTP or HTTPS URL and that the page origin did not change between tab inspection and page execution.

Controllable page URLs, titles, visible text, form values, and action results can enter model context and the Harness session log.

## Browser Tools

The default bundle registers these tools:

| Category | Tools |
|---|---|
| Observe | `browser_list_tabs`, `browser_snapshot`, `browser_wait` |
| Tab and navigation state | `browser_new_tab`, `browser_navigate`, `browser_back`, `browser_forward`, `browser_reload` |
| Page actions | `browser_click`, `browser_type`, `browser_scroll`, `browser_key` |

`browser_evaluate` is registered by default. Set `browser-tools.config.enableEvaluate: false` in a profile override to remove it. Harness approval still applies under interactive permission presets.

Model tools cannot activate a tab or focus a browser window. `browser_new_tab` always opens an inactive background tab, and later tools use its returned `tabId` directly without changing the user's active tab.

Snapshots return bounded visible text and interactive elements. Each element `ref` is valid only with the snapshot's `documentId`; navigation or document replacement invalidates it and returns `STALE_REF`.

When an Agent first targets a controllable page, the extension displays a fixed localized DeepSeek Harness control notice, virtual pointer, and favicon marker for that Agent. Chinese browser UI displays `DeepSeek Harness 正在控制此页面`; other languages currently use `DeepSeek Harness is controlling this page`. The indicators remain across consecutive browser tools and disappear when that Agent returns to `idle`, is disposed, or loses its browser connection. They are excluded from snapshots, element refs, and text waits. Listing tabs does not display them because it has no target page.

Mutation tools return a Harness `ask` decision under the default `workspace-write` permission preset. A rejected approval prevents the browser command from reaching the page. The default browser policy delegates these tools without a prompt under `danger-full-access`; the HTTP/HTTPS target restriction remains mandatory.

## Direct Development Mode

Generate a token and launch Harness with matching bridge settings:

```sh
export DSH_BROWSER_AUTH_TOKEN="$(node -e 'process.stdout.write(require("node:crypto").randomBytes(32).toString("hex"))')"
export DSH_BROWSER_PORT=9122
pnpm dsh web
```

The production popup does not expose Direct mode. For manual diagnostics, open the popup's DevTools console and configure the internal development transport:

```js
await chrome.runtime.sendMessage({
  type: 'bridge:configure',
  transport: 'direct',
  port: 9122,
  authToken: '<the same DSH_BROWSER_AUTH_TOKEN>',
})
```

Direct mode still requires the versioned handshake, Chrome-extension Origin, and token authentication. Reloading an installed production extension uses its persisted transport; send the same message with `transport: 'native-host'` to return it to the production path.

## Verification

```sh
pnpm typecheck
pnpm test
pnpm test:snapshot
pnpm smoke
pnpm smoke:profile
pnpm test:chromium
```

`smoke:profile` expects DeepSeek Harness at the parent directory by default. Set `DSH_HARNESS_ROOT=/path/to/deepseek-harness` when the repositories are elsewhere, and run `pnpm run build` in the Harness checkout after a fresh clone before running the smoke.

## Current Limits

- One authenticated browser client owns the bridge at a time.
- Only HTTP and HTTPS pages are controllable; every such tab in the browser profile is visible to the extension.
- Page snapshots operate on the top-level document; cross-origin frames and closed shadow roots are not exposed.
- Screenshot, upload, download, dialog, network inspection, and general-purpose CDP control are outside this release. `browser_evaluate` is the only command that uses `debugger`.
- Firefox, Safari, and cross-machine browser control are unsupported.

## Documentation

- [Requirements](doc/01-需求文档.md)
- [ChatGPT extension and Codex investigation](doc/02-调查报告-ChatGPT扩展与Codex通信机制.md)
- [Communication design](doc/03-通信方式设计.md)
- [Security design](doc/04-安全设计.md)
- [Implementation and acceptance](doc/05-实施与验收.md)

Install

dsh plugin --profile web add github:justwe-bot/dsh-browser

Profile: web

  • 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.
Source