dsh-inner-browser-use 0.11.44 → 0.13.0
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.md +108 -75
- package/README.zh.md +88 -45
- package/client.js +473 -3276
- package/docs/ARCHITECTURE.md +183 -151
- package/docs/BENCH.md +124 -0
- package/docs/COMPATIBILITY.md +72 -102
- package/docs/ROADMAP.md +108 -0
- package/docs/VERIFY.md +80 -417
- package/index.js +227 -1117
- package/locale/en.json +11 -22
- package/locale/zh.json +11 -22
- package/package.json +9 -5
- package/scripts/doctor.mjs +89 -0
- package/sidecar.js +1323 -0
- package/docs/upstream/cookie-persistence.md +0 -52
package/docs/COMPATIBILITY.md
CHANGED
|
@@ -1,104 +1,74 @@
|
|
|
1
1
|
# Compatibility
|
|
2
2
|
|
|
3
|
-
What this plugin assumes, and what it
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
|
8
|
-
|
|
|
9
|
-
|
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
##
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
plugin then has only what the page already holds, so ask the page for the file
|
|
76
|
-
through its own UI.
|
|
77
|
-
- A file streams only while the page keeps answering. A page that navigates away
|
|
78
|
-
mid-save ends the transfer, and the call says so instead of writing half a file.
|
|
79
|
-
|
|
80
|
-
## Checking an install
|
|
81
|
-
|
|
82
|
-
Run these in the chat whose tab is open, in this order. Each line is what a
|
|
83
|
-
working install answers.
|
|
84
|
-
|
|
85
|
-
1. `browser_navigate` to `https://example.com/` → title `Example Domain`, one control.
|
|
86
|
-
2. `browser_view` → the same page, so the tab is the one this chat owns.
|
|
87
|
-
3. `browser_script` adding a button, then `browser_click` it → `Clicked #2 [button] clicked at 120,160`.
|
|
88
|
-
4. `browser_screenshot` → a path under `.dsh-inner-browser-use/`, or the sentence
|
|
89
|
-
naming the tab to bring forward.
|
|
90
|
-
5. Restart the app once if `browser_selection` answers `unknown tool`: the tool
|
|
91
|
-
list is read at start.
|
|
92
|
-
|
|
93
|
-
## A tab that is not the active one
|
|
94
|
-
|
|
95
|
-
The strip mounts only the tab it shows, and after a restart the restored tab is
|
|
96
|
-
not the active one. Nothing in the tab face switches it: `openTabIn` with
|
|
97
|
-
`activate`/`focus`, `focus(id)`, `focus(session, id)`, `active(id)`,
|
|
98
|
-
`tab.activate` and `tab.focus` were each tried and left the active tab
|
|
99
|
-
unchanged; the tab bar's controls are not inside `sidebarRight.host`, so there is
|
|
100
|
-
no element to click.
|
|
101
|
-
|
|
102
|
-
A call therefore never depends on that switch. On load, the chat on screen gets
|
|
103
|
-
its own tab back and the page it had; every other chat opens nothing, because a
|
|
104
|
-
tab lands in the column that is showing.
|
|
3
|
+
What this plugin assumes, and what it does when an assumption fails.
|
|
4
|
+
|
|
5
|
+
| | |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| Harness | 0.2.0 or newer, with the right column |
|
|
8
|
+
| Runtime | Node 20 or newer |
|
|
9
|
+
| Browser | Google Chrome, Chromium or Canary, 112 or newer |
|
|
10
|
+
| System | macOS 12 or newer; Linux x86_64 or arm64 |
|
|
11
|
+
| License | MIT |
|
|
12
|
+
|
|
13
|
+
## Where Chrome is looked for
|
|
14
|
+
|
|
15
|
+
The plugin starts a browser it finds at one of these paths, in this order:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
|
|
19
|
+
/Applications/Chromium.app/Contents/MacOS/Chromium
|
|
20
|
+
/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary
|
|
21
|
+
/usr/bin/google-chrome
|
|
22
|
+
/usr/bin/chromium
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
That is the whole list. A Chromium kept elsewhere (snap, flatpak, a home directory, a bundled
|
|
26
|
+
runtime) is not found, and there is no setting to point at one. Installing Chrome the ordinary
|
|
27
|
+
way, or placing the binary at `/usr/bin/chromium`, is the supported arrangement.
|
|
28
|
+
|
|
29
|
+
If nothing in the list exists, the first tool call returns `sidecar: no Chrome found on this
|
|
30
|
+
machine` and nothing is written to disk.
|
|
31
|
+
|
|
32
|
+
Chrome 112 is the floor: the mirror needs `--headless=new` and a screencast that survives an
|
|
33
|
+
idle page.
|
|
34
|
+
|
|
35
|
+
## macOS
|
|
36
|
+
|
|
37
|
+
The browser is launched with `--use-mock-keychain` and `--password-store=basic`, so no keychain
|
|
38
|
+
dialog appears on the person's screen and no password is read from the OS keyring. Chrome's own
|
|
39
|
+
password store inside the profile still works.
|
|
40
|
+
|
|
41
|
+
The profile directory is created under the home directory of whoever runs DSH, which is the
|
|
42
|
+
same user the browser runs as. Running that process as a different user leaves the profile
|
|
43
|
+
unwritable, and running it as root leaves Chrome unable to start its sandbox: run DSH as the
|
|
44
|
+
person using it.
|
|
45
|
+
|
|
46
|
+
## Linux
|
|
47
|
+
|
|
48
|
+
The two Linux entries above are the same lookup list; put Chrome or Chromium there. The browser
|
|
49
|
+
runs without a display, so no X or Wayland session is needed for the mirror itself.
|
|
50
|
+
|
|
51
|
+
Linux has not been part of the release test pass; macOS is where this plugin is developed and
|
|
52
|
+
checked.
|
|
53
|
+
|
|
54
|
+
## Windows
|
|
55
|
+
|
|
56
|
+
Not supported. There is no Windows path in the lookup list, and no installation of this plugin
|
|
57
|
+
on Windows has been checked.
|
|
58
|
+
|
|
59
|
+
## When an assumption fails
|
|
60
|
+
|
|
61
|
+
| Assumption | What happens |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| No Chrome at a listed path | First tool call returns the error above; no profile, no process. |
|
|
64
|
+
| Harness older than 0.2.0 | The plugin does not load. |
|
|
65
|
+
| A Harness build with no right column | The tools still drive the browser; there is nowhere to show the mirror. |
|
|
66
|
+
| A site that refuses headless | The user agent is replaced with an ordinary desktop Chrome string; a site that insists on a window can be opened with `headless: false`. |
|
|
67
|
+
| A page wider than 1440×900 | The viewport is fixed, so the page lays out for 1440 wide; nothing is scaled. |
|
|
68
|
+
| Two plugin instances, one profile | The second adopts the Chrome already running on that profile rather than starting another. |
|
|
69
|
+
| The debugging file left by a crashed Chrome | It is removed and the browser is started again. |
|
|
70
|
+
|
|
71
|
+
## Limits by design
|
|
72
|
+
|
|
73
|
+
One page per browser, fixed 1440×900 viewport, no mobile emulation, no downloads, no uploads, no
|
|
74
|
+
script evaluation. The eight tools in the README are the whole surface.
|
package/docs/ROADMAP.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<!-- ui-copy-ignore -->
|
|
2
|
+
# Roadmap: from a working mirror to the best computer-use plugin
|
|
3
|
+
|
|
4
|
+
The bar is not "another browser driver". The bar is: an agent can finish a real
|
|
5
|
+
task in this browser with fewer turns, fewer tokens, fewer surprises than with
|
|
6
|
+
Codex, Claude Code, browser-use, Stagehand, Playwright MCP or any screenshot-only
|
|
7
|
+
computer-use model — and the person can watch it happen in the sidebar of the
|
|
8
|
+
chat that asked, while every other chat stays untouched.
|
|
9
|
+
|
|
10
|
+
Written as phases with a number attached, because a phase without a number is a
|
|
11
|
+
wish. Baselines come from `node scripts/bench.mjs`; every phase must move one.
|
|
12
|
+
|
|
13
|
+
## Where the competition actually wins
|
|
14
|
+
|
|
15
|
+
| Project | What it does well | What it costs |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| Codex / Claude Code (computer + bash) | free-form shell, one action per turn, human can take over mid-run | no page structure, no refs, screenshots dominate context |
|
|
18
|
+
| browser-use | indexed DOM tree with stable element ids, action model, per-step memory | tree is big; a full read is thousands of tokens |
|
|
19
|
+
| Stagehand | `act` / `observe` / `extract` split, self-healing selectors, natural-language actions | server round trips; two model calls per step |
|
|
20
|
+
| Playwright MCP | accessibility tree with `ref` handles, deterministic waits | text-only; a page read is large; no live picture |
|
|
21
|
+
| Skyvern / CUA screenshot models | works on canvas apps and hostile DOM | ~1 image per step, slow and token-expensive |
|
|
22
|
+
|
|
23
|
+
Our position: **a real Chrome with a live, interactive mirror in the owning
|
|
24
|
+
chat, and a read model that is small by construction** — accessibility refs that
|
|
25
|
+
survive a read, viewport-only text, diffs instead of full re-reads, and one
|
|
26
|
+
batched tool for multi-step work. The mirror is not decoration: it is the human
|
|
27
|
+
takeover surface, and no other plugin can show it inside the asking chat without
|
|
28
|
+
stealing the column from other chats.
|
|
29
|
+
|
|
30
|
+
## Phase 0 — measurement (done when numbers exist)
|
|
31
|
+
|
|
32
|
+
- `scripts/bench.mjs`: launch→first frame, steady fps, frame KB, read ms /
|
|
33
|
+
chars / approx tokens for a dense page, a text page and a light page, click,
|
|
34
|
+
key, screenshot KB.
|
|
35
|
+
- Record every run in `docs/BENCH.md` with the commit; no phase is "done"
|
|
36
|
+
without a before/after row.
|
|
37
|
+
|
|
38
|
+
## Phase 1 — read model that costs less (target: dense page read ≤ 1.2k tokens)
|
|
39
|
+
|
|
40
|
+
- Accessibility-tree walk with `ref` handles that stay valid across reads of the
|
|
41
|
+
same page; only elements that exist in the tree get a number.
|
|
42
|
+
- Viewport-limited by default (`inView`), with `mode`: `text` (default),
|
|
43
|
+
`links`, `forms`, `full`; `max_chars` budget; text deduplicated and
|
|
44
|
+
truncation marked, never silent.
|
|
45
|
+
- `changed_only`: after an action, return only added / removed / changed refs —
|
|
46
|
+
the browser-use and Playwright MCP gap.
|
|
47
|
+
- Stable refs: a read re-numbers nothing that did not change, so the model can
|
|
48
|
+
act on numbers from an earlier read and gets a clear "ref 3 is gone, re-read"
|
|
49
|
+
instead of clicking the wrong thing.
|
|
50
|
+
|
|
51
|
+
## Phase 2 — one call, many steps (target: a login flow in 1 tool call)
|
|
52
|
+
|
|
53
|
+
- `sidecar_do`: ordered steps with per-step waits (`wait_text`, `wait_gone`,
|
|
54
|
+
`wait_idle`, `wait_url`), one result: what changed, the final URL, tokens spent
|
|
55
|
+
on one read instead of five.
|
|
56
|
+
- Auto-wait after every action: navigation start/finish, DOM quiet, and
|
|
57
|
+
`document.readyState`, so the next step never races the page.
|
|
58
|
+
- Ref errors are actionable: which ref, why it is gone, and one call that
|
|
59
|
+
re-reads and retries once.
|
|
60
|
+
|
|
61
|
+
## Phase 3 — any operation (target: no "can't do that" left)
|
|
62
|
+
|
|
63
|
+
- Hover, drag, double-click, right-click, wheel with modifiers.
|
|
64
|
+
- `select` option by label or value; checkboxes and radios by label.
|
|
65
|
+
- File upload (`DOM.setFileInputFiles`), download capture with a returned path,
|
|
66
|
+
print-to-PDF, full-page and element screenshots.
|
|
67
|
+
- Tabs: new / switch / close / list; iframes addressed by frame id; dialog
|
|
68
|
+
accept/dismiss; `sidecar_eval` for the last 1% of cases; cookies read/write for
|
|
69
|
+
debugging; console + failed requests surfaced in the state read.
|
|
70
|
+
- Keyboard: modifiers, shortcuts, clipboard paste, IME composition unchanged.
|
|
71
|
+
|
|
72
|
+
## Phase 4 — mirror latency and clarity (target: ≤120 ms input→painted, 60 fps idle)
|
|
73
|
+
|
|
74
|
+
- Adaptive JPEG quality and frame size: drop quality before dropping fps; send a
|
|
75
|
+
small first frame, refine when idle.
|
|
76
|
+
- `Page.startScreencast` tuning (maxWidth/quality/everyNthFrame), Chrome flags
|
|
77
|
+
that stop background throttling, `--disable-frame-rate-limit`.
|
|
78
|
+
- Client: decode off the main thread (`createImageBitmap`), draw only the newest
|
|
79
|
+
frame, no layout thrash, ResizeObserver-driven backing-store sizing for a crisp
|
|
80
|
+
picture at any pane width, DPR-aware.
|
|
81
|
+
- Pointer: keep the 1 ms path; add remote cursor shape to the pane cursor with a
|
|
82
|
+
proper fallback, and a visible "the agent is acting" pulse that never moves the
|
|
83
|
+
system cursor.
|
|
84
|
+
|
|
85
|
+
## Phase 5 — reliability and safety
|
|
86
|
+
|
|
87
|
+
- Human takeover: typing in the pane pauses the agent's next action and says so;
|
|
88
|
+
a resume action exists.
|
|
89
|
+
- Guarded actions (upload, download, close tab, buy-ish submits) can require a
|
|
90
|
+
confirm flag.
|
|
91
|
+
- Crash recovery: attach to a still-running Chrome, rebuild the page, keep the
|
|
92
|
+
profile; a killed host never leaves a zombie Chrome.
|
|
93
|
+
- Every failure names what happened, what state the page is in, and the next
|
|
94
|
+
call to make.
|
|
95
|
+
|
|
96
|
+
## Phase 6 — proof and packaging
|
|
97
|
+
|
|
98
|
+
- `docs/BENCH.md` with before/after per phase; a competitor comparison table with
|
|
99
|
+
measured numbers, not adjectives.
|
|
100
|
+
- `docs/VERIFY.md` walk-through that a stranger can run; `scripts/doctor.mjs`
|
|
101
|
+
green; 3 linters zero errors; tests covering every new tool.
|
|
102
|
+
- Packed tarball, CHANGELOG per release, `0.x` bumps that match behaviour.
|
|
103
|
+
|
|
104
|
+
## Order of work
|
|
105
|
+
|
|
106
|
+
1. Phase 0 baseline. 2. Phase 1 + 2 together (they share the read model).
|
|
107
|
+
3. Phase 3 breadth. 4. Phase 4 numbers. 5. Phase 5 hardening. 6. Phase 6 proof,
|
|
108
|
+
then repeat the loop with whatever the numbers say is worst.
|