cdp-skill 1.0.8 → 1.0.14
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 +151 -239
- 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 +237 -43
- package/src/cdp/browser.js +22 -4
- package/src/cdp-skill.js +245 -69
- package/src/dom/click-executor.js +240 -76
- package/src/dom/element-locator.js +34 -25
- package/src/dom/fill-executor.js +55 -27
- package/src/page/dialog-handler.js +119 -0
- package/src/page/page-controller.js +190 -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 +99 -120
- package/src/runner/execute-navigation.js +11 -26
- package/src/runner/execute-query.js +8 -5
- 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/ContextHelpers.test.js +39 -28
- 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 +2 -2
- package/src/tests/StepValidator.test.js +222 -76
- package/src/tests/TestRunner.test.js +36 -25
- 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:**
|
|
@@ -129,7 +121,7 @@ Use refs with `click`, `fill`, `hover`. Each snapshot increments the ID. Refs fr
|
|
|
129
121
|
| Action | Waits For |
|
|
130
122
|
|--------|-----------|
|
|
131
123
|
| `click` | visible, enabled, stable, not covered, pointer-events |
|
|
132
|
-
| `fill
|
|
124
|
+
| `fill` | visible, enabled, editable |
|
|
133
125
|
| `hover` | visible, stable |
|
|
134
126
|
|
|
135
127
|
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 +136,112 @@ Optional parameters on action steps to customize the step lifecycle:
|
|
|
144
136
|
|
|
145
137
|
Hooks can be combined on any action step. Applies to: click, fill, press, hover, drag, selectOption, scroll.
|
|
146
138
|
|
|
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.)
|
|
139
|
+
## Core Steps
|
|
140
|
+
|
|
141
|
+
### chromeStatus (optional diagnostic)
|
|
142
|
+
`true` | `{host, port, headless, autoLaunch}` — returns `{running, launched, version, port, tabs[]}`
|
|
143
|
+
|
|
144
|
+
> **Note**: You rarely need this — `newTab` auto-launches Chrome. Use `chromeStatus` only for diagnostics or non-default ports.
|
|
145
|
+
|
|
146
|
+
### newTab
|
|
147
|
+
`true` | `"url"` | `{url, host, port, headless}` — returns `{opened, tab, url, navigated, viewportSnapshot, fullSnapshot, context}`
|
|
148
|
+
Response includes top-level `siteProfile` or `actionRequired` when URL provided (see Site Profiles).
|
|
149
|
+
**REQUIRED as first step** when no tab specified. Chrome auto-launches if not running.
|
|
150
|
+
Non-default Chrome: `{"steps":[{"newTab":{"url":"https://example.com","port":9333,"headless":true}}]}`
|
|
151
|
+
|
|
152
|
+
### goto
|
|
153
|
+
`"url"` | `{url, waitUntil}` — waitUntil: commit | domcontentloaded | load | networkidle
|
|
154
|
+
Response includes top-level `siteProfile` or `actionRequired` (see Site Profiles).
|
|
155
|
+
|
|
156
|
+
### click
|
|
157
|
+
`"selector"` | `"ref"` | `{ref, selector, text, x/y, selectors[]}`
|
|
158
|
+
Options: force, jsClick, nativeOnly, doubleClick, scrollUntilVisible, searchFrames, exact, timeout, waitAfter
|
|
159
|
+
Hooks: readyWhen, settledWhen, observe
|
|
160
|
+
Returns: `{clicked, method: "cdp"|"jsClick"|"jsClick-auto", navigated?, newUrl?, newTabs?: [{targetId, url, title}]}`
|
|
161
|
+
|
|
162
|
+
### fill
|
|
163
|
+
`{selector|ref|label, value}` — the primary way to input text.
|
|
164
|
+
Options: clear(true), react, force, exact, timeout
|
|
165
|
+
Hooks: readyWhen, settledWhen, observe
|
|
166
|
+
Returns: `{filled, navigated?, newUrl?}`
|
|
167
|
+
|
|
168
|
+
### press
|
|
169
|
+
`"Enter"` | `"Control+a"` | `"Meta+Shift+Enter"` — keyboard shortcuts and key presses.
|
|
170
|
+
|
|
171
|
+
### scroll
|
|
172
|
+
`"top"` | `"bottom"` | `"selector"` | `{deltaY}` | `{x, y}`
|
|
173
|
+
Returns: `{scrollX, scrollY}`
|
|
174
|
+
|
|
175
|
+
### snapshot
|
|
176
|
+
`true` | `{root, detail, mode, maxDepth, maxElements, includeText, includeFrames, pierceShadow, viewportOnly, inlineLimit, since}`
|
|
177
|
+
Detail: summary | interactive | full(default)
|
|
178
|
+
Since: `"s1"` — returns `{unchanged: true}` if page hasn't changed
|
|
179
|
+
Returns: YAML with role, "name", states, `[ref=s{N}e{M}]`, snapshotId
|
|
180
|
+
Notes: snapshots over 9KB saved to file (configurable via inlineLimit)
|
|
181
|
+
|
|
182
|
+
### snapshotSearch
|
|
183
|
+
`{text, pattern, role, exact, limit(10), context, near: {x, y, radius}}`
|
|
184
|
+
Returns: `{matches[], matchCount, searchedElements}`
|
|
185
|
+
Notes: refs from snapshotSearch persist across subsequent commands.
|
|
186
|
+
|
|
187
|
+
### wait
|
|
188
|
+
`"selector"` | `{selector, hidden, minCount}` | `{text}` | `{textRegex}` | `{urlContains}`
|
|
189
|
+
|
|
190
|
+
### get
|
|
191
|
+
`"selector"` (text) | `{selector, mode: "text"|"html"|"value"|"box"|"attributes"}` — unified content extraction.
|
|
192
|
+
Returns: text → `{text}`, html → `{html, tagName, length}`, value → `{fields[], valid, fieldCount}`, box → `{x, y, width, height}`, attributes → `{attributes}`
|
|
193
|
+
|
|
194
|
+
### getUrl
|
|
195
|
+
`true` — returns `{url}`
|
|
196
|
+
|
|
197
|
+
### getTitle
|
|
198
|
+
`true` — returns `{title}`
|
|
199
|
+
|
|
200
|
+
### pageFunction
|
|
201
|
+
`"() => expr"` | `{fn, refs(bool), timeout}` — run custom JavaScript in the browser.
|
|
202
|
+
Notes: auto-wrapped as IIFE, refs passes `window.__ariaRefs`, return value auto-serialized, runs in current frame context.
|
|
203
|
+
|
|
204
|
+
### closeTab
|
|
205
|
+
`"tabId"` — returns `{closed}`
|
|
206
|
+
|
|
207
|
+
### listTabs
|
|
208
|
+
`true` — returns `{count, tabs[]}`
|
|
209
|
+
|
|
210
|
+
## Also Available
|
|
211
|
+
|
|
212
|
+
These steps are fully functional — see EXAMPLES.md for usage details.
|
|
213
|
+
|
|
214
|
+
| Step | Description |
|
|
215
|
+
|------|-------------|
|
|
216
|
+
| `fill` | Unified fill (replaces `type`): `"text"` (focused), `{selector, value}` (single), `{"#a":"x","#b":"y"}` (batch), `{fields:{...}, react}` (batch+options), `{value, clear}` (focused+options) |
|
|
217
|
+
| `sleep` | Time delay: `2000` (ms, 0–60000) |
|
|
218
|
+
| `pageFunction` | JS execution: `"() => expr"` (function) or `"document.title"` (bare expression) or `{fn, expression, refs, timeout}` |
|
|
219
|
+
| `poll` | Poll predicate until truthy: `"() => expr"` or `{fn, interval, timeout}` |
|
|
220
|
+
| `query` | CSS/ARIA query: `"selector"` or `{role, name}` → `{total, results[]}` |
|
|
221
|
+
| `queryAll` | Batch queries: `{"label": "selector", ...}` |
|
|
222
|
+
| `inspect` | Page overview: `true` → `{title, url, counts}` |
|
|
223
|
+
| `get` | Unified content extraction (replaces `extract`, `getDom`, `getBox`, `formState`): `"selector"` (text), `{selector, mode: "text"\|"html"\|"value"\|"box"\|"attributes"}` |
|
|
224
|
+
| `getUrl` | Get current URL: `true` → `{url}` |
|
|
225
|
+
| `getTitle` | Get page title: `true` → `{title}` |
|
|
226
|
+
| `hover` | Hover element: `"selector"` or `{selector, ref, text, x/y, duration}` |
|
|
227
|
+
| `drag` | Drag and drop: `{source, target, steps, delay, method}` — method: `auto`(default)\|`mouse`\|`html5` |
|
|
228
|
+
| `selectText` | Text selection (renamed from `select`): `"selector"` or `{selector, start, end}` |
|
|
229
|
+
| `selectOption` | Dropdown: `{selector, value\|label\|index\|values}` |
|
|
230
|
+
| `submit` | Submit form: `"selector"` → `{submitted, valid, errors[]}` |
|
|
231
|
+
| `assert` | Assert conditions: `{url: {contains\|equals\|matches}}` or `{text}` or `{selector, text}` |
|
|
232
|
+
| `elementsAt` | Coordinate lookup: `{x,y}` (point), `[{x,y},...]` (batch), `{x,y,radius}` (nearby) |
|
|
233
|
+
| `frame` | Frame ops: `"selector"` (switch), `0` (by index), `"top"` (main frame), `{name}`, `{list:true}` |
|
|
234
|
+
| `viewport` | Set viewport: `"iphone-14"` or `{width, height, mobile}` |
|
|
235
|
+
| `cookies` | Get/set/delete: `{get: true}`, `{set: [...]}`, `{delete: "name"}`, `{clear: true}` |
|
|
236
|
+
| `console` | Browser console: `true` or `{level, limit, clear}` → `{messages[]}` |
|
|
237
|
+
| `pdf` | Generate PDF: `"filename"` or `{path, landscape, scale, pageRanges}` |
|
|
238
|
+
| `back` / `forward` | History navigation: `true` → `{url, title}` or `{noHistory: true}` |
|
|
239
|
+
| `reload` | Reload page: `true` or `{waitUntil}` |
|
|
240
|
+
| `newTab` | Create new tab (renamed from `openTab`): `"url"` or `{url, wait}` → `{tab, url}` |
|
|
241
|
+
| `switchTab` | Switch to existing tab (renamed from `connectTab`): `"t1"` or `{targetId}` or `{url: "regex"}` |
|
|
242
|
+
| `closeTab` | Close tab: `"t1"` or `true` (current) |
|
|
243
|
+
| `listTabs` | List all tabs: `true` → `{tabs[]}` |
|
|
244
|
+
| `waitForNavigation` | Wait for nav: `true` or `{timeout, waitUntil}` |
|
|
336
245
|
|
|
337
246
|
### Optional Steps
|
|
338
247
|
|
|
@@ -342,25 +251,28 @@ Add `"optional": true` to any step to continue on failure (status becomes "skipp
|
|
|
342
251
|
|
|
343
252
|
| Issue | Solution |
|
|
344
253
|
|-------|----------|
|
|
345
|
-
| Tabs accumulating | Include `tab`
|
|
346
|
-
| CONNECTION error |
|
|
254
|
+
| Tabs accumulating | Include `tab` at top level |
|
|
255
|
+
| CONNECTION error | Check Chrome is reachable; use `chromeStatus` to diagnose |
|
|
347
256
|
| Chrome not found | Set `CHROME_PATH` env var |
|
|
348
257
|
| Element not found | Add `wait` step first |
|
|
349
258
|
| Clicks not working | Scroll into view first, or `force: true` |
|
|
350
259
|
| `back` returns noHistory | New tabs start at about:blank; navigate first |
|
|
351
260
|
| Select dropdown not working | Use click+click or press arrow keys |
|
|
352
261
|
| Type not appearing | Click input first to focus, then type |
|
|
262
|
+
| Elements missing from snapshot | Custom widgets may lack ARIA roles; use `pageFunction` or `get` with `mode: "html"` as fallback |
|
|
353
263
|
| macOS: Chrome running but no CDP | `chromeStatus` launches new instance with CDP enabled |
|
|
354
264
|
|
|
355
265
|
## Best Practices
|
|
356
266
|
|
|
357
267
|
- **Handle `actionRequired` immediately** — when a response contains this field, complete it before doing anything else
|
|
358
|
-
- **Never launch Chrome directly** —
|
|
359
|
-
- **Use
|
|
268
|
+
- **Never launch Chrome directly** — `newTab` handles it automatically
|
|
269
|
+
- **Use newTab** as your first step to create a tab; use the returned tab ID for all subsequent calls
|
|
360
270
|
- **Reuse only your own tabs** — other agents may share the browser
|
|
361
271
|
- **Update the site profile before closing** — add any quirks, selectors, or recipes you discovered
|
|
362
272
|
- **Close your tab when done** — `closeTab` with your tab ID
|
|
363
|
-
- **Discover before interacting** — use `snapshot`
|
|
273
|
+
- **Discover before interacting** — use `snapshot` to understand the page structure
|
|
364
274
|
- **Use website navigation** — click links and submit forms; don't guess URLs
|
|
365
275
|
- **Prefer refs** over CSS selectors — use `snapshot` + refs for resilient targeting
|
|
276
|
+
- **Check `newTabs` after click** — clicks on `target="_blank"` links report new tabs; use `switchTab` to switch
|
|
277
|
+
- **Use `switchTab` for popups** — connect by alias (`"t2"`), targetId, or URL regex (`{url: "pattern"}`)
|
|
366
278
|
- **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';
|