browserclaw 0.3.3 → 0.3.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
@@ -751,12 +751,13 @@ async function getPageForTargetId(opts) {
751
751
  const found = await findPageByTargetId(browser, opts.targetId, opts.cdpUrl);
752
752
  if (!found) {
753
753
  if (pages.length === 1) return first;
754
- throw new Error("tab not found");
754
+ throw new Error(`Tab not found (targetId: ${opts.targetId}). Call browser.tabs() to list open tabs.`);
755
755
  }
756
756
  return found;
757
757
  }
758
758
  function refLocator(page, ref) {
759
759
  const normalized = ref.startsWith("@") ? ref.slice(1) : ref.startsWith("ref=") ? ref.slice(4) : ref;
760
+ if (!normalized.trim()) throw new Error("ref is required");
760
761
  if (/^e\d+$/.test(normalized)) {
761
762
  const state = pageStates.get(page);
762
763
  if (state?.roleRefsMode === "aria") {
@@ -1105,7 +1106,7 @@ async function snapshotRole(opts) {
1105
1106
  const frameSelector = opts.frameSelector?.trim() || "";
1106
1107
  const selector = opts.selector?.trim() || "";
1107
1108
  const locator = frameSelector ? selector ? page.frameLocator(frameSelector).locator(selector) : page.frameLocator(frameSelector).locator(":root") : selector ? page.locator(selector) : page.locator(":root");
1108
- const ariaSnapshot = await locator.ariaSnapshot({ timeout: 1e4 });
1109
+ const ariaSnapshot = await locator.ariaSnapshot({ timeout: normalizeTimeoutMs(opts.timeoutMs, 5e3) });
1109
1110
  const built = buildRoleSnapshotFromAriaSnapshot(String(ariaSnapshot ?? ""), opts.options);
1110
1111
  storeRoleRefsForTarget({
1111
1112
  page,
@@ -1411,7 +1412,7 @@ async function assertBrowserNavigationAllowed(opts) {
1411
1412
  throw new InvalidBrowserNavigationUrlError(`Navigation blocked: unsupported protocol "${parsed.protocol}"`);
1412
1413
  }
1413
1414
  const policy = opts.ssrfPolicy;
1414
- if (policy?.allowPrivateNetwork) return;
1415
+ if (policy?.dangerouslyAllowPrivateNetwork ?? policy?.allowPrivateNetwork ?? true) return;
1415
1416
  const allowedHostnames = [
1416
1417
  ...policy?.allowedHostnames ?? [],
1417
1418
  ...policy?.hostnameAllowlist ?? []
@@ -1422,7 +1423,7 @@ async function assertBrowserNavigationAllowed(opts) {
1422
1423
  }
1423
1424
  if (await isInternalUrlResolved(rawUrl, opts.lookupFn)) {
1424
1425
  throw new InvalidBrowserNavigationUrlError(
1425
- `Navigation to internal/loopback address blocked: "${rawUrl}". Use ssrfPolicy: { allowPrivateNetwork: true } if this is intentional.`
1426
+ `Navigation to internal/loopback address blocked: "${rawUrl}". ssrfPolicy.dangerouslyAllowPrivateNetwork is false (strict mode).`
1426
1427
  );
1427
1428
  }
1428
1429
  }
@@ -1569,7 +1570,7 @@ async function isInternalUrlResolved(url, lookupFn = promises.lookup) {
1569
1570
  async function navigateViaPlaywright(opts) {
1570
1571
  const url = String(opts.url ?? "").trim();
1571
1572
  if (!url) throw new Error("url is required");
1572
- const policy = opts.allowInternal ? { ...opts.ssrfPolicy, allowPrivateNetwork: true } : opts.ssrfPolicy;
1573
+ const policy = opts.allowInternal ? { ...opts.ssrfPolicy, dangerouslyAllowPrivateNetwork: true } : opts.ssrfPolicy;
1573
1574
  await assertBrowserNavigationAllowed({ url, ssrfPolicy: policy });
1574
1575
  const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
1575
1576
  ensurePageState(page);
@@ -1594,7 +1595,7 @@ async function listPagesViaPlaywright(opts) {
1594
1595
  async function createPageViaPlaywright(opts) {
1595
1596
  const targetUrl = (opts.url ?? "").trim() || "about:blank";
1596
1597
  if (targetUrl !== "about:blank") {
1597
- const policy = opts.allowInternal ? { ...opts.ssrfPolicy, allowPrivateNetwork: true } : opts.ssrfPolicy;
1598
+ const policy = opts.allowInternal ? { ...opts.ssrfPolicy, dangerouslyAllowPrivateNetwork: true } : opts.ssrfPolicy;
1598
1599
  await assertBrowserNavigationAllowed({ url: targetUrl, ssrfPolicy: policy });
1599
1600
  }
1600
1601
  const { browser } = await connectBrowser(opts.cdpUrl);
@@ -1834,7 +1835,7 @@ async function setGeolocationViaPlaywright(opts) {
1834
1835
  return;
1835
1836
  }
1836
1837
  if (opts.latitude === void 0 || opts.longitude === void 0) {
1837
- throw new Error("latitude and longitude are required when not clearing geolocation.");
1838
+ throw new Error("latitude and longitude are required (or set clear=true)");
1838
1839
  }
1839
1840
  await context.grantPermissions(["geolocation"], opts.origin ? { origin: opts.origin } : void 0);
1840
1841
  await context.setGeolocation({
@@ -1981,8 +1982,9 @@ async function responseBodyViaPlaywright(opts) {
1981
1982
  const response = await page.waitForResponse(opts.url, { timeout });
1982
1983
  let body = await response.text();
1983
1984
  let truncated = false;
1984
- if (opts.maxChars && body.length > opts.maxChars) {
1985
- body = body.slice(0, opts.maxChars);
1985
+ const maxChars = typeof opts.maxChars === "number" && Number.isFinite(opts.maxChars) ? Math.max(1, Math.min(5e6, Math.floor(opts.maxChars))) : void 0;
1986
+ if (maxChars !== void 0 && body.length > maxChars) {
1987
+ body = body.slice(0, maxChars);
1986
1988
  truncated = true;
1987
1989
  }
1988
1990
  const headers = {};
@@ -2153,6 +2155,7 @@ var CrawlPage = class {
2153
2155
  selector: opts.selector,
2154
2156
  frameSelector: opts.frameSelector,
2155
2157
  refsMode: opts.refsMode,
2158
+ timeoutMs: opts.timeoutMs,
2156
2159
  options: {
2157
2160
  interactive: opts.interactive,
2158
2161
  compact: opts.compact,
@@ -3016,7 +3019,7 @@ var BrowserClaw = class _BrowserClaw {
3016
3019
  static async launch(opts = {}) {
3017
3020
  const chrome = await launchChrome(opts);
3018
3021
  const cdpUrl = `http://127.0.0.1:${chrome.cdpPort}`;
3019
- const ssrfPolicy = opts.allowInternal ? { ...opts.ssrfPolicy, allowPrivateNetwork: true } : opts.ssrfPolicy;
3022
+ const ssrfPolicy = opts.allowInternal ? { ...opts.ssrfPolicy, dangerouslyAllowPrivateNetwork: true } : opts.ssrfPolicy;
3020
3023
  return new _BrowserClaw(cdpUrl, chrome, ssrfPolicy);
3021
3024
  }
3022
3025
  /**
@@ -3038,7 +3041,7 @@ var BrowserClaw = class _BrowserClaw {
3038
3041
  throw new Error(`Cannot connect to Chrome at ${cdpUrl}. Is Chrome running with --remote-debugging-port?`);
3039
3042
  }
3040
3043
  await connectBrowser(cdpUrl, opts?.authToken);
3041
- const ssrfPolicy = opts?.allowInternal ? { ...opts.ssrfPolicy, allowPrivateNetwork: true } : opts?.ssrfPolicy;
3044
+ const ssrfPolicy = opts?.allowInternal ? { ...opts.ssrfPolicy, dangerouslyAllowPrivateNetwork: true } : opts?.ssrfPolicy;
3042
3045
  return new _BrowserClaw(cdpUrl, null, ssrfPolicy);
3043
3046
  }
3044
3047
  /**