browserclaw 0.11.3 → 0.11.4

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.d.cts CHANGED
@@ -1791,15 +1791,19 @@ declare function setDialogHandler(opts: {
1791
1791
  handler?: DialogHandler;
1792
1792
  }): Promise<void>;
1793
1793
  /**
1794
- * Force-disconnect a Playwright browser connection for a given CDP target.
1795
- * Clears the connection cache, sends Runtime.terminateExecution via raw CDP
1796
- * websocket to kill stuck evals (bypassing Playwright), and closes the browser.
1794
+ * Force-disconnect the ENTIRE Playwright browser connection, not just one target.
1795
+ * Clears the connection cache, optionally sends Runtime.terminateExecution to
1796
+ * a specific target via raw CDP websocket to kill stuck evals (bypassing
1797
+ * Playwright), then closes the browser — which disconnects ALL tabs.
1798
+ * The targetId parameter is only used to send Runtime.terminateExecution before closing.
1797
1799
  */
1798
- declare function forceDisconnectPlaywrightForTarget(opts: {
1800
+ declare function forceDisconnectPlaywrightConnection(opts: {
1799
1801
  cdpUrl: string;
1800
1802
  targetId?: string;
1801
1803
  reason?: string;
1802
1804
  }): Promise<void>;
1805
+ /** @deprecated Use `forceDisconnectPlaywrightConnection` instead. */
1806
+ declare const forceDisconnectPlaywrightForTarget: typeof forceDisconnectPlaywrightConnection;
1803
1807
  /**
1804
1808
  * Resolve a page by targetId or throw BrowserTabNotFoundError.
1805
1809
  */
@@ -1862,4 +1866,4 @@ declare function waitForChallengeViaPlaywright(opts: {
1862
1866
  pollMs?: number;
1863
1867
  }): Promise<ChallengeWaitResult>;
1864
1868
 
1865
- export { type AriaNode, type AriaSnapshotResult, type BatchAction, type BatchActionResult, BrowserClaw, type BrowserNavigationPolicyOptions, type BrowserNavigationRequestLike, type BrowserTab, BrowserTabNotFoundError, type ChallengeInfo, type ChallengeKind, type ChallengeWaitResult, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type ContextState, type CookieData, CrawlPage, type DialogEvent, type DialogHandler, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type LookupFn, type NetworkRequest, type PageError, type PinnedHostname, type RequestResult, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, STEALTH_SCRIPT, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type SsrfPolicy, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions, assertBrowserNavigationAllowed, assertBrowserNavigationRedirectChainAllowed, assertBrowserNavigationResultAllowed, assertSafeUploadPaths, batchViaPlaywright, createPinnedLookup, detectChallengeViaPlaywright, ensureContextState, executeSingleAction, forceDisconnectPlaywrightForTarget, getChromeWebSocketUrl, getRestoredPageForTarget, isChromeCdpReady, isChromeReachable, normalizeCdpHttpBaseForJsonEndpoints, parseRoleRef, pressAndHoldViaCdp, requireRef, requireRefOrSelector, requiresInspectableBrowserNavigationRedirects, resolveBoundedDelayMs, resolveInteractionTimeoutMs, resolvePageByTargetIdOrThrow, resolvePinnedHostnameWithPolicy, resolveStrictExistingUploadPaths, sanitizeUntrustedFileName, setDialogHandler, waitForChallengeViaPlaywright, withBrowserNavigationPolicy, withPageScopedCdpClient, withPlaywrightPageCdpSession, writeViaSiblingTempPath };
1869
+ export { type AriaNode, type AriaSnapshotResult, type BatchAction, type BatchActionResult, BrowserClaw, type BrowserNavigationPolicyOptions, type BrowserNavigationRequestLike, type BrowserTab, BrowserTabNotFoundError, type ChallengeInfo, type ChallengeKind, type ChallengeWaitResult, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type ContextState, type CookieData, CrawlPage, type DialogEvent, type DialogHandler, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type LookupFn, type NetworkRequest, type PageError, type PinnedHostname, type RequestResult, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, STEALTH_SCRIPT, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type SsrfPolicy, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions, assertBrowserNavigationAllowed, assertBrowserNavigationRedirectChainAllowed, assertBrowserNavigationResultAllowed, assertSafeUploadPaths, batchViaPlaywright, createPinnedLookup, detectChallengeViaPlaywright, ensureContextState, executeSingleAction, forceDisconnectPlaywrightConnection, forceDisconnectPlaywrightForTarget, getChromeWebSocketUrl, getRestoredPageForTarget, isChromeCdpReady, isChromeReachable, normalizeCdpHttpBaseForJsonEndpoints, parseRoleRef, pressAndHoldViaCdp, requireRef, requireRefOrSelector, requiresInspectableBrowserNavigationRedirects, resolveBoundedDelayMs, resolveInteractionTimeoutMs, resolvePageByTargetIdOrThrow, resolvePinnedHostnameWithPolicy, resolveStrictExistingUploadPaths, sanitizeUntrustedFileName, setDialogHandler, waitForChallengeViaPlaywright, withBrowserNavigationPolicy, withPageScopedCdpClient, withPlaywrightPageCdpSession, writeViaSiblingTempPath };
package/dist/index.d.ts CHANGED
@@ -1791,15 +1791,19 @@ declare function setDialogHandler(opts: {
1791
1791
  handler?: DialogHandler;
1792
1792
  }): Promise<void>;
1793
1793
  /**
1794
- * Force-disconnect a Playwright browser connection for a given CDP target.
1795
- * Clears the connection cache, sends Runtime.terminateExecution via raw CDP
1796
- * websocket to kill stuck evals (bypassing Playwright), and closes the browser.
1794
+ * Force-disconnect the ENTIRE Playwright browser connection, not just one target.
1795
+ * Clears the connection cache, optionally sends Runtime.terminateExecution to
1796
+ * a specific target via raw CDP websocket to kill stuck evals (bypassing
1797
+ * Playwright), then closes the browser — which disconnects ALL tabs.
1798
+ * The targetId parameter is only used to send Runtime.terminateExecution before closing.
1797
1799
  */
1798
- declare function forceDisconnectPlaywrightForTarget(opts: {
1800
+ declare function forceDisconnectPlaywrightConnection(opts: {
1799
1801
  cdpUrl: string;
1800
1802
  targetId?: string;
1801
1803
  reason?: string;
1802
1804
  }): Promise<void>;
1805
+ /** @deprecated Use `forceDisconnectPlaywrightConnection` instead. */
1806
+ declare const forceDisconnectPlaywrightForTarget: typeof forceDisconnectPlaywrightConnection;
1803
1807
  /**
1804
1808
  * Resolve a page by targetId or throw BrowserTabNotFoundError.
1805
1809
  */
@@ -1862,4 +1866,4 @@ declare function waitForChallengeViaPlaywright(opts: {
1862
1866
  pollMs?: number;
1863
1867
  }): Promise<ChallengeWaitResult>;
1864
1868
 
1865
- export { type AriaNode, type AriaSnapshotResult, type BatchAction, type BatchActionResult, BrowserClaw, type BrowserNavigationPolicyOptions, type BrowserNavigationRequestLike, type BrowserTab, BrowserTabNotFoundError, type ChallengeInfo, type ChallengeKind, type ChallengeWaitResult, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type ContextState, type CookieData, CrawlPage, type DialogEvent, type DialogHandler, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type LookupFn, type NetworkRequest, type PageError, type PinnedHostname, type RequestResult, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, STEALTH_SCRIPT, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type SsrfPolicy, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions, assertBrowserNavigationAllowed, assertBrowserNavigationRedirectChainAllowed, assertBrowserNavigationResultAllowed, assertSafeUploadPaths, batchViaPlaywright, createPinnedLookup, detectChallengeViaPlaywright, ensureContextState, executeSingleAction, forceDisconnectPlaywrightForTarget, getChromeWebSocketUrl, getRestoredPageForTarget, isChromeCdpReady, isChromeReachable, normalizeCdpHttpBaseForJsonEndpoints, parseRoleRef, pressAndHoldViaCdp, requireRef, requireRefOrSelector, requiresInspectableBrowserNavigationRedirects, resolveBoundedDelayMs, resolveInteractionTimeoutMs, resolvePageByTargetIdOrThrow, resolvePinnedHostnameWithPolicy, resolveStrictExistingUploadPaths, sanitizeUntrustedFileName, setDialogHandler, waitForChallengeViaPlaywright, withBrowserNavigationPolicy, withPageScopedCdpClient, withPlaywrightPageCdpSession, writeViaSiblingTempPath };
1869
+ export { type AriaNode, type AriaSnapshotResult, type BatchAction, type BatchActionResult, BrowserClaw, type BrowserNavigationPolicyOptions, type BrowserNavigationRequestLike, type BrowserTab, BrowserTabNotFoundError, type ChallengeInfo, type ChallengeKind, type ChallengeWaitResult, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type ContextState, type CookieData, CrawlPage, type DialogEvent, type DialogHandler, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type LookupFn, type NetworkRequest, type PageError, type PinnedHostname, type RequestResult, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, STEALTH_SCRIPT, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type SsrfPolicy, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions, assertBrowserNavigationAllowed, assertBrowserNavigationRedirectChainAllowed, assertBrowserNavigationResultAllowed, assertSafeUploadPaths, batchViaPlaywright, createPinnedLookup, detectChallengeViaPlaywright, ensureContextState, executeSingleAction, forceDisconnectPlaywrightConnection, forceDisconnectPlaywrightForTarget, getChromeWebSocketUrl, getRestoredPageForTarget, isChromeCdpReady, isChromeReachable, normalizeCdpHttpBaseForJsonEndpoints, parseRoleRef, pressAndHoldViaCdp, requireRef, requireRefOrSelector, requiresInspectableBrowserNavigationRedirects, resolveBoundedDelayMs, resolveInteractionTimeoutMs, resolvePageByTargetIdOrThrow, resolvePinnedHostnameWithPolicy, resolveStrictExistingUploadPaths, sanitizeUntrustedFileName, setDialogHandler, waitForChallengeViaPlaywright, withBrowserNavigationPolicy, withPageScopedCdpClient, withPlaywrightPageCdpSession, writeViaSiblingTempPath };
package/dist/index.js CHANGED
@@ -1308,7 +1308,10 @@ function normalizeCdpHttpBaseForJsonEndpoints(cdpUrl) {
1308
1308
  url.pathname = url.pathname.replace(/\/cdp$/, "");
1309
1309
  return url.toString().replace(/\/$/, "");
1310
1310
  } catch {
1311
- return cdpUrl.replace(/^ws:/, "http:").replace(/^wss:/, "https:").replace(/\/devtools\/browser\/.*$/, "").replace(/\/cdp$/, "").replace(/\/$/, "");
1311
+ let normalized = cdpUrl.replace(/^ws:/, "http:").replace(/^wss:/, "https:");
1312
+ const dtIdx = normalized.indexOf("/devtools/browser/");
1313
+ if (dtIdx >= 0) normalized = normalized.slice(0, dtIdx);
1314
+ return normalized.replace(/\/cdp$/, "").replace(/\/$/, "");
1312
1315
  }
1313
1316
  }
1314
1317
  function appendCdpPath(cdpUrl, cdpPath) {
@@ -1779,20 +1782,17 @@ var pageStates = /* @__PURE__ */ new WeakMap();
1779
1782
  var contextStates = /* @__PURE__ */ new WeakMap();
1780
1783
  var observedContexts = /* @__PURE__ */ new WeakSet();
1781
1784
  var observedPages = /* @__PURE__ */ new WeakSet();
1782
- var nextUploadArmId = 0;
1783
- var nextDialogArmId = 0;
1784
- var nextDownloadArmId = 0;
1785
- function bumpUploadArmId() {
1786
- nextUploadArmId += 1;
1787
- return nextUploadArmId;
1785
+ function bumpUploadArmId(state) {
1786
+ state.nextArmIdUpload += 1;
1787
+ return state.nextArmIdUpload;
1788
1788
  }
1789
- function bumpDialogArmId() {
1790
- nextDialogArmId += 1;
1791
- return nextDialogArmId;
1789
+ function bumpDialogArmId(state) {
1790
+ state.nextArmIdDialog += 1;
1791
+ return state.nextArmIdDialog;
1792
1792
  }
1793
- function bumpDownloadArmId() {
1794
- nextDownloadArmId += 1;
1795
- return nextDownloadArmId;
1793
+ function bumpDownloadArmId(state) {
1794
+ state.nextArmIdDownload += 1;
1795
+ return state.nextArmIdDownload;
1796
1796
  }
1797
1797
  function ensureContextState(context) {
1798
1798
  const existing = contextStates.get(context);
@@ -1822,7 +1822,10 @@ function ensurePageState(page) {
1822
1822
  nextRequestId: 0,
1823
1823
  armIdUpload: 0,
1824
1824
  armIdDialog: 0,
1825
- armIdDownload: 0
1825
+ armIdDownload: 0,
1826
+ nextArmIdUpload: 0,
1827
+ nextArmIdDialog: 0,
1828
+ nextArmIdDownload: 0
1826
1829
  };
1827
1830
  pageStates.set(page, state);
1828
1831
  if (!observedPages.has(page)) {
@@ -2151,51 +2154,41 @@ function isLoopbackCdpUrl(url) {
2151
2154
  return false;
2152
2155
  }
2153
2156
  }
2154
- var NoProxyLeaseManager = class {
2155
- leaseCount = 0;
2156
- snapshot = null;
2157
- acquire(url) {
2158
- if (!isLoopbackCdpUrl(url) || !hasProxyEnvConfigured()) return null;
2159
- if (this.leaseCount === 0 && !noProxyAlreadyCoversLocalhost()) {
2160
- const noProxy = process.env.NO_PROXY;
2161
- const noProxyLower = process.env.no_proxy;
2162
- const current = noProxy ?? noProxyLower ?? "";
2163
- const applied = current ? `${current},${LOOPBACK_ENTRIES}` : LOOPBACK_ENTRIES;
2164
- process.env.NO_PROXY = applied;
2165
- process.env.no_proxy = applied;
2166
- this.snapshot = { noProxy, noProxyLower, applied };
2167
- }
2168
- this.leaseCount += 1;
2169
- let released = false;
2170
- return () => {
2171
- if (released) return;
2172
- released = true;
2173
- this.release();
2174
- };
2175
- }
2176
- release() {
2177
- if (this.leaseCount <= 0) return;
2178
- this.leaseCount -= 1;
2179
- if (this.leaseCount > 0 || !this.snapshot) return;
2180
- const { noProxy, noProxyLower, applied } = this.snapshot;
2181
- const currentNoProxy = process.env.NO_PROXY;
2182
- const currentNoProxyLower = process.env.no_proxy;
2183
- if (currentNoProxy === applied && (currentNoProxyLower === applied || currentNoProxyLower === void 0)) {
2184
- if (noProxy !== void 0) process.env.NO_PROXY = noProxy;
2185
- else delete process.env.NO_PROXY;
2186
- if (noProxyLower !== void 0) process.env.no_proxy = noProxyLower;
2187
- else delete process.env.no_proxy;
2157
+ var envMutexPromise = Promise.resolve();
2158
+ async function withNoProxyForCdpUrl(url, fn) {
2159
+ if (!isLoopbackCdpUrl(url) || !hasProxyEnvConfigured()) return fn();
2160
+ const prev = envMutexPromise;
2161
+ let release = () => {
2162
+ };
2163
+ envMutexPromise = new Promise((r) => {
2164
+ release = r;
2165
+ });
2166
+ await prev;
2167
+ if (noProxyAlreadyCoversLocalhost()) {
2168
+ try {
2169
+ return await fn();
2170
+ } finally {
2171
+ release();
2188
2172
  }
2189
- this.snapshot = null;
2190
2173
  }
2191
- };
2192
- var noProxyLeaseManager = new NoProxyLeaseManager();
2193
- async function withNoProxyForCdpUrl(url, fn) {
2194
- const release = noProxyLeaseManager.acquire(url);
2174
+ const savedNoProxy = process.env.NO_PROXY;
2175
+ const savedNoProxyLower = process.env.no_proxy;
2176
+ const current = savedNoProxy ?? savedNoProxyLower ?? "";
2177
+ const applied = current ? `${current},${LOOPBACK_ENTRIES}` : LOOPBACK_ENTRIES;
2178
+ process.env.NO_PROXY = applied;
2179
+ process.env.no_proxy = applied;
2195
2180
  try {
2196
2181
  return await fn();
2197
2182
  } finally {
2198
- release?.();
2183
+ if (process.env.NO_PROXY === applied) {
2184
+ if (savedNoProxy !== void 0) process.env.NO_PROXY = savedNoProxy;
2185
+ else delete process.env.NO_PROXY;
2186
+ }
2187
+ if (process.env.no_proxy === applied) {
2188
+ if (savedNoProxyLower !== void 0) process.env.no_proxy = savedNoProxyLower;
2189
+ else delete process.env.no_proxy;
2190
+ }
2191
+ release();
2199
2192
  }
2200
2193
  }
2201
2194
  new http.Agent();
@@ -2425,7 +2418,7 @@ async function tryTerminateExecutionViaCdp(cdpUrl, targetId) {
2425
2418
  };
2426
2419
  });
2427
2420
  }
2428
- async function forceDisconnectPlaywrightForTarget(opts) {
2421
+ async function forceDisconnectPlaywrightConnection(opts) {
2429
2422
  const normalized = normalizeCdpUrl(opts.cdpUrl);
2430
2423
  const cur = cachedByCdpUrl.get(normalized);
2431
2424
  if (!cur) return;
@@ -2442,6 +2435,7 @@ async function forceDisconnectPlaywrightForTarget(opts) {
2442
2435
  cur.browser.close().catch(() => {
2443
2436
  });
2444
2437
  }
2438
+ var forceDisconnectPlaywrightForTarget = forceDisconnectPlaywrightConnection;
2445
2439
  function getAllPages(browser) {
2446
2440
  return browser.contexts().flatMap((c) => c.pages());
2447
2441
  }
@@ -2674,7 +2668,7 @@ async function evaluateViaPlaywright(opts) {
2674
2668
  }
2675
2669
  if (signal !== void 0) {
2676
2670
  const disconnect = () => {
2677
- forceDisconnectPlaywrightForTarget({
2671
+ forceDisconnectPlaywrightConnection({
2678
2672
  cdpUrl: opts.cdpUrl,
2679
2673
  targetId: opts.targetId}).catch(() => {
2680
2674
  });
@@ -2741,7 +2735,6 @@ function withBrowserNavigationPolicy(ssrfPolicy) {
2741
2735
  }
2742
2736
  var NETWORK_NAVIGATION_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
2743
2737
  var SAFE_NON_NETWORK_URLS = /* @__PURE__ */ new Set(["about:blank"]);
2744
- var PROXY_ENV_KEYS2 = ["HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy"];
2745
2738
  var BLOCKED_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "localhost.localdomain", "metadata.google.internal"]);
2746
2739
  function isAllowedNonNetworkNavigationUrl(parsed) {
2747
2740
  return SAFE_NON_NETWORK_URLS.has(parsed.href);
@@ -2749,13 +2742,6 @@ function isAllowedNonNetworkNavigationUrl(parsed) {
2749
2742
  function isPrivateNetworkAllowedByPolicy(policy) {
2750
2743
  return policy?.dangerouslyAllowPrivateNetwork === true || policy?.allowPrivateNetwork === true;
2751
2744
  }
2752
- function hasProxyEnvConfigured2(env = process.env) {
2753
- for (const key of PROXY_ENV_KEYS2) {
2754
- const value = env[key];
2755
- if (typeof value === "string" && value.trim().length > 0) return true;
2756
- }
2757
- return false;
2758
- }
2759
2745
  function normalizeHostname(hostname) {
2760
2746
  let h = hostname.trim().toLowerCase();
2761
2747
  if (h.startsWith("[") && h.endsWith("]")) h = h.slice(1, -1);
@@ -3066,7 +3052,7 @@ async function assertBrowserNavigationAllowed(opts) {
3066
3052
  if (isAllowedNonNetworkNavigationUrl(parsed)) return;
3067
3053
  throw new InvalidBrowserNavigationUrlError(`Navigation blocked: unsupported protocol "${parsed.protocol}"`);
3068
3054
  }
3069
- if (hasProxyEnvConfigured2() && !isPrivateNetworkAllowedByPolicy(opts.ssrfPolicy)) {
3055
+ if (hasProxyEnvConfigured() && !isPrivateNetworkAllowedByPolicy(opts.ssrfPolicy)) {
3070
3056
  throw new InvalidBrowserNavigationUrlError(
3071
3057
  "Navigation blocked: strict browser SSRF policy cannot be enforced while env proxy variables are set"
3072
3058
  );
@@ -3521,7 +3507,7 @@ async function armDialogViaPlaywright(opts) {
3521
3507
  const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
3522
3508
  const state = ensurePageState(page);
3523
3509
  const timeout = normalizeTimeoutMs(opts.timeoutMs, 12e4);
3524
- state.armIdDialog = bumpDialogArmId();
3510
+ state.armIdDialog = bumpDialogArmId(state);
3525
3511
  const armId = state.armIdDialog;
3526
3512
  page.waitForEvent("dialog", { timeout }).then(async (dialog) => {
3527
3513
  if (state.armIdDialog !== armId) return;
@@ -3539,7 +3525,7 @@ async function armFileUploadViaPlaywright(opts) {
3539
3525
  const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
3540
3526
  const state = ensurePageState(page);
3541
3527
  const timeout = normalizeTimeoutMs(opts.timeoutMs, 12e4);
3542
- state.armIdUpload = bumpUploadArmId();
3528
+ state.armIdUpload = bumpUploadArmId(state);
3543
3529
  const armId = state.armIdUpload;
3544
3530
  page.waitForEvent("filechooser", { timeout }).then(async (fileChooser) => {
3545
3531
  if (state.armIdUpload !== armId) return;
@@ -3699,7 +3685,7 @@ async function navigateViaPlaywright(opts) {
3699
3685
  response = await navigate();
3700
3686
  } catch (err) {
3701
3687
  if (!isRetryableNavigateError(err)) throw err;
3702
- await forceDisconnectPlaywrightForTarget({
3688
+ await forceDisconnectPlaywrightConnection({
3703
3689
  cdpUrl: opts.cdpUrl,
3704
3690
  targetId: opts.targetId}).catch(() => {
3705
3691
  });
@@ -3841,18 +3827,12 @@ async function resizeViewportViaPlaywright(opts) {
3841
3827
 
3842
3828
  // src/actions/wait.ts
3843
3829
  var MAX_WAIT_TIME_MS = 3e4;
3844
- function resolveBoundedDelayMs2(value, label, maxMs) {
3845
- const normalized = Math.floor(value ?? 0);
3846
- if (!Number.isFinite(normalized) || normalized < 0) throw new Error(`${label} must be >= 0`);
3847
- if (normalized > maxMs) throw new Error(`${label} exceeds maximum of ${String(maxMs)}ms`);
3848
- return normalized;
3849
- }
3850
3830
  async function waitForViaPlaywright(opts) {
3851
3831
  const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
3852
3832
  ensurePageState(page);
3853
3833
  const timeout = normalizeTimeoutMs(opts.timeoutMs, 2e4);
3854
3834
  if (typeof opts.timeMs === "number" && Number.isFinite(opts.timeMs)) {
3855
- await page.waitForTimeout(resolveBoundedDelayMs2(opts.timeMs, "wait timeMs", MAX_WAIT_TIME_MS));
3835
+ await page.waitForTimeout(resolveBoundedDelayMs(opts.timeMs, "wait timeMs", MAX_WAIT_TIME_MS));
3856
3836
  }
3857
3837
  if (opts.text !== void 0 && opts.text !== "") {
3858
3838
  await page.waitForFunction((text) => (document.body?.innerText ?? "").includes(text), opts.text, { timeout });
@@ -4109,7 +4089,7 @@ async function downloadViaPlaywright(opts) {
4109
4089
  const timeout = normalizeTimeoutMs(opts.timeoutMs, 12e4);
4110
4090
  const outPath = opts.path.trim();
4111
4091
  if (!outPath) throw new Error("path is required");
4112
- state.armIdDownload = bumpDownloadArmId();
4092
+ state.armIdDownload = bumpDownloadArmId(state);
4113
4093
  const armId = state.armIdDownload;
4114
4094
  const waiter = createPageDownloadWaiter(page, timeout);
4115
4095
  try {
@@ -4129,7 +4109,7 @@ async function waitForDownloadViaPlaywright(opts) {
4129
4109
  const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
4130
4110
  const state = ensurePageState(page);
4131
4111
  const timeout = normalizeTimeoutMs(opts.timeoutMs, 12e4);
4132
- state.armIdDownload = bumpDownloadArmId();
4112
+ state.armIdDownload = bumpDownloadArmId(state);
4133
4113
  const armId = state.armIdDownload;
4134
4114
  const waiter = createPageDownloadWaiter(page, timeout);
4135
4115
  try {
@@ -6566,6 +6546,6 @@ var BrowserClaw = class _BrowserClaw {
6566
6546
  }
6567
6547
  };
6568
6548
 
6569
- export { BrowserClaw, BrowserTabNotFoundError, CrawlPage, InvalidBrowserNavigationUrlError, STEALTH_SCRIPT, assertBrowserNavigationAllowed, assertBrowserNavigationRedirectChainAllowed, assertBrowserNavigationResultAllowed, assertSafeUploadPaths, batchViaPlaywright, createPinnedLookup, detectChallengeViaPlaywright, ensureContextState, executeSingleAction, forceDisconnectPlaywrightForTarget, getChromeWebSocketUrl, getRestoredPageForTarget, isChromeCdpReady, isChromeReachable, normalizeCdpHttpBaseForJsonEndpoints, parseRoleRef, pressAndHoldViaCdp, requireRef, requireRefOrSelector, requiresInspectableBrowserNavigationRedirects, resolveBoundedDelayMs, resolveInteractionTimeoutMs, resolvePageByTargetIdOrThrow, resolvePinnedHostnameWithPolicy, resolveStrictExistingUploadPaths, sanitizeUntrustedFileName, setDialogHandler, waitForChallengeViaPlaywright, withBrowserNavigationPolicy, withPageScopedCdpClient, withPlaywrightPageCdpSession, writeViaSiblingTempPath };
6549
+ export { BrowserClaw, BrowserTabNotFoundError, CrawlPage, InvalidBrowserNavigationUrlError, STEALTH_SCRIPT, assertBrowserNavigationAllowed, assertBrowserNavigationRedirectChainAllowed, assertBrowserNavigationResultAllowed, assertSafeUploadPaths, batchViaPlaywright, createPinnedLookup, detectChallengeViaPlaywright, ensureContextState, executeSingleAction, forceDisconnectPlaywrightConnection, forceDisconnectPlaywrightForTarget, getChromeWebSocketUrl, getRestoredPageForTarget, isChromeCdpReady, isChromeReachable, normalizeCdpHttpBaseForJsonEndpoints, parseRoleRef, pressAndHoldViaCdp, requireRef, requireRefOrSelector, requiresInspectableBrowserNavigationRedirects, resolveBoundedDelayMs, resolveInteractionTimeoutMs, resolvePageByTargetIdOrThrow, resolvePinnedHostnameWithPolicy, resolveStrictExistingUploadPaths, sanitizeUntrustedFileName, setDialogHandler, waitForChallengeViaPlaywright, withBrowserNavigationPolicy, withPageScopedCdpClient, withPlaywrightPageCdpSession, writeViaSiblingTempPath };
6570
6550
  //# sourceMappingURL=index.js.map
6571
6551
  //# sourceMappingURL=index.js.map