@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.cjs CHANGED
@@ -39,8 +39,10 @@ var constants_exports = {};
39
39
  __export(constants_exports, {
40
40
  ActorInfo: () => ActorInfo,
41
41
  Code: () => Code,
42
+ Device: () => Device,
42
43
  PresetOfLiveViewKey: () => PresetOfLiveViewKey,
43
- Status: () => Status
44
+ Status: () => Status,
45
+ normalizeDevice: () => normalizeDevice
44
46
  });
45
47
  var Code = {
46
48
  Success: 0,
@@ -56,6 +58,17 @@ var Status = {
56
58
  Failed: "FAILED"
57
59
  };
58
60
  var PresetOfLiveViewKey = "LIVE_VIEW_SCREENSHOT";
61
+ var Device = Object.freeze({
62
+ Desktop: "desktop",
63
+ Mobile: "mobile"
64
+ });
65
+ var normalizeDevice = (value, fallback = Device.Desktop) => {
66
+ const normalizedFallback = String(fallback || "").trim().toLowerCase() === Device.Mobile ? Device.Mobile : Device.Desktop;
67
+ const raw = String(value || "").trim().toLowerCase();
68
+ if (raw === Device.Mobile) return Device.Mobile;
69
+ if (raw === Device.Desktop) return Device.Desktop;
70
+ return normalizedFallback;
71
+ };
59
72
  var createActorInfo = (info) => {
60
73
  const normalizeDomain = (value) => {
61
74
  if (!value) return "";
@@ -133,12 +146,14 @@ var createActorInfo = (info) => {
133
146
  const domain = normalizeDomain(info.domain);
134
147
  const path2 = normalizePath(info.path);
135
148
  const share = normalizeShare2(info.share);
149
+ const device = normalizeDevice(info.device);
136
150
  return {
137
151
  ...info,
138
152
  protocol,
139
153
  domain,
140
154
  path: path2,
141
155
  share,
156
+ device,
142
157
  get icon() {
143
158
  if (info.icon) return info.icon;
144
159
  return buildIcon(this);
@@ -190,6 +205,7 @@ var ActorInfo = {
190
205
  name: "\u8C46\u5305",
191
206
  domain: "www.doubao.com",
192
207
  path: "/",
208
+ device: Device.Mobile,
193
209
  share: {
194
210
  mode: "response",
195
211
  prefix: "https://www.doubao.com/thread/",
@@ -205,6 +221,7 @@ var ActorInfo = {
205
221
  name: "DeepSeek",
206
222
  domain: "chat.deepseek.com",
207
223
  path: "/",
224
+ device: Device.Mobile,
208
225
  share: {
209
226
  mode: "response",
210
227
  prefix: "https://chat.deepseek.com/share/",
@@ -361,18 +378,18 @@ var fallbackLog = {
361
378
  error: (...args) => console.error(...args),
362
379
  debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
363
380
  };
364
- var resolveLogMethod = (logger15, name) => {
365
- if (logger15 && typeof logger15[name] === "function") {
366
- return logger15[name].bind(logger15);
381
+ var resolveLogMethod = (logger16, name) => {
382
+ if (logger16 && typeof logger16[name] === "function") {
383
+ return logger16[name].bind(logger16);
367
384
  }
368
- if (name === "warning" && logger15 && typeof logger15.warn === "function") {
369
- return logger15.warn.bind(logger15);
385
+ if (name === "warning" && logger16 && typeof logger16.warn === "function") {
386
+ return logger16.warn.bind(logger16);
370
387
  }
371
388
  return fallbackLog[name];
372
389
  };
373
390
  var defaultLogger = null;
374
- var setDefaultLogger = (logger15) => {
375
- defaultLogger = logger15;
391
+ var setDefaultLogger = (logger16) => {
392
+ defaultLogger = logger16;
376
393
  };
377
394
  var resolveLogger = (explicitLogger) => {
378
395
  if (explicitLogger && typeof explicitLogger.info === "function") {
@@ -399,8 +416,8 @@ var colorize = (text, color) => {
399
416
  var createBaseLogger = (prefix = "", explicitLogger) => {
400
417
  const name = prefix ? String(prefix) : "";
401
418
  const dispatch = (methodName, icon, message, color) => {
402
- const logger15 = resolveLogger(explicitLogger);
403
- const logFn = resolveLogMethod(logger15, methodName);
419
+ const logger16 = resolveLogger(explicitLogger);
420
+ const logFn = resolveLogMethod(logger16, methodName);
404
421
  const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
405
422
  const line = formatLine(name, icon, message);
406
423
  const coloredLine = colorize(line, color);
@@ -1000,6 +1017,12 @@ var PageRuntimeStateKey = "__playwright_toolkit_runtime_state__";
1000
1017
  var BROWSER_PROFILE_SCHEMA_VERSION = 1;
1001
1018
  var rememberedRuntimeState = null;
1002
1019
  var isPlainObject = (value) => value && typeof value === "object" && !Array.isArray(value);
1020
+ var normalizeKnownDevice = (value) => {
1021
+ const raw = String(value || "").trim().toLowerCase();
1022
+ if (raw === Device.Mobile) return Device.Mobile;
1023
+ if (raw === Device.Desktop) return Device.Desktop;
1024
+ return "";
1025
+ };
1003
1026
  var deepClone = (value) => {
1004
1027
  if (value == null) return value;
1005
1028
  try {
@@ -1351,6 +1374,10 @@ var normalizeObservedBrowserProfile = (value) => {
1351
1374
  var normalizeBrowserProfileCore = (value) => {
1352
1375
  const source = isPlainObject(value) ? value : {};
1353
1376
  const profile = {};
1377
+ const device = normalizeKnownDevice(source.device);
1378
+ if (device) {
1379
+ profile.device = device;
1380
+ }
1354
1381
  if (isPlainObject(source.fingerprint) && Object.keys(source.fingerprint).length > 0) {
1355
1382
  profile.fingerprint = deepClone(source.fingerprint);
1356
1383
  }
@@ -1408,9 +1435,11 @@ var mergeBrowserProfilePayload = (target = {}, source = {}) => {
1408
1435
  if (Object.keys(mergedCore).length === 0 && Object.keys(incomingCore).length > 0) {
1409
1436
  mergedCore = incomingCore;
1410
1437
  } else if (Object.keys(incomingCore).length > 0) {
1438
+ const currentDevice = normalizeKnownDevice(currentCore.device);
1439
+ const incomingDevice = normalizeKnownDevice(incomingCore.device);
1411
1440
  const currentVersion = Number(currentCore.browser_major_version || 0);
1412
1441
  const incomingVersion = Number(incomingCore.browser_major_version || 0);
1413
- if (currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {
1442
+ if (incomingDevice && currentDevice !== incomingDevice || currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {
1414
1443
  mergedCore = incomingCore;
1415
1444
  }
1416
1445
  }
@@ -1461,8 +1490,13 @@ var normalizeRuntimeState = (source = {}, actor = "") => {
1461
1490
  }
1462
1491
  return RuntimeEnv.parseInput(source, actor);
1463
1492
  };
1493
+ var resolveInputDevice = (input = {}, runtime2 = {}, actor = "") => {
1494
+ const actorDevice = ActorInfo?.[actor]?.device;
1495
+ return normalizeDevice(actorDevice ?? input?.device ?? runtime2?.device);
1496
+ };
1464
1497
  var RuntimeEnv = {
1465
1498
  tryParseJSON,
1499
+ normalizeDevice,
1466
1500
  normalizeCookies,
1467
1501
  normalizeLocalStorage,
1468
1502
  normalizeSessionStorage,
@@ -1488,6 +1522,7 @@ var RuntimeEnv = {
1488
1522
  parseInput(input = {}, actor = "") {
1489
1523
  const runtime2 = tryParseJSON(input?.runtime) || {};
1490
1524
  const resolvedActor = String(actor || input?.actor || "").trim();
1525
+ const device = resolveInputDevice(input, runtime2, resolvedActor);
1491
1526
  const query = String(input?.query || "").trim();
1492
1527
  const cookies = normalizeCookies(runtime2?.cookies);
1493
1528
  const cookieMap = buildCookieMap(cookies);
@@ -1507,6 +1542,7 @@ var RuntimeEnv = {
1507
1542
  }
1508
1543
  const state = {
1509
1544
  actor: resolvedActor,
1545
+ device,
1510
1546
  runtime: normalizedRuntime,
1511
1547
  envId,
1512
1548
  query,
@@ -1552,7 +1588,10 @@ var RuntimeEnv = {
1552
1588
  },
1553
1589
  setBrowserProfileCore(source = {}, core = {}, actor = "") {
1554
1590
  const state = normalizeRuntimeState(source, actor);
1555
- const normalizedCore = normalizeBrowserProfileCore(core);
1591
+ const normalizedCore = normalizeBrowserProfileCore({
1592
+ ...core,
1593
+ device: normalizeKnownDevice(core?.device) || state.device
1594
+ });
1556
1595
  state.browserProfileCore = normalizedCore;
1557
1596
  state.browserProfile = buildBrowserProfilePayload(normalizedCore, state.browserProfileObserved);
1558
1597
  if (Object.keys(state.browserProfile).length > 0) {
@@ -2027,15 +2066,25 @@ var DEFAULT_LAUNCH_ARGS = [
2027
2066
  "--disable-setuid-sandbox",
2028
2067
  "--window-position=0,0"
2029
2068
  ];
2030
- function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0 } = {}) {
2069
+ function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0, device = Device.Desktop } = {}) {
2070
+ const resolvedDevice = normalizeDevice(device);
2031
2071
  const normalizedBrowserMajorVersion = Number(browserMajorVersion || 0);
2032
2072
  const browserDescriptor = normalizedBrowserMajorVersion > 0 ? [{ name: "chrome", minVersion: normalizedBrowserMajorVersion, maxVersion: normalizedBrowserMajorVersion }] : [{ name: "chrome", minVersion: 110 }];
2033
- return {
2073
+ const options = {
2034
2074
  browsers: browserDescriptor,
2035
- devices: ["desktop"],
2036
- operatingSystems: ["windows", "macos", "linux"],
2075
+ devices: [resolvedDevice],
2076
+ operatingSystems: resolvedDevice === Device.Mobile ? ["android"] : ["windows", "macos", "linux"],
2037
2077
  locales: [locale]
2038
2078
  };
2079
+ if (resolvedDevice === Device.Mobile) {
2080
+ options.screen = {
2081
+ minWidth: 320,
2082
+ maxWidth: 480,
2083
+ minHeight: 640,
2084
+ maxHeight: 1100
2085
+ };
2086
+ }
2087
+ return options;
2039
2088
  }
2040
2089
  var AntiCheat = {
2041
2090
  /**
@@ -2045,7 +2094,7 @@ var AntiCheat = {
2045
2094
  return { ...BASE_CONFIG };
2046
2095
  },
2047
2096
  /**
2048
- * 用于 Crawlee fingerprint generator 的统一配置(桌面端)。
2097
+ * 用于 Crawlee fingerprint generator 的统一配置。
2049
2098
  */
2050
2099
  getFingerprintGeneratorOptions(options = {}) {
2051
2100
  return buildFingerprintOptions(options);
@@ -2058,10 +2107,10 @@ var AntiCheat = {
2058
2107
  return [...DEFAULT_LAUNCH_ARGS, `--lang=${locale}`];
2059
2108
  },
2060
2109
  /**
2061
- * 为 got-scraping 生成与浏览器一致的 TLS 指纹配置(桌面端)。
2110
+ * 为 got-scraping 生成与浏览器一致的 TLS 指纹配置。
2062
2111
  */
2063
- getTlsFingerprintOptions(userAgent = "", acceptLanguage = "") {
2064
- return buildFingerprintOptions();
2112
+ getTlsFingerprintOptions(userAgent = "", acceptLanguage = "", options = {}) {
2113
+ return buildFingerprintOptions(options);
2065
2114
  },
2066
2115
  /**
2067
2116
  * 规范化请求头
@@ -2074,7 +2123,7 @@ var AntiCheat = {
2074
2123
  }
2075
2124
  };
2076
2125
 
2077
- // src/humanize.js
2126
+ // src/internals/humanize/desktop.js
2078
2127
  var import_delay = __toESM(require("delay"), 1);
2079
2128
  var import_ghost_cursor_playwright = require("ghost-cursor-playwright");
2080
2129
  var logger6 = createInternalLogger("Humanize");
@@ -2099,7 +2148,7 @@ var Humanize = {
2099
2148
  },
2100
2149
  /**
2101
2150
  * 初始化页面的 Ghost Cursor(必须在使用其他 cursor 相关方法前调用)
2102
- *
2151
+ *
2103
2152
  * @param {import('playwright').Page} page
2104
2153
  * @returns {Promise<void>}
2105
2154
  */
@@ -2115,7 +2164,7 @@ var Humanize = {
2115
2164
  },
2116
2165
  /**
2117
2166
  * 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
2118
- *
2167
+ *
2119
2168
  * @param {import('playwright').Page} page
2120
2169
  * @param {string|{x: number, y: number}|import('playwright').ElementHandle} target - CSS选择器、坐标对象或元素句柄
2121
2170
  */
@@ -2157,7 +2206,7 @@ var Humanize = {
2157
2206
  /**
2158
2207
  * 渐进式滚动到元素可见(仅处理 Y 轴滚动)
2159
2208
  * 返回 restore 方法,用于将滚动容器恢复到原位置
2160
- *
2209
+ *
2161
2210
  * @param {import('playwright').Page} page
2162
2211
  * @param {string|import('playwright').ElementHandle} target - CSS 选择器或元素句柄
2163
2212
  * @param {Object} [options]
@@ -2228,7 +2277,7 @@ var Humanize = {
2228
2277
  return { code: "VISIBLE", isFixed };
2229
2278
  });
2230
2279
  };
2231
- const getScrollableRect = async () => {
2280
+ const getScrollableRect2 = async () => {
2232
2281
  return await element.evaluate((el) => {
2233
2282
  const isScrollable = (node) => {
2234
2283
  const style = window.getComputedStyle(node);
@@ -2271,7 +2320,7 @@ var Humanize = {
2271
2320
  if (status.code === "OBSTRUCTED" && status.obstruction) {
2272
2321
  logger6.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
2273
2322
  }
2274
- const scrollRect = await getScrollableRect();
2323
+ const scrollRect = await getScrollableRect2();
2275
2324
  if (!scrollRect && status.isFixed) {
2276
2325
  logger6.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
2277
2326
  return { element, didScroll };
@@ -2318,7 +2367,7 @@ var Humanize = {
2318
2367
  },
2319
2368
  /**
2320
2369
  * 人类化点击 - 使用 ghost-cursor 模拟人类鼠标移动轨迹并点击
2321
- *
2370
+ *
2322
2371
  * @param {import('playwright').Page} page
2323
2372
  * @param {string|import('playwright').ElementHandle} [target] - CSS 选择器或元素句柄。如果为空,则点击当前鼠标位置
2324
2373
  * @param {Object} [options]
@@ -2424,7 +2473,7 @@ var Humanize = {
2424
2473
  * @param {import('playwright').Page} page
2425
2474
  * @param {string} selector - 输入框选择器
2426
2475
  * @param {string} text - 要输入的文本
2427
- * @param {Object} [options]
2476
+ * @param {Object} [options]
2428
2477
  * @param {number} [options.baseDelay=180] - 基础按键延迟 (ms),实际 ±40% 抖动
2429
2478
  * @param {number} [options.pauseProbability=0.08] - 停顿概率 (0-1)
2430
2479
  * @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
@@ -2552,6 +2601,787 @@ var Humanize = {
2552
2601
  }
2553
2602
  };
2554
2603
 
2604
+ // src/internals/humanize/shared.js
2605
+ var import_delay2 = __toESM(require("delay"), 1);
2606
+ var jitterMs = (base, jitterPercent = 0.3) => {
2607
+ const jitter = Number(base || 0) * Number(jitterPercent || 0) * (Math.random() * 2 - 1);
2608
+ return Math.max(10, Math.round(Number(base || 0) + jitter));
2609
+ };
2610
+ var randomPointInBox = (box, paddingRatio = 0.24) => {
2611
+ const safePaddingX = Math.max(2, Math.min(box.width * paddingRatio, box.width / 2));
2612
+ const safePaddingY = Math.max(2, Math.min(box.height * paddingRatio, box.height / 2));
2613
+ const x = box.x + safePaddingX + Math.random() * Math.max(1, box.width - safePaddingX * 2);
2614
+ const y = box.y + safePaddingY + Math.random() * Math.max(1, box.height - safePaddingY * 2);
2615
+ return { x, y };
2616
+ };
2617
+ var resolveElement = async (page, target, { throwOnMissing = true } = {}) => {
2618
+ if (target == null) return null;
2619
+ let element = target;
2620
+ if (typeof target === "string") {
2621
+ element = await page.$(target);
2622
+ }
2623
+ if (!element) {
2624
+ if (throwOnMissing) {
2625
+ throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${String(target)}`);
2626
+ }
2627
+ return null;
2628
+ }
2629
+ return element;
2630
+ };
2631
+ var waitJitter = (base, jitterPercent = 0.3) => (0, import_delay2.default)(jitterMs(base, jitterPercent));
2632
+
2633
+ // src/internals/humanize/mobile.js
2634
+ var logger7 = createInternalLogger("Humanize.Mobile");
2635
+ var initializedPages = /* @__PURE__ */ new WeakSet();
2636
+ var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
2637
+ var resolveViewport = (page) => page?.viewportSize?.() || { width: 390, height: 844 };
2638
+ var describeTarget = (target) => {
2639
+ if (target == null) return "Current Position";
2640
+ return typeof target === "string" ? target : "ElementHandle";
2641
+ };
2642
+ var clipBoxToViewport = (box, viewport) => {
2643
+ if (!box || !viewport) return box;
2644
+ const left = clamp(box.x, 0, viewport.width);
2645
+ const top = clamp(box.y, 0, viewport.height);
2646
+ const right = clamp(box.x + box.width, 0, viewport.width);
2647
+ const bottom = clamp(box.y + box.height, 0, viewport.height);
2648
+ if (right - left > 1 && bottom - top > 1) {
2649
+ return {
2650
+ x: left,
2651
+ y: top,
2652
+ width: right - left,
2653
+ height: bottom - top
2654
+ };
2655
+ }
2656
+ return box;
2657
+ };
2658
+ var checkElementVisibility = async (element) => {
2659
+ return element.evaluate((el) => {
2660
+ const targetStyle = window.getComputedStyle(el);
2661
+ if (!targetStyle || targetStyle.display === "none" || targetStyle.visibility === "hidden" || targetStyle.visibility === "collapse") {
2662
+ return { code: "NOT_INTERACTABLE", reason: "\u5143\u7D20\u4E0D\u53EF\u89C1", direction: "down" };
2663
+ }
2664
+ const rect = el.getBoundingClientRect();
2665
+ if (!rect || rect.width <= 0 || rect.height <= 0) {
2666
+ return { code: "ZERO_DIMENSIONS", reason: "\u5C3A\u5BF8\u4E3A\u96F6", direction: "down" };
2667
+ }
2668
+ const viewW = window.innerWidth;
2669
+ const viewH = window.innerHeight;
2670
+ const centerY = rect.top + rect.height / 2;
2671
+ let clipLeft = 0;
2672
+ let clipRight = viewW;
2673
+ let clipTop = 0;
2674
+ let clipBottom = viewH;
2675
+ let isFixed = false;
2676
+ for (let node = el; node && node !== document.body; node = node.parentElement) {
2677
+ const style = window.getComputedStyle(node);
2678
+ if (style && (style.position === "fixed" || style.position === "sticky")) {
2679
+ isFixed = true;
2680
+ break;
2681
+ }
2682
+ }
2683
+ for (let node = el.parentElement; node && node !== document.body; node = node.parentElement) {
2684
+ const style = window.getComputedStyle(node);
2685
+ if (!style) continue;
2686
+ const clipsY = ["auto", "scroll", "overlay", "hidden", "clip"].includes(style.overflowY);
2687
+ const clipsX = ["auto", "scroll", "overlay", "hidden", "clip"].includes(style.overflowX);
2688
+ if (!clipsX && !clipsY) continue;
2689
+ const nodeRect = node.getBoundingClientRect();
2690
+ if (!nodeRect || nodeRect.width <= 0 || nodeRect.height <= 0) continue;
2691
+ if (clipsX) {
2692
+ clipLeft = Math.max(clipLeft, nodeRect.left);
2693
+ clipRight = Math.min(clipRight, nodeRect.right);
2694
+ }
2695
+ if (clipsY) {
2696
+ clipTop = Math.max(clipTop, nodeRect.top);
2697
+ clipBottom = Math.min(clipBottom, nodeRect.bottom);
2698
+ }
2699
+ }
2700
+ const visibleLeft = Math.max(clipLeft, Math.min(clipRight, rect.left));
2701
+ const visibleRight = Math.max(clipLeft, Math.min(clipRight, rect.right));
2702
+ const visibleTop = Math.max(clipTop, Math.min(clipBottom, rect.top));
2703
+ const visibleBottom = Math.max(clipTop, Math.min(clipBottom, rect.bottom));
2704
+ const visibleWidth = visibleRight - visibleLeft;
2705
+ const visibleHeight = visibleBottom - visibleTop;
2706
+ const cx = visibleLeft + visibleWidth / 2;
2707
+ const cy = visibleTop + visibleHeight / 2;
2708
+ if (visibleWidth <= 1 || visibleHeight <= 1) {
2709
+ return {
2710
+ code: "OUT_OF_VIEWPORT",
2711
+ reason: "\u4E0D\u5728\u89C6\u53E3\u5185",
2712
+ direction: centerY < clipTop ? "up" : "down",
2713
+ cy: centerY,
2714
+ viewH,
2715
+ isFixed
2716
+ };
2717
+ }
2718
+ const interactiveSelector = [
2719
+ "button",
2720
+ '[role="button"]',
2721
+ "a[href]",
2722
+ "label",
2723
+ "input",
2724
+ "textarea",
2725
+ "select",
2726
+ "summary",
2727
+ '[contenteditable="true"]',
2728
+ '[tabindex]:not([tabindex="-1"])'
2729
+ ].join(",");
2730
+ const targetInteractive = typeof el.closest === "function" ? el.closest(interactiveSelector) : null;
2731
+ const sameInteractiveTarget = (pointElement) => {
2732
+ if (!pointElement) return false;
2733
+ if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
2734
+ return true;
2735
+ }
2736
+ if (!targetInteractive || typeof pointElement.closest !== "function") {
2737
+ return false;
2738
+ }
2739
+ return pointElement.closest(interactiveSelector) === targetInteractive;
2740
+ };
2741
+ const describeElement = (node) => {
2742
+ if (!node) return null;
2743
+ const className = typeof node.className === "string" ? node.className : node.className && typeof node.className.baseVal === "string" ? node.className.baseVal : "";
2744
+ const rect2 = node.getBoundingClientRect?.();
2745
+ const style = window.getComputedStyle(node);
2746
+ return {
2747
+ tag: node.tagName,
2748
+ id: node.id || "",
2749
+ className,
2750
+ isFixed: Boolean(style && (style.position === "fixed" || style.position === "sticky")),
2751
+ top: rect2 ? rect2.top : null,
2752
+ bottom: rect2 ? rect2.bottom : null,
2753
+ left: rect2 ? rect2.left : null,
2754
+ right: rect2 ? rect2.right : null
2755
+ };
2756
+ };
2757
+ const samplePoints = [
2758
+ { x: cx, y: cy },
2759
+ { x: visibleLeft + Math.min(8, Math.max(1, visibleWidth * 0.25)), y: cy },
2760
+ { x: visibleRight - Math.min(8, Math.max(1, visibleWidth * 0.25)), y: cy },
2761
+ { x: cx, y: visibleTop + Math.min(8, Math.max(1, visibleHeight * 0.25)) },
2762
+ { x: cx, y: visibleBottom - Math.min(8, Math.max(1, visibleHeight * 0.25)) }
2763
+ ];
2764
+ let obstruction = null;
2765
+ for (const point of samplePoints) {
2766
+ const pointElement = document.elementFromPoint(point.x, point.y);
2767
+ if (sameInteractiveTarget(pointElement)) {
2768
+ return { code: "VISIBLE", isFixed };
2769
+ }
2770
+ obstruction = obstruction || describeElement(pointElement);
2771
+ }
2772
+ if (obstruction) {
2773
+ return {
2774
+ code: "OBSTRUCTED",
2775
+ reason: "\u88AB\u906E\u6321",
2776
+ direction: cy > viewH / 2 ? "down" : "up",
2777
+ obstruction,
2778
+ cy,
2779
+ viewH,
2780
+ isFixed
2781
+ };
2782
+ }
2783
+ return { code: "VISIBLE", isFixed };
2784
+ });
2785
+ };
2786
+ var resolveSafeTapPoint = async (element) => {
2787
+ return element.evaluate((el) => {
2788
+ const rect = el.getBoundingClientRect();
2789
+ if (!rect || rect.width <= 0 || rect.height <= 0) {
2790
+ return null;
2791
+ }
2792
+ const viewW = window.innerWidth;
2793
+ const viewH = window.innerHeight;
2794
+ let clipLeft = 0;
2795
+ let clipRight = viewW;
2796
+ let clipTop = 0;
2797
+ let clipBottom = viewH;
2798
+ for (let node = el.parentElement; node && node !== document.body; node = node.parentElement) {
2799
+ const style = window.getComputedStyle(node);
2800
+ if (!style) continue;
2801
+ const clipsX = ["auto", "scroll", "overlay", "hidden", "clip"].includes(style.overflowX);
2802
+ const clipsY = ["auto", "scroll", "overlay", "hidden", "clip"].includes(style.overflowY);
2803
+ if (!clipsX && !clipsY) continue;
2804
+ const nodeRect = node.getBoundingClientRect();
2805
+ if (!nodeRect || nodeRect.width <= 0 || nodeRect.height <= 0) continue;
2806
+ if (clipsX) {
2807
+ clipLeft = Math.max(clipLeft, nodeRect.left);
2808
+ clipRight = Math.min(clipRight, nodeRect.right);
2809
+ }
2810
+ if (clipsY) {
2811
+ clipTop = Math.max(clipTop, nodeRect.top);
2812
+ clipBottom = Math.min(clipBottom, nodeRect.bottom);
2813
+ }
2814
+ }
2815
+ const visibleLeft = Math.max(clipLeft, Math.min(clipRight, rect.left));
2816
+ const visibleRight = Math.max(clipLeft, Math.min(clipRight, rect.right));
2817
+ const visibleTop = Math.max(clipTop, Math.min(clipBottom, rect.top));
2818
+ const visibleBottom = Math.max(clipTop, Math.min(clipBottom, rect.bottom));
2819
+ const visibleWidth = visibleRight - visibleLeft;
2820
+ const visibleHeight = visibleBottom - visibleTop;
2821
+ if (visibleWidth <= 1 || visibleHeight <= 1) {
2822
+ return null;
2823
+ }
2824
+ const interactiveSelector = [
2825
+ "button",
2826
+ '[role="button"]',
2827
+ "a[href]",
2828
+ "label",
2829
+ "input",
2830
+ "textarea",
2831
+ "select",
2832
+ "summary",
2833
+ '[contenteditable="true"]',
2834
+ '[tabindex]:not([tabindex="-1"])'
2835
+ ].join(",");
2836
+ const targetInteractive = typeof el.closest === "function" ? el.closest(interactiveSelector) : null;
2837
+ const sameInteractiveTarget = (pointElement) => {
2838
+ if (!pointElement) return false;
2839
+ if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
2840
+ return true;
2841
+ }
2842
+ if (!targetInteractive || typeof pointElement.closest !== "function") {
2843
+ return false;
2844
+ }
2845
+ return pointElement.closest(interactiveSelector) === targetInteractive;
2846
+ };
2847
+ const cx = visibleLeft + visibleWidth / 2;
2848
+ const cy = visibleTop + visibleHeight / 2;
2849
+ const smallX = Math.min(12, Math.max(2, visibleWidth * 0.18));
2850
+ const smallY = Math.min(12, Math.max(2, visibleHeight * 0.18));
2851
+ const points = [
2852
+ { x: cx, y: cy },
2853
+ { x: visibleLeft + smallX, y: visibleTop + smallY },
2854
+ { x: visibleRight - smallX, y: visibleTop + smallY },
2855
+ { x: visibleLeft + smallX, y: visibleBottom - smallY },
2856
+ { x: visibleRight - smallX, y: visibleBottom - smallY },
2857
+ { x: cx, y: visibleTop + Math.min(10, Math.max(2, visibleHeight * 0.2)) },
2858
+ { x: cx, y: visibleBottom - Math.min(10, Math.max(2, visibleHeight * 0.2)) },
2859
+ { x: visibleLeft + Math.min(10, Math.max(2, visibleWidth * 0.2)), y: cy },
2860
+ { x: visibleRight - Math.min(10, Math.max(2, visibleWidth * 0.2)), y: cy }
2861
+ ];
2862
+ const safePoints = points.filter((point) => {
2863
+ const pointElement = document.elementFromPoint(point.x, point.y);
2864
+ return sameInteractiveTarget(pointElement);
2865
+ });
2866
+ const candidates = safePoints.length ? safePoints : points;
2867
+ const chosen = candidates[Math.floor(Math.random() * candidates.length)];
2868
+ if (!chosen) return null;
2869
+ return {
2870
+ x: chosen.x,
2871
+ y: chosen.y
2872
+ };
2873
+ });
2874
+ };
2875
+ var getScrollableRect = async (element) => {
2876
+ return element.evaluate((el) => {
2877
+ const isScrollable = (node) => {
2878
+ const style = window.getComputedStyle(node);
2879
+ if (!style) return false;
2880
+ const overflowY = style.overflowY;
2881
+ if (!["auto", "scroll", "overlay"].includes(overflowY)) return false;
2882
+ return node.scrollHeight > node.clientHeight + 1;
2883
+ };
2884
+ let current = el;
2885
+ while (current && current !== document.body) {
2886
+ if (isScrollable(current)) {
2887
+ const rect = current.getBoundingClientRect();
2888
+ if (rect && rect.width > 0 && rect.height > 0) {
2889
+ return {
2890
+ x: rect.x,
2891
+ y: rect.y,
2892
+ width: rect.width,
2893
+ height: rect.height
2894
+ };
2895
+ }
2896
+ }
2897
+ current = current.parentElement;
2898
+ }
2899
+ return null;
2900
+ });
2901
+ };
2902
+ var scrollScrollableAncestor = async (element, deltaY) => {
2903
+ return element.evaluate((el, amount) => {
2904
+ const isScrollable = (node) => {
2905
+ const style = window.getComputedStyle(node);
2906
+ if (!style) return false;
2907
+ const overflowY = style.overflowY;
2908
+ if (!["auto", "scroll", "overlay"].includes(overflowY)) return false;
2909
+ return node.scrollHeight > node.clientHeight + 1;
2910
+ };
2911
+ let current = el;
2912
+ while (current && current !== document.body) {
2913
+ if (isScrollable(current)) {
2914
+ const beforeTop2 = current.scrollTop;
2915
+ current.scrollTop = beforeTop2 + amount;
2916
+ return {
2917
+ scroller: true,
2918
+ moved: current.scrollTop !== beforeTop2,
2919
+ scrollTop: current.scrollTop
2920
+ };
2921
+ }
2922
+ current = current.parentElement;
2923
+ }
2924
+ const beforeTop = window.scrollY;
2925
+ window.scrollBy(0, amount);
2926
+ return {
2927
+ scroller: null,
2928
+ moved: window.scrollY !== beforeTop,
2929
+ scrollTop: window.scrollY
2930
+ };
2931
+ }, deltaY);
2932
+ };
2933
+ var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
2934
+ const viewport = resolveViewport(page);
2935
+ const rawRect = options.rect || null;
2936
+ const rect = rawRect ? {
2937
+ x: clamp(rawRect.x, 0, viewport.width),
2938
+ y: clamp(rawRect.y, 0, viewport.height),
2939
+ width: clamp(rawRect.width, 0, viewport.width),
2940
+ height: clamp(rawRect.height, 0, viewport.height)
2941
+ } : null;
2942
+ const area = rect && rect.width > 24 && rect.height > 48 ? {
2943
+ left: rect.x,
2944
+ right: Math.min(viewport.width, rect.x + rect.width),
2945
+ top: rect.y,
2946
+ bottom: Math.min(viewport.height, rect.y + rect.height)
2947
+ } : {
2948
+ left: 0,
2949
+ right: viewport.width,
2950
+ top: 0,
2951
+ bottom: viewport.height
2952
+ };
2953
+ const areaWidth = Math.max(1, area.right - area.left);
2954
+ const areaHeight = Math.max(1, area.bottom - area.top);
2955
+ const maxDistance = rect ? Math.max(60, areaHeight * 0.72) : Math.max(120, viewport.height * 0.72);
2956
+ const distance = clamp(Math.abs(deltaY), Math.min(80, maxDistance), maxDistance);
2957
+ const direction = deltaY >= 0 ? 1 : -1;
2958
+ const startX = clamp(
2959
+ area.left + areaWidth * (0.45 + Math.random() * 0.1),
2960
+ 24,
2961
+ viewport.width - 24
2962
+ );
2963
+ 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);
2964
+ const endY = clamp(startY - direction * distance, Math.max(16, area.top + 12), Math.min(viewport.height - 16, area.bottom - 12));
2965
+ const steps = Math.max(4, Math.round(Number(options.steps || 6)));
2966
+ const durationMs = jitterMs(options.durationMs || 320, 0.35);
2967
+ let client = null;
2968
+ const scrollBefore = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
2969
+ try {
2970
+ if (page.context && typeof page.context().newCDPSession === "function") {
2971
+ client = await page.context().newCDPSession(page);
2972
+ }
2973
+ if (!client) throw new Error("CDP session unavailable");
2974
+ await client.send("Input.synthesizeScrollGesture", {
2975
+ x: startX,
2976
+ y: startY,
2977
+ yDistance: -direction * distance,
2978
+ xOverscroll: (Math.random() - 0.5) * 4,
2979
+ yOverscroll: (Math.random() - 0.5) * 8,
2980
+ speed: 700 + Math.round(Math.random() * 350),
2981
+ gestureSourceType: "touch"
2982
+ });
2983
+ await waitJitter(160, 0.35);
2984
+ const scrollAfterSynth = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
2985
+ if (scrollBefore && scrollAfterSynth && (Math.abs(scrollAfterSynth.y - scrollBefore.y) > 2 || Math.abs(scrollAfterSynth.x - scrollBefore.x) > 2)) {
2986
+ return true;
2987
+ }
2988
+ await client.send("Input.dispatchTouchEvent", {
2989
+ type: "touchStart",
2990
+ touchPoints: [{ x: startX, y: startY, id: 1 }]
2991
+ });
2992
+ for (let i = 1; i <= steps; i += 1) {
2993
+ const progress = i / steps;
2994
+ const eased = 1 - Math.pow(1 - progress, 2);
2995
+ const x = startX + (Math.random() - 0.5) * 3;
2996
+ const y = startY + (endY - startY) * eased + (Math.random() - 0.5) * 5;
2997
+ await waitJitter(durationMs / steps, 0.25);
2998
+ await client.send("Input.dispatchTouchEvent", {
2999
+ type: "touchMove",
3000
+ touchPoints: [{ x, y, id: 1 }]
3001
+ });
3002
+ }
3003
+ await client.send("Input.dispatchTouchEvent", {
3004
+ type: "touchEnd",
3005
+ touchPoints: []
3006
+ });
3007
+ await waitJitter(120, 0.35);
3008
+ const scrollAfterTouch = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
3009
+ if (scrollBefore && scrollAfterTouch && Math.abs(scrollAfterTouch.y - scrollBefore.y) <= 2 && Math.abs(scrollAfterTouch.x - scrollBefore.x) <= 2) {
3010
+ await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
3011
+ await waitJitter(120, 0.35);
3012
+ }
3013
+ return true;
3014
+ } catch (error) {
3015
+ logger7.debug(`touch swipe fallback: ${error?.message || error}`);
3016
+ try {
3017
+ await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
3018
+ await waitJitter(120, 0.35);
3019
+ return true;
3020
+ } catch {
3021
+ await page.mouse.wheel(0, deltaY);
3022
+ await waitJitter(120, 0.35);
3023
+ return true;
3024
+ }
3025
+ } finally {
3026
+ if (client && typeof client.detach === "function") {
3027
+ try {
3028
+ await client.detach();
3029
+ } catch {
3030
+ }
3031
+ }
3032
+ }
3033
+ };
3034
+ var tapPoint = async (page, point) => {
3035
+ if (page.touchscreen && typeof page.touchscreen.tap === "function") {
3036
+ await page.touchscreen.tap(point.x, point.y);
3037
+ return;
3038
+ }
3039
+ await page.mouse.click(point.x, point.y);
3040
+ };
3041
+ var MobileHumanize = {
3042
+ jitterMs,
3043
+ async initializeCursor(page) {
3044
+ if (initializedPages.has(page)) return;
3045
+ initializedPages.add(page);
3046
+ logger7.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
3047
+ },
3048
+ async humanMove(page, target) {
3049
+ logger7.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
3050
+ if (typeof target === "string" || target && typeof target.boundingBox === "function") {
3051
+ const element = await resolveElement(page, target, { throwOnMissing: false });
3052
+ if (!element) {
3053
+ return false;
3054
+ }
3055
+ }
3056
+ await waitJitter(80, 0.4);
3057
+ return true;
3058
+ },
3059
+ async humanScroll(page, target, options = {}) {
3060
+ const {
3061
+ maxSteps = 12,
3062
+ minStep = 180,
3063
+ maxStep = 520,
3064
+ maxDurationMs = maxSteps * 280 + 1200,
3065
+ throwOnMissing = false
3066
+ } = options;
3067
+ const targetDesc = describeTarget(target);
3068
+ logger7.start("humanScroll", `target=${targetDesc}`);
3069
+ const element = await resolveElement(page, target, { throwOnMissing });
3070
+ if (!element) {
3071
+ logger7.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${targetDesc}`);
3072
+ return { element: null, didScroll: false, restore: null };
3073
+ }
3074
+ const startTime = Date.now();
3075
+ let didScroll = false;
3076
+ for (let i = 0; i < maxSteps; i += 1) {
3077
+ const status = await checkElementVisibility(element);
3078
+ if (status.code === "VISIBLE") {
3079
+ if (status.isFixed) {
3080
+ logger7.info("humanScroll | fixed/sticky \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3081
+ } else {
3082
+ logger7.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
3083
+ }
3084
+ logger7.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
3085
+ return { element, didScroll, restore: null };
3086
+ }
3087
+ if (status.code === "ZERO_DIMENSIONS" || status.code === "NOT_INTERACTABLE") {
3088
+ logger7.warn(`humanScroll | \u5143\u7D20\u4E0D\u53EF\u6EDA\u52A8\u81F3\u53EF\u70B9\u51FB\u72B6\u6001: ${status.reason || status.code}`);
3089
+ return { element, didScroll, restore: null };
3090
+ }
3091
+ const scrollRect = await getScrollableRect(element);
3092
+ if (!scrollRect && status.isFixed && status.code === "OBSTRUCTED") {
3093
+ logger7.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
3094
+ return { element, didScroll, restore: null };
3095
+ }
3096
+ if (Date.now() - startTime > maxDurationMs) {
3097
+ logger7.warn(`humanScroll | mobile timeout (${maxDurationMs}ms, status=${status.code}, direction=${status.direction || "unknown"}, fixed=${Boolean(status.isFixed)})`);
3098
+ return { element, didScroll, restore: null };
3099
+ }
3100
+ const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
3101
+ const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;
3102
+ logger7.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason || status.code} ${status.direction ? `(${status.direction})` : ""}`);
3103
+ const distance = stepMin + Math.random() * Math.max(1, stepMax - stepMin);
3104
+ let deltaY = status.direction === "up" ? -distance : distance;
3105
+ if (status.code === "OBSTRUCTED") {
3106
+ if (status.obstruction?.isFixed && status.obstruction.top != null) {
3107
+ const obstructionMiddle = (Number(status.obstruction.top || 0) + Number(status.obstruction.bottom || status.obstruction.top || 0)) / 2;
3108
+ const visibleMiddle = scrollRect ? scrollRect.y + scrollRect.height / 2 : status.viewH / 2;
3109
+ deltaY = obstructionMiddle < visibleMiddle ? -distance : distance;
3110
+ } else {
3111
+ const halfY = scrollRect ? scrollRect.y + scrollRect.height / 2 : status.viewH / 2;
3112
+ deltaY = status.cy > halfY ? distance : -distance;
3113
+ }
3114
+ }
3115
+ const beforeWindowState = scrollRect ? await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })) : null;
3116
+ const beforeState = scrollRect ? await element.evaluate((el) => {
3117
+ const isScrollable = (node) => {
3118
+ const style = window.getComputedStyle(node);
3119
+ if (!style) return false;
3120
+ const overflowY = style.overflowY;
3121
+ if (!["auto", "scroll", "overlay"].includes(overflowY)) return false;
3122
+ return node.scrollHeight > node.clientHeight + 1;
3123
+ };
3124
+ let current = el;
3125
+ while (current && current !== document.body) {
3126
+ if (isScrollable(current)) {
3127
+ return {
3128
+ kind: "element",
3129
+ top: current.scrollTop,
3130
+ left: current.scrollLeft
3131
+ };
3132
+ }
3133
+ current = current.parentElement;
3134
+ }
3135
+ return { kind: "window", top: window.scrollY, left: window.scrollX };
3136
+ }) : null;
3137
+ await dispatchTouchSwipe(page, deltaY, { rect: scrollRect });
3138
+ if (scrollRect && beforeWindowState) {
3139
+ const afterWindowState = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY }));
3140
+ if (Math.abs(afterWindowState.x - beforeWindowState.x) > 2 || Math.abs(afterWindowState.y - beforeWindowState.y) > 2) {
3141
+ await page.evaluate((state) => window.scrollTo(state.x, state.y), beforeWindowState);
3142
+ logger7.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
3143
+ }
3144
+ }
3145
+ if (scrollRect && beforeState) {
3146
+ const afterState = await element.evaluate((el) => {
3147
+ const isScrollable = (node) => {
3148
+ const style = window.getComputedStyle(node);
3149
+ if (!style) return false;
3150
+ const overflowY = style.overflowY;
3151
+ if (!["auto", "scroll", "overlay"].includes(overflowY)) return false;
3152
+ return node.scrollHeight > node.clientHeight + 1;
3153
+ };
3154
+ let current = el;
3155
+ while (current && current !== document.body) {
3156
+ if (isScrollable(current)) {
3157
+ return {
3158
+ kind: "element",
3159
+ top: current.scrollTop,
3160
+ left: current.scrollLeft
3161
+ };
3162
+ }
3163
+ current = current.parentElement;
3164
+ }
3165
+ return { kind: "window", top: window.scrollY, left: window.scrollX };
3166
+ });
3167
+ const topDelta = Number(afterState.top || 0) - Number(beforeState.top || 0);
3168
+ const leftDelta = Number(afterState.left || 0) - Number(beforeState.left || 0);
3169
+ const expectedDelta = Number(deltaY || 0);
3170
+ const moved = beforeState.kind !== afterState.kind || Math.abs(topDelta) > 2 || Math.abs(leftDelta) > 2;
3171
+ if (!moved) {
3172
+ const fallback = await scrollScrollableAncestor(element, deltaY);
3173
+ 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)}`);
3174
+ } 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)) {
3175
+ const residualDelta = expectedDelta - topDelta;
3176
+ if (Math.sign(residualDelta) === Math.sign(expectedDelta) && Math.abs(residualDelta) > 24) {
3177
+ const fallback = await scrollScrollableAncestor(element, residualDelta);
3178
+ 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)}`);
3179
+ }
3180
+ }
3181
+ }
3182
+ didScroll = true;
3183
+ }
3184
+ try {
3185
+ await element.scrollIntoViewIfNeeded?.();
3186
+ await waitJitter(80, 0.3);
3187
+ const finalStatus = await checkElementVisibility(element);
3188
+ if (finalStatus.code === "VISIBLE") {
3189
+ logger7.info("humanScroll | \u539F\u751F scrollIntoViewIfNeeded \u515C\u5E95\u6210\u529F");
3190
+ logger7.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
3191
+ return { element, didScroll: true, restore: null };
3192
+ }
3193
+ } catch (fallbackError) {
3194
+ logger7.debug(`humanScroll | native fallback failed: ${fallbackError?.message || fallbackError}`);
3195
+ }
3196
+ logger7.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
3197
+ return { element, didScroll, restore: null };
3198
+ },
3199
+ async humanClick(page, target, options = {}) {
3200
+ const {
3201
+ reactionDelay = 220,
3202
+ throwOnMissing = true,
3203
+ scrollIfNeeded = true
3204
+ } = options;
3205
+ const targetDesc = describeTarget(target);
3206
+ logger7.start("humanClick", `target=${targetDesc}`);
3207
+ try {
3208
+ if (target == null) {
3209
+ const viewport = resolveViewport(page);
3210
+ await waitJitter(reactionDelay, 0.45);
3211
+ await tapPoint(page, {
3212
+ x: viewport.width * (0.45 + Math.random() * 0.1),
3213
+ y: viewport.height * (0.48 + Math.random() * 0.12)
3214
+ });
3215
+ logger7.success("humanClick", "Tapped current position");
3216
+ return true;
3217
+ }
3218
+ const element = await resolveElement(page, target, { throwOnMissing });
3219
+ if (!element) {
3220
+ logger7.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
3221
+ return false;
3222
+ }
3223
+ if (scrollIfNeeded) {
3224
+ await MobileHumanize.humanScroll(page, element, { throwOnMissing });
3225
+ }
3226
+ const status = await checkElementVisibility(element).catch(() => null);
3227
+ if (status && (status.code === "ZERO_DIMENSIONS" || status.code === "NOT_INTERACTABLE")) {
3228
+ const message = `\u5143\u7D20\u4E0D\u53EF\u70B9\u51FB: ${status.reason || status.code}`;
3229
+ if (throwOnMissing) throw new Error(message);
3230
+ logger7.warn(`humanClick: ${message}\uFF0C\u8DF3\u8FC7\u70B9\u51FB`);
3231
+ return false;
3232
+ }
3233
+ const box = await element.boundingBox();
3234
+ if (!box) {
3235
+ if (throwOnMissing) throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
3236
+ logger7.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
3237
+ return false;
3238
+ }
3239
+ await waitJitter(reactionDelay, 0.45);
3240
+ const safePoint = await resolveSafeTapPoint(element).catch(() => null);
3241
+ const tapTarget = safePoint || randomPointInBox(clipBoxToViewport(box, resolveViewport(page)), 0.2);
3242
+ await tapPoint(page, tapTarget);
3243
+ await waitJitter(120, 0.35);
3244
+ logger7.success("humanClick");
3245
+ return true;
3246
+ } catch (error) {
3247
+ logger7.fail("humanClick", error);
3248
+ throw error;
3249
+ }
3250
+ },
3251
+ async randomSleep(baseMs, jitterPercent = 0.3) {
3252
+ await waitJitter(baseMs, jitterPercent);
3253
+ },
3254
+ async simulateGaze(page, baseDurationMs = 2500) {
3255
+ const durationMs = jitterMs(baseDurationMs, 0.4);
3256
+ const startTime = Date.now();
3257
+ while (Date.now() - startTime < durationMs) {
3258
+ if (Math.random() < 0.28) {
3259
+ const distance = 70 + Math.random() * 120;
3260
+ await dispatchTouchSwipe(page, Math.random() < 0.7 ? distance : -distance, {
3261
+ durationMs: 180,
3262
+ steps: 4
3263
+ });
3264
+ } else {
3265
+ await waitJitter(420, 0.55);
3266
+ }
3267
+ }
3268
+ },
3269
+ async humanType(page, selector, text, options = {}) {
3270
+ const {
3271
+ baseDelay = 160,
3272
+ pauseProbability = 0.08,
3273
+ pauseBase = 700
3274
+ } = options;
3275
+ await MobileHumanize.humanClick(page, selector, { scrollIfNeeded: true });
3276
+ await waitJitter(220, 0.45);
3277
+ for (let i = 0; i < String(text).length; i += 1) {
3278
+ const char = String(text)[i];
3279
+ const charDelay = /[,.!?;:,。!?;:]/.test(char) ? jitterMs(baseDelay * 1.45, 0.4) : jitterMs(char === " " ? baseDelay * 0.65 : baseDelay, 0.4);
3280
+ await page.keyboard.type(char);
3281
+ await waitJitter(charDelay, 0.15);
3282
+ if (Math.random() < pauseProbability && i < String(text).length - 1) {
3283
+ await waitJitter(pauseBase, 0.5);
3284
+ }
3285
+ }
3286
+ },
3287
+ async humanClear(page, selector) {
3288
+ const locator = page.locator(selector);
3289
+ await MobileHumanize.humanClick(page, locator, { scrollIfNeeded: true });
3290
+ await waitJitter(160, 0.4);
3291
+ await locator.evaluate((el) => {
3292
+ if ("value" in el) {
3293
+ el.value = "";
3294
+ el.dispatchEvent(new Event("input", { bubbles: true }));
3295
+ el.dispatchEvent(new Event("change", { bubbles: true }));
3296
+ return;
3297
+ }
3298
+ el.textContent = "";
3299
+ el.dispatchEvent(new Event("input", { bubbles: true }));
3300
+ });
3301
+ },
3302
+ async warmUpBrowsing(page, baseDuration = 3500) {
3303
+ const durationMs = jitterMs(baseDuration, 0.4);
3304
+ const startTime = Date.now();
3305
+ while (Date.now() - startTime < durationMs) {
3306
+ const action = Math.random();
3307
+ if (action < 0.5) {
3308
+ await dispatchTouchSwipe(page, 120 + Math.random() * 220, {
3309
+ durationMs: 240,
3310
+ steps: 5
3311
+ });
3312
+ } else if (action < 0.7) {
3313
+ await dispatchTouchSwipe(page, -(80 + Math.random() * 160), {
3314
+ durationMs: 220,
3315
+ steps: 4
3316
+ });
3317
+ } else {
3318
+ await waitJitter(560, 0.55);
3319
+ }
3320
+ }
3321
+ },
3322
+ async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
3323
+ const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
3324
+ const actualDistance = jitterMs(distance, 0.15);
3325
+ const sign = direction === "down" ? 1 : -1;
3326
+ for (let i = 0; i < steps; i += 1) {
3327
+ const factor = 1 - i / steps * 0.45;
3328
+ await dispatchTouchSwipe(page, actualDistance / steps * factor * sign, {
3329
+ durationMs: 150 + i * 20,
3330
+ steps: 4
3331
+ });
3332
+ }
3333
+ }
3334
+ };
3335
+
3336
+ // src/humanize.js
3337
+ var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
3338
+ var resolveDelegate = (page) => {
3339
+ return resolveDeviceFromPage(page) === Device.Mobile ? MobileHumanize : Humanize;
3340
+ };
3341
+ var callDelegate = (method, page, args) => {
3342
+ const delegate = resolveDelegate(page);
3343
+ return delegate[method](page, ...args);
3344
+ };
3345
+ var Humanize2 = {
3346
+ jitterMs(base, jitterPercent = 0.3) {
3347
+ return Humanize.jitterMs(base, jitterPercent);
3348
+ },
3349
+ initializeCursor(page) {
3350
+ return callDelegate("initializeCursor", page, []);
3351
+ },
3352
+ humanMove(page, target) {
3353
+ return callDelegate("humanMove", page, [target]);
3354
+ },
3355
+ humanScroll(page, target, options = {}) {
3356
+ return callDelegate("humanScroll", page, [target, options]);
3357
+ },
3358
+ humanClick(page, target, options = {}) {
3359
+ return callDelegate("humanClick", page, [target, options]);
3360
+ },
3361
+ randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
3362
+ if (pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function") {
3363
+ const delegate = resolveDelegate(pageOrBaseMs);
3364
+ return delegate.randomSleep(maybeBaseMs, maybeJitterPercent);
3365
+ }
3366
+ return Humanize.randomSleep(pageOrBaseMs, maybeBaseMs);
3367
+ },
3368
+ simulateGaze(page, baseDurationMs = 2500) {
3369
+ return callDelegate("simulateGaze", page, [baseDurationMs]);
3370
+ },
3371
+ humanType(page, selector, text, options = {}) {
3372
+ return callDelegate("humanType", page, [selector, text, options]);
3373
+ },
3374
+ humanClear(page, selector) {
3375
+ return callDelegate("humanClear", page, [selector]);
3376
+ },
3377
+ warmUpBrowsing(page, baseDuration = 3500) {
3378
+ return callDelegate("warmUpBrowsing", page, [baseDuration]);
3379
+ },
3380
+ naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
3381
+ return callDelegate("naturalScroll", page, [direction, distance, baseSteps]);
3382
+ }
3383
+ };
3384
+
2555
3385
  // src/launch.js
2556
3386
  var import_node_child_process = require("node:child_process");
2557
3387
  var import_fingerprint_generator = require("fingerprint-generator");
@@ -2638,7 +3468,7 @@ var ByPass = {
2638
3468
  };
2639
3469
 
2640
3470
  // src/launch.js
2641
- var logger7 = createInternalLogger("Launch");
3471
+ var logger8 = createInternalLogger("Launch");
2642
3472
  var REQUEST_HOOK_FLAG = Symbol("playwright-toolkit-request-hook");
2643
3473
  var injectedContexts = /* @__PURE__ */ new WeakSet();
2644
3474
  var browserMajorVersionCache = /* @__PURE__ */ new Map();
@@ -2690,20 +3520,29 @@ var detectBrowserMajorVersion = (launcher) => {
2690
3520
  });
2691
3521
  detectedVersion = parseChromeMajorVersion(rawVersion);
2692
3522
  } catch (error) {
2693
- logger7.warn(`\u8BFB\u53D6\u6D4F\u89C8\u5668\u7248\u672C\u5931\u8D25: ${error?.message || error}`);
3523
+ logger8.warn(`\u8BFB\u53D6\u6D4F\u89C8\u5668\u7248\u672C\u5931\u8D25: ${error?.message || error}`);
2694
3524
  }
2695
3525
  browserMajorVersionCache.set(executablePath, detectedVersion);
2696
3526
  return detectedVersion;
2697
3527
  };
2698
- var buildFingerprintGenerator = ({ locale, browserMajorVersion }) => {
3528
+ var resolveRuntimeDevice = (runtimeState = {}) => normalizeDevice(runtimeState?.device);
3529
+ var resolveCoreDevice = (core = {}) => {
3530
+ const raw = String(core?.device || "").trim().toLowerCase();
3531
+ if (raw === Device.Mobile) return Device.Mobile;
3532
+ if (raw === Device.Desktop) return Device.Desktop;
3533
+ return "";
3534
+ };
3535
+ var buildFingerprintGenerator = ({ locale, browserMajorVersion, device }) => {
2699
3536
  return new import_fingerprint_generator.FingerprintGenerator(
2700
3537
  AntiCheat.getFingerprintGeneratorOptions({
2701
3538
  locale,
2702
- browserMajorVersion
3539
+ browserMajorVersion,
3540
+ device
2703
3541
  })
2704
3542
  );
2705
3543
  };
2706
3544
  var buildReplayableBrowserProfile = (runtimeState, launcher) => {
3545
+ const device = resolveRuntimeDevice(runtimeState);
2707
3546
  if (!runtimeState || !RuntimeEnv.hasLoginState(runtimeState)) {
2708
3547
  return { runtimeState, browserProfileCore: null };
2709
3548
  }
@@ -2713,29 +3552,34 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
2713
3552
  const locale = DEFAULT_LOCALE;
2714
3553
  const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);
2715
3554
  const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);
2716
- const needsRebuild = !browserProfileCore?.fingerprint || Object.keys(browserProfileCore.fingerprint || {}).length === 0 || currentBrowserMajorVersion > 0 && storedBrowserMajorVersion > 0 && storedBrowserMajorVersion !== currentBrowserMajorVersion;
3555
+ const storedDevice = resolveCoreDevice(browserProfileCore);
3556
+ const needsDeviceRebuild = storedDevice ? storedDevice !== device : device === Device.Mobile;
3557
+ const needsRebuild = !browserProfileCore?.fingerprint || Object.keys(browserProfileCore.fingerprint || {}).length === 0 || needsDeviceRebuild || currentBrowserMajorVersion > 0 && storedBrowserMajorVersion > 0 && storedBrowserMajorVersion !== currentBrowserMajorVersion;
2717
3558
  if (needsRebuild) {
2718
3559
  const generator = buildFingerprintGenerator({
2719
3560
  locale,
2720
- browserMajorVersion: currentBrowserMajorVersion
3561
+ browserMajorVersion: currentBrowserMajorVersion,
3562
+ device
2721
3563
  });
2722
3564
  const fingerprint = generator.getFingerprint();
2723
3565
  const fingerprintBrowserMajorVersion = parseChromeMajorVersion(fingerprint?.fingerprint?.navigator?.userAgent || "");
2724
3566
  browserProfileCore = {
2725
3567
  fingerprint,
3568
+ device,
2726
3569
  timezone_id: timezoneId,
2727
3570
  locale,
2728
3571
  browser_major_version: currentBrowserMajorVersion > 0 ? currentBrowserMajorVersion : fingerprintBrowserMajorVersion,
2729
3572
  schema_version: DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION
2730
3573
  };
2731
3574
  nextState = RuntimeEnv.setBrowserProfileCore(nextState, browserProfileCore);
2732
- logger7.info(
2733
- `\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || "-")} | version=${browserProfileCore.browser_major_version || "-"} | timezone=${timezoneId}`
3575
+ logger8.info(
3576
+ `\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || "-")} | device=${device} | version=${browserProfileCore.browser_major_version || "-"} | timezone=${timezoneId}`
2734
3577
  );
2735
3578
  return { runtimeState: nextState, browserProfileCore };
2736
3579
  }
2737
3580
  const normalizedBrowserProfileCore = {
2738
3581
  ...browserProfileCore,
3582
+ device,
2739
3583
  timezone_id: timezoneId,
2740
3584
  locale,
2741
3585
  schema_version: Number(browserProfileCore.schema_version || 0) > 0 ? Number(browserProfileCore.schema_version || 0) : DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION,
@@ -2751,6 +3595,35 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
2751
3595
  browserProfileCore: normalizedBrowserProfileCore
2752
3596
  };
2753
3597
  };
3598
+ var applyDevicePageOptions = (pageOptions = {}, { device = Device.Desktop, fingerprint = null } = {}) => {
3599
+ if (!pageOptions || typeof pageOptions !== "object") return;
3600
+ const resolvedDevice = normalizeDevice(device);
3601
+ const screen = fingerprint?.screen || {};
3602
+ const dpr = Number(screen.devicePixelRatio || 0);
3603
+ if (resolvedDevice === Device.Mobile) {
3604
+ pageOptions.isMobile = true;
3605
+ pageOptions.hasTouch = true;
3606
+ pageOptions.deviceScaleFactor = dpr > 0 ? dpr : 2;
3607
+ if (!pageOptions.viewport) {
3608
+ pageOptions.viewport = {
3609
+ width: Number(screen.width || 390),
3610
+ height: Number(screen.height || 844)
3611
+ };
3612
+ }
3613
+ if (!pageOptions.screen) {
3614
+ pageOptions.screen = {
3615
+ width: Number(screen.width || pageOptions.viewport.width || 390),
3616
+ height: Number(screen.height || pageOptions.viewport.height || 844)
3617
+ };
3618
+ }
3619
+ return;
3620
+ }
3621
+ pageOptions.isMobile = false;
3622
+ pageOptions.hasTouch = false;
3623
+ if (!pageOptions.deviceScaleFactor) {
3624
+ pageOptions.deviceScaleFactor = dpr > 0 ? dpr : 1;
3625
+ }
3626
+ };
2754
3627
  var buildReplayBrowserPoolOptions = (browserProfileCore) => {
2755
3628
  const fingerprintWithHeaders = browserProfileCore?.fingerprint;
2756
3629
  const fingerprint = fingerprintWithHeaders?.fingerprint;
@@ -2783,6 +3656,10 @@ var buildReplayBrowserPoolOptions = (browserProfileCore) => {
2783
3656
  if (browserProfileCore.timezone_id) {
2784
3657
  pageOptions.timezoneId = browserProfileCore.timezone_id;
2785
3658
  }
3659
+ applyDevicePageOptions(pageOptions, {
3660
+ device: browserProfileCore.device,
3661
+ fingerprint
3662
+ });
2786
3663
  }
2787
3664
  ],
2788
3665
  postPageCreateHooks: [
@@ -2812,6 +3689,7 @@ var Launch = {
2812
3689
  postNavigationHooks = [],
2813
3690
  runtimeState = null
2814
3691
  } = normalizedOptions;
3692
+ const device = resolveRuntimeDevice(runtimeState);
2815
3693
  const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);
2816
3694
  const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
2817
3695
  const proxyMeter = enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
@@ -2840,18 +3718,18 @@ var Launch = {
2840
3718
  upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
2841
3719
  } catch {
2842
3720
  }
2843
- logger7.info(
3721
+ logger8.info(
2844
3722
  `[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
2845
3723
  );
2846
- 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`);
3724
+ 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`);
2847
3725
  } else if (enableByPassLogger && enableProxy && !launchProxy) {
2848
- logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
2849
- 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`);
3726
+ logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
3727
+ 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`);
2850
3728
  } else if (enableByPassLogger && !enableProxy && proxyUrl) {
2851
- logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
2852
- 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`);
3729
+ logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
3730
+ 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`);
2853
3731
  } else if (enableByPassLogger) {
2854
- 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`);
3732
+ 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`);
2855
3733
  }
2856
3734
  const onPageCreated = (page) => {
2857
3735
  const recommendedGotoOptions = {
@@ -2873,7 +3751,7 @@ var Launch = {
2873
3751
  }
2874
3752
  if (!enableByPassLogger || byPassDomains.length === 0) return;
2875
3753
  if (!matched || !matched.rule) return;
2876
- 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}`);
3754
+ 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}`);
2877
3755
  };
2878
3756
  page.on("request", requestHandler);
2879
3757
  return recommendedGotoOptions;
@@ -2892,8 +3770,23 @@ var Launch = {
2892
3770
  browserPoolOptions: replayBrowserPoolOptions || {
2893
3771
  useFingerprints: true,
2894
3772
  fingerprintOptions: {
2895
- fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions()
2896
- }
3773
+ fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions({
3774
+ locale: launchLocale,
3775
+ device
3776
+ })
3777
+ },
3778
+ prePageCreateHooks: [
3779
+ (_pageId, _browserController, pageOptions = {}) => {
3780
+ applyDevicePageOptions(pageOptions, { device });
3781
+ if (launchLocale) {
3782
+ pageOptions.locale = launchLocale;
3783
+ }
3784
+ const timezoneId = AntiCheat.getBaseConfig().timezoneId;
3785
+ if (timezoneId) {
3786
+ pageOptions.timezoneId = timezoneId;
3787
+ }
3788
+ }
3789
+ ]
2897
3790
  },
2898
3791
  launchContext
2899
3792
  };
@@ -2916,7 +3809,7 @@ var Launch = {
2916
3809
  // src/live-view.js
2917
3810
  var import_express = __toESM(require("express"), 1);
2918
3811
  var import_apify = require("apify");
2919
- var logger8 = createInternalLogger("LiveView");
3812
+ var logger9 = createInternalLogger("LiveView");
2920
3813
  async function startLiveViewServer(liveViewKey) {
2921
3814
  const app = (0, import_express.default)();
2922
3815
  app.get("/", async (req, res) => {
@@ -2941,13 +3834,13 @@ async function startLiveViewServer(liveViewKey) {
2941
3834
  </html>
2942
3835
  `);
2943
3836
  } catch (error) {
2944
- logger8.fail("Live View Server", error);
3837
+ logger9.fail("Live View Server", error);
2945
3838
  res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
2946
3839
  }
2947
3840
  });
2948
3841
  const port = process.env.APIFY_CONTAINER_PORT || 4321;
2949
3842
  app.listen(port, () => {
2950
- logger8.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
3843
+ logger9.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
2951
3844
  });
2952
3845
  }
2953
3846
  async function takeLiveScreenshot(liveViewKey, page, logMessage) {
@@ -2955,10 +3848,10 @@ async function takeLiveScreenshot(liveViewKey, page, logMessage) {
2955
3848
  const buffer = await capturePageScreenshot(page, { type: "png" });
2956
3849
  await import_apify.Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
2957
3850
  if (logMessage) {
2958
- logger8.info(`(\u622A\u56FE): ${logMessage}`);
3851
+ logger9.info(`(\u622A\u56FE): ${logMessage}`);
2959
3852
  }
2960
3853
  } catch (e) {
2961
- logger8.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
3854
+ logger9.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
2962
3855
  }
2963
3856
  }
2964
3857
  var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
@@ -3058,7 +3951,7 @@ var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
3058
3951
  };
3059
3952
 
3060
3953
  // src/internals/captcha/bytedance.js
3061
- var logger9 = createInternalLogger("Captcha");
3954
+ var logger10 = createInternalLogger("Captcha");
3062
3955
  var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
3063
3956
  apiType: "31234",
3064
3957
  maxRetries: 3,
@@ -3125,14 +4018,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
3125
4018
  if (!isContainerVisible) {
3126
4019
  return null;
3127
4020
  }
3128
- logger9.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
4021
+ logger10.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
3129
4022
  let iframeLocator = page.locator(options.iframeSelector).first();
3130
4023
  let isIframeVisible = await waitForVisible(
3131
4024
  iframeLocator,
3132
4025
  options.iframeVisibleTimeoutMs
3133
4026
  );
3134
4027
  if (!isIframeVisible) {
3135
- logger9.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
4028
+ logger10.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
3136
4029
  iframeLocator = captchaContainer.locator(options.iframeFallbackSelector).first();
3137
4030
  isIframeVisible = await waitForVisible(
3138
4031
  iframeLocator,
@@ -3142,7 +4035,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
3142
4035
  if (!isIframeVisible) {
3143
4036
  throw new Error("verifycenter iframe not found inside captcha container.");
3144
4037
  }
3145
- logger9.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
4038
+ logger10.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
3146
4039
  const frame = await resolveContentFrame(page, iframeLocator, options);
3147
4040
  if (!frame) {
3148
4041
  throw new Error("Failed to resolve verifycenter iframe content frame.");
@@ -3152,7 +4045,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
3152
4045
  var refreshCaptcha = async (page, frame, options) => {
3153
4046
  const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
3154
4047
  if (!clicked) {
3155
- logger9.warn("Refresh button not found.");
4048
+ logger10.warn("Refresh button not found.");
3156
4049
  return false;
3157
4050
  }
3158
4051
  await page.waitForTimeout(options.refreshWaitMs);
@@ -3193,18 +4086,18 @@ var waitForCaptchaChallengeReady = async (page, frame, options) => {
3193
4086
  const imageCount = await sourceImages.count().catch(() => 0);
3194
4087
  const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
3195
4088
  if (!isLoadingVisible && hasVisibleSourceImage) {
3196
- logger9.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
4089
+ logger10.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
3197
4090
  return;
3198
4091
  }
3199
4092
  if (hasErrorTextVisible) {
3200
- 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");
4093
+ 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");
3201
4094
  await refreshCaptcha(page, frame, options);
3202
4095
  refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3203
4096
  hasSeenLoading = false;
3204
4097
  continue;
3205
4098
  }
3206
4099
  if (!hasVisibleSourceImage && Date.now() >= refreshDeadline) {
3207
- logger9.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
4100
+ logger10.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
3208
4101
  await refreshCaptcha(page, frame, options);
3209
4102
  refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
3210
4103
  hasSeenLoading = false;
@@ -3224,16 +4117,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
3224
4117
  ...options
3225
4118
  };
3226
4119
  if (!config.token) {
3227
- logger9.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
4120
+ logger10.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
3228
4121
  return false;
3229
4122
  }
3230
- logger9.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
4123
+ logger10.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
3231
4124
  for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
3232
- logger9.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
4125
+ logger10.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
3233
4126
  try {
3234
4127
  const captchaContext = await getVerifycenterCaptchaContext(page, config);
3235
4128
  if (!captchaContext) {
3236
- logger9.info("Captcha container is not visible anymore.");
4129
+ logger10.info("Captcha container is not visible anymore.");
3237
4130
  return true;
3238
4131
  }
3239
4132
  const { iframeLocator, frame } = captchaContext;
@@ -3248,16 +4141,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
3248
4141
  });
3249
4142
  const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
3250
4143
  if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
3251
- logger9.warn(
4144
+ logger10.warn(
3252
4145
  `\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\u3002code=${apiResponse?.code}, msg=${apiResponse?.msg || "unknown"}`
3253
4146
  );
3254
4147
  await refreshCaptcha(page, frame, config);
3255
4148
  continue;
3256
4149
  }
3257
- logger9.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
4150
+ logger10.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
3258
4151
  const dropTarget = await findCaptchaDropTarget(frame, config);
3259
4152
  if (!dropTarget) {
3260
- logger9.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
4153
+ logger10.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
3261
4154
  await refreshCaptcha(page, frame, config);
3262
4155
  continue;
3263
4156
  }
@@ -3280,31 +4173,31 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
3280
4173
  }
3281
4174
  const submitted = await clickCaptchaAction(frame, config.submitTexts, config).catch(() => false);
3282
4175
  if (!submitted) {
3283
- logger9.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
4176
+ logger10.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
3284
4177
  }
3285
4178
  await page.waitForTimeout(config.submitWaitMs);
3286
4179
  const stillVisible = await iframeLocator.isVisible({ timeout: config.containerVisibleTimeoutMs }).catch(() => false);
3287
4180
  if (!stillVisible) {
3288
- logger9.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
4181
+ logger10.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
3289
4182
  return true;
3290
4183
  }
3291
- logger9.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
4184
+ logger10.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
3292
4185
  await page.waitForTimeout(2e3);
3293
4186
  await refreshCaptcha(page, frame, config);
3294
4187
  } catch (error) {
3295
- logger9.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
4188
+ logger10.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
3296
4189
  }
3297
4190
  if (attempt < config.maxRetries) {
3298
4191
  await page.waitForTimeout(config.retryDelayBaseMs + attempt * config.retryDelayStepMs);
3299
4192
  }
3300
4193
  }
3301
- logger9.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
4194
+ logger10.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
3302
4195
  return false;
3303
4196
  }
3304
4197
  var sloveCaptcha = solveCaptcha;
3305
4198
 
3306
4199
  // src/chaptcha.js
3307
- var logger10 = createInternalLogger("Captcha");
4200
+ var logger11 = createInternalLogger("Captcha");
3308
4201
  var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
3309
4202
  token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
3310
4203
  apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
@@ -3391,7 +4284,7 @@ function useCaptchaMonitor(page, options) {
3391
4284
  };
3392
4285
  })();
3393
4286
  }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
3394
- logger10.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
4287
+ logger11.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
3395
4288
  cleanupFns.push(async () => {
3396
4289
  try {
3397
4290
  await page.evaluate((name) => {
@@ -3415,14 +4308,14 @@ function useCaptchaMonitor(page, options) {
3415
4308
  }
3416
4309
  };
3417
4310
  page.on("framenavigated", frameHandler);
3418
- logger10.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
4311
+ logger11.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
3419
4312
  cleanupFns.push(async () => {
3420
4313
  page.off("framenavigated", frameHandler);
3421
4314
  });
3422
4315
  }
3423
4316
  return {
3424
4317
  stop: async () => {
3425
- logger10.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
4318
+ logger11.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
3426
4319
  for (const fn of cleanupFns) {
3427
4320
  await fn();
3428
4321
  }
@@ -3461,7 +4354,7 @@ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
3461
4354
  );
3462
4355
  return strategy.sloveCaptcha(page, resolvedOptions, {
3463
4356
  callCaptchaRecognitionApi,
3464
- logger: logger10
4357
+ logger: logger11
3465
4358
  });
3466
4359
  }
3467
4360
  var Captcha = {
@@ -3472,7 +4365,7 @@ var Captcha = {
3472
4365
  // src/mutation.js
3473
4366
  var import_node_crypto = require("node:crypto");
3474
4367
  var import_uuid2 = require("uuid");
3475
- var logger11 = createInternalLogger("Mutation");
4368
+ var logger12 = createInternalLogger("Mutation");
3476
4369
  var MUTATION_MONITOR_MODE = Object.freeze({
3477
4370
  Added: "added",
3478
4371
  Changed: "changed",
@@ -3505,14 +4398,14 @@ var Mutation = {
3505
4398
  const stableTime = options.stableTime ?? 5 * 1e3;
3506
4399
  const timeout = options.timeout ?? 120 * 1e3;
3507
4400
  const onMutation = options.onMutation;
3508
- logger11.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
4401
+ logger12.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
3509
4402
  if (initialTimeout > 0) {
3510
4403
  const selectorQuery = selectorList.join(",");
3511
4404
  try {
3512
4405
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3513
- logger11.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
4406
+ logger12.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3514
4407
  } catch (e) {
3515
- logger11.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
4408
+ logger12.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3516
4409
  throw e;
3517
4410
  }
3518
4411
  }
@@ -3528,7 +4421,7 @@ var Mutation = {
3528
4421
  return "__CONTINUE__";
3529
4422
  }
3530
4423
  });
3531
- logger11.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
4424
+ logger12.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
3532
4425
  } catch (e) {
3533
4426
  }
3534
4427
  }
@@ -3643,9 +4536,9 @@ var Mutation = {
3643
4536
  { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
3644
4537
  );
3645
4538
  if (result.mutationCount === 0 && result.stableTime === 0) {
3646
- logger11.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
4539
+ logger12.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3647
4540
  }
3648
- logger11.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
4541
+ logger12.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3649
4542
  return result;
3650
4543
  },
3651
4544
  /**
@@ -3817,22 +4710,22 @@ var Mutation = {
3817
4710
  return "__CONTINUE__";
3818
4711
  }
3819
4712
  };
3820
- logger11.start(
4713
+ logger12.start(
3821
4714
  "waitForStableAcrossRoots",
3822
4715
  `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
3823
4716
  );
3824
4717
  if (initialTimeout > 0) {
3825
4718
  try {
3826
4719
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
3827
- logger11.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
4720
+ logger12.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
3828
4721
  } catch (e) {
3829
- logger11.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
4722
+ logger12.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
3830
4723
  throw e;
3831
4724
  }
3832
4725
  }
3833
4726
  let state = await buildState();
3834
4727
  if (!state?.hasMatched) {
3835
- logger11.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
4728
+ logger12.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
3836
4729
  return { mutationCount: 0, stableTime: 0, wasPaused: false };
3837
4730
  }
3838
4731
  let mutationCount = 0;
@@ -3869,7 +4762,7 @@ var Mutation = {
3869
4762
  if (lastState.snapshotKey !== lastSnapshotKey) {
3870
4763
  lastSnapshotKey = lastState.snapshotKey;
3871
4764
  mutationCount += 1;
3872
- logger11.info(
4765
+ logger12.info(
3873
4766
  `waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
3874
4767
  );
3875
4768
  const signal = await invokeMutationCallback({
@@ -3882,7 +4775,7 @@ var Mutation = {
3882
4775
  continue;
3883
4776
  }
3884
4777
  if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
3885
- logger11.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
4778
+ logger12.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
3886
4779
  return {
3887
4780
  mutationCount,
3888
4781
  stableTime: waitForStableTime,
@@ -3909,7 +4802,7 @@ var Mutation = {
3909
4802
  const onMutation = options.onMutation;
3910
4803
  const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
3911
4804
  const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
3912
- logger11.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
4805
+ logger12.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
3913
4806
  const monitorKey = generateKey("pk_mon");
3914
4807
  const callbackName = generateKey("pk_mon_cb");
3915
4808
  const cleanerName = generateKey("pk_mon_clean");
@@ -4052,7 +4945,7 @@ var Mutation = {
4052
4945
  return total;
4053
4946
  };
4054
4947
  }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
4055
- logger11.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
4948
+ logger12.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
4056
4949
  return {
4057
4950
  stop: async () => {
4058
4951
  let totalMutations = 0;
@@ -4065,7 +4958,7 @@ var Mutation = {
4065
4958
  }, cleanerName);
4066
4959
  } catch (e) {
4067
4960
  }
4068
- logger11.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
4961
+ logger12.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
4069
4962
  return { totalMutations };
4070
4963
  }
4071
4964
  };
@@ -4934,7 +5827,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
4934
5827
  };
4935
5828
  var getDefaultBaseLogger = () => createBaseLogger("");
4936
5829
  var Logger = {
4937
- setLogger: (logger15) => setDefaultLogger(logger15),
5830
+ setLogger: (logger16) => setDefaultLogger(logger16),
4938
5831
  info: (message) => getDefaultBaseLogger().info(message),
4939
5832
  success: (message) => getDefaultBaseLogger().success(message),
4940
5833
  warning: (message) => getDefaultBaseLogger().warning(message),
@@ -4942,14 +5835,14 @@ var Logger = {
4942
5835
  error: (message) => getDefaultBaseLogger().error(message),
4943
5836
  debug: (message) => getDefaultBaseLogger().debug(message),
4944
5837
  start: (message) => getDefaultBaseLogger().start(message),
4945
- useTemplate: (logger15) => {
4946
- if (logger15) return createTemplateLogger(createBaseLogger("", logger15));
5838
+ useTemplate: (logger16) => {
5839
+ if (logger16) return createTemplateLogger(createBaseLogger("", logger16));
4947
5840
  return createTemplateLogger();
4948
5841
  }
4949
5842
  };
4950
5843
 
4951
5844
  // src/share.js
4952
- var import_delay2 = __toESM(require("delay"), 1);
5845
+ var import_delay3 = __toESM(require("delay"), 1);
4953
5846
 
4954
5847
  // src/internals/watermarkify.js
4955
5848
  var DEFAULT_TIMEZONE_OFFSET = 8;
@@ -5008,7 +5901,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
5008
5901
  ];
5009
5902
  var cachedStripLogoSrcPromise = null;
5010
5903
  var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
5011
- var logger12 = createInternalLogger("Watermarkify");
5904
+ var logger13 = createInternalLogger("Watermarkify");
5012
5905
  var normalizeText = (value) => String(value || "").trim();
5013
5906
  var toInline = (value, maxLen = 200) => {
5014
5907
  const text = normalizeText(value);
@@ -5250,9 +6143,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
5250
6143
  location: toInline(resolved.location, 80)
5251
6144
  };
5252
6145
  if (enrichment.ip || enrichment.location) {
5253
- logger12.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
6146
+ logger13.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
5254
6147
  } else {
5255
- logger12.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
6148
+ logger13.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
5256
6149
  }
5257
6150
  return enrichment;
5258
6151
  } finally {
@@ -5436,12 +6329,12 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height }) => {
5436
6329
  };
5437
6330
  var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}) => {
5438
6331
  if (!page || typeof page.context !== "function") {
5439
- logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
6332
+ logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
5440
6333
  return buffer;
5441
6334
  }
5442
6335
  const renderScope = await openProbePage(page);
5443
6336
  if (!renderScope?.page) {
5444
- logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
6337
+ logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
5445
6338
  return buffer;
5446
6339
  }
5447
6340
  try {
@@ -5484,13 +6377,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
5484
6377
  fullPage: true,
5485
6378
  animations: "disabled"
5486
6379
  }).catch((error) => {
5487
- logger12.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6380
+ logger13.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
5488
6381
  return null;
5489
6382
  });
5490
6383
  if (Buffer.isBuffer(composed) && composed.length > 0) {
5491
6384
  return composed;
5492
6385
  }
5493
- logger12.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
6386
+ logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
5494
6387
  return buffer;
5495
6388
  } finally {
5496
6389
  await renderScope.close().catch(() => {
@@ -5503,7 +6396,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
5503
6396
  }
5504
6397
  const probeScope = await openProbePage(page);
5505
6398
  if (!probeScope?.page) {
5506
- logger12.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
6399
+ logger13.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
5507
6400
  return null;
5508
6401
  }
5509
6402
  const timeoutMs = Math.max(
@@ -5512,12 +6405,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
5512
6405
  );
5513
6406
  try {
5514
6407
  const probePage = probeScope.page;
5515
- logger12.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
6408
+ logger13.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
5516
6409
  const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
5517
6410
  waitUntil: "commit",
5518
6411
  timeout: timeoutMs
5519
6412
  }).catch((error) => {
5520
- logger12.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
6413
+ logger13.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
5521
6414
  return null;
5522
6415
  });
5523
6416
  const status = response && typeof response.status === "function" ? response.status() : 0;
@@ -5539,13 +6432,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
5539
6432
  }
5540
6433
  const parsed = parseIpIpJsonResponse(rawText);
5541
6434
  if (parsed?.ip || parsed?.location) {
5542
- logger12.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
6435
+ logger13.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
5543
6436
  return parsed;
5544
6437
  }
5545
- logger12.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
6438
+ logger13.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
5546
6439
  return null;
5547
6440
  } catch (error) {
5548
- logger12.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
6441
+ logger13.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
5549
6442
  return null;
5550
6443
  } finally {
5551
6444
  await probeScope.close().catch(() => {
@@ -5559,10 +6452,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5559
6452
  ip: toInline(options.ip, 80),
5560
6453
  location: toInline(options.location, 80)
5561
6454
  };
5562
- logger12.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
6455
+ logger13.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
5563
6456
  if (!merged.ip || !merged.location) {
5564
6457
  if (cached?.ip || cached?.location) {
5565
- logger12.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
6458
+ logger13.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
5566
6459
  }
5567
6460
  fillEnrichment(merged, cached);
5568
6461
  }
@@ -5586,15 +6479,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
5586
6479
  "x-geo-country"
5587
6480
  ]), 80);
5588
6481
  if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
5589
- logger12.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
6482
+ logger13.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
5590
6483
  merged.location = headerLocation || merged.location;
5591
6484
  }
5592
6485
  }
5593
6486
  writeCachedEnrichment(page, merged);
5594
6487
  if (merged.ip || merged.location) {
5595
- logger12.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
6488
+ logger13.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
5596
6489
  } else {
5597
- logger12.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
6490
+ logger13.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
5598
6491
  }
5599
6492
  return merged;
5600
6493
  };
@@ -6262,7 +7155,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6262
7155
  }
6263
7156
  const imageInfo = readImageInfo(buffer);
6264
7157
  if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
6265
- logger12.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
7158
+ logger13.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
6266
7159
  return buffer;
6267
7160
  }
6268
7161
  const overlaySvg = buildWatermarkifySvg(meta, imageInfo.width, imageInfo.height);
@@ -6274,7 +7167,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
6274
7167
 
6275
7168
  // src/internals/screenshot-compression.js
6276
7169
  var import_jimp = require("jimp");
6277
- var logger13 = createInternalLogger("ScreenshotCompression");
7170
+ var logger14 = createInternalLogger("ScreenshotCompression");
6278
7171
  var DEFAULT_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
6279
7172
  var DEFAULT_SCREENSHOT_OUTPUT_TYPE = "jpeg";
6280
7173
  var DEFAULT_SCREENSHOT_QUALITY = 0.72;
@@ -6393,18 +7286,18 @@ var compressScreenshotBufferToBase64 = async (buffer, compression) => {
6393
7286
  return buffer.toString("base64");
6394
7287
  }
6395
7288
  const result = await compressScreenshotBuffer(buffer, compression).catch((error) => {
6396
- logger13.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
7289
+ logger14.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
6397
7290
  return null;
6398
7291
  });
6399
7292
  if (!result?.buffer) {
6400
7293
  return buffer.toString("base64");
6401
7294
  }
6402
7295
  if (result.withinLimit) {
6403
- logger13.info(
7296
+ logger14.info(
6404
7297
  `captureScreen \u5DF2\u538B\u7F29: ${originalBytes} -> ${result.bytes} bytes, format=${result.format}, quality=${result.quality}, scale=${result.scale}, size=${result.width}x${result.height}`
6405
7298
  );
6406
7299
  } else {
6407
- logger13.warning(
7300
+ logger14.warning(
6408
7301
  `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}`
6409
7302
  );
6410
7303
  }
@@ -6412,7 +7305,7 @@ var compressScreenshotBufferToBase64 = async (buffer, compression) => {
6412
7305
  };
6413
7306
 
6414
7307
  // src/share.js
6415
- var logger14 = createInternalLogger("Share");
7308
+ var logger15 = createInternalLogger("Share");
6416
7309
  var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
6417
7310
  var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
6418
7311
  var DEFAULT_POLL_INTERVAL_MS = 120;
@@ -6549,7 +7442,7 @@ var createDomShareMonitor = async (page, options = {}) => {
6549
7442
  const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
6550
7443
  const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
6551
7444
  let matched = false;
6552
- logger14.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
7445
+ logger15.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
6553
7446
  const monitor = await Mutation.useMonitor(page, selectors, {
6554
7447
  mode,
6555
7448
  onMutation: (context = {}) => {
@@ -6567,12 +7460,12 @@ ${text}`;
6567
7460
  });
6568
7461
  }
6569
7462
  if (mutationCount <= 5 || mutationCount % 50 === 0) {
6570
- logger14.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
7463
+ logger15.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
6571
7464
  }
6572
7465
  const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
6573
7466
  if (!candidate) return;
6574
7467
  matched = true;
6575
- logger14.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
7468
+ logger15.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
6576
7469
  if (onMatch) {
6577
7470
  onMatch({
6578
7471
  link: candidate,
@@ -6588,7 +7481,7 @@ ${text}`;
6588
7481
  return {
6589
7482
  stop: async () => {
6590
7483
  const result = await monitor.stop();
6591
- logger14.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
7484
+ logger15.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
6592
7485
  return result;
6593
7486
  }
6594
7487
  };
@@ -6628,8 +7521,8 @@ var Share = {
6628
7521
  if (share.mode === "response" && apiMatchers.length === 0) {
6629
7522
  throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
6630
7523
  }
6631
- logger14.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
6632
- logger14.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
7524
+ logger15.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
7525
+ logger15.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
6633
7526
  const stats = {
6634
7527
  actionTimedOut: false,
6635
7528
  domMutationCount: 0,
@@ -6654,7 +7547,7 @@ var Share = {
6654
7547
  link: validated,
6655
7548
  payloadText: String(payloadText || "")
6656
7549
  };
6657
- logger14.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
7550
+ logger15.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
6658
7551
  return true;
6659
7552
  };
6660
7553
  const resolveResponseCandidate = (responseText) => {
@@ -6689,7 +7582,7 @@ var Share = {
6689
7582
  try {
6690
7583
  await monitor.stop();
6691
7584
  } catch (error) {
6692
- logger14.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
7585
+ logger15.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
6693
7586
  }
6694
7587
  };
6695
7588
  const onResponse = async (response) => {
@@ -6702,29 +7595,29 @@ var Share = {
6702
7595
  stats.responseSampleUrls.push(url);
6703
7596
  }
6704
7597
  if (stats.responseObserved <= 5) {
6705
- logger14.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
7598
+ logger15.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
6706
7599
  }
6707
7600
  if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
6708
7601
  stats.responseMatched += 1;
6709
7602
  stats.lastMatchedUrl = url;
6710
- logger14.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
7603
+ logger15.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
6711
7604
  const text = await response.text();
6712
7605
  const hit = resolveResponseCandidate(text);
6713
7606
  if (!hit?.link) {
6714
7607
  if (stats.responseMatched <= 3) {
6715
- logger14.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
7608
+ logger15.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
6716
7609
  }
6717
7610
  return;
6718
7611
  }
6719
7612
  stats.responseResolved += 1;
6720
- logger14.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
7613
+ logger15.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
6721
7614
  setCandidate("response", hit.link, hit.payloadText);
6722
7615
  } catch (error) {
6723
- logger14.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
7616
+ logger15.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
6724
7617
  }
6725
7618
  };
6726
7619
  if (share.mode === "dom") {
6727
- logger14.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
7620
+ logger15.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
6728
7621
  domMonitor = await createDomShareMonitor(page, {
6729
7622
  prefix: share.prefix,
6730
7623
  selectors: domSelectors,
@@ -6739,14 +7632,14 @@ var Share = {
6739
7632
  });
6740
7633
  }
6741
7634
  if (share.mode === "response") {
6742
- logger14.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
7635
+ logger15.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
6743
7636
  page.on("response", onResponse);
6744
7637
  }
6745
7638
  const deadline = Date.now() + timeoutMs;
6746
7639
  const getRemainingMs = () => Math.max(0, deadline - Date.now());
6747
7640
  try {
6748
7641
  const actionTimeout = getRemainingMs();
6749
- logger14.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
7642
+ logger15.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
6750
7643
  if (actionTimeout > 0) {
6751
7644
  let timer = null;
6752
7645
  let actionError = null;
@@ -6760,21 +7653,21 @@ var Share = {
6760
7653
  const actionResult = await Promise.race([actionPromise, timeoutPromise]);
6761
7654
  if (timer) clearTimeout(timer);
6762
7655
  if (actionResult === "__ACTION_ERROR__") {
6763
- logger14.fail("captureLink.performActions", actionError);
7656
+ logger15.fail("captureLink.performActions", actionError);
6764
7657
  throw actionError;
6765
7658
  }
6766
7659
  if (actionResult === "__ACTION_TIMEOUT__") {
6767
7660
  stats.actionTimedOut = true;
6768
- logger14.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
7661
+ logger15.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
6769
7662
  } else {
6770
- logger14.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
7663
+ logger15.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
6771
7664
  }
6772
7665
  }
6773
7666
  let nextProgressLogTs = Date.now() + 3e3;
6774
7667
  while (true) {
6775
7668
  const selected = share.mode === "dom" ? candidates.dom : candidates.response;
6776
7669
  if (selected?.link) {
6777
- logger14.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
7670
+ logger15.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
6778
7671
  return {
6779
7672
  link: selected.link,
6780
7673
  payloadText: selected.payloadText,
@@ -6786,19 +7679,19 @@ var Share = {
6786
7679
  if (remaining <= 0) break;
6787
7680
  const now = Date.now();
6788
7681
  if (now >= nextProgressLogTs) {
6789
- logger14.info(
7682
+ logger15.info(
6790
7683
  `captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
6791
7684
  );
6792
7685
  nextProgressLogTs = now + 5e3;
6793
7686
  }
6794
- await (0, import_delay2.default)(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
7687
+ await (0, import_delay3.default)(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
6795
7688
  }
6796
7689
  if (share.mode === "response" && stats.responseMatched === 0) {
6797
- logger14.warning(
7690
+ logger15.warning(
6798
7691
  `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
6799
7692
  );
6800
7693
  }
6801
- logger14.warning(
7694
+ logger15.warning(
6802
7695
  `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"}`
6803
7696
  );
6804
7697
  return {
@@ -6810,7 +7703,7 @@ var Share = {
6810
7703
  } finally {
6811
7704
  if (share.mode === "response") {
6812
7705
  page.off("response", onResponse);
6813
- logger14.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
7706
+ logger15.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
6814
7707
  }
6815
7708
  await stopDomMonitor();
6816
7709
  }
@@ -6862,7 +7755,7 @@ var Share = {
6862
7755
  width: originalViewport.width,
6863
7756
  height: targetHeight
6864
7757
  });
6865
- await (0, import_delay2.default)(1e3);
7758
+ await (0, import_delay3.default)(1e3);
6866
7759
  const capturedAt = /* @__PURE__ */ new Date();
6867
7760
  const rawBuffer = await capturePageScreenshot(page, {
6868
7761
  fullPage: true,
@@ -6903,7 +7796,7 @@ var usePlaywrightToolKit = () => {
6903
7796
  return {
6904
7797
  ApifyKit,
6905
7798
  AntiCheat,
6906
- Humanize,
7799
+ Humanize: Humanize2,
6907
7800
  Launch,
6908
7801
  LiveView,
6909
7802
  Constants: constants_exports,