@intentic/browser 1.310.0 → 1.311.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 +24 -81
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,88 +1,31 @@
|
|
|
1
|
-
#
|
|
1
|
+
# browser
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
type by element reference. No dependencies.
|
|
3
|
+
Drives a Chromium-family browser from Node over the DevTools protocol: opens pages, lists what can be clicked as numbered refs, and clicks and types by ref.
|
|
5
4
|
|
|
6
|
-
```
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
await web.fill("e0", "someone@example.com");
|
|
14
|
-
await web.fill("e1", "…", true); // true = submit
|
|
15
|
-
const after = await web.snapshot();
|
|
5
|
+
```mermaid
|
|
6
|
+
flowchart LR
|
|
7
|
+
tools["intentic-machine<br/>browser_* tools"] --> browser(["browser()"])
|
|
8
|
+
browser -->|"ensureBrowser"| binary["Brave, Chrome or Edge<br/>own profile, debugging port"]
|
|
9
|
+
browser -->|"CDP over WebSocket"| tab["The agent's tab"]
|
|
10
|
+
page["./page<br/>refs and rendering"] --> browser
|
|
11
|
+
page --> webext["webext<br/>same vocabulary"]
|
|
16
12
|
```
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
**Refs are deliberately short-lived.** They index an array parked on the page, and the next snapshot replaces it,
|
|
29
|
-
so a ref taken before a click that navigated cannot silently address whatever now occupies that slot. A stale ref
|
|
30
|
-
fails loudly, which is the behaviour worth having.
|
|
31
|
-
|
|
32
|
-
## Which browser it drives
|
|
33
|
-
|
|
34
|
-
**Their browser, not their profile.** A browser only speaks CDP if it was started with `--remote-debugging-port`,
|
|
35
|
-
and nobody's everyday browser was; restarting theirs to add the flag would close every tab they had open. So: if a
|
|
36
|
-
debugging endpoint is already there, it is used; otherwise a separate instance starts with its own profile
|
|
37
|
-
directory under `~/.intentic/browser`, one per browser: a user-data-dir records the build that wrote it, and
|
|
38
|
-
Chromium refuses a profile from a newer version than its own, so Brave must not be handed the directory Edge left.
|
|
39
|
-
|
|
40
|
-
That separate profile is a feature rather than a compromise. It is empty the first time, so the user signs into
|
|
41
|
-
whatever is needed once, in a window they can watch, and it persists afterwards. Their own session is never
|
|
42
|
-
automated and never at risk from a misfired click.
|
|
43
|
-
|
|
44
|
-
Which *binary* gets started is asked of the OS, not guessed: the browser registered for `https` (Windows'
|
|
45
|
-
`UserChoice` ProgId, `xdg-settings get default-web-browser` on Linux), used whenever it is Chromium-family. A
|
|
46
|
-
default that cannot speak CDP — Firefox, Safari — falls through to the guesses in `browserCandidates`, and those
|
|
47
|
-
are ordered so a browser installed on purpose outranks one the OS shipped: Brave, then Chrome, then Edge.
|
|
48
|
-
|
|
49
|
-
With one exception, which was reported as a bug and is one: **Edge registered as the default does not count as a
|
|
50
|
-
choice.** Windows ships Edge and hands it the `https` association, and setting a different default takes a
|
|
51
|
-
deliberate trip through Settings that a fresh install does not always win — so on a machine whose owner lives in
|
|
52
|
-
Brave, "the default browser" answers Edge, and an agent opening Edge in front of them is simply wrong. When the
|
|
53
|
-
OS's answer is the browser it shipped and something else is installed, the installed one wins (`pickBrowser`).
|
|
54
|
-
Nothing of the person's rides on either choice: the profile is this package's own, empty of their logins and
|
|
55
|
-
extensions whichever binary starts.
|
|
56
|
-
|
|
57
|
-
## Why hand-rolled CDP rather than Puppeteer or Playwright
|
|
58
|
-
|
|
59
|
-
**Not because Playwright is too heavy to ship.** It bundles into the `bun build --compile` binary this ends up
|
|
60
|
-
inside perfectly well: one `--external chromium-bidi`, for a require its own bundle makes and never resolves, and
|
|
61
|
-
about 6 MB on top of a binary that already weighs ~95 MB. Anyone who assumes packaging is the obstacle will try
|
|
62
|
-
it, watch it compile, and conclude this package exists for no reason.
|
|
63
|
-
|
|
64
|
-
**It is that Playwright cannot reach a browser from Bun.** `chromium.connectOverCDP()` fetches the debugger's
|
|
65
|
-
WebSocket URL over HTTP, then stalls on the upgrade and times out thirty seconds later. That happens compiled and
|
|
66
|
-
uncompiled alike, so it is the runtime rather than the bundling: and the same script against the same Chrome on
|
|
67
|
-
Node drives the page and returns an accessibility snapshot. Bun's own global `WebSocket`, which is what this
|
|
68
|
-
package is built on, connects from inside the compiled binary and gets a CDP reply back.
|
|
69
|
-
|
|
70
|
-
CDP needs no dependency either way. The protocol is JSON, `fetch` and `WebSocket` are globals, and the ~200 lines
|
|
71
|
-
here are the subset that driving a page actually uses.
|
|
72
|
-
|
|
73
|
-
**Worth re-testing rather than inheriting.** The above was measured against playwright-core 1.62.1 on Bun 1.4.1.
|
|
74
|
-
If a later pair connects, Playwright's accessibility snapshot is a better instrument than the DOM walk in
|
|
75
|
-
`snapshot.ts`, and this whole package is ~500 lines: the trade would be worth making, not merely tolerable.
|
|
76
|
-
|
|
77
|
-
## What is testable without a browser
|
|
78
|
-
|
|
79
|
-
`snapshot.ts`'s renderer and ref parsing, the per-platform candidate list, and the parsing of what the OS answers
|
|
80
|
-
about its default browser (a registry open command, a `.desktop` Exec line): all pure. Asking the OS shells out,
|
|
81
|
-
and the CDP calls end in a real browser painting a real page; those need a machine, not a test.
|
|
14
|
+
- Runs on the user's device inside [`intentic-machine`](../machine). It never touches the user's own profile:
|
|
15
|
+
`ensureBrowser` reuses whatever answers on `DEFAULT_PORT`, otherwise it starts the OS default Chromium-family
|
|
16
|
+
browser with `--remote-debugging-port` and a profile of its own under `~/.intentic/browser/<browser>`. Edge
|
|
17
|
+
ranks below any Chromium browser someone installed by choice (`pickBrowser`).
|
|
18
|
+
- A snapshot (`SNAPSHOT_SCRIPT`) lists visible interactive elements as refs `e0`, `e1`, … A ref lives until the next
|
|
19
|
+
snapshot, and a stale one fails with a message instead of clicking whatever sits there now.
|
|
20
|
+
- Clicks and fills run as DOM calls inside the page and fire `input` and `change`, so they survive scrolling and
|
|
21
|
+
reach a framework's state. Key presses go through `Input.dispatchKeyEvent`, since pages ignore synthetic keyboard events.
|
|
22
|
+
- The `./page` entry point has no DOM or Node imports, so the [browser extension](../webext) renders pages with
|
|
23
|
+
the same `renderPage`.
|
|
82
24
|
|
|
83
25
|
## Key files
|
|
84
26
|
|
|
85
|
-
- [src/index.ts](src/index.ts)
|
|
86
|
-
- [src/
|
|
87
|
-
- [src/snapshot.ts](src/snapshot.ts)
|
|
88
|
-
- [src/
|
|
27
|
+
- [src/index.ts](src/index.ts) — `browser()`: one CDP session per object, and every page action.
|
|
28
|
+
- [src/launch.ts](src/launch.ts) — which binary to start, its flags and its profile directory.
|
|
29
|
+
- [src/snapshot.ts](src/snapshot.ts) — the in-page script that numbers the elements.
|
|
30
|
+
- [src/page.ts](src/page.ts) — `PageState`, `renderPage` and ref parsing, shared with the extension.
|
|
31
|
+
- [src/cdp.ts](src/cdp.ts) — the DevTools protocol subset: find tabs, attach, send.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentic/browser",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.311.0",
|
|
4
4
|
"description": "Drive a Chromium browser from Node over CDP — open pages, read them as structured text, click and type by element reference. No dependencies.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@intentic/base": "1.
|
|
44
|
+
"@intentic/base": "1.311.0",
|
|
45
45
|
"tslib": "2.8.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|