cdp-skill 1.0.14 → 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/SKILL.md +8 -4
- package/package.json +1 -1
- package/src/aria.js +14 -7
- package/src/cdp-skill.js +2 -1
- package/src/dom/LazyResolver.js +634 -0
- package/src/dom/click-executor.js +162 -54
- package/src/dom/fill-executor.js +32 -27
- package/src/dom/index.js +3 -0
- package/src/page/page-controller.js +46 -0
- package/src/runner/execute-interaction.js +6 -6
- package/src/runner/execute-navigation.js +3 -3
- package/src/runner/execute-query.js +9 -6
- package/src/runner/step-registry.js +4 -4
- package/src/tests/Aria.test.js +5 -5
- package/src/tests/ClickExecutor.test.js +170 -50
- package/src/tests/ContextHelpers.test.js +2 -2
- package/src/tests/ExecuteInteraction.test.js +2 -2
- package/src/tests/ExecuteQuery.test.js +33 -33
- package/src/tests/FillExecutor.test.js +87 -35
- package/src/tests/LazyResolver.test.js +383 -0
- package/src/tests/StepValidator.test.js +2 -2
- package/src/tests/TestRunner.test.js +2 -2
package/SKILL.md
CHANGED
|
@@ -111,8 +111,12 @@ The skill now passes 1261/1263 unit tests (99.8%) and maintains SHS 99/100 on th
|
|
|
111
111
|
|
|
112
112
|
## Element References
|
|
113
113
|
|
|
114
|
-
Snapshots return versioned refs like `[ref=
|
|
115
|
-
|
|
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.
|
|
116
120
|
|
|
117
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.
|
|
118
122
|
|
|
@@ -175,8 +179,8 @@ Returns: `{scrollX, scrollY}`
|
|
|
175
179
|
### snapshot
|
|
176
180
|
`true` | `{root, detail, mode, maxDepth, maxElements, includeText, includeFrames, pierceShadow, viewportOnly, inlineLimit, since}`
|
|
177
181
|
Detail: summary | interactive | full(default)
|
|
178
|
-
Since: `"
|
|
179
|
-
Returns: YAML with role, "name", states, `[ref=s{N}e{M}]`, snapshotId
|
|
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.)
|
|
180
184
|
Notes: snapshots over 9KB saved to file (configurable via inlineLimit)
|
|
181
185
|
|
|
182
186
|
### snapshotSearch
|
package/package.json
CHANGED
package/src/aria.js
CHANGED
|
@@ -475,7 +475,7 @@ export function createRoleQueryExecutor(session, elementLocator, options = {}) {
|
|
|
475
475
|
// The snapshot script runs entirely in the browser context
|
|
476
476
|
const SNAPSHOT_SCRIPT = `
|
|
477
477
|
(function generateAriaSnapshot(rootSelector, options) {
|
|
478
|
-
const { mode = 'ai', maxDepth = 50, maxElements = 0, includeText = false, includeFrames = false, viewportOnly = false, pierceShadow = false, preserveRefs = false, since = null, internal = false } = options || {};
|
|
478
|
+
const { mode = 'ai', maxDepth = 50, maxElements = 0, includeText = false, includeFrames = false, viewportOnly = false, pierceShadow = false, preserveRefs = false, since = null, internal = false, frameIdentifier = 'f0' } = options || {};
|
|
479
479
|
|
|
480
480
|
// Viewport dimensions for viewport-only mode
|
|
481
481
|
const viewportWidth = window.innerWidth;
|
|
@@ -491,6 +491,9 @@ const SNAPSHOT_SCRIPT = `
|
|
|
491
491
|
window.__ariaSnapshotId = 0;
|
|
492
492
|
}
|
|
493
493
|
|
|
494
|
+
// Store frame identifier for ref generation (used by all ref-generating operations)
|
|
495
|
+
window.__ariaFrameIdentifier = frameIdentifier;
|
|
496
|
+
|
|
494
497
|
// Compute page hash for change detection
|
|
495
498
|
// Hash combines: URL + scroll position + DOM size + interactive element count
|
|
496
499
|
function computePageHash() {
|
|
@@ -514,7 +517,7 @@ const SNAPSHOT_SCRIPT = `
|
|
|
514
517
|
if (currentHash === window.__ariaSnapshotHash) {
|
|
515
518
|
return {
|
|
516
519
|
unchanged: true,
|
|
517
|
-
snapshotId: 's' + window.__ariaSnapshotId,
|
|
520
|
+
snapshotId: frameIdentifier + 's' + window.__ariaSnapshotId,
|
|
518
521
|
hash: currentHash
|
|
519
522
|
};
|
|
520
523
|
}
|
|
@@ -951,9 +954,9 @@ const SNAPSHOT_SCRIPT = `
|
|
|
951
954
|
}
|
|
952
955
|
}
|
|
953
956
|
|
|
954
|
-
// New element - assign new ref with versioned format: s{snapshotId}e{refCounter}
|
|
957
|
+
// New element - assign new ref with versioned format: f{frameId}s{snapshotId}e{refCounter}
|
|
955
958
|
refCounter++;
|
|
956
|
-
const ref = 's' + currentSnapshotId + 'e' + refCounter;
|
|
959
|
+
const ref = frameIdentifier + 's' + currentSnapshotId + 'e' + refCounter;
|
|
957
960
|
elementRefs.set(el, ref);
|
|
958
961
|
refElements.set(ref, el);
|
|
959
962
|
// Store metadata for re-resolution fallback
|
|
@@ -1389,7 +1392,7 @@ const SNAPSHOT_SCRIPT = `
|
|
|
1389
1392
|
yaml,
|
|
1390
1393
|
refs,
|
|
1391
1394
|
truncated: limitReached,
|
|
1392
|
-
snapshotId: 's' + currentSnapshotId
|
|
1395
|
+
snapshotId: frameIdentifier + 's' + currentSnapshotId
|
|
1393
1396
|
};
|
|
1394
1397
|
if (autoScoped) snapshotResult.autoScoped = true;
|
|
1395
1398
|
return snapshotResult;
|
|
@@ -1403,6 +1406,7 @@ const SNAPSHOT_SCRIPT = `
|
|
|
1403
1406
|
*/
|
|
1404
1407
|
export function createAriaSnapshot(session, options = {}) {
|
|
1405
1408
|
const getFrameContext = options.getFrameContext || null;
|
|
1409
|
+
const getFrameIdentifier = options.getFrameIdentifier || null;
|
|
1406
1410
|
/**
|
|
1407
1411
|
* Generate accessibility snapshot of the page
|
|
1408
1412
|
* @param {Object} options - Snapshot options
|
|
@@ -1416,14 +1420,17 @@ export function createAriaSnapshot(session, options = {}) {
|
|
|
1416
1420
|
* @param {boolean} options.viewportOnly - Only include elements visible in viewport (default: false)
|
|
1417
1421
|
* @param {boolean} options.pierceShadow - Traverse into open shadow DOM trees (default: false)
|
|
1418
1422
|
* @param {boolean} options.preserveRefs - Merge new refs into existing instead of overwriting (default: false)
|
|
1419
|
-
* @param {string} options.since - Snapshot ID to check against (e.g., "
|
|
1423
|
+
* @param {string} options.since - Snapshot ID to check against (e.g., "f0s1") - returns {unchanged: true} if page hasn't changed
|
|
1420
1424
|
* @returns {Promise<Object>} Snapshot result with tree, yaml, refs, and snapshotId
|
|
1421
1425
|
*/
|
|
1422
1426
|
async function generate(options = {}) {
|
|
1423
1427
|
const { root = null, mode = 'ai', detail = 'full', maxDepth = 50, maxElements = 0, includeText = false, includeFrames = false, viewportOnly = false, pierceShadow = false, preserveRefs = false, since = null, internal = false } = options;
|
|
1424
1428
|
|
|
1429
|
+
// Get frame identifier for ref generation (f0 for main frame, f1, f2, etc. for iframes)
|
|
1430
|
+
const frameIdentifier = getFrameIdentifier ? await getFrameIdentifier() : 'f0';
|
|
1431
|
+
|
|
1425
1432
|
const evalArgs = {
|
|
1426
|
-
expression: `(${SNAPSHOT_SCRIPT})(${JSON.stringify(root)}, ${JSON.stringify({ mode, detail, maxDepth, maxElements, includeText, includeFrames, viewportOnly, pierceShadow, preserveRefs, since, internal })})`,
|
|
1433
|
+
expression: `(${SNAPSHOT_SCRIPT})(${JSON.stringify(root)}, ${JSON.stringify({ mode, detail, maxDepth, maxElements, includeText, includeFrames, viewportOnly, pierceShadow, preserveRefs, since, internal, frameIdentifier })})`,
|
|
1427
1434
|
returnByValue: true,
|
|
1428
1435
|
awaitPromise: false
|
|
1429
1436
|
};
|
package/src/cdp-skill.js
CHANGED
|
@@ -687,12 +687,13 @@ async function main() {
|
|
|
687
687
|
getSavedFrameState: () => loadFrameState(session.targetId)
|
|
688
688
|
});
|
|
689
689
|
const frameContextProvider = () => pageController.getFrameContext();
|
|
690
|
+
const frameIdentifierProvider = () => pageController.getFrameIdentifier();
|
|
690
691
|
const elementLocator = createElementLocator(session, { getFrameContext: frameContextProvider });
|
|
691
692
|
const inputEmulator = createInputEmulator(session);
|
|
692
693
|
const screenshotCapture = createScreenshotCapture(session);
|
|
693
694
|
const consoleCapture = createConsoleCapture(session);
|
|
694
695
|
const pdfCapture = createPdfCapture(session);
|
|
695
|
-
const ariaSnapshot = createAriaSnapshot(session, { getFrameContext: frameContextProvider });
|
|
696
|
+
const ariaSnapshot = createAriaSnapshot(session, { getFrameContext: frameContextProvider, getFrameIdentifier: frameIdentifierProvider });
|
|
696
697
|
const cookieManager = createCookieManager(session);
|
|
697
698
|
|
|
698
699
|
// Initialize page controller (enables required CDP domains)
|