@skrillex1224/playwright-toolkit 3.0.15 → 3.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -13,9 +13,12 @@ __export(constants_exports, {
13
13
  ActorInfo: () => ActorInfo,
14
14
  Code: () => Code,
15
15
  Device: () => Device,
16
+ Mode: () => Mode,
16
17
  PresetOfLiveViewKey: () => PresetOfLiveViewKey,
17
18
  Status: () => Status,
18
- normalizeDevice: () => normalizeDevice
19
+ mode: () => mode,
20
+ normalizeDevice: () => normalizeDevice,
21
+ normalizeMode: () => normalizeMode
19
22
  });
20
23
  var Code = {
21
24
  Success: 0,
@@ -35,6 +38,14 @@ var Device = Object.freeze({
35
38
  Desktop: "desktop",
36
39
  Mobile: "mobile"
37
40
  });
41
+ var Mode = Object.freeze({
42
+ Default: "default",
43
+ Cloak: "cloak"
44
+ });
45
+ var mode = Object.freeze({
46
+ default: Mode.Default,
47
+ cloak: Mode.Cloak
48
+ });
38
49
  var normalizeDevice = (value, fallback = Device.Desktop) => {
39
50
  const normalizedFallback = String(fallback || "").trim().toLowerCase() === Device.Mobile ? Device.Mobile : Device.Desktop;
40
51
  const raw = String(value || "").trim().toLowerCase();
@@ -42,6 +53,13 @@ var normalizeDevice = (value, fallback = Device.Desktop) => {
42
53
  if (raw === Device.Desktop) return Device.Desktop;
43
54
  return normalizedFallback;
44
55
  };
56
+ var normalizeMode = (value, fallback = Mode.Default) => {
57
+ const normalizedFallback = String(fallback || "").trim().toLowerCase() === Mode.Cloak ? Mode.Cloak : Mode.Default;
58
+ const raw = String(value || "").trim().toLowerCase();
59
+ if (raw === Mode.Cloak) return Mode.Cloak;
60
+ if (raw === Mode.Default) return Mode.Default;
61
+ return normalizedFallback;
62
+ };
45
63
  var createActorInfo = (info) => {
46
64
  const normalizeDomain = (value) => {
47
65
  if (!value) return "";
@@ -56,7 +74,7 @@ var createActorInfo = (info) => {
56
74
  const normalizeShare2 = (value) => {
57
75
  const raw = value && typeof value === "object" ? value : {};
58
76
  const modeRaw = String(raw.mode || "dom").trim().toLowerCase();
59
- const mode = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
77
+ const mode2 = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
60
78
  const prefix = String(raw.prefix || "").trim();
61
79
  const rawXurl = Array.isArray(raw.xurl) ? raw.xurl : [];
62
80
  const normalizeMatcherList = (input) => {
@@ -101,7 +119,7 @@ var createActorInfo = (info) => {
101
119
  xurl.push(...extraPaths);
102
120
  }
103
121
  return {
104
- mode,
122
+ mode: mode2,
105
123
  prefix,
106
124
  xurl
107
125
  };
@@ -109,7 +127,6 @@ var createActorInfo = (info) => {
109
127
  const buildLandingUrl = ({ protocol: protocol2, domain: domain2, path: path4 }) => {
110
128
  const safeProtocol = String(protocol2).trim();
111
129
  const safeDomain = normalizeDomain(domain2);
112
- if (!safeDomain) return "";
113
130
  const safePath = normalizePath(path4);
114
131
  return `${safeProtocol}://${safeDomain}${safePath}`;
115
132
  };
@@ -317,18 +334,6 @@ var ActorInfo = {
317
334
  prefix: "",
318
335
  xurl: []
319
336
  }
320
- }),
321
- // 通用网页抓取 Actor:入口 URL 来自 query,因此这里只声明统一的 Actor 元信息。
322
- webpage: createActorInfo({
323
- key: "webpage",
324
- name: "\u901A\u7528\u7F51\u9875",
325
- domain: "",
326
- path: "/",
327
- share: {
328
- mode: "dom",
329
- prefix: "",
330
- xurl: []
331
- }
332
337
  })
333
338
  };
334
339
 
@@ -360,18 +365,18 @@ var fallbackLog = {
360
365
  error: (...args) => console.error(...args),
361
366
  debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
362
367
  };
363
- var resolveLogMethod = (logger16, name) => {
364
- if (logger16 && typeof logger16[name] === "function") {
365
- return logger16[name].bind(logger16);
368
+ var resolveLogMethod = (logger17, name) => {
369
+ if (logger17 && typeof logger17[name] === "function") {
370
+ return logger17[name].bind(logger17);
366
371
  }
367
- if (name === "warning" && logger16 && typeof logger16.warn === "function") {
368
- return logger16.warn.bind(logger16);
372
+ if (name === "warning" && logger17 && typeof logger17.warn === "function") {
373
+ return logger17.warn.bind(logger17);
369
374
  }
370
375
  return fallbackLog[name];
371
376
  };
372
377
  var defaultLogger = null;
373
- var setDefaultLogger = (logger16) => {
374
- defaultLogger = logger16;
378
+ var setDefaultLogger = (logger17) => {
379
+ defaultLogger = logger17;
375
380
  };
376
381
  var resolveLogger = (explicitLogger) => {
377
382
  if (explicitLogger && typeof explicitLogger.info === "function") {
@@ -398,8 +403,8 @@ var colorize = (text, color) => {
398
403
  var createBaseLogger = (prefix = "", explicitLogger) => {
399
404
  const name = prefix ? String(prefix) : "";
400
405
  const dispatch = (methodName, icon, message, color) => {
401
- const logger16 = resolveLogger(explicitLogger);
402
- const logFn = resolveLogMethod(logger16, methodName);
406
+ const logger17 = resolveLogger(explicitLogger);
407
+ const logFn = resolveLogMethod(logger17, methodName);
403
408
  const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
404
409
  const line = formatLine(name, icon, message);
405
410
  const coloredLine = colorize(line, color);
@@ -753,7 +758,7 @@ var adjustAffixedElementsForExpandedScreenshot = async (page, options = {}) => {
753
758
  if (safeTargetHeight <= viewportHeight + 1) {
754
759
  return 0;
755
760
  }
756
- const hasOwn = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
761
+ const hasOwn2 = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
757
762
  const isVisible = (el, style, rect) => {
758
763
  if (!el || !style || !rect) return false;
759
764
  if (style.display === "none" || style.visibility === "hidden" || style.visibility === "collapse") {
@@ -793,7 +798,7 @@ var adjustAffixedElementsForExpandedScreenshot = async (page, options = {}) => {
793
798
  return true;
794
799
  });
795
800
  topLevelCandidates.forEach(({ el, position, edge }) => {
796
- if (!hasOwn(el.dataset, "pkAffixedAdjusted")) {
801
+ if (!hasOwn2(el.dataset, "pkAffixedAdjusted")) {
797
802
  el.dataset.pkAffixedAdjusted = "1";
798
803
  el.dataset.pkOrigPosition = el.style.getPropertyValue("position") || "";
799
804
  el.dataset.pkOrigPositionPriority = el.style.getPropertyPriority("position") || "";
@@ -824,7 +829,7 @@ var adjustAffixedElementsForExpandedScreenshot = async (page, options = {}) => {
824
829
  };
825
830
  var restoreAffixedElementsForExpandedScreenshot = async (page) => {
826
831
  await page.evaluate((className) => {
827
- const hasOwn = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
832
+ const hasOwn2 = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
828
833
  const expansionKeys = [
829
834
  "pkOrigOverflow",
830
835
  "pkOrigHeight",
@@ -832,28 +837,28 @@ var restoreAffixedElementsForExpandedScreenshot = async (page) => {
832
837
  "pkOrigMaxHeight"
833
838
  ];
834
839
  document.querySelectorAll('[data-pk-affixed-adjusted="1"]').forEach((el) => {
835
- if (hasOwn(el.dataset, "pkOrigPosition")) {
840
+ if (hasOwn2(el.dataset, "pkOrigPosition")) {
836
841
  el.style.setProperty("position", el.dataset.pkOrigPosition || "", el.dataset.pkOrigPositionPriority || "");
837
842
  delete el.dataset.pkOrigPosition;
838
843
  delete el.dataset.pkOrigPositionPriority;
839
844
  }
840
- if (hasOwn(el.dataset, "pkOrigTop")) {
845
+ if (hasOwn2(el.dataset, "pkOrigTop")) {
841
846
  el.style.setProperty("top", el.dataset.pkOrigTop || "", el.dataset.pkOrigTopPriority || "");
842
847
  delete el.dataset.pkOrigTop;
843
848
  delete el.dataset.pkOrigTopPriority;
844
849
  }
845
- if (hasOwn(el.dataset, "pkOrigBottom")) {
850
+ if (hasOwn2(el.dataset, "pkOrigBottom")) {
846
851
  el.style.setProperty("bottom", el.dataset.pkOrigBottom || "", el.dataset.pkOrigBottomPriority || "");
847
852
  delete el.dataset.pkOrigBottom;
848
853
  delete el.dataset.pkOrigBottomPriority;
849
854
  }
850
- if (hasOwn(el.dataset, "pkOrigTranslate")) {
855
+ if (hasOwn2(el.dataset, "pkOrigTranslate")) {
851
856
  el.style.setProperty("translate", el.dataset.pkOrigTranslate || "", el.dataset.pkOrigTranslatePriority || "");
852
857
  delete el.dataset.pkOrigTranslate;
853
858
  delete el.dataset.pkOrigTranslatePriority;
854
859
  }
855
860
  delete el.dataset.pkAffixedAdjusted;
856
- const stillExpanded = expansionKeys.some((key) => hasOwn(el.dataset, key));
861
+ const stillExpanded = expansionKeys.some((key) => hasOwn2(el.dataset, key));
857
862
  if (!stillExpanded) {
858
863
  el.classList.remove(className);
859
864
  }
@@ -896,7 +901,7 @@ var prepareExpandedFullPageScreenshot = async (page, options = {}) => {
896
901
  viewportResized
897
902
  };
898
903
  };
899
- var restoreExpandedFullPageScreenshot = async (page, state = {}) => {
904
+ var restoreExpandedFullPageScreenshot = async (page, state2 = {}) => {
900
905
  await page.evaluate((className) => {
901
906
  const targets = new Set([
902
907
  ...document.querySelectorAll(`.${className}`),
@@ -920,8 +925,8 @@ var restoreExpandedFullPageScreenshot = async (page, state = {}) => {
920
925
  el.classList.remove(className);
921
926
  });
922
927
  }, EXPANDED_SCROLLABLE_CLASS);
923
- if (state?.originalViewport && state?.viewportResized) {
924
- await page.setViewportSize(state.originalViewport);
928
+ if (state2?.originalViewport && state2?.viewportResized) {
929
+ await page.setViewportSize(state2.originalViewport);
925
930
  }
926
931
  };
927
932
  var capturePageScreenshot = async (page, options = {}) => {
@@ -978,21 +983,21 @@ var capturePageScreenshot = async (page, options = {}) => {
978
983
  }
979
984
  };
980
985
  var captureExpandedFullPageScreenshot = async (page, options = {}) => {
981
- const state = await prepareExpandedFullPageScreenshot(page, options);
986
+ const state2 = await prepareExpandedFullPageScreenshot(page, options);
982
987
  try {
983
988
  return await capturePageScreenshot(page, {
984
989
  fullPage: true,
985
990
  type: options.type || "png",
986
991
  quality: options.quality,
987
992
  timeout: options.timeout,
988
- maxClipHeight: state.targetHeight
993
+ maxClipHeight: state2.targetHeight
989
994
  });
990
995
  } finally {
991
996
  await restoreAffixedElementsForExpandedScreenshot(page).catch((error) => {
992
997
  logger.warning(`\u79FB\u52A8\u7AEF\u5438\u9644\u5143\u7D20\u6062\u590D\u5931\u8D25: ${error?.message || error}`);
993
998
  });
994
999
  if (options.restore) {
995
- await restoreExpandedFullPageScreenshot(page, state);
1000
+ await restoreExpandedFullPageScreenshot(page, state2);
996
1001
  }
997
1002
  }
998
1003
  };
@@ -1910,8 +1915,8 @@ var normalizeBrowserProfile = (value) => {
1910
1915
  payload: buildBrowserProfilePayload(core, observed)
1911
1916
  };
1912
1917
  };
1913
- var rememberRuntimeState = (state) => {
1914
- rememberedRuntimeState = deepClone(state);
1918
+ var rememberRuntimeState = (state2) => {
1919
+ rememberedRuntimeState = deepClone(state2);
1915
1920
  return rememberedRuntimeState;
1916
1921
  };
1917
1922
  var normalizeRuntimeState = (source = {}, actor = "") => {
@@ -1970,7 +1975,7 @@ var RuntimeEnv = {
1970
1975
  } else {
1971
1976
  delete normalizedRuntime.browser_profile;
1972
1977
  }
1973
- const state = {
1978
+ const state2 = {
1974
1979
  actor: resolvedActor,
1975
1980
  device,
1976
1981
  runtime: normalizedRuntime,
@@ -1984,73 +1989,73 @@ var RuntimeEnv = {
1984
1989
  browserProfileCore: browserProfile.core,
1985
1990
  browserProfileObserved: browserProfile.observed
1986
1991
  };
1987
- rememberRuntimeState(state);
1988
- return state;
1992
+ rememberRuntimeState(state2);
1993
+ return state2;
1989
1994
  },
1990
1995
  // buildEnvPatch 只构造允许回写到后端 env 的字段集合。
1991
1996
  buildEnvPatch(source = {}, actor = "") {
1992
- const state = normalizeRuntimeState(source, actor);
1993
- const browserProfile = buildBrowserProfilePayload(state.browserProfileCore, state.browserProfileObserved);
1997
+ const state2 = normalizeRuntimeState(source, actor);
1998
+ const browserProfile = buildBrowserProfilePayload(state2.browserProfileCore, state2.browserProfileObserved);
1994
1999
  const envPatch = {
1995
- ...Array.isArray(state.cookies) && state.cookies.length > 0 ? { cookies: state.cookies } : {},
1996
- ...Object.keys(state.localStorage || {}).length > 0 ? { local_storage: state.localStorage } : {},
1997
- ...Object.keys(state.sessionStorage || {}).length > 0 ? { session_storage: state.sessionStorage } : {},
2000
+ ...Array.isArray(state2.cookies) && state2.cookies.length > 0 ? { cookies: state2.cookies } : {},
2001
+ ...Object.keys(state2.localStorage || {}).length > 0 ? { local_storage: state2.localStorage } : {},
2002
+ ...Object.keys(state2.sessionStorage || {}).length > 0 ? { session_storage: state2.sessionStorage } : {},
1998
2003
  ...Object.keys(browserProfile).length > 0 ? { browser_profile: browserProfile } : {}
1999
2004
  };
2000
2005
  return Object.keys(envPatch).length > 0 ? envPatch : null;
2001
2006
  },
2002
2007
  // hasLoginState 只判断 runtime 是否存在有效载荷,不再区分具体字段来源。
2003
2008
  hasLoginState(source = {}, actor = "") {
2004
- const state = normalizeRuntimeState(source, actor);
2005
- return isPlainObject(state.runtime) && Object.keys(state.runtime || {}).length > 0;
2009
+ const state2 = normalizeRuntimeState(source, actor);
2010
+ return isPlainObject(state2.runtime) && Object.keys(state2.runtime || {}).length > 0;
2006
2011
  },
2007
2012
  rememberState(source = {}) {
2008
- const state = normalizeRuntimeState(source);
2009
- rememberRuntimeState(state);
2013
+ const state2 = normalizeRuntimeState(source);
2014
+ rememberRuntimeState(state2);
2010
2015
  return RuntimeEnv.peekRememberedState();
2011
2016
  },
2012
2017
  peekRememberedState() {
2013
2018
  return rememberedRuntimeState ? deepClone(rememberedRuntimeState) : null;
2014
2019
  },
2015
2020
  getBrowserProfileCore(source = {}, actor = "") {
2016
- const state = normalizeRuntimeState(source, actor);
2017
- return deepClone(state.browserProfileCore || {});
2021
+ const state2 = normalizeRuntimeState(source, actor);
2022
+ return deepClone(state2.browserProfileCore || {});
2018
2023
  },
2019
2024
  setBrowserProfileCore(source = {}, core = {}, actor = "") {
2020
- const state = normalizeRuntimeState(source, actor);
2025
+ const state2 = normalizeRuntimeState(source, actor);
2021
2026
  const normalizedCore = normalizeBrowserProfileCore({
2022
2027
  ...core,
2023
- device: normalizeKnownDevice(core?.device) || state.device
2028
+ device: normalizeKnownDevice(core?.device) || state2.device
2024
2029
  });
2025
- state.browserProfileCore = normalizedCore;
2026
- state.browserProfile = buildBrowserProfilePayload(normalizedCore, state.browserProfileObserved);
2027
- if (Object.keys(state.browserProfile).length > 0) {
2028
- state.runtime.browser_profile = state.browserProfile;
2030
+ state2.browserProfileCore = normalizedCore;
2031
+ state2.browserProfile = buildBrowserProfilePayload(normalizedCore, state2.browserProfileObserved);
2032
+ if (Object.keys(state2.browserProfile).length > 0) {
2033
+ state2.runtime.browser_profile = state2.browserProfile;
2029
2034
  } else {
2030
- delete state.runtime.browser_profile;
2035
+ delete state2.runtime.browser_profile;
2031
2036
  }
2032
- rememberRuntimeState(state);
2033
- return state;
2037
+ rememberRuntimeState(state2);
2038
+ return state2;
2034
2039
  },
2035
2040
  // applyToPage 只负责把登录态相关字段注入页面:
2036
2041
  // cookies / localStorage / sessionStorage。
2037
2042
  // 指纹、时区、UA、viewport 的回放发生在 launch.js 启动阶段,不在这里做。
2038
2043
  async applyToPage(page, source = {}, options = {}) {
2039
2044
  if (!page) return;
2040
- let state = normalizeRuntimeState(source, options?.actor || "");
2045
+ let state2 = normalizeRuntimeState(source, options?.actor || "");
2041
2046
  if (typeof options?.preapply === "function") {
2042
- state = await options.preapply(state) || state;
2043
- rememberRuntimeState(state);
2047
+ state2 = await options.preapply(state2) || state2;
2048
+ rememberRuntimeState(state2);
2044
2049
  }
2045
2050
  Object.defineProperty(page, PageRuntimeStateKey, {
2046
2051
  configurable: true,
2047
2052
  enumerable: false,
2048
2053
  writable: true,
2049
- value: state
2054
+ value: state2
2050
2055
  });
2051
- const localStorage = state.localStorage || {};
2052
- const sessionStorage = state.sessionStorage || {};
2053
- const cookies = (state.cookies || []).map((cookie) => {
2056
+ const localStorage = state2.localStorage || {};
2057
+ const sessionStorage = state2.sessionStorage || {};
2058
+ const cookies = (state2.cookies || []).map((cookie) => {
2054
2059
  const normalized = { ...cookie };
2055
2060
  if (!normalized.path) {
2056
2061
  normalized.path = "/";
@@ -2088,8 +2093,8 @@ var RuntimeEnv = {
2088
2093
  },
2089
2094
  // captureEnvPatch 在任务结束时采集最新环境快照,用于 pushSuccess / pushFailed 自动回写。
2090
2095
  async captureEnvPatch(page, source = {}, options = {}) {
2091
- const state = normalizeRuntimeState(source, options?.actor || "");
2092
- const baseline = RuntimeEnv.buildEnvPatch(state) || {};
2096
+ const state2 = normalizeRuntimeState(source, options?.actor || "");
2097
+ const baseline = RuntimeEnv.buildEnvPatch(state2) || {};
2093
2098
  if (!page || typeof page.evaluate !== "function" || typeof page.context !== "function") {
2094
2099
  return Object.keys(baseline).length > 0 ? baseline : null;
2095
2100
  }
@@ -2108,7 +2113,7 @@ var RuntimeEnv = {
2108
2113
  cookies
2109
2114
  },
2110
2115
  {
2111
- browserProfileCore: state.browserProfileCore
2116
+ browserProfileCore: state2.browserProfileCore
2112
2117
  }
2113
2118
  );
2114
2119
  return RuntimeEnv.mergeEnvPatches(baseline, capturedPatch);
@@ -2122,11 +2127,11 @@ var RuntimeEnv = {
2122
2127
  var logger3 = createInternalLogger("ApifyKit");
2123
2128
  var resolveRuntimeContext = (input) => {
2124
2129
  const rememberedState = RuntimeEnv.peekRememberedState();
2125
- const state = rememberedState || RuntimeEnv.parseInput(input || {});
2126
- const envPatch = RuntimeEnv.buildEnvPatch(state) || null;
2130
+ const state2 = rememberedState || RuntimeEnv.parseInput(input || {});
2131
+ const envPatch = RuntimeEnv.buildEnvPatch(state2) || null;
2127
2132
  return {
2128
- actor: state.actor,
2129
- runtime: state.runtime,
2133
+ actor: state2.actor,
2134
+ runtime: state2.runtime,
2130
2135
  envPatch
2131
2136
  };
2132
2137
  };
@@ -2485,8 +2490,82 @@ var Utils = {
2485
2490
  }
2486
2491
  };
2487
2492
 
2488
- // src/anti-cheat.js
2489
- var logger5 = createInternalLogger("AntiCheat");
2493
+ // src/internals/context.js
2494
+ var state = {
2495
+ mode: Mode.Default
2496
+ };
2497
+ var normalizeStrategies = (strategies) => strategies && typeof strategies === "object" ? strategies : {};
2498
+ var ToolkitContext = {
2499
+ get mode() {
2500
+ return state.mode;
2501
+ },
2502
+ setMode(mode2 = Mode.Default) {
2503
+ state.mode = normalizeMode(mode2, Mode.Default);
2504
+ return state.mode;
2505
+ }
2506
+ };
2507
+ var getToolkitMode = () => state.mode;
2508
+ var setToolkitMode = (mode2 = Mode.Default) => ToolkitContext.setMode(mode2);
2509
+ var resolveModeStrategy = (strategies = {}, mode2 = getToolkitMode(), fallbackMode = Mode.Default) => {
2510
+ const normalizedStrategies = normalizeStrategies(strategies);
2511
+ const normalizedMode = normalizeMode(mode2, fallbackMode);
2512
+ const strategy = normalizedStrategies[normalizedMode] ?? normalizedStrategies[fallbackMode] ?? Object.values(normalizedStrategies).find(Boolean) ?? null;
2513
+ return {
2514
+ mode: normalizedMode,
2515
+ strategy
2516
+ };
2517
+ };
2518
+
2519
+ // src/internals/reflect.js
2520
+ var normalizeStrategies2 = (strategies) => strategies && typeof strategies === "object" ? strategies : {};
2521
+ var collectFunctionNames = (strategies = []) => {
2522
+ const names = /* @__PURE__ */ new Set();
2523
+ for (const strategy of strategies) {
2524
+ if (!strategy || typeof strategy !== "object") continue;
2525
+ for (const name of Reflect.ownKeys(strategy)) {
2526
+ if (typeof name === "string" && typeof strategy[name] === "function") {
2527
+ names.add(name);
2528
+ }
2529
+ }
2530
+ }
2531
+ return names;
2532
+ };
2533
+ var methodDescriptor = (namespace, name, resolveTarget) => ({
2534
+ enumerable: true,
2535
+ configurable: true,
2536
+ writable: true,
2537
+ value: (...args) => {
2538
+ const { mode: mode2, strategy } = resolveTarget(args);
2539
+ const method = strategy?.[name];
2540
+ if (typeof method !== "function") {
2541
+ throw new Error(`${namespace}.${name} is not available in ${mode2} mode`);
2542
+ }
2543
+ return method.apply(strategy, args);
2544
+ }
2545
+ });
2546
+ var withModeReflect = (namespace, strategies = {}) => {
2547
+ const normalizedStrategies = normalizeStrategies2(strategies);
2548
+ const baseStrategy = normalizedStrategies.default ?? Object.values(normalizedStrategies).find(Boolean);
2549
+ const names = collectFunctionNames([baseStrategy]);
2550
+ const descriptors = {};
2551
+ for (const name of names) {
2552
+ descriptors[name] = methodDescriptor(namespace, name, () => resolveModeStrategy(normalizedStrategies));
2553
+ }
2554
+ return Object.defineProperties({}, descriptors);
2555
+ };
2556
+ var withPageReflect = (namespace, resolveStrategy, strategies = []) => {
2557
+ const names = collectFunctionNames(strategies);
2558
+ const descriptors = {};
2559
+ for (const name of names) {
2560
+ descriptors[name] = methodDescriptor(namespace, name, ([page]) => ({
2561
+ mode: "page",
2562
+ strategy: resolveStrategy(page)
2563
+ }));
2564
+ }
2565
+ return Object.defineProperties({}, descriptors);
2566
+ };
2567
+
2568
+ // src/internals/anti-cheat/default.js
2490
2569
  var BASE_CONFIG = Object.freeze({
2491
2570
  locale: "zh-CN",
2492
2571
  acceptLanguage: "zh-CN,zh;q=0.9",
@@ -2521,7 +2600,7 @@ function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVers
2521
2600
  }
2522
2601
  return options;
2523
2602
  }
2524
- var AntiCheat = {
2603
+ var DefaultAntiCheat = {
2525
2604
  /**
2526
2605
  * 获取统一的基础配置
2527
2606
  */
@@ -2558,6 +2637,47 @@ var AntiCheat = {
2558
2637
  }
2559
2638
  };
2560
2639
 
2640
+ // src/internals/anti-cheat/cloak.js
2641
+ var CLOAK_BASE_CONFIG = Object.freeze({
2642
+ locale: "",
2643
+ acceptLanguage: "",
2644
+ timezoneId: "",
2645
+ timezoneOffset: null,
2646
+ geolocation: null
2647
+ });
2648
+ var normalizeHeaders = (headers) => headers && typeof headers === "object" ? headers : {};
2649
+ var CloakAntiCheat = {
2650
+ /**
2651
+ * Cloak 自身会负责浏览器指纹,toolkit 在该模式下尽量不再注入额外反检测配置。
2652
+ */
2653
+ getBaseConfig() {
2654
+ return { ...CLOAK_BASE_CONFIG };
2655
+ },
2656
+ getFingerprintGeneratorOptions() {
2657
+ return {};
2658
+ },
2659
+ getLaunchArgs() {
2660
+ return [];
2661
+ },
2662
+ getTlsFingerprintOptions() {
2663
+ return {};
2664
+ },
2665
+ applyLocaleHeaders(headers, acceptLanguage = "") {
2666
+ const normalizedHeaders = normalizeHeaders(headers);
2667
+ if (acceptLanguage && !normalizedHeaders["accept-language"]) {
2668
+ normalizedHeaders["accept-language"] = acceptLanguage;
2669
+ }
2670
+ return normalizedHeaders;
2671
+ }
2672
+ };
2673
+
2674
+ // src/anti-cheat.js
2675
+ var antiCheatStrategies = {
2676
+ [Mode.Default]: DefaultAntiCheat,
2677
+ [Mode.Cloak]: CloakAntiCheat
2678
+ };
2679
+ var AntiCheat = withModeReflect("AntiCheat", antiCheatStrategies);
2680
+
2561
2681
  // src/device-input.js
2562
2682
  var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
2563
2683
  var assertPage = (page, method) => {
@@ -2957,12 +3077,12 @@ var resolveDescriptor = (descriptor, device) => {
2957
3077
  }
2958
3078
  return resolved;
2959
3079
  };
2960
- var attachRuntimeState = (page, state) => {
3080
+ var attachRuntimeState = (page, state2) => {
2961
3081
  Object.defineProperty(page, PageRuntimeStateKey, {
2962
3082
  configurable: true,
2963
3083
  enumerable: false,
2964
3084
  writable: true,
2965
- value: state
3085
+ value: state2
2966
3086
  });
2967
3087
  };
2968
3088
  var restoreRuntimeState = (page, snapshot) => {
@@ -3108,10 +3228,13 @@ var DeviceView = {
3108
3228
  }
3109
3229
  };
3110
3230
 
3231
+ // src/internals/humanize/index.js
3232
+ import delay4 from "delay";
3233
+
3111
3234
  // src/internals/humanize/desktop.js
3112
3235
  import delay2 from "delay";
3113
3236
  import { createCursor } from "ghost-cursor-playwright";
3114
- var logger6 = createInternalLogger("Humanize");
3237
+ var logger5 = createInternalLogger("Humanize");
3115
3238
  var $CursorWeakMap = /* @__PURE__ */ new WeakMap();
3116
3239
  function $GetCursor(page) {
3117
3240
  const cursor = $CursorWeakMap.get(page);
@@ -3139,13 +3262,13 @@ var Humanize = {
3139
3262
  */
3140
3263
  async initializeCursor(page) {
3141
3264
  if ($CursorWeakMap.has(page)) {
3142
- logger6.debug("initializeCursor: cursor already exists, skipping");
3265
+ logger5.debug("initializeCursor: cursor already exists, skipping");
3143
3266
  return;
3144
3267
  }
3145
- logger6.start("initializeCursor", "creating cursor");
3268
+ logger5.start("initializeCursor", "creating cursor");
3146
3269
  const cursor = await createCursor(page);
3147
3270
  $CursorWeakMap.set(page, cursor);
3148
- logger6.success("initializeCursor", "cursor initialized");
3271
+ logger5.success("initializeCursor", "cursor initialized");
3149
3272
  },
3150
3273
  /**
3151
3274
  * 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
@@ -3155,17 +3278,17 @@ var Humanize = {
3155
3278
  */
3156
3279
  async humanMove(page, target) {
3157
3280
  const cursor = $GetCursor(page);
3158
- logger6.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
3281
+ logger5.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
3159
3282
  try {
3160
3283
  if (typeof target === "string") {
3161
3284
  const element = await page.$(target);
3162
3285
  if (!element) {
3163
- logger6.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
3286
+ logger5.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
3164
3287
  return false;
3165
3288
  }
3166
3289
  const box = await element.boundingBox();
3167
3290
  if (!box) {
3168
- logger6.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
3291
+ logger5.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
3169
3292
  return false;
3170
3293
  }
3171
3294
  const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;
@@ -3181,10 +3304,10 @@ var Humanize = {
3181
3304
  await cursor.actions.move({ x, y });
3182
3305
  }
3183
3306
  }
3184
- logger6.success("humanMove");
3307
+ logger5.success("humanMove");
3185
3308
  return true;
3186
3309
  } catch (error) {
3187
- logger6.fail("humanMove", error);
3310
+ logger5.fail("humanMove", error);
3188
3311
  throw error;
3189
3312
  }
3190
3313
  },
@@ -3208,12 +3331,12 @@ var Humanize = {
3208
3331
  maxDurationMs = maxSteps * 220 + 800
3209
3332
  } = options;
3210
3333
  const targetDesc = typeof target === "string" ? target : "ElementHandle";
3211
- logger6.start("humanScroll", `target=${targetDesc}`);
3334
+ logger5.start("humanScroll", `target=${targetDesc}`);
3212
3335
  let element;
3213
3336
  if (typeof target === "string") {
3214
3337
  element = await page.$(target);
3215
3338
  if (!element) {
3216
- logger6.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
3339
+ logger5.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
3217
3340
  return { element: null, didScroll: false };
3218
3341
  }
3219
3342
  } else {
@@ -3288,26 +3411,26 @@ var Humanize = {
3288
3411
  try {
3289
3412
  for (let i = 0; i < maxSteps; i++) {
3290
3413
  if (Date.now() - startTime > maxDurationMs) {
3291
- logger6.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
3414
+ logger5.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
3292
3415
  return { element, didScroll };
3293
3416
  }
3294
3417
  const status = await checkVisibility();
3295
3418
  if (status.code === "VISIBLE") {
3296
3419
  if (status.isFixed) {
3297
- logger6.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3420
+ logger5.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3298
3421
  } else {
3299
- logger6.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
3422
+ logger5.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
3300
3423
  }
3301
- logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
3424
+ logger5.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
3302
3425
  return { element, didScroll };
3303
3426
  }
3304
- logger6.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
3427
+ logger5.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
3305
3428
  if (status.code === "OBSTRUCTED" && status.obstruction) {
3306
- logger6.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
3429
+ logger5.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
3307
3430
  }
3308
3431
  const scrollRect = await getScrollableRect2();
3309
3432
  if (!scrollRect && status.isFixed) {
3310
- logger6.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3433
+ logger5.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3311
3434
  return { element, didScroll };
3312
3435
  }
3313
3436
  const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
@@ -3343,10 +3466,10 @@ var Humanize = {
3343
3466
  didScroll = true;
3344
3467
  await delay2(this.jitterMs(20 + Math.random() * 40, 0.2));
3345
3468
  }
3346
- logger6.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
3469
+ logger5.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
3347
3470
  return { element, didScroll };
3348
3471
  } catch (error) {
3349
- logger6.fail("humanScroll", error);
3472
+ logger5.fail("humanScroll", error);
3350
3473
  throw error;
3351
3474
  }
3352
3475
  },
@@ -3364,7 +3487,7 @@ var Humanize = {
3364
3487
  const cursor = $GetCursor(page);
3365
3488
  const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;
3366
3489
  const targetDesc = target == null ? "Current Position" : typeof target === "string" ? target : "ElementHandle";
3367
- logger6.start("humanClick", `target=${targetDesc}`);
3490
+ logger5.start("humanClick", `target=${targetDesc}`);
3368
3491
  const restoreOnce = async () => {
3369
3492
  if (restoreOnce.restored) return;
3370
3493
  restoreOnce.restored = true;
@@ -3373,14 +3496,14 @@ var Humanize = {
3373
3496
  await delay2(this.jitterMs(1e3));
3374
3497
  await restoreOnce.do();
3375
3498
  } catch (restoreError) {
3376
- logger6.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
3499
+ logger5.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
3377
3500
  }
3378
3501
  };
3379
3502
  try {
3380
3503
  if (target == null) {
3381
3504
  await delay2(this.jitterMs(reactionDelay, 0.4));
3382
3505
  await cursor.actions.click();
3383
- logger6.success("humanClick", "Clicked current position");
3506
+ logger5.success("humanClick", "Clicked current position");
3384
3507
  return true;
3385
3508
  }
3386
3509
  let element;
@@ -3390,7 +3513,7 @@ var Humanize = {
3390
3513
  if (throwOnMissing) {
3391
3514
  throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);
3392
3515
  }
3393
- logger6.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
3516
+ logger5.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
3394
3517
  return false;
3395
3518
  }
3396
3519
  } else {
@@ -3406,7 +3529,7 @@ var Humanize = {
3406
3529
  if (throwOnMissing) {
3407
3530
  throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
3408
3531
  }
3409
- logger6.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
3532
+ logger5.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
3410
3533
  return false;
3411
3534
  }
3412
3535
  const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
@@ -3415,11 +3538,11 @@ var Humanize = {
3415
3538
  await delay2(this.jitterMs(reactionDelay, 0.4));
3416
3539
  await cursor.actions.click();
3417
3540
  await restoreOnce();
3418
- logger6.success("humanClick");
3541
+ logger5.success("humanClick");
3419
3542
  return true;
3420
3543
  } catch (error) {
3421
3544
  await restoreOnce();
3422
- logger6.fail("humanClick", error);
3545
+ logger5.fail("humanClick", error);
3423
3546
  throw error;
3424
3547
  }
3425
3548
  },
@@ -3430,9 +3553,9 @@ var Humanize = {
3430
3553
  */
3431
3554
  async randomSleep(baseMs, jitterPercent = 0.3) {
3432
3555
  const ms = this.jitterMs(baseMs, jitterPercent);
3433
- logger6.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
3556
+ logger5.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
3434
3557
  await delay2(ms);
3435
- logger6.success("randomSleep");
3558
+ logger5.success("randomSleep");
3436
3559
  },
3437
3560
  /**
3438
3561
  * 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
@@ -3442,7 +3565,7 @@ var Humanize = {
3442
3565
  async simulateGaze(page, baseDurationMs = 2500) {
3443
3566
  const cursor = $GetCursor(page);
3444
3567
  const durationMs = this.jitterMs(baseDurationMs, 0.4);
3445
- logger6.start("simulateGaze", `duration=${durationMs}ms`);
3568
+ logger5.start("simulateGaze", `duration=${durationMs}ms`);
3446
3569
  const startTime = Date.now();
3447
3570
  const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
3448
3571
  while (Date.now() - startTime < durationMs) {
@@ -3451,7 +3574,7 @@ var Humanize = {
3451
3574
  await cursor.actions.move({ x, y });
3452
3575
  await delay2(this.jitterMs(600, 0.5));
3453
3576
  }
3454
- logger6.success("simulateGaze");
3577
+ logger5.success("simulateGaze");
3455
3578
  },
3456
3579
  /**
3457
3580
  * 人类化输入 - 带节奏变化(快-慢-停顿-偶尔加速)
@@ -3464,7 +3587,7 @@ var Humanize = {
3464
3587
  * @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
3465
3588
  */
3466
3589
  async humanType(page, selector, text, options = {}) {
3467
- logger6.start("humanType", `selector=${selector}, textLen=${text.length}`);
3590
+ logger5.start("humanType", `selector=${selector}, textLen=${text.length}`);
3468
3591
  const {
3469
3592
  baseDelay = 180,
3470
3593
  pauseProbability = 0.08,
@@ -3488,13 +3611,13 @@ var Humanize = {
3488
3611
  await delay2(charDelay);
3489
3612
  if (Math.random() < pauseProbability && i < text.length - 1) {
3490
3613
  const pauseTime = this.jitterMs(pauseBase, 0.5);
3491
- logger6.debug(`\u505C\u987F ${pauseTime}ms...`);
3614
+ logger5.debug(`\u505C\u987F ${pauseTime}ms...`);
3492
3615
  await delay2(pauseTime);
3493
3616
  }
3494
3617
  }
3495
- logger6.success("humanType");
3618
+ logger5.success("humanType");
3496
3619
  } catch (error) {
3497
- logger6.fail("humanType", error);
3620
+ logger5.fail("humanType", error);
3498
3621
  throw error;
3499
3622
  }
3500
3623
  },
@@ -3518,7 +3641,7 @@ var Humanize = {
3518
3641
  keyboardOptions = {}
3519
3642
  } = pressOptions || {};
3520
3643
  const targetDesc = hasTarget ? typeof targetOrKey === "string" ? targetOrKey : "ElementHandle" : "current focus";
3521
- logger6.start("humanPress", `key=${key}, target=${targetDesc}`);
3644
+ logger5.start("humanPress", `key=${key}, target=${targetDesc}`);
3522
3645
  try {
3523
3646
  if (hasTarget) {
3524
3647
  await this.humanClick(page, targetOrKey, { reactionDelay: focusDelay, scrollIfNeeded, throwOnMissing });
@@ -3528,10 +3651,10 @@ var Humanize = {
3528
3651
  ...keyboardOptions,
3529
3652
  delay: this.jitterMs(holdDelay, 0.5)
3530
3653
  });
3531
- logger6.success("humanPress");
3654
+ logger5.success("humanPress");
3532
3655
  return true;
3533
3656
  } catch (error) {
3534
- logger6.fail("humanPress", error);
3657
+ logger5.fail("humanPress", error);
3535
3658
  throw error;
3536
3659
  }
3537
3660
  },
@@ -3541,22 +3664,22 @@ var Humanize = {
3541
3664
  * @param {string} selector - 输入框选择器
3542
3665
  */
3543
3666
  async humanClear(page, selector) {
3544
- logger6.start("humanClear", `selector=${selector}`);
3667
+ logger5.start("humanClear", `selector=${selector}`);
3545
3668
  try {
3546
3669
  const locator = page.locator(selector);
3547
3670
  await locator.click();
3548
3671
  await delay2(this.jitterMs(200, 0.4));
3549
3672
  const currentValue = await locator.inputValue();
3550
3673
  if (!currentValue || currentValue.length === 0) {
3551
- logger6.success("humanClear", "already empty");
3674
+ logger5.success("humanClear", "already empty");
3552
3675
  return;
3553
3676
  }
3554
3677
  await page.keyboard.press("Meta+A");
3555
3678
  await delay2(this.jitterMs(100, 0.4));
3556
3679
  await page.keyboard.press("Backspace");
3557
- logger6.success("humanClear");
3680
+ logger5.success("humanClear");
3558
3681
  } catch (error) {
3559
- logger6.fail("humanClear", error);
3682
+ logger5.fail("humanClear", error);
3560
3683
  throw error;
3561
3684
  }
3562
3685
  },
@@ -3568,7 +3691,7 @@ var Humanize = {
3568
3691
  async warmUpBrowsing(page, baseDuration = 3500) {
3569
3692
  const cursor = $GetCursor(page);
3570
3693
  const durationMs = this.jitterMs(baseDuration, 0.4);
3571
- logger6.start("warmUpBrowsing", `duration=${durationMs}ms`);
3694
+ logger5.start("warmUpBrowsing", `duration=${durationMs}ms`);
3572
3695
  const startTime = Date.now();
3573
3696
  const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
3574
3697
  try {
@@ -3587,9 +3710,9 @@ var Humanize = {
3587
3710
  await delay2(this.jitterMs(800, 0.5));
3588
3711
  }
3589
3712
  }
3590
- logger6.success("warmUpBrowsing");
3713
+ logger5.success("warmUpBrowsing");
3591
3714
  } catch (error) {
3592
- logger6.fail("warmUpBrowsing", error);
3715
+ logger5.fail("warmUpBrowsing", error);
3593
3716
  throw error;
3594
3717
  }
3595
3718
  },
@@ -3603,7 +3726,7 @@ var Humanize = {
3603
3726
  async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
3604
3727
  const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
3605
3728
  const actualDistance = this.jitterMs(distance, 0.15);
3606
- logger6.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
3729
+ logger5.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
3607
3730
  const sign = direction === "down" ? 1 : -1;
3608
3731
  const stepDistance = actualDistance / steps;
3609
3732
  try {
@@ -3615,9 +3738,9 @@ var Humanize = {
3615
3738
  const baseDelay = 60 + i * 25;
3616
3739
  await delay2(this.jitterMs(baseDelay, 0.3));
3617
3740
  }
3618
- logger6.success("naturalScroll");
3741
+ logger5.success("naturalScroll");
3619
3742
  } catch (error) {
3620
- logger6.fail("naturalScroll", error);
3743
+ logger5.fail("naturalScroll", error);
3621
3744
  throw error;
3622
3745
  }
3623
3746
  }
@@ -3646,7 +3769,7 @@ var resolveElement = async (page, target, { throwOnMissing = true } = {}) => {
3646
3769
  var waitJitter = (base, jitterPercent = 0.3) => delay3(jitterMs(base, jitterPercent));
3647
3770
 
3648
3771
  // src/internals/humanize/mobile.js
3649
- var logger7 = createInternalLogger("Humanize.Mobile");
3772
+ var logger6 = createInternalLogger("Humanize.Mobile");
3650
3773
  var initializedPages = /* @__PURE__ */ new WeakSet();
3651
3774
  var DEFAULT_TAP_TIMEOUT_MS = 2500;
3652
3775
  var DEFAULT_MOUSE_TAP_FALLBACK_TIMEOUT_MS = 1200;
@@ -4016,7 +4139,7 @@ var restoreWindowFromSnapshot = async (page, before, after) => {
4016
4139
  return;
4017
4140
  }
4018
4141
  await page.evaluate(
4019
- (state) => window.scrollTo(state.x, state.y),
4142
+ (state2) => window.scrollTo(state2.x, state2.y),
4020
4143
  { x: Number(before.scrollX || 0), y: Number(before.scrollY || 0) }
4021
4144
  ).catch(() => {
4022
4145
  });
@@ -4103,7 +4226,7 @@ var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
4103
4226
  }
4104
4227
  return true;
4105
4228
  } catch (error) {
4106
- logger7.debug(`touch swipe fallback: ${error?.message || error}`);
4229
+ logger6.debug(`touch swipe fallback: ${error?.message || error}`);
4107
4230
  try {
4108
4231
  await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
4109
4232
  await waitJitter(120, 0.35);
@@ -4137,7 +4260,7 @@ var tapPoint = async (page, point, options = {}) => {
4137
4260
  );
4138
4261
  return { method: "touchscreen" };
4139
4262
  } catch (error) {
4140
- logger7.warn(`tapPoint | touchscreen.tap \u5931\u8D25\u6216\u8D85\u65F6\uFF0C\u5C1D\u8BD5\u9F20\u6807\u515C\u5E95: ${error?.message || error}`);
4263
+ logger6.warn(`tapPoint | touchscreen.tap \u5931\u8D25\u6216\u8D85\u65F6\uFF0C\u5C1D\u8BD5\u9F20\u6807\u515C\u5E95: ${error?.message || error}`);
4141
4264
  if (!allowMouseFallback) throw error;
4142
4265
  }
4143
4266
  }
@@ -4153,10 +4276,10 @@ var MobileHumanize = {
4153
4276
  async initializeCursor(page) {
4154
4277
  if (initializedPages.has(page)) return;
4155
4278
  initializedPages.add(page);
4156
- logger7.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
4279
+ logger6.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
4157
4280
  },
4158
4281
  async humanMove(page, target) {
4159
- logger7.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
4282
+ logger6.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
4160
4283
  if (typeof target === "string" || target && typeof target.boundingBox === "function") {
4161
4284
  const element = await resolveElement(page, target, { throwOnMissing: false });
4162
4285
  if (!element) {
@@ -4175,10 +4298,10 @@ var MobileHumanize = {
4175
4298
  throwOnMissing = false
4176
4299
  } = options;
4177
4300
  const targetDesc = describeTarget(target);
4178
- logger7.start("humanScroll", `target=${targetDesc}`);
4301
+ logger6.start("humanScroll", `target=${targetDesc}`);
4179
4302
  const element = await resolveElement(page, target, { throwOnMissing });
4180
4303
  if (!element) {
4181
- logger7.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${targetDesc}`);
4304
+ logger6.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${targetDesc}`);
4182
4305
  return { element: null, didScroll: false, restore: null };
4183
4306
  }
4184
4307
  const startTime = Date.now();
@@ -4187,42 +4310,42 @@ var MobileHumanize = {
4187
4310
  const status = await checkElementVisibility(element);
4188
4311
  if (status.code === "VISIBLE") {
4189
4312
  if (status.isFixed) {
4190
- logger7.info("humanScroll | fixed/sticky \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
4313
+ logger6.info("humanScroll | fixed/sticky \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
4191
4314
  } else {
4192
- logger7.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
4315
+ logger6.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
4193
4316
  }
4194
- logger7.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
4317
+ logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
4195
4318
  return { element, didScroll, restore: null };
4196
4319
  }
4197
4320
  if (status.code === "ZERO_DIMENSIONS" || status.code === "NOT_INTERACTABLE") {
4198
- logger7.warn(`humanScroll | \u5143\u7D20\u4E0D\u53EF\u6EDA\u52A8\u81F3\u53EF\u70B9\u51FB\u72B6\u6001: ${status.reason || status.code}`);
4321
+ logger6.warn(`humanScroll | \u5143\u7D20\u4E0D\u53EF\u6EDA\u52A8\u81F3\u53EF\u70B9\u51FB\u72B6\u6001: ${status.reason || status.code}`);
4199
4322
  return { element, didScroll, restore: null };
4200
4323
  }
4201
4324
  const scrollRect = await getScrollableRect(element);
4202
4325
  if (!scrollRect && status.isFixed && status.code === "OUT_OF_VIEWPORT") {
4203
- logger7.warn(`humanScroll | fixed/sticky \u76EE\u6807\u4E0D\u5728\u89C6\u53E3\u5185\uFF0C\u9875\u9762\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (direction=${status.direction || "unknown"})`);
4326
+ logger6.warn(`humanScroll | fixed/sticky \u76EE\u6807\u4E0D\u5728\u89C6\u53E3\u5185\uFF0C\u9875\u9762\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (direction=${status.direction || "unknown"})`);
4204
4327
  return { element, didScroll, restore: null, unscrollable: true };
4205
4328
  }
4206
4329
  if (!scrollRect && status.isFixed && status.code === "OBSTRUCTED") {
4207
- logger7.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
4330
+ logger6.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
4208
4331
  return { element, didScroll, restore: null, unscrollable: true };
4209
4332
  }
4210
4333
  if (scrollRect && status.code === "OBSTRUCTED" && status.obstruction?.isFixed) {
4211
4334
  const moved = await scrollAwayFromObstruction(element, status);
4212
4335
  if (moved.moved) {
4213
- logger7.debug(`humanScroll | sticky/fixed \u906E\u6321\u8865\u507F\u6EDA\u52A8 top=${Math.round(moved.scrollTop || 0)}`);
4336
+ logger6.debug(`humanScroll | sticky/fixed \u906E\u6321\u8865\u507F\u6EDA\u52A8 top=${Math.round(moved.scrollTop || 0)}`);
4214
4337
  await waitJitter(90, 0.3);
4215
4338
  didScroll = true;
4216
4339
  continue;
4217
4340
  }
4218
4341
  }
4219
4342
  if (Date.now() - startTime > maxDurationMs) {
4220
- logger7.warn(`humanScroll | mobile timeout (${maxDurationMs}ms, status=${status.code}, direction=${status.direction || "unknown"}, fixed=${Boolean(status.isFixed)})`);
4343
+ logger6.warn(`humanScroll | mobile timeout (${maxDurationMs}ms, status=${status.code}, direction=${status.direction || "unknown"}, fixed=${Boolean(status.isFixed)})`);
4221
4344
  return { element, didScroll, restore: null };
4222
4345
  }
4223
4346
  const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
4224
4347
  const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;
4225
- logger7.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason || status.code} ${status.direction ? `(${status.direction})` : ""}`);
4348
+ logger6.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason || status.code} ${status.direction ? `(${status.direction})` : ""}`);
4226
4349
  const distance = stepMin + Math.random() * Math.max(1, stepMax - stepMin);
4227
4350
  let deltaY = status.direction === "up" ? -distance : distance;
4228
4351
  if (status.code === "OBSTRUCTED") {
@@ -4262,8 +4385,8 @@ var MobileHumanize = {
4262
4385
  if (scrollRect && beforeWindowState) {
4263
4386
  const afterWindowState = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY }));
4264
4387
  if (Math.abs(afterWindowState.x - beforeWindowState.x) > 2 || Math.abs(afterWindowState.y - beforeWindowState.y) > 2) {
4265
- await page.evaluate((state) => window.scrollTo(state.x, state.y), beforeWindowState);
4266
- logger7.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
4388
+ await page.evaluate((state2) => window.scrollTo(state2.x, state2.y), beforeWindowState);
4389
+ logger6.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
4267
4390
  }
4268
4391
  }
4269
4392
  let afterElementSnapshot = null;
@@ -4277,7 +4400,7 @@ var MobileHumanize = {
4277
4400
  const afterSnapshot = await readAfterElementSnapshot();
4278
4401
  if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
4279
4402
  await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
4280
- logger7.warn(`humanScroll | \u76EE\u6807\u4E0D\u968F\u9875\u9762\u6EDA\u52A8\u79FB\u52A8\uFF0C\u9875\u9762\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (status=${status.code}, direction=${status.direction || "unknown"})`);
4403
+ logger6.warn(`humanScroll | \u76EE\u6807\u4E0D\u968F\u9875\u9762\u6EDA\u52A8\u79FB\u52A8\uFF0C\u9875\u9762\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (status=${status.code}, direction=${status.direction || "unknown"})`);
4281
4404
  return { element, didScroll, restore: null, unscrollable: true };
4282
4405
  }
4283
4406
  }
@@ -4309,12 +4432,12 @@ var MobileHumanize = {
4309
4432
  const moved = beforeState.kind !== afterState.kind || Math.abs(topDelta) > 2 || Math.abs(leftDelta) > 2;
4310
4433
  if (!moved) {
4311
4434
  const fallback = await scrollScrollableAncestor(element, deltaY);
4312
- 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)}`);
4435
+ logger6.debug(`humanScroll | \u5BB9\u5668\u89E6\u6478\u65E0\u6548\uFF0C\u76F4\u63A5\u6EDA\u52A8 fallback=${fallback.scroller ? "ancestor" : "window"} top=${Math.round(fallback.scrollTop || 0)}`);
4313
4436
  } 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)) {
4314
4437
  const residualDelta = expectedDelta - topDelta;
4315
4438
  if (Math.sign(residualDelta) === Math.sign(expectedDelta) && Math.abs(residualDelta) > 24) {
4316
4439
  const fallback = await scrollScrollableAncestor(element, residualDelta);
4317
- 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)}`);
4440
+ logger6.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)}`);
4318
4441
  }
4319
4442
  }
4320
4443
  }
@@ -4322,7 +4445,7 @@ var MobileHumanize = {
4322
4445
  const afterSnapshot = await getElementViewportSnapshot(element).catch(() => null);
4323
4446
  if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
4324
4447
  await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
4325
- logger7.warn(`humanScroll | \u76EE\u6807\u4E0D\u968F\u6EDA\u52A8\u5BB9\u5668\u79FB\u52A8\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (status=${status.code}, direction=${status.direction || "unknown"})`);
4448
+ logger6.warn(`humanScroll | \u76EE\u6807\u4E0D\u968F\u6EDA\u52A8\u5BB9\u5668\u79FB\u52A8\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (status=${status.code}, direction=${status.direction || "unknown"})`);
4326
4449
  return { element, didScroll, restore: null, unscrollable: true };
4327
4450
  }
4328
4451
  }
@@ -4333,14 +4456,14 @@ var MobileHumanize = {
4333
4456
  await waitJitter(80, 0.3);
4334
4457
  const finalStatus = await checkElementVisibility(element);
4335
4458
  if (finalStatus.code === "VISIBLE") {
4336
- logger7.info("humanScroll | \u539F\u751F scrollIntoViewIfNeeded \u515C\u5E95\u6210\u529F");
4337
- logger7.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
4459
+ logger6.info("humanScroll | \u539F\u751F scrollIntoViewIfNeeded \u515C\u5E95\u6210\u529F");
4460
+ logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
4338
4461
  return { element, didScroll: true, restore: null };
4339
4462
  }
4340
4463
  } catch (fallbackError) {
4341
- logger7.debug(`humanScroll | native fallback failed: ${fallbackError?.message || fallbackError}`);
4464
+ logger6.debug(`humanScroll | native fallback failed: ${fallbackError?.message || fallbackError}`);
4342
4465
  }
4343
- logger7.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
4466
+ logger6.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
4344
4467
  return { element, didScroll, restore: null };
4345
4468
  },
4346
4469
  async humanClick(page, target, options = {}) {
@@ -4355,7 +4478,7 @@ var MobileHumanize = {
4355
4478
  fallbackDomClickOnTapError = true
4356
4479
  } = options;
4357
4480
  const targetDesc = describeTarget(target);
4358
- logger7.start("humanClick", `target=${targetDesc}`);
4481
+ logger6.start("humanClick", `target=${targetDesc}`);
4359
4482
  try {
4360
4483
  if (target == null) {
4361
4484
  const viewport = resolveViewport(page);
@@ -4367,12 +4490,12 @@ var MobileHumanize = {
4367
4490
  timeoutMs: tapTimeoutMs,
4368
4491
  mouseFallbackTimeoutMs
4369
4492
  });
4370
- logger7.success("humanClick", "Tapped current position");
4493
+ logger6.success("humanClick", "Tapped current position");
4371
4494
  return true;
4372
4495
  }
4373
4496
  const element = await resolveElement(page, target, { throwOnMissing });
4374
4497
  if (!element) {
4375
- logger7.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
4498
+ logger6.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
4376
4499
  return false;
4377
4500
  }
4378
4501
  const scrollResult = scrollIfNeeded ? await MobileHumanize.humanScroll(page, element, { throwOnMissing }) : null;
@@ -4396,19 +4519,19 @@ var MobileHumanize = {
4396
4519
  ).catch(() => null);
4397
4520
  }
4398
4521
  if (fallback?.activated) {
4399
- logger7.warn(`humanClick: \u4E0D\u53EF\u6EDA\u52A8\u76EE\u6807\u4E0D\u53EF\u7269\u7406\u70B9\u51FB\uFF0C\u5DF2\u7528 ${fallback.method} \u6FC0\u6D3B`);
4522
+ logger6.warn(`humanClick: \u4E0D\u53EF\u6EDA\u52A8\u76EE\u6807\u4E0D\u53EF\u7269\u7406\u70B9\u51FB\uFF0C\u5DF2\u7528 ${fallback.method} \u6FC0\u6D3B`);
4400
4523
  return true;
4401
4524
  }
4402
4525
  }
4403
4526
  const message = `\u5143\u7D20\u4E0D\u53EF\u70B9\u51FB: ${status.reason || status.code}`;
4404
4527
  if (throwOnMissing) throw new Error(message);
4405
- logger7.warn(`humanClick: ${message}\uFF0C\u8DF3\u8FC7\u70B9\u51FB`);
4528
+ logger6.warn(`humanClick: ${message}\uFF0C\u8DF3\u8FC7\u70B9\u51FB`);
4406
4529
  return false;
4407
4530
  }
4408
4531
  const box = await element.boundingBox();
4409
4532
  if (!box) {
4410
4533
  if (throwOnMissing) throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
4411
- logger7.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
4534
+ logger6.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
4412
4535
  return false;
4413
4536
  }
4414
4537
  await waitJitter(reactionDelay, 0.45);
@@ -4429,13 +4552,13 @@ var MobileHumanize = {
4429
4552
  "activation fallback"
4430
4553
  ).catch(() => null);
4431
4554
  if (!fallback?.activated) throw tapError;
4432
- logger7.warn(`humanClick: tap \u5931\u8D25\u540E\u5DF2\u7528 ${fallback.method} \u515C\u5E95: ${tapError?.message || tapError}`);
4555
+ logger6.warn(`humanClick: tap \u5931\u8D25\u540E\u5DF2\u7528 ${fallback.method} \u515C\u5E95: ${tapError?.message || tapError}`);
4433
4556
  }
4434
4557
  await waitJitter(120, 0.35);
4435
- logger7.success("humanClick");
4558
+ logger6.success("humanClick");
4436
4559
  return true;
4437
4560
  } catch (error) {
4438
- logger7.fail("humanClick", error);
4561
+ logger6.fail("humanClick", error);
4439
4562
  throw error;
4440
4563
  }
4441
4564
  },
@@ -4488,7 +4611,7 @@ var MobileHumanize = {
4488
4611
  keyboardOptions = {}
4489
4612
  } = pressOptions || {};
4490
4613
  const targetDesc = hasTarget ? describeTarget(targetOrKey) : "current focus";
4491
- logger7.start("humanPress", `key=${key}, target=${targetDesc}`);
4614
+ logger6.start("humanPress", `key=${key}, target=${targetDesc}`);
4492
4615
  try {
4493
4616
  if (hasTarget) {
4494
4617
  await MobileHumanize.humanClick(page, targetOrKey, {
@@ -4502,10 +4625,10 @@ var MobileHumanize = {
4502
4625
  ...keyboardOptions,
4503
4626
  delay: jitterMs(holdDelay, 0.5)
4504
4627
  });
4505
- logger7.success("humanPress");
4628
+ logger6.success("humanPress");
4506
4629
  return true;
4507
4630
  } catch (error) {
4508
- logger7.fail("humanPress", error);
4631
+ logger6.fail("humanPress", error);
4509
4632
  throw error;
4510
4633
  }
4511
4634
  },
@@ -4572,65 +4695,96 @@ var MobileHumanize = {
4572
4695
  }
4573
4696
  };
4574
4697
 
4575
- // src/humanize.js
4698
+ // src/internals/humanize/default.js
4576
4699
  var resolveDeviceFromPage2 = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
4577
4700
  var resolveDelegate = (page) => {
4578
4701
  return resolveDeviceFromPage2(page) === Device.Mobile ? MobileHumanize : Humanize;
4579
4702
  };
4580
- var callDelegate = (method, page, args) => {
4581
- const delegate = resolveDelegate(page);
4582
- return delegate[method](page, ...args);
4703
+ var DefaultHumanizeDevice = withPageReflect(
4704
+ "DefaultHumanize",
4705
+ resolveDelegate,
4706
+ [Humanize, MobileHumanize]
4707
+ );
4708
+
4709
+ // src/internals/humanize/cloak.js
4710
+ var FORCE_CLICK = Object.freeze({
4711
+ forceClick: true,
4712
+ clickOptions: { force: true }
4713
+ });
4714
+ var pointOrNull = async (target) => {
4715
+ if (!target || typeof target.boundingBox !== "function") return null;
4716
+ const box = await target.boundingBox().catch(() => null);
4717
+ return box ? { x: box.x + box.width / 2, y: box.y + box.height / 2 } : null;
4583
4718
  };
4584
- var Humanize2 = {
4585
- jitterMs(base, jitterPercent = 0.3) {
4586
- return Humanize.jitterMs(base, jitterPercent);
4587
- },
4588
- initializeCursor(page) {
4589
- return callDelegate("initializeCursor", page, []);
4719
+ var CloakHumanizeInput = {
4720
+ async initializeCursor(page) {
4721
+ return Boolean(page);
4590
4722
  },
4591
- humanMove(page, target) {
4592
- return callDelegate("humanMove", page, [target]);
4723
+ async humanMove(page, target) {
4724
+ const point = target?.x != null && target?.y != null ? target : await pointOrNull(typeof target === "string" ? page.locator(target).first() : target);
4725
+ return point ? await DeviceInput.move(page, point, { forceMouse: true }) : false;
4593
4726
  },
4594
- humanScroll(page, target, options = {}) {
4595
- return callDelegate("humanScroll", page, [target, options]);
4727
+ async humanScroll(page, target) {
4728
+ const element = typeof target === "string" ? page.locator(target).first() : target;
4729
+ if (!element) return { element: null, didScroll: false, restore: null };
4730
+ await element.scrollIntoViewIfNeeded?.();
4731
+ return { element, didScroll: true, restore: null };
4596
4732
  },
4597
- humanClick(page, target, options = {}) {
4598
- return callDelegate("humanClick", page, [target, options]);
4733
+ async humanClick(page, target) {
4734
+ return await DeviceInput.click(page, target, FORCE_CLICK);
4599
4735
  },
4600
- randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
4601
- if (pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function") {
4602
- const delegate = resolveDelegate(pageOrBaseMs);
4603
- return delegate.randomSleep(maybeBaseMs, maybeJitterPercent);
4604
- }
4605
- return Humanize.randomSleep(pageOrBaseMs, maybeBaseMs);
4736
+ async humanType(page, selector, text) {
4737
+ await DeviceInput.click(page, selector, FORCE_CLICK);
4738
+ return await DeviceInput.keyboardType(page, text);
4606
4739
  },
4607
- simulateGaze(page, baseDurationMs = 2500) {
4608
- return callDelegate("simulateGaze", page, [baseDurationMs]);
4740
+ async humanPress(page, targetOrKey, maybeKey) {
4741
+ return await DeviceInput.press(page, targetOrKey, maybeKey, {
4742
+ clickOptions: FORCE_CLICK,
4743
+ keyboardOptions: {}
4744
+ });
4609
4745
  },
4610
- humanType(page, selector, text, options = {}) {
4611
- return callDelegate("humanType", page, [selector, text, options]);
4746
+ async humanClear(page, selector) {
4747
+ return await DeviceInput.fill(page, selector, "", { force: true });
4612
4748
  },
4613
- humanPress(page, targetOrKey, maybeKey, options = {}) {
4614
- if (typeof maybeKey === "string") {
4615
- return callDelegate("humanPress", page, [targetOrKey, maybeKey, options]);
4616
- }
4617
- return callDelegate("humanPress", page, [targetOrKey, maybeKey || options]);
4749
+ async simulateGaze(page) {
4750
+ return await DeviceInput.move(page, { x: 0, y: 0 }, { forceMouse: true });
4618
4751
  },
4619
- humanClear(page, selector) {
4620
- return callDelegate("humanClear", page, [selector]);
4752
+ async warmUpBrowsing(page) {
4753
+ return await this.simulateGaze(page);
4621
4754
  },
4622
- warmUpBrowsing(page, baseDuration = 3500) {
4623
- return callDelegate("warmUpBrowsing", page, [baseDuration]);
4755
+ async naturalScroll(page, direction = "down", distance = 300) {
4756
+ const sign = direction === "down" ? 1 : -1;
4757
+ await page.mouse.wheel(0, Number(distance || 0) * sign);
4758
+ }
4759
+ };
4760
+
4761
+ // src/internals/humanize/index.js
4762
+ var HumanizeCommon = {
4763
+ jitterMs(base, jitterPercent = 0.3) {
4764
+ return jitterMs(base, jitterPercent);
4624
4765
  },
4625
- naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
4626
- return callDelegate("naturalScroll", page, [direction, distance, baseSteps]);
4766
+ async randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
4767
+ const hasPage = pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function";
4768
+ const baseMs = hasPage ? maybeBaseMs : pageOrBaseMs;
4769
+ const jitterPercent = hasPage ? maybeJitterPercent : maybeBaseMs;
4770
+ await delay4(jitterMs(baseMs, jitterPercent ?? 0.3));
4627
4771
  }
4628
4772
  };
4773
+ var DefaultHumanize = Object.assign({}, DefaultHumanizeDevice, HumanizeCommon);
4774
+ var CloakHumanize = Object.assign({}, CloakHumanizeInput, HumanizeCommon);
4629
4775
 
4630
- // src/launch.js
4776
+ // src/humanize.js
4777
+ var humanizeStrategies = {
4778
+ [Mode.Default]: DefaultHumanize,
4779
+ [Mode.Cloak]: CloakHumanize
4780
+ };
4781
+ var Humanize2 = withModeReflect("Humanize", humanizeStrategies);
4782
+
4783
+ // src/internals/launch/default.js
4631
4784
  import { execFileSync } from "node:child_process";
4632
4785
  import { FingerprintGenerator } from "fingerprint-generator";
4633
4786
  import { FingerprintInjector } from "fingerprint-injector";
4787
+ import { chromium as defaultChromiumLauncher } from "playwright";
4634
4788
 
4635
4789
  // src/proxy-bypass.js
4636
4790
  import picomatch from "picomatch";
@@ -4712,9 +4866,107 @@ var ByPass = {
4712
4866
  resolveRouteByProxy
4713
4867
  };
4714
4868
 
4715
- // src/launch.js
4869
+ // src/internals/launch/traffic.js
4870
+ var logger7 = createInternalLogger("Launch");
4871
+ var normalizeObject = (value) => {
4872
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
4873
+ return {};
4874
+ }
4875
+ return value;
4876
+ };
4877
+ var parseProxyConfiguration = (proxyConfiguration = {}) => {
4878
+ const config = normalizeObject(proxyConfiguration);
4879
+ const proxyUrl = String(config.proxy_url || "").trim();
4880
+ const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
4881
+ const byPassDomains = enableProxy && proxyUrl ? ByPass.normalizeByPassDomains(config.by_pass_domains) : [];
4882
+ return {
4883
+ byPassDomains,
4884
+ enableProxy,
4885
+ proxyUrl
4886
+ };
4887
+ };
4888
+ var resolveLaunchTraffic = ({
4889
+ proxyConfiguration = {},
4890
+ debugMode = false,
4891
+ useMeter = true
4892
+ } = {}) => {
4893
+ const { byPassDomains, enableProxy, proxyUrl } = parseProxyConfiguration(proxyConfiguration);
4894
+ const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
4895
+ const proxyMeter = useMeter && enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
4896
+ const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;
4897
+ if (launchProxy && byPassDomains.length > 0) {
4898
+ launchProxy.bypass = byPassDomains.join(",");
4899
+ }
4900
+ return {
4901
+ byPassDomains,
4902
+ byPassRules,
4903
+ enableProxy,
4904
+ proxyUrl,
4905
+ launchProxy
4906
+ };
4907
+ };
4908
+ var logLaunchTraffic = ({
4909
+ byPassDomains = [],
4910
+ debugMode = false,
4911
+ enabled = false,
4912
+ enableProxy = false,
4913
+ explicitProxy = false,
4914
+ launchProxy = null,
4915
+ proxyUrl = ""
4916
+ } = {}) => {
4917
+ if (!enabled) return;
4918
+ if (explicitProxy) {
4919
+ logger7.info("[\u4EE3\u7406\u5DF2\u542F\u7528] \u4F7F\u7528\u663E\u5F0F proxy \u914D\u7F6E\uFF0C\u8DF3\u8FC7 toolkit \u672C\u5730\u6D41\u91CF\u89C2\u6D4B");
4920
+ return;
4921
+ }
4922
+ if (launchProxy) {
4923
+ let upstreamLabel = "";
4924
+ try {
4925
+ const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
4926
+ upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
4927
+ } catch {
4928
+ }
4929
+ logger7.info(
4930
+ `[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${byPassDomains.join(",")}`
4931
+ );
4932
+ 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`);
4933
+ return;
4934
+ }
4935
+ if (enableProxy) {
4936
+ logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
4937
+ } else if (proxyUrl) {
4938
+ logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
4939
+ }
4940
+ 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`);
4941
+ };
4942
+ var createLaunchTrafficHook = ({
4943
+ byPassDomains = [],
4944
+ byPassRules = [],
4945
+ enabled = false,
4946
+ launchProxy = null
4947
+ } = {}) => {
4948
+ const patchedPages = /* @__PURE__ */ new WeakSet();
4949
+ return (page) => {
4950
+ if (!page || typeof page.on !== "function" || patchedPages.has(page)) {
4951
+ return;
4952
+ }
4953
+ patchedPages.add(page);
4954
+ page.on("request", (req) => {
4955
+ const requestUrl = req.url();
4956
+ const resourceType = req.resourceType();
4957
+ const matched = byPassDomains.length > 0 ? ByPass.findMatchedByPassRule(byPassRules, requestUrl) : null;
4958
+ if (launchProxy) {
4959
+ ProxyMeterRuntime.recordProxyMeterResourceType(requestUrl, resourceType);
4960
+ }
4961
+ if (!enabled || byPassDomains.length === 0) return;
4962
+ if (!matched || !matched.rule) return;
4963
+ 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}`);
4964
+ });
4965
+ };
4966
+ };
4967
+
4968
+ // src/internals/launch/default.js
4716
4969
  var logger8 = createInternalLogger("Launch");
4717
- var REQUEST_HOOK_FLAG = Symbol("playwright-toolkit-request-hook");
4718
4970
  var injectedContexts = /* @__PURE__ */ new WeakSet();
4719
4971
  var browserMajorVersionCache = /* @__PURE__ */ new Map();
4720
4972
  var DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION = 1;
@@ -4726,16 +4978,6 @@ var DEFAULT_CRAWLER_BASE_OPTIONS = Object.freeze({
4726
4978
  navigationTimeoutSecs: 120
4727
4979
  });
4728
4980
  var fingerprintInjector = new FingerprintInjector();
4729
- var resolveProxyLaunchOptions = (proxyConfiguration = {}) => {
4730
- const config = proxyConfiguration && typeof proxyConfiguration === "object" && !Array.isArray(proxyConfiguration) ? proxyConfiguration : {};
4731
- const proxyUrl = String(config.proxy_url || "").trim();
4732
- const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
4733
- if (!enableProxy || !proxyUrl) {
4734
- return { byPassDomains: [], enableProxy, proxyUrl };
4735
- }
4736
- const byPassDomains = ByPass.normalizeByPassDomains(config.by_pass_domains);
4737
- return { byPassDomains, enableProxy, proxyUrl };
4738
- };
4739
4981
  var parseChromeMajorVersion = (rawValue = "") => {
4740
4982
  const match = String(rawValue || "").match(/(?:Chrome|Chromium)(?:\/|\s+(?:for Testing\s+)?)(\d+)/i);
4741
4983
  return match ? Number(match[1] || 0) : 0;
@@ -4779,7 +5021,7 @@ var resolveCoreDevice = (core = {}) => {
4779
5021
  };
4780
5022
  var buildFingerprintGenerator = ({ locale, browserMajorVersion, device }) => {
4781
5023
  return new FingerprintGenerator(
4782
- AntiCheat.getFingerprintGeneratorOptions({
5024
+ DefaultAntiCheat.getFingerprintGeneratorOptions({
4783
5025
  locale,
4784
5026
  browserMajorVersion,
4785
5027
  device
@@ -4823,7 +5065,7 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
4823
5065
  }
4824
5066
  let nextState = RuntimeEnv.rememberState(runtimeState);
4825
5067
  let browserProfileCore = RuntimeEnv.getBrowserProfileCore(nextState);
4826
- const timezoneId = String(browserProfileCore?.timezone_id || "").trim() || AntiCheat.getBaseConfig().timezoneId;
5068
+ const timezoneId = String(browserProfileCore?.timezone_id || "").trim() || DefaultAntiCheat.getBaseConfig().timezoneId;
4827
5069
  const locale = DEFAULT_LOCALE;
4828
5070
  const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);
4829
5071
  const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);
@@ -4902,7 +5144,7 @@ var applyFingerprintPageOptions = (pageOptions = {}, { fingerprintWithHeaders =
4902
5144
  pageOptions.timezoneId = timezoneId;
4903
5145
  }
4904
5146
  };
4905
- var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = null) => {
5147
+ var buildReplayBrowserPoolOptions = (browserProfileCore) => {
4906
5148
  const fingerprintWithHeaders = browserProfileCore?.fingerprint;
4907
5149
  const fingerprint = fingerprintWithHeaders?.fingerprint;
4908
5150
  if (!fingerprintWithHeaders || !fingerprint) {
@@ -4911,16 +5153,13 @@ var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = nul
4911
5153
  return {
4912
5154
  useFingerprints: false,
4913
5155
  prePageCreateHooks: [
4914
- async (pageId, browserController, pageOptions = {}) => {
5156
+ (_pageId, _browserController, pageOptions = {}) => {
4915
5157
  if (!pageOptions || typeof pageOptions !== "object") return;
4916
5158
  applyFingerprintPageOptions(pageOptions, {
4917
5159
  fingerprintWithHeaders,
4918
5160
  locale: browserProfileCore.locale,
4919
5161
  timezoneId: browserProfileCore.timezone_id
4920
5162
  });
4921
- if (modifyPageOptions) {
4922
- await modifyPageOptions(pageOptions, { pageId, browserController });
4923
- }
4924
5163
  }
4925
5164
  ],
4926
5165
  postPageCreateHooks: [
@@ -4935,7 +5174,7 @@ var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = nul
4935
5174
  ]
4936
5175
  };
4937
5176
  };
4938
- var Launch = {
5177
+ var DefaultLaunch = {
4939
5178
  getPlaywrightCrawlerOptions(options = {}) {
4940
5179
  const normalizedOptions = Array.isArray(options) ? { customArgs: options } : options || {};
4941
5180
  const {
@@ -4946,54 +5185,36 @@ var Launch = {
4946
5185
  debugMode = false,
4947
5186
  isRunningOnApify = false,
4948
5187
  launcher = null,
4949
- hooks = {},
4950
5188
  preNavigationHooks = [],
4951
5189
  postNavigationHooks = [],
4952
5190
  runtimeState = null
4953
5191
  } = normalizedOptions;
4954
5192
  const device = resolveRuntimeDevice(runtimeState);
4955
- const modifyPageOptions = typeof hooks?.modifyPageOptions === "function" ? hooks.modifyPageOptions : null;
4956
- const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);
4957
- const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
4958
- const proxyMeter = enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
4959
- const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;
4960
- if (launchProxy && byPassDomains.length > 0) {
4961
- launchProxy.bypass = byPassDomains.join(",");
4962
- }
4963
- const replayContext = buildReplayableBrowserProfile(runtimeState, launcher);
4964
- const replayBrowserPoolOptions = buildReplayBrowserPoolOptions(replayContext.browserProfileCore, modifyPageOptions);
5193
+ const effectiveLauncher = launcher || defaultChromiumLauncher;
5194
+ const enableByPassLogger = Boolean(logOptions && logOptions.enable);
5195
+ const traffic = resolveLaunchTraffic({ proxyConfiguration, debugMode });
5196
+ const trafficHook = createLaunchTrafficHook({
5197
+ ...traffic,
5198
+ enabled: enableByPassLogger
5199
+ });
5200
+ const replayContext = buildReplayableBrowserProfile(runtimeState, effectiveLauncher);
5201
+ const replayBrowserPoolOptions = buildReplayBrowserPoolOptions(replayContext.browserProfileCore);
4965
5202
  const launchLocale = String(replayContext.browserProfileCore?.locale || DEFAULT_LOCALE).trim() || DEFAULT_LOCALE;
4966
5203
  const launchOptions = {
4967
5204
  args: [
4968
- ...AntiCheat.getLaunchArgs({ locale: launchLocale }),
5205
+ ...DefaultAntiCheat.getLaunchArgs({ locale: launchLocale }),
4969
5206
  ...customArgs
4970
5207
  ],
4971
5208
  ignoreDefaultArgs: ["--enable-automation"]
4972
5209
  };
4973
- if (launchProxy) {
4974
- launchOptions.proxy = launchProxy;
4975
- }
4976
- const enableByPassLogger = Boolean(logOptions && logOptions.enable);
4977
- if (enableByPassLogger && launchProxy) {
4978
- let upstreamLabel = "";
4979
- try {
4980
- const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
4981
- upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
4982
- } catch {
4983
- }
4984
- logger8.info(
4985
- `[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
4986
- );
4987
- 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`);
4988
- } else if (enableByPassLogger && enableProxy && !launchProxy) {
4989
- logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
4990
- 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`);
4991
- } else if (enableByPassLogger && !enableProxy && proxyUrl) {
4992
- logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
4993
- 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`);
4994
- } else if (enableByPassLogger) {
4995
- 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`);
5210
+ if (traffic.launchProxy) {
5211
+ launchOptions.proxy = traffic.launchProxy;
4996
5212
  }
5213
+ logLaunchTraffic({
5214
+ ...traffic,
5215
+ debugMode,
5216
+ enabled: enableByPassLogger
5217
+ });
4997
5218
  const onPageCreated = (page) => {
4998
5219
  const recommendedGotoOptions = {
4999
5220
  waitUntil: "commit"
@@ -5001,31 +5222,14 @@ var Launch = {
5001
5222
  if (!page || typeof page.on !== "function") {
5002
5223
  return recommendedGotoOptions;
5003
5224
  }
5004
- if (page[REQUEST_HOOK_FLAG]) {
5005
- return recommendedGotoOptions;
5006
- }
5007
- page[REQUEST_HOOK_FLAG] = true;
5008
- const requestHandler = (req) => {
5009
- const requestUrl = req.url();
5010
- const resourceType = req.resourceType();
5011
- const matched = byPassDomains.length > 0 ? ByPass.findMatchedByPassRule(byPassRules, requestUrl) : null;
5012
- if (launchProxy) {
5013
- ProxyMeterRuntime.recordProxyMeterResourceType(requestUrl, resourceType);
5014
- }
5015
- if (!enableByPassLogger || byPassDomains.length === 0) return;
5016
- if (!matched || !matched.rule) return;
5017
- 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}`);
5018
- };
5019
- page.on("request", requestHandler);
5225
+ trafficHook(page);
5020
5226
  return recommendedGotoOptions;
5021
5227
  };
5022
5228
  const launchContext = {
5023
5229
  useIncognitoPages: true,
5024
- launchOptions
5230
+ launchOptions,
5231
+ launcher: effectiveLauncher
5025
5232
  };
5026
- if (launcher) {
5027
- launchContext.launcher = launcher;
5028
- }
5029
5233
  const crawlerBaseOptions = {
5030
5234
  ...DEFAULT_CRAWLER_BASE_OPTIONS,
5031
5235
  headless: !runInHeadfulMode || isRunningOnApify,
@@ -5033,23 +5237,20 @@ var Launch = {
5033
5237
  browserPoolOptions: replayBrowserPoolOptions || {
5034
5238
  useFingerprints: true,
5035
5239
  fingerprintOptions: {
5036
- fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions({
5240
+ fingerprintGeneratorOptions: DefaultAntiCheat.getFingerprintGeneratorOptions({
5037
5241
  locale: launchLocale,
5038
5242
  device
5039
5243
  })
5040
5244
  },
5041
5245
  prePageCreateHooks: [
5042
- async (pageId, browserController, pageOptions = {}) => {
5246
+ (_pageId, browserController, pageOptions = {}) => {
5043
5247
  const fingerprintWithHeaders = browserController?.launchContext?.fingerprint;
5044
- const timezoneId = AntiCheat.getBaseConfig().timezoneId;
5248
+ const timezoneId = DefaultAntiCheat.getBaseConfig().timezoneId;
5045
5249
  applyFingerprintPageOptions(pageOptions, {
5046
5250
  fingerprintWithHeaders,
5047
5251
  locale: launchLocale,
5048
5252
  timezoneId
5049
5253
  });
5050
- if (modifyPageOptions) {
5051
- await modifyPageOptions(pageOptions, { pageId, browserController });
5052
- }
5053
5254
  }
5054
5255
  ]
5055
5256
  },
@@ -5071,10 +5272,303 @@ var Launch = {
5071
5272
  }
5072
5273
  };
5073
5274
 
5275
+ // src/internals/launch/cloak.js
5276
+ import { execFile } from "node:child_process";
5277
+ import { promisify } from "node:util";
5278
+ var logger9 = createInternalLogger("Launch");
5279
+ var execFileAsync = promisify(execFile);
5280
+ var DEFAULT_CLOAK_CRAWLER_BASE_OPTIONS = Object.freeze({
5281
+ maxConcurrency: 1,
5282
+ maxRequestRetries: 0,
5283
+ requestHandlerTimeoutSecs: 240,
5284
+ navigationTimeoutSecs: 120
5285
+ });
5286
+ var DEFAULT_CLOAK_HUMANIZE_OPTIONS = Object.freeze({
5287
+ humanize: true
5288
+ });
5289
+ var DEFAULT_CLOAK_GOTO_OPTIONS = Object.freeze({
5290
+ waitUntil: "commit"
5291
+ });
5292
+ var DEFAULT_CLOAK_FINGERPRINT_PLATFORM = "linux";
5293
+ var CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX = "--fingerprint-platform=";
5294
+ var SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS = /* @__PURE__ */ new Set(["linux", "macos", "windows"]);
5295
+ var cachedCloakModulePromise = null;
5296
+ var hasOwn = (target, key) => Object.prototype.hasOwnProperty.call(target, key);
5297
+ var loadCloakModule = async () => {
5298
+ if (!cachedCloakModulePromise) {
5299
+ cachedCloakModulePromise = import("cloakbrowser").catch((error) => {
5300
+ cachedCloakModulePromise = null;
5301
+ throw new Error("Cloak \u6A21\u5757\u52A0\u8F7D\u5931\u8D25\uFF0C\u8BF7\u786E\u8BA4\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u5DF2\u5B89\u88C5 cloakbrowser\u3002", {
5302
+ cause: error
5303
+ });
5304
+ });
5305
+ }
5306
+ return cachedCloakModulePromise;
5307
+ };
5308
+ var buildCloakLaunchOptions = async (options = {}) => {
5309
+ const { buildLaunchOptions } = await loadCloakModule();
5310
+ return await buildLaunchOptions(normalizeObject2(options));
5311
+ };
5312
+ var normalizeObject2 = (value) => {
5313
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
5314
+ return {};
5315
+ }
5316
+ return value;
5317
+ };
5318
+ var normalizeStringArray = (value) => {
5319
+ if (!Array.isArray(value)) {
5320
+ return [];
5321
+ }
5322
+ return value.map((item) => String(item || "").trim()).filter(Boolean);
5323
+ };
5324
+ var resolveCloakFingerprintPlatformArg = (fingerprintPlatform = "", args = []) => {
5325
+ const normalizedFingerprintPlatform = String(fingerprintPlatform || "").trim().toLowerCase();
5326
+ if (SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS.has(normalizedFingerprintPlatform)) {
5327
+ return `${CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX}${normalizedFingerprintPlatform}`;
5328
+ }
5329
+ const existingArg = normalizeStringArray(args).find((value) => value.startsWith(CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX));
5330
+ if (existingArg) {
5331
+ return existingArg;
5332
+ }
5333
+ return `${CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX}${DEFAULT_CLOAK_FINGERPRINT_PLATFORM}`;
5334
+ };
5335
+ var resolveCloakProxy = (proxyConfiguration = {}) => {
5336
+ const config = normalizeObject2(proxyConfiguration);
5337
+ const proxyUrl = String(config.proxy_url || "").trim();
5338
+ const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
5339
+ if (!enableProxy || !proxyUrl) {
5340
+ return null;
5341
+ }
5342
+ const byPassDomains = ByPass.normalizeByPassDomains(config.by_pass_domains);
5343
+ if (byPassDomains.length === 0) {
5344
+ return proxyUrl;
5345
+ }
5346
+ const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
5347
+ return {
5348
+ server: `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`,
5349
+ username: decodeURIComponent(parsedProxyUrl.username || ""),
5350
+ password: decodeURIComponent(parsedProxyUrl.password || ""),
5351
+ bypass: byPassDomains.join(",")
5352
+ };
5353
+ };
5354
+ var extractFingerprintArg = (launchOptions = {}) => {
5355
+ const args = Array.isArray(launchOptions?.args) ? launchOptions.args : [];
5356
+ return args.find((value) => String(value || "").startsWith("--fingerprint=")) || "";
5357
+ };
5358
+ var createStableGotoHook = (recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS) => {
5359
+ const normalizedRecommendedGotoOptions = normalizeObject2(recommendedGotoOptions);
5360
+ const fallbackGotoOptions = Object.keys(normalizedRecommendedGotoOptions).length > 0 ? normalizedRecommendedGotoOptions : DEFAULT_CLOAK_GOTO_OPTIONS;
5361
+ return async (_crawlingContext, gotoOptions = {}) => {
5362
+ for (const [key, value] of Object.entries(fallbackGotoOptions)) {
5363
+ if (gotoOptions[key] == null) {
5364
+ gotoOptions[key] = value;
5365
+ }
5366
+ }
5367
+ };
5368
+ };
5369
+ var attachCloakHumanizeHook = ({
5370
+ browserPoolOptions = {},
5371
+ activeBrowsers,
5372
+ patchedBrowsers,
5373
+ humanizeOptions = DEFAULT_CLOAK_HUMANIZE_OPTIONS
5374
+ } = {}) => {
5375
+ const normalizedBrowserPoolOptions = normalizeObject2(browserPoolOptions);
5376
+ const shouldHumanize = humanizeOptions !== false;
5377
+ const normalizedHumanizeOptions = shouldHumanize ? {
5378
+ ...DEFAULT_CLOAK_HUMANIZE_OPTIONS,
5379
+ ...normalizeObject2(humanizeOptions)
5380
+ } : null;
5381
+ return {
5382
+ ...normalizedBrowserPoolOptions,
5383
+ useFingerprints: false,
5384
+ postLaunchHooks: [
5385
+ ...Array.isArray(normalizedBrowserPoolOptions.postLaunchHooks) ? normalizedBrowserPoolOptions.postLaunchHooks : [],
5386
+ async (_pageId, browserController) => {
5387
+ const browser = browserController?.browser;
5388
+ if (!browser || typeof browser.contexts !== "function") {
5389
+ return;
5390
+ }
5391
+ activeBrowsers.add(browser);
5392
+ if (typeof browser.once === "function") {
5393
+ browser.once("disconnected", () => {
5394
+ activeBrowsers.delete(browser);
5395
+ });
5396
+ }
5397
+ if (!shouldHumanize || patchedBrowsers.has(browser)) {
5398
+ return;
5399
+ }
5400
+ const { humanizeBrowser } = await loadCloakModule();
5401
+ await humanizeBrowser(browser, normalizedHumanizeOptions);
5402
+ patchedBrowsers.add(browser);
5403
+ }
5404
+ ]
5405
+ };
5406
+ };
5407
+ var closeTrackedBrowsers = async (activeBrowsers) => {
5408
+ const browsers = Array.from(activeBrowsers || []);
5409
+ activeBrowsers?.clear?.();
5410
+ await Promise.allSettled(
5411
+ browsers.map(async (browser) => {
5412
+ if (!browser || typeof browser.isConnected !== "function" || !browser.isConnected()) {
5413
+ return;
5414
+ }
5415
+ await browser.close().catch(() => {
5416
+ });
5417
+ })
5418
+ );
5419
+ };
5420
+ var forceTerminateBrowsersByFingerprintArg = async (fingerprintArg) => {
5421
+ if (!fingerprintArg) {
5422
+ return;
5423
+ }
5424
+ await execFileAsync("pkill", ["-f", "--", fingerprintArg]).catch((error) => {
5425
+ if (error?.code === 1 || error?.code === "ENOENT") {
5426
+ return;
5427
+ }
5428
+ logger9.info(`\u5F3A\u5236\u5173\u95ED Cloak \u8FDB\u7A0B\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${error?.message || String(error)}`);
5429
+ });
5430
+ };
5431
+ var CloakLaunch = {
5432
+ resolveProxyConfiguration(proxyConfiguration = {}) {
5433
+ return resolveCloakProxy(proxyConfiguration);
5434
+ },
5435
+ extractFingerprintArg(launchOptions = {}) {
5436
+ return extractFingerprintArg(launchOptions);
5437
+ },
5438
+ createStableGotoHook(recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS) {
5439
+ return createStableGotoHook(recommendedGotoOptions);
5440
+ },
5441
+ async getPlaywrightCrawlerOptions(options = {}) {
5442
+ const runtime2 = await CloakLaunch.createPlaywrightCrawlerRuntime(options);
5443
+ return Object.defineProperties(runtime2.crawlerOptions, {
5444
+ cleanup: {
5445
+ enumerable: false,
5446
+ value: runtime2.cleanup
5447
+ },
5448
+ closeActiveBrowsers: {
5449
+ enumerable: false,
5450
+ value: runtime2.closeActiveBrowsers
5451
+ },
5452
+ forceTerminateActiveProcesses: {
5453
+ enumerable: false,
5454
+ value: runtime2.forceTerminateActiveProcesses
5455
+ }
5456
+ });
5457
+ },
5458
+ async buildLaunchOptions(options = {}) {
5459
+ return await buildCloakLaunchOptions(options);
5460
+ },
5461
+ async createPlaywrightCrawlerRuntime(options = {}) {
5462
+ const normalizedOptions = normalizeObject2(options);
5463
+ const {
5464
+ proxyConfiguration = {},
5465
+ log: logOptions = null,
5466
+ debugMode = false,
5467
+ runInHeadfulMode = false,
5468
+ isRunningOnApify = false,
5469
+ launcher = null,
5470
+ fingerprintPlatform = "",
5471
+ cloakOptions = {},
5472
+ humanizeOptions = DEFAULT_CLOAK_HUMANIZE_OPTIONS,
5473
+ crawlerBaseOptions = {},
5474
+ browserPoolOptions = {},
5475
+ launchContext = {},
5476
+ preNavigationHooks = [],
5477
+ postNavigationHooks = [],
5478
+ recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS
5479
+ } = normalizedOptions;
5480
+ const normalizedCloakOptions = normalizeObject2(cloakOptions);
5481
+ const activeBrowsers = /* @__PURE__ */ new Set();
5482
+ const patchedBrowsers = /* @__PURE__ */ new WeakSet();
5483
+ const defaultArgs = isRunningOnApify ? ["--no-sandbox", "--disable-setuid-sandbox"] : [];
5484
+ const fingerprintPlatformArg = resolveCloakFingerprintPlatformArg(fingerprintPlatform, normalizedCloakOptions.args);
5485
+ const extraArgs = normalizeStringArray(normalizedCloakOptions.args).filter((value) => !value.startsWith(CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX));
5486
+ const hasExplicitProxy = hasOwn(normalizedCloakOptions, "proxy");
5487
+ const proxyLaunchState = hasExplicitProxy ? resolveLaunchTraffic({ proxyConfiguration, debugMode, useMeter: false }) : resolveLaunchTraffic({ proxyConfiguration, debugMode });
5488
+ const proxy = hasExplicitProxy ? normalizedCloakOptions.proxy : proxyLaunchState.launchProxy;
5489
+ const headless = hasOwn(normalizedCloakOptions, "headless") ? normalizedCloakOptions.headless : !runInHeadfulMode || isRunningOnApify;
5490
+ const enableByPassLogger = Boolean(logOptions && logOptions.enable);
5491
+ const mergedCloakOptions = {
5492
+ ...normalizedCloakOptions,
5493
+ headless,
5494
+ proxy,
5495
+ args: [...defaultArgs, ...extraArgs, fingerprintPlatformArg]
5496
+ };
5497
+ const launchOptions = await buildCloakLaunchOptions(mergedCloakOptions);
5498
+ const fingerprintArg = extractFingerprintArg(launchOptions);
5499
+ const internalPreNavigationHook = createStableGotoHook(recommendedGotoOptions);
5500
+ const trafficHook = createLaunchTrafficHook({
5501
+ byPassDomains: proxyLaunchState.byPassDomains,
5502
+ byPassRules: proxyLaunchState.byPassRules,
5503
+ enabled: enableByPassLogger,
5504
+ launchProxy: proxyLaunchState.launchProxy
5505
+ });
5506
+ const normalizedPreNavigationHooks = Array.isArray(preNavigationHooks) ? preNavigationHooks : [];
5507
+ const normalizedPostNavigationHooks = Array.isArray(postNavigationHooks) ? postNavigationHooks : [];
5508
+ logLaunchTraffic({
5509
+ ...proxyLaunchState,
5510
+ debugMode,
5511
+ enabled: enableByPassLogger,
5512
+ explicitProxy: hasExplicitProxy
5513
+ });
5514
+ const crawlerOptions = {
5515
+ ...DEFAULT_CLOAK_CRAWLER_BASE_OPTIONS,
5516
+ ...normalizeObject2(crawlerBaseOptions),
5517
+ headless,
5518
+ launchContext: {
5519
+ useIncognitoPages: true,
5520
+ ...normalizeObject2(launchContext),
5521
+ ...launcher ? { launcher } : {},
5522
+ launchOptions
5523
+ },
5524
+ browserPoolOptions: attachCloakHumanizeHook({
5525
+ browserPoolOptions,
5526
+ activeBrowsers,
5527
+ patchedBrowsers,
5528
+ humanizeOptions
5529
+ }),
5530
+ preNavigationHooks: [
5531
+ async (crawlingContext, gotoOptions = {}) => {
5532
+ trafficHook(crawlingContext?.page);
5533
+ await internalPreNavigationHook(crawlingContext, gotoOptions);
5534
+ },
5535
+ ...normalizedPreNavigationHooks
5536
+ ],
5537
+ ...normalizedPostNavigationHooks.length > 0 ? { postNavigationHooks: normalizedPostNavigationHooks } : {}
5538
+ };
5539
+ const closeActiveBrowsers = async () => {
5540
+ await closeTrackedBrowsers(activeBrowsers);
5541
+ };
5542
+ const forceTerminateActiveProcesses = async () => {
5543
+ await forceTerminateBrowsersByFingerprintArg(fingerprintArg);
5544
+ };
5545
+ const cleanup = async () => {
5546
+ await closeActiveBrowsers();
5547
+ await forceTerminateActiveProcesses();
5548
+ };
5549
+ return {
5550
+ headless,
5551
+ launchOptions,
5552
+ fingerprintArg,
5553
+ crawlerOptions,
5554
+ closeActiveBrowsers,
5555
+ forceTerminateActiveProcesses,
5556
+ cleanup
5557
+ };
5558
+ }
5559
+ };
5560
+
5561
+ // src/launch.js
5562
+ var launchStrategies = {
5563
+ [Mode.Default]: DefaultLaunch,
5564
+ [Mode.Cloak]: CloakLaunch
5565
+ };
5566
+ var Launch = withModeReflect("Launch", launchStrategies);
5567
+
5074
5568
  // src/live-view.js
5075
5569
  import express from "express";
5076
5570
  import { Actor } from "apify";
5077
- var logger9 = createInternalLogger("LiveView");
5571
+ var logger10 = createInternalLogger("LiveView");
5078
5572
  async function startLiveViewServer(liveViewKey) {
5079
5573
  const app = express();
5080
5574
  app.get("/", async (req, res) => {
@@ -5099,13 +5593,13 @@ async function startLiveViewServer(liveViewKey) {
5099
5593
  </html>
5100
5594
  `);
5101
5595
  } catch (error) {
5102
- logger9.fail("Live View Server", error);
5596
+ logger10.fail("Live View Server", error);
5103
5597
  res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
5104
5598
  }
5105
5599
  });
5106
5600
  const port = process.env.APIFY_CONTAINER_PORT || 4321;
5107
5601
  app.listen(port, () => {
5108
- logger9.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
5602
+ logger10.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
5109
5603
  });
5110
5604
  }
5111
5605
  async function takeLiveScreenshot(liveViewKey, page, logMessage) {
@@ -5113,10 +5607,10 @@ async function takeLiveScreenshot(liveViewKey, page, logMessage) {
5113
5607
  const buffer = await capturePageScreenshot(page, { type: "png" });
5114
5608
  await Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
5115
5609
  if (logMessage) {
5116
- logger9.info(`(\u622A\u56FE): ${logMessage}`);
5610
+ logger10.info(`(\u622A\u56FE): ${logMessage}`);
5117
5611
  }
5118
5612
  } catch (e) {
5119
- logger9.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
5613
+ logger10.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
5120
5614
  }
5121
5615
  }
5122
5616
  var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
@@ -5133,9 +5627,6 @@ var LiveView = {
5133
5627
  useLiveView
5134
5628
  };
5135
5629
 
5136
- // src/chaptcha.js
5137
- import { v4 as uuidv4 } from "uuid";
5138
-
5139
5630
  // src/internals/captcha/bytedance.js
5140
5631
  import { mkdir, writeFile } from "fs/promises";
5141
5632
  import path2 from "path";
@@ -5225,7 +5716,7 @@ var dragCaptchaAction = async (page, sourceLocator, targetLocator, options = {})
5225
5716
  };
5226
5717
 
5227
5718
  // src/internals/captcha/bytedance.js
5228
- var logger10 = createInternalLogger("Captcha");
5719
+ var logger11 = createInternalLogger("Captcha");
5229
5720
  var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
5230
5721
  apiType: "31234",
5231
5722
  maxRetries: 3,
@@ -5357,7 +5848,7 @@ var collectCaptchaDebugInfo = async (page, frame, iframeLocator, attempt, phase,
5357
5848
  }
5358
5849
  await writeFile(infoPath, JSON.stringify(payload, null, 2), "utf8");
5359
5850
  }
5360
- logger10.info(`\u5DF2\u5199\u51FA\u9A8C\u8BC1\u7801\u8C03\u8BD5\u4EA7\u7269\uFF1A${debugDir}`);
5851
+ logger11.info(`\u5DF2\u5199\u51FA\u9A8C\u8BC1\u7801\u8C03\u8BD5\u4EA7\u7269\uFF1A${debugDir}`);
5361
5852
  };
5362
5853
  var maybeCollectCaptchaDebugInfo = async (page, frame, iframeLocator, attempt, phase, options, extra = null) => {
5363
5854
  if (!options.debugArtifacts) {
@@ -5394,14 +5885,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
5394
5885
  if (!isContainerVisible) {
5395
5886
  return null;
5396
5887
  }
5397
- logger10.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
5888
+ logger11.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
5398
5889
  let iframeLocator = page.locator(options.iframeSelector).first();
5399
5890
  let isIframeVisible = await waitForVisible(
5400
5891
  iframeLocator,
5401
5892
  options.iframeVisibleTimeoutMs
5402
5893
  );
5403
5894
  if (!isIframeVisible) {
5404
- logger10.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
5895
+ logger11.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
5405
5896
  iframeLocator = captchaContainer.locator(options.iframeFallbackSelector).first();
5406
5897
  isIframeVisible = await waitForVisible(
5407
5898
  iframeLocator,
@@ -5411,7 +5902,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
5411
5902
  if (!isIframeVisible) {
5412
5903
  throw new Error("verifycenter iframe not found inside captcha container.");
5413
5904
  }
5414
- logger10.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
5905
+ logger11.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
5415
5906
  const frame = await resolveContentFrame(page, iframeLocator, options);
5416
5907
  if (!frame) {
5417
5908
  throw new Error("Failed to resolve verifycenter iframe content frame.");
@@ -5527,11 +6018,11 @@ var refreshCaptcha = async (page, frame, options) => {
5527
6018
  const clicked = await clickCaptchaAction(frame, options.refreshTexts, {
5528
6019
  ...options,
5529
6020
  page,
5530
- logger: logger10,
6021
+ logger: logger11,
5531
6022
  forceMouse: true
5532
6023
  }).catch(() => false);
5533
6024
  if (!clicked) {
5534
- logger10.warn("Refresh button not found.");
6025
+ logger11.warn("Refresh button not found.");
5535
6026
  return false;
5536
6027
  }
5537
6028
  await page.waitForTimeout(options.refreshWaitMs);
@@ -5562,24 +6053,24 @@ var waitForCaptchaChallengeReady = async (page, frame, options) => {
5562
6053
  const hasGuideMaskVisible = options.guideMaskSelector ? await frame.locator(options.guideMaskSelector).first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
5563
6054
  hasSeenGuideMask = hasSeenGuideMask || hasGuideMaskVisible;
5564
6055
  if (hasGuideMaskVisible && !hasLoggedGuideMask) {
5565
- logger10.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u64CD\u4F5C\u5F15\u5BFC\u5C42\uFF0C\u7B49\u5F85\u5176\u6D88\u5931\u540E\u518D\u5F00\u59CB\u8BC6\u522B\u3002");
6056
+ logger11.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u64CD\u4F5C\u5F15\u5BFC\u5C42\uFF0C\u7B49\u5F85\u5176\u6D88\u5931\u540E\u518D\u5F00\u59CB\u8BC6\u522B\u3002");
5566
6057
  hasLoggedGuideMask = true;
5567
6058
  }
5568
6059
  if (!isLoadingVisible && hasVisibleSourceImage && hasVisibleDropTarget && !hasGuideMaskVisible) {
5569
- logger10.info(
6060
+ logger11.info(
5570
6061
  hasSeenGuideMask ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u548C\u62D6\u62FD\u533A\u57DF\u5DF2\u5C31\u7EEA\uFF0C\u5F15\u5BFC\u5C42\u5DF2\u6D88\u5931\u3002" : hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002"
5571
6062
  );
5572
6063
  return;
5573
6064
  }
5574
6065
  if (hasErrorTextVisible) {
5575
- 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");
6066
+ logger11.warn("\u9A8C\u8BC1\u7801\u9762\u677F\u51FA\u73B0\u7F51\u7EDC\u5F02\u5E38\u6587\u6848\uFF0C\u5C1D\u8BD5\u7ACB\u5373\u5237\u65B0\u9898\u76EE\u3002");
5576
6067
  await refreshCaptcha(page, frame, options);
5577
6068
  refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
5578
6069
  hasSeenLoading = false;
5579
6070
  continue;
5580
6071
  }
5581
6072
  if ((!hasVisibleSourceImage || !hasVisibleDropTarget) && Date.now() >= refreshDeadline) {
5582
- logger10.warn(`\u9A8C\u8BC1\u7801\u9898\u76EE\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51C6\u5907\u597D\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
6073
+ logger11.warn(`\u9A8C\u8BC1\u7801\u9898\u76EE\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51C6\u5907\u597D\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
5583
6074
  await refreshCaptcha(page, frame, options);
5584
6075
  refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
5585
6076
  hasSeenLoading = false;
@@ -5627,7 +6118,7 @@ var dragPromptCaptchaImage = async (page, frame, iframeLocator, sourceLocator, d
5627
6118
  accepted
5628
6119
  };
5629
6120
  dragAttempts.push(attemptInfo);
5630
- logger10.info(
6121
+ logger11.info(
5631
6122
  `\u9A8C\u8BC1\u7801\u62D6\u62FD\u7B2C ${visualIndex + 1} \u5F20\uFF0C\u65B9\u6848 ${plan.name}\uFF0Cbadge ${baselineState.badgeCount} -> ${afterState.badgeCount}\uFF0Cselected ${baselineState.selectedCount} -> ${afterState.selectedCount}`
5632
6123
  );
5633
6124
  if (accepted) {
@@ -5645,7 +6136,7 @@ var dragPromptCaptchaImage = async (page, frame, iframeLocator, sourceLocator, d
5645
6136
  dragAttempts,
5646
6137
  finalState: await readPromptCaptchaState(frame, options)
5647
6138
  }).catch((error) => {
5648
- logger10.warn(`\u9A8C\u8BC1\u7801\u62D6\u62FD\u5931\u8D25\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
6139
+ logger11.warn(`\u9A8C\u8BC1\u7801\u62D6\u62FD\u5931\u8D25\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
5649
6140
  });
5650
6141
  return {
5651
6142
  accepted: false,
@@ -5662,16 +6153,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5662
6153
  ...options
5663
6154
  };
5664
6155
  if (!config.token) {
5665
- logger10.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
6156
+ logger11.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
5666
6157
  return false;
5667
6158
  }
5668
- logger10.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
6159
+ logger11.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
5669
6160
  for (let attempt = 1; attempt <= config.maxRetries; attempt += 1) {
5670
- logger10.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
6161
+ logger11.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
5671
6162
  try {
5672
6163
  const captchaContext = await getVerifycenterCaptchaContext(page, config);
5673
6164
  if (!captchaContext) {
5674
- logger10.info("Captcha container is not visible anymore.");
6165
+ logger11.info("Captcha container is not visible anymore.");
5675
6166
  return true;
5676
6167
  }
5677
6168
  const { iframeLocator, frame } = captchaContext;
@@ -5684,7 +6175,7 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5684
6175
  "ready",
5685
6176
  config
5686
6177
  ).catch((error) => {
5687
- logger10.warn(`\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
6178
+ logger11.warn(`\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
5688
6179
  });
5689
6180
  await page.waitForTimeout(config.recognitionDelayMs);
5690
6181
  const screenshotBuffer = await iframeLocator.screenshot();
@@ -5696,16 +6187,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5696
6187
  });
5697
6188
  const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
5698
6189
  if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
5699
- logger10.warn(
6190
+ logger11.warn(
5700
6191
  `\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\u3002code=${apiResponse?.code}, msg=${apiResponse?.msg || "unknown"}`
5701
6192
  );
5702
6193
  await refreshCaptcha(page, frame, config);
5703
6194
  continue;
5704
6195
  }
5705
- logger10.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
6196
+ logger11.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
5706
6197
  const dropTarget = await findCaptchaDropTarget(frame, config);
5707
6198
  if (!dropTarget) {
5708
- logger10.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
6199
+ logger11.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
5709
6200
  await refreshCaptcha(page, frame, config);
5710
6201
  continue;
5711
6202
  }
@@ -5716,7 +6207,7 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5716
6207
  `Captcha image indexes could not be normalized. raw=${serialNumbers.join(", ")}, count=${orderedSourceImages.length}`
5717
6208
  );
5718
6209
  }
5719
- logger10.info(`\u9A8C\u8BC1\u7801\u89C6\u89C9\u4F4D\u5E8F\u6620\u5C04\uFF1A${normalizedIndexes.map((index) => index + 1).join(", ")}`);
6210
+ logger11.info(`\u9A8C\u8BC1\u7801\u89C6\u89C9\u4F4D\u5E8F\u6620\u5C04\uFF1A${normalizedIndexes.map((index) => index + 1).join(", ")}`);
5720
6211
  for (const imageIndex of normalizedIndexes) {
5721
6212
  if (imageIndex < 0 || imageIndex >= orderedSourceImages.length) {
5722
6213
  throw new Error(
@@ -5748,52 +6239,55 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5748
6239
  }
5749
6240
  }
5750
6241
  const beforeSubmitState = await readPromptCaptchaState(frame, config);
5751
- logger10.info(
6242
+ logger11.info(
5752
6243
  `\u63D0\u4EA4\u524D\u9A8C\u8BC1\u7801\u72B6\u6001\uFF1Abadge=${beforeSubmitState.badgeCount}, selected=${beforeSubmitState.selectedCount}, submitDisabled=${beforeSubmitState.submitDisabled}`
5753
6244
  );
5754
6245
  const submitted = await clickCaptchaAction(frame, config.submitTexts, {
5755
6246
  ...config,
5756
6247
  page,
5757
- logger: logger10,
6248
+ logger: logger11,
5758
6249
  forceMouse: true,
5759
6250
  actionVisibleTimeoutMs: config.submitReadyTimeoutMs
5760
6251
  }).catch(() => false);
5761
6252
  if (!submitted) {
5762
- logger10.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
6253
+ logger11.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
5763
6254
  }
5764
6255
  await page.waitForTimeout(config.submitWaitMs);
5765
6256
  const afterSubmitState = await readPromptCaptchaState(frame, config);
5766
- logger10.info(
6257
+ logger11.info(
5767
6258
  `\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u72B6\u6001\uFF1Abadge=${afterSubmitState.badgeCount}, selected=${afterSubmitState.selectedCount}, submitDisabled=${afterSubmitState.submitDisabled}`
5768
6259
  );
5769
6260
  const stillVisible = await iframeLocator.isVisible({ timeout: config.containerVisibleTimeoutMs }).catch(() => false);
5770
6261
  if (!stillVisible) {
5771
- logger10.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
6262
+ logger11.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
5772
6263
  return true;
5773
6264
  }
5774
6265
  await maybeCollectCaptchaDebugInfo(page, frame, iframeLocator, attempt, "submit-still-visible", config, {
5775
6266
  beforeSubmitState,
5776
6267
  afterSubmitState
5777
6268
  }).catch((error) => {
5778
- logger10.warn(`\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
6269
+ logger11.warn(`\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
5779
6270
  });
5780
- logger10.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
6271
+ logger11.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
5781
6272
  await page.waitForTimeout(2e3);
5782
6273
  await refreshCaptcha(page, frame, config);
5783
6274
  } catch (error) {
5784
- logger10.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
6275
+ logger11.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
5785
6276
  }
5786
6277
  if (attempt < config.maxRetries) {
5787
6278
  await page.waitForTimeout(config.retryDelayBaseMs + attempt * config.retryDelayStepMs);
5788
6279
  }
5789
6280
  }
5790
- logger10.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
6281
+ logger11.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
5791
6282
  return false;
5792
6283
  }
5793
6284
  var sloveCaptcha = solveCaptcha;
5794
6285
 
5795
6286
  // src/chaptcha.js
5796
- var logger11 = createInternalLogger("Captcha");
6287
+ var logger12 = createInternalLogger("Captcha");
6288
+ var DOM_MONITOR_WAIT_TIMEOUT_MS = 1e3;
6289
+ var DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS = 300;
6290
+ var DOM_MONITOR_RECOVERY_WAIT_MS = 100;
5797
6291
  var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
5798
6292
  token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
5799
6293
  apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
@@ -5814,6 +6308,15 @@ var mergeDefinedOptions = (...sources) => {
5814
6308
  }
5815
6309
  return merged;
5816
6310
  };
6311
+ var sleep = (ms) => new Promise((resolve) => {
6312
+ setTimeout(resolve, ms);
6313
+ });
6314
+ var getErrorMessage = (error) => String(error?.message || error || "");
6315
+ var isTimeoutError = (error) => error?.name === "TimeoutError" || getErrorMessage(error).includes("Timeout");
6316
+ var isPageLifecycleError = (error) => {
6317
+ const message = getErrorMessage(error);
6318
+ return message.includes("Execution context was destroyed") || message.includes("Frame was detached") || message.includes("Target page, context or browser has been closed") || message.includes("Target closed") || message.includes("Most likely the page has been closed");
6319
+ };
5817
6320
  function useCaptchaMonitor(page, options) {
5818
6321
  const { domSelector, urlPattern, onDetected } = options;
5819
6322
  if (!domSelector && !urlPattern) {
@@ -5825,10 +6328,13 @@ function useCaptchaMonitor(page, options) {
5825
6328
  let isStopped = false;
5826
6329
  let isHandling = false;
5827
6330
  let frameHandler = null;
5828
- let exposedFunctionName = null;
6331
+ let domMonitorTask = null;
6332
+ let lastTriggeredAt = 0;
5829
6333
  const triggerDetected = async () => {
5830
- if (isStopped || isHandling) return;
6334
+ const now = Date.now();
6335
+ if (isStopped || isHandling || now - lastTriggeredAt < 250) return;
5831
6336
  isHandling = true;
6337
+ lastTriggeredAt = now;
5832
6338
  try {
5833
6339
  await onDetected();
5834
6340
  } finally {
@@ -5837,60 +6343,38 @@ function useCaptchaMonitor(page, options) {
5837
6343
  };
5838
6344
  const cleanupFns = [];
5839
6345
  if (domSelector) {
5840
- exposedFunctionName = `__c_d_${uuidv4().replace(/-/g, "_")}`;
5841
- const cleanerName = `__c_cleaner_${uuidv4().replace(/-/g, "_")}`;
5842
- page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
5843
- });
5844
- page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
5845
- (() => {
5846
- let observer = null;
5847
- const checkAndReport = () => {
5848
- const element = document.querySelector(selector);
5849
- if (!element) {
5850
- return false;
5851
- }
5852
- if (window[callbackName]) {
5853
- window[callbackName]();
5854
- }
5855
- return true;
5856
- };
5857
- checkAndReport();
5858
- observer = new MutationObserver((mutations) => {
5859
- const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
5860
- if (shouldCheck && observer) {
5861
- checkAndReport();
5862
- }
5863
- });
5864
- const mountObserver = () => {
5865
- const target = document.documentElement;
5866
- if (target && observer) {
5867
- observer.observe(target, { childList: true, subtree: true });
6346
+ domMonitorTask = (async () => {
6347
+ const locator = page.locator(domSelector).first();
6348
+ while (!isStopped) {
6349
+ try {
6350
+ await locator.waitFor({ state: "visible", timeout: DOM_MONITOR_WAIT_TIMEOUT_MS });
6351
+ if (isStopped) break;
6352
+ await triggerDetected();
6353
+ if (isStopped) break;
6354
+ await locator.waitFor({
6355
+ state: "hidden",
6356
+ timeout: DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS
6357
+ }).catch(() => {
6358
+ });
6359
+ } catch (error) {
6360
+ if (isStopped) break;
6361
+ if (page?.isClosed?.() && isPageLifecycleError(error)) break;
6362
+ if (isTimeoutError(error) || isPageLifecycleError(error)) {
6363
+ await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
6364
+ continue;
5868
6365
  }
5869
- };
5870
- if (document.readyState === "loading") {
5871
- window.addEventListener("DOMContentLoaded", mountObserver);
5872
- } else {
5873
- mountObserver();
6366
+ logger12.warning(
6367
+ "useCaptchaMonitor",
6368
+ `DOM \u76D1\u63A7\u51FA\u73B0\u5F02\u5E38\uFF08\u7EE7\u7EED\u91CD\u8BD5\uFF09: selector=${domSelector}, error=${getErrorMessage(error)}`
6369
+ );
6370
+ await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
5874
6371
  }
5875
- window[cleanupName] = () => {
5876
- if (observer) {
5877
- observer.disconnect();
5878
- observer = null;
5879
- }
5880
- };
5881
- })();
5882
- }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
5883
- logger11.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
5884
- cleanupFns.push(async () => {
5885
- try {
5886
- await page.evaluate((name) => {
5887
- if (window[name]) {
5888
- window[name]();
5889
- delete window[name];
5890
- }
5891
- }, cleanerName);
5892
- } catch {
5893
6372
  }
6373
+ })();
6374
+ logger12.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
6375
+ cleanupFns.push(async () => {
6376
+ await domMonitorTask?.catch(() => {
6377
+ });
5894
6378
  });
5895
6379
  }
5896
6380
  if (urlPattern) {
@@ -5904,18 +6388,24 @@ function useCaptchaMonitor(page, options) {
5904
6388
  }
5905
6389
  };
5906
6390
  page.on("framenavigated", frameHandler);
5907
- logger11.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
6391
+ logger12.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
6392
+ Promise.resolve().then(async () => {
6393
+ if (!isStopped && page.url().includes(urlPattern)) {
6394
+ await triggerDetected();
6395
+ }
6396
+ }).catch(() => {
6397
+ });
5908
6398
  cleanupFns.push(async () => {
5909
6399
  page.off("framenavigated", frameHandler);
5910
6400
  });
5911
6401
  }
5912
6402
  return {
5913
6403
  stop: async () => {
5914
- logger11.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
6404
+ logger12.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
6405
+ isStopped = true;
5915
6406
  for (const fn of cleanupFns) {
5916
6407
  await fn();
5917
6408
  }
5918
- isStopped = true;
5919
6409
  }
5920
6410
  };
5921
6411
  }
@@ -5950,7 +6440,7 @@ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
5950
6440
  );
5951
6441
  return strategy.sloveCaptcha(page, resolvedOptions, {
5952
6442
  callCaptchaRecognitionApi,
5953
- logger: logger11
6443
+ logger: logger12
5954
6444
  });
5955
6445
  }
5956
6446
  var Captcha = {
@@ -5960,15 +6450,15 @@ var Captcha = {
5960
6450
 
5961
6451
  // src/mutation.js
5962
6452
  import { createHash } from "node:crypto";
5963
- import { v4 as uuidv42 } from "uuid";
5964
- var logger12 = createInternalLogger("Mutation");
6453
+ import { v4 as uuidv4 } from "uuid";
6454
+ var logger13 = createInternalLogger("Mutation");
5965
6455
  var MUTATION_MONITOR_MODE = Object.freeze({
5966
6456
  Added: "added",
5967
6457
  Changed: "changed",
5968
6458
  All: "all"
5969
6459
  });
5970
6460
  function generateKey(prefix) {
5971
- return `__${prefix}_${uuidv42().replace(/-/g, "_")}`;
6461
+ return `__${prefix}_${uuidv4().replace(/-/g, "_")}`;
5972
6462
  }
5973
6463
  var Mutation = {
5974
6464
  Mode: MUTATION_MONITOR_MODE,
@@ -5994,14 +6484,14 @@ var Mutation = {
5994
6484
  const stableTime = options.stableTime ?? 5 * 1e3;
5995
6485
  const timeout = options.timeout ?? 120 * 1e3;
5996
6486
  const onMutation = options.onMutation;
5997
- logger12.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
6487
+ logger13.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
5998
6488
  if (initialTimeout > 0) {
5999
6489
  const selectorQuery = selectorList.join(",");
6000
6490
  try {
6001
6491
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
6002
- logger12.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
6492
+ logger13.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
6003
6493
  } catch (e) {
6004
- logger12.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
6494
+ logger13.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
6005
6495
  throw e;
6006
6496
  }
6007
6497
  }
@@ -6017,7 +6507,7 @@ var Mutation = {
6017
6507
  return "__CONTINUE__";
6018
6508
  }
6019
6509
  });
6020
- logger12.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
6510
+ logger13.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
6021
6511
  } catch (e) {
6022
6512
  }
6023
6513
  }
@@ -6132,9 +6622,9 @@ var Mutation = {
6132
6622
  { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
6133
6623
  );
6134
6624
  if (result.mutationCount === 0 && result.stableTime === 0) {
6135
- logger12.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
6625
+ logger13.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
6136
6626
  }
6137
- logger12.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
6627
+ logger13.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
6138
6628
  return result;
6139
6629
  },
6140
6630
  /**
@@ -6158,7 +6648,7 @@ var Mutation = {
6158
6648
  const overallTimeout = options.timeout ?? 180 * 1e3;
6159
6649
  const onMutation = options.onMutation;
6160
6650
  const pollInterval = 500;
6161
- const sleep = (ms) => new Promise((resolve) => {
6651
+ const sleep2 = (ms) => new Promise((resolve) => {
6162
6652
  setTimeout(resolve, ms);
6163
6653
  });
6164
6654
  const truncate = (value, max = 800) => {
@@ -6306,29 +6796,29 @@ var Mutation = {
6306
6796
  return "__CONTINUE__";
6307
6797
  }
6308
6798
  };
6309
- logger12.start(
6799
+ logger13.start(
6310
6800
  "waitForStableAcrossRoots",
6311
6801
  `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
6312
6802
  );
6313
6803
  if (initialTimeout > 0) {
6314
6804
  try {
6315
6805
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
6316
- logger12.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
6806
+ logger13.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
6317
6807
  } catch (e) {
6318
- logger12.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
6808
+ logger13.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
6319
6809
  throw e;
6320
6810
  }
6321
6811
  }
6322
- let state = await buildState();
6323
- if (!state?.hasMatched) {
6324
- logger12.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
6812
+ let state2 = await buildState();
6813
+ if (!state2?.hasMatched) {
6814
+ logger13.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
6325
6815
  return { mutationCount: 0, stableTime: 0, wasPaused: false };
6326
6816
  }
6327
6817
  let mutationCount = 0;
6328
6818
  let stableSince = 0;
6329
6819
  let isPaused = false;
6330
6820
  let wasPaused = false;
6331
- let lastSnapshotKey = state.snapshotKey;
6821
+ let lastSnapshotKey = state2.snapshotKey;
6332
6822
  const applyPauseSignal = (signal) => {
6333
6823
  const nextPaused = signal === "__PAUSE__";
6334
6824
  if (nextPaused) {
@@ -6342,15 +6832,15 @@ var Mutation = {
6342
6832
  };
6343
6833
  const initialSignal = await invokeMutationCallback({
6344
6834
  mutationCount: 0,
6345
- html: state.html || "",
6346
- text: state.text || "",
6347
- mutationNodes: state.mutationNodes || []
6835
+ html: state2.html || "",
6836
+ text: state2.text || "",
6837
+ mutationNodes: state2.mutationNodes || []
6348
6838
  });
6349
6839
  applyPauseSignal(initialSignal);
6350
6840
  const deadline = Date.now() + overallTimeout;
6351
- let lastState = state;
6841
+ let lastState = state2;
6352
6842
  while (Date.now() < deadline) {
6353
- await sleep(pollInterval);
6843
+ await sleep2(pollInterval);
6354
6844
  lastState = await buildState();
6355
6845
  if (!lastState?.hasMatched) {
6356
6846
  continue;
@@ -6358,7 +6848,7 @@ var Mutation = {
6358
6848
  if (lastState.snapshotKey !== lastSnapshotKey) {
6359
6849
  lastSnapshotKey = lastState.snapshotKey;
6360
6850
  mutationCount += 1;
6361
- logger12.info(
6851
+ logger13.info(
6362
6852
  `waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
6363
6853
  );
6364
6854
  const signal = await invokeMutationCallback({
@@ -6371,7 +6861,7 @@ var Mutation = {
6371
6861
  continue;
6372
6862
  }
6373
6863
  if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
6374
- logger12.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
6864
+ logger13.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
6375
6865
  return {
6376
6866
  mutationCount,
6377
6867
  stableTime: waitForStableTime,
@@ -6397,8 +6887,8 @@ var Mutation = {
6397
6887
  const selectorList = Array.isArray(selectors) ? selectors : [selectors];
6398
6888
  const onMutation = options.onMutation;
6399
6889
  const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
6400
- const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
6401
- logger12.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
6890
+ const mode2 = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
6891
+ logger13.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode2}`);
6402
6892
  const monitorKey = generateKey("pk_mon");
6403
6893
  const callbackName = generateKey("pk_mon_cb");
6404
6894
  const cleanerName = generateKey("pk_mon_clean");
@@ -6413,7 +6903,7 @@ var Mutation = {
6413
6903
  } catch (e) {
6414
6904
  }
6415
6905
  }
6416
- await page.evaluate(({ selectorList: selectorList2, monitorKey: monitorKey2, callbackName: callbackName2, cleanerName: cleanerName2, hasCallback, mode: mode2 }) => {
6906
+ await page.evaluate(({ selectorList: selectorList2, monitorKey: monitorKey2, callbackName: callbackName2, cleanerName: cleanerName2, hasCallback, mode: mode3 }) => {
6417
6907
  const monitor = {
6418
6908
  observers: [],
6419
6909
  totalMutations: 0,
@@ -6457,7 +6947,7 @@ var Mutation = {
6457
6947
  const collectMutationNodes = (mutations) => {
6458
6948
  const mutationNodes = [];
6459
6949
  for (const mutation of mutations) {
6460
- if (mode2 === "added") {
6950
+ if (mode3 === "added") {
6461
6951
  if (mutation.type !== "childList") continue;
6462
6952
  const added = Array.from(mutation.addedNodes || []);
6463
6953
  for (const node of added) {
@@ -6465,7 +6955,7 @@ var Mutation = {
6465
6955
  }
6466
6956
  continue;
6467
6957
  }
6468
- if (mode2 === "changed") {
6958
+ if (mode3 === "changed") {
6469
6959
  if (mutation.type === "attributes" || mutation.type === "characterData") {
6470
6960
  mutationNodes.push(serializeNode(mutation.target, mutation.type));
6471
6961
  } else if (mutation.type === "childList") {
@@ -6525,8 +7015,8 @@ var Mutation = {
6525
7015
  observer.observe(element, {
6526
7016
  childList: true,
6527
7017
  subtree: true,
6528
- characterData: mode2 !== "added",
6529
- attributes: mode2 !== "added"
7018
+ characterData: mode3 !== "added",
7019
+ attributes: mode3 !== "added"
6530
7020
  });
6531
7021
  monitor.observers.push(observer);
6532
7022
  });
@@ -6540,8 +7030,8 @@ var Mutation = {
6540
7030
  delete window[cleanerName2];
6541
7031
  return total;
6542
7032
  };
6543
- }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
6544
- logger12.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
7033
+ }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode: mode2 });
7034
+ logger13.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
6545
7035
  return {
6546
7036
  stop: async () => {
6547
7037
  let totalMutations = 0;
@@ -6554,7 +7044,7 @@ var Mutation = {
6554
7044
  }, cleanerName);
6555
7045
  } catch (e) {
6556
7046
  }
6557
- logger12.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
7047
+ logger13.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
6558
7048
  return { totalMutations };
6559
7049
  }
6560
7050
  };
@@ -7423,7 +7913,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
7423
7913
  };
7424
7914
  var getDefaultBaseLogger = () => createBaseLogger("");
7425
7915
  var Logger = {
7426
- setLogger: (logger16) => setDefaultLogger(logger16),
7916
+ setLogger: (logger17) => setDefaultLogger(logger17),
7427
7917
  info: (message) => getDefaultBaseLogger().info(message),
7428
7918
  success: (message) => getDefaultBaseLogger().success(message),
7429
7919
  warning: (message) => getDefaultBaseLogger().warning(message),
@@ -7431,14 +7921,14 @@ var Logger = {
7431
7921
  error: (message) => getDefaultBaseLogger().error(message),
7432
7922
  debug: (message) => getDefaultBaseLogger().debug(message),
7433
7923
  start: (message) => getDefaultBaseLogger().start(message),
7434
- useTemplate: (logger16) => {
7435
- if (logger16) return createTemplateLogger(createBaseLogger("", logger16));
7924
+ useTemplate: (logger17) => {
7925
+ if (logger17) return createTemplateLogger(createBaseLogger("", logger17));
7436
7926
  return createTemplateLogger();
7437
7927
  }
7438
7928
  };
7439
7929
 
7440
7930
  // src/share.js
7441
- import delay4 from "delay";
7931
+ import delay5 from "delay";
7442
7932
 
7443
7933
  // src/internals/watermarkify.js
7444
7934
  var DEFAULT_TIMEZONE_OFFSET = 8;
@@ -7506,7 +7996,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
7506
7996
  ];
7507
7997
  var cachedStripLogoSrcPromise = null;
7508
7998
  var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
7509
- var logger13 = createInternalLogger("Watermarkify");
7999
+ var logger14 = createInternalLogger("Watermarkify");
7510
8000
  var normalizeText = (value) => String(value || "").trim();
7511
8001
  var toInline = (value, maxLen = 200) => {
7512
8002
  const text = normalizeText(value);
@@ -7748,9 +8238,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
7748
8238
  location: toInline(resolved.location, 80)
7749
8239
  };
7750
8240
  if (enrichment.ip || enrichment.location) {
7751
- logger13.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
8241
+ logger14.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
7752
8242
  } else {
7753
- logger13.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
8243
+ logger14.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
7754
8244
  }
7755
8245
  return enrichment;
7756
8246
  } finally {
@@ -7934,14 +8424,17 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height, imageH
7934
8424
  </html>
7935
8425
  `;
7936
8426
  };
7937
- var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}) => {
8427
+ var normalizeWatermarkifyRenderMode = (value) => {
8428
+ return String(value || Mode.Default).trim().toLowerCase() === Mode.Cloak ? Mode.Cloak : Mode.Default;
8429
+ };
8430
+ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}, options = {}) => {
7938
8431
  if (!page || typeof page.context !== "function") {
7939
- logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
8432
+ logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
7940
8433
  return buffer;
7941
8434
  }
7942
8435
  const renderScope = await openProbePage(page);
7943
8436
  if (!renderScope?.page) {
7944
- logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
8437
+ logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
7945
8438
  return buffer;
7946
8439
  }
7947
8440
  try {
@@ -7958,15 +8451,35 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
7958
8451
  height: viewportHeight
7959
8452
  }).catch(() => {
7960
8453
  });
7961
- await renderPage.setContent(buildWatermarkifyRenderHtml({
7962
- imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
7963
- overlaySvg,
7964
- width: safeWidth,
7965
- height: safeHeight,
7966
- imageHeight: safeImageHeight
7967
- }), {
7968
- waitUntil: "load"
7969
- });
8454
+ const renderMode = normalizeWatermarkifyRenderMode(options.mode);
8455
+ if (renderMode === Mode.Cloak) {
8456
+ const renderHtml = buildWatermarkifyRenderHtml({
8457
+ imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
8458
+ overlaySvg,
8459
+ width: safeWidth,
8460
+ height: safeHeight,
8461
+ imageHeight: safeImageHeight
8462
+ });
8463
+ await renderPage.goto("about:blank", {
8464
+ waitUntil: "commit"
8465
+ }).catch(() => {
8466
+ });
8467
+ await renderPage.evaluate((html) => {
8468
+ document.open();
8469
+ document.write(html);
8470
+ document.close();
8471
+ }, renderHtml);
8472
+ } else {
8473
+ await renderPage.setContent(buildWatermarkifyRenderHtml({
8474
+ imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
8475
+ overlaySvg,
8476
+ width: safeWidth,
8477
+ height: safeHeight,
8478
+ imageHeight: safeImageHeight
8479
+ }), {
8480
+ waitUntil: "load"
8481
+ });
8482
+ }
7970
8483
  await renderPage.waitForFunction(() => {
7971
8484
  const image = document.getElementById("pk-base-image");
7972
8485
  return image instanceof HTMLImageElement && image.complete && image.naturalWidth > 0 && image.naturalHeight > 0;
@@ -7986,13 +8499,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
7986
8499
  fullPage: true,
7987
8500
  animations: "disabled"
7988
8501
  }).catch((error) => {
7989
- logger13.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
8502
+ logger14.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
7990
8503
  return null;
7991
8504
  });
7992
8505
  if (Buffer.isBuffer(composed) && composed.length > 0) {
7993
8506
  return composed;
7994
8507
  }
7995
- logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
8508
+ logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
7996
8509
  return buffer;
7997
8510
  } finally {
7998
8511
  await renderScope.close().catch(() => {
@@ -8005,7 +8518,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
8005
8518
  }
8006
8519
  const probeScope = await openProbePage(page);
8007
8520
  if (!probeScope?.page) {
8008
- logger13.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
8521
+ logger14.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
8009
8522
  return null;
8010
8523
  }
8011
8524
  const timeoutMs = Math.max(
@@ -8014,12 +8527,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
8014
8527
  );
8015
8528
  try {
8016
8529
  const probePage = probeScope.page;
8017
- logger13.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
8530
+ logger14.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
8018
8531
  const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
8019
8532
  waitUntil: "commit",
8020
8533
  timeout: timeoutMs
8021
8534
  }).catch((error) => {
8022
- logger13.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
8535
+ logger14.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
8023
8536
  return null;
8024
8537
  });
8025
8538
  const status = response && typeof response.status === "function" ? response.status() : 0;
@@ -8041,13 +8554,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
8041
8554
  }
8042
8555
  const parsed = parseIpIpJsonResponse(rawText);
8043
8556
  if (parsed?.ip || parsed?.location) {
8044
- logger13.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
8557
+ logger14.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
8045
8558
  return parsed;
8046
8559
  }
8047
- logger13.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
8560
+ logger14.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
8048
8561
  return null;
8049
8562
  } catch (error) {
8050
- logger13.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
8563
+ logger14.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
8051
8564
  return null;
8052
8565
  } finally {
8053
8566
  await probeScope.close().catch(() => {
@@ -8061,10 +8574,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
8061
8574
  ip: toInline(options.ip, 80),
8062
8575
  location: toInline(options.location, 80)
8063
8576
  };
8064
- logger13.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
8577
+ logger14.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
8065
8578
  if (!merged.ip || !merged.location) {
8066
8579
  if (cached?.ip || cached?.location) {
8067
- logger13.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
8580
+ logger14.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
8068
8581
  }
8069
8582
  fillEnrichment(merged, cached);
8070
8583
  }
@@ -8088,15 +8601,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
8088
8601
  "x-geo-country"
8089
8602
  ]), 80);
8090
8603
  if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
8091
- logger13.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
8604
+ logger14.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
8092
8605
  merged.location = headerLocation || merged.location;
8093
8606
  }
8094
8607
  }
8095
8608
  writeCachedEnrichment(page, merged);
8096
8609
  if (merged.ip || merged.location) {
8097
- logger13.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
8610
+ logger14.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
8098
8611
  } else {
8099
- logger13.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
8612
+ logger14.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
8100
8613
  }
8101
8614
  return merged;
8102
8615
  };
@@ -8901,7 +9414,7 @@ var buildWatermarkifySvg = (meta, imageWidth, imageHeight) => {
8901
9414
  </svg>
8902
9415
  `;
8903
9416
  };
8904
- var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
9417
+ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null, options = {}) => {
8905
9418
  const hasWatermark = meta?.watermark?.enabled !== false && normalizeText(meta?.watermarkText);
8906
9419
  const hasStrip = meta?.strip?.enabled !== false && Array.isArray(meta?.stripSegments) && meta.stripSegments.length > 0;
8907
9420
  if (!Buffer.isBuffer(buffer) || !meta || !hasWatermark && !hasStrip) {
@@ -8909,7 +9422,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
8909
9422
  }
8910
9423
  const imageInfo = readImageInfo(buffer);
8911
9424
  if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
8912
- logger13.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
9425
+ logger14.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
8913
9426
  return buffer;
8914
9427
  }
8915
9428
  const isMobileStrip = normalizeDevice(meta.device) === Device.Mobile && hasStrip;
@@ -8922,12 +9435,12 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
8922
9435
  if (!overlaySvg) {
8923
9436
  return buffer;
8924
9437
  }
8925
- return await composeScreenshotBufferWithBrowser(page, buffer, overlaySvg, outputImageInfo);
9438
+ return await composeScreenshotBufferWithBrowser(page, buffer, overlaySvg, outputImageInfo, options);
8926
9439
  };
8927
9440
 
8928
9441
  // src/internals/compression.js
8929
9442
  import { Jimp, JimpMime, ResizeStrategy } from "jimp";
8930
- var logger14 = createInternalLogger("Compression");
9443
+ var logger15 = createInternalLogger("Compression");
8931
9444
  var DEFAULT_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
8932
9445
  var DEFAULT_SCREENSHOT_OUTPUT_TYPE = "jpeg";
8933
9446
  var DEFAULT_SCREENSHOT_QUALITY = 0.72;
@@ -9046,18 +9559,18 @@ var compressImageBufferToBase64 = async (buffer, compression) => {
9046
9559
  return buffer.toString("base64");
9047
9560
  }
9048
9561
  const result = await compressImageBuffer(buffer, compression).catch((error) => {
9049
- logger14.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
9562
+ logger15.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
9050
9563
  return null;
9051
9564
  });
9052
9565
  if (!result?.buffer) {
9053
9566
  return buffer.toString("base64");
9054
9567
  }
9055
9568
  if (result.withinLimit) {
9056
- logger14.info(
9569
+ logger15.info(
9057
9570
  `captureScreen \u5DF2\u538B\u7F29: ${originalBytes} -> ${result.bytes} bytes, format=${result.format}, quality=${result.quality}, scale=${result.scale}, size=${result.width}x${result.height}`
9058
9571
  );
9059
9572
  } else {
9060
- logger14.warning(
9573
+ logger15.warning(
9061
9574
  `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}`
9062
9575
  );
9063
9576
  }
@@ -9065,7 +9578,7 @@ var compressImageBufferToBase64 = async (buffer, compression) => {
9065
9578
  };
9066
9579
 
9067
9580
  // src/share.js
9068
- var logger15 = createInternalLogger("Share");
9581
+ var logger16 = createInternalLogger("Share");
9069
9582
  var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
9070
9583
  var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
9071
9584
  var DEFAULT_POLL_INTERVAL_MS = 120;
@@ -9135,9 +9648,9 @@ var normalizeXurl = (value) => {
9135
9648
  var normalizeShare = (share) => {
9136
9649
  const source = share && typeof share === "object" ? share : {};
9137
9650
  const modeRaw = String(source.mode || "dom").trim().toLowerCase();
9138
- const mode = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
9651
+ const mode2 = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
9139
9652
  return {
9140
- mode,
9653
+ mode: mode2,
9141
9654
  prefix: normalizePrefix(source.prefix),
9142
9655
  xurl: normalizeXurl(source.xurl)
9143
9656
  };
@@ -9198,13 +9711,13 @@ var parseJsonSafely = (text) => {
9198
9711
  var createDomShareMonitor = async (page, options = {}) => {
9199
9712
  const prefix = normalizePrefix(options.prefix);
9200
9713
  const selectors = options.selectors ?? "html";
9201
- const mode = options.mode ?? Mutation.Mode.All;
9714
+ const mode2 = options.mode ?? Mutation.Mode.All;
9202
9715
  const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
9203
9716
  const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
9204
9717
  let matched = false;
9205
- logger15.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
9718
+ logger16.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode2}`);
9206
9719
  const monitor = await Mutation.useMonitor(page, selectors, {
9207
- mode,
9720
+ mode: mode2,
9208
9721
  onMutation: (context = {}) => {
9209
9722
  if (matched) return;
9210
9723
  const mutationCount = Number(context.mutationCount || 0);
@@ -9220,12 +9733,12 @@ ${text}`;
9220
9733
  });
9221
9734
  }
9222
9735
  if (mutationCount <= 5 || mutationCount % 50 === 0) {
9223
- logger15.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
9736
+ logger16.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
9224
9737
  }
9225
9738
  const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
9226
9739
  if (!candidate) return;
9227
9740
  matched = true;
9228
- logger15.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
9741
+ logger16.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
9229
9742
  if (onMatch) {
9230
9743
  onMatch({
9231
9744
  link: candidate,
@@ -9241,7 +9754,7 @@ ${text}`;
9241
9754
  return {
9242
9755
  stop: async () => {
9243
9756
  const result = await monitor.stop();
9244
- logger15.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
9757
+ logger16.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
9245
9758
  return result;
9246
9759
  }
9247
9760
  };
@@ -9290,8 +9803,8 @@ var Share = {
9290
9803
  if (share.mode === "response" && apiMatchers.length === 0) {
9291
9804
  throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
9292
9805
  }
9293
- logger15.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutDisabled ? "disabled" : timeoutMs}, prefix=${share.prefix}`);
9294
- logger15.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
9806
+ logger16.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutDisabled ? "disabled" : timeoutMs}, prefix=${share.prefix}`);
9807
+ logger16.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
9295
9808
  const stats = {
9296
9809
  actionTimedOut: false,
9297
9810
  domMutationCount: 0,
@@ -9303,7 +9816,7 @@ var Share = {
9303
9816
  responseSampleUrls: []
9304
9817
  };
9305
9818
  if (isAborted()) {
9306
- logger15.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
9819
+ logger16.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
9307
9820
  return {
9308
9821
  link: null,
9309
9822
  payloadText: "",
@@ -9326,7 +9839,7 @@ var Share = {
9326
9839
  link: validated,
9327
9840
  payloadText: String(payloadText || "")
9328
9841
  };
9329
- logger15.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
9842
+ logger16.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
9330
9843
  return true;
9331
9844
  };
9332
9845
  const resolveResponseCandidate = (responseText) => {
@@ -9361,7 +9874,7 @@ var Share = {
9361
9874
  try {
9362
9875
  await monitor.stop();
9363
9876
  } catch (error) {
9364
- logger15.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
9877
+ logger16.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
9365
9878
  }
9366
9879
  };
9367
9880
  const onResponse = async (response) => {
@@ -9375,29 +9888,29 @@ var Share = {
9375
9888
  stats.responseSampleUrls.push(url);
9376
9889
  }
9377
9890
  if (stats.responseObserved <= 5) {
9378
- logger15.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
9891
+ logger16.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
9379
9892
  }
9380
9893
  if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
9381
9894
  stats.responseMatched += 1;
9382
9895
  stats.lastMatchedUrl = url;
9383
- logger15.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
9896
+ logger16.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
9384
9897
  const text = await response.text();
9385
9898
  const hit = resolveResponseCandidate(text);
9386
9899
  if (!hit?.link) {
9387
9900
  if (stats.responseMatched <= 3) {
9388
- logger15.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
9901
+ logger16.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
9389
9902
  }
9390
9903
  return;
9391
9904
  }
9392
9905
  stats.responseResolved += 1;
9393
- logger15.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
9906
+ logger16.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
9394
9907
  setCandidate("response", hit.link, hit.payloadText);
9395
9908
  } catch (error) {
9396
- logger15.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
9909
+ logger16.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
9397
9910
  }
9398
9911
  };
9399
9912
  if (share.mode === "dom") {
9400
- logger15.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
9913
+ logger16.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
9401
9914
  domMonitor = await createDomShareMonitor(page, {
9402
9915
  prefix: share.prefix,
9403
9916
  selectors: domSelectors,
@@ -9412,17 +9925,17 @@ var Share = {
9412
9925
  });
9413
9926
  }
9414
9927
  if (share.mode === "response") {
9415
- logger15.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
9928
+ logger16.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
9416
9929
  page.on("response", onResponse);
9417
9930
  }
9418
9931
  if (share.mode === "custom") {
9419
- logger15.info("\u5F53\u524D\u4E3A custom \u6A21\u5F0F\uFF0C\u5C06\u4F7F\u7528 performActions \u8FD4\u56DE\u503C");
9932
+ logger16.info("\u5F53\u524D\u4E3A custom \u6A21\u5F0F\uFF0C\u5C06\u4F7F\u7528 performActions \u8FD4\u56DE\u503C");
9420
9933
  }
9421
9934
  const deadline = timeoutDisabled ? Infinity : Date.now() + timeoutMs;
9422
9935
  const getRemainingMs = () => timeoutDisabled ? Infinity : Math.max(0, deadline - Date.now());
9423
9936
  try {
9424
9937
  const actionTimeout = getRemainingMs();
9425
- logger15.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${timeoutDisabled ? "disabled" : `${actionTimeout}ms`}`);
9938
+ logger16.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${timeoutDisabled ? "disabled" : `${actionTimeout}ms`}`);
9426
9939
  let actionValue;
9427
9940
  if (!isAborted() && actionTimeout > 0) {
9428
9941
  let timer = null;
@@ -9435,30 +9948,30 @@ var Share = {
9435
9948
  ]);
9436
9949
  if (timer) clearTimeout(timer);
9437
9950
  if (actionResult.type === "error") {
9438
- logger15.fail("captureLink.performActions", actionResult.error);
9951
+ logger16.fail("captureLink.performActions", actionResult.error);
9439
9952
  throw actionResult.error;
9440
9953
  }
9441
9954
  if (actionResult.type === "timeout") {
9442
9955
  stats.actionTimedOut = true;
9443
- logger15.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
9956
+ logger16.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
9444
9957
  } else {
9445
9958
  actionValue = actionResult.result;
9446
- logger15.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
9959
+ logger16.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
9447
9960
  }
9448
9961
  }
9449
9962
  if (share.mode === "custom") {
9450
9963
  const customLink = typeof actionValue === "string" ? actionValue : actionValue?.link || actionValue?.payloadText;
9451
9964
  const customPayloadText = typeof actionValue === "string" ? actionValue : actionValue?.payloadText;
9452
9965
  if (setCandidate("custom", customLink, customPayloadText)) {
9453
- logger15.success("captureLink.customResult", `custom \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: link=${candidates.custom.link}`);
9966
+ logger16.success("captureLink.customResult", `custom \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: link=${candidates.custom.link}`);
9454
9967
  } else {
9455
- logger15.warning("performActions \u6267\u884C\u5B8C\u6210\u4F46\u672A\u8FD4\u56DE\u6709\u6548\u5206\u4EAB\u94FE\u63A5");
9968
+ logger16.warning("performActions \u6267\u884C\u5B8C\u6210\u4F46\u672A\u8FD4\u56DE\u6709\u6548\u5206\u4EAB\u94FE\u63A5");
9456
9969
  }
9457
9970
  }
9458
9971
  let nextProgressLogTs = Date.now() + 3e3;
9459
9972
  while (true) {
9460
9973
  if (isAborted()) {
9461
- logger15.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
9974
+ logger16.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
9462
9975
  return {
9463
9976
  link: null,
9464
9977
  payloadText: "",
@@ -9468,7 +9981,7 @@ var Share = {
9468
9981
  }
9469
9982
  const selected = candidates[share.mode];
9470
9983
  if (selected?.link) {
9471
- logger15.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
9984
+ logger16.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
9472
9985
  return {
9473
9986
  link: selected.link,
9474
9987
  payloadText: selected.payloadText,
@@ -9481,19 +9994,19 @@ var Share = {
9481
9994
  if (remaining <= 0) break;
9482
9995
  const now = Date.now();
9483
9996
  if (now >= nextProgressLogTs) {
9484
- logger15.info(
9997
+ logger16.info(
9485
9998
  `captureLink \u7B49\u5F85\u4E2D: remaining=${timeoutDisabled ? "disabled" : `${remaining}ms`}, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
9486
9999
  );
9487
10000
  nextProgressLogTs = now + 5e3;
9488
10001
  }
9489
- await delay4(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
10002
+ await delay5(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
9490
10003
  }
9491
10004
  if (!timeoutDisabled && share.mode === "response" && stats.responseMatched === 0) {
9492
- logger15.warning(
10005
+ logger16.warning(
9493
10006
  `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
9494
10007
  );
9495
10008
  }
9496
- logger15.warning(
10009
+ logger16.warning(
9497
10010
  `captureLink ${timeoutDisabled ? "\u672A\u62FF\u5230\u94FE\u63A5" : "\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"}`
9498
10011
  );
9499
10012
  return {
@@ -9505,7 +10018,7 @@ var Share = {
9505
10018
  } finally {
9506
10019
  if (share.mode === "response") {
9507
10020
  page.off("response", onResponse);
9508
- logger15.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
10021
+ logger16.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
9509
10022
  }
9510
10023
  await stopDomMonitor();
9511
10024
  }
@@ -9520,12 +10033,14 @@ var Share = {
9520
10033
  * @param {number} [options.maxBytes] 默认 5MiB,返回 base64 超过后会压缩
9521
10034
  * @param {'jpeg'|'jpg'} [options.type] 压缩输出格式,默认 jpeg
9522
10035
  * @param {boolean|Object} [options.compression] 传 false 可关闭压缩
10036
+ * @param {'default'|'cloak'} [options.mode] 截图水印合成模式,默认取当前 toolkit mode
9523
10037
  * @returns {Promise<string>} base64 image
9524
10038
  */
9525
10039
  async captureScreen(page, options = {}) {
9526
10040
  const restore = options.restore ?? false;
9527
10041
  const screenshotWatermarkify = resolveCaptureScreenWatermarkify(page, options.watermarkify);
9528
10042
  const compression = resolveImageCompression(options);
10043
+ const screenshotMode = options.mode ?? getToolkitMode();
9529
10044
  const captureOptions = {
9530
10045
  restore,
9531
10046
  maxHeight: options.maxHeight,
@@ -9540,7 +10055,9 @@ var Share = {
9540
10055
  ...screenshotWatermarkify,
9541
10056
  capturedAt
9542
10057
  });
9543
- outputBuffer = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta, page);
10058
+ outputBuffer = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta, page, {
10059
+ mode: screenshotMode
10060
+ });
9544
10061
  }
9545
10062
  return await compressImageBufferToBase64(outputBuffer, compression);
9546
10063
  }
@@ -9548,8 +10065,13 @@ var Share = {
9548
10065
 
9549
10066
  // entrys/node.js
9550
10067
  Logger.setLogger(crawleeLog);
9551
- var usePlaywrightToolKit = () => {
9552
- return {
10068
+ var ToolkitMode = Object.freeze({
10069
+ default: Mode.Default,
10070
+ cloak: Mode.Cloak
10071
+ });
10072
+ var usePlaywrightToolKit = (mode2 = Mode.Default) => {
10073
+ setToolkitMode(mode2);
10074
+ const toolkit = {
9553
10075
  ApifyKit,
9554
10076
  AntiCheat,
9555
10077
  DeviceInput,
@@ -9569,7 +10091,9 @@ var usePlaywrightToolKit = () => {
9569
10091
  ByPass,
9570
10092
  $Internals: { LOG_TEMPLATES, stripAnsi }
9571
10093
  };
10094
+ return toolkit;
9572
10095
  };
10096
+ usePlaywrightToolKit.Mode = ToolkitMode;
9573
10097
  export {
9574
10098
  usePlaywrightToolKit
9575
10099
  };