browserclaw 0.10.4 → 0.10.5
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 +55 -126
- package/dist/index.cjs +30 -248
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -105
- package/dist/index.d.ts +3 -105
- package/dist/index.js +31 -248
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -48,9 +48,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
48
48
|
mod
|
|
49
49
|
));
|
|
50
50
|
|
|
51
|
-
// node_modules/ipaddr.js/lib/ipaddr.js
|
|
51
|
+
// ../../../node_modules/ipaddr.js/lib/ipaddr.js
|
|
52
52
|
var require_ipaddr = __commonJS({
|
|
53
|
-
"node_modules/ipaddr.js/lib/ipaddr.js"(exports$1, module) {
|
|
53
|
+
"../../../node_modules/ipaddr.js/lib/ipaddr.js"(exports$1, module) {
|
|
54
54
|
(function(root) {
|
|
55
55
|
const ipv4Part = "(0?\\d+|0x[a-f0-9]+)";
|
|
56
56
|
const ipv4Regexes = {
|
|
@@ -1388,7 +1388,6 @@ async function launchChrome(opts = {}) {
|
|
|
1388
1388
|
const spawnChrome = () => {
|
|
1389
1389
|
const args = [
|
|
1390
1390
|
`--remote-debugging-port=${String(cdpPort)}`,
|
|
1391
|
-
"--remote-debugging-address=127.0.0.1",
|
|
1392
1391
|
`--user-data-dir=${userDataDir}`,
|
|
1393
1392
|
"--no-first-run",
|
|
1394
1393
|
"--no-default-browser-check",
|
|
@@ -1407,9 +1406,6 @@ async function launchChrome(opts = {}) {
|
|
|
1407
1406
|
if (opts.noSandbox === true) {
|
|
1408
1407
|
args.push("--no-sandbox", "--disable-setuid-sandbox");
|
|
1409
1408
|
}
|
|
1410
|
-
if (opts.ignoreHTTPSErrors === true) {
|
|
1411
|
-
args.push("--ignore-certificate-errors");
|
|
1412
|
-
}
|
|
1413
1409
|
if (process.platform === "linux") args.push("--disable-dev-shm-usage");
|
|
1414
1410
|
const extraArgs = Array.isArray(opts.chromeArgs) ? opts.chromeArgs.filter((a) => typeof a === "string" && a.trim().length > 0) : [];
|
|
1415
1411
|
if (extraArgs.length) args.push(...extraArgs);
|
|
@@ -1730,15 +1726,7 @@ function appendCdpPath2(cdpUrl, cdpPath) {
|
|
|
1730
1726
|
}
|
|
1731
1727
|
}
|
|
1732
1728
|
async function withPlaywrightPageCdpSession(page, fn) {
|
|
1733
|
-
const
|
|
1734
|
-
const session = await Promise.race([
|
|
1735
|
-
page.context().newCDPSession(page),
|
|
1736
|
-
new Promise((_, reject) => {
|
|
1737
|
-
setTimeout(() => {
|
|
1738
|
-
reject(new Error("newCDPSession timed out after 10s"));
|
|
1739
|
-
}, CDP_SESSION_TIMEOUT_MS);
|
|
1740
|
-
})
|
|
1741
|
-
]);
|
|
1729
|
+
const session = await page.context().newCDPSession(page);
|
|
1742
1730
|
try {
|
|
1743
1731
|
return await fn(session);
|
|
1744
1732
|
} finally {
|
|
@@ -2378,14 +2366,7 @@ function toAIFriendlyError(error, selector) {
|
|
|
2378
2366
|
`Element "${selector}" is not interactable (hidden or covered). Try scrolling it into view, closing overlays, or re-snapshotting.`
|
|
2379
2367
|
);
|
|
2380
2368
|
}
|
|
2381
|
-
|
|
2382
|
-
if (timeoutMatch) {
|
|
2383
|
-
return new Error(
|
|
2384
|
-
`Element "${selector}" timed out after ${timeoutMatch[1]}ms \u2014 element may be hidden or not interactable. Run a new snapshot to see current page elements.`
|
|
2385
|
-
);
|
|
2386
|
-
}
|
|
2387
|
-
const cleaned = message.replace(/locator\([^)]*\)\./g, "").replace(/waiting for locator\([^)]*\)/g, "").trim();
|
|
2388
|
-
return new Error(cleaned || message);
|
|
2369
|
+
return error instanceof Error ? error : new Error(message);
|
|
2389
2370
|
}
|
|
2390
2371
|
function normalizeTimeoutMs(timeoutMs, fallback, maxMs = 12e4) {
|
|
2391
2372
|
return Math.max(500, Math.min(maxMs, timeoutMs ?? fallback));
|
|
@@ -3083,19 +3064,7 @@ function requiresInspectableBrowserNavigationRedirects(ssrfPolicy) {
|
|
|
3083
3064
|
|
|
3084
3065
|
// src/actions/interaction.ts
|
|
3085
3066
|
var MAX_CLICK_DELAY_MS = 5e3;
|
|
3086
|
-
var
|
|
3087
|
-
var CHECKABLE_ROLES = /* @__PURE__ */ new Set(["menuitemcheckbox", "menuitemradio", "checkbox", "radio", "switch"]);
|
|
3088
|
-
async function setCheckedViaEvaluate(locator, checked) {
|
|
3089
|
-
await locator.evaluate((el, desired) => {
|
|
3090
|
-
const input = el;
|
|
3091
|
-
const desc = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "checked");
|
|
3092
|
-
if (desc?.set) desc.set.call(input, desired);
|
|
3093
|
-
else input.checked = desired;
|
|
3094
|
-
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3095
|
-
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
3096
|
-
input.click();
|
|
3097
|
-
}, checked);
|
|
3098
|
-
}
|
|
3067
|
+
var CHECKABLE_ROLES = /* @__PURE__ */ new Set(["menuitemcheckbox", "menuitemradio", "checkbox", "switch"]);
|
|
3099
3068
|
function resolveLocator(page, resolved) {
|
|
3100
3069
|
if (resolved.ref !== void 0 && resolved.ref !== "") return refLocator(page, resolved.ref);
|
|
3101
3070
|
const sel = resolved.selector ?? "";
|
|
@@ -3109,29 +3078,11 @@ async function mouseClickViaPlaywright(opts) {
|
|
|
3109
3078
|
delay: opts.delayMs
|
|
3110
3079
|
});
|
|
3111
3080
|
}
|
|
3112
|
-
async function pressAndHoldViaCdp(opts) {
|
|
3113
|
-
const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
|
|
3114
|
-
ensurePageState(page);
|
|
3115
|
-
const { x, y } = opts;
|
|
3116
|
-
await withPageScopedCdpClient({
|
|
3117
|
-
cdpUrl: opts.cdpUrl,
|
|
3118
|
-
page,
|
|
3119
|
-
targetId: opts.targetId,
|
|
3120
|
-
fn: async (send) => {
|
|
3121
|
-
await send("Input.dispatchMouseEvent", { type: "mouseMoved", x, y, button: "none" });
|
|
3122
|
-
if (opts.delay !== void 0 && opts.delay !== 0) await new Promise((r) => setTimeout(r, opts.delay));
|
|
3123
|
-
await send("Input.dispatchMouseEvent", { type: "mousePressed", x, y, button: "left", clickCount: 1 });
|
|
3124
|
-
if (opts.holdMs !== void 0 && opts.holdMs !== 0) await new Promise((r) => setTimeout(r, opts.holdMs));
|
|
3125
|
-
await send("Input.dispatchMouseEvent", { type: "mouseReleased", x, y, button: "left", clickCount: 1 });
|
|
3126
|
-
}
|
|
3127
|
-
});
|
|
3128
|
-
}
|
|
3129
3081
|
async function clickByTextViaPlaywright(opts) {
|
|
3130
3082
|
const page = await getRestoredPageForTarget(opts);
|
|
3131
3083
|
const timeout = resolveInteractionTimeoutMs(opts.timeoutMs);
|
|
3132
|
-
const locator = page.getByText(opts.text, { exact: opts.exact }).and(page.locator(":visible")).or(page.getByTitle(opts.text, { exact: opts.exact })).first();
|
|
3133
3084
|
try {
|
|
3134
|
-
await
|
|
3085
|
+
await page.getByText(opts.text, { exact: opts.exact }).click({ timeout, button: opts.button, modifiers: opts.modifiers });
|
|
3135
3086
|
} catch (err) {
|
|
3136
3087
|
throw toAIFriendlyError(err, `text="${opts.text}"`);
|
|
3137
3088
|
}
|
|
@@ -3139,12 +3090,13 @@ async function clickByTextViaPlaywright(opts) {
|
|
|
3139
3090
|
async function clickByRoleViaPlaywright(opts) {
|
|
3140
3091
|
const page = await getRestoredPageForTarget(opts);
|
|
3141
3092
|
const timeout = resolveInteractionTimeoutMs(opts.timeoutMs);
|
|
3142
|
-
const label = `role=${opts.role}${opts.name !== void 0 && opts.name !== "" ? ` name="${opts.name}"` : ""}`;
|
|
3143
|
-
const locator = page.getByRole(opts.role, { name: opts.name }).nth(opts.index ?? 0);
|
|
3144
3093
|
try {
|
|
3145
|
-
await
|
|
3094
|
+
await page.getByRole(opts.role, { name: opts.name }).click({ timeout, button: opts.button, modifiers: opts.modifiers });
|
|
3146
3095
|
} catch (err) {
|
|
3147
|
-
throw toAIFriendlyError(
|
|
3096
|
+
throw toAIFriendlyError(
|
|
3097
|
+
err,
|
|
3098
|
+
`role=${opts.role}${opts.name !== void 0 && opts.name !== "" ? ` name="${opts.name}"` : ""}`
|
|
3099
|
+
);
|
|
3148
3100
|
}
|
|
3149
3101
|
}
|
|
3150
3102
|
async function clickViaPlaywright(opts) {
|
|
@@ -3165,7 +3117,7 @@ async function clickViaPlaywright(opts) {
|
|
|
3165
3117
|
try {
|
|
3166
3118
|
const delayMs = resolveBoundedDelayMs(opts.delayMs, "click delayMs", MAX_CLICK_DELAY_MS);
|
|
3167
3119
|
if (delayMs > 0) {
|
|
3168
|
-
await locator.hover({ timeout
|
|
3120
|
+
await locator.hover({ timeout });
|
|
3169
3121
|
await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
3170
3122
|
}
|
|
3171
3123
|
let ariaCheckedBefore;
|
|
@@ -3173,9 +3125,9 @@ async function clickViaPlaywright(opts) {
|
|
|
3173
3125
|
ariaCheckedBefore = await locator.getAttribute("aria-checked", { timeout }).catch(() => void 0);
|
|
3174
3126
|
}
|
|
3175
3127
|
if (opts.doubleClick === true) {
|
|
3176
|
-
await locator.dblclick({ timeout, button: opts.button, modifiers: opts.modifiers
|
|
3128
|
+
await locator.dblclick({ timeout, button: opts.button, modifiers: opts.modifiers });
|
|
3177
3129
|
} else {
|
|
3178
|
-
await locator.click({ timeout, button: opts.button, modifiers: opts.modifiers
|
|
3130
|
+
await locator.click({ timeout, button: opts.button, modifiers: opts.modifiers });
|
|
3179
3131
|
}
|
|
3180
3132
|
if (checkableRole && opts.doubleClick !== true && ariaCheckedBefore !== void 0) {
|
|
3181
3133
|
const POLL_INTERVAL_MS = 50;
|
|
@@ -3269,13 +3221,9 @@ async function fillFormViaPlaywright(opts) {
|
|
|
3269
3221
|
if (type === "checkbox" || type === "radio") {
|
|
3270
3222
|
const checked = rawValue === true || rawValue === 1 || rawValue === "1" || rawValue === "true";
|
|
3271
3223
|
try {
|
|
3272
|
-
await locator.setChecked(checked, { timeout
|
|
3273
|
-
} catch {
|
|
3274
|
-
|
|
3275
|
-
await setCheckedViaEvaluate(locator, checked);
|
|
3276
|
-
} catch (err) {
|
|
3277
|
-
throw toAIFriendlyError(err, ref);
|
|
3278
|
-
}
|
|
3224
|
+
await locator.setChecked(checked, { timeout });
|
|
3225
|
+
} catch (err) {
|
|
3226
|
+
throw toAIFriendlyError(err, ref);
|
|
3279
3227
|
}
|
|
3280
3228
|
continue;
|
|
3281
3229
|
}
|
|
@@ -3292,13 +3240,7 @@ async function scrollIntoViewViaPlaywright(opts) {
|
|
|
3292
3240
|
const label = resolved.ref ?? resolved.selector ?? "";
|
|
3293
3241
|
const locator = resolveLocator(page, resolved);
|
|
3294
3242
|
try {
|
|
3295
|
-
await locator.
|
|
3296
|
-
state: "attached",
|
|
3297
|
-
timeout: normalizeTimeoutMs(opts.timeoutMs, DEFAULT_SCROLL_TIMEOUT_MS)
|
|
3298
|
-
});
|
|
3299
|
-
await locator.evaluate((el) => {
|
|
3300
|
-
el.scrollIntoView({ block: "center", behavior: "instant" });
|
|
3301
|
-
});
|
|
3243
|
+
await locator.scrollIntoViewIfNeeded({ timeout: normalizeTimeoutMs(opts.timeoutMs, 2e4) });
|
|
3302
3244
|
} catch (err) {
|
|
3303
3245
|
throw toAIFriendlyError(err, label);
|
|
3304
3246
|
}
|
|
@@ -3506,12 +3448,7 @@ async function closePageViaPlaywright(opts) {
|
|
|
3506
3448
|
await page.close();
|
|
3507
3449
|
}
|
|
3508
3450
|
async function closePageByTargetIdViaPlaywright(opts) {
|
|
3509
|
-
|
|
3510
|
-
await (await resolvePageByTargetIdOrThrow(opts)).close();
|
|
3511
|
-
} catch (err) {
|
|
3512
|
-
if (err instanceof BrowserTabNotFoundError) return;
|
|
3513
|
-
throw err;
|
|
3514
|
-
}
|
|
3451
|
+
await (await resolvePageByTargetIdOrThrow(opts)).close();
|
|
3515
3452
|
}
|
|
3516
3453
|
async function focusPageByTargetIdViaPlaywright(opts) {
|
|
3517
3454
|
const page = await resolvePageByTargetIdOrThrow(opts);
|
|
@@ -3533,27 +3470,6 @@ async function focusPageByTargetIdViaPlaywright(opts) {
|
|
|
3533
3470
|
}
|
|
3534
3471
|
}
|
|
3535
3472
|
}
|
|
3536
|
-
async function waitForTabViaPlaywright(opts) {
|
|
3537
|
-
if (opts.urlContains === void 0 && opts.titleContains === void 0)
|
|
3538
|
-
throw new Error("urlContains or titleContains is required");
|
|
3539
|
-
const timeout = Math.max(1e3, Math.min(12e4, opts.timeoutMs ?? 3e4));
|
|
3540
|
-
const start = Date.now();
|
|
3541
|
-
const POLL_INTERVAL_MS = 250;
|
|
3542
|
-
while (Date.now() - start < timeout) {
|
|
3543
|
-
const tabs = await listPagesViaPlaywright({ cdpUrl: opts.cdpUrl });
|
|
3544
|
-
const match = tabs.find((t) => {
|
|
3545
|
-
if (opts.urlContains !== void 0 && !t.url.includes(opts.urlContains)) return false;
|
|
3546
|
-
if (opts.titleContains !== void 0 && !t.title.includes(opts.titleContains)) return false;
|
|
3547
|
-
return true;
|
|
3548
|
-
});
|
|
3549
|
-
if (match) return match;
|
|
3550
|
-
await new Promise((resolve2) => setTimeout(resolve2, POLL_INTERVAL_MS));
|
|
3551
|
-
}
|
|
3552
|
-
const criteria = [];
|
|
3553
|
-
if (opts.urlContains !== void 0) criteria.push(`url contains "${opts.urlContains}"`);
|
|
3554
|
-
if (opts.titleContains !== void 0) criteria.push(`title contains "${opts.titleContains}"`);
|
|
3555
|
-
throw new Error(`Timed out waiting for tab: ${criteria.join(", ")}`);
|
|
3556
|
-
}
|
|
3557
3473
|
async function resizeViewportViaPlaywright(opts) {
|
|
3558
3474
|
const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
|
|
3559
3475
|
ensurePageState(page);
|
|
@@ -3595,13 +3511,9 @@ async function waitForViaPlaywright(opts) {
|
|
|
3595
3511
|
if (opts.loadState !== void 0) {
|
|
3596
3512
|
await page.waitForLoadState(opts.loadState, { timeout });
|
|
3597
3513
|
}
|
|
3598
|
-
if (opts.fn !== void 0) {
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
} else {
|
|
3602
|
-
const fn = opts.fn.trim();
|
|
3603
|
-
if (fn !== "") await page.waitForFunction(fn, opts.arg, { timeout });
|
|
3604
|
-
}
|
|
3514
|
+
if (opts.fn !== void 0 && opts.fn !== "") {
|
|
3515
|
+
const fn = opts.fn.trim();
|
|
3516
|
+
if (fn !== "") await page.waitForFunction(fn, void 0, { timeout });
|
|
3605
3517
|
}
|
|
3606
3518
|
}
|
|
3607
3519
|
|
|
@@ -3713,7 +3625,6 @@ async function executeSingleAction(action, cdpUrl, targetId, evaluateEnabled, de
|
|
|
3713
3625
|
url: action.url,
|
|
3714
3626
|
loadState: action.loadState,
|
|
3715
3627
|
fn: action.fn,
|
|
3716
|
-
arg: action.arg,
|
|
3717
3628
|
timeoutMs: action.timeoutMs
|
|
3718
3629
|
});
|
|
3719
3630
|
break;
|
|
@@ -4189,40 +4100,6 @@ async function responseBodyViaPlaywright(opts) {
|
|
|
4189
4100
|
truncated
|
|
4190
4101
|
};
|
|
4191
4102
|
}
|
|
4192
|
-
async function waitForRequestViaPlaywright(opts) {
|
|
4193
|
-
const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
|
|
4194
|
-
ensurePageState(page);
|
|
4195
|
-
const timeout = normalizeTimeoutMs(opts.timeoutMs, 3e4, 12e4);
|
|
4196
|
-
const pattern = opts.url.trim();
|
|
4197
|
-
if (!pattern) throw new Error("url is required");
|
|
4198
|
-
const upperMethod = opts.method !== void 0 ? opts.method.toUpperCase() : void 0;
|
|
4199
|
-
const response = await page.waitForResponse(
|
|
4200
|
-
(resp) => matchUrlPattern(pattern, resp.url()) && (upperMethod === void 0 || resp.request().method() === upperMethod),
|
|
4201
|
-
{ timeout }
|
|
4202
|
-
);
|
|
4203
|
-
const request = response.request();
|
|
4204
|
-
let responseBody;
|
|
4205
|
-
let truncated = false;
|
|
4206
|
-
try {
|
|
4207
|
-
responseBody = await response.text();
|
|
4208
|
-
const maxChars = typeof opts.maxChars === "number" && Number.isFinite(opts.maxChars) ? Math.max(1, Math.min(5e6, Math.floor(opts.maxChars))) : 2e5;
|
|
4209
|
-
if (responseBody.length > maxChars) {
|
|
4210
|
-
responseBody = responseBody.slice(0, maxChars);
|
|
4211
|
-
truncated = true;
|
|
4212
|
-
}
|
|
4213
|
-
} catch (err) {
|
|
4214
|
-
console.warn("[browserclaw] response body unavailable:", err instanceof Error ? err.message : String(err));
|
|
4215
|
-
}
|
|
4216
|
-
return {
|
|
4217
|
-
url: response.url(),
|
|
4218
|
-
method: request.method(),
|
|
4219
|
-
postData: request.postData() ?? void 0,
|
|
4220
|
-
status: response.status(),
|
|
4221
|
-
ok: response.ok(),
|
|
4222
|
-
responseBody,
|
|
4223
|
-
truncated
|
|
4224
|
-
};
|
|
4225
|
-
}
|
|
4226
4103
|
|
|
4227
4104
|
// src/capture/screenshot.ts
|
|
4228
4105
|
async function takeScreenshotViaPlaywright(opts) {
|
|
@@ -4346,13 +4223,6 @@ async function traceStopViaPlaywright(opts) {
|
|
|
4346
4223
|
}
|
|
4347
4224
|
|
|
4348
4225
|
// src/snapshot/ref-map.ts
|
|
4349
|
-
function parseStateFromSuffix(suffix) {
|
|
4350
|
-
const state = {};
|
|
4351
|
-
if (/\[disabled\]/i.test(suffix)) state.disabled = true;
|
|
4352
|
-
if (/\[checked\s*=\s*"?mixed"?\]/i.test(suffix)) state.checked = "mixed";
|
|
4353
|
-
else if (/\[checked\]/i.test(suffix)) state.checked = true;
|
|
4354
|
-
return state;
|
|
4355
|
-
}
|
|
4356
4226
|
var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
|
|
4357
4227
|
"button",
|
|
4358
4228
|
"link",
|
|
@@ -4511,8 +4381,7 @@ function buildRoleSnapshotFromAriaSnapshot(ariaSnapshot, options = {}) {
|
|
|
4511
4381
|
const ref = nextRef();
|
|
4512
4382
|
const nth = tracker.getNextIndex(role, name);
|
|
4513
4383
|
tracker.trackRef(role, name, ref);
|
|
4514
|
-
|
|
4515
|
-
refs[ref] = { role, name, nth, ...state };
|
|
4384
|
+
refs[ref] = { role, name, nth };
|
|
4516
4385
|
let enhanced = `${prefix}${roleRaw}`;
|
|
4517
4386
|
if (name !== void 0 && name !== "") enhanced += ` "${name}"`;
|
|
4518
4387
|
enhanced += ` [ref=${ref}]`;
|
|
@@ -4549,8 +4418,7 @@ function buildRoleSnapshotFromAriaSnapshot(ariaSnapshot, options = {}) {
|
|
|
4549
4418
|
const ref = nextRef();
|
|
4550
4419
|
const nth = tracker.getNextIndex(role, name);
|
|
4551
4420
|
tracker.trackRef(role, name, ref);
|
|
4552
|
-
|
|
4553
|
-
refs[ref] = { role, name, nth, ...state };
|
|
4421
|
+
refs[ref] = { role, name, nth };
|
|
4554
4422
|
let enhanced = `${prefix}${roleRaw}`;
|
|
4555
4423
|
if (name !== "") enhanced += ` "${name}"`;
|
|
4556
4424
|
enhanced += ` [ref=${ref}]`;
|
|
@@ -4588,13 +4456,12 @@ function buildRoleSnapshotFromAiSnapshot(aiSnapshot, options = {}) {
|
|
|
4588
4456
|
if (!INTERACTIVE_ROLES.has(role)) continue;
|
|
4589
4457
|
const ref = parseAiSnapshotRef(suffix);
|
|
4590
4458
|
const prefix = /^(\s*-\s*)/.exec(line)?.[1] ?? "";
|
|
4591
|
-
const state = parseStateFromSuffix(suffix);
|
|
4592
4459
|
if (ref !== null) {
|
|
4593
|
-
refs[ref] = { role, ...name !== void 0 && name !== "" ? { name } : {}
|
|
4460
|
+
refs[ref] = { role, ...name !== void 0 && name !== "" ? { name } : {} };
|
|
4594
4461
|
out2.push(`${prefix}${roleRaw}${name !== void 0 && name !== "" ? ` "${name}"` : ""}${suffix}`);
|
|
4595
4462
|
} else {
|
|
4596
4463
|
const generatedRef = nextInteractiveRef();
|
|
4597
|
-
refs[generatedRef] = { role, ...name !== void 0 && name !== "" ? { name } : {}
|
|
4464
|
+
refs[generatedRef] = { role, ...name !== void 0 && name !== "" ? { name } : {} };
|
|
4598
4465
|
let enhanced = `${prefix}${roleRaw}`;
|
|
4599
4466
|
if (name !== void 0 && name !== "") enhanced += ` "${name}"`;
|
|
4600
4467
|
enhanced += ` [ref=${generatedRef}]`;
|
|
@@ -4632,13 +4499,12 @@ function buildRoleSnapshotFromAiSnapshot(aiSnapshot, options = {}) {
|
|
|
4632
4499
|
const isStructural = STRUCTURAL_ROLES.has(role);
|
|
4633
4500
|
if (options.compact === true && isStructural && name === "") continue;
|
|
4634
4501
|
const ref = parseAiSnapshotRef(suffix);
|
|
4635
|
-
const state = parseStateFromSuffix(suffix);
|
|
4636
4502
|
if (ref !== null) {
|
|
4637
|
-
refs[ref] = { role, ...name !== "" ? { name } : {}
|
|
4503
|
+
refs[ref] = { role, ...name !== "" ? { name } : {} };
|
|
4638
4504
|
out.push(line);
|
|
4639
4505
|
} else if (INTERACTIVE_ROLES.has(role)) {
|
|
4640
4506
|
const generatedRef = nextGeneratedRef();
|
|
4641
|
-
refs[generatedRef] = { role, ...name !== "" ? { name } : {}
|
|
4507
|
+
refs[generatedRef] = { role, ...name !== "" ? { name } : {} };
|
|
4642
4508
|
let enhanced = `${prefix}${roleRaw}`;
|
|
4643
4509
|
if (name !== "") enhanced += ` "${name}"`;
|
|
4644
4510
|
enhanced += ` [ref=${generatedRef}]`;
|
|
@@ -5004,8 +4870,7 @@ var CrawlPage = class {
|
|
|
5004
4870
|
button: opts?.button,
|
|
5005
4871
|
modifiers: opts?.modifiers,
|
|
5006
4872
|
delayMs: opts?.delayMs,
|
|
5007
|
-
timeoutMs: opts?.timeoutMs
|
|
5008
|
-
force: opts?.force
|
|
4873
|
+
timeoutMs: opts?.timeoutMs
|
|
5009
4874
|
});
|
|
5010
4875
|
}
|
|
5011
4876
|
/**
|
|
@@ -5031,8 +4896,7 @@ var CrawlPage = class {
|
|
|
5031
4896
|
button: opts?.button,
|
|
5032
4897
|
modifiers: opts?.modifiers,
|
|
5033
4898
|
delayMs: opts?.delayMs,
|
|
5034
|
-
timeoutMs: opts?.timeoutMs
|
|
5035
|
-
force: opts?.force
|
|
4899
|
+
timeoutMs: opts?.timeoutMs
|
|
5036
4900
|
});
|
|
5037
4901
|
}
|
|
5038
4902
|
/**
|
|
@@ -5062,32 +4926,6 @@ var CrawlPage = class {
|
|
|
5062
4926
|
delayMs: opts?.delayMs
|
|
5063
4927
|
});
|
|
5064
4928
|
}
|
|
5065
|
-
/**
|
|
5066
|
-
* Press and hold at page coordinates using raw CDP events.
|
|
5067
|
-
*
|
|
5068
|
-
* Bypasses Playwright's automation layer by dispatching CDP
|
|
5069
|
-
* `Input.dispatchMouseEvent` directly — useful for anti-bot challenges
|
|
5070
|
-
* that detect automated clicks.
|
|
5071
|
-
*
|
|
5072
|
-
* @param x - X coordinate in CSS pixels
|
|
5073
|
-
* @param y - Y coordinate in CSS pixels
|
|
5074
|
-
* @param opts - Options (delay: ms before press, holdMs: hold duration)
|
|
5075
|
-
*
|
|
5076
|
-
* @example
|
|
5077
|
-
* ```ts
|
|
5078
|
-
* await page.pressAndHold(400, 300, { delay: 150, holdMs: 5000 });
|
|
5079
|
-
* ```
|
|
5080
|
-
*/
|
|
5081
|
-
async pressAndHold(x, y, opts) {
|
|
5082
|
-
return pressAndHoldViaCdp({
|
|
5083
|
-
cdpUrl: this.cdpUrl,
|
|
5084
|
-
targetId: this.targetId,
|
|
5085
|
-
x,
|
|
5086
|
-
y,
|
|
5087
|
-
delay: opts?.delay,
|
|
5088
|
-
holdMs: opts?.holdMs
|
|
5089
|
-
});
|
|
5090
|
-
}
|
|
5091
4929
|
/**
|
|
5092
4930
|
* Click an element by its visible text content (no snapshot/ref needed).
|
|
5093
4931
|
*
|
|
@@ -5135,7 +4973,6 @@ var CrawlPage = class {
|
|
|
5135
4973
|
targetId: this.targetId,
|
|
5136
4974
|
role,
|
|
5137
4975
|
name,
|
|
5138
|
-
index: opts?.index,
|
|
5139
4976
|
button: opts?.button,
|
|
5140
4977
|
modifiers: opts?.modifiers,
|
|
5141
4978
|
timeoutMs: opts?.timeoutMs
|
|
@@ -5659,35 +5496,6 @@ var CrawlPage = class {
|
|
|
5659
5496
|
maxChars: opts?.maxChars
|
|
5660
5497
|
});
|
|
5661
5498
|
}
|
|
5662
|
-
/**
|
|
5663
|
-
* Wait for a network request matching a URL pattern and return request + response details.
|
|
5664
|
-
*
|
|
5665
|
-
* Unlike `networkRequests()` which only captures metadata, this method captures
|
|
5666
|
-
* the full request body (POST data) and response body.
|
|
5667
|
-
*
|
|
5668
|
-
* @param url - URL string or pattern to match (supports `*` wildcards and substring matching)
|
|
5669
|
-
* @param opts - Options (method filter, timeoutMs, maxChars for response body)
|
|
5670
|
-
* @returns Request method, postData, response status, and response body
|
|
5671
|
-
*
|
|
5672
|
-
* @example
|
|
5673
|
-
* ```ts
|
|
5674
|
-
* const reqPromise = page.waitForRequest('/api/submit', { method: 'POST' });
|
|
5675
|
-
* await page.click('e5'); // submit a form
|
|
5676
|
-
* const req = await reqPromise;
|
|
5677
|
-
* console.log(req.postData); // form body
|
|
5678
|
-
* console.log(req.status, req.responseBody); // response
|
|
5679
|
-
* ```
|
|
5680
|
-
*/
|
|
5681
|
-
async waitForRequest(url, opts) {
|
|
5682
|
-
return waitForRequestViaPlaywright({
|
|
5683
|
-
cdpUrl: this.cdpUrl,
|
|
5684
|
-
targetId: this.targetId,
|
|
5685
|
-
url,
|
|
5686
|
-
method: opts?.method,
|
|
5687
|
-
timeoutMs: opts?.timeoutMs,
|
|
5688
|
-
maxChars: opts?.maxChars
|
|
5689
|
-
});
|
|
5690
|
-
}
|
|
5691
5499
|
/**
|
|
5692
5500
|
* Get console messages captured from the page.
|
|
5693
5501
|
*
|
|
@@ -6210,31 +6018,6 @@ var BrowserClaw = class _BrowserClaw {
|
|
|
6210
6018
|
async tabs() {
|
|
6211
6019
|
return listPagesViaPlaywright({ cdpUrl: this.cdpUrl });
|
|
6212
6020
|
}
|
|
6213
|
-
/**
|
|
6214
|
-
* Wait for a tab matching the given criteria and return a page handle.
|
|
6215
|
-
*
|
|
6216
|
-
* Polls open tabs until one matches, then focuses it and returns a CrawlPage.
|
|
6217
|
-
*
|
|
6218
|
-
* @param opts - Match criteria (urlContains, titleContains) and timeout
|
|
6219
|
-
* @returns A CrawlPage for the matched tab
|
|
6220
|
-
*
|
|
6221
|
-
* @example
|
|
6222
|
-
* ```ts
|
|
6223
|
-
* await page.click('e5'); // opens a new tab
|
|
6224
|
-
* const appPage = await browser.waitForTab({ urlContains: 'app-web' });
|
|
6225
|
-
* const { snapshot } = await appPage.snapshot();
|
|
6226
|
-
* ```
|
|
6227
|
-
*/
|
|
6228
|
-
async waitForTab(opts) {
|
|
6229
|
-
const tab = await waitForTabViaPlaywright({
|
|
6230
|
-
cdpUrl: this.cdpUrl,
|
|
6231
|
-
urlContains: opts.urlContains,
|
|
6232
|
-
titleContains: opts.titleContains,
|
|
6233
|
-
timeoutMs: opts.timeoutMs
|
|
6234
|
-
});
|
|
6235
|
-
await focusPageByTargetIdViaPlaywright({ cdpUrl: this.cdpUrl, targetId: tab.targetId });
|
|
6236
|
-
return new CrawlPage(this.cdpUrl, tab.targetId, this.ssrfPolicy);
|
|
6237
|
-
}
|
|
6238
6021
|
/**
|
|
6239
6022
|
* Bring a tab to the foreground.
|
|
6240
6023
|
*
|
|
@@ -6304,7 +6087,6 @@ exports.isChromeCdpReady = isChromeCdpReady;
|
|
|
6304
6087
|
exports.isChromeReachable = isChromeReachable;
|
|
6305
6088
|
exports.normalizeCdpHttpBaseForJsonEndpoints = normalizeCdpHttpBaseForJsonEndpoints;
|
|
6306
6089
|
exports.parseRoleRef = parseRoleRef;
|
|
6307
|
-
exports.pressAndHoldViaCdp = pressAndHoldViaCdp;
|
|
6308
6090
|
exports.requireRef = requireRef;
|
|
6309
6091
|
exports.requireRefOrSelector = requireRefOrSelector;
|
|
6310
6092
|
exports.requiresInspectableBrowserNavigationRedirects = requiresInspectableBrowserNavigationRedirects;
|