dsh-builtin-browser 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -1,106 +1,179 @@
1
- # dsh-builtin-browser (built-in shared real browser plugin for DeepSeek Harness)
1
+ <p align="center">
2
+ <img src="https://img.shields.io/github/stars/wqty123/dsh-browser?style=flat&amp;label=%E2%98%85&amp;color=08C" alt="GitHub stars">
3
+ <img src="https://img.shields.io/npm/v/dsh-builtin-browser?style=flat&amp;label=npm&amp;color=CB3837" alt="npm version">
4
+ <img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat" alt="MIT License">
5
+ <img src="https://img.shields.io/badge/DSH-Plugin-47848F?style=flat" alt="DeepSeek Harness plugin">
6
+ <img src="https://img.shields.io/badge/Windows%20%7C%20macOS%20%7C%20Linux-4493F8?style=flat-square" alt="Platforms">
7
+ </p>
2
8
 
3
- 中文 | [English](README.en.md)
9
+ <p align="center"><a href="README.md">中文</a> · English</p>
4
10
 
5
- A shared **real browser** capability plugin for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness): install and it just works — the agent drives a real, visible browser over CDP that the human can watch and take over at any time. Human and agent operate the **very same page**.
11
+ <h3 align="center">A <b>shared real browser</b> plugin for the DeepSeek Harness ecosystem (install-and-use, human and agent on the same page)</h3>
6
12
 
7
- **Why this plugin**
13
+ <h4 align="center">The agent drives a real, visible browser the human can watch and take over at any time — both operate the <b>same page</b>.</h4>
8
14
 
9
- - **Install-and-use.** With a desktop shell the shell's embedded view is used; on plain `dsh web` the plugin **self-hosts** — it spawns its own Electron window with zero extra configuration.
10
- - **Real and visible, human-takeover friendly.** Not a headless screenshot or a relay: the user sees the page and can grab control directly.
11
- - **DOM-level driving, framework-friendly.** React/Vue controlled inputs fill reliably.
12
- - **Concurrency-safe.** Task-level browser session isolation — parallel tasks never fight over the page or pollute each other.
13
- - **Built for the real world.** CAPTCHA detection, login persistence, batch form filling, authenticated downloads, operation replay, and action restriction — all included.
15
+ ## Documentation
14
16
 
15
- ## Features
17
+ | Goal | Entry |
18
+ | --- | --- |
19
+ | Why a shared real browser, and how it differs from headless approaches | [Why a shared real browser](docs/why-browser.md) |
20
+ | Installation, configuration, day-to-day use | [User guide](docs/user-guide.md) |
21
+ | All 20 tools: parameters, output, examples | [Tool reference](docs/tool-reference.md) |
22
+ | How the seam / provider / tools layers and self-hosting work | [Architecture](docs/architecture.md) |
23
+ | Documentation index and README split | [Docs index](docs/README.md) |
16
24
 
17
- **Browser capability**
25
+ ## What is this
18
26
 
19
- - **Real view, not a relay.** The browser is a native view (`WebContentsView`) the human can see and operate directly; the agent drives the very same page. The view is provided by the host shell; the plugin drives it.
20
- - **DOM-referenced, not coordinate-guessing.** `browser_snapshot` returns numbered interactive elements; `browser_execute` runs JS in the page (native setters for framework inputs), so interaction works on React/Vue pages.
21
- - **Multi-tab sessions.** Open URLs in parallel tabs, list/switch/close/reset, all keeping state.
22
- - **Multi-format content.** Fetch pages as html / markdown / txt / json, scoped by selector, capped by length and timeout.
27
+ `dsh-builtin-browser` adds browser capability to [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness):
23
28
 
24
- **Engineering capability**
29
+ - **A real view, not a relay**: the browser is a native `WebContentsView`; the human sees every step the agent takes and can grab control at any time;
30
+ - **Install-and-use**: with a desktop shell the shell's embedded view is used; on plain `dsh web` the plugin **self-hosts** — it spawns its own Electron window with zero extra configuration;
31
+ - **One plugin, one toolset**: after install the agent automatically gets 20 `browser_*` tools (open, inspect, interact, fill forms, screenshot, download, auth management…).
25
32
 
26
- - **Per-task isolation.** Each DSH task (session) gets its own browser session (own tabs and history); concurrent tasks never interfere, and calls within one task reuse the same session (`browser_session` / `browser_reset_session`).
27
- - **Login persistence.** `browser_auth` exports/restores cookies, so logins survive host restarts.
28
- - **CAPTCHA / bot-detection awareness.** Cloudflare, reCAPTCHA, hCaptcha, Turnstile and generic challenges are detected automatically (`browser_challenge`, and flagged in snapshots); instead of blindly retrying, the agent asks the human to complete it in the shared window.
29
- - **Batch form filling.** `browser_fill` sets many fields in one call — matched by selector/name/label, handling controlled inputs, selects, checkboxes and radio groups, with optional submit.
30
- - **Operation history & replay.** `browser_history` records operations; `browser_replay` re-runs one step.
31
- - **Authenticated downloads.** `browser_download` fetches a URL with the session's cookies straight to a local file.
32
- - **Safety restriction.** `browser_restrict` limits which browser actions are allowed, preventing stray clicks/navigation.
33
+ In one sentence: **installing the plugin gives you a real browser that is shared with the user and drivable by the agent.**
33
34
 
34
- ## Requirements
35
-
36
- - DeepSeek Harness (dsh) with the `web` profile
37
- - **Electron runtime** (optional peer dependency): the desktop shell carries it; on plain `dsh web` the plugin must be able to locate an Electron binary (see below)
38
- - With a desktop shell (`ctx.electronViewHost`) the shell's embedded view is used; without one the plugin **self-hosts**: it spawns its own Electron window and the `browser_*` tools still work
39
-
40
- **Electron lookup order**: ① `require('electron')` (peer installed) → ② DSH install anchors → ③ `node_modules/.pnpm` virtual store → ④ `ELECTRON_PATH` env var. A clear error tells you when none is found.
41
-
42
- ### Verified versions
43
-
44
- | Component | Version |
45
- |---|---|
46
- | DeepSeek Harness (dsh) | `0.1.0-rc.5` |
47
- | Electron | `43.4.0` |
48
- | Node.js | `22.20.0` |
49
- | dsh-builtin-browser | `0.1.7` |
50
- | OS | Windows 10 (10.0.26200) |
51
-
52
- > The plugin declares `electron >= 30`; other platforms (macOS/Linux) run the same protocol but were only verified on the Windows environment above.
53
-
54
- ## Install
35
+ ## Quick start
55
36
 
56
37
  ```sh
57
- dsh plugin --profile web add dsh-builtin-browser # from npm once published
58
- # or from a checkout (one plugin, one repository):
38
+ # Option 1: install from npm (published)
39
+ dsh plugin --profile web add dsh-builtin-browser
40
+
41
+ # Option 2: install from a checkout (one plugin, one repository)
59
42
  dsh plugin --profile web add <path-to-this-repo>
60
43
  ```
61
44
 
62
- This links the plugin, adds `dsh-builtin-browser` to the profile's bundle layer, and mounts:
63
-
64
- | Row | Subpath | Role |
65
- |---|---|---|
66
- | `browser` | `dsh-builtin-browser/browser` | `ctx.browser` capability seam (always mounted) |
67
- | `browser-electron` | `dsh-builtin-browser/browser-electron` | Electron CDP provider (needs `electronViewHost`) |
68
- | `tool-browser` | `dsh-builtin-browser/tool-browser` | `browser_*` model-facing tools |
69
-
70
- The provider and tools are gated on `ctx.get('electronViewHost')` being present, so a composition without a desktop shell simply keeps the seam and nothing else.
45
+ After install the agent can use the browser tools, e.g.:
46
+
47
+ | What you want | Tool | Notes |
48
+ | --- | --- | --- |
49
+ | Open a page | `browser_open` | Opens a URL and returns a numbered snapshot |
50
+ | Understand a page | `browser_snapshot` | Numbered inventory of inputs/buttons/links to target |
51
+ | Operate a page | `browser_execute` | Runs JS in the page (native setters, framework-friendly) |
52
+ | Fill a form | `browser_fill` | Fills many fields in one call, optional submit |
53
+ | See the page | `browser_screenshot` | PNG capture, optionally saved for a vision model |
54
+
55
+ See the full list in [Tool reference](#tool-reference).
56
+
57
+ ## Main features
58
+
59
+ <table>
60
+ <tr>
61
+ <td width="50%" valign="top">
62
+ <h3>Shared real browser</h3>
63
+ <p>A native view, not a headless screenshot. Human and agent operate the same page: the user sees every step and can take over; the agent drives the very window in front of the user.</p>
64
+ </td>
65
+ <td width="50%" valign="top">
66
+ <h3>DOM-level driving, framework-friendly</h3>
67
+ <p><code>browser_snapshot</code> returns numbered interactive elements; <code>browser_execute</code> runs JS in the page (native setters + input/change events for controlled inputs), so React/Vue pages work reliably.</p>
68
+ </td>
69
+ </tr>
70
+ <tr>
71
+ <td width="50%" valign="top">
72
+ <h3>Multi-tab sessions</h3>
73
+ <p>Open URLs in parallel tabs; list/switch/close/reset tabs while each session keeps its own state.</p>
74
+ </td>
75
+ <td width="50%" valign="top">
76
+ <h3>Multi-format content</h3>
77
+ <p>Fetch pages as html / markdown / txt / json, scoped by CSS selector, capped by character limit and timeout.</p>
78
+ </td>
79
+ </tr>
80
+ <tr>
81
+ <td width="50%" valign="top">
82
+ <h3>Per-task session isolation</h3>
83
+ <p>Each DSH task (session) gets its own browser session (own tabs and history); concurrent tasks never fight over the page or pollute each other. Calls within one task reuse the same session.</p>
84
+ </td>
85
+ <td width="50%" valign="top">
86
+ <h3>Login persistence</h3>
87
+ <p><code>browser_auth</code> exports/restores cookies so logins survive host restarts; self-hosted cookies are also persisted to disk.</p>
88
+ </td>
89
+ </tr>
90
+ <tr>
91
+ <td width="50%" valign="top">
92
+ <h3>CAPTCHA / bot-detection awareness</h3>
93
+ <p>Detects Cloudflare, reCAPTCHA, hCaptcha, Turnstile and generic challenges (<code>browser_challenge</code>, also flagged in snapshots); instead of retrying blindly, the agent asks the human to complete it in the shared window.</p>
94
+ </td>
95
+ <td width="50%" valign="top">
96
+ <h3>Batch form filling</h3>
97
+ <p><code>browser_fill</code> fills many fields at once — matched by selector/name/label, handling controlled inputs, selects, checkboxes and radio groups, with optional submit; one failing field never aborts the rest.</p>
98
+ </td>
99
+ </tr>
100
+ <tr>
101
+ <td width="50%" valign="top">
102
+ <h3>Operation history &amp; replay</h3>
103
+ <p><code>browser_history</code> logs operations (open/execute/click/type/fill/download/auth); <code>browser_replay</code> re-runs one step by sequence number.</p>
104
+ </td>
105
+ <td width="50%" valign="top">
106
+ <h3>Authenticated downloads</h3>
107
+ <p><code>browser_download</code> fetches a file in the page context with the session's cookies and writes it to disk — content behind login works too.</p>
108
+ </td>
109
+ </tr>
110
+ <tr>
111
+ <td width="50%" valign="top">
112
+ <h3>Safety restriction</h3>
113
+ <p><code>browser_restrict</code> limits which browser actions are allowed (allow-list) to prevent stray clicks/navigation; read-only tools (snapshot/content/screenshot) are never blocked.</p>
114
+ </td>
115
+ <td width="50%" valign="top">
116
+ <h3>Screenshot, save and read</h3>
117
+ <p><code>browser_screenshot</code> supports <code>savePath</code> to write the PNG to disk, ready for vision models (modlens etc.) to locate elements visually.</p>
118
+ </td>
119
+ </tr>
120
+ </table>
121
+
122
+ ## Why this plugin
123
+
124
+ - **Install-and-use, zero config**: no desktop shell or extra startup step required; on plain `dsh web` it self-hosts an Electron window and the `browser_*` tools just work.
125
+ - **Human-in-the-loop, non-interfering**: the user sees and can take over every agent action; per-task isolation gives each parallel task its own tabs and history.
126
+ - **Built for the real world**: CAPTCHA detection, login persistence, batch form filling, authenticated downloads, operation replay, action restriction — real-browser automation that is actually reliable.
127
+ - **Testable, replaceable architecture**: the provider talks to Electron through the `ElectronBrowserViewHost` seam, so a future headless relay provider can serve remote deployments without touching the tool layer.
128
+
129
+ ## Tool reference
130
+
131
+ | Tool | Purpose | Guard |
132
+ | --- | --- | --- |
133
+ | `browser_open` | Open a URL (optionally in a new tab); returns a page snapshot | ✅ |
134
+ | `browser_snapshot` | Numbered inventory of interactive elements (inputs/buttons/links) | – |
135
+ | `browser_execute` | Run JS in the page; args arrive as `arguments[0..n]` | ✅ |
136
+ | `browser_content` | Fetch the page as html / markdown / txt / json (selector, maxChars, timeoutMs) | – |
137
+ | `browser_click` | Click at viewport coordinates (for vision-located targets) | ✅ |
138
+ | `browser_type` | Type text into the focused element (CDP `Input.insertText`) | ✅ |
139
+ | `browser_fill` | Batch form fill (selector/name/label matching, controlled inputs, selects, checkbox/radio, optional submit) | ✅ |
140
+ | `browser_screenshot` | PNG capture, optional `fullPage` and `savePath` | – |
141
+ | `browser_list_tabs` | List the session's tabs | – |
142
+ | `browser_switch_tab` | Switch to a tab by id (also switches the visible view when self-hosted) | ✅ |
143
+ | `browser_close_tab` | Close a tab by id; closing the active tab activates the next | – |
144
+ | `browser_reset` | Close all tabs of this task, back to one blank tab | ✅ |
145
+ | `browser_session` | Show this task's browser session and tabs | – |
146
+ | `browser_reset_session` | Close and rebuild this task's browser session | ✅ |
147
+ | `browser_history` | Operation log (newest last), with per-step success/error and result summary | – |
148
+ | `browser_replay` | Replay one step by sequence number (navigate/execute/click/type) | ✅ |
149
+ | `browser_download` | Download a URL with session cookies to a local file (256 MB cap) | ✅ |
150
+ | `browser_auth` | Export/restore cookies (login persistence, self-hosted) | ✅ |
151
+ | `browser_challenge` | Detect a human-verification challenge (CAPTCHA / Cloudflare / reCAPTCHA / hCaptcha / Turnstile) | – |
152
+ | `browser_restrict` | Restrict allowed browser actions (allow-list; empty list lifts it) | – |
153
+
154
+ > "Guard" column: ✅ actions are governed by the `browser_restrict` allow-list; read-only tools (snapshot/content/screenshot/list_tabs/session/challenge/history) are never blocked.
155
+
156
+ ### Operating discipline (click/fill)
157
+
158
+ - **Prefer DOM semantics over coordinates**: submit forms with `form.requestSubmit()`; click with `element.click()`; coordinate clicks are the last resort.
159
+ - **Target the right element**: pages often have hidden duplicates (e.g. mobile buttons); filter visible elements with `browser_execute` (`getBoundingClientRect()` w/h > 0, `getComputedStyle` not `display:none`), then take coordinates.
160
+ - **Click right after taking coordinates**: do not insert other operations in between (filling/scrolling moves elements and invalidates old coordinates).
161
+ - **Verify before clicking**: use `document.elementFromPoint(x, y)` to confirm the coordinate hits the intended element (button/link), then perform the real click.
162
+ - **DPR awareness**: CDP input uses CSS pixels; on high-DPI screens calibrate with `elementFromPoint` instead of guessing coordinates.
71
163
 
72
164
  ## Configuration
73
165
 
74
- The plugin mounts through `cordis.patch.yml`; per-row config:
166
+ The plugin mounts through `cordis.patch.yml` (three rows); per-row config:
75
167
 
76
168
  | Row | Key | Type | Default | Description |
77
- |---|---|---|---|---|
169
+ | --- | --- | --- | --- | --- |
78
170
  | `browser-electron` | `viewHost` | object | required | `ElectronBrowserViewHost` supplied by the host shell (typically `!!js ctx.get('electronViewHost')`) |
79
- | `browser-electron` | `httpOnly` | boolean | `true` | Allow HTTP(S) navigation only; other protocols (e.g. `file:`/`data:`) are rejected (`BROWSER_NAVIGATION_BLOCKED`) |
171
+ | `browser-electron` | `httpOnly` | boolean | `true` | Allow HTTP(S) navigation only; other protocols (e.g. `file:`/`data:`) rejected (`BROWSER_NAVIGATION_BLOCKED`) |
80
172
  | `browser-electron` | `snapshotMaxElements` | number | `60` | Max snapshot elements before truncation |
81
173
  | `browser-electron` | `contentMaxChars` | number | `100000` | Default content character cap |
82
174
  | `tool-browser` | `timeoutMs` | number | `60000` | Cooperative tool timeout (ms) |
83
175
  | `tool-browser` | `tabTools` | boolean | `true` | Register tab-management tools (`browser_list_tabs` etc.) |
84
176
 
85
- ## Tools
86
-
87
- | Tool | Purpose |
88
- |---|---|
89
- | `browser_open` | Open a URL (optionally a new tab); returns a snapshot |
90
- | `browser_snapshot` | Numbered inventory of interactive elements (inputs/buttons/links) |
91
- | `browser_execute` | Run JS in the page; args arrive as `arguments[0..n]` |
92
- | `browser_content` | Fetch the page as html / markdown / txt / json (selector, maxChars, timeoutMs) |
93
- | `browser_screenshot` | PNG capture, optional `fullPage` |
94
- | `browser_list_tabs` / `browser_switch_tab` / `browser_close_tab` / `browser_reset` | Multi-tab session management |
95
-
96
- ### Interaction discipline (clicking / filling forms)
97
-
98
- - **Prefer DOM semantics over coordinates**: submit forms with `form.requestSubmit()`, click with `element.click()`; coordinate clicks are the last resort.
99
- - **Target the right element**: pages often carry hidden copies (e.g. mobile buttons). Use `browser_execute` to filter visible elements (`getBoundingClientRect()` with width/height > 0, computed style not `display:none`) before reading coordinates.
100
- - **Click immediately after reading coordinates**: do not interleave other actions (filling, scrolling moves elements; stale coordinates fail instantly).
101
- - **Verify the hit before clicking**: `document.elementFromPoint(x, y)` confirms the coordinate actually lands on the target button/link before issuing a real click.
102
- - **Mind DPR**: CDP input uses CSS pixels; on high-DPI screens, calibrate with `elementFromPoint` instead of blind coordinate tries.
103
-
104
177
  ## How it works
105
178
 
106
179
  ```
@@ -111,26 +184,73 @@ agent (browser_* tools)
111
184
  → WebContentsView + webContents.debugger (CDP)
112
185
  ```
113
186
 
114
- The provider is Electron-agnostic by construction: it operates through the `ElectronBrowserViewHost` seam (create/destroy/show views, `sendCommand`), which a real shell implements with Electron objects. The same seam lets a future relay provider (headless Chromium screenshot stream) serve remote deployments without touching the tools.
187
+ - **Seam** (`browser` row): provides the `ctx.browser` service — provider registration, session lifecycle, error codes — decoupled from any implementation.
188
+ - **Provider** (`browser-electron` row): operates views through the `ElectronBrowserViewHost` seam (create/destroy/show, `sendCommand`), implemented with real Electron objects by the shell.
189
+ - **Tools** (`tool-browser` row): the 20 model-facing `browser_*` tools, maintaining one browser session per calling task (DSH session).
190
+
191
+ **Self-hosted mode**: without a desktop shell, the plugin spawns its own Electron child process (`host-main.js`) and drives it over loopback TCP JSON-RPC (window title `dsh-browser`). The child auto-restarts after a crash; screenshots prefer Electron's native `capturePage` (CDP capture can hang with multiple views in the window); the plugin automatically picks the **newest** Electron in the environment (33.x has a compositor defect; ≥ 40 recommended).
192
+
193
+ **Electron lookup order**: ① `require('electron')` (peer dependency) → ② `ELECTRON_PATH` (explicit override) → ③ the newest among DSH install anchors and pnpm virtual stores. A clear error tells you when none is found.
115
194
 
116
195
  ## Division of labor with the desktop shell
117
196
 
118
- The browser's **visible view**, the **browser column layout**, and the **column-to-view alignment** belong to the host shell (e.g. dsh's `apps/desktop`), not this plugin. This plugin only consumes the shell-provided `electronViewHost` and owns the seam, provider, and tools. Installing the plugin without a matching shell leaves the capability disabled.
197
+ The browser's **visible view**, the **browser column layout**, and the **column-to-view alignment** belong to the host shell (e.g. dsh's `apps/desktop`), not this plugin. This plugin consumes the shell-provided `electronViewHost` and owns the seam, provider, and tools. Without a shell the plugin **self-hosts** and everything still works.
198
+
199
+ ## Requirements
200
+
201
+ - DeepSeek Harness (dsh) with the `web` profile
202
+ - **Electron runtime** (optional peer dependency): the desktop shell carries it; on plain `dsh web` the plugin locates an Electron binary automatically (see above; ≥ 40 recommended)
203
+
204
+ ### Verified versions
205
+
206
+ | Component | Version |
207
+ | --- | --- |
208
+ | DeepSeek Harness (dsh) | `0.1.0-rc.5` |
209
+ | Electron | `43.4.0` (≥ 40 recommended; 33.x has a compositor defect) |
210
+ | Node.js | `22.20.0` |
211
+ | dsh-builtin-browser | `0.1.11` |
212
+ | OS | Windows 10 (10.0.26200) |
213
+
214
+ > The plugin declares `electron >= 30`; other platforms (macOS/Linux) run the same protocol but were only verified on the Windows environment above.
119
215
 
120
216
  ## Known limitations
121
217
 
122
218
  - Screenshots are PNG-only (CDP JPEG hangs on Electron 43); JPEG awaits a non-CDP conversion path.
123
219
  - Self-hosted captures prefer Electron's native `capturePage` (CDP `captureScreenshot` can hang with multiple views in the window); the target tab is raised before capturing.
124
- - **Electron >= 40 is recommended**: 33.x has a compositor defect that intermittently breaks capture ("display surface not available"). The plugin automatically picks the newest Electron in the environment (peer dependency > `ELECTRON_PATH` > newest among anchors/pnpm store).
125
220
  - `fullPage` capture is flaky under software compositing on some hosts.
126
- - Sessions are isolated per task (each DSH session gets its own browser session with own tabs/history; concurrent tasks never interfere; calls within one task reuse the same session). Logins (cookies) are shared and can be exported/restored with `browser_auth`.
127
- - CAPTCHA cannot be solved automatically: snapshots flag detected challenges (`browser_challenge` checks explicitly); ask the human to complete it in the shared window instead of retrying.
221
+ - CAPTCHA cannot be solved automatically: snapshots flag detected challenges; ask the human to complete it in the shared window instead of retrying.
128
222
  - Private mode (`privateMode`) is not implemented: it needs Electron session partitioning, which is host-layer territory; this plugin does not promise it.
129
223
  - `browser_download` fetches in the page context (keeps logins) and is subject to same-origin/CORS constraints; single files are capped at 256 MB.
130
224
  - The `browser_auth` cookie round-trip does not preserve `hostOnly`/`sameSite` (host-only cookies come back as domain cookies); it is available on the self-hosted browser only.
131
225
  - After a self-hosted child crash the browser host restarts automatically, but sessions opened before the crash are gone — call `browser_reset_session` to rebuild.
132
226
  - This plugin contains no browser-column UI — that is host-shell territory; do not treat "browser column" as a plugin feature.
133
227
 
228
+ ## Development
229
+
230
+ ```sh
231
+ # Type-check + build (lib/)
232
+ pnpm run build
233
+
234
+ # Functional tests: start a local page server + Electron probe (see repo test scripts)
235
+ ```
236
+
237
+ Code layout:
238
+
239
+ | Directory | Responsibility |
240
+ | --- | --- |
241
+ | `src/browser/` | The `ctx.browser` seam and all request/result types |
242
+ | `src/browser-electron/` | Electron CDP provider, self-hosted child (`host-main.ts`), RPC layer |
243
+ | `src/tool-browser/` | Model-facing `browser_*` tools |
244
+ | `src/types/` | Electron ambient types (shim; no hard electron type dependency) |
245
+
246
+ ## Acknowledgements
247
+
248
+ Special thanks to the [DeepSeek Harness repository](https://github.com/deepseek-ai/deepseek-harness) and the DeepSeek AI team: the seam, the tool runtime, and the plugin system this plugin builds on all come from that project.
249
+
250
+ Thanks as well to [Cordis](https://github.com/cordiverse/cordis) for the plugin foundation, and to everyone in the community who discussed, tested, gave feedback, and built plugins.
251
+
134
252
  ## License
135
253
 
136
- MIT
254
+ MIT License, see [LICENSE](LICENSE).
255
+
256
+ > This project is a community plugin for DeepSeek Harness, not an official DeepSeek product.
package/README.md CHANGED
@@ -1,80 +1,172 @@
1
- # dsh-builtin-browser(DeepSeek Harness 内置共享真实浏览器插件)
1
+ <p align="center">
2
+ <img src="https://img.shields.io/github/stars/wqty123/dsh-browser?style=flat&amp;label=%E2%98%85&amp;color=08C" alt="GitHub stars">
3
+ <img src="https://img.shields.io/npm/v/dsh-builtin-browser?style=flat&amp;label=npm&amp;color=CB3837" alt="npm version">
4
+ <img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat" alt="MIT License">
5
+ <img src="https://img.shields.io/badge/DSH-Plugin-47848F?style=flat" alt="DeepSeek Harness plugin">
6
+ <img src="https://img.shields.io/badge/Windows%20%7C%20macOS%20%7C%20Linux-4493F8?style=flat-square" alt="Platforms">
7
+ </p>
2
8
 
3
- [English](README.en.md) | 中文
9
+ <p align="center"><sub>中文 · <a href="README.en.md">English</a></sub></p>
4
10
 
5
- 面向 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 的**共享真实浏览器**能力插件:装好即可用——agent 通过 CDP 驱动一个真实、可见、可随时人工接管的浏览器,人与 agent 操作的是**同一个页面**。
11
+ <h3 align="center">为 DeepSeek Harness 生态打造的<b>共享真实浏览器</b>插件(装好即用,人机同页)</h3>
6
12
 
7
- **我们的优势**
13
+ <h4 align="center">agent 驱动一个真实、可见、可随时人工接管的浏览器——人与 agent 操作的是<b>同一个页面</b>。</h4>
8
14
 
9
- - **装好即用**:有桌面外壳时嵌入外壳视图;纯 `dsh web` 也能**自托管**拉起自己的 Electron 窗口,不需要任何额外配置。
10
- - **真实可见、人工可接管**:不是无头截屏或转播,用户随时能看到页面并直接接手操作。
11
- - **DOM 级驱动,框架友好**:React/Vue 受控组件也能可靠填写。
12
- - **并发安全**:任务级浏览器会话隔离,多个任务并行互不抢页面、不互相污染。
13
- - **面向真实世界**:人机验证识别、登录态持久化、批量填表、带登录态下载、操作回放、动作限制,一应俱全。
15
+ ## 文档
14
16
 
15
- ## 功能
17
+ | 目标 | 入口 |
18
+ | --- | --- |
19
+ | 了解插件为什么存在、与无头方案的区别 | [为什么做共享真实浏览器](docs/why-browser.md) |
20
+ | 安装、配置与日常使用 | [用户指南](docs/user-guide.md) |
21
+ | 全部 20 个工具的参数、输出与示例 | [工具参考](docs/tool-reference.md) |
22
+ | 了解 seam / provider / 工具三层与自托管实现 | [架构说明](docs/architecture.md) |
23
+ | 查看全部文档与 README 分工 | [文档索引](docs/README.md) |
16
24
 
17
- **浏览器能力**
25
+ ## 这是什么
18
26
 
19
- - **真实视图,而非转播。** 浏览器是原生视图(`WebContentsView`),用户可直接看到并操作;agent 驱动的是同一个页面。视图由宿主外壳提供,插件负责驱动。
20
- - **DOM 引用,而非猜坐标。** `browser_snapshot` 返回带编号的交互元素;`browser_execute` 在页面里执行 JS(框架输入用原生 setter),在 React/Vue 页面上也能可靠交互。
21
- - **多标签会话。** 并行打开 URL、查看/切换/关闭/重置标签,状态保持。
22
- - **多格式内容。** 以 html / markdown / txt / json 抓取页面,支持 selector 限定、长度与超时上限。
27
+ `dsh-builtin-browser` 给 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 提供浏览器能力:
23
28
 
24
- **工程化能力**
29
+ - **真实视图,而非转播**:浏览器是原生 `WebContentsView`,用户直接看到 agent 在做什么,随时可以上手接管;
30
+ - **装好即用**:有桌面外壳时嵌入外壳视图;纯 `dsh web` 也能**自托管**——插件自己拉起一个 Electron 窗口,不需要任何额外配置;
31
+ - **一插件即一套工具**:安装后 agent 自动获得 20 个 `browser_*` 工具(打开、查看、操作、填表、截图、下载、登录态管理……)。
25
32
 
26
- - **按任务隔离。** 每个 DSH 任务(会话)拥有独立的浏览器会话(独立标签页与历史),并发任务互不干扰;同一任务内多次调用复用同一会话(`browser_session` / `browser_reset_session`)。
27
- - **登录态持久化。** `browser_auth` 导出/恢复 cookie,重启后登录态不丢。
28
- - **人机验证识别。** 自动检测 Cloudflare / reCAPTCHA / hCaptcha / Turnstile 等挑战(`browser_challenge`,快照也会标注),提示人工在共享窗口完成,不再盲目重试。
29
- - **批量表单填充。** `browser_fill` 一次填写多个字段:按选择器/名称/标签匹配,支持受控输入、下拉、单选/复选,可选提交。
30
- - **操作历史与回放。** `browser_history` 记录操作日志,`browser_replay` 可回放某一步。
31
- - **带登录态下载。** `browser_download` 用会话 cookie 把文件取到本地,登录后内容可直接落盘。
32
- - **安全限制。** `browser_restrict` 限制允许的浏览器动作,防误点/误导航。
33
+ 一句话:**安装插件 = 获得一个与用户共享、可被 agent 驱动的真实浏览器。**
33
34
 
34
- ## 环境要求
35
-
36
- - DeepSeek Harness(dsh)且安装了 `web` profile
37
- - **Electron 运行时**(可选 peer 依赖):桌面外壳自带;纯 `dsh web` 下需要能定位到 Electron 二进制(见下)
38
- - 有桌面外壳(`ctx.electronViewHost`)时用外壳嵌入视图;没有时插件**自托管**:自己拉起一个 Electron 窗口,`browser_*` 工具照常可用
39
-
40
- **Electron 定位顺序**:① `require('electron')`(peer 依赖已装)→ ② DSH 安装锚点 → ③ `node_modules/.pnpm` 虚拟仓库 → ④ `ELECTRON_PATH` 环境变量。找不到时工具会报清晰的错误提示。
41
-
42
- ### 验证过的版本
43
-
44
- | 组件 | 版本 |
45
- |---|---|
46
- | DeepSeek Harness(dsh) | `0.1.0-rc.5` |
47
- | Electron | `43.4.0` |
48
- | Node.js | `22.20.0` |
49
- | dsh-builtin-browser | `0.1.7` |
50
- | 操作系统 | Windows 10 (10.0.26200) |
51
-
52
- > 插件声明 `electron >= 30`;其他平台(如 macOS/Linux)按同一协议运行,但仅在上表 Windows 环境实测。
53
-
54
- ## 安装
35
+ ## 快速开始
55
36
 
56
37
  ```sh
57
- dsh plugin --profile web add dsh-builtin-browser # 发布到 npm 后
58
- # 或从源码目录(独立仓库,一插件一仓库):
38
+ # 方式一:从 npm 安装(已发布)
39
+ dsh plugin --profile web add dsh-builtin-browser
40
+
41
+ # 方式二:从源码目录安装(独立仓库,一插件一仓库)
59
42
  dsh plugin --profile web add <本仓库路径>
60
43
  ```
61
44
 
62
- 这会链接插件、把 `dsh-builtin-browser` 加入 profile 的 bundle 层,并挂载:
45
+ 安装后,agent 即可使用浏览器工具,例如:
46
+
47
+ | 想做什么 | 用哪个工具 | 说明 |
48
+ | --- | --- | --- |
49
+ | 打开页面 | `browser_open` | 打开 URL,返回带编号元素的快照 |
50
+ | 了解页面 | `browser_snapshot` | 输入框/按钮/链接的编号清单,可据此定位 |
51
+ | 操作页面 | `browser_execute` | 在页面里执行 JS(原生 setter,框架友好) |
52
+ | 填写表单 | `browser_fill` | 一次填写多个字段,可选提交 |
53
+ | 看到页面 | `browser_screenshot` | PNG 截图,可存文件交给视觉模型 |
54
+
55
+ 完整清单见[工具参考](#工具参考)。
56
+
57
+ ## 主要功能
58
+
59
+ <table>
60
+ <tr>
61
+ <td width="50%" valign="top">
62
+ <h3>共享真实浏览器</h3>
63
+ <p>原生视图而非无头截屏。用户与 agent 操作同一个页面:用户能看到每一步,随时接管;agent 驱动的就是用户眼前那个窗口。</p>
64
+ </td>
65
+ <td width="50%" valign="top">
66
+ <h3>DOM 级驱动,框架友好</h3>
67
+ <p><code>browser_snapshot</code> 返回带编号的交互元素;<code>browser_execute</code> 在页面内执行 JS(受控输入用原生 setter + input/change 事件),React/Vue 页面也能可靠交互。</p>
68
+ </td>
69
+ </tr>
70
+ <tr>
71
+ <td width="50%" valign="top">
72
+ <h3>多标签会话</h3>
73
+ <p>并行打开 URL,查看/切换/关闭/重置标签,每个会话的状态独立保持。</p>
74
+ </td>
75
+ <td width="50%" valign="top">
76
+ <h3>多格式内容</h3>
77
+ <p>以 html / markdown / txt / json 抓取页面,支持 CSS selector 限定、字符上限与超时控制。</p>
78
+ </td>
79
+ </tr>
80
+ <tr>
81
+ <td width="50%" valign="top">
82
+ <h3>任务级会话隔离</h3>
83
+ <p>每个 DSH 任务(会话)拥有独立的浏览器会话(独立标签页与历史),并发任务互不抢页面、互不污染;同一任务内多次调用复用同一会话。</p>
84
+ </td>
85
+ <td width="50%" valign="top">
86
+ <h3>登录态持久化</h3>
87
+ <p><code>browser_auth</code> 导出/恢复 cookie,重启后登录态不丢;自托管实例的 cookie 本身也落盘持久。</p>
88
+ </td>
89
+ </tr>
90
+ <tr>
91
+ <td width="50%" valign="top">
92
+ <h3>人机验证识别</h3>
93
+ <p>自动检测 Cloudflare / reCAPTCHA / hCaptcha / Turnstile 等挑战(<code>browser_challenge</code>,快照也会标注),提示人工在共享窗口完成,不再盲目重试。</p>
94
+ </td>
95
+ <td width="50%" valign="top">
96
+ <h3>批量表单填充</h3>
97
+ <p><code>browser_fill</code> 一次填写多个字段:按选择器/名称/标签匹配,支持受控输入、下拉、单选/复选,可选提交;单个字段失败不影响其余字段。</p>
98
+ </td>
99
+ </tr>
100
+ <tr>
101
+ <td width="50%" valign="top">
102
+ <h3>操作历史与回放</h3>
103
+ <p><code>browser_history</code> 记录操作日志(打开/执行/点击/输入/填表/下载/登录),<code>browser_replay</code> 可按序号回放某一步。</p>
104
+ </td>
105
+ <td width="50%" valign="top">
106
+ <h3>带登录态下载</h3>
107
+ <p><code>browser_download</code> 在页面上下文内携带会话 cookie 拉取文件并落盘,登录后才能访问的内容也能直接下载。</p>
108
+ </td>
109
+ </tr>
110
+ <tr>
111
+ <td width="50%" valign="top">
112
+ <h3>安全限制</h3>
113
+ <p><code>browser_restrict</code> 限制允许的浏览器动作(白名单),防止 agent 误点、误导航;只读工具(snapshot/content/screenshot)不受限。</p>
114
+ </td>
115
+ <td width="50%" valign="top">
116
+ <h3>截图即存即读</h3>
117
+ <p><code>browser_screenshot</code> 支持 <code>savePath</code> 直接落盘 PNG,交给视觉模型(modlens 等)做基于视觉的元素定位。</p>
118
+ </td>
119
+ </tr>
120
+ </table>
121
+
122
+ ## 为什么选它
123
+
124
+ - **装好即用,零配置**:不需要桌面外壳、不需要额外启动步骤;纯 `dsh web` 环境自托管拉起 Electron 窗口,`browser_*` 工具照常可用。
125
+ - **人机协同,互不干扰**:用户能看到并接管 agent 的每一个动作;任务级会话隔离让多个并行任务各自拥有独立的标签页与历史。
126
+ - **面向真实世界的自动化**:人机验证识别、登录态持久化、批量填表、带登录态下载、操作回放、动作限制——把"真实浏览器"变成可靠的 agent 能力。
127
+ - **可测试、可替换的架构**:provider 与 Electron 通过 `ElectronBrowserViewHost` 接缝解耦,同一套工具层未来可对接无头转播 provider,无需改动模型侧。
128
+
129
+ ## 工具参考
130
+
131
+ | 工具 | 用途 | 守卫 |
132
+ | --- | --- | --- |
133
+ | `browser_open` | 打开 URL(可选新标签),返回页面快照 | ✅ |
134
+ | `browser_snapshot` | 交互元素(输入框/按钮/链接)带编号清单 | – |
135
+ | `browser_execute` | 在页面执行 JS;参数以 `arguments[0..n]` 传入 | ✅ |
136
+ | `browser_content` | 以 html / markdown / txt / json 抓取页面(selector、maxChars、timeoutMs) | – |
137
+ | `browser_click` | 按视口坐标点击(配合截图做视觉定位) | ✅ |
138
+ | `browser_type` | 向聚焦元素输入文本(CDP `Input.insertText`) | ✅ |
139
+ | `browser_fill` | 批量填充表单(选择器/名称/标签匹配,受控输入、下拉、单选/复选,可选提交) | ✅ |
140
+ | `browser_screenshot` | PNG 截图,可选 `fullPage` 与 `savePath` | – |
141
+ | `browser_list_tabs` | 当前会话的标签列表 | – |
142
+ | `browser_switch_tab` | 按 id 切换标签(自托管下同步切换可见视图) | ✅ |
143
+ | `browser_close_tab` | 按 id 关闭标签;关闭活动标签后激活下一个 | – |
144
+ | `browser_reset` | 关闭本任务所有标签,回到一个空白标签 | ✅ |
145
+ | `browser_session` | 查看本任务的浏览器会话与标签 | – |
146
+ | `browser_reset_session` | 关闭并重建本任务的浏览器会话 | ✅ |
147
+ | `browser_history` | 操作日志(最新在后),含成功/失败与结果摘要 | – |
148
+ | `browser_replay` | 按序号回放某一步(navigate/execute/click/type) | ✅ |
149
+ | `browser_download` | 带会话 cookie 下载 URL 到本地文件(上限 256MB) | ✅ |
150
+ | `browser_auth` | 导出/恢复 cookie(登录态持久化,自托管可用) | ✅ |
151
+ | `browser_challenge` | 检测人机验证(CAPTCHA / Cloudflare / reCAPTCHA / hCaptcha / Turnstile) | – |
152
+ | `browser_restrict` | 限制允许的浏览器动作(白名单;空列表解除) | – |
153
+
154
+ > 「守卫」列:打 ✅ 的动作受 `browser_restrict` 白名单约束;只读工具(snapshot/content/screenshot/list_tabs/session/challenge/history)永不拦截。
63
155
 
64
- | 行 | 子路径 | 角色 |
65
- |---|---|---|
66
- | `browser` | `dsh-builtin-browser/browser` | `ctx.browser` 能力 seam(始终挂载) |
67
- | `browser-electron` | `dsh-builtin-browser/browser-electron` | Electron CDP provider(需要 `electronViewHost`) |
68
- | `tool-browser` | `dsh-builtin-browser/tool-browser` | `browser_*` 模型侧工具 |
156
+ ### 操作纪律(点击/填表)
69
157
 
70
- provider 与工具以 `ctx.get('electronViewHost')` 是否存在为门控,因此没有桌面外壳的组合只会保留 seam,其余不启用。
158
+ - **优先用 DOM 语义而非坐标**:表单提交优先 `form.requestSubmit()`;点击优先 `element.click()`;坐标点击是最后手段。
159
+ - **选中正确的元素**:页面常有隐藏副本(如移动端按钮),用 `browser_execute` 过滤可见元素(`getBoundingClientRect()` 宽高 > 0、`getComputedStyle` 非 `display:none`),再取坐标。
160
+ - **取坐标后立即点击**:中间不要插入其他操作(填表、滚动会移动元素,旧坐标立即失效)。
161
+ - **点击前验证命中**:`document.elementFromPoint(x, y)` 确认该坐标确实是目标元素(按钮/链接),再执行真实点击。
162
+ - **DPR 注意**:CDP 输入使用 CSS 像素;高 DPI 屏上若点击落空,用 `elementFromPoint` 校准,不要盲试坐标。
71
163
 
72
164
  ## 配置
73
165
 
74
- 插件通过 `cordis.patch.yml` 挂载,各行的配置:
166
+ 插件通过 `cordis.patch.yml` 挂载三行,各行配置:
75
167
 
76
168
  | 行 | 配置项 | 类型 | 默认 | 说明 |
77
- |---|---|---|---|---|
169
+ | --- | --- | --- | --- | --- |
78
170
  | `browser-electron` | `viewHost` | 对象 | 必填 | 宿主提供的 `ElectronBrowserViewHost` 实例(通常 `!!js ctx.get('electronViewHost')`) |
79
171
  | `browser-electron` | `httpOnly` | 布尔 | `true` | 仅允许 HTTP(S) 导航;其余协议(如 `file:`/`data:`)拒绝(`BROWSER_NAVIGATION_BLOCKED`) |
80
172
  | `browser-electron` | `snapshotMaxElements` | 数字 | `60` | 快照最多收录的交互元素数,超出截断 |
@@ -82,32 +174,6 @@ provider 与工具以 `ctx.get('electronViewHost')` 是否存在为门控,因此
82
174
  | `tool-browser` | `timeoutMs` | 数字 | `60000` | 工具协作超时(ms) |
83
175
  | `tool-browser` | `tabTools` | 布尔 | `true` | 是否注册标签管理工具(`browser_list_tabs` 等) |
84
176
 
85
- ## 工具
86
-
87
- | 工具 | 用途 |
88
- |---|---|
89
- | `browser_open` | 打开 URL(可选新标签);返回快照 |
90
- | `browser_snapshot` | 交互元素(输入框/按钮/链接)带编号清单 |
91
- | `browser_execute` | 在页面执行 JS;参数以 `arguments[0..n]` 传入 |
92
- | `browser_content` | 以 html / markdown / txt / json 抓取页面(selector、maxChars、timeoutMs) |
93
- | `browser_screenshot` | PNG 截图,可选 `fullPage` |
94
- | `browser_list_tabs` / `browser_switch_tab` / `browser_close_tab` / `browser_reset` | 多标签会话管理 |
95
- | `browser_session` / `browser_reset_session` | 查看/重置当前任务的浏览器会话(按任务隔离) |
96
- | `browser_history` / `browser_replay` | 查看操作记录并回放某一步 |
97
- | `browser_download` | 带会话 cookie 下载 URL 到本地文件 |
98
- | `browser_restrict` | 限制允许的浏览器动作,防误点/误导航 |
99
- | `browser_auth` | 导出/恢复 cookie,持久化登录态 |
100
- | `browser_challenge` | 检测人机验证(CAPTCHA / Cloudflare / reCAPTCHA / hCaptcha / Turnstile)是否拦截当前页 |
101
- | `browser_fill` | 批量填充表单(选择器/名称/标签匹配,支持受控输入、下拉、单选/复选,可选提交) |
102
-
103
- ### 操作纪律(点击/填表)
104
-
105
- - **优先用 DOM 语义而非坐标**:表单提交优先 `form.requestSubmit()`;点击优先 `element.click()`;坐标点击是最后手段。
106
- - **选中正确的元素**:页面常有隐藏副本(如移动端按钮),用 `browser_execute` 过滤可见元素(`getBoundingClientRect()` 宽高 > 0、`getComputedStyle` 非 `display:none`),再取坐标。
107
- - **取坐标后立即点击**:中间不要插入其他操作(填表、滚动会移动元素,旧坐标立即失效)。
108
- - **点击前验证命中**:`document.elementFromPoint(x, y)` 确认该坐标确实是目标元素(按钮/链接),再执行真实点击。
109
- - **DPR 注意**:CDP 输入使用 CSS 像素;高 DPI 屏上若点击落空,用 `elementFromPoint` 校准,不要盲试坐标。
110
-
111
177
  ## 工作原理
112
178
 
113
179
  ```
@@ -118,26 +184,73 @@ agent (browser_* 工具)
118
184
  → WebContentsView + webContents.debugger (CDP)
119
185
  ```
120
186
 
121
- provider 按构造与 Electron 解耦:它通过 `ElectronBrowserViewHost` 接缝操作(创建/销毁/显示视图、`sendCommand`),由真实外壳用 Electron 对象实现。同一接缝也让未来的转播 provider(无头 Chromium 截图流)服务远程部署,而无需改动工具。
187
+ - **seam 层**(`browser` 行)提供 `ctx.browser` 服务:provider 注册、会话生命周期、错误码,与具体实现解耦;
188
+ - **provider 层**(`browser-electron` 行)通过 `ElectronBrowserViewHost` 接缝操作视图(创建/销毁/显示/`sendCommand`),由真实外壳用 Electron 对象实现;
189
+ - **工具层**(`tool-browser` 行)提供模型侧的 20 个 `browser_*` 工具,按调用方任务(DSH 会话)维护独立的浏览器会话。
190
+
191
+ **自托管模式**:没有桌面外壳时,插件自己拉起一个 Electron 子进程(`host-main.js`),通过本机 TCP JSON-RPC 驱动,窗口标题 `dsh-browser`。子进程崩溃会自动重启;截图优先走 Electron 原生 `capturePage`(CDP 截图在多视图下会挂起),并自动选择环境中**最新版本**的 Electron(33.x 有合成器缺陷,建议 ≥ 40)。
192
+
193
+ **Electron 定位顺序**:① `require('electron')`(peer 依赖)→ ② `ELECTRON_PATH`(显式覆盖)→ ③ DSH 安装锚点与 pnpm 虚拟仓库中**版本最新**者。找不到时工具会报清晰的错误提示。
122
194
 
123
195
  ## 与桌面外壳的分工
124
196
 
125
- 浏览器**可见视图**、**浏览器列布局**、**列与视图的对齐**都属于宿主外壳(如 dsh 的 `apps/desktop`),不在本插件内。本插件只消费外壳提供的 `electronViewHost`,负责 seam、provider 与工具。若你只装插件而没有配套外壳,插件功能保持禁用。
197
+ 浏览器**可见视图**、**浏览器列布局**、**列与视图的对齐**都属于宿主外壳(如 dsh 的 `apps/desktop`),不在本插件内。本插件只消费外壳提供的 `electronViewHost`,负责 seam、provider 与工具。没有配套外壳时插件**自托管**,功能照常可用。
198
+
199
+ ## 环境要求
200
+
201
+ - DeepSeek Harness(dsh)且安装了 `web` profile
202
+ - **Electron 运行时**(可选 peer 依赖):桌面外壳自带;纯 `dsh web` 下插件自动定位 Electron 二进制(见上,建议 ≥ 40)
203
+
204
+ ### 验证过的版本
205
+
206
+ | 组件 | 版本 |
207
+ | --- | --- |
208
+ | DeepSeek Harness(dsh) | `0.1.0-rc.5` |
209
+ | Electron | `43.4.0`(推荐 ≥ 40;33.x 存在合成器缺陷) |
210
+ | Node.js | `22.20.0` |
211
+ | dsh-builtin-browser | `0.1.11` |
212
+ | 操作系统 | Windows 10 (10.0.26200) |
213
+
214
+ > 插件声明 `electron >= 30`;其他平台(macOS/Linux)按同一协议运行,但仅在上表 Windows 环境实测。
126
215
 
127
216
  ## 已知限制
128
217
 
129
218
  - 截图仅 PNG(CDP JPEG 在 Electron 43 上挂起);JPEG 等待非 CDP 转换路径。
130
219
  - 自托管截图优先走 Electron 原生 `capturePage`(CDP `captureScreenshot` 在多视图下会挂起);截图前自动把目标标签置顶。
131
- - **Electron 版本建议 ≥ 40**:33.x 存在合成器缺陷,会间歇性导致截图失败("display surface not available")。插件会**自动选择环境中最新版本的 Electron**(peer 依赖 > `ELECTRON_PATH` > 锚点/pnpm store 中最新版)。
132
220
  - 部分主机在软件合成下 `fullPage` 截图不稳定。
133
- - 会话按任务隔离:每个调用方任务(DSH 会话)拥有独立的浏览器会话(独立标签页与历史),并发任务互不干扰;同一任务的多次调用复用同一会话。登录态(cookie)为共享,可用 `browser_auth` 导出/恢复。
134
- - 人机验证(CAPTCHA)无法自动解决:快照会标注检测到的挑战(`browser_challenge` 可显式检查),此时应请用户在共享窗口中人工完成,而不是反复重试。
221
+ - 人机验证(CAPTCHA)无法自动解决:快照会标注检测到的挑战,此时应请用户在共享窗口中人工完成,而不是反复重试。
135
222
  - 无痕模式(`privateMode`)未实现:它需要 Electron 的 session 分区能力,属于宿主层,本插件不承诺。
136
223
  - `browser_download` 在页面上下文内 `fetch`(带登录态),受同源/CORS 约束;单文件上限 256MB。
137
224
  - `browser_auth` 的 cookie 往返不保留 `hostOnly`/`sameSite` 字段(host-only cookie 恢复后变成 domain cookie);仅自托管浏览器可用。
138
225
  - 自托管浏览器子进程崩溃后会自动重启,但崩溃前已打开的会话视图已失效,调用 `browser_reset_session` 重建即可。
139
226
  - 本插件不含浏览器列 UI——那是宿主外壳的配套,别把"浏览器列"当成插件能力。
140
227
 
141
- ## 许可证
228
+ ## 开发
229
+
230
+ ```sh
231
+ # 类型检查 + 构建(lib/)
232
+ pnpm run build
233
+
234
+ # 功能测试:启动本地页面服务器 + Electron probe(见仓库测试脚本)
235
+ ```
236
+
237
+ 代码结构:
238
+
239
+ | 目录 | 职责 |
240
+ | --- | --- |
241
+ | `src/browser/` | `ctx.browser` seam 与全部请求/结果类型 |
242
+ | `src/browser-electron/` | Electron CDP provider、自托管子进程(`host-main.ts`)与 RPC 层 |
243
+ | `src/tool-browser/` | 模型侧 `browser_*` 工具 |
244
+ | `src/types/` | electron 环境类型(shim,避免强制依赖 electron 类型) |
245
+
246
+ ## 特别感谢
247
+
248
+ 特别感谢 [DeepSeek Harness 原始仓库](https://github.com/deepseek-ai/deepseek-harness) 与 DeepSeek AI 团队:本插件的 seam、工具运行时与插件体系都构建在这个项目之上。
249
+
250
+ 同时感谢 [Cordis](https://github.com/cordiverse/cordis) 提供的插件化基础,以及所有参与讨论、测试、反馈和插件开发的社区成员。
251
+
252
+ ## License
253
+
254
+ 本项目遵循 [MIT License](LICENSE)。
142
255
 
143
- MIT
256
+ > 本项目是 DeepSeek Harness 的社区插件,并非 DeepSeek 官方产品。
package/docs/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # dsh-builtin-browser 文档索引
2
+
3
+ 按"你想做什么"选择入口:
4
+
5
+ | 目标 | 入口 |
6
+ | --- | --- |
7
+ | 了解插件为什么存在、与无头方案的区别 | [为什么做共享真实浏览器](why-browser.md) |
8
+ | 安装、配置、日常使用与常见问题 | [用户指南](user-guide.md) |
9
+ | 全部 20 个工具的参数、输出与示例 | [工具参考](tool-reference.md) |
10
+ | 了解 seam / provider / 工具三层与自托管实现 | [架构说明](architecture.md) |
11
+ | 回到项目首页 | [README](../README.md) |
12
+
13
+ ## 各篇概览
14
+
15
+ - **[为什么做共享真实浏览器](why-browser.md)** — 定位、设计理念、与 Playwright 等无头方案的对比、边界与取舍。
16
+ - **[用户指南](user-guide.md)** — 环境要求、安装、配置项、快速上手、操作纪律、FAQ 与故障排查。
17
+ - **[工具参考](tool-reference.md)** — 每个 `browser_*` 工具的参数、输出、守卫与示例。
18
+ - **[架构说明](architecture.md)** — 三层结构、`ElectronBrowserViewHost` 接缝、自托管 RPC 子进程、截图通道、Electron 版本选择。
@@ -0,0 +1,75 @@
1
+ # 架构说明
2
+
3
+ ## 三层结构
4
+
5
+ ```
6
+ agent (browser_* 工具)
7
+ → ctx.browser (seam, dsh-builtin-browser/browser)
8
+ → dsh-builtin-browser/browser-electron (provider)
9
+ → ElectronBrowserViewHost (由宿主外壳提供)
10
+ → WebContentsView + webContents.debugger (CDP)
11
+ ```
12
+
13
+ ### seam 层(`src/browser/`)
14
+
15
+ `BrowserRuntime` 以 Cordis Service 形式注册为 `ctx.browser`:
16
+
17
+ - **provider 注册**:`registerBrowserProvider(provider)` 登记一个实现 `BrowserProvider` 接口的 provider,重名抛 `BROWSER_DUPLICATE_PROVIDER`;disposer 挂在注册方自身的 fiber 上,插件重载时正确清理。
18
+ - **provider 选择**(执行期解析,不依赖顺序):
19
+ - 配置了 id 且注册且可用 → 该 provider
20
+ - 配置了 id 但未注册 → `BROWSER_PROVIDER_CONFIGURED_MISSING`
21
+ - 配置了 id 但不可用 → `BROWSER_PROVIDER_CONFIGURED_UNAVAILABLE`
22
+ - 未配置、恰一个可用 → 自动选择
23
+ - 未配置、多个可用 → `BROWSER_PROVIDER_AMBIGUOUS`
24
+ - 未配置、无可用 → `BROWSER_PROVIDER_UNAVAILABLE`
25
+ - 所有请求/结果类型(`BrowserProvider` 接口、`BrowserError` 错误码)定义在 `src/browser/types.ts`。
26
+
27
+ ### provider 层(`src/browser-electron/`)
28
+
29
+ `ElectronBrowserProvider` 通过 `ElectronBrowserViewHost` 接缝操作视图,与 Electron 解耦:
30
+
31
+ - 会话 = 有序标签列表 + 历史;每次 `open()` 新建会话(工具层按任务缓存复用);
32
+ - 每个标签对应一个视图(handle);`showActive` 让宿主把活动标签的视图置顶;
33
+ - 页面驱动全部走 CDP:`Page.navigate` / `Runtime.evaluate` / `Input.dispatchMouseEvent` / `Input.insertText` / `Page.captureScreenshot`(兜底);
34
+ - **截图优先走宿主原生 `capturePage`**(新增 `capture` 通道):CDP `captureScreenshot` 在窗口存在多个(隐藏)视图时会挂起,原生捕获对可见视图快速可靠,失败时自动回退 CDP(临时摘除其他视图保证单视图状态);
35
+ - 所有 CDP 调用都有超时兜底(`withTimeout`),避免卡死工具调用;
36
+ - 历史记录单调递增的 seq,截断(500 条)后不回绕;失败导航只记一条。
37
+
38
+ ### 工具层(`src/tool-browser/`)
39
+
40
+ 20 个 `browser_*` 工具,按**调用方任务**(`exec.agent.id`)维护独立浏览器会话:
41
+
42
+ - 会话缓存 `sessionsByTask`:同一任务复用同一会话,并发首开去重;
43
+ - `browser_reset_session` 关闭本任务会话并遗忘映射(即使 close 抛错也清除,下次调用重建);
44
+ - `browser_restrict` 维护模块级白名单,守卫所有非只读工具;
45
+ - 输出 schema 与返回值严格一致(DSH 运行时会校验,`additionalProperties: false` 下多一个字段都会报错)。
46
+
47
+ ## 自托管实现(纯 `dsh web`)
48
+
49
+ 没有桌面外壳时,`RemoteElectronViewHost` 接管:
50
+
51
+ ```
52
+ 父进程(DSH) 子进程(Electron main)
53
+ RemoteElectronViewHost ──TCP JSON-RPC──▶ host-main.js
54
+ resolveElectronPath() BrowserWindow('dsh-browser')
55
+ ElectronChildClient WebContentsView × N
56
+ DeferredRemoteView(物化缓存) webContents.debugger(CDP)
57
+ ```
58
+
59
+ - **协议**:本机 loopback TCP,每行一个 JSON(`{ id, op, ... }` ↔ `{ id, ok, result|err }`);
60
+ - **Electron 定位**:① peer 依赖 → ② `ELECTRON_PATH` → ③ 锚点与 pnpm store 中**版本最新**者(33.x 有合成器缺陷,建议 ≥ 40);
61
+ - **稳健性**:子进程/套接字都有 `error` 监听(否则未捕获事件会炸掉整个 DSH 进程);子进程退出自动重启;物化失败可重试;下载有 256MB 上限与 60s 超时;cookie 导出/恢复有 30s 超时;
62
+ - **视图可见性**:多标签/多会话时,`showView` 隐藏其他视图并把目标视图置顶(remove+re-add),确保用户看到的是活动标签;
63
+ - **孤儿防护**:父进程断开时子进程自动退出,不留僵尸窗口;
64
+ - **cookie 落盘**:子进程使用独立 userData 目录(`<DSH_HOME>/dsh-builtin-browser-host`),登录态跨重启保留(另有 `browser_auth` 手动导出/恢复)。
65
+
66
+ ## 关键设计决策
67
+
68
+ | 决策 | 原因 |
69
+ | --- | --- |
70
+ | 任务级会话隔离,共享 cookie | 并行任务不抢页面;登录一次到处可用 |
71
+ | 原生 capturePage 优先,CDP 兜底 | CDP 截图多视图挂起;原生捕获窗口未激活时失败——两通道互补 |
72
+ | 自动选最新 Electron | 33.x 合成器缺陷导致截图间歇失败 |
73
+ | 独立 userData | 多实例争用默认目录导致 GPU 缓存/会话锁冲突 |
74
+ | withTimeout 全覆盖 | 卡死的 CDP 调用必须能被工具超时兜底 |
75
+ | 输出 schema 严格匹配 | DSH 运行时会校验返回值,多字段即报错 |
@@ -0,0 +1,82 @@
1
+ # 工具参考
2
+
3
+ 全部 20 个 `browser_*` 工具。守卫列:✅ 表示该动作受 `browser_restrict` 白名单约束;只读工具永不拦截。
4
+
5
+ ## 页面与导航
6
+
7
+ | 工具 | 参数 | 输出 | 守卫 | 说明 |
8
+ | --- | --- | --- | --- | --- |
9
+ | `browser_open` | `url`(必填), `newTab?` | 快照(url/title/elements/truncated/challenge) | ✅ | 打开 URL,返回带编号元素的快照;`newTab: true` 在新标签打开 |
10
+ | `browser_snapshot` | – | 快照 | – | 交互元素(输入框/按钮/链接)编号清单,供定位与点击 |
11
+ | `browser_content` | `format`(html/markdown/txt/json,必填), `selector?`, `maxChars?`, `timeoutMs?` | `{ content, truncated }` | – | 抓取页面内容;`selector` 限定区域 |
12
+ | `browser_challenge` | – | `{ blocked, kind?, reason?, hint? }` | – | 检测人机验证(CAPTCHA/Cloudflare/reCAPTCHA/hCaptcha/Turnstile);阻塞时请用户处理 |
13
+
14
+ ## 页面操作
15
+
16
+ | 工具 | 参数 | 输出 | 守卫 | 说明 |
17
+ | --- | --- | --- | --- | --- |
18
+ | `browser_execute` | `script`(必填), `args?` | `{ ok, value? / exception? }` | ✅ | 在页面执行 JS;脚本以 `return` 开头或作为表达式;`args` 以 `arguments[0..n]` 传入 |
19
+ | `browser_click` | `x`, `y`(必填) | `{ clicked }` | ✅ | 视口坐标点击(配合截图做视觉定位) |
20
+ | `browser_type` | `text`(必填) | `{ typed }` | ✅ | 向聚焦元素输入文本(CDP `Input.insertText`) |
21
+ | `browser_fill` | `fields`(必填,数组), `submit?` | `{ fields[], submitted }` | ✅ | 批量填表;字段按 `selector`/`name`/`label`/`placeholder` 匹配,值支持字符串/数字/布尔;单个字段失败不影响其余;`submit: true` 提交表单 |
22
+
23
+ ## 标签与会话
24
+
25
+ | 工具 | 参数 | 输出 | 守卫 | 说明 |
26
+ | --- | --- | --- | --- | --- |
27
+ | `browser_list_tabs` | – | `{ session, tabs[] }` | – | 当前会话的标签列表 |
28
+ | `browser_switch_tab` | `tabId`(必填) | `{ switched }` | ✅ | 按 id 切换标签;自托管下同步切换可见视图 |
29
+ | `browser_close_tab` | `tabId`(必填) | `{ closed }` | – | 关闭标签;关闭活动标签后激活下一个 |
30
+ | `browser_reset` | – | `{ reset }` | ✅ | 关闭本任务所有标签,回到一个空白标签 |
31
+ | `browser_session` | – | `{ session, tabs[] }` | – | 查看本任务的浏览器会话与标签 |
32
+ | `browser_reset_session` | – | `{ reset }` | ✅ | 关闭并重建本任务的浏览器会话(崩溃/卡死后恢复) |
33
+
34
+ ## 历史与下载
35
+
36
+ | 工具 | 参数 | 输出 | 守卫 | 说明 |
37
+ | --- | --- | --- | --- | --- |
38
+ | `browser_history` | – | `{ entries[] }` | – | 操作日志(最新在后),含 seq/action/ok/params/result/error |
39
+ | `browser_replay` | `seq`(必填) | `{ replayed }` | ✅ | 按序号回放某一步(navigate/execute/click/type) |
40
+ | `browser_download` | `url`(必填), `savePath`(必填) | `{ path }` | ✅ | 带会话 cookie 下载到本地(上限 256MB,受 CORS 约束) |
41
+
42
+ ## 登录态与安全
43
+
44
+ | 工具 | 参数 | 输出 | 守卫 | 说明 |
45
+ | --- | --- | --- | --- | --- |
46
+ | `browser_auth` | `action`(flush/restore,必填), `cookies?` | `{ cookies[]? / restored? }` | ✅ | 导出/恢复 cookie(自托管可用);flush 返回 cookie 列表,restore 带列表写回 |
47
+ | `browser_restrict` | `allowed?` | `{ restrictedTo[] }` | – | 设置动作白名单;空列表解除;未知工具名报错 |
48
+
49
+ ## 截图
50
+
51
+ | 工具 | 参数 | 输出 | 守卫 | 说明 |
52
+ | --- | --- | --- | --- | --- |
53
+ | `browser_screenshot` | `fullPage?`, `savePath?` | `{ dataUrl, path? }` | – | PNG 截图;`savePath` 落盘供视觉模型读取 |
54
+
55
+ ## 常用组合
56
+
57
+ **调研一个网站**
58
+ ```
59
+ browser_open https://site → browser_content format=markdown → browser_snapshot → 逐页浏览
60
+ ```
61
+
62
+ **登录并下载文件**
63
+ ```
64
+ browser_open https://site/login → browser_fill(用户名/密码) submit=true →
65
+ 等待跳转 → browser_download(url, savePath)
66
+ ```
67
+
68
+ **表单填写(React/Vue 页面)**
69
+ ```
70
+ browser_snapshot → browser_fill(fields=[{name:'email',value:'a@b.c'},{label:'密码',value:'***'}], submit=true)
71
+ ```
72
+
73
+ **误操作恢复**
74
+ ```
75
+ browser_reset_session → browser_open(重新开始)
76
+ ```
77
+
78
+ **遇到验证码**
79
+ ```
80
+ browser_challenge → 阻塞 → 提示用户:"页面出现人机验证,请在共享浏览器窗口完成,完成后告诉我" →
81
+ browser_snapshot 复查
82
+ ```
@@ -0,0 +1,94 @@
1
+ # 用户指南
2
+
3
+ ## 环境要求
4
+
5
+ - DeepSeek Harness(dsh)且安装了 `web` profile
6
+ - **Electron 运行时**(可选 peer 依赖):桌面外壳自带;纯 `dsh web` 下插件自动定位 Electron 二进制(建议 ≥ 40,33.x 存在截图合成器缺陷)
7
+
8
+ ## 安装
9
+
10
+ ```sh
11
+ # 从 npm 安装(已发布)
12
+ dsh plugin --profile web add dsh-builtin-browser
13
+
14
+ # 或从源码目录(独立仓库,一插件一仓库)
15
+ dsh plugin --profile web add <本仓库路径>
16
+ ```
17
+
18
+ 安装会链接插件、把 `dsh-builtin-browser` 加入 profile 的 bundle 层,并挂载三行:
19
+
20
+ | 行 | 子路径 | 角色 |
21
+ | --- | --- | --- |
22
+ | `browser` | `dsh-builtin-browser/browser` | `ctx.browser` 能力 seam(始终挂载) |
23
+ | `browser-electron` | `dsh-builtin-browser/browser-electron` | Electron CDP provider |
24
+ | `tool-browser` | `dsh-builtin-browser/tool-browser` | `browser_*` 模型侧工具 |
25
+
26
+ > 没有桌面外壳时插件**自托管**:自己拉起一个标题为 `dsh-browser` 的 Electron 窗口,`browser_*` 工具照常可用。
27
+
28
+ ## 配置
29
+
30
+ | 行 | 配置项 | 类型 | 默认 | 说明 |
31
+ | --- | --- | --- | --- | --- |
32
+ | `browser-electron` | `viewHost` | 对象 | 必填 | 宿主提供的 `ElectronBrowserViewHost`(通常 `!!js ctx.get('electronViewHost')`) |
33
+ | `browser-electron` | `httpOnly` | 布尔 | `true` | 仅允许 HTTP(S) 导航;`file:`/`data:` 等拒绝 |
34
+ | `browser-electron` | `snapshotMaxElements` | 数字 | `60` | 快照最多收录的交互元素数 |
35
+ | `browser-electron` | `contentMaxChars` | 数字 | `100000` | 内容抓取默认字符上限 |
36
+ | `tool-browser` | `timeoutMs` | 数字 | `60000` | 工具协作超时(ms) |
37
+ | `tool-browser` | `tabTools` | 布尔 | `true` | 是否注册标签管理工具 |
38
+
39
+ ## 快速上手(给 agent 的提示词示例)
40
+
41
+ ```
42
+ 1. browser_open 打开 https://example.com
43
+ 2. browser_snapshot 查看页面有哪些可交互元素(带编号)
44
+ 3. 需要填表时用 browser_fill(按 name/label/placeholder 匹配,一次填多个字段)
45
+ 4. 需要截图确认时用 browser_screenshot(可 savePath 存文件)
46
+ 5. 遇到验证码(browser_challenge 或快照标注 CHALLENGE)时,停下请用户处理
47
+ 6. 每次操作后告知用户你在页面上做了什么
48
+ ```
49
+
50
+ ## 操作纪律
51
+
52
+ - **优先用 DOM 语义而非坐标**:表单提交优先 `form.requestSubmit()`;点击优先 `element.click()`;坐标点击是最后手段。
53
+ - **选中正确的元素**:页面常有隐藏副本(如移动端按钮),用 `browser_execute` 过滤可见元素(`getBoundingClientRect()` 宽高 > 0、`getComputedStyle` 非 `display:none`),再取坐标。
54
+ - **取坐标后立即点击**:中间不要插入其他操作(填表、滚动会移动元素,旧坐标立即失效)。
55
+ - **点击前验证命中**:`document.elementFromPoint(x, y)` 确认该坐标确实是目标元素,再执行真实点击。
56
+ - **DPR 注意**:CDP 输入使用 CSS 像素;高 DPI 屏上若点击落空,用 `elementFromPoint` 校准,不要盲试坐标。
57
+
58
+ ## 多任务并行
59
+
60
+ 每个 DSH 会话(任务)拥有独立的浏览器会话(独立标签页与历史),并发任务互不干扰:
61
+
62
+ - `browser_session` 查看本任务的会话与标签;
63
+ - `browser_reset_session` 关闭并重建本任务的会话(崩溃或卡死后用它恢复)。
64
+
65
+ 登录态(cookie)为所有任务共享;可用 `browser_auth` 导出/恢复,重启后不丢。
66
+
67
+ ## FAQ
68
+
69
+ **Q:纯 `dsh web` 能用吗?**
70
+ 能。插件自托管:自己拉起 Electron 窗口,无需桌面外壳。
71
+
72
+ **Q:找不到 Electron?**
73
+ 插件按顺序自动定位:① peer 依赖 `require('electron')` → ② `ELECTRON_PATH` 环境变量 → ③ DSH 锚点与 pnpm 虚拟仓库中版本最新者。都找不到时报清晰错误,可 `dsh plugin --profile web add electron` 或设置 `ELECTRON_PATH`。
74
+
75
+ **Q:截图失败或挂起?**
76
+ 确保 Electron ≥ 40(33.x 有合成器缺陷)。自托管截图优先走原生 `capturePage`,多视图/窗口未激活时自动兜底到 CDP。
77
+
78
+ **Q:浏览器窗口不见了?**
79
+ 窗口标题为 `dsh-browser`(自托管)。若子进程崩溃会自动重启;重启后旧会话失效,调用 `browser_reset_session` 重建。
80
+
81
+ **Q:下载报 CORS 错误?**
82
+ `browser_download` 在页面上下文内 `fetch`,受同源/CORS 约束;跨域文件请先在同源页面内操作,或直接请求用户提供。
83
+
84
+ **Q:如何禁止 agent 乱点?**
85
+ `browser_restrict` 设置白名单(如只允许 `browser_snapshot`/`browser_content`);传空列表解除。
86
+
87
+ ## 故障排查
88
+
89
+ | 现象 | 可能原因 | 处理 |
90
+ | --- | --- | --- |
91
+ | `BROWSER_SESSION_UNKNOWN` | 子进程重启后旧会话失效 | `browser_reset_session` |
92
+ | 工具超时 | 页面卡死/未渲染完成 | 稍后重试;`browser_reset` 重置标签 |
93
+ | 导航被拒 | 非 HTTP(S) 协议 | 检查 URL;`httpOnly` 配置 |
94
+ | 快照为空 | 页面尚未加载 | 等待后重试 `browser_snapshot` |
@@ -0,0 +1,45 @@
1
+ # 为什么做共享真实浏览器
2
+
3
+ ## 问题
4
+
5
+ LLM agent 需要"上网"。传统做法是给 agent 一个**无头浏览器**(Playwright/Puppeteer 等)或**网页抓取工具**:
6
+
7
+ - 无头浏览器:agent 在看不见的页面里操作,用户无法确认它在做什么,也无法中途接管;遇到登录、验证码、人机检测时寸步难行。
8
+ - 网页抓取:只能读不能交互,且大量现代网站依赖 JS 渲染,抓到的内容失真。
9
+
10
+ 这两条路都绕开了"用户"——浏览器成了 agent 的私有工具,而不是用户和 agent 共用的工具。
11
+
12
+ ## 方案:共享真实浏览器
13
+
14
+ `dsh-builtin-browser` 的思路很朴素:**让 agent 驱动用户眼前那个真实的浏览器窗口**。
15
+
16
+ - 浏览器是原生 `WebContentsView`,用户直接看到 agent 的每一步操作(打开页面、填写表单、点击、滚动);
17
+ - 用户**随时可以上手接管**:输入、点击、登录、过验证码——做完之后 agent 继续;
18
+ - agent 通过 CDP 在同一个页面里执行 JS,拿到的是与用户所见完全一致的真实 DOM。
19
+
20
+ 一句话:浏览器不是 agent 的"黑盒工具",而是**用户与 agent 之间的共享工作台**。
21
+
22
+ ## 与无头方案的能力对比
23
+
24
+ | 能力 | 无头浏览器 | 网页抓取 | 本插件(共享真实浏览器) |
25
+ | --- | --- | --- | --- |
26
+ | 真实页面渲染 | ✅ | 部分 | ✅ |
27
+ | 复杂交互(填表/点击/拖拽) | ✅ | ❌ | ✅ |
28
+ | 用户可见、可接管 | ❌ | ❌ | ✅ |
29
+ | 保留登录态 | 需手动管理 | ❌ | ✅(`browser_auth` + cookie 落盘) |
30
+ | 人工处理验证码 | ❌ 卡死 | ❌ | ✅ 请用户点一下即可 |
31
+ | 多任务并行 | 需多实例 | – | ✅ 任务级会话隔离 |
32
+
33
+ ## 设计取舍
34
+
35
+ - **登录态共享**:所有任务共享同一份 cookie(符合"用户登录一次,agent 到处可用");需要隔离时用 `browser_auth` 手动导出/恢复。
36
+ - **任务级会话隔离**:每个 DSH 会话(任务)拥有独立的浏览器会话(标签页与历史),并发任务互不抢页面;但窗口只有一个,当前活动的任务视图可见。
37
+ - **装好即用**:不依赖桌面外壳。有外壳时嵌入外壳视图;纯 `dsh web` 时插件自托管——自己拉起 Electron 窗口,通过本机 TCP JSON-RPC 驱动。
38
+ - **边界清晰**:可见视图、浏览器列布局属于宿主外壳;插件只负责 seam、provider 与工具,不含任何 UI。
39
+ - **人机验证不硬刚**:检测到 Cloudflare/reCAPTCHA/hCaptcha/Turnstile 时停下,请用户在共享窗口人工完成,而不是盲目重试。
40
+
41
+ ## 什么场景不适合
42
+
43
+ - 需要**无头批量抓取**(成千上万页面):请用专门的抓取工具/服务,不必开窗口。
44
+ - 需要**每个任务完全独立的登录态**(互不可见):本插件默认共享 cookie;如需强隔离,可用多个 DSH 实例或 `browser_auth` 手动管理。
45
+ - 需要**浏览器列 UI / 布局管理**:那是宿主外壳的配套,本插件不包含。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-builtin-browser",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Shared real browser plugin for DeepSeek Harness: install-and-use — a visible native browser the human can take over, driven by the agent over CDP. DOM-level interaction (React/Vue safe), per-task session isolation, cookie persistence (browser_auth), CAPTCHA detection, batch form fill (browser_fill), authenticated download, history/replay, action restriction",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -31,6 +31,7 @@
31
31
  "files": [
32
32
  "lib",
33
33
  "src",
34
+ "docs",
34
35
  "cordis.patch.yml",
35
36
  "README.md",
36
37
  "README.en.md",