@mercuryo-ai/agentbrowse 0.2.57 → 0.2.61
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 +76 -57
- package/dist/browser-session-state.d.ts +39 -0
- package/dist/browser-session-state.d.ts.map +1 -1
- package/dist/browser-session-state.js +63 -1
- package/dist/command-name.js +1 -1
- package/dist/commands/act.d.ts.map +1 -1
- package/dist/commands/act.js +540 -528
- package/dist/commands/action-executor-helpers.d.ts.map +1 -1
- package/dist/commands/action-executor-helpers.js +10 -8
- package/dist/commands/attach.d.ts.map +1 -1
- package/dist/commands/attach.js +5 -10
- package/dist/commands/browser-connection-failure.d.ts +9 -0
- package/dist/commands/browser-connection-failure.d.ts.map +1 -0
- package/dist/commands/browser-connection-failure.js +15 -0
- package/dist/commands/browser-status.d.ts.map +1 -1
- package/dist/commands/browser-status.js +26 -30
- package/dist/commands/click-activation-policy.d.ts.map +1 -1
- package/dist/commands/click-activation-policy.js +6 -2
- package/dist/commands/close.d.ts.map +1 -1
- package/dist/commands/close.js +5 -0
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +147 -144
- package/dist/commands/launch.d.ts +0 -1
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +13 -16
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +79 -73
- package/dist/commands/observe-inventory.d.ts +6 -1
- package/dist/commands/observe-inventory.d.ts.map +1 -1
- package/dist/commands/observe-inventory.js +331 -8
- package/dist/commands/observe-persistence.d.ts.map +1 -1
- package/dist/commands/observe-persistence.js +2 -0
- package/dist/commands/observe-projection.d.ts +3 -2
- package/dist/commands/observe-projection.d.ts.map +1 -1
- package/dist/commands/observe-projection.js +1 -0
- package/dist/commands/observe-protected.d.ts +3 -1
- package/dist/commands/observe-protected.d.ts.map +1 -1
- package/dist/commands/observe-protected.js +23 -1
- package/dist/commands/observe-semantics.d.ts.map +1 -1
- package/dist/commands/observe-semantics.js +70 -0
- package/dist/commands/observe.d.ts +1 -0
- package/dist/commands/observe.d.ts.map +1 -1
- package/dist/commands/observe.js +260 -270
- package/dist/commands/screenshot.d.ts.map +1 -1
- package/dist/commands/screenshot.js +50 -64
- package/dist/control-semantics.d.ts.map +1 -1
- package/dist/control-semantics.js +5 -0
- package/dist/date-value-normalization.d.ts +16 -0
- package/dist/date-value-normalization.d.ts.map +1 -0
- package/dist/date-value-normalization.js +117 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -24
- package/dist/library.d.ts +5 -1
- package/dist/library.d.ts.map +1 -1
- package/dist/library.js +4 -1
- package/dist/protected-fill.d.ts +3 -2
- package/dist/protected-fill.d.ts.map +1 -1
- package/dist/protected-fill.js +46 -7
- package/dist/runtime-protected-state.d.ts.map +1 -1
- package/dist/runtime-protected-state.js +8 -1
- package/dist/runtime-state.d.ts +11 -0
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/secrets/form-matcher.d.ts +1 -2
- package/dist/secrets/form-matcher.d.ts.map +1 -1
- package/dist/secrets/form-matcher.js +125 -119
- package/dist/secrets/matching-helpers.d.ts +13 -0
- package/dist/secrets/matching-helpers.d.ts.map +1 -0
- package/dist/secrets/matching-helpers.js +147 -0
- package/dist/secrets/observed-field-resolution.d.ts +43 -0
- package/dist/secrets/observed-field-resolution.d.ts.map +1 -0
- package/dist/secrets/observed-field-resolution.js +223 -0
- package/dist/secrets/protected-field-semantics.d.ts.map +1 -1
- package/dist/secrets/protected-field-semantics.js +3 -2
- package/dist/secrets/protected-fill.d.ts +3 -1
- package/dist/secrets/protected-fill.d.ts.map +1 -1
- package/dist/secrets/protected-fill.js +31 -0
- package/dist/secrets/protected-value-adapters.d.ts.map +1 -1
- package/dist/secrets/protected-value-adapters.js +14 -22
- package/dist/secrets/types.d.ts +3 -0
- package/dist/secrets/types.d.ts.map +1 -1
- package/dist/sticky-owner-host-entry.d.ts +2 -0
- package/dist/sticky-owner-host-entry.d.ts.map +1 -0
- package/dist/sticky-owner-host-entry.js +97 -0
- package/dist/sticky-owner.d.ts +15 -0
- package/dist/sticky-owner.d.ts.map +1 -0
- package/dist/sticky-owner.js +431 -0
- package/docs/README.md +15 -2
- package/docs/api-reference.md +13 -3
- package/docs/assistive-runtime.md +63 -7
- package/docs/configuration.md +48 -8
- package/docs/getting-started.md +42 -9
- package/docs/integration-checklist.md +8 -7
- package/docs/protected-fill.md +40 -7
- package/docs/testing.md +4 -3
- package/docs/troubleshooting.md +126 -36
- package/examples/README.md +9 -2
- package/package.json +8 -3
- package/dist/protected-fill-browser.d.ts +0 -22
- package/dist/protected-fill-browser.d.ts.map +0 -1
- package/dist/protected-fill-browser.js +0 -52
package/docs/getting-started.md
CHANGED
|
@@ -19,7 +19,28 @@ The normal flow is:
|
|
|
19
19
|
5. `close(session)` ends the browser session
|
|
20
20
|
|
|
21
21
|
The `session` is the key object in the whole API. It is the handle that keeps
|
|
22
|
-
the browser connection
|
|
22
|
+
the browser connection, runtime state, and sticky-owner metadata together
|
|
23
|
+
between calls. Healthy commands reuse that sticky owner instead of issuing a
|
|
24
|
+
fresh root attach on every call. If you persist the session and restart your
|
|
25
|
+
process, the next command may repair the owner while the underlying browser is
|
|
26
|
+
still alive; otherwise the session fails closed and you start fresh. Detached
|
|
27
|
+
sticky owners also have a bounded lifetime, so an idle or expired owner may be
|
|
28
|
+
recreated on the next browser command while the underlying browser session is
|
|
29
|
+
still live.
|
|
30
|
+
|
|
31
|
+
The sticky owner may live in-process or in an internal detached host. That is
|
|
32
|
+
an implementation detail of AgentBrowse, not a daemon you manage separately.
|
|
33
|
+
Detached hosts default to a 30 minute TTL.
|
|
34
|
+
|
|
35
|
+
Refs returned by `observe(...)` (target refs, scope refs, fill refs) are
|
|
36
|
+
valid for the page state that produced them, not forever. Any of these
|
|
37
|
+
invalidates them:
|
|
38
|
+
|
|
39
|
+
- navigation to a different page;
|
|
40
|
+
- major DOM re-render (route change, modal open/close);
|
|
41
|
+
- an element removed by script.
|
|
42
|
+
|
|
43
|
+
After any of the above, call `observe(...)` again and use the new refs.
|
|
23
44
|
|
|
24
45
|
At a high level, AgentBrowse has three kinds of behavior:
|
|
25
46
|
|
|
@@ -35,13 +56,10 @@ approval, secret, or payment logic.
|
|
|
35
56
|
|
|
36
57
|
## Managed Launch Note
|
|
37
58
|
|
|
38
|
-
`launch(...)`
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
browser startup on sensitive sites.
|
|
43
|
-
|
|
44
|
-
After launch, the normal page interaction flow still runs over Playwright CDP.
|
|
59
|
+
`launch(...)` starts a managed browser session. For that path, AgentBrowse
|
|
60
|
+
uses `puppeteer` with stealth evasions to reduce unnecessary captcha or
|
|
61
|
+
anti-bot challenge pages on sensitive sites. Page interaction then runs
|
|
62
|
+
through Playwright over CDP, which is what the rest of the API targets.
|
|
45
63
|
|
|
46
64
|
## Basic Example
|
|
47
65
|
|
|
@@ -107,6 +125,11 @@ Success result includes:
|
|
|
107
125
|
- current `url`
|
|
108
126
|
- current `title`
|
|
109
127
|
|
|
128
|
+
`attach(...)` bootstraps the same sticky-owner lifecycle as `launch(...)`.
|
|
129
|
+
After attach succeeds, later browser commands use that owner. A new provider-
|
|
130
|
+
level root attach is only attempted again as an explicit repair path after
|
|
131
|
+
owner loss.
|
|
132
|
+
|
|
110
133
|
### `observe(session, goal?)`
|
|
111
134
|
|
|
112
135
|
Reads the current page and returns what AgentBrowse found.
|
|
@@ -163,12 +186,17 @@ before calling it.
|
|
|
163
186
|
Returns local browser/runtime diagnostics for an existing session.
|
|
164
187
|
|
|
165
188
|
Use it when you want to know whether the browser is still reachable and what
|
|
166
|
-
page AgentBrowse believes it is on.
|
|
189
|
+
page AgentBrowse believes it is on. After restoring a persisted session,
|
|
190
|
+
`status(session)` is the cheapest explicit health check before more expensive
|
|
191
|
+
workflows.
|
|
167
192
|
|
|
168
193
|
### `close(session)`
|
|
169
194
|
|
|
170
195
|
Closes the browser session.
|
|
171
196
|
|
|
197
|
+
This also terminates the internal sticky owner. Repeated closes and already-
|
|
198
|
+
dead owner hosts are treated as idempotent.
|
|
199
|
+
|
|
172
200
|
## How To Handle Results
|
|
173
201
|
|
|
174
202
|
All main commands use the same broad pattern:
|
|
@@ -224,6 +252,11 @@ If you want to restore a browser session between process runs, use:
|
|
|
224
252
|
- `loadBrowserSession()`
|
|
225
253
|
- `createBrowserSessionStore({ rootDir })`
|
|
226
254
|
|
|
255
|
+
Persisted session records now require restorable sticky-owner metadata.
|
|
256
|
+
Incompatible reconnect-era records are rejected at load time instead of being
|
|
257
|
+
auto-migrated. Treat `loadBrowserSession() === null` as "no usable session",
|
|
258
|
+
not as a recoverable partial state.
|
|
259
|
+
|
|
227
260
|
See:
|
|
228
261
|
|
|
229
262
|
- [Configuration Guide](./configuration.md)
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
# AgentBrowse Integration Checklist
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Checklist for engineers integrating `@mercuryo-ai/agentbrowse` into another
|
|
4
|
+
package or service. Use it as a final read-through before shipping an
|
|
5
|
+
integration.
|
|
6
|
+
|
|
7
|
+
> AgentBrowse is pre-1.0. Treat minor-version updates as potential
|
|
8
|
+
> behavior changes and re-run this checklist whenever you move to a newer
|
|
9
|
+
> release.
|
|
5
10
|
|
|
6
11
|
## Core Assumptions
|
|
7
12
|
|
|
@@ -28,9 +33,5 @@ contract into another package or service.
|
|
|
28
33
|
|
|
29
34
|
- the root library entrypoint does not load `.env`
|
|
30
35
|
- the CLI entrypoint is the only place that loads dotenv support
|
|
31
|
-
- published examples and docs are part of
|
|
32
|
-
|
|
33
|
-
## Versioning Expectation
|
|
36
|
+
- published examples and docs are part of what consumers rely on
|
|
34
37
|
|
|
35
|
-
AgentBrowse is still pre-1.0. Treat minor updates as contract-bearing changes
|
|
36
|
-
and verify this checklist whenever you move to a newer release.
|
package/docs/protected-fill.md
CHANGED
|
@@ -34,13 +34,19 @@ Use ordinary `act(..., 'fill', value)` when:
|
|
|
34
34
|
|
|
35
35
|
Compared with a normal fill action, protected fill works with:
|
|
36
36
|
|
|
37
|
-
- a
|
|
38
|
-
- structured `protectedValues` keyed by field meaning
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
- a `fillableForm` returned by a previous `observe(...)` call;
|
|
38
|
+
- structured `protectedValues` keyed by field meaning (e.g. `card_number`,
|
|
39
|
+
`password`), not by raw DOM selector;
|
|
40
|
+
- optional `fieldPolicies` that pin per-field behavior such as
|
|
41
|
+
`strict: true` (abort if the expected target is missing) or
|
|
42
|
+
`allowPartial: true` (apply what you can, skip the rest);
|
|
43
|
+
- typed execution outcomes so your code can distinguish success from
|
|
44
|
+
stale bindings, validation failure, and generic execution errors.
|
|
45
|
+
|
|
46
|
+
It also validates that the form bindings returned by `observe(...)` still
|
|
47
|
+
apply to the current DOM. If the page changed between observation and
|
|
48
|
+
fill, protected fill fails with a stale-binding result instead of trying
|
|
49
|
+
to fill a moved or removed target.
|
|
44
50
|
|
|
45
51
|
## Import
|
|
46
52
|
|
|
@@ -80,6 +86,33 @@ if (!result.success) {
|
|
|
80
86
|
}
|
|
81
87
|
```
|
|
82
88
|
|
|
89
|
+
### Form purpose values
|
|
90
|
+
|
|
91
|
+
`fillableForm.purpose` identifies which kind of form AgentBrowse detected.
|
|
92
|
+
The currently surfaced purposes are:
|
|
93
|
+
|
|
94
|
+
- `login` — username/password or email/password form.
|
|
95
|
+
- `identity` — identity-verification fields (name, address, document
|
|
96
|
+
details).
|
|
97
|
+
- `payment_card` — credit/debit card entry.
|
|
98
|
+
- `wallet` — crypto wallet address/chain fields.
|
|
99
|
+
|
|
100
|
+
### Protected value keys
|
|
101
|
+
|
|
102
|
+
The keys in `protectedValues` are the standard field names chosen by the
|
|
103
|
+
form detector, not raw DOM attributes. Typical keys per purpose:
|
|
104
|
+
|
|
105
|
+
- `login`: `username`, `password` (or `email`, `password`).
|
|
106
|
+
- `identity`: `given_name`, `family_name`, `date_of_birth`, `country`,
|
|
107
|
+
`document_number`, etc.
|
|
108
|
+
- `payment_card`: `card_number`, `cardholder_name`, `exp_month`,
|
|
109
|
+
`exp_year`, `cvv`.
|
|
110
|
+
- `wallet`: `address`, `chain`.
|
|
111
|
+
|
|
112
|
+
The exact set of keys expected for a given `fillableForm` is listed in
|
|
113
|
+
`fillableForm.fields`. Always build `protectedValues` from that list rather
|
|
114
|
+
than assuming defaults.
|
|
115
|
+
|
|
83
116
|
## Where It Fits
|
|
84
117
|
|
|
85
118
|
Protected fill handles the browser execution step.
|
package/docs/testing.md
CHANGED
|
@@ -21,7 +21,8 @@ Use it when:
|
|
|
21
21
|
|
|
22
22
|
- your tests wrap `extract(...)`
|
|
23
23
|
- your tests cover goal-based `observe(session, goal)`
|
|
24
|
-
- your package wants to exercise the current public assistive runtime
|
|
24
|
+
- your package wants to exercise the current public assistive runtime
|
|
25
|
+
shape
|
|
25
26
|
|
|
26
27
|
## Example
|
|
27
28
|
|
|
@@ -46,5 +47,5 @@ afterEach(() => {
|
|
|
46
47
|
|
|
47
48
|
## Scope
|
|
48
49
|
|
|
49
|
-
This helper
|
|
50
|
-
sessions, pages, or observed
|
|
50
|
+
This helper targets the assistive runtime only. It does not mock browser
|
|
51
|
+
sessions, pages, or observed targets.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -1,71 +1,161 @@
|
|
|
1
1
|
# AgentBrowse Troubleshooting
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
Common failures and what to do about each.
|
|
4
|
+
|
|
5
|
+
## `launch(...)` Fails
|
|
6
|
+
|
|
7
|
+
Most `launch(...)` failures come from the environment, not from AgentBrowse
|
|
8
|
+
itself:
|
|
9
|
+
|
|
10
|
+
- **Missing or unreachable browser binary.** Confirm that Chrome or Chromium
|
|
11
|
+
starts outside AgentBrowse first.
|
|
12
|
+
- **No display server.** If you expect a visible window, verify the host
|
|
13
|
+
actually has one. To isolate launch-vs-page problems, retry with
|
|
14
|
+
`headless: true`.
|
|
15
|
+
- **Conflicting debug port.** If another Chrome instance is already
|
|
16
|
+
listening on the CDP port you need, the launch cannot bind.
|
|
17
|
+
|
|
18
|
+
Inspect the `error` and `reason` fields on the `launch(...)` failure result
|
|
19
|
+
(typed by `LAUNCH_ERROR_CODES`) before deciding whether to retry.
|
|
20
|
+
|
|
21
|
+
## `attach(...)` Fails
|
|
22
|
+
|
|
23
|
+
- **Unreachable CDP WebSocket URL.** Verify the URL with a simple
|
|
24
|
+
WebSocket client or `curl`.
|
|
25
|
+
- **Session already owned.** Some providers reject a second CDP attach for
|
|
26
|
+
the same session. In the sticky-owner architecture this should only happen
|
|
27
|
+
during the initial `attach(...)` or an explicit repair attempt after the
|
|
28
|
+
original owner was lost, not during every healthy command.
|
|
29
|
+
- **Version mismatch.** Very old or very new Chrome versions may not match
|
|
30
|
+
Playwright's expected CDP shape; `status(session)` after attach returns
|
|
31
|
+
details in that case.
|
|
32
|
+
|
|
33
|
+
## Browser Session Becomes Invalid
|
|
34
|
+
|
|
35
|
+
A `session` handle is valid only while the underlying browser connection
|
|
36
|
+
is live.
|
|
37
|
+
|
|
38
|
+
- If the detached sticky owner died but the browser is still alive,
|
|
39
|
+
AgentBrowse may repair ownership on the next command or explicit restore
|
|
40
|
+
path.
|
|
41
|
+
- If the detached sticky owner hit its TTL, the next browser command may
|
|
42
|
+
recycle the owner and continue as long as the browser session is still live.
|
|
43
|
+
- If the browser process or remote CDP session died, the next
|
|
44
|
+
`act(...)` / `observe(...)` call fails closed. Use `status(session)` to
|
|
45
|
+
confirm, then call `launch(...)` or `attach(...)` again.
|
|
46
|
+
- If you restored a session from `loadBrowserSession()` or a custom store,
|
|
47
|
+
call `status(session)` right after loading. If it reports the session is
|
|
48
|
+
no longer reachable, or a later command fails with
|
|
49
|
+
`sticky_owner_unrecoverable`, discard it and start fresh.
|
|
50
|
+
- `close(session)` called twice is safe — the second call is a no-op, and an
|
|
51
|
+
already-dead owner host is treated as already closed.
|
|
52
|
+
|
|
53
|
+
## Restored Session Loads As `null`
|
|
54
|
+
|
|
55
|
+
`loadBrowserSession()` and custom stores intentionally reject incompatible
|
|
56
|
+
older session records that do not contain persistable sticky-owner metadata.
|
|
57
|
+
|
|
58
|
+
If a session that used to restore now loads as `null`:
|
|
59
|
+
|
|
60
|
+
- treat it as a stale local record, not as a partial session you should patch
|
|
61
|
+
by hand;
|
|
62
|
+
- delete the old session file if it is still on disk;
|
|
63
|
+
- run `launch(...)` or `attach(...)` again to create a new session record.
|
|
64
|
+
|
|
65
|
+
AgentBrowse does not auto-migrate reconnect-era session files.
|
|
66
|
+
|
|
67
|
+
## `close(session)` Seems Stuck Or The Owner Host Already Died
|
|
68
|
+
|
|
69
|
+
`close(session)` first terminates the sticky owner and then closes the managed
|
|
70
|
+
browser when the session owns it.
|
|
71
|
+
|
|
72
|
+
- If the owner host is already gone, close remains idempotent.
|
|
73
|
+
- For detached owner hosts, AgentBrowse escalates from graceful termination to
|
|
74
|
+
a forced kill internally; there is no separate daemon command to run.
|
|
75
|
+
- In CLI wrappers, a successful close also clears the locally persisted browser
|
|
76
|
+
session and workflow bindings.
|
|
77
|
+
- If closing the managed browser itself fails, AgentBrowse reports that failure
|
|
78
|
+
and keeps the session record so you can inspect or retry.
|
|
10
79
|
|
|
11
80
|
## Why The Package Uses Both Puppeteer And Playwright
|
|
12
81
|
|
|
13
|
-
`launch(...)` uses Puppeteer
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
82
|
+
`launch(...)` uses Puppeteer with stealth evasions to connect to the
|
|
83
|
+
managed browser — this reduces unnecessary anti-bot friction on sensitive
|
|
84
|
+
sites. Live page interaction runs through Playwright over CDP, which is
|
|
85
|
+
what the rest of the API targets.
|
|
17
86
|
|
|
18
|
-
|
|
19
|
-
|
|
87
|
+
You do not need to know the split to use the library; it only matters when
|
|
88
|
+
a stack trace points at one runtime or the other.
|
|
20
89
|
|
|
21
90
|
## `observe(...)` Returned Zero Targets
|
|
22
91
|
|
|
23
92
|
This usually means one of three things:
|
|
24
93
|
|
|
25
|
-
- the page has not reached the state you expect yet
|
|
26
|
-
- the goal was too narrow for the current page state
|
|
27
|
-
- the page is mostly blocked by a gate, overlay, or challenge
|
|
94
|
+
- the page has not reached the state you expect yet;
|
|
95
|
+
- the goal was too narrow for the current page state;
|
|
96
|
+
- the page is mostly blocked by a gate, overlay, or challenge.
|
|
28
97
|
|
|
29
98
|
What to do:
|
|
30
99
|
|
|
31
|
-
- run `observe(session)` without a goal first
|
|
32
|
-
- inspect `signals`
|
|
33
|
-
- inspect `fillableForms`
|
|
34
|
-
|
|
100
|
+
- run `observe(session)` without a goal first;
|
|
101
|
+
- inspect `signals` for notices, errors, or challenge messages;
|
|
102
|
+
- inspect `fillableForms` — there may be a form target without a clear goal
|
|
103
|
+
match;
|
|
104
|
+
- check `status(session)` and the current `url`.
|
|
35
105
|
|
|
36
106
|
## `act(...)` Fails With A Stale Or Missing Target
|
|
37
107
|
|
|
38
|
-
|
|
108
|
+
A `ref` returned by `observe(...)` is valid for the page state that
|
|
109
|
+
produced it, not forever. Any of these invalidates it:
|
|
39
110
|
|
|
40
|
-
|
|
41
|
-
|
|
111
|
+
- navigation to a different page;
|
|
112
|
+
- major DOM re-render (route change, modal open/close, framework patch);
|
|
113
|
+
- element removed by script.
|
|
114
|
+
|
|
115
|
+
After any of the above, call `observe(...)` again and use the new `ref`
|
|
116
|
+
values. `act(...)` failures from a stale ref surface as an error code in
|
|
117
|
+
`ACT_ERROR_CODES`; check the error field before retrying the same ref.
|
|
42
118
|
|
|
43
119
|
## Scoped `extract(...)` Fails With A Stale Scope
|
|
44
120
|
|
|
45
|
-
`scopeRef` is tied to the observed scope
|
|
121
|
+
`scopeRef` is tied to the observed scope that produced it. If the page
|
|
122
|
+
changed enough that the scope no longer maps cleanly, `extract(...)`
|
|
123
|
+
surfaces a stale-scope error.
|
|
46
124
|
|
|
47
|
-
|
|
48
|
-
`observe(...)` again and use the current `scopeRef`.
|
|
125
|
+
Run `observe(...)` again and use the fresh `scopeRef`.
|
|
49
126
|
|
|
50
127
|
## `extract(...)` Fails Immediately
|
|
51
128
|
|
|
52
129
|
Two common causes:
|
|
53
130
|
|
|
54
|
-
-
|
|
55
|
-
|
|
131
|
+
- **No assistive runtime configured.** `extract(...)` calls an LLM through
|
|
132
|
+
the assistive runtime. Without one, the call fails with
|
|
133
|
+
`AgentbrowseAssistiveRuntimeMissingError`. See the
|
|
134
|
+
[Assistive Runtime Guide](./assistive-runtime.md).
|
|
135
|
+
- **Invalid schema input.** Valid inputs are a plain schema object
|
|
136
|
+
(`{ field: 'string' }`) or a Zod schema. Other shapes are rejected.
|
|
137
|
+
|
|
138
|
+
If the LLM returns a structured output that was cut off mid-response,
|
|
139
|
+
AgentBrowse throws `AssistiveStructuredOutputTruncatedError` — usually a
|
|
140
|
+
signal to increase the assistive-runtime token budget.
|
|
56
141
|
|
|
57
|
-
|
|
142
|
+
## Protected Fill Reports Stale Bindings
|
|
58
143
|
|
|
59
|
-
|
|
60
|
-
|
|
144
|
+
`fillProtectedForm(...)` validates that the previously observed form
|
|
145
|
+
bindings still make sense. If the page changed between `observe(...)` and
|
|
146
|
+
`fillProtectedForm(...)`, the call returns a stale-binding failure. Re-run
|
|
147
|
+
`observe(...)`, find the updated `fillableForm`, and call
|
|
148
|
+
`fillProtectedForm(...)` again with the new reference.
|
|
61
149
|
|
|
62
150
|
## You Keep Hitting Captcha Or Anti-Bot Pages
|
|
63
151
|
|
|
64
|
-
Managed `launch(...)` enables a stealth-oriented Puppeteer connection
|
|
65
|
-
that only reduces unnecessary friction. It does not guarantee
|
|
152
|
+
Managed `launch(...)` enables a stealth-oriented Puppeteer connection
|
|
153
|
+
layer, but that only reduces unnecessary friction. It does not guarantee
|
|
154
|
+
bypass.
|
|
66
155
|
|
|
67
156
|
If a site still gates the session:
|
|
68
157
|
|
|
69
|
-
- retry with a normal local browser profile if your flow permits it
|
|
70
|
-
- confirm that the site is reachable outside automation
|
|
71
|
-
- treat the page as a site policy or anti-abuse boundary until proven
|
|
158
|
+
- retry with a normal local browser profile if your flow permits it;
|
|
159
|
+
- confirm that the site is reachable outside automation;
|
|
160
|
+
- treat the page as a site policy or anti-abuse boundary until proven
|
|
161
|
+
otherwise.
|
package/examples/README.md
CHANGED
|
@@ -20,8 +20,15 @@ npx tsx examples/extract.ts
|
|
|
20
20
|
Examples:
|
|
21
21
|
|
|
22
22
|
- `basic.ts`
|
|
23
|
-
Launches a managed browser, observes the page, and prints a small target
|
|
23
|
+
Launches a managed browser, observes the page, and prints a small target
|
|
24
|
+
summary.
|
|
24
25
|
- `attach.ts`
|
|
25
26
|
Attaches to an existing CDP browser session.
|
|
26
27
|
- `extract.ts`
|
|
27
|
-
Runs structured extraction with an assistive runtime and a plain schema
|
|
28
|
+
Runs structured extraction with an assistive runtime and a plain schema
|
|
29
|
+
object.
|
|
30
|
+
|
|
31
|
+
For protected-fill usage (paying with a card, filling login credentials
|
|
32
|
+
from a user's vault), see [../docs/protected-fill.md](../docs/protected-fill.md).
|
|
33
|
+
The example in that guide is self-contained and uses the same `observe(...)` →
|
|
34
|
+
`fillProtectedForm(...)` pattern.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mercuryo-ai/agentbrowse",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.61",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Browser automation primitives library for AI agents",
|
|
6
6
|
"license": "MIT",
|
|
@@ -70,11 +70,16 @@
|
|
|
70
70
|
"vitest": "^4.0.18"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
|
-
"build": "node -e \"require('node:fs').rmSync('dist',{ recursive: true, force: true })\" && tsc -p tsconfig.build.json",
|
|
73
|
+
"build": "node -e \"require('node:fs').rmSync('dist',{ recursive: true, force: true, maxRetries: 10, retryDelay: 50 })\" && tsc -p tsconfig.build.json",
|
|
74
74
|
"agentbrowse": "tsx src/index.ts",
|
|
75
|
-
"test": "npm run test:
|
|
75
|
+
"test": "npm run test:full",
|
|
76
|
+
"test:full": "npm run test:unit && npm run test:e2e",
|
|
76
77
|
"test:unit": "vitest run --exclude \"src/__tests__/*.e2e.test.ts\"",
|
|
77
78
|
"test:e2e": "vitest run --no-file-parallelism --maxWorkers=1 src/__tests__/observe-stagehand.e2e.test.ts src/__tests__/extract.e2e.test.ts src/__tests__/runtime.e2e.test.ts",
|
|
79
|
+
"test:autonomous:scenarios": "npm run test:autonomous:scenarios:bare",
|
|
80
|
+
"test:autonomous:scenarios:bare": "vitest run --no-file-parallelism --maxWorkers=1 src/__tests__/runtime.e2e.test.ts src/commands/act-locator-resolution.test.ts src/secrets/form-matcher.contract.test.ts src/secrets/form-matcher.test.ts -t \"\\\\[S\"",
|
|
81
|
+
"test:e2e:autonomous": "npm run test:autonomous:scenarios",
|
|
82
|
+
"test:e2e:autonomous:bare": "npm run test:autonomous:scenarios:bare",
|
|
78
83
|
"check-types": "tsc --noEmit",
|
|
79
84
|
"lint": "biome check src docs README.md",
|
|
80
85
|
"pack:verify": "node scripts/verify-pack-artifact.mjs",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { BrowserSessionState } from './browser-session-state.js';
|
|
2
|
-
import { type ProtectedFillExecutionResult } from './secrets/protected-fill.js';
|
|
3
|
-
import type { PersistedFillableForm, StoredSecretFieldPolicies, StoredSecretFieldKey } from './secrets/types.js';
|
|
4
|
-
export type FillProtectedFormBrowserResult = {
|
|
5
|
-
success: true;
|
|
6
|
-
pageRef: string;
|
|
7
|
-
url: string;
|
|
8
|
-
title: string;
|
|
9
|
-
execution: ProtectedFillExecutionResult;
|
|
10
|
-
} | {
|
|
11
|
-
success: false;
|
|
12
|
-
error: 'browser_connection_failed' | 'page_resolution_failed';
|
|
13
|
-
message: string;
|
|
14
|
-
reason: string;
|
|
15
|
-
};
|
|
16
|
-
export declare function fillProtectedFormBrowser(params: {
|
|
17
|
-
session: BrowserSessionState;
|
|
18
|
-
fillableForm: PersistedFillableForm;
|
|
19
|
-
protectedValues: Partial<Record<StoredSecretFieldKey, string>>;
|
|
20
|
-
fieldPolicies?: StoredSecretFieldPolicies;
|
|
21
|
-
}): Promise<FillProtectedFormBrowserResult>;
|
|
22
|
-
//# sourceMappingURL=protected-fill-browser.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protected-fill-browser.d.ts","sourceRoot":"","sources":["../src/protected-fill-browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAOtE,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACV,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,8BAA8B,GACtC;IACE,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,4BAA4B,CAAC;CACzC,GACD;IACE,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,2BAA2B,GAAG,wBAAwB,CAAC;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEN,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,OAAO,EAAE,mBAAmB,CAAC;IAC7B,YAAY,EAAE,qBAAqB,CAAC;IACpC,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/D,aAAa,CAAC,EAAE,yBAAyB,CAAC;CAC3C,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAqD1C"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { connectPlaywright, disconnectPlaywright, resolvePageByRef, syncSessionPage, } from './playwright-runtime.js';
|
|
2
|
-
import { executeProtectedFill, } from './secrets/protected-fill.js';
|
|
3
|
-
export async function fillProtectedFormBrowser(params) {
|
|
4
|
-
let browser = null;
|
|
5
|
-
try {
|
|
6
|
-
browser = await connectPlaywright(params.session.cdpUrl);
|
|
7
|
-
}
|
|
8
|
-
catch (error) {
|
|
9
|
-
return {
|
|
10
|
-
success: false,
|
|
11
|
-
error: 'browser_connection_failed',
|
|
12
|
-
message: 'Protected fill could not connect to the browser.',
|
|
13
|
-
reason: error instanceof Error ? error.message : String(error),
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
try {
|
|
17
|
-
const page = await resolvePageByRef(browser, params.session, params.fillableForm.pageRef).catch((error) => {
|
|
18
|
-
throw new Error(error instanceof Error ? error.message : String(error));
|
|
19
|
-
});
|
|
20
|
-
const { url, title } = await syncSessionPage(params.session, params.fillableForm.pageRef, page);
|
|
21
|
-
const execution = await executeProtectedFill({
|
|
22
|
-
session: params.session,
|
|
23
|
-
page,
|
|
24
|
-
fillableForm: params.fillableForm,
|
|
25
|
-
protectedValues: Object.fromEntries(Object.entries(params.protectedValues).filter((entry) => {
|
|
26
|
-
const value = entry[1];
|
|
27
|
-
return typeof value === 'string' && value.length > 0;
|
|
28
|
-
})),
|
|
29
|
-
fieldPolicies: params.fieldPolicies,
|
|
30
|
-
});
|
|
31
|
-
return {
|
|
32
|
-
success: true,
|
|
33
|
-
pageRef: params.fillableForm.pageRef,
|
|
34
|
-
url,
|
|
35
|
-
title,
|
|
36
|
-
execution,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
return {
|
|
41
|
-
success: false,
|
|
42
|
-
error: 'page_resolution_failed',
|
|
43
|
-
message: 'Protected fill could not resolve the target page in the browser.',
|
|
44
|
-
reason: error instanceof Error ? error.message : String(error),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
finally {
|
|
48
|
-
if (browser) {
|
|
49
|
-
await disconnectPlaywright(browser);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|