cdp-skill 1.0.8 → 1.0.15
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 +80 -35
- package/SKILL.md +157 -241
- package/install.js +1 -0
- package/package.json +1 -1
- package/src/aria/index.js +8 -0
- package/src/aria/output-processor.js +173 -0
- package/src/aria/role-query.js +1229 -0
- package/src/aria/snapshot.js +459 -0
- package/src/aria.js +251 -50
- package/src/cdp/browser.js +22 -4
- package/src/cdp-skill.js +246 -69
- package/src/dom/LazyResolver.js +634 -0
- package/src/dom/click-executor.js +366 -94
- package/src/dom/element-locator.js +34 -25
- package/src/dom/fill-executor.js +83 -50
- package/src/dom/index.js +3 -0
- package/src/page/dialog-handler.js +119 -0
- package/src/page/page-controller.js +236 -3
- package/src/runner/context-helpers.js +33 -55
- package/src/runner/execute-dynamic.js +8 -7
- package/src/runner/execute-form.js +11 -11
- package/src/runner/execute-input.js +2 -2
- package/src/runner/execute-interaction.js +105 -126
- package/src/runner/execute-navigation.js +14 -29
- package/src/runner/execute-query.js +17 -11
- package/src/runner/step-executors.js +225 -84
- package/src/runner/step-registry.js +1064 -0
- package/src/runner/step-validator.js +16 -754
- package/src/tests/Aria.test.js +1025 -0
- package/src/tests/ClickExecutor.test.js +170 -50
- package/src/tests/ContextHelpers.test.js +41 -30
- package/src/tests/ExecuteBrowser.test.js +572 -0
- package/src/tests/ExecuteDynamic.test.js +2 -457
- package/src/tests/ExecuteForm.test.js +700 -0
- package/src/tests/ExecuteInput.test.js +540 -0
- package/src/tests/ExecuteInteraction.test.js +319 -0
- package/src/tests/ExecuteQuery.test.js +820 -0
- package/src/tests/FillExecutor.test.js +89 -37
- package/src/tests/LazyResolver.test.js +383 -0
- package/src/tests/StepValidator.test.js +224 -78
- package/src/tests/TestRunner.test.js +38 -27
- package/src/tests/integration.test.js +2 -1
- package/src/types.js +9 -9
- package/src/utils/backoff.js +118 -0
- package/src/utils/cdp-helpers.js +130 -0
- package/src/utils/devices.js +140 -0
- package/src/utils/errors.js +242 -0
- package/src/utils/index.js +65 -0
- package/src/utils/temp.js +75 -0
- package/src/utils/validators.js +433 -0
- package/src/utils.js +14 -1142
package/SKILL.md
CHANGED
|
@@ -19,7 +19,7 @@ Site profiles are per-domain cheatsheets stored at `~/.cdp-skill/sites/{domain}.
|
|
|
19
19
|
|
|
20
20
|
### How navigation uses profiles
|
|
21
21
|
|
|
22
|
-
Every `goto
|
|
22
|
+
Every `goto`, `newTab` (with URL), and `switchTab` checks for a profile. The result appears as a **top-level field** in the response:
|
|
23
23
|
|
|
24
24
|
- **`siteProfile`** present → read it before doing anything else. It contains strategies, quirks, and recipes. Apply its `settledWhen`/`readyWhen` hooks, use its selectors, and respect its quirks.
|
|
25
25
|
- **`actionRequired`** present → **STOP. Create the profile NOW** before continuing your task:
|
|
@@ -33,69 +33,61 @@ The profile only needs to capture what's useful: environment, quirks, stable sel
|
|
|
33
33
|
|
|
34
34
|
After completing your goal, update the site profile with anything you learned. Discovered a quirk? Found a reliable selector? Worked out a multi-step flow? Call `writeSiteProfile` again with the improved content before closing your tab. If you didn't learn anything new, skip the update.
|
|
35
35
|
|
|
36
|
-
### readSiteProfile
|
|
37
|
-
|
|
38
|
-
`"domain"` | `{domain}` — returns `{found, domain, content}` or `{found: false, domain}`
|
|
39
|
-
|
|
40
|
-
Read a site profile without navigating. Use this to check or update a profile ad-hoc.
|
|
41
|
-
|
|
42
|
-
### writeSiteProfile
|
|
43
|
-
|
|
44
|
-
`{domain, content}` — returns `{written, path, domain}`
|
|
45
|
-
|
|
46
36
|
### Profile format
|
|
47
37
|
|
|
48
38
|
```
|
|
49
|
-
#
|
|
50
|
-
Updated:
|
|
39
|
+
# domain.com
|
|
40
|
+
Updated: YYYY-MM-DD | Fingerprint: <tech-stack>
|
|
41
|
+
|
|
42
|
+
## Environment / Quirks / Strategies / Regions / Recipes
|
|
43
|
+
```
|
|
51
44
|
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
45
|
+
- **Environment**: tech stack, SPA behavior, main element selectors
|
|
46
|
+
- **Quirks**: pitfalls that cause failures without foreknowledge
|
|
47
|
+
- **Strategies**: how to fill, click, or wait on this specific site (include `settledWhen`/`readyWhen` hooks)
|
|
48
|
+
- **Regions**: stable landmark selectors
|
|
49
|
+
- **Recipes**: pre-built step sequences for common flows
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
- Turbo intercepts link clicks — use settledWhen with URL check
|
|
58
|
-
- Search results load async — poll for .results-count before extracting
|
|
51
|
+
Sections are optional — include what's useful. See EXAMPLES.md for a full profile template.
|
|
59
52
|
|
|
60
|
-
|
|
61
|
-
### fill (React controlled inputs)
|
|
62
|
-
Use nativeSetter.call(el, value) then dispatch input event with bubbles.
|
|
53
|
+
### readSiteProfile
|
|
63
54
|
|
|
64
|
-
|
|
65
|
-
settledWhen: () => !document.querySelector('.loading-bar')
|
|
55
|
+
`"domain"` | `{domain}` — returns `{found, domain, content}` or `{found: false, domain}`
|
|
66
56
|
|
|
67
|
-
|
|
68
|
-
- mainContent: main, [role="main"]
|
|
69
|
-
- navigation: .nav-bar
|
|
70
|
-
- searchResults: #search-results
|
|
57
|
+
### writeSiteProfile
|
|
71
58
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
59
|
+
`{domain, content}` — returns `{written, path, domain}`
|
|
60
|
+
```json
|
|
61
|
+
{"writeSiteProfile": {"domain": "example.com", "content": "# example.com\nUpdated: 2025-01-15\n\n## Environment\n- React SPA\n..."}}
|
|
75
62
|
```
|
|
76
63
|
|
|
77
|
-
Sections are optional — include what's useful. The key sections agents rely on:
|
|
78
|
-
- **Quirks**: pitfalls that cause failures without foreknowledge
|
|
79
|
-
- **Strategies**: how to fill, click, or wait on this specific site
|
|
80
|
-
- **Recipes**: pre-built step sequences for common flows
|
|
81
|
-
|
|
82
64
|
## Quick Start
|
|
83
65
|
|
|
84
|
-
|
|
85
|
-
|
|
66
|
+
```bash
|
|
67
|
+
echo '{"steps":[{"openTab":"https://google.com"}]}' | node src/cdp-skill.js
|
|
68
|
+
echo '{"tab":"t1","steps":[{"click":"#btn"}]}' | node src/cdp-skill.js
|
|
69
|
+
echo '{"tab":"t1","steps":[{"snapshot":true}]}' | node src/cdp-skill.js
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Tab IDs (t1, t2, ...) persist across CLI invocations. Chrome auto-launches if not running.
|
|
86
73
|
|
|
87
|
-
|
|
88
|
-
`node src/cdp-skill.js '{"steps":[{"openTab":"https://google.com"}]}'`
|
|
74
|
+
## Reliability (v1.0.10-1.0.11)
|
|
89
75
|
|
|
90
|
-
|
|
91
|
-
`node src/cdp-skill.js '{"config":{"tab":"t1"},"steps":[{"click":"#btn"}]}'`
|
|
76
|
+
Recent improvements to stability and correctness:
|
|
92
77
|
|
|
93
|
-
|
|
78
|
+
- **Validation robustness** — Fixed null pointer crashes in step validation for edge cases with missing or malformed parameters
|
|
79
|
+
- **Race condition fixes** — Resolved timing issues in browser connection initialization, file lock contention, and scroll-wait coordination
|
|
80
|
+
- **Resource cleanup** — Fixed HTTP connection leaks, event listener cleanup, and stderr stream handling
|
|
81
|
+
- **Frame context** — Corrected iframe element location and interaction to respect frame boundaries
|
|
82
|
+
- **Step simplification** — Consolidated 47 steps into 41 unified operations (fill, frame, elementsAt, pageFunction, sleep) for clearer API
|
|
83
|
+
|
|
84
|
+
The skill now passes 1261/1263 unit tests (99.8%) and maintains SHS 99/100 on the cdp-bench evaluation suite.
|
|
94
85
|
|
|
95
86
|
## Input / Output Schema
|
|
96
87
|
|
|
97
88
|
**Input fields:**
|
|
98
|
-
- `
|
|
89
|
+
- `tab`: tab alias (e.g. "t1") — required after first call
|
|
90
|
+
- `timeout`: step timeout in ms (default 30000)
|
|
99
91
|
- `steps`: array of step objects (one action per step)
|
|
100
92
|
|
|
101
93
|
**Output fields:**
|
|
@@ -119,8 +111,12 @@ Tab IDs (t1, t2, ...) persist across CLI invocations. Stdin pipe also works: `ec
|
|
|
119
111
|
|
|
120
112
|
## Element References
|
|
121
113
|
|
|
122
|
-
Snapshots return versioned refs like `[ref=
|
|
123
|
-
|
|
114
|
+
Snapshots return versioned refs like `[ref=f0s1e4]` — format: `f{frameId}s{snapshotId}e{elementNumber}`.
|
|
115
|
+
- `f0` = main frame (default)
|
|
116
|
+
- `f1`, `f2`, ... = iframe by index
|
|
117
|
+
- `f[name]` = iframe by name (e.g., `f[frame-top]`)
|
|
118
|
+
|
|
119
|
+
Each frame maintains its own snapshot counter. Use refs with `click`, `fill`, `hover`. Refs remain valid while the element is in DOM.
|
|
124
120
|
|
|
125
121
|
**Auto re-resolution**: when a ref's element leaves the DOM (React re-render, lazy-load), the system tries to re-find it by stored selector + role + name. Response includes `reResolved: true` on success.
|
|
126
122
|
|
|
@@ -129,7 +125,7 @@ Use refs with `click`, `fill`, `hover`. Each snapshot increments the ID. Refs fr
|
|
|
129
125
|
| Action | Waits For |
|
|
130
126
|
|--------|-----------|
|
|
131
127
|
| `click` | visible, enabled, stable, not covered, pointer-events |
|
|
132
|
-
| `fill
|
|
128
|
+
| `fill` | visible, enabled, editable |
|
|
133
129
|
| `hover` | visible, stable |
|
|
134
130
|
|
|
135
131
|
Use `force: true` to bypass all checks. **Auto-force**: when actionability times out but element exists, automatically retries with force (outputs `autoForced: true`).
|
|
@@ -144,195 +140,112 @@ Optional parameters on action steps to customize the step lifecycle:
|
|
|
144
140
|
|
|
145
141
|
Hooks can be combined on any action step. Applies to: click, fill, press, hover, drag, selectOption, scroll.
|
|
146
142
|
|
|
147
|
-
##
|
|
148
|
-
|
|
149
|
-
###
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
###
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
###
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
**queryAll**: {"label": "selector", ...}
|
|
255
|
-
|
|
256
|
-
**inspect**: true | {selectors[], limit}
|
|
257
|
-
returns: {title, url, counts, custom}
|
|
258
|
-
|
|
259
|
-
**console**: true | {level, type, since, limit, clear, stackTrace}
|
|
260
|
-
returns: {total, showing, messages[]}
|
|
261
|
-
notes: logs don't persist across CLI invocations
|
|
262
|
-
|
|
263
|
-
### Accessibility Snapshot
|
|
264
|
-
|
|
265
|
-
**snapshot**: true | {root, detail, mode, maxDepth, maxElements, includeText, includeFrames, pierceShadow, viewportOnly, inlineLimit, since}
|
|
266
|
-
detail: summary | interactive | full(default)
|
|
267
|
-
since: "s1" — returns {unchanged: true} if page hasn't changed
|
|
268
|
-
returns: YAML with role, "name", states, [ref=s{N}e{M}], snapshotId
|
|
269
|
-
notes: snapshots over 9KB saved to file (configurable via inlineLimit)
|
|
270
|
-
|
|
271
|
-
**snapshotSearch**: {text, pattern, role, exact, limit(10), context, near: {x, y, radius}}
|
|
272
|
-
returns: {matches[], matchCount, searchedElements}
|
|
273
|
-
notes: refs from snapshotSearch persist across subsequent commands
|
|
274
|
-
|
|
275
|
-
### Screenshots & PDF
|
|
276
|
-
|
|
277
|
-
Screenshots auto-captured on every visual action to `/tmp/cdp-skill/<tab>.before.png` and `.after.png`.
|
|
278
|
-
|
|
279
|
-
**pdf**: "filename" | {path, selector, landscape, printBackground, scale, paperWidth, paperHeight, margins, pageRanges, validate}
|
|
280
|
-
returns: {path, fileSize, fileSizeFormatted, pageCount, dimensions}
|
|
281
|
-
|
|
282
|
-
### Dynamic Browser Execution
|
|
283
|
-
|
|
284
|
-
**pageFunction**: "() => expr" | {fn, refs(bool), timeout}
|
|
285
|
-
notes: auto-wrapped as IIFE, refs passes window.__ariaRefs, return value auto-serialized, runs in current frame context
|
|
286
|
-
|
|
287
|
-
**poll**: "() => predicate" | {fn, interval(100), timeout(30000)}
|
|
288
|
-
returns: {resolved, value|lastValue, elapsed}
|
|
289
|
-
|
|
290
|
-
**pipeline**: [{find+fill|click|type|check|select}, {waitFor}, {sleep}, {return}] | {steps[], timeout(30000)}
|
|
291
|
-
returns: {completed, steps, results[]} or {completed: false, failedAt, error, results[]}
|
|
292
|
-
notes: compiles to single async JS function, zero roundtrips between micro-ops
|
|
293
|
-
|
|
294
|
-
### Form Validation
|
|
295
|
-
|
|
296
|
-
**validate**: "selector"
|
|
297
|
-
returns: {valid, message, validity}
|
|
298
|
-
|
|
299
|
-
**submit**: "selector" | {selector, reportValidity}
|
|
300
|
-
returns: {submitted, valid, errors[]}
|
|
301
|
-
|
|
302
|
-
### Assertions
|
|
303
|
-
|
|
304
|
-
**assert**: {url: {contains|equals|startsWith|endsWith|matches}} | {text} | {selector, text, caseSensitive}
|
|
305
|
-
|
|
306
|
-
### Tab Management
|
|
307
|
-
|
|
308
|
-
**listTabs**: true
|
|
309
|
-
returns: {count, tabs[]}
|
|
310
|
-
|
|
311
|
-
**closeTab**: "tabId"
|
|
312
|
-
returns: {closed}
|
|
313
|
-
|
|
314
|
-
**openTab**: true | "url" | {url}
|
|
315
|
-
returns: {opened, tab, url, navigated, viewportSnapshot, fullSnapshot, context}
|
|
316
|
-
response: top-level `siteProfile` or `actionRequired` when URL provided (see Site Profiles)
|
|
317
|
-
notes: REQUIRED as first step when no tab specified
|
|
318
|
-
|
|
319
|
-
### Viewport
|
|
320
|
-
|
|
321
|
-
**viewport**: "preset" | {width, height, deviceScaleFactor, mobile, hasTouch, isLandscape}
|
|
322
|
-
presets: iphone-se, iphone-14, iphone-15-pro, ipad, ipad-pro-11, pixel-7, samsung-galaxy-s23, desktop, desktop-hd, macbook-pro-14
|
|
323
|
-
returns: {width, height, deviceScaleFactor, mobile, hasTouch}
|
|
324
|
-
|
|
325
|
-
### Cookies
|
|
326
|
-
|
|
327
|
-
**cookies**: {get: true|[urls], name?} | {set: [{name, value, domain, expires}]} | {delete: "name", domain?} | {clear: true, domain?}
|
|
328
|
-
expires formats: 30m, 1h, 7d, 1w, 1y, or Unix timestamp
|
|
329
|
-
returns: get → {cookies[]}; set → {action, count}; delete/clear → {action, count}
|
|
330
|
-
notes: get without URLs returns only current tab's domain cookies
|
|
331
|
-
|
|
332
|
-
### JavaScript Execution
|
|
333
|
-
|
|
334
|
-
**eval**: "expression" | {expression, await, timeout, serialize}
|
|
335
|
-
returns: typed results (Number, Date, Map, Set, Element, NodeList, etc.)
|
|
143
|
+
## Core Steps
|
|
144
|
+
|
|
145
|
+
### chromeStatus (optional diagnostic)
|
|
146
|
+
`true` | `{host, port, headless, autoLaunch}` — returns `{running, launched, version, port, tabs[]}`
|
|
147
|
+
|
|
148
|
+
> **Note**: You rarely need this — `newTab` auto-launches Chrome. Use `chromeStatus` only for diagnostics or non-default ports.
|
|
149
|
+
|
|
150
|
+
### newTab
|
|
151
|
+
`true` | `"url"` | `{url, host, port, headless}` — returns `{opened, tab, url, navigated, viewportSnapshot, fullSnapshot, context}`
|
|
152
|
+
Response includes top-level `siteProfile` or `actionRequired` when URL provided (see Site Profiles).
|
|
153
|
+
**REQUIRED as first step** when no tab specified. Chrome auto-launches if not running.
|
|
154
|
+
Non-default Chrome: `{"steps":[{"newTab":{"url":"https://example.com","port":9333,"headless":true}}]}`
|
|
155
|
+
|
|
156
|
+
### goto
|
|
157
|
+
`"url"` | `{url, waitUntil}` — waitUntil: commit | domcontentloaded | load | networkidle
|
|
158
|
+
Response includes top-level `siteProfile` or `actionRequired` (see Site Profiles).
|
|
159
|
+
|
|
160
|
+
### click
|
|
161
|
+
`"selector"` | `"ref"` | `{ref, selector, text, x/y, selectors[]}`
|
|
162
|
+
Options: force, jsClick, nativeOnly, doubleClick, scrollUntilVisible, searchFrames, exact, timeout, waitAfter
|
|
163
|
+
Hooks: readyWhen, settledWhen, observe
|
|
164
|
+
Returns: `{clicked, method: "cdp"|"jsClick"|"jsClick-auto", navigated?, newUrl?, newTabs?: [{targetId, url, title}]}`
|
|
165
|
+
|
|
166
|
+
### fill
|
|
167
|
+
`{selector|ref|label, value}` — the primary way to input text.
|
|
168
|
+
Options: clear(true), react, force, exact, timeout
|
|
169
|
+
Hooks: readyWhen, settledWhen, observe
|
|
170
|
+
Returns: `{filled, navigated?, newUrl?}`
|
|
171
|
+
|
|
172
|
+
### press
|
|
173
|
+
`"Enter"` | `"Control+a"` | `"Meta+Shift+Enter"` — keyboard shortcuts and key presses.
|
|
174
|
+
|
|
175
|
+
### scroll
|
|
176
|
+
`"top"` | `"bottom"` | `"selector"` | `{deltaY}` | `{x, y}`
|
|
177
|
+
Returns: `{scrollX, scrollY}`
|
|
178
|
+
|
|
179
|
+
### snapshot
|
|
180
|
+
`true` | `{root, detail, mode, maxDepth, maxElements, includeText, includeFrames, pierceShadow, viewportOnly, inlineLimit, since}`
|
|
181
|
+
Detail: summary | interactive | full(default)
|
|
182
|
+
Since: `"f0s1"` — returns `{unchanged: true}` if page hasn't changed
|
|
183
|
+
Returns: YAML with role, "name", states, `[ref=f{F}s{N}e{M}]`, snapshotId (`f0s1`, `f1s1`, etc.)
|
|
184
|
+
Notes: snapshots over 9KB saved to file (configurable via inlineLimit)
|
|
185
|
+
|
|
186
|
+
### snapshotSearch
|
|
187
|
+
`{text, pattern, role, exact, limit(10), context, near: {x, y, radius}}`
|
|
188
|
+
Returns: `{matches[], matchCount, searchedElements}`
|
|
189
|
+
Notes: refs from snapshotSearch persist across subsequent commands.
|
|
190
|
+
|
|
191
|
+
### wait
|
|
192
|
+
`"selector"` | `{selector, hidden, minCount}` | `{text}` | `{textRegex}` | `{urlContains}`
|
|
193
|
+
|
|
194
|
+
### get
|
|
195
|
+
`"selector"` (text) | `{selector, mode: "text"|"html"|"value"|"box"|"attributes"}` — unified content extraction.
|
|
196
|
+
Returns: text → `{text}`, html → `{html, tagName, length}`, value → `{fields[], valid, fieldCount}`, box → `{x, y, width, height}`, attributes → `{attributes}`
|
|
197
|
+
|
|
198
|
+
### getUrl
|
|
199
|
+
`true` — returns `{url}`
|
|
200
|
+
|
|
201
|
+
### getTitle
|
|
202
|
+
`true` — returns `{title}`
|
|
203
|
+
|
|
204
|
+
### pageFunction
|
|
205
|
+
`"() => expr"` | `{fn, refs(bool), timeout}` — run custom JavaScript in the browser.
|
|
206
|
+
Notes: auto-wrapped as IIFE, refs passes `window.__ariaRefs`, return value auto-serialized, runs in current frame context.
|
|
207
|
+
|
|
208
|
+
### closeTab
|
|
209
|
+
`"tabId"` — returns `{closed}`
|
|
210
|
+
|
|
211
|
+
### listTabs
|
|
212
|
+
`true` — returns `{count, tabs[]}`
|
|
213
|
+
|
|
214
|
+
## Also Available
|
|
215
|
+
|
|
216
|
+
These steps are fully functional — see EXAMPLES.md for usage details.
|
|
217
|
+
|
|
218
|
+
| Step | Description |
|
|
219
|
+
|------|-------------|
|
|
220
|
+
| `fill` | Unified fill (replaces `type`): `"text"` (focused), `{selector, value}` (single), `{"#a":"x","#b":"y"}` (batch), `{fields:{...}, react}` (batch+options), `{value, clear}` (focused+options) |
|
|
221
|
+
| `sleep` | Time delay: `2000` (ms, 0–60000) |
|
|
222
|
+
| `pageFunction` | JS execution: `"() => expr"` (function) or `"document.title"` (bare expression) or `{fn, expression, refs, timeout}` |
|
|
223
|
+
| `poll` | Poll predicate until truthy: `"() => expr"` or `{fn, interval, timeout}` |
|
|
224
|
+
| `query` | CSS/ARIA query: `"selector"` or `{role, name}` → `{total, results[]}` |
|
|
225
|
+
| `queryAll` | Batch queries: `{"label": "selector", ...}` |
|
|
226
|
+
| `inspect` | Page overview: `true` → `{title, url, counts}` |
|
|
227
|
+
| `get` | Unified content extraction (replaces `extract`, `getDom`, `getBox`, `formState`): `"selector"` (text), `{selector, mode: "text"\|"html"\|"value"\|"box"\|"attributes"}` |
|
|
228
|
+
| `getUrl` | Get current URL: `true` → `{url}` |
|
|
229
|
+
| `getTitle` | Get page title: `true` → `{title}` |
|
|
230
|
+
| `hover` | Hover element: `"selector"` or `{selector, ref, text, x/y, duration}` |
|
|
231
|
+
| `drag` | Drag and drop: `{source, target, steps, delay, method}` — method: `auto`(default)\|`mouse`\|`html5` |
|
|
232
|
+
| `selectText` | Text selection (renamed from `select`): `"selector"` or `{selector, start, end}` |
|
|
233
|
+
| `selectOption` | Dropdown: `{selector, value\|label\|index\|values}` |
|
|
234
|
+
| `submit` | Submit form: `"selector"` → `{submitted, valid, errors[]}` |
|
|
235
|
+
| `assert` | Assert conditions: `{url: {contains\|equals\|matches}}` or `{text}` or `{selector, text}` |
|
|
236
|
+
| `elementsAt` | Coordinate lookup: `{x,y}` (point), `[{x,y},...]` (batch), `{x,y,radius}` (nearby) |
|
|
237
|
+
| `frame` | Frame ops: `"selector"` (switch), `0` (by index), `"top"` (main frame), `{name}`, `{list:true}` |
|
|
238
|
+
| `viewport` | Set viewport: `"iphone-14"` or `{width, height, mobile}` |
|
|
239
|
+
| `cookies` | Get/set/delete: `{get: true}`, `{set: [...]}`, `{delete: "name"}`, `{clear: true}` |
|
|
240
|
+
| `console` | Browser console: `true` or `{level, limit, clear}` → `{messages[]}` |
|
|
241
|
+
| `pdf` | Generate PDF: `"filename"` or `{path, landscape, scale, pageRanges}` |
|
|
242
|
+
| `back` / `forward` | History navigation: `true` → `{url, title}` or `{noHistory: true}` |
|
|
243
|
+
| `reload` | Reload page: `true` or `{waitUntil}` |
|
|
244
|
+
| `newTab` | Create new tab (renamed from `openTab`): `"url"` or `{url, wait}` → `{tab, url}` |
|
|
245
|
+
| `switchTab` | Switch to existing tab (renamed from `connectTab`): `"t1"` or `{targetId}` or `{url: "regex"}` |
|
|
246
|
+
| `closeTab` | Close tab: `"t1"` or `true` (current) |
|
|
247
|
+
| `listTabs` | List all tabs: `true` → `{tabs[]}` |
|
|
248
|
+
| `waitForNavigation` | Wait for nav: `true` or `{timeout, waitUntil}` |
|
|
336
249
|
|
|
337
250
|
### Optional Steps
|
|
338
251
|
|
|
@@ -342,25 +255,28 @@ Add `"optional": true` to any step to continue on failure (status becomes "skipp
|
|
|
342
255
|
|
|
343
256
|
| Issue | Solution |
|
|
344
257
|
|-------|----------|
|
|
345
|
-
| Tabs accumulating | Include `tab`
|
|
346
|
-
| CONNECTION error |
|
|
258
|
+
| Tabs accumulating | Include `tab` at top level |
|
|
259
|
+
| CONNECTION error | Check Chrome is reachable; use `chromeStatus` to diagnose |
|
|
347
260
|
| Chrome not found | Set `CHROME_PATH` env var |
|
|
348
261
|
| Element not found | Add `wait` step first |
|
|
349
262
|
| Clicks not working | Scroll into view first, or `force: true` |
|
|
350
263
|
| `back` returns noHistory | New tabs start at about:blank; navigate first |
|
|
351
264
|
| Select dropdown not working | Use click+click or press arrow keys |
|
|
352
265
|
| Type not appearing | Click input first to focus, then type |
|
|
266
|
+
| Elements missing from snapshot | Custom widgets may lack ARIA roles; use `pageFunction` or `get` with `mode: "html"` as fallback |
|
|
353
267
|
| macOS: Chrome running but no CDP | `chromeStatus` launches new instance with CDP enabled |
|
|
354
268
|
|
|
355
269
|
## Best Practices
|
|
356
270
|
|
|
357
271
|
- **Handle `actionRequired` immediately** — when a response contains this field, complete it before doing anything else
|
|
358
|
-
- **Never launch Chrome directly** —
|
|
359
|
-
- **Use
|
|
272
|
+
- **Never launch Chrome directly** — `newTab` handles it automatically
|
|
273
|
+
- **Use newTab** as your first step to create a tab; use the returned tab ID for all subsequent calls
|
|
360
274
|
- **Reuse only your own tabs** — other agents may share the browser
|
|
361
275
|
- **Update the site profile before closing** — add any quirks, selectors, or recipes you discovered
|
|
362
276
|
- **Close your tab when done** — `closeTab` with your tab ID
|
|
363
|
-
- **Discover before interacting** — use `snapshot`
|
|
277
|
+
- **Discover before interacting** — use `snapshot` to understand the page structure
|
|
364
278
|
- **Use website navigation** — click links and submit forms; don't guess URLs
|
|
365
279
|
- **Prefer refs** over CSS selectors — use `snapshot` + refs for resilient targeting
|
|
280
|
+
- **Check `newTabs` after click** — clicks on `target="_blank"` links report new tabs; use `switchTab` to switch
|
|
281
|
+
- **Use `switchTab` for popups** — connect by alias (`"t2"`), targetId, or URL regex (`{url: "pattern"}`)
|
|
366
282
|
- **Be persistent** — try alternative selectors, add waits, scroll first
|
package/install.js
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ARIA Module
|
|
3
|
+
* Re-exports accessibility tree and role-based query functionality
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { createQueryOutputProcessor } from './output-processor.js';
|
|
7
|
+
export { createRoleQueryExecutor } from './role-query.js';
|
|
8
|
+
export { createAriaSnapshot } from './snapshot.js';
|