@skrillex1224/playwright-toolkit 2.1.224 → 2.1.226

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.js CHANGED
@@ -12,8 +12,10 @@ var constants_exports = {};
12
12
  __export(constants_exports, {
13
13
  ActorInfo: () => ActorInfo,
14
14
  Code: () => Code,
15
+ Device: () => Device,
15
16
  PresetOfLiveViewKey: () => PresetOfLiveViewKey,
16
- Status: () => Status
17
+ Status: () => Status,
18
+ normalizeDevice: () => normalizeDevice
17
19
  });
18
20
  var Code = {
19
21
  Success: 0,
@@ -29,6 +31,17 @@ var Status = {
29
31
  Failed: "FAILED"
30
32
  };
31
33
  var PresetOfLiveViewKey = "LIVE_VIEW_SCREENSHOT";
34
+ var Device = Object.freeze({
35
+ Desktop: "desktop",
36
+ Mobile: "mobile"
37
+ });
38
+ var normalizeDevice = (value, fallback = Device.Desktop) => {
39
+ const normalizedFallback = String(fallback || "").trim().toLowerCase() === Device.Mobile ? Device.Mobile : Device.Desktop;
40
+ const raw = String(value || "").trim().toLowerCase();
41
+ if (raw === Device.Mobile) return Device.Mobile;
42
+ if (raw === Device.Desktop) return Device.Desktop;
43
+ return normalizedFallback;
44
+ };
32
45
  var createActorInfo = (info) => {
33
46
  const normalizeDomain = (value) => {
34
47
  if (!value) return "";
@@ -106,12 +119,14 @@ var createActorInfo = (info) => {
106
119
  const domain = normalizeDomain(info.domain);
107
120
  const path2 = normalizePath(info.path);
108
121
  const share = normalizeShare2(info.share);
122
+ const device = normalizeDevice(info.device);
109
123
  return {
110
124
  ...info,
111
125
  protocol,
112
126
  domain,
113
127
  path: path2,
114
128
  share,
129
+ device,
115
130
  get icon() {
116
131
  if (info.icon) return info.icon;
117
132
  return buildIcon(this);
@@ -163,6 +178,7 @@ var ActorInfo = {
163
178
  name: "\u8C46\u5305",
164
179
  domain: "www.doubao.com",
165
180
  path: "/",
181
+ device: Device.Mobile,
166
182
  share: {
167
183
  mode: "response",
168
184
  prefix: "https://www.doubao.com/thread/",
@@ -178,6 +194,7 @@ var ActorInfo = {
178
194
  name: "DeepSeek",
179
195
  domain: "chat.deepseek.com",
180
196
  path: "/",
197
+ device: Device.Mobile,
181
198
  share: {
182
199
  mode: "response",
183
200
  prefix: "https://chat.deepseek.com/share/",
@@ -334,18 +351,18 @@ var fallbackLog = {
334
351
  error: (...args) => console.error(...args),
335
352
  debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
336
353
  };
337
- var resolveLogMethod = (logger15, name) => {
338
- if (logger15 && typeof logger15[name] === "function") {
339
- return logger15[name].bind(logger15);
354
+ var resolveLogMethod = (logger16, name) => {
355
+ if (logger16 && typeof logger16[name] === "function") {
356
+ return logger16[name].bind(logger16);
340
357
  }
341
- if (name === "warning" && logger15 && typeof logger15.warn === "function") {
342
- return logger15.warn.bind(logger15);
358
+ if (name === "warning" && logger16 && typeof logger16.warn === "function") {
359
+ return logger16.warn.bind(logger16);
343
360
  }
344
361
  return fallbackLog[name];
345
362
  };
346
363
  var defaultLogger = null;
347
- var setDefaultLogger = (logger15) => {
348
- defaultLogger = logger15;
364
+ var setDefaultLogger = (logger16) => {
365
+ defaultLogger = logger16;
349
366
  };
350
367
  var resolveLogger = (explicitLogger) => {
351
368
  if (explicitLogger && typeof explicitLogger.info === "function") {
@@ -372,8 +389,8 @@ var colorize = (text, color) => {
372
389
  var createBaseLogger = (prefix = "", explicitLogger) => {
373
390
  const name = prefix ? String(prefix) : "";
374
391
  const dispatch = (methodName, icon, message, color) => {
375
- const logger15 = resolveLogger(explicitLogger);
376
- const logFn = resolveLogMethod(logger15, methodName);
392
+ const logger16 = resolveLogger(explicitLogger);
393
+ const logFn = resolveLogMethod(logger16, methodName);
377
394
  const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
378
395
  const line = formatLine(name, icon, message);
379
396
  const coloredLine = colorize(line, color);
@@ -972,6 +989,12 @@ var PageRuntimeStateKey = "__playwright_toolkit_runtime_state__";
972
989
  var BROWSER_PROFILE_SCHEMA_VERSION = 1;
973
990
  var rememberedRuntimeState = null;
974
991
  var isPlainObject = (value) => value && typeof value === "object" && !Array.isArray(value);
992
+ var normalizeKnownDevice = (value) => {
993
+ const raw = String(value || "").trim().toLowerCase();
994
+ if (raw === Device.Mobile) return Device.Mobile;
995
+ if (raw === Device.Desktop) return Device.Desktop;
996
+ return "";
997
+ };
975
998
  var deepClone = (value) => {
976
999
  if (value == null) return value;
977
1000
  try {
@@ -1323,6 +1346,10 @@ var normalizeObservedBrowserProfile = (value) => {
1323
1346
  var normalizeBrowserProfileCore = (value) => {
1324
1347
  const source = isPlainObject(value) ? value : {};
1325
1348
  const profile = {};
1349
+ const device = normalizeKnownDevice(source.device);
1350
+ if (device) {
1351
+ profile.device = device;
1352
+ }
1326
1353
  if (isPlainObject(source.fingerprint) && Object.keys(source.fingerprint).length > 0) {
1327
1354
  profile.fingerprint = deepClone(source.fingerprint);
1328
1355
  }
@@ -1380,9 +1407,11 @@ var mergeBrowserProfilePayload = (target = {}, source = {}) => {
1380
1407
  if (Object.keys(mergedCore).length === 0 && Object.keys(incomingCore).length > 0) {
1381
1408
  mergedCore = incomingCore;
1382
1409
  } else if (Object.keys(incomingCore).length > 0) {
1410
+ const currentDevice = normalizeKnownDevice(currentCore.device);
1411
+ const incomingDevice = normalizeKnownDevice(incomingCore.device);
1383
1412
  const currentVersion = Number(currentCore.browser_major_version || 0);
1384
1413
  const incomingVersion = Number(incomingCore.browser_major_version || 0);
1385
- if (currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {
1414
+ if (incomingDevice && currentDevice !== incomingDevice || currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {
1386
1415
  mergedCore = incomingCore;
1387
1416
  }
1388
1417
  }
@@ -1433,8 +1462,13 @@ var normalizeRuntimeState = (source = {}, actor = "") => {
1433
1462
  }
1434
1463
  return RuntimeEnv.parseInput(source, actor);
1435
1464
  };
1465
+ var resolveInputDevice = (input = {}, runtime2 = {}, actor = "") => {
1466
+ const actorDevice = ActorInfo?.[actor]?.device;
1467
+ return normalizeDevice(actorDevice ?? input?.device ?? runtime2?.device);
1468
+ };
1436
1469
  var RuntimeEnv = {
1437
1470
  tryParseJSON,
1471
+ normalizeDevice,
1438
1472
  normalizeCookies,
1439
1473
  normalizeLocalStorage,
1440
1474
  normalizeSessionStorage,
@@ -1460,6 +1494,7 @@ var RuntimeEnv = {
1460
1494
  parseInput(input = {}, actor = "") {
1461
1495
  const runtime2 = tryParseJSON(input?.runtime) || {};
1462
1496
  const resolvedActor = String(actor || input?.actor || "").trim();
1497
+ const device = resolveInputDevice(input, runtime2, resolvedActor);
1463
1498
  const query = String(input?.query || "").trim();
1464
1499
  const cookies = normalizeCookies(runtime2?.cookies);
1465
1500
  const cookieMap = buildCookieMap(cookies);
@@ -1479,6 +1514,7 @@ var RuntimeEnv = {
1479
1514
  }
1480
1515
  const state = {
1481
1516
  actor: resolvedActor,
1517
+ device,
1482
1518
  runtime: normalizedRuntime,
1483
1519
  envId,
1484
1520
  query,
@@ -1524,7 +1560,10 @@ var RuntimeEnv = {
1524
1560
  },
1525
1561
  setBrowserProfileCore(source = {}, core = {}, actor = "") {
1526
1562
  const state = normalizeRuntimeState(source, actor);
1527
- const normalizedCore = normalizeBrowserProfileCore(core);
1563
+ const normalizedCore = normalizeBrowserProfileCore({
1564
+ ...core,
1565
+ device: normalizeKnownDevice(core?.device) || state.device
1566
+ });
1528
1567
  state.browserProfileCore = normalizedCore;
1529
1568
  state.browserProfile = buildBrowserProfilePayload(normalizedCore, state.browserProfileObserved);
1530
1569
  if (Object.keys(state.browserProfile).length > 0) {
@@ -1999,15 +2038,25 @@ var DEFAULT_LAUNCH_ARGS = [
1999
2038
  "--disable-setuid-sandbox",
2000
2039
  "--window-position=0,0"
2001
2040
  ];
2002
- function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0 } = {}) {
2041
+ function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0, device = Device.Desktop } = {}) {
2042
+ const resolvedDevice = normalizeDevice(device);
2003
2043
  const normalizedBrowserMajorVersion = Number(browserMajorVersion || 0);
2004
2044
  const browserDescriptor = normalizedBrowserMajorVersion > 0 ? [{ name: "chrome", minVersion: normalizedBrowserMajorVersion, maxVersion: normalizedBrowserMajorVersion }] : [{ name: "chrome", minVersion: 110 }];
2005
- return {
2045
+ const options = {
2006
2046
  browsers: browserDescriptor,
2007
- devices: ["desktop"],
2008
- operatingSystems: ["windows", "macos", "linux"],
2047
+ devices: [resolvedDevice],
2048
+ operatingSystems: resolvedDevice === Device.Mobile ? ["android"] : ["windows", "macos", "linux"],
2009
2049
  locales: [locale]
2010
2050
  };
2051
+ if (resolvedDevice === Device.Mobile) {
2052
+ options.screen = {
2053
+ minWidth: 320,
2054
+ maxWidth: 480,
2055
+ minHeight: 640,
2056
+ maxHeight: 1100
2057
+ };
2058
+ }
2059
+ return options;
2011
2060
  }
2012
2061
  var AntiCheat = {
2013
2062
  /**
@@ -2017,7 +2066,7 @@ var AntiCheat = {
2017
2066
  return { ...BASE_CONFIG };
2018
2067
  },
2019
2068
  /**
2020
- * 用于 Crawlee fingerprint generator 的统一配置(桌面端)。
2069
+ * 用于 Crawlee fingerprint generator 的统一配置。
2021
2070
  */
2022
2071
  getFingerprintGeneratorOptions(options = {}) {
2023
2072
  return buildFingerprintOptions(options);
@@ -2030,10 +2079,10 @@ var AntiCheat = {
2030
2079
  return [...DEFAULT_LAUNCH_ARGS, `--lang=${locale}`];
2031
2080
  },
2032
2081
  /**
2033
- * 为 got-scraping 生成与浏览器一致的 TLS 指纹配置(桌面端)。
2082
+ * 为 got-scraping 生成与浏览器一致的 TLS 指纹配置。
2034
2083
  */
2035
- getTlsFingerprintOptions(userAgent = "", acceptLanguage = "") {
2036
- return buildFingerprintOptions();
2084
+ getTlsFingerprintOptions(userAgent = "", acceptLanguage = "", options = {}) {
2085
+ return buildFingerprintOptions(options);
2037
2086
  },
2038
2087
  /**
2039
2088
  * 规范化请求头
@@ -2046,7 +2095,7 @@ var AntiCheat = {
2046
2095
  }
2047
2096
  };
2048
2097
 
2049
- // src/humanize.js
2098
+ // src/internals/humanize/desktop.js
2050
2099
  import delay from "delay";
2051
2100
  import { createCursor } from "ghost-cursor-playwright";
2052
2101
  var logger6 = createInternalLogger("Humanize");
@@ -2071,7 +2120,7 @@ var Humanize = {
2071
2120
  },
2072
2121
  /**
2073
2122
  * 初始化页面的 Ghost Cursor(必须在使用其他 cursor 相关方法前调用)
2074
- *
2123
+ *
2075
2124
  * @param {import('playwright').Page} page
2076
2125
  * @returns {Promise<void>}
2077
2126
  */
@@ -2087,7 +2136,7 @@ var Humanize = {
2087
2136
  },
2088
2137
  /**
2089
2138
  * 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
2090
- *
2139
+ *
2091
2140
  * @param {import('playwright').Page} page
2092
2141
  * @param {string|{x: number, y: number}|import('playwright').ElementHandle} target - CSS选择器、坐标对象或元素句柄
2093
2142
  */
@@ -2129,7 +2178,7 @@ var Humanize = {
2129
2178
  /**
2130
2179
  * 渐进式滚动到元素可见(仅处理 Y 轴滚动)
2131
2180
  * 返回 restore 方法,用于将滚动容器恢复到原位置
2132
- *
2181
+ *
2133
2182
  * @param {import('playwright').Page} page
2134
2183
  * @param {string|import('playwright').ElementHandle} target - CSS 选择器或元素句柄
2135
2184
  * @param {Object} [options]
@@ -2200,7 +2249,7 @@ var Humanize = {
2200
2249
  return { code: "VISIBLE", isFixed };
2201
2250
  });
2202
2251
  };
2203
- const getScrollableRect = async () => {
2252
+ const getScrollableRect2 = async () => {
2204
2253
  return await element.evaluate((el) => {
2205
2254
  const isScrollable = (node) => {
2206
2255
  const style = window.getComputedStyle(node);
@@ -2243,7 +2292,7 @@ var Humanize = {
2243
2292
  if (status.code === "OBSTRUCTED" && status.obstruction) {
2244
2293
  logger6.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
2245
2294
  }
2246
- const scrollRect = await getScrollableRect();
2295
+ const scrollRect = await getScrollableRect2();
2247
2296
  if (!scrollRect && status.isFixed) {
2248
2297
  logger6.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
2249
2298
  return { element, didScroll };
@@ -2290,7 +2339,7 @@ var Humanize = {
2290
2339
  },
2291
2340
  /**
2292
2341
  * 人类化点击 - 使用 ghost-cursor 模拟人类鼠标移动轨迹并点击
2293
- *
2342
+ *
2294
2343
  * @param {import('playwright').Page} page
2295
2344
  * @param {string|import('playwright').ElementHandle} [target] - CSS 选择器或元素句柄。如果为空,则点击当前鼠标位置
2296
2345
  * @param {Object} [options]
@@ -2396,7 +2445,7 @@ var Humanize = {
2396
2445
  * @param {import('playwright').Page} page
2397
2446
  * @param {string} selector - 输入框选择器
2398
2447
  * @param {string} text - 要输入的文本
2399
- * @param {Object} [options]
2448
+ * @param {Object} [options]
2400
2449
  * @param {number} [options.baseDelay=180] - 基础按键延迟 (ms),实际 ±40% 抖动
2401
2450
  * @param {number} [options.pauseProbability=0.08] - 停顿概率 (0-1)
2402
2451
  * @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
@@ -2524,6 +2573,787 @@ var Humanize = {
2524
2573
  }
2525
2574
  };
2526
2575
 
2576
+ // src/internals/humanize/shared.js
2577
+ import delay2 from "delay";
2578
+ var jitterMs = (base, jitterPercent = 0.3) => {
2579
+ const jitter = Number(base || 0) * Number(jitterPercent || 0) * (Math.random() * 2 - 1);
2580
+ return Math.max(10, Math.round(Number(base || 0) + jitter));
2581
+ };
2582
+ var randomPointInBox = (box, paddingRatio = 0.24) => {
2583
+ const safePaddingX = Math.max(2, Math.min(box.width * paddingRatio, box.width / 2));
2584
+ const safePaddingY = Math.max(2, Math.min(box.height * paddingRatio, box.height / 2));
2585
+ const x = box.x + safePaddingX + Math.random() * Math.max(1, box.width - safePaddingX * 2);
2586
+ const y = box.y + safePaddingY + Math.random() * Math.max(1, box.height - safePaddingY * 2);
2587
+ return { x, y };
2588
+ };
2589
+ var resolveElement = async (page, target, { throwOnMissing = true } = {}) => {
2590
+ if (target == null) return null;
2591
+ let element = target;
2592
+ if (typeof target === "string") {
2593
+ element = await page.$(target);
2594
+ }
2595
+ if (!element) {
2596
+ if (throwOnMissing) {
2597
+ throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${String(target)}`);
2598
+ }
2599
+ return null;
2600
+ }
2601
+ return element;
2602
+ };
2603
+ var waitJitter = (base, jitterPercent = 0.3) => delay2(jitterMs(base, jitterPercent));
2604
+
2605
+ // src/internals/humanize/mobile.js
2606
+ var logger7 = createInternalLogger("Humanize.Mobile");
2607
+ var initializedPages = /* @__PURE__ */ new WeakSet();
2608
+ var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
2609
+ var resolveViewport = (page) => page?.viewportSize?.() || { width: 390, height: 844 };
2610
+ var describeTarget = (target) => {
2611
+ if (target == null) return "Current Position";
2612
+ return typeof target === "string" ? target : "ElementHandle";
2613
+ };
2614
+ var clipBoxToViewport = (box, viewport) => {
2615
+ if (!box || !viewport) return box;
2616
+ const left = clamp(box.x, 0, viewport.width);
2617
+ const top = clamp(box.y, 0, viewport.height);
2618
+ const right = clamp(box.x + box.width, 0, viewport.width);
2619
+ const bottom = clamp(box.y + box.height, 0, viewport.height);
2620
+ if (right - left > 1 && bottom - top > 1) {
2621
+ return {
2622
+ x: left,
2623
+ y: top,
2624
+ width: right - left,
2625
+ height: bottom - top
2626
+ };
2627
+ }
2628
+ return box;
2629
+ };
2630
+ var checkElementVisibility = async (element) => {
2631
+ return element.evaluate((el) => {
2632
+ const targetStyle = window.getComputedStyle(el);
2633
+ if (!targetStyle || targetStyle.display === "none" || targetStyle.visibility === "hidden" || targetStyle.visibility === "collapse") {
2634
+ return { code: "NOT_INTERACTABLE", reason: "\u5143\u7D20\u4E0D\u53EF\u89C1", direction: "down" };
2635
+ }
2636
+ const rect = el.getBoundingClientRect();
2637
+ if (!rect || rect.width <= 0 || rect.height <= 0) {
2638
+ return { code: "ZERO_DIMENSIONS", reason: "\u5C3A\u5BF8\u4E3A\u96F6", direction: "down" };
2639
+ }
2640
+ const viewW = window.innerWidth;
2641
+ const viewH = window.innerHeight;
2642
+ const centerY = rect.top + rect.height / 2;
2643
+ let clipLeft = 0;
2644
+ let clipRight = viewW;
2645
+ let clipTop = 0;
2646
+ let clipBottom = viewH;
2647
+ let isFixed = false;
2648
+ for (let node = el; node && node !== document.body; node = node.parentElement) {
2649
+ const style = window.getComputedStyle(node);
2650
+ if (style && (style.position === "fixed" || style.position === "sticky")) {
2651
+ isFixed = true;
2652
+ break;
2653
+ }
2654
+ }
2655
+ for (let node = el.parentElement; node && node !== document.body; node = node.parentElement) {
2656
+ const style = window.getComputedStyle(node);
2657
+ if (!style) continue;
2658
+ const clipsY = ["auto", "scroll", "overlay", "hidden", "clip"].includes(style.overflowY);
2659
+ const clipsX = ["auto", "scroll", "overlay", "hidden", "clip"].includes(style.overflowX);
2660
+ if (!clipsX && !clipsY) continue;
2661
+ const nodeRect = node.getBoundingClientRect();
2662
+ if (!nodeRect || nodeRect.width <= 0 || nodeRect.height <= 0) continue;
2663
+ if (clipsX) {
2664
+ clipLeft = Math.max(clipLeft, nodeRect.left);
2665
+ clipRight = Math.min(clipRight, nodeRect.right);
2666
+ }
2667
+ if (clipsY) {
2668
+ clipTop = Math.max(clipTop, nodeRect.top);
2669
+ clipBottom = Math.min(clipBottom, nodeRect.bottom);
2670
+ }
2671
+ }
2672
+ const visibleLeft = Math.max(clipLeft, Math.min(clipRight, rect.left));
2673
+ const visibleRight = Math.max(clipLeft, Math.min(clipRight, rect.right));
2674
+ const visibleTop = Math.max(clipTop, Math.min(clipBottom, rect.top));
2675
+ const visibleBottom = Math.max(clipTop, Math.min(clipBottom, rect.bottom));
2676
+ const visibleWidth = visibleRight - visibleLeft;
2677
+ const visibleHeight = visibleBottom - visibleTop;
2678
+ const cx = visibleLeft + visibleWidth / 2;
2679
+ const cy = visibleTop + visibleHeight / 2;
2680
+ if (visibleWidth <= 1 || visibleHeight <= 1) {
2681
+ return {
2682
+ code: "OUT_OF_VIEWPORT",
2683
+ reason: "\u4E0D\u5728\u89C6\u53E3\u5185",
2684
+ direction: centerY < clipTop ? "up" : "down",
2685
+ cy: centerY,
2686
+ viewH,
2687
+ isFixed
2688
+ };
2689
+ }
2690
+ const interactiveSelector = [
2691
+ "button",
2692
+ '[role="button"]',
2693
+ "a[href]",
2694
+ "label",
2695
+ "input",
2696
+ "textarea",
2697
+ "select",
2698
+ "summary",
2699
+ '[contenteditable="true"]',
2700
+ '[tabindex]:not([tabindex="-1"])'
2701
+ ].join(",");
2702
+ const targetInteractive = typeof el.closest === "function" ? el.closest(interactiveSelector) : null;
2703
+ const sameInteractiveTarget = (pointElement) => {
2704
+ if (!pointElement) return false;
2705
+ if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
2706
+ return true;
2707
+ }
2708
+ if (!targetInteractive || typeof pointElement.closest !== "function") {
2709
+ return false;
2710
+ }
2711
+ return pointElement.closest(interactiveSelector) === targetInteractive;
2712
+ };
2713
+ const describeElement = (node) => {
2714
+ if (!node) return null;
2715
+ const className = typeof node.className === "string" ? node.className : node.className && typeof node.className.baseVal === "string" ? node.className.baseVal : "";
2716
+ const rect2 = node.getBoundingClientRect?.();
2717
+ const style = window.getComputedStyle(node);
2718
+ return {
2719
+ tag: node.tagName,
2720
+ id: node.id || "",
2721
+ className,
2722
+ isFixed: Boolean(style && (style.position === "fixed" || style.position === "sticky")),
2723
+ top: rect2 ? rect2.top : null,
2724
+ bottom: rect2 ? rect2.bottom : null,
2725
+ left: rect2 ? rect2.left : null,
2726
+ right: rect2 ? rect2.right : null
2727
+ };
2728
+ };
2729
+ const samplePoints = [
2730
+ { x: cx, y: cy },
2731
+ { x: visibleLeft + Math.min(8, Math.max(1, visibleWidth * 0.25)), y: cy },
2732
+ { x: visibleRight - Math.min(8, Math.max(1, visibleWidth * 0.25)), y: cy },
2733
+ { x: cx, y: visibleTop + Math.min(8, Math.max(1, visibleHeight * 0.25)) },
2734
+ { x: cx, y: visibleBottom - Math.min(8, Math.max(1, visibleHeight * 0.25)) }
2735
+ ];
2736
+ let obstruction = null;
2737
+ for (const point of samplePoints) {
2738
+ const pointElement = document.elementFromPoint(point.x, point.y);
2739
+ if (sameInteractiveTarget(pointElement)) {
2740
+ return { code: "VISIBLE", isFixed };
2741
+ }
2742
+ obstruction = obstruction || describeElement(pointElement);
2743
+ }
2744
+ if (obstruction) {
2745
+ return {
2746
+ code: "OBSTRUCTED",
2747
+ reason: "\u88AB\u906E\u6321",
2748
+ direction: cy > viewH / 2 ? "down" : "up",
2749
+ obstruction,
2750
+ cy,
2751
+ viewH,
2752
+ isFixed
2753
+ };
2754
+ }
2755
+ return { code: "VISIBLE", isFixed };
2756
+ });
2757
+ };
2758
+ var resolveSafeTapPoint = async (element) => {
2759
+ return element.evaluate((el) => {
2760
+ const rect = el.getBoundingClientRect();
2761
+ if (!rect || rect.width <= 0 || rect.height <= 0) {
2762
+ return null;
2763
+ }
2764
+ const viewW = window.innerWidth;
2765
+ const viewH = window.innerHeight;
2766
+ let clipLeft = 0;
2767
+ let clipRight = viewW;
2768
+ let clipTop = 0;
2769
+ let clipBottom = viewH;
2770
+ for (let node = el.parentElement; node && node !== document.body; node = node.parentElement) {
2771
+ const style = window.getComputedStyle(node);
2772
+ if (!style) continue;
2773
+ const clipsX = ["auto", "scroll", "overlay", "hidden", "clip"].includes(style.overflowX);
2774
+ const clipsY = ["auto", "scroll", "overlay", "hidden", "clip"].includes(style.overflowY);
2775
+ if (!clipsX && !clipsY) continue;
2776
+ const nodeRect = node.getBoundingClientRect();
2777
+ if (!nodeRect || nodeRect.width <= 0 || nodeRect.height <= 0) continue;
2778
+ if (clipsX) {
2779
+ clipLeft = Math.max(clipLeft, nodeRect.left);
2780
+ clipRight = Math.min(clipRight, nodeRect.right);
2781
+ }
2782
+ if (clipsY) {
2783
+ clipTop = Math.max(clipTop, nodeRect.top);
2784
+ clipBottom = Math.min(clipBottom, nodeRect.bottom);
2785
+ }
2786
+ }
2787
+ const visibleLeft = Math.max(clipLeft, Math.min(clipRight, rect.left));
2788
+ const visibleRight = Math.max(clipLeft, Math.min(clipRight, rect.right));
2789
+ const visibleTop = Math.max(clipTop, Math.min(clipBottom, rect.top));
2790
+ const visibleBottom = Math.max(clipTop, Math.min(clipBottom, rect.bottom));
2791
+ const visibleWidth = visibleRight - visibleLeft;
2792
+ const visibleHeight = visibleBottom - visibleTop;
2793
+ if (visibleWidth <= 1 || visibleHeight <= 1) {
2794
+ return null;
2795
+ }
2796
+ const interactiveSelector = [
2797
+ "button",
2798
+ '[role="button"]',
2799
+ "a[href]",
2800
+ "label",
2801
+ "input",
2802
+ "textarea",
2803
+ "select",
2804
+ "summary",
2805
+ '[contenteditable="true"]',
2806
+ '[tabindex]:not([tabindex="-1"])'
2807
+ ].join(",");
2808
+ const targetInteractive = typeof el.closest === "function" ? el.closest(interactiveSelector) : null;
2809
+ const sameInteractiveTarget = (pointElement) => {
2810
+ if (!pointElement) return false;
2811
+ if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
2812
+ return true;
2813
+ }
2814
+ if (!targetInteractive || typeof pointElement.closest !== "function") {
2815
+ return false;
2816
+ }
2817
+ return pointElement.closest(interactiveSelector) === targetInteractive;
2818
+ };
2819
+ const cx = visibleLeft + visibleWidth / 2;
2820
+ const cy = visibleTop + visibleHeight / 2;
2821
+ const smallX = Math.min(12, Math.max(2, visibleWidth * 0.18));
2822
+ const smallY = Math.min(12, Math.max(2, visibleHeight * 0.18));
2823
+ const points = [
2824
+ { x: cx, y: cy },
2825
+ { x: visibleLeft + smallX, y: visibleTop + smallY },
2826
+ { x: visibleRight - smallX, y: visibleTop + smallY },
2827
+ { x: visibleLeft + smallX, y: visibleBottom - smallY },
2828
+ { x: visibleRight - smallX, y: visibleBottom - smallY },
2829
+ { x: cx, y: visibleTop + Math.min(10, Math.max(2, visibleHeight * 0.2)) },
2830
+ { x: cx, y: visibleBottom - Math.min(10, Math.max(2, visibleHeight * 0.2)) },
2831
+ { x: visibleLeft + Math.min(10, Math.max(2, visibleWidth * 0.2)), y: cy },
2832
+ { x: visibleRight - Math.min(10, Math.max(2, visibleWidth * 0.2)), y: cy }
2833
+ ];
2834
+ const safePoints = points.filter((point) => {
2835
+ const pointElement = document.elementFromPoint(point.x, point.y);
2836
+ return sameInteractiveTarget(pointElement);
2837
+ });
2838
+ const candidates = safePoints.length ? safePoints : points;
2839
+ const chosen = candidates[Math.floor(Math.random() * candidates.length)];
2840
+ if (!chosen) return null;
2841
+ return {
2842
+ x: chosen.x,
2843
+ y: chosen.y
2844
+ };
2845
+ });
2846
+ };
2847
+ var getScrollableRect = async (element) => {
2848
+ return element.evaluate((el) => {
2849
+ const isScrollable = (node) => {
2850
+ const style = window.getComputedStyle(node);
2851
+ if (!style) return false;
2852
+ const overflowY = style.overflowY;
2853
+ if (!["auto", "scroll", "overlay"].includes(overflowY)) return false;
2854
+ return node.scrollHeight > node.clientHeight + 1;
2855
+ };
2856
+ let current = el;
2857
+ while (current && current !== document.body) {
2858
+ if (isScrollable(current)) {
2859
+ const rect = current.getBoundingClientRect();
2860
+ if (rect && rect.width > 0 && rect.height > 0) {
2861
+ return {
2862
+ x: rect.x,
2863
+ y: rect.y,
2864
+ width: rect.width,
2865
+ height: rect.height
2866
+ };
2867
+ }
2868
+ }
2869
+ current = current.parentElement;
2870
+ }
2871
+ return null;
2872
+ });
2873
+ };
2874
+ var scrollScrollableAncestor = async (element, deltaY) => {
2875
+ return element.evaluate((el, amount) => {
2876
+ const isScrollable = (node) => {
2877
+ const style = window.getComputedStyle(node);
2878
+ if (!style) return false;
2879
+ const overflowY = style.overflowY;
2880
+ if (!["auto", "scroll", "overlay"].includes(overflowY)) return false;
2881
+ return node.scrollHeight > node.clientHeight + 1;
2882
+ };
2883
+ let current = el;
2884
+ while (current && current !== document.body) {
2885
+ if (isScrollable(current)) {
2886
+ const beforeTop2 = current.scrollTop;
2887
+ current.scrollTop = beforeTop2 + amount;
2888
+ return {
2889
+ scroller: true,
2890
+ moved: current.scrollTop !== beforeTop2,
2891
+ scrollTop: current.scrollTop
2892
+ };
2893
+ }
2894
+ current = current.parentElement;
2895
+ }
2896
+ const beforeTop = window.scrollY;
2897
+ window.scrollBy(0, amount);
2898
+ return {
2899
+ scroller: null,
2900
+ moved: window.scrollY !== beforeTop,
2901
+ scrollTop: window.scrollY
2902
+ };
2903
+ }, deltaY);
2904
+ };
2905
+ var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
2906
+ const viewport = resolveViewport(page);
2907
+ const rawRect = options.rect || null;
2908
+ const rect = rawRect ? {
2909
+ x: clamp(rawRect.x, 0, viewport.width),
2910
+ y: clamp(rawRect.y, 0, viewport.height),
2911
+ width: clamp(rawRect.width, 0, viewport.width),
2912
+ height: clamp(rawRect.height, 0, viewport.height)
2913
+ } : null;
2914
+ const area = rect && rect.width > 24 && rect.height > 48 ? {
2915
+ left: rect.x,
2916
+ right: Math.min(viewport.width, rect.x + rect.width),
2917
+ top: rect.y,
2918
+ bottom: Math.min(viewport.height, rect.y + rect.height)
2919
+ } : {
2920
+ left: 0,
2921
+ right: viewport.width,
2922
+ top: 0,
2923
+ bottom: viewport.height
2924
+ };
2925
+ const areaWidth = Math.max(1, area.right - area.left);
2926
+ const areaHeight = Math.max(1, area.bottom - area.top);
2927
+ const maxDistance = rect ? Math.max(60, areaHeight * 0.72) : Math.max(120, viewport.height * 0.72);
2928
+ const distance = clamp(Math.abs(deltaY), Math.min(80, maxDistance), maxDistance);
2929
+ const direction = deltaY >= 0 ? 1 : -1;
2930
+ const startX = clamp(
2931
+ area.left + areaWidth * (0.45 + Math.random() * 0.1),
2932
+ 24,
2933
+ viewport.width - 24
2934
+ );
2935
+ const startY = direction > 0 ? clamp(area.top + areaHeight * (0.72 + Math.random() * 0.1), area.top + 24, area.bottom - 16) : clamp(area.top + areaHeight * (0.28 + Math.random() * 0.1), area.top + 16, area.bottom - 24);
2936
+ const endY = clamp(startY - direction * distance, Math.max(16, area.top + 12), Math.min(viewport.height - 16, area.bottom - 12));
2937
+ const steps = Math.max(4, Math.round(Number(options.steps || 6)));
2938
+ const durationMs = jitterMs(options.durationMs || 320, 0.35);
2939
+ let client = null;
2940
+ const scrollBefore = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
2941
+ try {
2942
+ if (page.context && typeof page.context().newCDPSession === "function") {
2943
+ client = await page.context().newCDPSession(page);
2944
+ }
2945
+ if (!client) throw new Error("CDP session unavailable");
2946
+ await client.send("Input.synthesizeScrollGesture", {
2947
+ x: startX,
2948
+ y: startY,
2949
+ yDistance: -direction * distance,
2950
+ xOverscroll: (Math.random() - 0.5) * 4,
2951
+ yOverscroll: (Math.random() - 0.5) * 8,
2952
+ speed: 700 + Math.round(Math.random() * 350),
2953
+ gestureSourceType: "touch"
2954
+ });
2955
+ await waitJitter(160, 0.35);
2956
+ const scrollAfterSynth = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
2957
+ if (scrollBefore && scrollAfterSynth && (Math.abs(scrollAfterSynth.y - scrollBefore.y) > 2 || Math.abs(scrollAfterSynth.x - scrollBefore.x) > 2)) {
2958
+ return true;
2959
+ }
2960
+ await client.send("Input.dispatchTouchEvent", {
2961
+ type: "touchStart",
2962
+ touchPoints: [{ x: startX, y: startY, id: 1 }]
2963
+ });
2964
+ for (let i = 1; i <= steps; i += 1) {
2965
+ const progress = i / steps;
2966
+ const eased = 1 - Math.pow(1 - progress, 2);
2967
+ const x = startX + (Math.random() - 0.5) * 3;
2968
+ const y = startY + (endY - startY) * eased + (Math.random() - 0.5) * 5;
2969
+ await waitJitter(durationMs / steps, 0.25);
2970
+ await client.send("Input.dispatchTouchEvent", {
2971
+ type: "touchMove",
2972
+ touchPoints: [{ x, y, id: 1 }]
2973
+ });
2974
+ }
2975
+ await client.send("Input.dispatchTouchEvent", {
2976
+ type: "touchEnd",
2977
+ touchPoints: []
2978
+ });
2979
+ await waitJitter(120, 0.35);
2980
+ const scrollAfterTouch = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
2981
+ if (scrollBefore && scrollAfterTouch && Math.abs(scrollAfterTouch.y - scrollBefore.y) <= 2 && Math.abs(scrollAfterTouch.x - scrollBefore.x) <= 2) {
2982
+ await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
2983
+ await waitJitter(120, 0.35);
2984
+ }
2985
+ return true;
2986
+ } catch (error) {
2987
+ logger7.debug(`touch swipe fallback: ${error?.message || error}`);
2988
+ try {
2989
+ await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
2990
+ await waitJitter(120, 0.35);
2991
+ return true;
2992
+ } catch {
2993
+ await page.mouse.wheel(0, deltaY);
2994
+ await waitJitter(120, 0.35);
2995
+ return true;
2996
+ }
2997
+ } finally {
2998
+ if (client && typeof client.detach === "function") {
2999
+ try {
3000
+ await client.detach();
3001
+ } catch {
3002
+ }
3003
+ }
3004
+ }
3005
+ };
3006
+ var tapPoint = async (page, point) => {
3007
+ if (page.touchscreen && typeof page.touchscreen.tap === "function") {
3008
+ await page.touchscreen.tap(point.x, point.y);
3009
+ return;
3010
+ }
3011
+ await page.mouse.click(point.x, point.y);
3012
+ };
3013
+ var MobileHumanize = {
3014
+ jitterMs,
3015
+ async initializeCursor(page) {
3016
+ if (initializedPages.has(page)) return;
3017
+ initializedPages.add(page);
3018
+ logger7.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
3019
+ },
3020
+ async humanMove(page, target) {
3021
+ logger7.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
3022
+ if (typeof target === "string" || target && typeof target.boundingBox === "function") {
3023
+ const element = await resolveElement(page, target, { throwOnMissing: false });
3024
+ if (!element) {
3025
+ return false;
3026
+ }
3027
+ }
3028
+ await waitJitter(80, 0.4);
3029
+ return true;
3030
+ },
3031
+ async humanScroll(page, target, options = {}) {
3032
+ const {
3033
+ maxSteps = 12,
3034
+ minStep = 180,
3035
+ maxStep = 520,
3036
+ maxDurationMs = maxSteps * 280 + 1200,
3037
+ throwOnMissing = false
3038
+ } = options;
3039
+ const targetDesc = describeTarget(target);
3040
+ logger7.start("humanScroll", `target=${targetDesc}`);
3041
+ const element = await resolveElement(page, target, { throwOnMissing });
3042
+ if (!element) {
3043
+ logger7.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${targetDesc}`);
3044
+ return { element: null, didScroll: false, restore: null };
3045
+ }
3046
+ const startTime = Date.now();
3047
+ let didScroll = false;
3048
+ for (let i = 0; i < maxSteps; i += 1) {
3049
+ const status = await checkElementVisibility(element);
3050
+ if (status.code === "VISIBLE") {
3051
+ if (status.isFixed) {
3052
+ logger7.info("humanScroll | fixed/sticky \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3053
+ } else {
3054
+ logger7.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
3055
+ }
3056
+ logger7.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
3057
+ return { element, didScroll, restore: null };
3058
+ }
3059
+ if (status.code === "ZERO_DIMENSIONS" || status.code === "NOT_INTERACTABLE") {
3060
+ logger7.warn(`humanScroll | \u5143\u7D20\u4E0D\u53EF\u6EDA\u52A8\u81F3\u53EF\u70B9\u51FB\u72B6\u6001: ${status.reason || status.code}`);
3061
+ return { element, didScroll, restore: null };
3062
+ }
3063
+ const scrollRect = await getScrollableRect(element);
3064
+ if (!scrollRect && status.isFixed && status.code === "OBSTRUCTED") {
3065
+ logger7.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
3066
+ return { element, didScroll, restore: null };
3067
+ }
3068
+ if (Date.now() - startTime > maxDurationMs) {
3069
+ logger7.warn(`humanScroll | mobile timeout (${maxDurationMs}ms, status=${status.code}, direction=${status.direction || "unknown"}, fixed=${Boolean(status.isFixed)})`);
3070
+ return { element, didScroll, restore: null };
3071
+ }
3072
+ const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
3073
+ const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;
3074
+ logger7.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason || status.code} ${status.direction ? `(${status.direction})` : ""}`);
3075
+ const distance = stepMin + Math.random() * Math.max(1, stepMax - stepMin);
3076
+ let deltaY = status.direction === "up" ? -distance : distance;
3077
+ if (status.code === "OBSTRUCTED") {
3078
+ if (status.obstruction?.isFixed && status.obstruction.top != null) {
3079
+ const obstructionMiddle = (Number(status.obstruction.top || 0) + Number(status.obstruction.bottom || status.obstruction.top || 0)) / 2;
3080
+ const visibleMiddle = scrollRect ? scrollRect.y + scrollRect.height / 2 : status.viewH / 2;
3081
+ deltaY = obstructionMiddle < visibleMiddle ? -distance : distance;
3082
+ } else {
3083
+ const halfY = scrollRect ? scrollRect.y + scrollRect.height / 2 : status.viewH / 2;
3084
+ deltaY = status.cy > halfY ? distance : -distance;
3085
+ }
3086
+ }
3087
+ const beforeWindowState = scrollRect ? await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })) : null;
3088
+ const beforeState = scrollRect ? await element.evaluate((el) => {
3089
+ const isScrollable = (node) => {
3090
+ const style = window.getComputedStyle(node);
3091
+ if (!style) return false;
3092
+ const overflowY = style.overflowY;
3093
+ if (!["auto", "scroll", "overlay"].includes(overflowY)) return false;
3094
+ return node.scrollHeight > node.clientHeight + 1;
3095
+ };
3096
+ let current = el;
3097
+ while (current && current !== document.body) {
3098
+ if (isScrollable(current)) {
3099
+ return {
3100
+ kind: "element",
3101
+ top: current.scrollTop,
3102
+ left: current.scrollLeft
3103
+ };
3104
+ }
3105
+ current = current.parentElement;
3106
+ }
3107
+ return { kind: "window", top: window.scrollY, left: window.scrollX };
3108
+ }) : null;
3109
+ await dispatchTouchSwipe(page, deltaY, { rect: scrollRect });
3110
+ if (scrollRect && beforeWindowState) {
3111
+ const afterWindowState = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY }));
3112
+ if (Math.abs(afterWindowState.x - beforeWindowState.x) > 2 || Math.abs(afterWindowState.y - beforeWindowState.y) > 2) {
3113
+ await page.evaluate((state) => window.scrollTo(state.x, state.y), beforeWindowState);
3114
+ logger7.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
3115
+ }
3116
+ }
3117
+ if (scrollRect && beforeState) {
3118
+ const afterState = await element.evaluate((el) => {
3119
+ const isScrollable = (node) => {
3120
+ const style = window.getComputedStyle(node);
3121
+ if (!style) return false;
3122
+ const overflowY = style.overflowY;
3123
+ if (!["auto", "scroll", "overlay"].includes(overflowY)) return false;
3124
+ return node.scrollHeight > node.clientHeight + 1;
3125
+ };
3126
+ let current = el;
3127
+ while (current && current !== document.body) {
3128
+ if (isScrollable(current)) {
3129
+ return {
3130
+ kind: "element",
3131
+ top: current.scrollTop,
3132
+ left: current.scrollLeft
3133
+ };
3134
+ }
3135
+ current = current.parentElement;
3136
+ }
3137
+ return { kind: "window", top: window.scrollY, left: window.scrollX };
3138
+ });
3139
+ const topDelta = Number(afterState.top || 0) - Number(beforeState.top || 0);
3140
+ const leftDelta = Number(afterState.left || 0) - Number(beforeState.left || 0);
3141
+ const expectedDelta = Number(deltaY || 0);
3142
+ const moved = beforeState.kind !== afterState.kind || Math.abs(topDelta) > 2 || Math.abs(leftDelta) > 2;
3143
+ if (!moved) {
3144
+ const fallback = await scrollScrollableAncestor(element, deltaY);
3145
+ logger7.debug(`humanScroll | \u5BB9\u5668\u89E6\u6478\u65E0\u6548\uFF0C\u76F4\u63A5\u6EDA\u52A8 fallback=${fallback.scroller ? "ancestor" : "window"} top=${Math.round(fallback.scrollTop || 0)}`);
3146
+ } else if (beforeState.kind === afterState.kind && Math.abs(expectedDelta) > 24 && Math.sign(topDelta || expectedDelta) === Math.sign(expectedDelta) && Math.abs(topDelta) < Math.min(Math.abs(expectedDelta) * 0.45, 96)) {
3147
+ const residualDelta = expectedDelta - topDelta;
3148
+ if (Math.sign(residualDelta) === Math.sign(expectedDelta) && Math.abs(residualDelta) > 24) {
3149
+ const fallback = await scrollScrollableAncestor(element, residualDelta);
3150
+ logger7.debug(`humanScroll | \u5BB9\u5668\u89E6\u6478\u8DDD\u79BB\u4E0D\u8DB3\uFF0C\u8865\u507F\u6EDA\u52A8 fallback=${fallback.scroller ? "ancestor" : "window"} top=${Math.round(fallback.scrollTop || 0)}`);
3151
+ }
3152
+ }
3153
+ }
3154
+ didScroll = true;
3155
+ }
3156
+ try {
3157
+ await element.scrollIntoViewIfNeeded?.();
3158
+ await waitJitter(80, 0.3);
3159
+ const finalStatus = await checkElementVisibility(element);
3160
+ if (finalStatus.code === "VISIBLE") {
3161
+ logger7.info("humanScroll | \u539F\u751F scrollIntoViewIfNeeded \u515C\u5E95\u6210\u529F");
3162
+ logger7.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
3163
+ return { element, didScroll: true, restore: null };
3164
+ }
3165
+ } catch (fallbackError) {
3166
+ logger7.debug(`humanScroll | native fallback failed: ${fallbackError?.message || fallbackError}`);
3167
+ }
3168
+ logger7.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
3169
+ return { element, didScroll, restore: null };
3170
+ },
3171
+ async humanClick(page, target, options = {}) {
3172
+ const {
3173
+ reactionDelay = 220,
3174
+ throwOnMissing = true,
3175
+ scrollIfNeeded = true
3176
+ } = options;
3177
+ const targetDesc = describeTarget(target);
3178
+ logger7.start("humanClick", `target=${targetDesc}`);
3179
+ try {
3180
+ if (target == null) {
3181
+ const viewport = resolveViewport(page);
3182
+ await waitJitter(reactionDelay, 0.45);
3183
+ await tapPoint(page, {
3184
+ x: viewport.width * (0.45 + Math.random() * 0.1),
3185
+ y: viewport.height * (0.48 + Math.random() * 0.12)
3186
+ });
3187
+ logger7.success("humanClick", "Tapped current position");
3188
+ return true;
3189
+ }
3190
+ const element = await resolveElement(page, target, { throwOnMissing });
3191
+ if (!element) {
3192
+ logger7.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
3193
+ return false;
3194
+ }
3195
+ if (scrollIfNeeded) {
3196
+ await MobileHumanize.humanScroll(page, element, { throwOnMissing });
3197
+ }
3198
+ const status = await checkElementVisibility(element).catch(() => null);
3199
+ if (status && (status.code === "ZERO_DIMENSIONS" || status.code === "NOT_INTERACTABLE")) {
3200
+ const message = `\u5143\u7D20\u4E0D\u53EF\u70B9\u51FB: ${status.reason || status.code}`;
3201
+ if (throwOnMissing) throw new Error(message);
3202
+ logger7.warn(`humanClick: ${message}\uFF0C\u8DF3\u8FC7\u70B9\u51FB`);
3203
+ return false;
3204
+ }
3205
+ const box = await element.boundingBox();
3206
+ if (!box) {
3207
+ if (throwOnMissing) throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
3208
+ logger7.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
3209
+ return false;
3210
+ }
3211
+ await waitJitter(reactionDelay, 0.45);
3212
+ const safePoint = await resolveSafeTapPoint(element).catch(() => null);
3213
+ const tapTarget = safePoint || randomPointInBox(clipBoxToViewport(box, resolveViewport(page)), 0.2);
3214
+ await tapPoint(page, tapTarget);
3215
+ await waitJitter(120, 0.35);
3216
+ logger7.success("humanClick");
3217
+ return true;
3218
+ } catch (error) {
3219
+ logger7.fail("humanClick", error);
3220
+ throw error;
3221
+ }
3222
+ },
3223
+ async randomSleep(baseMs, jitterPercent = 0.3) {
3224
+ await waitJitter(baseMs, jitterPercent);
3225
+ },
3226
+ async simulateGaze(page, baseDurationMs = 2500) {
3227
+ const durationMs = jitterMs(baseDurationMs, 0.4);
3228
+ const startTime = Date.now();
3229
+ while (Date.now() - startTime < durationMs) {
3230
+ if (Math.random() < 0.28) {
3231
+ const distance = 70 + Math.random() * 120;
3232
+ await dispatchTouchSwipe(page, Math.random() < 0.7 ? distance : -distance, {
3233
+ durationMs: 180,
3234
+ steps: 4
3235
+ });
3236
+ } else {
3237
+ await waitJitter(420, 0.55);
3238
+ }
3239
+ }
3240
+ },
3241
+ async humanType(page, selector, text, options = {}) {
3242
+ const {
3243
+ baseDelay = 160,
3244
+ pauseProbability = 0.08,
3245
+ pauseBase = 700
3246
+ } = options;
3247
+ await MobileHumanize.humanClick(page, selector, { scrollIfNeeded: true });
3248
+ await waitJitter(220, 0.45);
3249
+ for (let i = 0; i < String(text).length; i += 1) {
3250
+ const char = String(text)[i];
3251
+ const charDelay = /[,.!?;:,。!?;:]/.test(char) ? jitterMs(baseDelay * 1.45, 0.4) : jitterMs(char === " " ? baseDelay * 0.65 : baseDelay, 0.4);
3252
+ await page.keyboard.type(char);
3253
+ await waitJitter(charDelay, 0.15);
3254
+ if (Math.random() < pauseProbability && i < String(text).length - 1) {
3255
+ await waitJitter(pauseBase, 0.5);
3256
+ }
3257
+ }
3258
+ },
3259
+ async humanClear(page, selector) {
3260
+ const locator = page.locator(selector);
3261
+ await MobileHumanize.humanClick(page, locator, { scrollIfNeeded: true });
3262
+ await waitJitter(160, 0.4);
3263
+ await locator.evaluate((el) => {
3264
+ if ("value" in el) {
3265
+ el.value = "";
3266
+ el.dispatchEvent(new Event("input", { bubbles: true }));
3267
+ el.dispatchEvent(new Event("change", { bubbles: true }));
3268
+ return;
3269
+ }
3270
+ el.textContent = "";
3271
+ el.dispatchEvent(new Event("input", { bubbles: true }));
3272
+ });
3273
+ },
3274
+ async warmUpBrowsing(page, baseDuration = 3500) {
3275
+ const durationMs = jitterMs(baseDuration, 0.4);
3276
+ const startTime = Date.now();
3277
+ while (Date.now() - startTime < durationMs) {
3278
+ const action = Math.random();
3279
+ if (action < 0.5) {
3280
+ await dispatchTouchSwipe(page, 120 + Math.random() * 220, {
3281
+ durationMs: 240,
3282
+ steps: 5
3283
+ });
3284
+ } else if (action < 0.7) {
3285
+ await dispatchTouchSwipe(page, -(80 + Math.random() * 160), {
3286
+ durationMs: 220,
3287
+ steps: 4
3288
+ });
3289
+ } else {
3290
+ await waitJitter(560, 0.55);
3291
+ }
3292
+ }
3293
+ },
3294
+ async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
3295
+ const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
3296
+ const actualDistance = jitterMs(distance, 0.15);
3297
+ const sign = direction === "down" ? 1 : -1;
3298
+ for (let i = 0; i < steps; i += 1) {
3299
+ const factor = 1 - i / steps * 0.45;
3300
+ await dispatchTouchSwipe(page, actualDistance / steps * factor * sign, {
3301
+ durationMs: 150 + i * 20,
3302
+ steps: 4
3303
+ });
3304
+ }
3305
+ }
3306
+ };
3307
+
3308
+ // src/humanize.js
3309
+ var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
3310
+ var resolveDelegate = (page) => {
3311
+ return resolveDeviceFromPage(page) === Device.Mobile ? MobileHumanize : Humanize;
3312
+ };
3313
+ var callDelegate = (method, page, args) => {
3314
+ const delegate = resolveDelegate(page);
3315
+ return delegate[method](page, ...args);
3316
+ };
3317
+ var Humanize2 = {
3318
+ jitterMs(base, jitterPercent = 0.3) {
3319
+ return Humanize.jitterMs(base, jitterPercent);
3320
+ },
3321
+ initializeCursor(page) {
3322
+ return callDelegate("initializeCursor", page, []);
3323
+ },
3324
+ humanMove(page, target) {
3325
+ return callDelegate("humanMove", page, [target]);
3326
+ },
3327
+ humanScroll(page, target, options = {}) {
3328
+ return callDelegate("humanScroll", page, [target, options]);
3329
+ },
3330
+ humanClick(page, target, options = {}) {
3331
+ return callDelegate("humanClick", page, [target, options]);
3332
+ },
3333
+ randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
3334
+ if (pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function") {
3335
+ const delegate = resolveDelegate(pageOrBaseMs);
3336
+ return delegate.randomSleep(maybeBaseMs, maybeJitterPercent);
3337
+ }
3338
+ return Humanize.randomSleep(pageOrBaseMs, maybeBaseMs);
3339
+ },
3340
+ simulateGaze(page, baseDurationMs = 2500) {
3341
+ return callDelegate("simulateGaze", page, [baseDurationMs]);
3342
+ },
3343
+ humanType(page, selector, text, options = {}) {
3344
+ return callDelegate("humanType", page, [selector, text, options]);
3345
+ },
3346
+ humanClear(page, selector) {
3347
+ return callDelegate("humanClear", page, [selector]);
3348
+ },
3349
+ warmUpBrowsing(page, baseDuration = 3500) {
3350
+ return callDelegate("warmUpBrowsing", page, [baseDuration]);
3351
+ },
3352
+ naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
3353
+ return callDelegate("naturalScroll", page, [direction, distance, baseSteps]);
3354
+ }
3355
+ };
3356
+
2527
3357
  // src/launch.js
2528
3358
  import { execFileSync } from "node:child_process";
2529
3359
  import { FingerprintGenerator } from "fingerprint-generator";
@@ -2610,7 +3440,7 @@ var ByPass = {
2610
3440
  };
2611
3441
 
2612
3442
  // src/launch.js
2613
- var logger7 = createInternalLogger("Launch");
3443
+ var logger8 = createInternalLogger("Launch");
2614
3444
  var REQUEST_HOOK_FLAG = Symbol("playwright-toolkit-request-hook");
2615
3445
  var injectedContexts = /* @__PURE__ */ new WeakSet();
2616
3446
  var browserMajorVersionCache = /* @__PURE__ */ new Map();
@@ -2662,20 +3492,29 @@ var detectBrowserMajorVersion = (launcher) => {
2662
3492
  });
2663
3493
  detectedVersion = parseChromeMajorVersion(rawVersion);
2664
3494
  } catch (error) {
2665
- logger7.warn(`\u8BFB\u53D6\u6D4F\u89C8\u5668\u7248\u672C\u5931\u8D25: ${error?.message || error}`);
3495
+ logger8.warn(`\u8BFB\u53D6\u6D4F\u89C8\u5668\u7248\u672C\u5931\u8D25: ${error?.message || error}`);
2666
3496
  }
2667
3497
  browserMajorVersionCache.set(executablePath, detectedVersion);
2668
3498
  return detectedVersion;
2669
3499
  };
2670
- var buildFingerprintGenerator = ({ locale, browserMajorVersion }) => {
3500
+ var resolveRuntimeDevice = (runtimeState = {}) => normalizeDevice(runtimeState?.device);
3501
+ var resolveCoreDevice = (core = {}) => {
3502
+ const raw = String(core?.device || "").trim().toLowerCase();
3503
+ if (raw === Device.Mobile) return Device.Mobile;
3504
+ if (raw === Device.Desktop) return Device.Desktop;
3505
+ return "";
3506
+ };
3507
+ var buildFingerprintGenerator = ({ locale, browserMajorVersion, device }) => {
2671
3508
  return new FingerprintGenerator(
2672
3509
  AntiCheat.getFingerprintGeneratorOptions({
2673
3510
  locale,
2674
- browserMajorVersion
3511
+ browserMajorVersion,
3512
+ device
2675
3513
  })
2676
3514
  );
2677
3515
  };
2678
3516
  var buildReplayableBrowserProfile = (runtimeState, launcher) => {
3517
+ const device = resolveRuntimeDevice(runtimeState);
2679
3518
  if (!runtimeState || !RuntimeEnv.hasLoginState(runtimeState)) {
2680
3519
  return { runtimeState, browserProfileCore: null };
2681
3520
  }
@@ -2685,29 +3524,34 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
2685
3524
  const locale = DEFAULT_LOCALE;
2686
3525
  const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);
2687
3526
  const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);
2688
- const needsRebuild = !browserProfileCore?.fingerprint || Object.keys(browserProfileCore.fingerprint || {}).length === 0 || currentBrowserMajorVersion > 0 && storedBrowserMajorVersion > 0 && storedBrowserMajorVersion !== currentBrowserMajorVersion;
3527
+ const storedDevice = resolveCoreDevice(browserProfileCore);
3528
+ const needsDeviceRebuild = storedDevice ? storedDevice !== device : device === Device.Mobile;
3529
+ const needsRebuild = !browserProfileCore?.fingerprint || Object.keys(browserProfileCore.fingerprint || {}).length === 0 || needsDeviceRebuild || currentBrowserMajorVersion > 0 && storedBrowserMajorVersion > 0 && storedBrowserMajorVersion !== currentBrowserMajorVersion;
2689
3530
  if (needsRebuild) {
2690
3531
  const generator = buildFingerprintGenerator({
2691
3532
  locale,
2692
- browserMajorVersion: currentBrowserMajorVersion
3533
+ browserMajorVersion: currentBrowserMajorVersion,
3534
+ device
2693
3535
  });
2694
3536
  const fingerprint = generator.getFingerprint();
2695
3537
  const fingerprintBrowserMajorVersion = parseChromeMajorVersion(fingerprint?.fingerprint?.navigator?.userAgent || "");
2696
3538
  browserProfileCore = {
2697
3539
  fingerprint,
3540
+ device,
2698
3541
  timezone_id: timezoneId,
2699
3542
  locale,
2700
3543
  browser_major_version: currentBrowserMajorVersion > 0 ? currentBrowserMajorVersion : fingerprintBrowserMajorVersion,
2701
3544
  schema_version: DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION
2702
3545
  };
2703
3546
  nextState = RuntimeEnv.setBrowserProfileCore(nextState, browserProfileCore);
2704
- logger7.info(
2705
- `\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || "-")} | version=${browserProfileCore.browser_major_version || "-"} | timezone=${timezoneId}`
3547
+ logger8.info(
3548
+ `\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || "-")} | device=${device} | version=${browserProfileCore.browser_major_version || "-"} | timezone=${timezoneId}`
2706
3549
  );
2707
3550
  return { runtimeState: nextState, browserProfileCore };
2708
3551
  }
2709
3552
  const normalizedBrowserProfileCore = {
2710
3553
  ...browserProfileCore,
3554
+ device,
2711
3555
  timezone_id: timezoneId,
2712
3556
  locale,
2713
3557
  schema_version: Number(browserProfileCore.schema_version || 0) > 0 ? Number(browserProfileCore.schema_version || 0) : DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION,
@@ -2723,6 +3567,35 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
2723
3567
  browserProfileCore: normalizedBrowserProfileCore
2724
3568
  };
2725
3569
  };
3570
+ var applyDevicePageOptions = (pageOptions = {}, { device = Device.Desktop, fingerprint = null } = {}) => {
3571
+ if (!pageOptions || typeof pageOptions !== "object") return;
3572
+ const resolvedDevice = normalizeDevice(device);
3573
+ const screen = fingerprint?.screen || {};
3574
+ const dpr = Number(screen.devicePixelRatio || 0);
3575
+ if (resolvedDevice === Device.Mobile) {
3576
+ pageOptions.isMobile = true;
3577
+ pageOptions.hasTouch = true;
3578
+ pageOptions.deviceScaleFactor = dpr > 0 ? dpr : 2;
3579
+ if (!pageOptions.viewport) {
3580
+ pageOptions.viewport = {
3581
+ width: Number(screen.width || 390),
3582
+ height: Number(screen.height || 844)
3583
+ };
3584
+ }
3585
+ if (!pageOptions.screen) {
3586
+ pageOptions.screen = {
3587
+ width: Number(screen.width || pageOptions.viewport.width || 390),
3588
+ height: Number(screen.height || pageOptions.viewport.height || 844)
3589
+ };
3590
+ }
3591
+ return;
3592
+ }
3593
+ pageOptions.isMobile = false;
3594
+ pageOptions.hasTouch = false;
3595
+ if (!pageOptions.deviceScaleFactor) {
3596
+ pageOptions.deviceScaleFactor = dpr > 0 ? dpr : 1;
3597
+ }
3598
+ };
2726
3599
  var buildReplayBrowserPoolOptions = (browserProfileCore) => {
2727
3600
  const fingerprintWithHeaders = browserProfileCore?.fingerprint;
2728
3601
  const fingerprint = fingerprintWithHeaders?.fingerprint;
@@ -2755,6 +3628,10 @@ var buildReplayBrowserPoolOptions = (browserProfileCore) => {
2755
3628
  if (browserProfileCore.timezone_id) {
2756
3629
  pageOptions.timezoneId = browserProfileCore.timezone_id;
2757
3630
  }
3631
+ applyDevicePageOptions(pageOptions, {
3632
+ device: browserProfileCore.device,
3633
+ fingerprint
3634
+ });
2758
3635
  }
2759
3636
  ],
2760
3637
  postPageCreateHooks: [
@@ -2784,6 +3661,7 @@ var Launch = {
2784
3661
  postNavigationHooks = [],
2785
3662
  runtimeState = null
2786
3663
  } = normalizedOptions;
3664
+ const device = resolveRuntimeDevice(runtimeState);
2787
3665
  const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);
2788
3666
  const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
2789
3667
  const proxyMeter = enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
@@ -2812,18 +3690,18 @@ var Launch = {
2812
3690
  upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
2813
3691
  } catch {
2814
3692
  }
2815
- logger7.info(
3693
+ logger8.info(
2816
3694
  `[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
2817
3695
  );
2818
- logger7.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
3696
+ logger8.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
2819
3697
  } else if (enableByPassLogger && enableProxy && !launchProxy) {
2820
- logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
2821
- logger7.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
3698
+ logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
3699
+ logger8.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
2822
3700
  } else if (enableByPassLogger && !enableProxy && proxyUrl) {
2823
- logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
2824
- logger7.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
3701
+ logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
3702
+ logger8.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
2825
3703
  } else if (enableByPassLogger) {
2826
- logger7.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
3704
+ logger8.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
2827
3705
  }
2828
3706
  const onPageCreated = (page) => {
2829
3707
  const recommendedGotoOptions = {
@@ -2845,7 +3723,7 @@ var Launch = {
2845
3723
  }
2846
3724
  if (!enableByPassLogger || byPassDomains.length === 0) return;
2847
3725
  if (!matched || !matched.rule) return;
2848
- logger7.info(`[\u76F4\u8FDE\u547D\u4E2D] \u89C4\u5219=${matched.rule.pattern} \u57DF\u540D=${matched.hostname} \u8D44\u6E90\u7C7B\u578B=${resourceType} \u65B9\u6CD5=${req.method()} \u5730\u5740=${requestUrl}`);
3726
+ logger8.info(`[\u76F4\u8FDE\u547D\u4E2D] \u89C4\u5219=${matched.rule.pattern} \u57DF\u540D=${matched.hostname} \u8D44\u6E90\u7C7B\u578B=${resourceType} \u65B9\u6CD5=${req.method()} \u5730\u5740=${requestUrl}`);
2849
3727
  };
2850
3728
  page.on("request", requestHandler);
2851
3729
  return recommendedGotoOptions;
@@ -2864,8 +3742,23 @@ var Launch = {
2864
3742
  browserPoolOptions: replayBrowserPoolOptions || {
2865
3743
  useFingerprints: true,
2866
3744
  fingerprintOptions: {
2867
- fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions()
2868
- }
3745
+ fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions({
3746
+ locale: launchLocale,
3747
+ device
3748
+ })
3749
+ },
3750
+ prePageCreateHooks: [
3751
+ (_pageId, _browserController, pageOptions = {}) => {
3752
+ applyDevicePageOptions(pageOptions, { device });
3753
+ if (launchLocale) {
3754
+ pageOptions.locale = launchLocale;
3755
+ }
3756
+ const timezoneId = AntiCheat.getBaseConfig().timezoneId;
3757
+ if (timezoneId) {
3758
+ pageOptions.timezoneId = timezoneId;
3759
+ }
3760
+ }
3761
+ ]
2869
3762
  },
2870
3763
  launchContext
2871
3764
  };
@@ -2888,7 +3781,7 @@ var Launch = {
2888
3781
  // src/live-view.js
2889
3782
  import express from "express";
2890
3783
  import { Actor } from "apify";
2891
- var logger8 = createInternalLogger("LiveView");
3784
+ var logger9 = createInternalLogger("LiveView");
2892
3785
  async function startLiveViewServer(liveViewKey) {
2893
3786
  const app = express();
2894
3787
  app.get("/", async (req, res) => {
@@ -2913,13 +3806,13 @@ async function startLiveViewServer(liveViewKey) {
2913
3806
  </html>
2914
3807
  `);
2915
3808
  } catch (error) {
2916
- logger8.fail("Live View Server", error);
3809
+ logger9.fail("Live View Server", error);
2917
3810
  res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
2918
3811
  }
2919
3812
  });
2920
3813
  const port = process.env.APIFY_CONTAINER_PORT || 4321;
2921
3814
  app.listen(port, () => {
2922
- logger8.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
3815
+ logger9.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
2923
3816
  });
2924
3817
  }
2925
3818
  async function takeLiveScreenshot(liveViewKey, page, logMessage) {
@@ -2927,10 +3820,10 @@ async function takeLiveScreenshot(liveViewKey, page, logMessage) {
2927
3820
  const buffer = await capturePageScreenshot(page, { type: "png" });
2928
3821
  await Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
2929
3822
  if (logMessage) {
2930
- logger8.info(`(\u622A\u56FE): ${logMessage}`);
3823
+ logger9.info(`(\u622A\u56FE): ${logMessage}`);
2931
3824
  }
2932
3825
  } catch (e) {
2933
- logger8.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
3826
+ logger9.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
2934
3827
  }
2935
3828
  }
2936
3829
  var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
@@ -3030,7 +3923,7 @@ var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
3030
3923
  };
3031
3924
 
3032
3925
  // src/internals/captcha/bytedance.js
3033
- var logger9 = createInternalLogger("Captcha");
3926
+ var logger10 = createInternalLogger("Captcha");
3034
3927
  var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
3035
3928
  apiType: "31234",
3036
3929
  maxRetries: 3,
@@ -3097,14 +3990,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
3097
3990
  if (!isContainerVisible) {
3098
3991
  return null;
3099
3992
  }
3100
- logger9.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
3993
+ logger10.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
3101
3994
  let iframeLocator = page.locator(options.iframeSelector).first();
3102
3995
  let isIframeVisible = await waitForVisible(
3103
3996
  iframeLocator,
3104
3997
  options.iframeVisibleTimeoutMs
3105
3998
  );
3106
3999
  if (!isIframeVisible) {
3107
- logger9.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
4000
+ logger10.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
3108
4001
  iframeLocator = captchaContainer.locator(options.iframeFallbackSelector).first();
3109
4002
  isIframeVisible = await waitForVisible(
3110
4003
  iframeLocator,
@@ -3114,7 +4007,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
3114
4007
  if (!isIframeVisible) {
3115
4008
  throw new Error("verifycenter iframe not found inside captcha container.");
3116
4009
  }
3117
- logger9.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
4010
+ logger10.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
3118
4011
  const frame = await resolveContentFrame(page, iframeLocator, options);
3119
4012
  if (!frame) {
3120
4013
  throw new Error("Failed to resolve verifycenter iframe content frame.");
@@ -3124,7 +4017,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
3124
4017
  var refreshCaptcha = async (page, frame, options) => {
3125
4018
  const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
3126
4019
  if (!clicked) {
3127
- logger9.warn("Refresh button not found.");
4020
+ logger10.warn("Refresh button not found.");
3128
4021
  return false;
3129
4022
  }
3130
4023
  await page.waitForTimeout(options.refreshWaitMs);
@@ -3165,18 +4058,18 @@ var waitForCaptchaChallengeReady = async (page, frame, options) => {
3165
4058
  const imageCount = await sourceImages.count().catch(() => 0);
3166
4059
  const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
3167
4060
  if (!isLoadingVisible && hasVisibleSourceImage) {
3168
- logger9.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
4061
+ logger10.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
3169
4062
  return;
3170
4063
  }
3171
4064
  if (hasErrorTextVisible) {
3172
- logger9.warn("\u9A8C\u8BC1\u7801\u9762\u677F\u51FA\u73B0\u7F51\u7EDC\u5F02\u5E38\u6587\u6848\uFF0C\u5C1D\u8BD5\u7ACB\u5373\u5237\u65B0\u9898\u76EE\u3002");
4065
+ logger10.warn("\u9A8C\u8BC1\u7801\u9762\u677F\u51FA\u73B0\u7F51\u7EDC\u5F02\u5E38\u6587\u6848\uFF0C\u5C1D\u8BD5\u7ACB\u5373\u5237\u65B0\u9898\u76EE\u3002");
3173
4066
  await refreshCaptcha(page, frame, options);
3174
4067
  refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3175
4068
  hasSeenLoading = false;
3176
4069
  continue;
3177
4070
  }
3178
4071
  if (!hasVisibleSourceImage && Date.now() >= refreshDeadline) {
3179
- logger9.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
4072
+ logger10.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
3180
4073
  await refreshCaptcha(page, frame, options);
3181
4074
  refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3182
4075
  hasSeenLoading = false;
@@ -3196,16 +4089,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
3196
4089
  ...options
3197
4090
  };
3198
4091
  if (!config.token) {
3199
- logger9.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
4092
+ logger10.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
3200
4093
  return false;
3201
4094
  }
3202
- logger9.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
4095
+ logger10.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
3203
4096
  for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
3204
- logger9.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
4097
+ logger10.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
3205
4098
  try {
3206
4099
  const captchaContext = await getVerifycenterCaptchaContext(page, config);
3207
4100
  if (!captchaContext) {
3208
- logger9.info("Captcha container is not visible anymore.");
4101
+ logger10.info("Captcha container is not visible anymore.");
3209
4102
  return true;
3210
4103
  }
3211
4104
  const { iframeLocator, frame } = captchaContext;
@@ -3220,16 +4113,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
3220
4113
  });
3221
4114
  const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
3222
4115
  if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
3223
- logger9.warn(
4116
+ logger10.warn(
3224
4117
  `\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\u3002code=${apiResponse?.code}, msg=${apiResponse?.msg || "unknown"}`
3225
4118
  );
3226
4119
  await refreshCaptcha(page, frame, config);
3227
4120
  continue;
3228
4121
  }
3229
- logger9.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
4122
+ logger10.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
3230
4123
  const dropTarget = await findCaptchaDropTarget(frame, config);
3231
4124
  if (!dropTarget) {
3232
- logger9.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
4125
+ logger10.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
3233
4126
  await refreshCaptcha(page, frame, config);
3234
4127
  continue;
3235
4128
  }
@@ -3252,31 +4145,31 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
3252
4145
  }
3253
4146
  const submitted = await clickCaptchaAction(frame, config.submitTexts, config).catch(() => false);
3254
4147
  if (!submitted) {
3255
- logger9.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
4148
+ logger10.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
3256
4149
  }
3257
4150
  await page.waitForTimeout(config.submitWaitMs);
3258
4151
  const stillVisible = await iframeLocator.isVisible({ timeout: config.containerVisibleTimeoutMs }).catch(() => false);
3259
4152
  if (!stillVisible) {
3260
- logger9.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
4153
+ logger10.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
3261
4154
  return true;
3262
4155
  }
3263
- logger9.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
4156
+ logger10.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
3264
4157
  await page.waitForTimeout(2e3);
3265
4158
  await refreshCaptcha(page, frame, config);
3266
4159
  } catch (error) {
3267
- logger9.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
4160
+ logger10.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
3268
4161
  }
3269
4162
  if (attempt < config.maxRetries) {
3270
4163
  await page.waitForTimeout(config.retryDelayBaseMs + attempt * config.retryDelayStepMs);
3271
4164
  }
3272
4165
  }
3273
- logger9.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
4166
+ logger10.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
3274
4167
  return false;
3275
4168
  }
3276
4169
  var sloveCaptcha = solveCaptcha;
3277
4170
 
3278
4171
  // src/chaptcha.js
3279
- var logger10 = createInternalLogger("Captcha");
4172
+ var logger11 = createInternalLogger("Captcha");
3280
4173
  var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
3281
4174
  token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
3282
4175
  apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
@@ -3363,7 +4256,7 @@ function useCaptchaMonitor(page, options) {
3363
4256
  };
3364
4257
  })();
3365
4258
  }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
3366
- logger10.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
4259
+ logger11.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
3367
4260
  cleanupFns.push(async () => {
3368
4261
  try {
3369
4262
  await page.evaluate((name) => {
@@ -3387,14 +4280,14 @@ function useCaptchaMonitor(page, options) {
3387
4280
  }
3388
4281
  };
3389
4282
  page.on("framenavigated", frameHandler);
3390
- logger10.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
4283
+ logger11.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
3391
4284
  cleanupFns.push(async () => {
3392
4285
  page.off("framenavigated", frameHandler);
3393
4286
  });
3394
4287
  }
3395
4288
  return {
3396
4289
  stop: async () => {
3397
- logger10.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
4290
+ logger11.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
3398
4291
  for (const fn of cleanupFns) {
3399
4292
  await fn();
3400
4293
  }
@@ -3433,7 +4326,7 @@ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
3433
4326
  );
3434
4327
  return strategy.sloveCaptcha(page, resolvedOptions, {
3435
4328
  callCaptchaRecognitionApi,
3436
- logger: logger10
4329
+ logger: logger11
3437
4330
  });
3438
4331
  }
3439
4332
  var Captcha = {
@@ -3444,7 +4337,7 @@ var Captcha = {
3444
4337
  // src/mutation.js
3445
4338
  import { createHash } from "node:crypto";
3446
4339
  import { v4 as uuidv42 } from "uuid";
3447
- var logger11 = createInternalLogger("Mutation");
4340
+ var logger12 = createInternalLogger("Mutation");
3448
4341
  var MUTATION_MONITOR_MODE = Object.freeze({
3449
4342
  Added: "added",
3450
4343
  Changed: "changed",
@@ -3477,14 +4370,14 @@ var Mutation = {
3477
4370
  const stableTime = options.stableTime ?? 5 * 1e3;
3478
4371
  const timeout = options.timeout ?? 120 * 1e3;
3479
4372
  const onMutation = options.onMutation;
3480
- logger11.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
4373
+ logger12.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
3481
4374
  if (initialTimeout > 0) {
3482
4375
  const selectorQuery = selectorList.join(",");
3483
4376
  try {
3484
4377
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3485
- logger11.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
4378
+ logger12.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3486
4379
  } catch (e) {
3487
- logger11.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
4380
+ logger12.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3488
4381
  throw e;
3489
4382
  }
3490
4383
  }
@@ -3500,7 +4393,7 @@ var Mutation = {
3500
4393
  return "__CONTINUE__";
3501
4394
  }
3502
4395
  });
3503
- logger11.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
4396
+ logger12.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
3504
4397
  } catch (e) {
3505
4398
  }
3506
4399
  }
@@ -3615,9 +4508,9 @@ var Mutation = {
3615
4508
  { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
3616
4509
  );
3617
4510
  if (result.mutationCount === 0 && result.stableTime === 0) {
3618
- logger11.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
4511
+ logger12.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3619
4512
  }
3620
- logger11.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
4513
+ logger12.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3621
4514
  return result;
3622
4515
  },
3623
4516
  /**
@@ -3789,22 +4682,22 @@ var Mutation = {
3789
4682
  return "__CONTINUE__";
3790
4683
  }
3791
4684
  };
3792
- logger11.start(
4685
+ logger12.start(
3793
4686
  "waitForStableAcrossRoots",
3794
4687
  `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
3795
4688
  );
3796
4689
  if (initialTimeout > 0) {
3797
4690
  try {
3798
4691
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3799
- logger11.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
4692
+ logger12.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3800
4693
  } catch (e) {
3801
- logger11.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
4694
+ logger12.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3802
4695
  throw e;
3803
4696
  }
3804
4697
  }
3805
4698
  let state = await buildState();
3806
4699
  if (!state?.hasMatched) {
3807
- logger11.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
4700
+ logger12.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3808
4701
  return { mutationCount: 0, stableTime: 0, wasPaused: false };
3809
4702
  }
3810
4703
  let mutationCount = 0;
@@ -3841,7 +4734,7 @@ var Mutation = {
3841
4734
  if (lastState.snapshotKey !== lastSnapshotKey) {
3842
4735
  lastSnapshotKey = lastState.snapshotKey;
3843
4736
  mutationCount += 1;
3844
- logger11.info(
4737
+ logger12.info(
3845
4738
  `waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
3846
4739
  );
3847
4740
  const signal = await invokeMutationCallback({
@@ -3854,7 +4747,7 @@ var Mutation = {
3854
4747
  continue;
3855
4748
  }
3856
4749
  if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
3857
- logger11.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
4750
+ logger12.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3858
4751
  return {
3859
4752
  mutationCount,
3860
4753
  stableTime: waitForStableTime,
@@ -3881,7 +4774,7 @@ var Mutation = {
3881
4774
  const onMutation = options.onMutation;
3882
4775
  const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
3883
4776
  const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
3884
- logger11.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
4777
+ logger12.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
3885
4778
  const monitorKey = generateKey("pk_mon");
3886
4779
  const callbackName = generateKey("pk_mon_cb");
3887
4780
  const cleanerName = generateKey("pk_mon_clean");
@@ -4024,7 +4917,7 @@ var Mutation = {
4024
4917
  return total;
4025
4918
  };
4026
4919
  }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
4027
- logger11.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
4920
+ logger12.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
4028
4921
  return {
4029
4922
  stop: async () => {
4030
4923
  let totalMutations = 0;
@@ -4037,7 +4930,7 @@ var Mutation = {
4037
4930
  }, cleanerName);
4038
4931
  } catch (e) {
4039
4932
  }
4040
- logger11.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
4933
+ logger12.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
4041
4934
  return { totalMutations };
4042
4935
  }
4043
4936
  };
@@ -4906,7 +5799,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
4906
5799
  };
4907
5800
  var getDefaultBaseLogger = () => createBaseLogger("");
4908
5801
  var Logger = {
4909
- setLogger: (logger15) => setDefaultLogger(logger15),
5802
+ setLogger: (logger16) => setDefaultLogger(logger16),
4910
5803
  info: (message) => getDefaultBaseLogger().info(message),
4911
5804
  success: (message) => getDefaultBaseLogger().success(message),
4912
5805
  warning: (message) => getDefaultBaseLogger().warning(message),
@@ -4914,14 +5807,14 @@ var Logger = {
4914
5807
  error: (message) => getDefaultBaseLogger().error(message),
4915
5808
  debug: (message) => getDefaultBaseLogger().debug(message),
4916
5809
  start: (message) => getDefaultBaseLogger().start(message),
4917
- useTemplate: (logger15) => {
4918
- if (logger15) return createTemplateLogger(createBaseLogger("", logger15));
5810
+ useTemplate: (logger16) => {
5811
+ if (logger16) return createTemplateLogger(createBaseLogger("", logger16));
4919
5812
  return createTemplateLogger();
4920
5813
  }
4921
5814
  };
4922
5815
 
4923
5816
  // src/share.js
4924
- import delay2 from "delay";
5817
+ import delay3 from "delay";
4925
5818
 
4926
5819
  // src/internals/watermarkify.js
4927
5820
  var DEFAULT_TIMEZONE_OFFSET = 8;
@@ -4980,7 +5873,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
4980
5873
  ];
4981
5874
  var cachedStripLogoSrcPromise = null;
4982
5875
  var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
4983
- var logger12 = createInternalLogger("Watermarkify");
5876
+ var logger13 = createInternalLogger("Watermarkify");
4984
5877
  var normalizeText = (value) => String(value || "").trim();
4985
5878
  var toInline = (value, maxLen = 200) => {
4986
5879
  const text = normalizeText(value);
@@ -5222,9 +6115,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
5222
6115
  location: toInline(resolved.location, 80)
5223
6116
  };
5224
6117
  if (enrichment.ip || enrichment.location) {
5225
- logger12.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
6118
+ logger13.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
5226
6119
  } else {
5227
- logger12.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
6120
+ logger13.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
5228
6121
  }
5229
6122
  return enrichment;
5230
6123
  } finally {
@@ -5408,12 +6301,12 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height }) => {
5408
6301
  };
5409
6302
  var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}) => {
5410
6303
  if (!page || typeof page.context !== "function") {
5411
- logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
6304
+ logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
5412
6305
  return buffer;
5413
6306
  }
5414
6307
  const renderScope = await openProbePage(page);
5415
6308
  if (!renderScope?.page) {
5416
- logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
6309
+ logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
5417
6310
  return buffer;
5418
6311
  }
5419
6312
  try {
@@ -5456,13 +6349,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
5456
6349
  fullPage: true,
5457
6350
  animations: "disabled"
5458
6351
  }).catch((error) => {
5459
- logger12.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6352
+ logger13.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
5460
6353
  return null;
5461
6354
  });
5462
6355
  if (Buffer.isBuffer(composed) && composed.length > 0) {
5463
6356
  return composed;
5464
6357
  }
5465
- logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
6358
+ logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
5466
6359
  return buffer;
5467
6360
  } finally {
5468
6361
  await renderScope.close().catch(() => {
@@ -5475,7 +6368,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
5475
6368
  }
5476
6369
  const probeScope = await openProbePage(page);
5477
6370
  if (!probeScope?.page) {
5478
- logger12.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
6371
+ logger13.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
5479
6372
  return null;
5480
6373
  }
5481
6374
  const timeoutMs = Math.max(
@@ -5484,12 +6377,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
5484
6377
  );
5485
6378
  try {
5486
6379
  const probePage = probeScope.page;
5487
- logger12.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
6380
+ logger13.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
5488
6381
  const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
5489
6382
  waitUntil: "commit",
5490
6383
  timeout: timeoutMs
5491
6384
  }).catch((error) => {
5492
- logger12.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
6385
+ logger13.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
5493
6386
  return null;
5494
6387
  });
5495
6388
  const status = response && typeof response.status === "function" ? response.status() : 0;
@@ -5511,13 +6404,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
5511
6404
  }
5512
6405
  const parsed = parseIpIpJsonResponse(rawText);
5513
6406
  if (parsed?.ip || parsed?.location) {
5514
- logger12.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
6407
+ logger13.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
5515
6408
  return parsed;
5516
6409
  }
5517
- logger12.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
6410
+ logger13.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
5518
6411
  return null;
5519
6412
  } catch (error) {
5520
- logger12.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
6413
+ logger13.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
5521
6414
  return null;
5522
6415
  } finally {
5523
6416
  await probeScope.close().catch(() => {
@@ -5531,10 +6424,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5531
6424
  ip: toInline(options.ip, 80),
5532
6425
  location: toInline(options.location, 80)
5533
6426
  };
5534
- logger12.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
6427
+ logger13.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
5535
6428
  if (!merged.ip || !merged.location) {
5536
6429
  if (cached?.ip || cached?.location) {
5537
- logger12.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
6430
+ logger13.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
5538
6431
  }
5539
6432
  fillEnrichment(merged, cached);
5540
6433
  }
@@ -5558,15 +6451,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5558
6451
  "x-geo-country"
5559
6452
  ]), 80);
5560
6453
  if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
5561
- logger12.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
6454
+ logger13.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
5562
6455
  merged.location = headerLocation || merged.location;
5563
6456
  }
5564
6457
  }
5565
6458
  writeCachedEnrichment(page, merged);
5566
6459
  if (merged.ip || merged.location) {
5567
- logger12.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
6460
+ logger13.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
5568
6461
  } else {
5569
- logger12.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
6462
+ logger13.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
5570
6463
  }
5571
6464
  return merged;
5572
6465
  };
@@ -6234,7 +7127,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6234
7127
  }
6235
7128
  const imageInfo = readImageInfo(buffer);
6236
7129
  if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
6237
- logger12.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
7130
+ logger13.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
6238
7131
  return buffer;
6239
7132
  }
6240
7133
  const overlaySvg = buildWatermarkifySvg(meta, imageInfo.width, imageInfo.height);
@@ -6246,7 +7139,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6246
7139
 
6247
7140
  // src/internals/screenshot-compression.js
6248
7141
  import { Jimp, JimpMime, ResizeStrategy } from "jimp";
6249
- var logger13 = createInternalLogger("ScreenshotCompression");
7142
+ var logger14 = createInternalLogger("ScreenshotCompression");
6250
7143
  var DEFAULT_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
6251
7144
  var DEFAULT_SCREENSHOT_OUTPUT_TYPE = "jpeg";
6252
7145
  var DEFAULT_SCREENSHOT_QUALITY = 0.72;
@@ -6365,18 +7258,18 @@ var compressScreenshotBufferToBase64 = async (buffer, compression) => {
6365
7258
  return buffer.toString("base64");
6366
7259
  }
6367
7260
  const result = await compressScreenshotBuffer(buffer, compression).catch((error) => {
6368
- logger13.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
7261
+ logger14.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
6369
7262
  return null;
6370
7263
  });
6371
7264
  if (!result?.buffer) {
6372
7265
  return buffer.toString("base64");
6373
7266
  }
6374
7267
  if (result.withinLimit) {
6375
- logger13.info(
7268
+ logger14.info(
6376
7269
  `captureScreen \u5DF2\u538B\u7F29: ${originalBytes} -> ${result.bytes} bytes, format=${result.format}, quality=${result.quality}, scale=${result.scale}, size=${result.width}x${result.height}`
6377
7270
  );
6378
7271
  } else {
6379
- logger13.warning(
7272
+ logger14.warning(
6380
7273
  `captureScreen \u538B\u7F29\u540E\u4ECD\u8D85\u8FC7\u76EE\u6807: ${originalBytes} -> ${result.bytes} bytes, maxBytes=${compression.maxBytes}, format=${result.format}, quality=${result.quality}, scale=${result.scale}`
6381
7274
  );
6382
7275
  }
@@ -6384,7 +7277,7 @@ var compressScreenshotBufferToBase64 = async (buffer, compression) => {
6384
7277
  };
6385
7278
 
6386
7279
  // src/share.js
6387
- var logger14 = createInternalLogger("Share");
7280
+ var logger15 = createInternalLogger("Share");
6388
7281
  var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
6389
7282
  var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
6390
7283
  var DEFAULT_POLL_INTERVAL_MS = 120;
@@ -6521,7 +7414,7 @@ var createDomShareMonitor = async (page, options = {}) => {
6521
7414
  const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
6522
7415
  const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
6523
7416
  let matched = false;
6524
- logger14.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
7417
+ logger15.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
6525
7418
  const monitor = await Mutation.useMonitor(page, selectors, {
6526
7419
  mode,
6527
7420
  onMutation: (context = {}) => {
@@ -6539,12 +7432,12 @@ ${text}`;
6539
7432
  });
6540
7433
  }
6541
7434
  if (mutationCount <= 5 || mutationCount % 50 === 0) {
6542
- logger14.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
7435
+ logger15.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
6543
7436
  }
6544
7437
  const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
6545
7438
  if (!candidate) return;
6546
7439
  matched = true;
6547
- logger14.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
7440
+ logger15.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
6548
7441
  if (onMatch) {
6549
7442
  onMatch({
6550
7443
  link: candidate,
@@ -6560,7 +7453,7 @@ ${text}`;
6560
7453
  return {
6561
7454
  stop: async () => {
6562
7455
  const result = await monitor.stop();
6563
- logger14.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
7456
+ logger15.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
6564
7457
  return result;
6565
7458
  }
6566
7459
  };
@@ -6600,8 +7493,8 @@ var Share = {
6600
7493
  if (share.mode === "response" && apiMatchers.length === 0) {
6601
7494
  throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
6602
7495
  }
6603
- logger14.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
6604
- logger14.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
7496
+ logger15.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
7497
+ logger15.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
6605
7498
  const stats = {
6606
7499
  actionTimedOut: false,
6607
7500
  domMutationCount: 0,
@@ -6626,7 +7519,7 @@ var Share = {
6626
7519
  link: validated,
6627
7520
  payloadText: String(payloadText || "")
6628
7521
  };
6629
- logger14.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
7522
+ logger15.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
6630
7523
  return true;
6631
7524
  };
6632
7525
  const resolveResponseCandidate = (responseText) => {
@@ -6661,7 +7554,7 @@ var Share = {
6661
7554
  try {
6662
7555
  await monitor.stop();
6663
7556
  } catch (error) {
6664
- logger14.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
7557
+ logger15.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6665
7558
  }
6666
7559
  };
6667
7560
  const onResponse = async (response) => {
@@ -6674,29 +7567,29 @@ var Share = {
6674
7567
  stats.responseSampleUrls.push(url);
6675
7568
  }
6676
7569
  if (stats.responseObserved <= 5) {
6677
- logger14.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
7570
+ logger15.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
6678
7571
  }
6679
7572
  if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
6680
7573
  stats.responseMatched += 1;
6681
7574
  stats.lastMatchedUrl = url;
6682
- logger14.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
7575
+ logger15.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
6683
7576
  const text = await response.text();
6684
7577
  const hit = resolveResponseCandidate(text);
6685
7578
  if (!hit?.link) {
6686
7579
  if (stats.responseMatched <= 3) {
6687
- logger14.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
7580
+ logger15.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
6688
7581
  }
6689
7582
  return;
6690
7583
  }
6691
7584
  stats.responseResolved += 1;
6692
- logger14.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
7585
+ logger15.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
6693
7586
  setCandidate("response", hit.link, hit.payloadText);
6694
7587
  } catch (error) {
6695
- logger14.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
7588
+ logger15.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
6696
7589
  }
6697
7590
  };
6698
7591
  if (share.mode === "dom") {
6699
- logger14.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
7592
+ logger15.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
6700
7593
  domMonitor = await createDomShareMonitor(page, {
6701
7594
  prefix: share.prefix,
6702
7595
  selectors: domSelectors,
@@ -6711,14 +7604,14 @@ var Share = {
6711
7604
  });
6712
7605
  }
6713
7606
  if (share.mode === "response") {
6714
- logger14.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
7607
+ logger15.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
6715
7608
  page.on("response", onResponse);
6716
7609
  }
6717
7610
  const deadline = Date.now() + timeoutMs;
6718
7611
  const getRemainingMs = () => Math.max(0, deadline - Date.now());
6719
7612
  try {
6720
7613
  const actionTimeout = getRemainingMs();
6721
- logger14.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
7614
+ logger15.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
6722
7615
  if (actionTimeout > 0) {
6723
7616
  let timer = null;
6724
7617
  let actionError = null;
@@ -6732,21 +7625,21 @@ var Share = {
6732
7625
  const actionResult = await Promise.race([actionPromise, timeoutPromise]);
6733
7626
  if (timer) clearTimeout(timer);
6734
7627
  if (actionResult === "__ACTION_ERROR__") {
6735
- logger14.fail("captureLink.performActions", actionError);
7628
+ logger15.fail("captureLink.performActions", actionError);
6736
7629
  throw actionError;
6737
7630
  }
6738
7631
  if (actionResult === "__ACTION_TIMEOUT__") {
6739
7632
  stats.actionTimedOut = true;
6740
- logger14.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
7633
+ logger15.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
6741
7634
  } else {
6742
- logger14.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
7635
+ logger15.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
6743
7636
  }
6744
7637
  }
6745
7638
  let nextProgressLogTs = Date.now() + 3e3;
6746
7639
  while (true) {
6747
7640
  const selected = share.mode === "dom" ? candidates.dom : candidates.response;
6748
7641
  if (selected?.link) {
6749
- logger14.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
7642
+ logger15.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
6750
7643
  return {
6751
7644
  link: selected.link,
6752
7645
  payloadText: selected.payloadText,
@@ -6758,19 +7651,19 @@ var Share = {
6758
7651
  if (remaining <= 0) break;
6759
7652
  const now = Date.now();
6760
7653
  if (now >= nextProgressLogTs) {
6761
- logger14.info(
7654
+ logger15.info(
6762
7655
  `captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
6763
7656
  );
6764
7657
  nextProgressLogTs = now + 5e3;
6765
7658
  }
6766
- await delay2(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
7659
+ await delay3(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
6767
7660
  }
6768
7661
  if (share.mode === "response" && stats.responseMatched === 0) {
6769
- logger14.warning(
7662
+ logger15.warning(
6770
7663
  `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
6771
7664
  );
6772
7665
  }
6773
- logger14.warning(
7666
+ logger15.warning(
6774
7667
  `captureLink \u8D85\u65F6\u672A\u62FF\u5230\u94FE\u63A5: mode=${share.mode}, actionTimedOut=${stats.actionTimedOut}, domMutationCount=${stats.domMutationCount}, responseObserved=${stats.responseObserved}, responseMatched=${stats.responseMatched}, lastMatchedUrl=${stats.lastMatchedUrl || "none"}`
6775
7668
  );
6776
7669
  return {
@@ -6782,7 +7675,7 @@ var Share = {
6782
7675
  } finally {
6783
7676
  if (share.mode === "response") {
6784
7677
  page.off("response", onResponse);
6785
- logger14.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
7678
+ logger15.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
6786
7679
  }
6787
7680
  await stopDomMonitor();
6788
7681
  }
@@ -6834,7 +7727,7 @@ var Share = {
6834
7727
  width: originalViewport.width,
6835
7728
  height: targetHeight
6836
7729
  });
6837
- await delay2(1e3);
7730
+ await delay3(1e3);
6838
7731
  const capturedAt = /* @__PURE__ */ new Date();
6839
7732
  const rawBuffer = await capturePageScreenshot(page, {
6840
7733
  fullPage: true,
@@ -6875,7 +7768,7 @@ var usePlaywrightToolKit = () => {
6875
7768
  return {
6876
7769
  ApifyKit,
6877
7770
  AntiCheat,
6878
- Humanize,
7771
+ Humanize: Humanize2,
6879
7772
  Launch,
6880
7773
  LiveView,
6881
7774
  Constants: constants_exports,