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/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 CDP_SESSION_TIMEOUT_MS = 1e4;
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
- const timeoutMatch = /Timeout (\d+)ms exceeded/.exec(message);
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 DEFAULT_SCROLL_TIMEOUT_MS = 2e4;
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 locator.click({ timeout, button: opts.button, modifiers: opts.modifiers });
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 locator.click({ timeout, button: opts.button, modifiers: opts.modifiers });
3094
+ await page.getByRole(opts.role, { name: opts.name }).click({ timeout, button: opts.button, modifiers: opts.modifiers });
3146
3095
  } catch (err) {
3147
- throw toAIFriendlyError(err, label);
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, force: opts.force });
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, force: opts.force });
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, force: opts.force });
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, force: true });
3273
- } catch {
3274
- try {
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.waitFor({
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
- try {
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
- if (typeof opts.fn === "function") {
3600
- await page.waitForFunction(opts.fn, opts.arg, { timeout });
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
- const state = parseStateFromSuffix(suffix);
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
- const state = parseStateFromSuffix(suffix);
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 } : {}, ...state };
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 } : {}, ...state };
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 } : {}, ...state };
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 } : {}, ...state };
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;