@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.cjs CHANGED
@@ -40,9 +40,12 @@ __export(constants_exports, {
40
40
  ActorInfo: () => ActorInfo,
41
41
  Code: () => Code,
42
42
  Device: () => Device,
43
+ Mode: () => Mode,
43
44
  PresetOfLiveViewKey: () => PresetOfLiveViewKey,
44
45
  Status: () => Status,
45
- normalizeDevice: () => normalizeDevice
46
+ mode: () => mode,
47
+ normalizeDevice: () => normalizeDevice,
48
+ normalizeMode: () => normalizeMode
46
49
  });
47
50
  var Code = {
48
51
  Success: 0,
@@ -62,6 +65,14 @@ var Device = Object.freeze({
62
65
  Desktop: "desktop",
63
66
  Mobile: "mobile"
64
67
  });
68
+ var Mode = Object.freeze({
69
+ Default: "default",
70
+ Cloak: "cloak"
71
+ });
72
+ var mode = Object.freeze({
73
+ default: Mode.Default,
74
+ cloak: Mode.Cloak
75
+ });
65
76
  var normalizeDevice = (value, fallback = Device.Desktop) => {
66
77
  const normalizedFallback = String(fallback || "").trim().toLowerCase() === Device.Mobile ? Device.Mobile : Device.Desktop;
67
78
  const raw = String(value || "").trim().toLowerCase();
@@ -69,6 +80,13 @@ var normalizeDevice = (value, fallback = Device.Desktop) => {
69
80
  if (raw === Device.Desktop) return Device.Desktop;
70
81
  return normalizedFallback;
71
82
  };
83
+ var normalizeMode = (value, fallback = Mode.Default) => {
84
+ const normalizedFallback = String(fallback || "").trim().toLowerCase() === Mode.Cloak ? Mode.Cloak : Mode.Default;
85
+ const raw = String(value || "").trim().toLowerCase();
86
+ if (raw === Mode.Cloak) return Mode.Cloak;
87
+ if (raw === Mode.Default) return Mode.Default;
88
+ return normalizedFallback;
89
+ };
72
90
  var createActorInfo = (info) => {
73
91
  const normalizeDomain = (value) => {
74
92
  if (!value) return "";
@@ -83,7 +101,7 @@ var createActorInfo = (info) => {
83
101
  const normalizeShare2 = (value) => {
84
102
  const raw = value && typeof value === "object" ? value : {};
85
103
  const modeRaw = String(raw.mode || "dom").trim().toLowerCase();
86
- const mode = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
104
+ const mode2 = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
87
105
  const prefix = String(raw.prefix || "").trim();
88
106
  const rawXurl = Array.isArray(raw.xurl) ? raw.xurl : [];
89
107
  const normalizeMatcherList = (input) => {
@@ -128,7 +146,7 @@ var createActorInfo = (info) => {
128
146
  xurl.push(...extraPaths);
129
147
  }
130
148
  return {
131
- mode,
149
+ mode: mode2,
132
150
  prefix,
133
151
  xurl
134
152
  };
@@ -136,7 +154,6 @@ var createActorInfo = (info) => {
136
154
  const buildLandingUrl = ({ protocol: protocol2, domain: domain2, path: path4 }) => {
137
155
  const safeProtocol = String(protocol2).trim();
138
156
  const safeDomain = normalizeDomain(domain2);
139
- if (!safeDomain) return "";
140
157
  const safePath = normalizePath(path4);
141
158
  return `${safeProtocol}://${safeDomain}${safePath}`;
142
159
  };
@@ -344,18 +361,6 @@ var ActorInfo = {
344
361
  prefix: "",
345
362
  xurl: []
346
363
  }
347
- }),
348
- // 通用网页抓取 Actor:入口 URL 来自 query,因此这里只声明统一的 Actor 元信息。
349
- webpage: createActorInfo({
350
- key: "webpage",
351
- name: "\u901A\u7528\u7F51\u9875",
352
- domain: "",
353
- path: "/",
354
- share: {
355
- mode: "dom",
356
- prefix: "",
357
- xurl: []
358
- }
359
364
  })
360
365
  };
361
366
 
@@ -387,18 +392,18 @@ var fallbackLog = {
387
392
  error: (...args) => console.error(...args),
388
393
  debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
389
394
  };
390
- var resolveLogMethod = (logger16, name) => {
391
- if (logger16 && typeof logger16[name] === "function") {
392
- return logger16[name].bind(logger16);
395
+ var resolveLogMethod = (logger17, name) => {
396
+ if (logger17 && typeof logger17[name] === "function") {
397
+ return logger17[name].bind(logger17);
393
398
  }
394
- if (name === "warning" && logger16 && typeof logger16.warn === "function") {
395
- return logger16.warn.bind(logger16);
399
+ if (name === "warning" && logger17 && typeof logger17.warn === "function") {
400
+ return logger17.warn.bind(logger17);
396
401
  }
397
402
  return fallbackLog[name];
398
403
  };
399
404
  var defaultLogger = null;
400
- var setDefaultLogger = (logger16) => {
401
- defaultLogger = logger16;
405
+ var setDefaultLogger = (logger17) => {
406
+ defaultLogger = logger17;
402
407
  };
403
408
  var resolveLogger = (explicitLogger) => {
404
409
  if (explicitLogger && typeof explicitLogger.info === "function") {
@@ -425,8 +430,8 @@ var colorize = (text, color) => {
425
430
  var createBaseLogger = (prefix = "", explicitLogger) => {
426
431
  const name = prefix ? String(prefix) : "";
427
432
  const dispatch = (methodName, icon, message, color) => {
428
- const logger16 = resolveLogger(explicitLogger);
429
- const logFn = resolveLogMethod(logger16, methodName);
433
+ const logger17 = resolveLogger(explicitLogger);
434
+ const logFn = resolveLogMethod(logger17, methodName);
430
435
  const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
431
436
  const line = formatLine(name, icon, message);
432
437
  const coloredLine = colorize(line, color);
@@ -780,7 +785,7 @@ var adjustAffixedElementsForExpandedScreenshot = async (page, options = {}) => {
780
785
  if (safeTargetHeight <= viewportHeight + 1) {
781
786
  return 0;
782
787
  }
783
- const hasOwn = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
788
+ const hasOwn2 = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
784
789
  const isVisible = (el, style, rect) => {
785
790
  if (!el || !style || !rect) return false;
786
791
  if (style.display === "none" || style.visibility === "hidden" || style.visibility === "collapse") {
@@ -820,7 +825,7 @@ var adjustAffixedElementsForExpandedScreenshot = async (page, options = {}) => {
820
825
  return true;
821
826
  });
822
827
  topLevelCandidates.forEach(({ el, position, edge }) => {
823
- if (!hasOwn(el.dataset, "pkAffixedAdjusted")) {
828
+ if (!hasOwn2(el.dataset, "pkAffixedAdjusted")) {
824
829
  el.dataset.pkAffixedAdjusted = "1";
825
830
  el.dataset.pkOrigPosition = el.style.getPropertyValue("position") || "";
826
831
  el.dataset.pkOrigPositionPriority = el.style.getPropertyPriority("position") || "";
@@ -851,7 +856,7 @@ var adjustAffixedElementsForExpandedScreenshot = async (page, options = {}) => {
851
856
  };
852
857
  var restoreAffixedElementsForExpandedScreenshot = async (page) => {
853
858
  await page.evaluate((className) => {
854
- const hasOwn = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
859
+ const hasOwn2 = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
855
860
  const expansionKeys = [
856
861
  "pkOrigOverflow",
857
862
  "pkOrigHeight",
@@ -859,28 +864,28 @@ var restoreAffixedElementsForExpandedScreenshot = async (page) => {
859
864
  "pkOrigMaxHeight"
860
865
  ];
861
866
  document.querySelectorAll('[data-pk-affixed-adjusted="1"]').forEach((el) => {
862
- if (hasOwn(el.dataset, "pkOrigPosition")) {
867
+ if (hasOwn2(el.dataset, "pkOrigPosition")) {
863
868
  el.style.setProperty("position", el.dataset.pkOrigPosition || "", el.dataset.pkOrigPositionPriority || "");
864
869
  delete el.dataset.pkOrigPosition;
865
870
  delete el.dataset.pkOrigPositionPriority;
866
871
  }
867
- if (hasOwn(el.dataset, "pkOrigTop")) {
872
+ if (hasOwn2(el.dataset, "pkOrigTop")) {
868
873
  el.style.setProperty("top", el.dataset.pkOrigTop || "", el.dataset.pkOrigTopPriority || "");
869
874
  delete el.dataset.pkOrigTop;
870
875
  delete el.dataset.pkOrigTopPriority;
871
876
  }
872
- if (hasOwn(el.dataset, "pkOrigBottom")) {
877
+ if (hasOwn2(el.dataset, "pkOrigBottom")) {
873
878
  el.style.setProperty("bottom", el.dataset.pkOrigBottom || "", el.dataset.pkOrigBottomPriority || "");
874
879
  delete el.dataset.pkOrigBottom;
875
880
  delete el.dataset.pkOrigBottomPriority;
876
881
  }
877
- if (hasOwn(el.dataset, "pkOrigTranslate")) {
882
+ if (hasOwn2(el.dataset, "pkOrigTranslate")) {
878
883
  el.style.setProperty("translate", el.dataset.pkOrigTranslate || "", el.dataset.pkOrigTranslatePriority || "");
879
884
  delete el.dataset.pkOrigTranslate;
880
885
  delete el.dataset.pkOrigTranslatePriority;
881
886
  }
882
887
  delete el.dataset.pkAffixedAdjusted;
883
- const stillExpanded = expansionKeys.some((key) => hasOwn(el.dataset, key));
888
+ const stillExpanded = expansionKeys.some((key) => hasOwn2(el.dataset, key));
884
889
  if (!stillExpanded) {
885
890
  el.classList.remove(className);
886
891
  }
@@ -923,7 +928,7 @@ var prepareExpandedFullPageScreenshot = async (page, options = {}) => {
923
928
  viewportResized
924
929
  };
925
930
  };
926
- var restoreExpandedFullPageScreenshot = async (page, state = {}) => {
931
+ var restoreExpandedFullPageScreenshot = async (page, state2 = {}) => {
927
932
  await page.evaluate((className) => {
928
933
  const targets = new Set([
929
934
  ...document.querySelectorAll(`.${className}`),
@@ -947,8 +952,8 @@ var restoreExpandedFullPageScreenshot = async (page, state = {}) => {
947
952
  el.classList.remove(className);
948
953
  });
949
954
  }, EXPANDED_SCROLLABLE_CLASS);
950
- if (state?.originalViewport && state?.viewportResized) {
951
- await page.setViewportSize(state.originalViewport);
955
+ if (state2?.originalViewport && state2?.viewportResized) {
956
+ await page.setViewportSize(state2.originalViewport);
952
957
  }
953
958
  };
954
959
  var capturePageScreenshot = async (page, options = {}) => {
@@ -1005,21 +1010,21 @@ var capturePageScreenshot = async (page, options = {}) => {
1005
1010
  }
1006
1011
  };
1007
1012
  var captureExpandedFullPageScreenshot = async (page, options = {}) => {
1008
- const state = await prepareExpandedFullPageScreenshot(page, options);
1013
+ const state2 = await prepareExpandedFullPageScreenshot(page, options);
1009
1014
  try {
1010
1015
  return await capturePageScreenshot(page, {
1011
1016
  fullPage: true,
1012
1017
  type: options.type || "png",
1013
1018
  quality: options.quality,
1014
1019
  timeout: options.timeout,
1015
- maxClipHeight: state.targetHeight
1020
+ maxClipHeight: state2.targetHeight
1016
1021
  });
1017
1022
  } finally {
1018
1023
  await restoreAffixedElementsForExpandedScreenshot(page).catch((error) => {
1019
1024
  logger.warning(`\u79FB\u52A8\u7AEF\u5438\u9644\u5143\u7D20\u6062\u590D\u5931\u8D25: ${error?.message || error}`);
1020
1025
  });
1021
1026
  if (options.restore) {
1022
- await restoreExpandedFullPageScreenshot(page, state);
1027
+ await restoreExpandedFullPageScreenshot(page, state2);
1023
1028
  }
1024
1029
  }
1025
1030
  };
@@ -1938,8 +1943,8 @@ var normalizeBrowserProfile = (value) => {
1938
1943
  payload: buildBrowserProfilePayload(core, observed)
1939
1944
  };
1940
1945
  };
1941
- var rememberRuntimeState = (state) => {
1942
- rememberedRuntimeState = deepClone(state);
1946
+ var rememberRuntimeState = (state2) => {
1947
+ rememberedRuntimeState = deepClone(state2);
1943
1948
  return rememberedRuntimeState;
1944
1949
  };
1945
1950
  var normalizeRuntimeState = (source = {}, actor = "") => {
@@ -1998,7 +2003,7 @@ var RuntimeEnv = {
1998
2003
  } else {
1999
2004
  delete normalizedRuntime.browser_profile;
2000
2005
  }
2001
- const state = {
2006
+ const state2 = {
2002
2007
  actor: resolvedActor,
2003
2008
  device,
2004
2009
  runtime: normalizedRuntime,
@@ -2012,73 +2017,73 @@ var RuntimeEnv = {
2012
2017
  browserProfileCore: browserProfile.core,
2013
2018
  browserProfileObserved: browserProfile.observed
2014
2019
  };
2015
- rememberRuntimeState(state);
2016
- return state;
2020
+ rememberRuntimeState(state2);
2021
+ return state2;
2017
2022
  },
2018
2023
  // buildEnvPatch 只构造允许回写到后端 env 的字段集合。
2019
2024
  buildEnvPatch(source = {}, actor = "") {
2020
- const state = normalizeRuntimeState(source, actor);
2021
- const browserProfile = buildBrowserProfilePayload(state.browserProfileCore, state.browserProfileObserved);
2025
+ const state2 = normalizeRuntimeState(source, actor);
2026
+ const browserProfile = buildBrowserProfilePayload(state2.browserProfileCore, state2.browserProfileObserved);
2022
2027
  const envPatch = {
2023
- ...Array.isArray(state.cookies) && state.cookies.length > 0 ? { cookies: state.cookies } : {},
2024
- ...Object.keys(state.localStorage || {}).length > 0 ? { local_storage: state.localStorage } : {},
2025
- ...Object.keys(state.sessionStorage || {}).length > 0 ? { session_storage: state.sessionStorage } : {},
2028
+ ...Array.isArray(state2.cookies) && state2.cookies.length > 0 ? { cookies: state2.cookies } : {},
2029
+ ...Object.keys(state2.localStorage || {}).length > 0 ? { local_storage: state2.localStorage } : {},
2030
+ ...Object.keys(state2.sessionStorage || {}).length > 0 ? { session_storage: state2.sessionStorage } : {},
2026
2031
  ...Object.keys(browserProfile).length > 0 ? { browser_profile: browserProfile } : {}
2027
2032
  };
2028
2033
  return Object.keys(envPatch).length > 0 ? envPatch : null;
2029
2034
  },
2030
2035
  // hasLoginState 只判断 runtime 是否存在有效载荷,不再区分具体字段来源。
2031
2036
  hasLoginState(source = {}, actor = "") {
2032
- const state = normalizeRuntimeState(source, actor);
2033
- return isPlainObject(state.runtime) && Object.keys(state.runtime || {}).length > 0;
2037
+ const state2 = normalizeRuntimeState(source, actor);
2038
+ return isPlainObject(state2.runtime) && Object.keys(state2.runtime || {}).length > 0;
2034
2039
  },
2035
2040
  rememberState(source = {}) {
2036
- const state = normalizeRuntimeState(source);
2037
- rememberRuntimeState(state);
2041
+ const state2 = normalizeRuntimeState(source);
2042
+ rememberRuntimeState(state2);
2038
2043
  return RuntimeEnv.peekRememberedState();
2039
2044
  },
2040
2045
  peekRememberedState() {
2041
2046
  return rememberedRuntimeState ? deepClone(rememberedRuntimeState) : null;
2042
2047
  },
2043
2048
  getBrowserProfileCore(source = {}, actor = "") {
2044
- const state = normalizeRuntimeState(source, actor);
2045
- return deepClone(state.browserProfileCore || {});
2049
+ const state2 = normalizeRuntimeState(source, actor);
2050
+ return deepClone(state2.browserProfileCore || {});
2046
2051
  },
2047
2052
  setBrowserProfileCore(source = {}, core = {}, actor = "") {
2048
- const state = normalizeRuntimeState(source, actor);
2053
+ const state2 = normalizeRuntimeState(source, actor);
2049
2054
  const normalizedCore = normalizeBrowserProfileCore({
2050
2055
  ...core,
2051
- device: normalizeKnownDevice(core?.device) || state.device
2056
+ device: normalizeKnownDevice(core?.device) || state2.device
2052
2057
  });
2053
- state.browserProfileCore = normalizedCore;
2054
- state.browserProfile = buildBrowserProfilePayload(normalizedCore, state.browserProfileObserved);
2055
- if (Object.keys(state.browserProfile).length > 0) {
2056
- state.runtime.browser_profile = state.browserProfile;
2058
+ state2.browserProfileCore = normalizedCore;
2059
+ state2.browserProfile = buildBrowserProfilePayload(normalizedCore, state2.browserProfileObserved);
2060
+ if (Object.keys(state2.browserProfile).length > 0) {
2061
+ state2.runtime.browser_profile = state2.browserProfile;
2057
2062
  } else {
2058
- delete state.runtime.browser_profile;
2063
+ delete state2.runtime.browser_profile;
2059
2064
  }
2060
- rememberRuntimeState(state);
2061
- return state;
2065
+ rememberRuntimeState(state2);
2066
+ return state2;
2062
2067
  },
2063
2068
  // applyToPage 只负责把登录态相关字段注入页面:
2064
2069
  // cookies / localStorage / sessionStorage。
2065
2070
  // 指纹、时区、UA、viewport 的回放发生在 launch.js 启动阶段,不在这里做。
2066
2071
  async applyToPage(page, source = {}, options = {}) {
2067
2072
  if (!page) return;
2068
- let state = normalizeRuntimeState(source, options?.actor || "");
2073
+ let state2 = normalizeRuntimeState(source, options?.actor || "");
2069
2074
  if (typeof options?.preapply === "function") {
2070
- state = await options.preapply(state) || state;
2071
- rememberRuntimeState(state);
2075
+ state2 = await options.preapply(state2) || state2;
2076
+ rememberRuntimeState(state2);
2072
2077
  }
2073
2078
  Object.defineProperty(page, PageRuntimeStateKey, {
2074
2079
  configurable: true,
2075
2080
  enumerable: false,
2076
2081
  writable: true,
2077
- value: state
2082
+ value: state2
2078
2083
  });
2079
- const localStorage = state.localStorage || {};
2080
- const sessionStorage = state.sessionStorage || {};
2081
- const cookies = (state.cookies || []).map((cookie) => {
2084
+ const localStorage = state2.localStorage || {};
2085
+ const sessionStorage = state2.sessionStorage || {};
2086
+ const cookies = (state2.cookies || []).map((cookie) => {
2082
2087
  const normalized = { ...cookie };
2083
2088
  if (!normalized.path) {
2084
2089
  normalized.path = "/";
@@ -2116,8 +2121,8 @@ var RuntimeEnv = {
2116
2121
  },
2117
2122
  // captureEnvPatch 在任务结束时采集最新环境快照,用于 pushSuccess / pushFailed 自动回写。
2118
2123
  async captureEnvPatch(page, source = {}, options = {}) {
2119
- const state = normalizeRuntimeState(source, options?.actor || "");
2120
- const baseline = RuntimeEnv.buildEnvPatch(state) || {};
2124
+ const state2 = normalizeRuntimeState(source, options?.actor || "");
2125
+ const baseline = RuntimeEnv.buildEnvPatch(state2) || {};
2121
2126
  if (!page || typeof page.evaluate !== "function" || typeof page.context !== "function") {
2122
2127
  return Object.keys(baseline).length > 0 ? baseline : null;
2123
2128
  }
@@ -2136,7 +2141,7 @@ var RuntimeEnv = {
2136
2141
  cookies
2137
2142
  },
2138
2143
  {
2139
- browserProfileCore: state.browserProfileCore
2144
+ browserProfileCore: state2.browserProfileCore
2140
2145
  }
2141
2146
  );
2142
2147
  return RuntimeEnv.mergeEnvPatches(baseline, capturedPatch);
@@ -2150,11 +2155,11 @@ var RuntimeEnv = {
2150
2155
  var logger3 = createInternalLogger("ApifyKit");
2151
2156
  var resolveRuntimeContext = (input) => {
2152
2157
  const rememberedState = RuntimeEnv.peekRememberedState();
2153
- const state = rememberedState || RuntimeEnv.parseInput(input || {});
2154
- const envPatch = RuntimeEnv.buildEnvPatch(state) || null;
2158
+ const state2 = rememberedState || RuntimeEnv.parseInput(input || {});
2159
+ const envPatch = RuntimeEnv.buildEnvPatch(state2) || null;
2155
2160
  return {
2156
- actor: state.actor,
2157
- runtime: state.runtime,
2161
+ actor: state2.actor,
2162
+ runtime: state2.runtime,
2158
2163
  envPatch
2159
2164
  };
2160
2165
  };
@@ -2513,8 +2518,82 @@ var Utils = {
2513
2518
  }
2514
2519
  };
2515
2520
 
2516
- // src/anti-cheat.js
2517
- var logger5 = createInternalLogger("AntiCheat");
2521
+ // src/internals/context.js
2522
+ var state = {
2523
+ mode: Mode.Default
2524
+ };
2525
+ var normalizeStrategies = (strategies) => strategies && typeof strategies === "object" ? strategies : {};
2526
+ var ToolkitContext = {
2527
+ get mode() {
2528
+ return state.mode;
2529
+ },
2530
+ setMode(mode2 = Mode.Default) {
2531
+ state.mode = normalizeMode(mode2, Mode.Default);
2532
+ return state.mode;
2533
+ }
2534
+ };
2535
+ var getToolkitMode = () => state.mode;
2536
+ var setToolkitMode = (mode2 = Mode.Default) => ToolkitContext.setMode(mode2);
2537
+ var resolveModeStrategy = (strategies = {}, mode2 = getToolkitMode(), fallbackMode = Mode.Default) => {
2538
+ const normalizedStrategies = normalizeStrategies(strategies);
2539
+ const normalizedMode = normalizeMode(mode2, fallbackMode);
2540
+ const strategy = normalizedStrategies[normalizedMode] ?? normalizedStrategies[fallbackMode] ?? Object.values(normalizedStrategies).find(Boolean) ?? null;
2541
+ return {
2542
+ mode: normalizedMode,
2543
+ strategy
2544
+ };
2545
+ };
2546
+
2547
+ // src/internals/reflect.js
2548
+ var normalizeStrategies2 = (strategies) => strategies && typeof strategies === "object" ? strategies : {};
2549
+ var collectFunctionNames = (strategies = []) => {
2550
+ const names = /* @__PURE__ */ new Set();
2551
+ for (const strategy of strategies) {
2552
+ if (!strategy || typeof strategy !== "object") continue;
2553
+ for (const name of Reflect.ownKeys(strategy)) {
2554
+ if (typeof name === "string" && typeof strategy[name] === "function") {
2555
+ names.add(name);
2556
+ }
2557
+ }
2558
+ }
2559
+ return names;
2560
+ };
2561
+ var methodDescriptor = (namespace, name, resolveTarget) => ({
2562
+ enumerable: true,
2563
+ configurable: true,
2564
+ writable: true,
2565
+ value: (...args) => {
2566
+ const { mode: mode2, strategy } = resolveTarget(args);
2567
+ const method = strategy?.[name];
2568
+ if (typeof method !== "function") {
2569
+ throw new Error(`${namespace}.${name} is not available in ${mode2} mode`);
2570
+ }
2571
+ return method.apply(strategy, args);
2572
+ }
2573
+ });
2574
+ var withModeReflect = (namespace, strategies = {}) => {
2575
+ const normalizedStrategies = normalizeStrategies2(strategies);
2576
+ const baseStrategy = normalizedStrategies.default ?? Object.values(normalizedStrategies).find(Boolean);
2577
+ const names = collectFunctionNames([baseStrategy]);
2578
+ const descriptors = {};
2579
+ for (const name of names) {
2580
+ descriptors[name] = methodDescriptor(namespace, name, () => resolveModeStrategy(normalizedStrategies));
2581
+ }
2582
+ return Object.defineProperties({}, descriptors);
2583
+ };
2584
+ var withPageReflect = (namespace, resolveStrategy, strategies = []) => {
2585
+ const names = collectFunctionNames(strategies);
2586
+ const descriptors = {};
2587
+ for (const name of names) {
2588
+ descriptors[name] = methodDescriptor(namespace, name, ([page]) => ({
2589
+ mode: "page",
2590
+ strategy: resolveStrategy(page)
2591
+ }));
2592
+ }
2593
+ return Object.defineProperties({}, descriptors);
2594
+ };
2595
+
2596
+ // src/internals/anti-cheat/default.js
2518
2597
  var BASE_CONFIG = Object.freeze({
2519
2598
  locale: "zh-CN",
2520
2599
  acceptLanguage: "zh-CN,zh;q=0.9",
@@ -2549,7 +2628,7 @@ function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVers
2549
2628
  }
2550
2629
  return options;
2551
2630
  }
2552
- var AntiCheat = {
2631
+ var DefaultAntiCheat = {
2553
2632
  /**
2554
2633
  * 获取统一的基础配置
2555
2634
  */
@@ -2586,6 +2665,47 @@ var AntiCheat = {
2586
2665
  }
2587
2666
  };
2588
2667
 
2668
+ // src/internals/anti-cheat/cloak.js
2669
+ var CLOAK_BASE_CONFIG = Object.freeze({
2670
+ locale: "",
2671
+ acceptLanguage: "",
2672
+ timezoneId: "",
2673
+ timezoneOffset: null,
2674
+ geolocation: null
2675
+ });
2676
+ var normalizeHeaders = (headers) => headers && typeof headers === "object" ? headers : {};
2677
+ var CloakAntiCheat = {
2678
+ /**
2679
+ * Cloak 自身会负责浏览器指纹,toolkit 在该模式下尽量不再注入额外反检测配置。
2680
+ */
2681
+ getBaseConfig() {
2682
+ return { ...CLOAK_BASE_CONFIG };
2683
+ },
2684
+ getFingerprintGeneratorOptions() {
2685
+ return {};
2686
+ },
2687
+ getLaunchArgs() {
2688
+ return [];
2689
+ },
2690
+ getTlsFingerprintOptions() {
2691
+ return {};
2692
+ },
2693
+ applyLocaleHeaders(headers, acceptLanguage = "") {
2694
+ const normalizedHeaders = normalizeHeaders(headers);
2695
+ if (acceptLanguage && !normalizedHeaders["accept-language"]) {
2696
+ normalizedHeaders["accept-language"] = acceptLanguage;
2697
+ }
2698
+ return normalizedHeaders;
2699
+ }
2700
+ };
2701
+
2702
+ // src/anti-cheat.js
2703
+ var antiCheatStrategies = {
2704
+ [Mode.Default]: DefaultAntiCheat,
2705
+ [Mode.Cloak]: CloakAntiCheat
2706
+ };
2707
+ var AntiCheat = withModeReflect("AntiCheat", antiCheatStrategies);
2708
+
2589
2709
  // src/device-input.js
2590
2710
  var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
2591
2711
  var assertPage = (page, method) => {
@@ -2985,12 +3105,12 @@ var resolveDescriptor = (descriptor, device) => {
2985
3105
  }
2986
3106
  return resolved;
2987
3107
  };
2988
- var attachRuntimeState = (page, state) => {
3108
+ var attachRuntimeState = (page, state2) => {
2989
3109
  Object.defineProperty(page, PageRuntimeStateKey, {
2990
3110
  configurable: true,
2991
3111
  enumerable: false,
2992
3112
  writable: true,
2993
- value: state
3113
+ value: state2
2994
3114
  });
2995
3115
  };
2996
3116
  var restoreRuntimeState = (page, snapshot) => {
@@ -3136,10 +3256,13 @@ var DeviceView = {
3136
3256
  }
3137
3257
  };
3138
3258
 
3259
+ // src/internals/humanize/index.js
3260
+ var import_delay4 = __toESM(require("delay"), 1);
3261
+
3139
3262
  // src/internals/humanize/desktop.js
3140
3263
  var import_delay2 = __toESM(require("delay"), 1);
3141
3264
  var import_ghost_cursor_playwright = require("ghost-cursor-playwright");
3142
- var logger6 = createInternalLogger("Humanize");
3265
+ var logger5 = createInternalLogger("Humanize");
3143
3266
  var $CursorWeakMap = /* @__PURE__ */ new WeakMap();
3144
3267
  function $GetCursor(page) {
3145
3268
  const cursor = $CursorWeakMap.get(page);
@@ -3167,13 +3290,13 @@ var Humanize = {
3167
3290
  */
3168
3291
  async initializeCursor(page) {
3169
3292
  if ($CursorWeakMap.has(page)) {
3170
- logger6.debug("initializeCursor: cursor already exists, skipping");
3293
+ logger5.debug("initializeCursor: cursor already exists, skipping");
3171
3294
  return;
3172
3295
  }
3173
- logger6.start("initializeCursor", "creating cursor");
3296
+ logger5.start("initializeCursor", "creating cursor");
3174
3297
  const cursor = await (0, import_ghost_cursor_playwright.createCursor)(page);
3175
3298
  $CursorWeakMap.set(page, cursor);
3176
- logger6.success("initializeCursor", "cursor initialized");
3299
+ logger5.success("initializeCursor", "cursor initialized");
3177
3300
  },
3178
3301
  /**
3179
3302
  * 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
@@ -3183,17 +3306,17 @@ var Humanize = {
3183
3306
  */
3184
3307
  async humanMove(page, target) {
3185
3308
  const cursor = $GetCursor(page);
3186
- logger6.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
3309
+ logger5.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
3187
3310
  try {
3188
3311
  if (typeof target === "string") {
3189
3312
  const element = await page.$(target);
3190
3313
  if (!element) {
3191
- logger6.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
3314
+ logger5.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
3192
3315
  return false;
3193
3316
  }
3194
3317
  const box = await element.boundingBox();
3195
3318
  if (!box) {
3196
- logger6.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
3319
+ logger5.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
3197
3320
  return false;
3198
3321
  }
3199
3322
  const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;
@@ -3209,10 +3332,10 @@ var Humanize = {
3209
3332
  await cursor.actions.move({ x, y });
3210
3333
  }
3211
3334
  }
3212
- logger6.success("humanMove");
3335
+ logger5.success("humanMove");
3213
3336
  return true;
3214
3337
  } catch (error) {
3215
- logger6.fail("humanMove", error);
3338
+ logger5.fail("humanMove", error);
3216
3339
  throw error;
3217
3340
  }
3218
3341
  },
@@ -3236,12 +3359,12 @@ var Humanize = {
3236
3359
  maxDurationMs = maxSteps * 220 + 800
3237
3360
  } = options;
3238
3361
  const targetDesc = typeof target === "string" ? target : "ElementHandle";
3239
- logger6.start("humanScroll", `target=${targetDesc}`);
3362
+ logger5.start("humanScroll", `target=${targetDesc}`);
3240
3363
  let element;
3241
3364
  if (typeof target === "string") {
3242
3365
  element = await page.$(target);
3243
3366
  if (!element) {
3244
- logger6.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
3367
+ logger5.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
3245
3368
  return { element: null, didScroll: false };
3246
3369
  }
3247
3370
  } else {
@@ -3316,26 +3439,26 @@ var Humanize = {
3316
3439
  try {
3317
3440
  for (let i = 0; i < maxSteps; i++) {
3318
3441
  if (Date.now() - startTime > maxDurationMs) {
3319
- logger6.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
3442
+ logger5.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
3320
3443
  return { element, didScroll };
3321
3444
  }
3322
3445
  const status = await checkVisibility();
3323
3446
  if (status.code === "VISIBLE") {
3324
3447
  if (status.isFixed) {
3325
- logger6.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3448
+ logger5.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3326
3449
  } else {
3327
- logger6.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
3450
+ logger5.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
3328
3451
  }
3329
- logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
3452
+ logger5.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
3330
3453
  return { element, didScroll };
3331
3454
  }
3332
- logger6.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
3455
+ logger5.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
3333
3456
  if (status.code === "OBSTRUCTED" && status.obstruction) {
3334
- logger6.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
3457
+ logger5.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
3335
3458
  }
3336
3459
  const scrollRect = await getScrollableRect2();
3337
3460
  if (!scrollRect && status.isFixed) {
3338
- logger6.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3461
+ logger5.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
3339
3462
  return { element, didScroll };
3340
3463
  }
3341
3464
  const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
@@ -3371,10 +3494,10 @@ var Humanize = {
3371
3494
  didScroll = true;
3372
3495
  await (0, import_delay2.default)(this.jitterMs(20 + Math.random() * 40, 0.2));
3373
3496
  }
3374
- logger6.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
3497
+ logger5.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
3375
3498
  return { element, didScroll };
3376
3499
  } catch (error) {
3377
- logger6.fail("humanScroll", error);
3500
+ logger5.fail("humanScroll", error);
3378
3501
  throw error;
3379
3502
  }
3380
3503
  },
@@ -3392,7 +3515,7 @@ var Humanize = {
3392
3515
  const cursor = $GetCursor(page);
3393
3516
  const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;
3394
3517
  const targetDesc = target == null ? "Current Position" : typeof target === "string" ? target : "ElementHandle";
3395
- logger6.start("humanClick", `target=${targetDesc}`);
3518
+ logger5.start("humanClick", `target=${targetDesc}`);
3396
3519
  const restoreOnce = async () => {
3397
3520
  if (restoreOnce.restored) return;
3398
3521
  restoreOnce.restored = true;
@@ -3401,14 +3524,14 @@ var Humanize = {
3401
3524
  await (0, import_delay2.default)(this.jitterMs(1e3));
3402
3525
  await restoreOnce.do();
3403
3526
  } catch (restoreError) {
3404
- logger6.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
3527
+ logger5.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
3405
3528
  }
3406
3529
  };
3407
3530
  try {
3408
3531
  if (target == null) {
3409
3532
  await (0, import_delay2.default)(this.jitterMs(reactionDelay, 0.4));
3410
3533
  await cursor.actions.click();
3411
- logger6.success("humanClick", "Clicked current position");
3534
+ logger5.success("humanClick", "Clicked current position");
3412
3535
  return true;
3413
3536
  }
3414
3537
  let element;
@@ -3418,7 +3541,7 @@ var Humanize = {
3418
3541
  if (throwOnMissing) {
3419
3542
  throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);
3420
3543
  }
3421
- logger6.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
3544
+ logger5.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
3422
3545
  return false;
3423
3546
  }
3424
3547
  } else {
@@ -3434,7 +3557,7 @@ var Humanize = {
3434
3557
  if (throwOnMissing) {
3435
3558
  throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
3436
3559
  }
3437
- logger6.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
3560
+ logger5.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
3438
3561
  return false;
3439
3562
  }
3440
3563
  const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
@@ -3443,11 +3566,11 @@ var Humanize = {
3443
3566
  await (0, import_delay2.default)(this.jitterMs(reactionDelay, 0.4));
3444
3567
  await cursor.actions.click();
3445
3568
  await restoreOnce();
3446
- logger6.success("humanClick");
3569
+ logger5.success("humanClick");
3447
3570
  return true;
3448
3571
  } catch (error) {
3449
3572
  await restoreOnce();
3450
- logger6.fail("humanClick", error);
3573
+ logger5.fail("humanClick", error);
3451
3574
  throw error;
3452
3575
  }
3453
3576
  },
@@ -3458,9 +3581,9 @@ var Humanize = {
3458
3581
  */
3459
3582
  async randomSleep(baseMs, jitterPercent = 0.3) {
3460
3583
  const ms = this.jitterMs(baseMs, jitterPercent);
3461
- logger6.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
3584
+ logger5.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
3462
3585
  await (0, import_delay2.default)(ms);
3463
- logger6.success("randomSleep");
3586
+ logger5.success("randomSleep");
3464
3587
  },
3465
3588
  /**
3466
3589
  * 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
@@ -3470,7 +3593,7 @@ var Humanize = {
3470
3593
  async simulateGaze(page, baseDurationMs = 2500) {
3471
3594
  const cursor = $GetCursor(page);
3472
3595
  const durationMs = this.jitterMs(baseDurationMs, 0.4);
3473
- logger6.start("simulateGaze", `duration=${durationMs}ms`);
3596
+ logger5.start("simulateGaze", `duration=${durationMs}ms`);
3474
3597
  const startTime = Date.now();
3475
3598
  const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
3476
3599
  while (Date.now() - startTime < durationMs) {
@@ -3479,7 +3602,7 @@ var Humanize = {
3479
3602
  await cursor.actions.move({ x, y });
3480
3603
  await (0, import_delay2.default)(this.jitterMs(600, 0.5));
3481
3604
  }
3482
- logger6.success("simulateGaze");
3605
+ logger5.success("simulateGaze");
3483
3606
  },
3484
3607
  /**
3485
3608
  * 人类化输入 - 带节奏变化(快-慢-停顿-偶尔加速)
@@ -3492,7 +3615,7 @@ var Humanize = {
3492
3615
  * @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
3493
3616
  */
3494
3617
  async humanType(page, selector, text, options = {}) {
3495
- logger6.start("humanType", `selector=${selector}, textLen=${text.length}`);
3618
+ logger5.start("humanType", `selector=${selector}, textLen=${text.length}`);
3496
3619
  const {
3497
3620
  baseDelay = 180,
3498
3621
  pauseProbability = 0.08,
@@ -3516,13 +3639,13 @@ var Humanize = {
3516
3639
  await (0, import_delay2.default)(charDelay);
3517
3640
  if (Math.random() < pauseProbability && i < text.length - 1) {
3518
3641
  const pauseTime = this.jitterMs(pauseBase, 0.5);
3519
- logger6.debug(`\u505C\u987F ${pauseTime}ms...`);
3642
+ logger5.debug(`\u505C\u987F ${pauseTime}ms...`);
3520
3643
  await (0, import_delay2.default)(pauseTime);
3521
3644
  }
3522
3645
  }
3523
- logger6.success("humanType");
3646
+ logger5.success("humanType");
3524
3647
  } catch (error) {
3525
- logger6.fail("humanType", error);
3648
+ logger5.fail("humanType", error);
3526
3649
  throw error;
3527
3650
  }
3528
3651
  },
@@ -3546,7 +3669,7 @@ var Humanize = {
3546
3669
  keyboardOptions = {}
3547
3670
  } = pressOptions || {};
3548
3671
  const targetDesc = hasTarget ? typeof targetOrKey === "string" ? targetOrKey : "ElementHandle" : "current focus";
3549
- logger6.start("humanPress", `key=${key}, target=${targetDesc}`);
3672
+ logger5.start("humanPress", `key=${key}, target=${targetDesc}`);
3550
3673
  try {
3551
3674
  if (hasTarget) {
3552
3675
  await this.humanClick(page, targetOrKey, { reactionDelay: focusDelay, scrollIfNeeded, throwOnMissing });
@@ -3556,10 +3679,10 @@ var Humanize = {
3556
3679
  ...keyboardOptions,
3557
3680
  delay: this.jitterMs(holdDelay, 0.5)
3558
3681
  });
3559
- logger6.success("humanPress");
3682
+ logger5.success("humanPress");
3560
3683
  return true;
3561
3684
  } catch (error) {
3562
- logger6.fail("humanPress", error);
3685
+ logger5.fail("humanPress", error);
3563
3686
  throw error;
3564
3687
  }
3565
3688
  },
@@ -3569,22 +3692,22 @@ var Humanize = {
3569
3692
  * @param {string} selector - 输入框选择器
3570
3693
  */
3571
3694
  async humanClear(page, selector) {
3572
- logger6.start("humanClear", `selector=${selector}`);
3695
+ logger5.start("humanClear", `selector=${selector}`);
3573
3696
  try {
3574
3697
  const locator = page.locator(selector);
3575
3698
  await locator.click();
3576
3699
  await (0, import_delay2.default)(this.jitterMs(200, 0.4));
3577
3700
  const currentValue = await locator.inputValue();
3578
3701
  if (!currentValue || currentValue.length === 0) {
3579
- logger6.success("humanClear", "already empty");
3702
+ logger5.success("humanClear", "already empty");
3580
3703
  return;
3581
3704
  }
3582
3705
  await page.keyboard.press("Meta+A");
3583
3706
  await (0, import_delay2.default)(this.jitterMs(100, 0.4));
3584
3707
  await page.keyboard.press("Backspace");
3585
- logger6.success("humanClear");
3708
+ logger5.success("humanClear");
3586
3709
  } catch (error) {
3587
- logger6.fail("humanClear", error);
3710
+ logger5.fail("humanClear", error);
3588
3711
  throw error;
3589
3712
  }
3590
3713
  },
@@ -3596,7 +3719,7 @@ var Humanize = {
3596
3719
  async warmUpBrowsing(page, baseDuration = 3500) {
3597
3720
  const cursor = $GetCursor(page);
3598
3721
  const durationMs = this.jitterMs(baseDuration, 0.4);
3599
- logger6.start("warmUpBrowsing", `duration=${durationMs}ms`);
3722
+ logger5.start("warmUpBrowsing", `duration=${durationMs}ms`);
3600
3723
  const startTime = Date.now();
3601
3724
  const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
3602
3725
  try {
@@ -3615,9 +3738,9 @@ var Humanize = {
3615
3738
  await (0, import_delay2.default)(this.jitterMs(800, 0.5));
3616
3739
  }
3617
3740
  }
3618
- logger6.success("warmUpBrowsing");
3741
+ logger5.success("warmUpBrowsing");
3619
3742
  } catch (error) {
3620
- logger6.fail("warmUpBrowsing", error);
3743
+ logger5.fail("warmUpBrowsing", error);
3621
3744
  throw error;
3622
3745
  }
3623
3746
  },
@@ -3631,7 +3754,7 @@ var Humanize = {
3631
3754
  async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
3632
3755
  const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
3633
3756
  const actualDistance = this.jitterMs(distance, 0.15);
3634
- logger6.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
3757
+ logger5.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
3635
3758
  const sign = direction === "down" ? 1 : -1;
3636
3759
  const stepDistance = actualDistance / steps;
3637
3760
  try {
@@ -3643,9 +3766,9 @@ var Humanize = {
3643
3766
  const baseDelay = 60 + i * 25;
3644
3767
  await (0, import_delay2.default)(this.jitterMs(baseDelay, 0.3));
3645
3768
  }
3646
- logger6.success("naturalScroll");
3769
+ logger5.success("naturalScroll");
3647
3770
  } catch (error) {
3648
- logger6.fail("naturalScroll", error);
3771
+ logger5.fail("naturalScroll", error);
3649
3772
  throw error;
3650
3773
  }
3651
3774
  }
@@ -3674,7 +3797,7 @@ var resolveElement = async (page, target, { throwOnMissing = true } = {}) => {
3674
3797
  var waitJitter = (base, jitterPercent = 0.3) => (0, import_delay3.default)(jitterMs(base, jitterPercent));
3675
3798
 
3676
3799
  // src/internals/humanize/mobile.js
3677
- var logger7 = createInternalLogger("Humanize.Mobile");
3800
+ var logger6 = createInternalLogger("Humanize.Mobile");
3678
3801
  var initializedPages = /* @__PURE__ */ new WeakSet();
3679
3802
  var DEFAULT_TAP_TIMEOUT_MS = 2500;
3680
3803
  var DEFAULT_MOUSE_TAP_FALLBACK_TIMEOUT_MS = 1200;
@@ -4044,7 +4167,7 @@ var restoreWindowFromSnapshot = async (page, before, after) => {
4044
4167
  return;
4045
4168
  }
4046
4169
  await page.evaluate(
4047
- (state) => window.scrollTo(state.x, state.y),
4170
+ (state2) => window.scrollTo(state2.x, state2.y),
4048
4171
  { x: Number(before.scrollX || 0), y: Number(before.scrollY || 0) }
4049
4172
  ).catch(() => {
4050
4173
  });
@@ -4131,7 +4254,7 @@ var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
4131
4254
  }
4132
4255
  return true;
4133
4256
  } catch (error) {
4134
- logger7.debug(`touch swipe fallback: ${error?.message || error}`);
4257
+ logger6.debug(`touch swipe fallback: ${error?.message || error}`);
4135
4258
  try {
4136
4259
  await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
4137
4260
  await waitJitter(120, 0.35);
@@ -4165,7 +4288,7 @@ var tapPoint = async (page, point, options = {}) => {
4165
4288
  );
4166
4289
  return { method: "touchscreen" };
4167
4290
  } catch (error) {
4168
- logger7.warn(`tapPoint | touchscreen.tap \u5931\u8D25\u6216\u8D85\u65F6\uFF0C\u5C1D\u8BD5\u9F20\u6807\u515C\u5E95: ${error?.message || error}`);
4291
+ logger6.warn(`tapPoint | touchscreen.tap \u5931\u8D25\u6216\u8D85\u65F6\uFF0C\u5C1D\u8BD5\u9F20\u6807\u515C\u5E95: ${error?.message || error}`);
4169
4292
  if (!allowMouseFallback) throw error;
4170
4293
  }
4171
4294
  }
@@ -4181,10 +4304,10 @@ var MobileHumanize = {
4181
4304
  async initializeCursor(page) {
4182
4305
  if (initializedPages.has(page)) return;
4183
4306
  initializedPages.add(page);
4184
- logger7.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
4307
+ logger6.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
4185
4308
  },
4186
4309
  async humanMove(page, target) {
4187
- logger7.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
4310
+ logger6.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
4188
4311
  if (typeof target === "string" || target && typeof target.boundingBox === "function") {
4189
4312
  const element = await resolveElement(page, target, { throwOnMissing: false });
4190
4313
  if (!element) {
@@ -4203,10 +4326,10 @@ var MobileHumanize = {
4203
4326
  throwOnMissing = false
4204
4327
  } = options;
4205
4328
  const targetDesc = describeTarget(target);
4206
- logger7.start("humanScroll", `target=${targetDesc}`);
4329
+ logger6.start("humanScroll", `target=${targetDesc}`);
4207
4330
  const element = await resolveElement(page, target, { throwOnMissing });
4208
4331
  if (!element) {
4209
- logger7.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${targetDesc}`);
4332
+ logger6.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${targetDesc}`);
4210
4333
  return { element: null, didScroll: false, restore: null };
4211
4334
  }
4212
4335
  const startTime = Date.now();
@@ -4215,42 +4338,42 @@ var MobileHumanize = {
4215
4338
  const status = await checkElementVisibility(element);
4216
4339
  if (status.code === "VISIBLE") {
4217
4340
  if (status.isFixed) {
4218
- logger7.info("humanScroll | fixed/sticky \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
4341
+ logger6.info("humanScroll | fixed/sticky \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
4219
4342
  } else {
4220
- logger7.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
4343
+ logger6.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
4221
4344
  }
4222
- logger7.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
4345
+ logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
4223
4346
  return { element, didScroll, restore: null };
4224
4347
  }
4225
4348
  if (status.code === "ZERO_DIMENSIONS" || status.code === "NOT_INTERACTABLE") {
4226
- logger7.warn(`humanScroll | \u5143\u7D20\u4E0D\u53EF\u6EDA\u52A8\u81F3\u53EF\u70B9\u51FB\u72B6\u6001: ${status.reason || status.code}`);
4349
+ logger6.warn(`humanScroll | \u5143\u7D20\u4E0D\u53EF\u6EDA\u52A8\u81F3\u53EF\u70B9\u51FB\u72B6\u6001: ${status.reason || status.code}`);
4227
4350
  return { element, didScroll, restore: null };
4228
4351
  }
4229
4352
  const scrollRect = await getScrollableRect(element);
4230
4353
  if (!scrollRect && status.isFixed && status.code === "OUT_OF_VIEWPORT") {
4231
- 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"})`);
4354
+ 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"})`);
4232
4355
  return { element, didScroll, restore: null, unscrollable: true };
4233
4356
  }
4234
4357
  if (!scrollRect && status.isFixed && status.code === "OBSTRUCTED") {
4235
- logger7.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
4358
+ logger6.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
4236
4359
  return { element, didScroll, restore: null, unscrollable: true };
4237
4360
  }
4238
4361
  if (scrollRect && status.code === "OBSTRUCTED" && status.obstruction?.isFixed) {
4239
4362
  const moved = await scrollAwayFromObstruction(element, status);
4240
4363
  if (moved.moved) {
4241
- logger7.debug(`humanScroll | sticky/fixed \u906E\u6321\u8865\u507F\u6EDA\u52A8 top=${Math.round(moved.scrollTop || 0)}`);
4364
+ logger6.debug(`humanScroll | sticky/fixed \u906E\u6321\u8865\u507F\u6EDA\u52A8 top=${Math.round(moved.scrollTop || 0)}`);
4242
4365
  await waitJitter(90, 0.3);
4243
4366
  didScroll = true;
4244
4367
  continue;
4245
4368
  }
4246
4369
  }
4247
4370
  if (Date.now() - startTime > maxDurationMs) {
4248
- logger7.warn(`humanScroll | mobile timeout (${maxDurationMs}ms, status=${status.code}, direction=${status.direction || "unknown"}, fixed=${Boolean(status.isFixed)})`);
4371
+ logger6.warn(`humanScroll | mobile timeout (${maxDurationMs}ms, status=${status.code}, direction=${status.direction || "unknown"}, fixed=${Boolean(status.isFixed)})`);
4249
4372
  return { element, didScroll, restore: null };
4250
4373
  }
4251
4374
  const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
4252
4375
  const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;
4253
- logger7.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason || status.code} ${status.direction ? `(${status.direction})` : ""}`);
4376
+ logger6.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason || status.code} ${status.direction ? `(${status.direction})` : ""}`);
4254
4377
  const distance = stepMin + Math.random() * Math.max(1, stepMax - stepMin);
4255
4378
  let deltaY = status.direction === "up" ? -distance : distance;
4256
4379
  if (status.code === "OBSTRUCTED") {
@@ -4290,8 +4413,8 @@ var MobileHumanize = {
4290
4413
  if (scrollRect && beforeWindowState) {
4291
4414
  const afterWindowState = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY }));
4292
4415
  if (Math.abs(afterWindowState.x - beforeWindowState.x) > 2 || Math.abs(afterWindowState.y - beforeWindowState.y) > 2) {
4293
- await page.evaluate((state) => window.scrollTo(state.x, state.y), beforeWindowState);
4294
- logger7.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
4416
+ await page.evaluate((state2) => window.scrollTo(state2.x, state2.y), beforeWindowState);
4417
+ logger6.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
4295
4418
  }
4296
4419
  }
4297
4420
  let afterElementSnapshot = null;
@@ -4305,7 +4428,7 @@ var MobileHumanize = {
4305
4428
  const afterSnapshot = await readAfterElementSnapshot();
4306
4429
  if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
4307
4430
  await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
4308
- 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"})`);
4431
+ 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"})`);
4309
4432
  return { element, didScroll, restore: null, unscrollable: true };
4310
4433
  }
4311
4434
  }
@@ -4337,12 +4460,12 @@ var MobileHumanize = {
4337
4460
  const moved = beforeState.kind !== afterState.kind || Math.abs(topDelta) > 2 || Math.abs(leftDelta) > 2;
4338
4461
  if (!moved) {
4339
4462
  const fallback = await scrollScrollableAncestor(element, deltaY);
4340
- 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)}`);
4463
+ 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)}`);
4341
4464
  } 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)) {
4342
4465
  const residualDelta = expectedDelta - topDelta;
4343
4466
  if (Math.sign(residualDelta) === Math.sign(expectedDelta) && Math.abs(residualDelta) > 24) {
4344
4467
  const fallback = await scrollScrollableAncestor(element, residualDelta);
4345
- 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)}`);
4468
+ 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)}`);
4346
4469
  }
4347
4470
  }
4348
4471
  }
@@ -4350,7 +4473,7 @@ var MobileHumanize = {
4350
4473
  const afterSnapshot = await getElementViewportSnapshot(element).catch(() => null);
4351
4474
  if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
4352
4475
  await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
4353
- 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"})`);
4476
+ 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"})`);
4354
4477
  return { element, didScroll, restore: null, unscrollable: true };
4355
4478
  }
4356
4479
  }
@@ -4361,14 +4484,14 @@ var MobileHumanize = {
4361
4484
  await waitJitter(80, 0.3);
4362
4485
  const finalStatus = await checkElementVisibility(element);
4363
4486
  if (finalStatus.code === "VISIBLE") {
4364
- logger7.info("humanScroll | \u539F\u751F scrollIntoViewIfNeeded \u515C\u5E95\u6210\u529F");
4365
- logger7.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
4487
+ logger6.info("humanScroll | \u539F\u751F scrollIntoViewIfNeeded \u515C\u5E95\u6210\u529F");
4488
+ logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
4366
4489
  return { element, didScroll: true, restore: null };
4367
4490
  }
4368
4491
  } catch (fallbackError) {
4369
- logger7.debug(`humanScroll | native fallback failed: ${fallbackError?.message || fallbackError}`);
4492
+ logger6.debug(`humanScroll | native fallback failed: ${fallbackError?.message || fallbackError}`);
4370
4493
  }
4371
- logger7.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
4494
+ logger6.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
4372
4495
  return { element, didScroll, restore: null };
4373
4496
  },
4374
4497
  async humanClick(page, target, options = {}) {
@@ -4383,7 +4506,7 @@ var MobileHumanize = {
4383
4506
  fallbackDomClickOnTapError = true
4384
4507
  } = options;
4385
4508
  const targetDesc = describeTarget(target);
4386
- logger7.start("humanClick", `target=${targetDesc}`);
4509
+ logger6.start("humanClick", `target=${targetDesc}`);
4387
4510
  try {
4388
4511
  if (target == null) {
4389
4512
  const viewport = resolveViewport(page);
@@ -4395,12 +4518,12 @@ var MobileHumanize = {
4395
4518
  timeoutMs: tapTimeoutMs,
4396
4519
  mouseFallbackTimeoutMs
4397
4520
  });
4398
- logger7.success("humanClick", "Tapped current position");
4521
+ logger6.success("humanClick", "Tapped current position");
4399
4522
  return true;
4400
4523
  }
4401
4524
  const element = await resolveElement(page, target, { throwOnMissing });
4402
4525
  if (!element) {
4403
- logger7.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
4526
+ logger6.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
4404
4527
  return false;
4405
4528
  }
4406
4529
  const scrollResult = scrollIfNeeded ? await MobileHumanize.humanScroll(page, element, { throwOnMissing }) : null;
@@ -4424,19 +4547,19 @@ var MobileHumanize = {
4424
4547
  ).catch(() => null);
4425
4548
  }
4426
4549
  if (fallback?.activated) {
4427
- logger7.warn(`humanClick: \u4E0D\u53EF\u6EDA\u52A8\u76EE\u6807\u4E0D\u53EF\u7269\u7406\u70B9\u51FB\uFF0C\u5DF2\u7528 ${fallback.method} \u6FC0\u6D3B`);
4550
+ logger6.warn(`humanClick: \u4E0D\u53EF\u6EDA\u52A8\u76EE\u6807\u4E0D\u53EF\u7269\u7406\u70B9\u51FB\uFF0C\u5DF2\u7528 ${fallback.method} \u6FC0\u6D3B`);
4428
4551
  return true;
4429
4552
  }
4430
4553
  }
4431
4554
  const message = `\u5143\u7D20\u4E0D\u53EF\u70B9\u51FB: ${status.reason || status.code}`;
4432
4555
  if (throwOnMissing) throw new Error(message);
4433
- logger7.warn(`humanClick: ${message}\uFF0C\u8DF3\u8FC7\u70B9\u51FB`);
4556
+ logger6.warn(`humanClick: ${message}\uFF0C\u8DF3\u8FC7\u70B9\u51FB`);
4434
4557
  return false;
4435
4558
  }
4436
4559
  const box = await element.boundingBox();
4437
4560
  if (!box) {
4438
4561
  if (throwOnMissing) throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
4439
- logger7.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
4562
+ logger6.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
4440
4563
  return false;
4441
4564
  }
4442
4565
  await waitJitter(reactionDelay, 0.45);
@@ -4457,13 +4580,13 @@ var MobileHumanize = {
4457
4580
  "activation fallback"
4458
4581
  ).catch(() => null);
4459
4582
  if (!fallback?.activated) throw tapError;
4460
- logger7.warn(`humanClick: tap \u5931\u8D25\u540E\u5DF2\u7528 ${fallback.method} \u515C\u5E95: ${tapError?.message || tapError}`);
4583
+ logger6.warn(`humanClick: tap \u5931\u8D25\u540E\u5DF2\u7528 ${fallback.method} \u515C\u5E95: ${tapError?.message || tapError}`);
4461
4584
  }
4462
4585
  await waitJitter(120, 0.35);
4463
- logger7.success("humanClick");
4586
+ logger6.success("humanClick");
4464
4587
  return true;
4465
4588
  } catch (error) {
4466
- logger7.fail("humanClick", error);
4589
+ logger6.fail("humanClick", error);
4467
4590
  throw error;
4468
4591
  }
4469
4592
  },
@@ -4516,7 +4639,7 @@ var MobileHumanize = {
4516
4639
  keyboardOptions = {}
4517
4640
  } = pressOptions || {};
4518
4641
  const targetDesc = hasTarget ? describeTarget(targetOrKey) : "current focus";
4519
- logger7.start("humanPress", `key=${key}, target=${targetDesc}`);
4642
+ logger6.start("humanPress", `key=${key}, target=${targetDesc}`);
4520
4643
  try {
4521
4644
  if (hasTarget) {
4522
4645
  await MobileHumanize.humanClick(page, targetOrKey, {
@@ -4530,10 +4653,10 @@ var MobileHumanize = {
4530
4653
  ...keyboardOptions,
4531
4654
  delay: jitterMs(holdDelay, 0.5)
4532
4655
  });
4533
- logger7.success("humanPress");
4656
+ logger6.success("humanPress");
4534
4657
  return true;
4535
4658
  } catch (error) {
4536
- logger7.fail("humanPress", error);
4659
+ logger6.fail("humanPress", error);
4537
4660
  throw error;
4538
4661
  }
4539
4662
  },
@@ -4600,65 +4723,96 @@ var MobileHumanize = {
4600
4723
  }
4601
4724
  };
4602
4725
 
4603
- // src/humanize.js
4726
+ // src/internals/humanize/default.js
4604
4727
  var resolveDeviceFromPage2 = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
4605
4728
  var resolveDelegate = (page) => {
4606
4729
  return resolveDeviceFromPage2(page) === Device.Mobile ? MobileHumanize : Humanize;
4607
4730
  };
4608
- var callDelegate = (method, page, args) => {
4609
- const delegate = resolveDelegate(page);
4610
- return delegate[method](page, ...args);
4731
+ var DefaultHumanizeDevice = withPageReflect(
4732
+ "DefaultHumanize",
4733
+ resolveDelegate,
4734
+ [Humanize, MobileHumanize]
4735
+ );
4736
+
4737
+ // src/internals/humanize/cloak.js
4738
+ var FORCE_CLICK = Object.freeze({
4739
+ forceClick: true,
4740
+ clickOptions: { force: true }
4741
+ });
4742
+ var pointOrNull = async (target) => {
4743
+ if (!target || typeof target.boundingBox !== "function") return null;
4744
+ const box = await target.boundingBox().catch(() => null);
4745
+ return box ? { x: box.x + box.width / 2, y: box.y + box.height / 2 } : null;
4611
4746
  };
4612
- var Humanize2 = {
4613
- jitterMs(base, jitterPercent = 0.3) {
4614
- return Humanize.jitterMs(base, jitterPercent);
4615
- },
4616
- initializeCursor(page) {
4617
- return callDelegate("initializeCursor", page, []);
4747
+ var CloakHumanizeInput = {
4748
+ async initializeCursor(page) {
4749
+ return Boolean(page);
4618
4750
  },
4619
- humanMove(page, target) {
4620
- return callDelegate("humanMove", page, [target]);
4751
+ async humanMove(page, target) {
4752
+ const point = target?.x != null && target?.y != null ? target : await pointOrNull(typeof target === "string" ? page.locator(target).first() : target);
4753
+ return point ? await DeviceInput.move(page, point, { forceMouse: true }) : false;
4621
4754
  },
4622
- humanScroll(page, target, options = {}) {
4623
- return callDelegate("humanScroll", page, [target, options]);
4755
+ async humanScroll(page, target) {
4756
+ const element = typeof target === "string" ? page.locator(target).first() : target;
4757
+ if (!element) return { element: null, didScroll: false, restore: null };
4758
+ await element.scrollIntoViewIfNeeded?.();
4759
+ return { element, didScroll: true, restore: null };
4624
4760
  },
4625
- humanClick(page, target, options = {}) {
4626
- return callDelegate("humanClick", page, [target, options]);
4761
+ async humanClick(page, target) {
4762
+ return await DeviceInput.click(page, target, FORCE_CLICK);
4627
4763
  },
4628
- randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
4629
- if (pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function") {
4630
- const delegate = resolveDelegate(pageOrBaseMs);
4631
- return delegate.randomSleep(maybeBaseMs, maybeJitterPercent);
4632
- }
4633
- return Humanize.randomSleep(pageOrBaseMs, maybeBaseMs);
4764
+ async humanType(page, selector, text) {
4765
+ await DeviceInput.click(page, selector, FORCE_CLICK);
4766
+ return await DeviceInput.keyboardType(page, text);
4634
4767
  },
4635
- simulateGaze(page, baseDurationMs = 2500) {
4636
- return callDelegate("simulateGaze", page, [baseDurationMs]);
4768
+ async humanPress(page, targetOrKey, maybeKey) {
4769
+ return await DeviceInput.press(page, targetOrKey, maybeKey, {
4770
+ clickOptions: FORCE_CLICK,
4771
+ keyboardOptions: {}
4772
+ });
4637
4773
  },
4638
- humanType(page, selector, text, options = {}) {
4639
- return callDelegate("humanType", page, [selector, text, options]);
4774
+ async humanClear(page, selector) {
4775
+ return await DeviceInput.fill(page, selector, "", { force: true });
4640
4776
  },
4641
- humanPress(page, targetOrKey, maybeKey, options = {}) {
4642
- if (typeof maybeKey === "string") {
4643
- return callDelegate("humanPress", page, [targetOrKey, maybeKey, options]);
4644
- }
4645
- return callDelegate("humanPress", page, [targetOrKey, maybeKey || options]);
4777
+ async simulateGaze(page) {
4778
+ return await DeviceInput.move(page, { x: 0, y: 0 }, { forceMouse: true });
4646
4779
  },
4647
- humanClear(page, selector) {
4648
- return callDelegate("humanClear", page, [selector]);
4780
+ async warmUpBrowsing(page) {
4781
+ return await this.simulateGaze(page);
4649
4782
  },
4650
- warmUpBrowsing(page, baseDuration = 3500) {
4651
- return callDelegate("warmUpBrowsing", page, [baseDuration]);
4783
+ async naturalScroll(page, direction = "down", distance = 300) {
4784
+ const sign = direction === "down" ? 1 : -1;
4785
+ await page.mouse.wheel(0, Number(distance || 0) * sign);
4786
+ }
4787
+ };
4788
+
4789
+ // src/internals/humanize/index.js
4790
+ var HumanizeCommon = {
4791
+ jitterMs(base, jitterPercent = 0.3) {
4792
+ return jitterMs(base, jitterPercent);
4652
4793
  },
4653
- naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
4654
- return callDelegate("naturalScroll", page, [direction, distance, baseSteps]);
4794
+ async randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
4795
+ const hasPage = pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function";
4796
+ const baseMs = hasPage ? maybeBaseMs : pageOrBaseMs;
4797
+ const jitterPercent = hasPage ? maybeJitterPercent : maybeBaseMs;
4798
+ await (0, import_delay4.default)(jitterMs(baseMs, jitterPercent ?? 0.3));
4655
4799
  }
4656
4800
  };
4801
+ var DefaultHumanize = Object.assign({}, DefaultHumanizeDevice, HumanizeCommon);
4802
+ var CloakHumanize = Object.assign({}, CloakHumanizeInput, HumanizeCommon);
4657
4803
 
4658
- // src/launch.js
4804
+ // src/humanize.js
4805
+ var humanizeStrategies = {
4806
+ [Mode.Default]: DefaultHumanize,
4807
+ [Mode.Cloak]: CloakHumanize
4808
+ };
4809
+ var Humanize2 = withModeReflect("Humanize", humanizeStrategies);
4810
+
4811
+ // src/internals/launch/default.js
4659
4812
  var import_node_child_process = require("node:child_process");
4660
4813
  var import_fingerprint_generator = require("fingerprint-generator");
4661
4814
  var import_fingerprint_injector = require("fingerprint-injector");
4815
+ var import_playwright2 = require("playwright");
4662
4816
 
4663
4817
  // src/proxy-bypass.js
4664
4818
  var import_picomatch = __toESM(require("picomatch"), 1);
@@ -4740,9 +4894,107 @@ var ByPass = {
4740
4894
  resolveRouteByProxy
4741
4895
  };
4742
4896
 
4743
- // src/launch.js
4897
+ // src/internals/launch/traffic.js
4898
+ var logger7 = createInternalLogger("Launch");
4899
+ var normalizeObject = (value) => {
4900
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
4901
+ return {};
4902
+ }
4903
+ return value;
4904
+ };
4905
+ var parseProxyConfiguration = (proxyConfiguration = {}) => {
4906
+ const config = normalizeObject(proxyConfiguration);
4907
+ const proxyUrl = String(config.proxy_url || "").trim();
4908
+ const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
4909
+ const byPassDomains = enableProxy && proxyUrl ? ByPass.normalizeByPassDomains(config.by_pass_domains) : [];
4910
+ return {
4911
+ byPassDomains,
4912
+ enableProxy,
4913
+ proxyUrl
4914
+ };
4915
+ };
4916
+ var resolveLaunchTraffic = ({
4917
+ proxyConfiguration = {},
4918
+ debugMode = false,
4919
+ useMeter = true
4920
+ } = {}) => {
4921
+ const { byPassDomains, enableProxy, proxyUrl } = parseProxyConfiguration(proxyConfiguration);
4922
+ const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
4923
+ const proxyMeter = useMeter && enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
4924
+ const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;
4925
+ if (launchProxy && byPassDomains.length > 0) {
4926
+ launchProxy.bypass = byPassDomains.join(",");
4927
+ }
4928
+ return {
4929
+ byPassDomains,
4930
+ byPassRules,
4931
+ enableProxy,
4932
+ proxyUrl,
4933
+ launchProxy
4934
+ };
4935
+ };
4936
+ var logLaunchTraffic = ({
4937
+ byPassDomains = [],
4938
+ debugMode = false,
4939
+ enabled = false,
4940
+ enableProxy = false,
4941
+ explicitProxy = false,
4942
+ launchProxy = null,
4943
+ proxyUrl = ""
4944
+ } = {}) => {
4945
+ if (!enabled) return;
4946
+ if (explicitProxy) {
4947
+ logger7.info("[\u4EE3\u7406\u5DF2\u542F\u7528] \u4F7F\u7528\u663E\u5F0F proxy \u914D\u7F6E\uFF0C\u8DF3\u8FC7 toolkit \u672C\u5730\u6D41\u91CF\u89C2\u6D4B");
4948
+ return;
4949
+ }
4950
+ if (launchProxy) {
4951
+ let upstreamLabel = "";
4952
+ try {
4953
+ const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
4954
+ upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
4955
+ } catch {
4956
+ }
4957
+ logger7.info(
4958
+ `[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${byPassDomains.join(",")}`
4959
+ );
4960
+ 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`);
4961
+ return;
4962
+ }
4963
+ if (enableProxy) {
4964
+ logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
4965
+ } else if (proxyUrl) {
4966
+ logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
4967
+ }
4968
+ 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`);
4969
+ };
4970
+ var createLaunchTrafficHook = ({
4971
+ byPassDomains = [],
4972
+ byPassRules = [],
4973
+ enabled = false,
4974
+ launchProxy = null
4975
+ } = {}) => {
4976
+ const patchedPages = /* @__PURE__ */ new WeakSet();
4977
+ return (page) => {
4978
+ if (!page || typeof page.on !== "function" || patchedPages.has(page)) {
4979
+ return;
4980
+ }
4981
+ patchedPages.add(page);
4982
+ page.on("request", (req) => {
4983
+ const requestUrl = req.url();
4984
+ const resourceType = req.resourceType();
4985
+ const matched = byPassDomains.length > 0 ? ByPass.findMatchedByPassRule(byPassRules, requestUrl) : null;
4986
+ if (launchProxy) {
4987
+ ProxyMeterRuntime.recordProxyMeterResourceType(requestUrl, resourceType);
4988
+ }
4989
+ if (!enabled || byPassDomains.length === 0) return;
4990
+ if (!matched || !matched.rule) return;
4991
+ 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}`);
4992
+ });
4993
+ };
4994
+ };
4995
+
4996
+ // src/internals/launch/default.js
4744
4997
  var logger8 = createInternalLogger("Launch");
4745
- var REQUEST_HOOK_FLAG = Symbol("playwright-toolkit-request-hook");
4746
4998
  var injectedContexts = /* @__PURE__ */ new WeakSet();
4747
4999
  var browserMajorVersionCache = /* @__PURE__ */ new Map();
4748
5000
  var DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION = 1;
@@ -4754,16 +5006,6 @@ var DEFAULT_CRAWLER_BASE_OPTIONS = Object.freeze({
4754
5006
  navigationTimeoutSecs: 120
4755
5007
  });
4756
5008
  var fingerprintInjector = new import_fingerprint_injector.FingerprintInjector();
4757
- var resolveProxyLaunchOptions = (proxyConfiguration = {}) => {
4758
- const config = proxyConfiguration && typeof proxyConfiguration === "object" && !Array.isArray(proxyConfiguration) ? proxyConfiguration : {};
4759
- const proxyUrl = String(config.proxy_url || "").trim();
4760
- const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
4761
- if (!enableProxy || !proxyUrl) {
4762
- return { byPassDomains: [], enableProxy, proxyUrl };
4763
- }
4764
- const byPassDomains = ByPass.normalizeByPassDomains(config.by_pass_domains);
4765
- return { byPassDomains, enableProxy, proxyUrl };
4766
- };
4767
5009
  var parseChromeMajorVersion = (rawValue = "") => {
4768
5010
  const match = String(rawValue || "").match(/(?:Chrome|Chromium)(?:\/|\s+(?:for Testing\s+)?)(\d+)/i);
4769
5011
  return match ? Number(match[1] || 0) : 0;
@@ -4807,7 +5049,7 @@ var resolveCoreDevice = (core = {}) => {
4807
5049
  };
4808
5050
  var buildFingerprintGenerator = ({ locale, browserMajorVersion, device }) => {
4809
5051
  return new import_fingerprint_generator.FingerprintGenerator(
4810
- AntiCheat.getFingerprintGeneratorOptions({
5052
+ DefaultAntiCheat.getFingerprintGeneratorOptions({
4811
5053
  locale,
4812
5054
  browserMajorVersion,
4813
5055
  device
@@ -4851,7 +5093,7 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
4851
5093
  }
4852
5094
  let nextState = RuntimeEnv.rememberState(runtimeState);
4853
5095
  let browserProfileCore = RuntimeEnv.getBrowserProfileCore(nextState);
4854
- const timezoneId = String(browserProfileCore?.timezone_id || "").trim() || AntiCheat.getBaseConfig().timezoneId;
5096
+ const timezoneId = String(browserProfileCore?.timezone_id || "").trim() || DefaultAntiCheat.getBaseConfig().timezoneId;
4855
5097
  const locale = DEFAULT_LOCALE;
4856
5098
  const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);
4857
5099
  const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);
@@ -4930,7 +5172,7 @@ var applyFingerprintPageOptions = (pageOptions = {}, { fingerprintWithHeaders =
4930
5172
  pageOptions.timezoneId = timezoneId;
4931
5173
  }
4932
5174
  };
4933
- var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = null) => {
5175
+ var buildReplayBrowserPoolOptions = (browserProfileCore) => {
4934
5176
  const fingerprintWithHeaders = browserProfileCore?.fingerprint;
4935
5177
  const fingerprint = fingerprintWithHeaders?.fingerprint;
4936
5178
  if (!fingerprintWithHeaders || !fingerprint) {
@@ -4939,16 +5181,13 @@ var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = nul
4939
5181
  return {
4940
5182
  useFingerprints: false,
4941
5183
  prePageCreateHooks: [
4942
- async (pageId, browserController, pageOptions = {}) => {
5184
+ (_pageId, _browserController, pageOptions = {}) => {
4943
5185
  if (!pageOptions || typeof pageOptions !== "object") return;
4944
5186
  applyFingerprintPageOptions(pageOptions, {
4945
5187
  fingerprintWithHeaders,
4946
5188
  locale: browserProfileCore.locale,
4947
5189
  timezoneId: browserProfileCore.timezone_id
4948
5190
  });
4949
- if (modifyPageOptions) {
4950
- await modifyPageOptions(pageOptions, { pageId, browserController });
4951
- }
4952
5191
  }
4953
5192
  ],
4954
5193
  postPageCreateHooks: [
@@ -4963,7 +5202,7 @@ var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = nul
4963
5202
  ]
4964
5203
  };
4965
5204
  };
4966
- var Launch = {
5205
+ var DefaultLaunch = {
4967
5206
  getPlaywrightCrawlerOptions(options = {}) {
4968
5207
  const normalizedOptions = Array.isArray(options) ? { customArgs: options } : options || {};
4969
5208
  const {
@@ -4974,54 +5213,36 @@ var Launch = {
4974
5213
  debugMode = false,
4975
5214
  isRunningOnApify = false,
4976
5215
  launcher = null,
4977
- hooks = {},
4978
5216
  preNavigationHooks = [],
4979
5217
  postNavigationHooks = [],
4980
5218
  runtimeState = null
4981
5219
  } = normalizedOptions;
4982
5220
  const device = resolveRuntimeDevice(runtimeState);
4983
- const modifyPageOptions = typeof hooks?.modifyPageOptions === "function" ? hooks.modifyPageOptions : null;
4984
- const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);
4985
- const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
4986
- const proxyMeter = enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
4987
- const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;
4988
- if (launchProxy && byPassDomains.length > 0) {
4989
- launchProxy.bypass = byPassDomains.join(",");
4990
- }
4991
- const replayContext = buildReplayableBrowserProfile(runtimeState, launcher);
4992
- const replayBrowserPoolOptions = buildReplayBrowserPoolOptions(replayContext.browserProfileCore, modifyPageOptions);
5221
+ const effectiveLauncher = launcher || import_playwright2.chromium;
5222
+ const enableByPassLogger = Boolean(logOptions && logOptions.enable);
5223
+ const traffic = resolveLaunchTraffic({ proxyConfiguration, debugMode });
5224
+ const trafficHook = createLaunchTrafficHook({
5225
+ ...traffic,
5226
+ enabled: enableByPassLogger
5227
+ });
5228
+ const replayContext = buildReplayableBrowserProfile(runtimeState, effectiveLauncher);
5229
+ const replayBrowserPoolOptions = buildReplayBrowserPoolOptions(replayContext.browserProfileCore);
4993
5230
  const launchLocale = String(replayContext.browserProfileCore?.locale || DEFAULT_LOCALE).trim() || DEFAULT_LOCALE;
4994
5231
  const launchOptions = {
4995
5232
  args: [
4996
- ...AntiCheat.getLaunchArgs({ locale: launchLocale }),
5233
+ ...DefaultAntiCheat.getLaunchArgs({ locale: launchLocale }),
4997
5234
  ...customArgs
4998
5235
  ],
4999
5236
  ignoreDefaultArgs: ["--enable-automation"]
5000
5237
  };
5001
- if (launchProxy) {
5002
- launchOptions.proxy = launchProxy;
5003
- }
5004
- const enableByPassLogger = Boolean(logOptions && logOptions.enable);
5005
- if (enableByPassLogger && launchProxy) {
5006
- let upstreamLabel = "";
5007
- try {
5008
- const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
5009
- upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
5010
- } catch {
5011
- }
5012
- logger8.info(
5013
- `[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
5014
- );
5015
- 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`);
5016
- } else if (enableByPassLogger && enableProxy && !launchProxy) {
5017
- logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
5018
- 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`);
5019
- } else if (enableByPassLogger && !enableProxy && proxyUrl) {
5020
- logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
5021
- 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`);
5022
- } else if (enableByPassLogger) {
5023
- 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`);
5238
+ if (traffic.launchProxy) {
5239
+ launchOptions.proxy = traffic.launchProxy;
5024
5240
  }
5241
+ logLaunchTraffic({
5242
+ ...traffic,
5243
+ debugMode,
5244
+ enabled: enableByPassLogger
5245
+ });
5025
5246
  const onPageCreated = (page) => {
5026
5247
  const recommendedGotoOptions = {
5027
5248
  waitUntil: "commit"
@@ -5029,31 +5250,14 @@ var Launch = {
5029
5250
  if (!page || typeof page.on !== "function") {
5030
5251
  return recommendedGotoOptions;
5031
5252
  }
5032
- if (page[REQUEST_HOOK_FLAG]) {
5033
- return recommendedGotoOptions;
5034
- }
5035
- page[REQUEST_HOOK_FLAG] = true;
5036
- const requestHandler = (req) => {
5037
- const requestUrl = req.url();
5038
- const resourceType = req.resourceType();
5039
- const matched = byPassDomains.length > 0 ? ByPass.findMatchedByPassRule(byPassRules, requestUrl) : null;
5040
- if (launchProxy) {
5041
- ProxyMeterRuntime.recordProxyMeterResourceType(requestUrl, resourceType);
5042
- }
5043
- if (!enableByPassLogger || byPassDomains.length === 0) return;
5044
- if (!matched || !matched.rule) return;
5045
- 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}`);
5046
- };
5047
- page.on("request", requestHandler);
5253
+ trafficHook(page);
5048
5254
  return recommendedGotoOptions;
5049
5255
  };
5050
5256
  const launchContext = {
5051
5257
  useIncognitoPages: true,
5052
- launchOptions
5258
+ launchOptions,
5259
+ launcher: effectiveLauncher
5053
5260
  };
5054
- if (launcher) {
5055
- launchContext.launcher = launcher;
5056
- }
5057
5261
  const crawlerBaseOptions = {
5058
5262
  ...DEFAULT_CRAWLER_BASE_OPTIONS,
5059
5263
  headless: !runInHeadfulMode || isRunningOnApify,
@@ -5061,23 +5265,20 @@ var Launch = {
5061
5265
  browserPoolOptions: replayBrowserPoolOptions || {
5062
5266
  useFingerprints: true,
5063
5267
  fingerprintOptions: {
5064
- fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions({
5268
+ fingerprintGeneratorOptions: DefaultAntiCheat.getFingerprintGeneratorOptions({
5065
5269
  locale: launchLocale,
5066
5270
  device
5067
5271
  })
5068
5272
  },
5069
5273
  prePageCreateHooks: [
5070
- async (pageId, browserController, pageOptions = {}) => {
5274
+ (_pageId, browserController, pageOptions = {}) => {
5071
5275
  const fingerprintWithHeaders = browserController?.launchContext?.fingerprint;
5072
- const timezoneId = AntiCheat.getBaseConfig().timezoneId;
5276
+ const timezoneId = DefaultAntiCheat.getBaseConfig().timezoneId;
5073
5277
  applyFingerprintPageOptions(pageOptions, {
5074
5278
  fingerprintWithHeaders,
5075
5279
  locale: launchLocale,
5076
5280
  timezoneId
5077
5281
  });
5078
- if (modifyPageOptions) {
5079
- await modifyPageOptions(pageOptions, { pageId, browserController });
5080
- }
5081
5282
  }
5082
5283
  ]
5083
5284
  },
@@ -5099,10 +5300,303 @@ var Launch = {
5099
5300
  }
5100
5301
  };
5101
5302
 
5303
+ // src/internals/launch/cloak.js
5304
+ var import_node_child_process2 = require("node:child_process");
5305
+ var import_node_util = require("node:util");
5306
+ var logger9 = createInternalLogger("Launch");
5307
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
5308
+ var DEFAULT_CLOAK_CRAWLER_BASE_OPTIONS = Object.freeze({
5309
+ maxConcurrency: 1,
5310
+ maxRequestRetries: 0,
5311
+ requestHandlerTimeoutSecs: 240,
5312
+ navigationTimeoutSecs: 120
5313
+ });
5314
+ var DEFAULT_CLOAK_HUMANIZE_OPTIONS = Object.freeze({
5315
+ humanize: true
5316
+ });
5317
+ var DEFAULT_CLOAK_GOTO_OPTIONS = Object.freeze({
5318
+ waitUntil: "commit"
5319
+ });
5320
+ var DEFAULT_CLOAK_FINGERPRINT_PLATFORM = "linux";
5321
+ var CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX = "--fingerprint-platform=";
5322
+ var SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS = /* @__PURE__ */ new Set(["linux", "macos", "windows"]);
5323
+ var cachedCloakModulePromise = null;
5324
+ var hasOwn = (target, key) => Object.prototype.hasOwnProperty.call(target, key);
5325
+ var loadCloakModule = async () => {
5326
+ if (!cachedCloakModulePromise) {
5327
+ cachedCloakModulePromise = import("cloakbrowser").catch((error) => {
5328
+ cachedCloakModulePromise = null;
5329
+ 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", {
5330
+ cause: error
5331
+ });
5332
+ });
5333
+ }
5334
+ return cachedCloakModulePromise;
5335
+ };
5336
+ var buildCloakLaunchOptions = async (options = {}) => {
5337
+ const { buildLaunchOptions } = await loadCloakModule();
5338
+ return await buildLaunchOptions(normalizeObject2(options));
5339
+ };
5340
+ var normalizeObject2 = (value) => {
5341
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
5342
+ return {};
5343
+ }
5344
+ return value;
5345
+ };
5346
+ var normalizeStringArray = (value) => {
5347
+ if (!Array.isArray(value)) {
5348
+ return [];
5349
+ }
5350
+ return value.map((item) => String(item || "").trim()).filter(Boolean);
5351
+ };
5352
+ var resolveCloakFingerprintPlatformArg = (fingerprintPlatform = "", args = []) => {
5353
+ const normalizedFingerprintPlatform = String(fingerprintPlatform || "").trim().toLowerCase();
5354
+ if (SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS.has(normalizedFingerprintPlatform)) {
5355
+ return `${CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX}${normalizedFingerprintPlatform}`;
5356
+ }
5357
+ const existingArg = normalizeStringArray(args).find((value) => value.startsWith(CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX));
5358
+ if (existingArg) {
5359
+ return existingArg;
5360
+ }
5361
+ return `${CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX}${DEFAULT_CLOAK_FINGERPRINT_PLATFORM}`;
5362
+ };
5363
+ var resolveCloakProxy = (proxyConfiguration = {}) => {
5364
+ const config = normalizeObject2(proxyConfiguration);
5365
+ const proxyUrl = String(config.proxy_url || "").trim();
5366
+ const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
5367
+ if (!enableProxy || !proxyUrl) {
5368
+ return null;
5369
+ }
5370
+ const byPassDomains = ByPass.normalizeByPassDomains(config.by_pass_domains);
5371
+ if (byPassDomains.length === 0) {
5372
+ return proxyUrl;
5373
+ }
5374
+ const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
5375
+ return {
5376
+ server: `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`,
5377
+ username: decodeURIComponent(parsedProxyUrl.username || ""),
5378
+ password: decodeURIComponent(parsedProxyUrl.password || ""),
5379
+ bypass: byPassDomains.join(",")
5380
+ };
5381
+ };
5382
+ var extractFingerprintArg = (launchOptions = {}) => {
5383
+ const args = Array.isArray(launchOptions?.args) ? launchOptions.args : [];
5384
+ return args.find((value) => String(value || "").startsWith("--fingerprint=")) || "";
5385
+ };
5386
+ var createStableGotoHook = (recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS) => {
5387
+ const normalizedRecommendedGotoOptions = normalizeObject2(recommendedGotoOptions);
5388
+ const fallbackGotoOptions = Object.keys(normalizedRecommendedGotoOptions).length > 0 ? normalizedRecommendedGotoOptions : DEFAULT_CLOAK_GOTO_OPTIONS;
5389
+ return async (_crawlingContext, gotoOptions = {}) => {
5390
+ for (const [key, value] of Object.entries(fallbackGotoOptions)) {
5391
+ if (gotoOptions[key] == null) {
5392
+ gotoOptions[key] = value;
5393
+ }
5394
+ }
5395
+ };
5396
+ };
5397
+ var attachCloakHumanizeHook = ({
5398
+ browserPoolOptions = {},
5399
+ activeBrowsers,
5400
+ patchedBrowsers,
5401
+ humanizeOptions = DEFAULT_CLOAK_HUMANIZE_OPTIONS
5402
+ } = {}) => {
5403
+ const normalizedBrowserPoolOptions = normalizeObject2(browserPoolOptions);
5404
+ const shouldHumanize = humanizeOptions !== false;
5405
+ const normalizedHumanizeOptions = shouldHumanize ? {
5406
+ ...DEFAULT_CLOAK_HUMANIZE_OPTIONS,
5407
+ ...normalizeObject2(humanizeOptions)
5408
+ } : null;
5409
+ return {
5410
+ ...normalizedBrowserPoolOptions,
5411
+ useFingerprints: false,
5412
+ postLaunchHooks: [
5413
+ ...Array.isArray(normalizedBrowserPoolOptions.postLaunchHooks) ? normalizedBrowserPoolOptions.postLaunchHooks : [],
5414
+ async (_pageId, browserController) => {
5415
+ const browser = browserController?.browser;
5416
+ if (!browser || typeof browser.contexts !== "function") {
5417
+ return;
5418
+ }
5419
+ activeBrowsers.add(browser);
5420
+ if (typeof browser.once === "function") {
5421
+ browser.once("disconnected", () => {
5422
+ activeBrowsers.delete(browser);
5423
+ });
5424
+ }
5425
+ if (!shouldHumanize || patchedBrowsers.has(browser)) {
5426
+ return;
5427
+ }
5428
+ const { humanizeBrowser } = await loadCloakModule();
5429
+ await humanizeBrowser(browser, normalizedHumanizeOptions);
5430
+ patchedBrowsers.add(browser);
5431
+ }
5432
+ ]
5433
+ };
5434
+ };
5435
+ var closeTrackedBrowsers = async (activeBrowsers) => {
5436
+ const browsers = Array.from(activeBrowsers || []);
5437
+ activeBrowsers?.clear?.();
5438
+ await Promise.allSettled(
5439
+ browsers.map(async (browser) => {
5440
+ if (!browser || typeof browser.isConnected !== "function" || !browser.isConnected()) {
5441
+ return;
5442
+ }
5443
+ await browser.close().catch(() => {
5444
+ });
5445
+ })
5446
+ );
5447
+ };
5448
+ var forceTerminateBrowsersByFingerprintArg = async (fingerprintArg) => {
5449
+ if (!fingerprintArg) {
5450
+ return;
5451
+ }
5452
+ await execFileAsync("pkill", ["-f", "--", fingerprintArg]).catch((error) => {
5453
+ if (error?.code === 1 || error?.code === "ENOENT") {
5454
+ return;
5455
+ }
5456
+ logger9.info(`\u5F3A\u5236\u5173\u95ED Cloak \u8FDB\u7A0B\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${error?.message || String(error)}`);
5457
+ });
5458
+ };
5459
+ var CloakLaunch = {
5460
+ resolveProxyConfiguration(proxyConfiguration = {}) {
5461
+ return resolveCloakProxy(proxyConfiguration);
5462
+ },
5463
+ extractFingerprintArg(launchOptions = {}) {
5464
+ return extractFingerprintArg(launchOptions);
5465
+ },
5466
+ createStableGotoHook(recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS) {
5467
+ return createStableGotoHook(recommendedGotoOptions);
5468
+ },
5469
+ async getPlaywrightCrawlerOptions(options = {}) {
5470
+ const runtime2 = await CloakLaunch.createPlaywrightCrawlerRuntime(options);
5471
+ return Object.defineProperties(runtime2.crawlerOptions, {
5472
+ cleanup: {
5473
+ enumerable: false,
5474
+ value: runtime2.cleanup
5475
+ },
5476
+ closeActiveBrowsers: {
5477
+ enumerable: false,
5478
+ value: runtime2.closeActiveBrowsers
5479
+ },
5480
+ forceTerminateActiveProcesses: {
5481
+ enumerable: false,
5482
+ value: runtime2.forceTerminateActiveProcesses
5483
+ }
5484
+ });
5485
+ },
5486
+ async buildLaunchOptions(options = {}) {
5487
+ return await buildCloakLaunchOptions(options);
5488
+ },
5489
+ async createPlaywrightCrawlerRuntime(options = {}) {
5490
+ const normalizedOptions = normalizeObject2(options);
5491
+ const {
5492
+ proxyConfiguration = {},
5493
+ log: logOptions = null,
5494
+ debugMode = false,
5495
+ runInHeadfulMode = false,
5496
+ isRunningOnApify = false,
5497
+ launcher = null,
5498
+ fingerprintPlatform = "",
5499
+ cloakOptions = {},
5500
+ humanizeOptions = DEFAULT_CLOAK_HUMANIZE_OPTIONS,
5501
+ crawlerBaseOptions = {},
5502
+ browserPoolOptions = {},
5503
+ launchContext = {},
5504
+ preNavigationHooks = [],
5505
+ postNavigationHooks = [],
5506
+ recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS
5507
+ } = normalizedOptions;
5508
+ const normalizedCloakOptions = normalizeObject2(cloakOptions);
5509
+ const activeBrowsers = /* @__PURE__ */ new Set();
5510
+ const patchedBrowsers = /* @__PURE__ */ new WeakSet();
5511
+ const defaultArgs = isRunningOnApify ? ["--no-sandbox", "--disable-setuid-sandbox"] : [];
5512
+ const fingerprintPlatformArg = resolveCloakFingerprintPlatformArg(fingerprintPlatform, normalizedCloakOptions.args);
5513
+ const extraArgs = normalizeStringArray(normalizedCloakOptions.args).filter((value) => !value.startsWith(CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX));
5514
+ const hasExplicitProxy = hasOwn(normalizedCloakOptions, "proxy");
5515
+ const proxyLaunchState = hasExplicitProxy ? resolveLaunchTraffic({ proxyConfiguration, debugMode, useMeter: false }) : resolveLaunchTraffic({ proxyConfiguration, debugMode });
5516
+ const proxy = hasExplicitProxy ? normalizedCloakOptions.proxy : proxyLaunchState.launchProxy;
5517
+ const headless = hasOwn(normalizedCloakOptions, "headless") ? normalizedCloakOptions.headless : !runInHeadfulMode || isRunningOnApify;
5518
+ const enableByPassLogger = Boolean(logOptions && logOptions.enable);
5519
+ const mergedCloakOptions = {
5520
+ ...normalizedCloakOptions,
5521
+ headless,
5522
+ proxy,
5523
+ args: [...defaultArgs, ...extraArgs, fingerprintPlatformArg]
5524
+ };
5525
+ const launchOptions = await buildCloakLaunchOptions(mergedCloakOptions);
5526
+ const fingerprintArg = extractFingerprintArg(launchOptions);
5527
+ const internalPreNavigationHook = createStableGotoHook(recommendedGotoOptions);
5528
+ const trafficHook = createLaunchTrafficHook({
5529
+ byPassDomains: proxyLaunchState.byPassDomains,
5530
+ byPassRules: proxyLaunchState.byPassRules,
5531
+ enabled: enableByPassLogger,
5532
+ launchProxy: proxyLaunchState.launchProxy
5533
+ });
5534
+ const normalizedPreNavigationHooks = Array.isArray(preNavigationHooks) ? preNavigationHooks : [];
5535
+ const normalizedPostNavigationHooks = Array.isArray(postNavigationHooks) ? postNavigationHooks : [];
5536
+ logLaunchTraffic({
5537
+ ...proxyLaunchState,
5538
+ debugMode,
5539
+ enabled: enableByPassLogger,
5540
+ explicitProxy: hasExplicitProxy
5541
+ });
5542
+ const crawlerOptions = {
5543
+ ...DEFAULT_CLOAK_CRAWLER_BASE_OPTIONS,
5544
+ ...normalizeObject2(crawlerBaseOptions),
5545
+ headless,
5546
+ launchContext: {
5547
+ useIncognitoPages: true,
5548
+ ...normalizeObject2(launchContext),
5549
+ ...launcher ? { launcher } : {},
5550
+ launchOptions
5551
+ },
5552
+ browserPoolOptions: attachCloakHumanizeHook({
5553
+ browserPoolOptions,
5554
+ activeBrowsers,
5555
+ patchedBrowsers,
5556
+ humanizeOptions
5557
+ }),
5558
+ preNavigationHooks: [
5559
+ async (crawlingContext, gotoOptions = {}) => {
5560
+ trafficHook(crawlingContext?.page);
5561
+ await internalPreNavigationHook(crawlingContext, gotoOptions);
5562
+ },
5563
+ ...normalizedPreNavigationHooks
5564
+ ],
5565
+ ...normalizedPostNavigationHooks.length > 0 ? { postNavigationHooks: normalizedPostNavigationHooks } : {}
5566
+ };
5567
+ const closeActiveBrowsers = async () => {
5568
+ await closeTrackedBrowsers(activeBrowsers);
5569
+ };
5570
+ const forceTerminateActiveProcesses = async () => {
5571
+ await forceTerminateBrowsersByFingerprintArg(fingerprintArg);
5572
+ };
5573
+ const cleanup = async () => {
5574
+ await closeActiveBrowsers();
5575
+ await forceTerminateActiveProcesses();
5576
+ };
5577
+ return {
5578
+ headless,
5579
+ launchOptions,
5580
+ fingerprintArg,
5581
+ crawlerOptions,
5582
+ closeActiveBrowsers,
5583
+ forceTerminateActiveProcesses,
5584
+ cleanup
5585
+ };
5586
+ }
5587
+ };
5588
+
5589
+ // src/launch.js
5590
+ var launchStrategies = {
5591
+ [Mode.Default]: DefaultLaunch,
5592
+ [Mode.Cloak]: CloakLaunch
5593
+ };
5594
+ var Launch = withModeReflect("Launch", launchStrategies);
5595
+
5102
5596
  // src/live-view.js
5103
5597
  var import_express = __toESM(require("express"), 1);
5104
5598
  var import_apify = require("apify");
5105
- var logger9 = createInternalLogger("LiveView");
5599
+ var logger10 = createInternalLogger("LiveView");
5106
5600
  async function startLiveViewServer(liveViewKey) {
5107
5601
  const app = (0, import_express.default)();
5108
5602
  app.get("/", async (req, res) => {
@@ -5127,13 +5621,13 @@ async function startLiveViewServer(liveViewKey) {
5127
5621
  </html>
5128
5622
  `);
5129
5623
  } catch (error) {
5130
- logger9.fail("Live View Server", error);
5624
+ logger10.fail("Live View Server", error);
5131
5625
  res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
5132
5626
  }
5133
5627
  });
5134
5628
  const port = process.env.APIFY_CONTAINER_PORT || 4321;
5135
5629
  app.listen(port, () => {
5136
- logger9.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
5630
+ logger10.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
5137
5631
  });
5138
5632
  }
5139
5633
  async function takeLiveScreenshot(liveViewKey, page, logMessage) {
@@ -5141,10 +5635,10 @@ async function takeLiveScreenshot(liveViewKey, page, logMessage) {
5141
5635
  const buffer = await capturePageScreenshot(page, { type: "png" });
5142
5636
  await import_apify.Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
5143
5637
  if (logMessage) {
5144
- logger9.info(`(\u622A\u56FE): ${logMessage}`);
5638
+ logger10.info(`(\u622A\u56FE): ${logMessage}`);
5145
5639
  }
5146
5640
  } catch (e) {
5147
- logger9.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
5641
+ logger10.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
5148
5642
  }
5149
5643
  }
5150
5644
  var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
@@ -5161,9 +5655,6 @@ var LiveView = {
5161
5655
  useLiveView
5162
5656
  };
5163
5657
 
5164
- // src/chaptcha.js
5165
- var import_uuid = require("uuid");
5166
-
5167
5658
  // src/internals/captcha/bytedance.js
5168
5659
  var import_promises = require("fs/promises");
5169
5660
  var import_path2 = __toESM(require("path"), 1);
@@ -5253,7 +5744,7 @@ var dragCaptchaAction = async (page, sourceLocator, targetLocator, options = {})
5253
5744
  };
5254
5745
 
5255
5746
  // src/internals/captcha/bytedance.js
5256
- var logger10 = createInternalLogger("Captcha");
5747
+ var logger11 = createInternalLogger("Captcha");
5257
5748
  var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
5258
5749
  apiType: "31234",
5259
5750
  maxRetries: 3,
@@ -5385,7 +5876,7 @@ var collectCaptchaDebugInfo = async (page, frame, iframeLocator, attempt, phase,
5385
5876
  }
5386
5877
  await (0, import_promises.writeFile)(infoPath, JSON.stringify(payload, null, 2), "utf8");
5387
5878
  }
5388
- logger10.info(`\u5DF2\u5199\u51FA\u9A8C\u8BC1\u7801\u8C03\u8BD5\u4EA7\u7269\uFF1A${debugDir}`);
5879
+ logger11.info(`\u5DF2\u5199\u51FA\u9A8C\u8BC1\u7801\u8C03\u8BD5\u4EA7\u7269\uFF1A${debugDir}`);
5389
5880
  };
5390
5881
  var maybeCollectCaptchaDebugInfo = async (page, frame, iframeLocator, attempt, phase, options, extra = null) => {
5391
5882
  if (!options.debugArtifacts) {
@@ -5422,14 +5913,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
5422
5913
  if (!isContainerVisible) {
5423
5914
  return null;
5424
5915
  }
5425
- logger10.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
5916
+ logger11.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
5426
5917
  let iframeLocator = page.locator(options.iframeSelector).first();
5427
5918
  let isIframeVisible = await waitForVisible(
5428
5919
  iframeLocator,
5429
5920
  options.iframeVisibleTimeoutMs
5430
5921
  );
5431
5922
  if (!isIframeVisible) {
5432
- logger10.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
5923
+ logger11.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
5433
5924
  iframeLocator = captchaContainer.locator(options.iframeFallbackSelector).first();
5434
5925
  isIframeVisible = await waitForVisible(
5435
5926
  iframeLocator,
@@ -5439,7 +5930,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
5439
5930
  if (!isIframeVisible) {
5440
5931
  throw new Error("verifycenter iframe not found inside captcha container.");
5441
5932
  }
5442
- logger10.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
5933
+ logger11.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
5443
5934
  const frame = await resolveContentFrame(page, iframeLocator, options);
5444
5935
  if (!frame) {
5445
5936
  throw new Error("Failed to resolve verifycenter iframe content frame.");
@@ -5555,11 +6046,11 @@ var refreshCaptcha = async (page, frame, options) => {
5555
6046
  const clicked = await clickCaptchaAction(frame, options.refreshTexts, {
5556
6047
  ...options,
5557
6048
  page,
5558
- logger: logger10,
6049
+ logger: logger11,
5559
6050
  forceMouse: true
5560
6051
  }).catch(() => false);
5561
6052
  if (!clicked) {
5562
- logger10.warn("Refresh button not found.");
6053
+ logger11.warn("Refresh button not found.");
5563
6054
  return false;
5564
6055
  }
5565
6056
  await page.waitForTimeout(options.refreshWaitMs);
@@ -5590,24 +6081,24 @@ var waitForCaptchaChallengeReady = async (page, frame, options) => {
5590
6081
  const hasGuideMaskVisible = options.guideMaskSelector ? await frame.locator(options.guideMaskSelector).first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
5591
6082
  hasSeenGuideMask = hasSeenGuideMask || hasGuideMaskVisible;
5592
6083
  if (hasGuideMaskVisible && !hasLoggedGuideMask) {
5593
- 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");
6084
+ 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");
5594
6085
  hasLoggedGuideMask = true;
5595
6086
  }
5596
6087
  if (!isLoadingVisible && hasVisibleSourceImage && hasVisibleDropTarget && !hasGuideMaskVisible) {
5597
- logger10.info(
6088
+ logger11.info(
5598
6089
  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"
5599
6090
  );
5600
6091
  return;
5601
6092
  }
5602
6093
  if (hasErrorTextVisible) {
5603
- 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");
6094
+ 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");
5604
6095
  await refreshCaptcha(page, frame, options);
5605
6096
  refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
5606
6097
  hasSeenLoading = false;
5607
6098
  continue;
5608
6099
  }
5609
6100
  if ((!hasVisibleSourceImage || !hasVisibleDropTarget) && Date.now() >= refreshDeadline) {
5610
- 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`);
6101
+ 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`);
5611
6102
  await refreshCaptcha(page, frame, options);
5612
6103
  refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
5613
6104
  hasSeenLoading = false;
@@ -5655,7 +6146,7 @@ var dragPromptCaptchaImage = async (page, frame, iframeLocator, sourceLocator, d
5655
6146
  accepted
5656
6147
  };
5657
6148
  dragAttempts.push(attemptInfo);
5658
- logger10.info(
6149
+ logger11.info(
5659
6150
  `\u9A8C\u8BC1\u7801\u62D6\u62FD\u7B2C ${visualIndex + 1} \u5F20\uFF0C\u65B9\u6848 ${plan.name}\uFF0Cbadge ${baselineState.badgeCount} -> ${afterState.badgeCount}\uFF0Cselected ${baselineState.selectedCount} -> ${afterState.selectedCount}`
5660
6151
  );
5661
6152
  if (accepted) {
@@ -5673,7 +6164,7 @@ var dragPromptCaptchaImage = async (page, frame, iframeLocator, sourceLocator, d
5673
6164
  dragAttempts,
5674
6165
  finalState: await readPromptCaptchaState(frame, options)
5675
6166
  }).catch((error) => {
5676
- logger10.warn(`\u9A8C\u8BC1\u7801\u62D6\u62FD\u5931\u8D25\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
6167
+ logger11.warn(`\u9A8C\u8BC1\u7801\u62D6\u62FD\u5931\u8D25\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
5677
6168
  });
5678
6169
  return {
5679
6170
  accepted: false,
@@ -5690,16 +6181,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5690
6181
  ...options
5691
6182
  };
5692
6183
  if (!config.token) {
5693
- logger10.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
6184
+ logger11.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
5694
6185
  return false;
5695
6186
  }
5696
- logger10.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
6187
+ logger11.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
5697
6188
  for (let attempt = 1; attempt <= config.maxRetries; attempt += 1) {
5698
- logger10.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
6189
+ logger11.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
5699
6190
  try {
5700
6191
  const captchaContext = await getVerifycenterCaptchaContext(page, config);
5701
6192
  if (!captchaContext) {
5702
- logger10.info("Captcha container is not visible anymore.");
6193
+ logger11.info("Captcha container is not visible anymore.");
5703
6194
  return true;
5704
6195
  }
5705
6196
  const { iframeLocator, frame } = captchaContext;
@@ -5712,7 +6203,7 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5712
6203
  "ready",
5713
6204
  config
5714
6205
  ).catch((error) => {
5715
- logger10.warn(`\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
6206
+ logger11.warn(`\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
5716
6207
  });
5717
6208
  await page.waitForTimeout(config.recognitionDelayMs);
5718
6209
  const screenshotBuffer = await iframeLocator.screenshot();
@@ -5724,16 +6215,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5724
6215
  });
5725
6216
  const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
5726
6217
  if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
5727
- logger10.warn(
6218
+ logger11.warn(
5728
6219
  `\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\u3002code=${apiResponse?.code}, msg=${apiResponse?.msg || "unknown"}`
5729
6220
  );
5730
6221
  await refreshCaptcha(page, frame, config);
5731
6222
  continue;
5732
6223
  }
5733
- logger10.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
6224
+ logger11.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
5734
6225
  const dropTarget = await findCaptchaDropTarget(frame, config);
5735
6226
  if (!dropTarget) {
5736
- logger10.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
6227
+ logger11.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
5737
6228
  await refreshCaptcha(page, frame, config);
5738
6229
  continue;
5739
6230
  }
@@ -5744,7 +6235,7 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5744
6235
  `Captcha image indexes could not be normalized. raw=${serialNumbers.join(", ")}, count=${orderedSourceImages.length}`
5745
6236
  );
5746
6237
  }
5747
- logger10.info(`\u9A8C\u8BC1\u7801\u89C6\u89C9\u4F4D\u5E8F\u6620\u5C04\uFF1A${normalizedIndexes.map((index) => index + 1).join(", ")}`);
6238
+ logger11.info(`\u9A8C\u8BC1\u7801\u89C6\u89C9\u4F4D\u5E8F\u6620\u5C04\uFF1A${normalizedIndexes.map((index) => index + 1).join(", ")}`);
5748
6239
  for (const imageIndex of normalizedIndexes) {
5749
6240
  if (imageIndex < 0 || imageIndex >= orderedSourceImages.length) {
5750
6241
  throw new Error(
@@ -5776,52 +6267,55 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
5776
6267
  }
5777
6268
  }
5778
6269
  const beforeSubmitState = await readPromptCaptchaState(frame, config);
5779
- logger10.info(
6270
+ logger11.info(
5780
6271
  `\u63D0\u4EA4\u524D\u9A8C\u8BC1\u7801\u72B6\u6001\uFF1Abadge=${beforeSubmitState.badgeCount}, selected=${beforeSubmitState.selectedCount}, submitDisabled=${beforeSubmitState.submitDisabled}`
5781
6272
  );
5782
6273
  const submitted = await clickCaptchaAction(frame, config.submitTexts, {
5783
6274
  ...config,
5784
6275
  page,
5785
- logger: logger10,
6276
+ logger: logger11,
5786
6277
  forceMouse: true,
5787
6278
  actionVisibleTimeoutMs: config.submitReadyTimeoutMs
5788
6279
  }).catch(() => false);
5789
6280
  if (!submitted) {
5790
- logger10.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
6281
+ logger11.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
5791
6282
  }
5792
6283
  await page.waitForTimeout(config.submitWaitMs);
5793
6284
  const afterSubmitState = await readPromptCaptchaState(frame, config);
5794
- logger10.info(
6285
+ logger11.info(
5795
6286
  `\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u72B6\u6001\uFF1Abadge=${afterSubmitState.badgeCount}, selected=${afterSubmitState.selectedCount}, submitDisabled=${afterSubmitState.submitDisabled}`
5796
6287
  );
5797
6288
  const stillVisible = await iframeLocator.isVisible({ timeout: config.containerVisibleTimeoutMs }).catch(() => false);
5798
6289
  if (!stillVisible) {
5799
- logger10.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
6290
+ logger11.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
5800
6291
  return true;
5801
6292
  }
5802
6293
  await maybeCollectCaptchaDebugInfo(page, frame, iframeLocator, attempt, "submit-still-visible", config, {
5803
6294
  beforeSubmitState,
5804
6295
  afterSubmitState
5805
6296
  }).catch((error) => {
5806
- logger10.warn(`\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
6297
+ logger11.warn(`\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
5807
6298
  });
5808
- logger10.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
6299
+ logger11.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
5809
6300
  await page.waitForTimeout(2e3);
5810
6301
  await refreshCaptcha(page, frame, config);
5811
6302
  } catch (error) {
5812
- logger10.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
6303
+ logger11.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
5813
6304
  }
5814
6305
  if (attempt < config.maxRetries) {
5815
6306
  await page.waitForTimeout(config.retryDelayBaseMs + attempt * config.retryDelayStepMs);
5816
6307
  }
5817
6308
  }
5818
- logger10.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
6309
+ logger11.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
5819
6310
  return false;
5820
6311
  }
5821
6312
  var sloveCaptcha = solveCaptcha;
5822
6313
 
5823
6314
  // src/chaptcha.js
5824
- var logger11 = createInternalLogger("Captcha");
6315
+ var logger12 = createInternalLogger("Captcha");
6316
+ var DOM_MONITOR_WAIT_TIMEOUT_MS = 1e3;
6317
+ var DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS = 300;
6318
+ var DOM_MONITOR_RECOVERY_WAIT_MS = 100;
5825
6319
  var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
5826
6320
  token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
5827
6321
  apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
@@ -5842,6 +6336,15 @@ var mergeDefinedOptions = (...sources) => {
5842
6336
  }
5843
6337
  return merged;
5844
6338
  };
6339
+ var sleep = (ms) => new Promise((resolve) => {
6340
+ setTimeout(resolve, ms);
6341
+ });
6342
+ var getErrorMessage = (error) => String(error?.message || error || "");
6343
+ var isTimeoutError = (error) => error?.name === "TimeoutError" || getErrorMessage(error).includes("Timeout");
6344
+ var isPageLifecycleError = (error) => {
6345
+ const message = getErrorMessage(error);
6346
+ 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");
6347
+ };
5845
6348
  function useCaptchaMonitor(page, options) {
5846
6349
  const { domSelector, urlPattern, onDetected } = options;
5847
6350
  if (!domSelector && !urlPattern) {
@@ -5853,10 +6356,13 @@ function useCaptchaMonitor(page, options) {
5853
6356
  let isStopped = false;
5854
6357
  let isHandling = false;
5855
6358
  let frameHandler = null;
5856
- let exposedFunctionName = null;
6359
+ let domMonitorTask = null;
6360
+ let lastTriggeredAt = 0;
5857
6361
  const triggerDetected = async () => {
5858
- if (isStopped || isHandling) return;
6362
+ const now = Date.now();
6363
+ if (isStopped || isHandling || now - lastTriggeredAt < 250) return;
5859
6364
  isHandling = true;
6365
+ lastTriggeredAt = now;
5860
6366
  try {
5861
6367
  await onDetected();
5862
6368
  } finally {
@@ -5865,60 +6371,38 @@ function useCaptchaMonitor(page, options) {
5865
6371
  };
5866
6372
  const cleanupFns = [];
5867
6373
  if (domSelector) {
5868
- exposedFunctionName = `__c_d_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
5869
- const cleanerName = `__c_cleaner_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
5870
- page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
5871
- });
5872
- page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
5873
- (() => {
5874
- let observer = null;
5875
- const checkAndReport = () => {
5876
- const element = document.querySelector(selector);
5877
- if (!element) {
5878
- return false;
5879
- }
5880
- if (window[callbackName]) {
5881
- window[callbackName]();
5882
- }
5883
- return true;
5884
- };
5885
- checkAndReport();
5886
- observer = new MutationObserver((mutations) => {
5887
- const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
5888
- if (shouldCheck && observer) {
5889
- checkAndReport();
5890
- }
5891
- });
5892
- const mountObserver = () => {
5893
- const target = document.documentElement;
5894
- if (target && observer) {
5895
- observer.observe(target, { childList: true, subtree: true });
6374
+ domMonitorTask = (async () => {
6375
+ const locator = page.locator(domSelector).first();
6376
+ while (!isStopped) {
6377
+ try {
6378
+ await locator.waitFor({ state: "visible", timeout: DOM_MONITOR_WAIT_TIMEOUT_MS });
6379
+ if (isStopped) break;
6380
+ await triggerDetected();
6381
+ if (isStopped) break;
6382
+ await locator.waitFor({
6383
+ state: "hidden",
6384
+ timeout: DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS
6385
+ }).catch(() => {
6386
+ });
6387
+ } catch (error) {
6388
+ if (isStopped) break;
6389
+ if (page?.isClosed?.() && isPageLifecycleError(error)) break;
6390
+ if (isTimeoutError(error) || isPageLifecycleError(error)) {
6391
+ await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
6392
+ continue;
5896
6393
  }
5897
- };
5898
- if (document.readyState === "loading") {
5899
- window.addEventListener("DOMContentLoaded", mountObserver);
5900
- } else {
5901
- mountObserver();
6394
+ logger12.warning(
6395
+ "useCaptchaMonitor",
6396
+ `DOM \u76D1\u63A7\u51FA\u73B0\u5F02\u5E38\uFF08\u7EE7\u7EED\u91CD\u8BD5\uFF09: selector=${domSelector}, error=${getErrorMessage(error)}`
6397
+ );
6398
+ await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
5902
6399
  }
5903
- window[cleanupName] = () => {
5904
- if (observer) {
5905
- observer.disconnect();
5906
- observer = null;
5907
- }
5908
- };
5909
- })();
5910
- }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
5911
- logger11.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
5912
- cleanupFns.push(async () => {
5913
- try {
5914
- await page.evaluate((name) => {
5915
- if (window[name]) {
5916
- window[name]();
5917
- delete window[name];
5918
- }
5919
- }, cleanerName);
5920
- } catch {
5921
6400
  }
6401
+ })();
6402
+ logger12.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
6403
+ cleanupFns.push(async () => {
6404
+ await domMonitorTask?.catch(() => {
6405
+ });
5922
6406
  });
5923
6407
  }
5924
6408
  if (urlPattern) {
@@ -5932,18 +6416,24 @@ function useCaptchaMonitor(page, options) {
5932
6416
  }
5933
6417
  };
5934
6418
  page.on("framenavigated", frameHandler);
5935
- logger11.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
6419
+ logger12.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
6420
+ Promise.resolve().then(async () => {
6421
+ if (!isStopped && page.url().includes(urlPattern)) {
6422
+ await triggerDetected();
6423
+ }
6424
+ }).catch(() => {
6425
+ });
5936
6426
  cleanupFns.push(async () => {
5937
6427
  page.off("framenavigated", frameHandler);
5938
6428
  });
5939
6429
  }
5940
6430
  return {
5941
6431
  stop: async () => {
5942
- logger11.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
6432
+ logger12.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
6433
+ isStopped = true;
5943
6434
  for (const fn of cleanupFns) {
5944
6435
  await fn();
5945
6436
  }
5946
- isStopped = true;
5947
6437
  }
5948
6438
  };
5949
6439
  }
@@ -5978,7 +6468,7 @@ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
5978
6468
  );
5979
6469
  return strategy.sloveCaptcha(page, resolvedOptions, {
5980
6470
  callCaptchaRecognitionApi,
5981
- logger: logger11
6471
+ logger: logger12
5982
6472
  });
5983
6473
  }
5984
6474
  var Captcha = {
@@ -5988,15 +6478,15 @@ var Captcha = {
5988
6478
 
5989
6479
  // src/mutation.js
5990
6480
  var import_node_crypto = require("node:crypto");
5991
- var import_uuid2 = require("uuid");
5992
- var logger12 = createInternalLogger("Mutation");
6481
+ var import_uuid = require("uuid");
6482
+ var logger13 = createInternalLogger("Mutation");
5993
6483
  var MUTATION_MONITOR_MODE = Object.freeze({
5994
6484
  Added: "added",
5995
6485
  Changed: "changed",
5996
6486
  All: "all"
5997
6487
  });
5998
6488
  function generateKey(prefix) {
5999
- return `__${prefix}_${(0, import_uuid2.v4)().replace(/-/g, "_")}`;
6489
+ return `__${prefix}_${(0, import_uuid.v4)().replace(/-/g, "_")}`;
6000
6490
  }
6001
6491
  var Mutation = {
6002
6492
  Mode: MUTATION_MONITOR_MODE,
@@ -6022,14 +6512,14 @@ var Mutation = {
6022
6512
  const stableTime = options.stableTime ?? 5 * 1e3;
6023
6513
  const timeout = options.timeout ?? 120 * 1e3;
6024
6514
  const onMutation = options.onMutation;
6025
- logger12.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
6515
+ logger13.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
6026
6516
  if (initialTimeout > 0) {
6027
6517
  const selectorQuery = selectorList.join(",");
6028
6518
  try {
6029
6519
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
6030
- logger12.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
6520
+ logger13.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
6031
6521
  } catch (e) {
6032
- logger12.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
6522
+ logger13.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
6033
6523
  throw e;
6034
6524
  }
6035
6525
  }
@@ -6045,7 +6535,7 @@ var Mutation = {
6045
6535
  return "__CONTINUE__";
6046
6536
  }
6047
6537
  });
6048
- logger12.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
6538
+ logger13.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
6049
6539
  } catch (e) {
6050
6540
  }
6051
6541
  }
@@ -6160,9 +6650,9 @@ var Mutation = {
6160
6650
  { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
6161
6651
  );
6162
6652
  if (result.mutationCount === 0 && result.stableTime === 0) {
6163
- logger12.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
6653
+ logger13.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
6164
6654
  }
6165
- logger12.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
6655
+ logger13.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
6166
6656
  return result;
6167
6657
  },
6168
6658
  /**
@@ -6186,7 +6676,7 @@ var Mutation = {
6186
6676
  const overallTimeout = options.timeout ?? 180 * 1e3;
6187
6677
  const onMutation = options.onMutation;
6188
6678
  const pollInterval = 500;
6189
- const sleep = (ms) => new Promise((resolve) => {
6679
+ const sleep2 = (ms) => new Promise((resolve) => {
6190
6680
  setTimeout(resolve, ms);
6191
6681
  });
6192
6682
  const truncate = (value, max = 800) => {
@@ -6334,29 +6824,29 @@ var Mutation = {
6334
6824
  return "__CONTINUE__";
6335
6825
  }
6336
6826
  };
6337
- logger12.start(
6827
+ logger13.start(
6338
6828
  "waitForStableAcrossRoots",
6339
6829
  `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
6340
6830
  );
6341
6831
  if (initialTimeout > 0) {
6342
6832
  try {
6343
6833
  await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
6344
- logger12.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
6834
+ logger13.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
6345
6835
  } catch (e) {
6346
- logger12.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
6836
+ logger13.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
6347
6837
  throw e;
6348
6838
  }
6349
6839
  }
6350
- let state = await buildState();
6351
- if (!state?.hasMatched) {
6352
- logger12.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
6840
+ let state2 = await buildState();
6841
+ if (!state2?.hasMatched) {
6842
+ logger13.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
6353
6843
  return { mutationCount: 0, stableTime: 0, wasPaused: false };
6354
6844
  }
6355
6845
  let mutationCount = 0;
6356
6846
  let stableSince = 0;
6357
6847
  let isPaused = false;
6358
6848
  let wasPaused = false;
6359
- let lastSnapshotKey = state.snapshotKey;
6849
+ let lastSnapshotKey = state2.snapshotKey;
6360
6850
  const applyPauseSignal = (signal) => {
6361
6851
  const nextPaused = signal === "__PAUSE__";
6362
6852
  if (nextPaused) {
@@ -6370,15 +6860,15 @@ var Mutation = {
6370
6860
  };
6371
6861
  const initialSignal = await invokeMutationCallback({
6372
6862
  mutationCount: 0,
6373
- html: state.html || "",
6374
- text: state.text || "",
6375
- mutationNodes: state.mutationNodes || []
6863
+ html: state2.html || "",
6864
+ text: state2.text || "",
6865
+ mutationNodes: state2.mutationNodes || []
6376
6866
  });
6377
6867
  applyPauseSignal(initialSignal);
6378
6868
  const deadline = Date.now() + overallTimeout;
6379
- let lastState = state;
6869
+ let lastState = state2;
6380
6870
  while (Date.now() < deadline) {
6381
- await sleep(pollInterval);
6871
+ await sleep2(pollInterval);
6382
6872
  lastState = await buildState();
6383
6873
  if (!lastState?.hasMatched) {
6384
6874
  continue;
@@ -6386,7 +6876,7 @@ var Mutation = {
6386
6876
  if (lastState.snapshotKey !== lastSnapshotKey) {
6387
6877
  lastSnapshotKey = lastState.snapshotKey;
6388
6878
  mutationCount += 1;
6389
- logger12.info(
6879
+ logger13.info(
6390
6880
  `waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
6391
6881
  );
6392
6882
  const signal = await invokeMutationCallback({
@@ -6399,7 +6889,7 @@ var Mutation = {
6399
6889
  continue;
6400
6890
  }
6401
6891
  if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
6402
- logger12.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
6892
+ logger13.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
6403
6893
  return {
6404
6894
  mutationCount,
6405
6895
  stableTime: waitForStableTime,
@@ -6425,8 +6915,8 @@ var Mutation = {
6425
6915
  const selectorList = Array.isArray(selectors) ? selectors : [selectors];
6426
6916
  const onMutation = options.onMutation;
6427
6917
  const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
6428
- const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
6429
- logger12.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
6918
+ const mode2 = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
6919
+ logger13.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode2}`);
6430
6920
  const monitorKey = generateKey("pk_mon");
6431
6921
  const callbackName = generateKey("pk_mon_cb");
6432
6922
  const cleanerName = generateKey("pk_mon_clean");
@@ -6441,7 +6931,7 @@ var Mutation = {
6441
6931
  } catch (e) {
6442
6932
  }
6443
6933
  }
6444
- await page.evaluate(({ selectorList: selectorList2, monitorKey: monitorKey2, callbackName: callbackName2, cleanerName: cleanerName2, hasCallback, mode: mode2 }) => {
6934
+ await page.evaluate(({ selectorList: selectorList2, monitorKey: monitorKey2, callbackName: callbackName2, cleanerName: cleanerName2, hasCallback, mode: mode3 }) => {
6445
6935
  const monitor = {
6446
6936
  observers: [],
6447
6937
  totalMutations: 0,
@@ -6485,7 +6975,7 @@ var Mutation = {
6485
6975
  const collectMutationNodes = (mutations) => {
6486
6976
  const mutationNodes = [];
6487
6977
  for (const mutation of mutations) {
6488
- if (mode2 === "added") {
6978
+ if (mode3 === "added") {
6489
6979
  if (mutation.type !== "childList") continue;
6490
6980
  const added = Array.from(mutation.addedNodes || []);
6491
6981
  for (const node of added) {
@@ -6493,7 +6983,7 @@ var Mutation = {
6493
6983
  }
6494
6984
  continue;
6495
6985
  }
6496
- if (mode2 === "changed") {
6986
+ if (mode3 === "changed") {
6497
6987
  if (mutation.type === "attributes" || mutation.type === "characterData") {
6498
6988
  mutationNodes.push(serializeNode(mutation.target, mutation.type));
6499
6989
  } else if (mutation.type === "childList") {
@@ -6553,8 +7043,8 @@ var Mutation = {
6553
7043
  observer.observe(element, {
6554
7044
  childList: true,
6555
7045
  subtree: true,
6556
- characterData: mode2 !== "added",
6557
- attributes: mode2 !== "added"
7046
+ characterData: mode3 !== "added",
7047
+ attributes: mode3 !== "added"
6558
7048
  });
6559
7049
  monitor.observers.push(observer);
6560
7050
  });
@@ -6568,8 +7058,8 @@ var Mutation = {
6568
7058
  delete window[cleanerName2];
6569
7059
  return total;
6570
7060
  };
6571
- }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
6572
- logger12.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
7061
+ }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode: mode2 });
7062
+ logger13.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
6573
7063
  return {
6574
7064
  stop: async () => {
6575
7065
  let totalMutations = 0;
@@ -6582,7 +7072,7 @@ var Mutation = {
6582
7072
  }, cleanerName);
6583
7073
  } catch (e) {
6584
7074
  }
6585
- logger12.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
7075
+ logger13.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
6586
7076
  return { totalMutations };
6587
7077
  }
6588
7078
  };
@@ -7451,7 +7941,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
7451
7941
  };
7452
7942
  var getDefaultBaseLogger = () => createBaseLogger("");
7453
7943
  var Logger = {
7454
- setLogger: (logger16) => setDefaultLogger(logger16),
7944
+ setLogger: (logger17) => setDefaultLogger(logger17),
7455
7945
  info: (message) => getDefaultBaseLogger().info(message),
7456
7946
  success: (message) => getDefaultBaseLogger().success(message),
7457
7947
  warning: (message) => getDefaultBaseLogger().warning(message),
@@ -7459,14 +7949,14 @@ var Logger = {
7459
7949
  error: (message) => getDefaultBaseLogger().error(message),
7460
7950
  debug: (message) => getDefaultBaseLogger().debug(message),
7461
7951
  start: (message) => getDefaultBaseLogger().start(message),
7462
- useTemplate: (logger16) => {
7463
- if (logger16) return createTemplateLogger(createBaseLogger("", logger16));
7952
+ useTemplate: (logger17) => {
7953
+ if (logger17) return createTemplateLogger(createBaseLogger("", logger17));
7464
7954
  return createTemplateLogger();
7465
7955
  }
7466
7956
  };
7467
7957
 
7468
7958
  // src/share.js
7469
- var import_delay4 = __toESM(require("delay"), 1);
7959
+ var import_delay5 = __toESM(require("delay"), 1);
7470
7960
 
7471
7961
  // src/internals/watermarkify.js
7472
7962
  var DEFAULT_TIMEZONE_OFFSET = 8;
@@ -7534,7 +8024,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
7534
8024
  ];
7535
8025
  var cachedStripLogoSrcPromise = null;
7536
8026
  var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
7537
- var logger13 = createInternalLogger("Watermarkify");
8027
+ var logger14 = createInternalLogger("Watermarkify");
7538
8028
  var normalizeText = (value) => String(value || "").trim();
7539
8029
  var toInline = (value, maxLen = 200) => {
7540
8030
  const text = normalizeText(value);
@@ -7776,9 +8266,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
7776
8266
  location: toInline(resolved.location, 80)
7777
8267
  };
7778
8268
  if (enrichment.ip || enrichment.location) {
7779
- logger13.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
8269
+ logger14.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
7780
8270
  } else {
7781
- logger13.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
8271
+ logger14.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
7782
8272
  }
7783
8273
  return enrichment;
7784
8274
  } finally {
@@ -7962,14 +8452,17 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height, imageH
7962
8452
  </html>
7963
8453
  `;
7964
8454
  };
7965
- var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}) => {
8455
+ var normalizeWatermarkifyRenderMode = (value) => {
8456
+ return String(value || Mode.Default).trim().toLowerCase() === Mode.Cloak ? Mode.Cloak : Mode.Default;
8457
+ };
8458
+ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}, options = {}) => {
7966
8459
  if (!page || typeof page.context !== "function") {
7967
- logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
8460
+ logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
7968
8461
  return buffer;
7969
8462
  }
7970
8463
  const renderScope = await openProbePage(page);
7971
8464
  if (!renderScope?.page) {
7972
- logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
8465
+ logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
7973
8466
  return buffer;
7974
8467
  }
7975
8468
  try {
@@ -7986,15 +8479,35 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
7986
8479
  height: viewportHeight
7987
8480
  }).catch(() => {
7988
8481
  });
7989
- await renderPage.setContent(buildWatermarkifyRenderHtml({
7990
- imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
7991
- overlaySvg,
7992
- width: safeWidth,
7993
- height: safeHeight,
7994
- imageHeight: safeImageHeight
7995
- }), {
7996
- waitUntil: "load"
7997
- });
8482
+ const renderMode = normalizeWatermarkifyRenderMode(options.mode);
8483
+ if (renderMode === Mode.Cloak) {
8484
+ const renderHtml = buildWatermarkifyRenderHtml({
8485
+ imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
8486
+ overlaySvg,
8487
+ width: safeWidth,
8488
+ height: safeHeight,
8489
+ imageHeight: safeImageHeight
8490
+ });
8491
+ await renderPage.goto("about:blank", {
8492
+ waitUntil: "commit"
8493
+ }).catch(() => {
8494
+ });
8495
+ await renderPage.evaluate((html) => {
8496
+ document.open();
8497
+ document.write(html);
8498
+ document.close();
8499
+ }, renderHtml);
8500
+ } else {
8501
+ await renderPage.setContent(buildWatermarkifyRenderHtml({
8502
+ imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
8503
+ overlaySvg,
8504
+ width: safeWidth,
8505
+ height: safeHeight,
8506
+ imageHeight: safeImageHeight
8507
+ }), {
8508
+ waitUntil: "load"
8509
+ });
8510
+ }
7998
8511
  await renderPage.waitForFunction(() => {
7999
8512
  const image = document.getElementById("pk-base-image");
8000
8513
  return image instanceof HTMLImageElement && image.complete && image.naturalWidth > 0 && image.naturalHeight > 0;
@@ -8014,13 +8527,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
8014
8527
  fullPage: true,
8015
8528
  animations: "disabled"
8016
8529
  }).catch((error) => {
8017
- logger13.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
8530
+ logger14.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
8018
8531
  return null;
8019
8532
  });
8020
8533
  if (Buffer.isBuffer(composed) && composed.length > 0) {
8021
8534
  return composed;
8022
8535
  }
8023
- logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
8536
+ logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
8024
8537
  return buffer;
8025
8538
  } finally {
8026
8539
  await renderScope.close().catch(() => {
@@ -8033,7 +8546,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
8033
8546
  }
8034
8547
  const probeScope = await openProbePage(page);
8035
8548
  if (!probeScope?.page) {
8036
- logger13.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
8549
+ logger14.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
8037
8550
  return null;
8038
8551
  }
8039
8552
  const timeoutMs = Math.max(
@@ -8042,12 +8555,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
8042
8555
  );
8043
8556
  try {
8044
8557
  const probePage = probeScope.page;
8045
- logger13.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
8558
+ logger14.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
8046
8559
  const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
8047
8560
  waitUntil: "commit",
8048
8561
  timeout: timeoutMs
8049
8562
  }).catch((error) => {
8050
- logger13.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
8563
+ logger14.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
8051
8564
  return null;
8052
8565
  });
8053
8566
  const status = response && typeof response.status === "function" ? response.status() : 0;
@@ -8069,13 +8582,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
8069
8582
  }
8070
8583
  const parsed = parseIpIpJsonResponse(rawText);
8071
8584
  if (parsed?.ip || parsed?.location) {
8072
- logger13.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
8585
+ logger14.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
8073
8586
  return parsed;
8074
8587
  }
8075
- logger13.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
8588
+ logger14.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
8076
8589
  return null;
8077
8590
  } catch (error) {
8078
- logger13.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
8591
+ logger14.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
8079
8592
  return null;
8080
8593
  } finally {
8081
8594
  await probeScope.close().catch(() => {
@@ -8089,10 +8602,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
8089
8602
  ip: toInline(options.ip, 80),
8090
8603
  location: toInline(options.location, 80)
8091
8604
  };
8092
- logger13.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
8605
+ logger14.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
8093
8606
  if (!merged.ip || !merged.location) {
8094
8607
  if (cached?.ip || cached?.location) {
8095
- logger13.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
8608
+ logger14.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
8096
8609
  }
8097
8610
  fillEnrichment(merged, cached);
8098
8611
  }
@@ -8116,15 +8629,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
8116
8629
  "x-geo-country"
8117
8630
  ]), 80);
8118
8631
  if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
8119
- logger13.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
8632
+ logger14.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
8120
8633
  merged.location = headerLocation || merged.location;
8121
8634
  }
8122
8635
  }
8123
8636
  writeCachedEnrichment(page, merged);
8124
8637
  if (merged.ip || merged.location) {
8125
- logger13.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
8638
+ logger14.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
8126
8639
  } else {
8127
- logger13.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
8640
+ logger14.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
8128
8641
  }
8129
8642
  return merged;
8130
8643
  };
@@ -8929,7 +9442,7 @@ var buildWatermarkifySvg = (meta, imageWidth, imageHeight) => {
8929
9442
  </svg>
8930
9443
  `;
8931
9444
  };
8932
- var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
9445
+ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null, options = {}) => {
8933
9446
  const hasWatermark = meta?.watermark?.enabled !== false && normalizeText(meta?.watermarkText);
8934
9447
  const hasStrip = meta?.strip?.enabled !== false && Array.isArray(meta?.stripSegments) && meta.stripSegments.length > 0;
8935
9448
  if (!Buffer.isBuffer(buffer) || !meta || !hasWatermark && !hasStrip) {
@@ -8937,7 +9450,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
8937
9450
  }
8938
9451
  const imageInfo = readImageInfo(buffer);
8939
9452
  if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
8940
- logger13.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
9453
+ logger14.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
8941
9454
  return buffer;
8942
9455
  }
8943
9456
  const isMobileStrip = normalizeDevice(meta.device) === Device.Mobile && hasStrip;
@@ -8950,12 +9463,12 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
8950
9463
  if (!overlaySvg) {
8951
9464
  return buffer;
8952
9465
  }
8953
- return await composeScreenshotBufferWithBrowser(page, buffer, overlaySvg, outputImageInfo);
9466
+ return await composeScreenshotBufferWithBrowser(page, buffer, overlaySvg, outputImageInfo, options);
8954
9467
  };
8955
9468
 
8956
9469
  // src/internals/compression.js
8957
9470
  var import_jimp = require("jimp");
8958
- var logger14 = createInternalLogger("Compression");
9471
+ var logger15 = createInternalLogger("Compression");
8959
9472
  var DEFAULT_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
8960
9473
  var DEFAULT_SCREENSHOT_OUTPUT_TYPE = "jpeg";
8961
9474
  var DEFAULT_SCREENSHOT_QUALITY = 0.72;
@@ -9074,18 +9587,18 @@ var compressImageBufferToBase64 = async (buffer, compression) => {
9074
9587
  return buffer.toString("base64");
9075
9588
  }
9076
9589
  const result = await compressImageBuffer(buffer, compression).catch((error) => {
9077
- logger14.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
9590
+ logger15.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
9078
9591
  return null;
9079
9592
  });
9080
9593
  if (!result?.buffer) {
9081
9594
  return buffer.toString("base64");
9082
9595
  }
9083
9596
  if (result.withinLimit) {
9084
- logger14.info(
9597
+ logger15.info(
9085
9598
  `captureScreen \u5DF2\u538B\u7F29: ${originalBytes} -> ${result.bytes} bytes, format=${result.format}, quality=${result.quality}, scale=${result.scale}, size=${result.width}x${result.height}`
9086
9599
  );
9087
9600
  } else {
9088
- logger14.warning(
9601
+ logger15.warning(
9089
9602
  `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}`
9090
9603
  );
9091
9604
  }
@@ -9093,7 +9606,7 @@ var compressImageBufferToBase64 = async (buffer, compression) => {
9093
9606
  };
9094
9607
 
9095
9608
  // src/share.js
9096
- var logger15 = createInternalLogger("Share");
9609
+ var logger16 = createInternalLogger("Share");
9097
9610
  var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
9098
9611
  var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
9099
9612
  var DEFAULT_POLL_INTERVAL_MS = 120;
@@ -9163,9 +9676,9 @@ var normalizeXurl = (value) => {
9163
9676
  var normalizeShare = (share) => {
9164
9677
  const source = share && typeof share === "object" ? share : {};
9165
9678
  const modeRaw = String(source.mode || "dom").trim().toLowerCase();
9166
- const mode = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
9679
+ const mode2 = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
9167
9680
  return {
9168
- mode,
9681
+ mode: mode2,
9169
9682
  prefix: normalizePrefix(source.prefix),
9170
9683
  xurl: normalizeXurl(source.xurl)
9171
9684
  };
@@ -9226,13 +9739,13 @@ var parseJsonSafely = (text) => {
9226
9739
  var createDomShareMonitor = async (page, options = {}) => {
9227
9740
  const prefix = normalizePrefix(options.prefix);
9228
9741
  const selectors = options.selectors ?? "html";
9229
- const mode = options.mode ?? Mutation.Mode.All;
9742
+ const mode2 = options.mode ?? Mutation.Mode.All;
9230
9743
  const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
9231
9744
  const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
9232
9745
  let matched = false;
9233
- logger15.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
9746
+ logger16.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode2}`);
9234
9747
  const monitor = await Mutation.useMonitor(page, selectors, {
9235
- mode,
9748
+ mode: mode2,
9236
9749
  onMutation: (context = {}) => {
9237
9750
  if (matched) return;
9238
9751
  const mutationCount = Number(context.mutationCount || 0);
@@ -9248,12 +9761,12 @@ ${text}`;
9248
9761
  });
9249
9762
  }
9250
9763
  if (mutationCount <= 5 || mutationCount % 50 === 0) {
9251
- logger15.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
9764
+ logger16.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
9252
9765
  }
9253
9766
  const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
9254
9767
  if (!candidate) return;
9255
9768
  matched = true;
9256
- logger15.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
9769
+ logger16.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
9257
9770
  if (onMatch) {
9258
9771
  onMatch({
9259
9772
  link: candidate,
@@ -9269,7 +9782,7 @@ ${text}`;
9269
9782
  return {
9270
9783
  stop: async () => {
9271
9784
  const result = await monitor.stop();
9272
- logger15.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
9785
+ logger16.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
9273
9786
  return result;
9274
9787
  }
9275
9788
  };
@@ -9318,8 +9831,8 @@ var Share = {
9318
9831
  if (share.mode === "response" && apiMatchers.length === 0) {
9319
9832
  throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
9320
9833
  }
9321
- logger15.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutDisabled ? "disabled" : timeoutMs}, prefix=${share.prefix}`);
9322
- logger15.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
9834
+ logger16.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutDisabled ? "disabled" : timeoutMs}, prefix=${share.prefix}`);
9835
+ logger16.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
9323
9836
  const stats = {
9324
9837
  actionTimedOut: false,
9325
9838
  domMutationCount: 0,
@@ -9331,7 +9844,7 @@ var Share = {
9331
9844
  responseSampleUrls: []
9332
9845
  };
9333
9846
  if (isAborted()) {
9334
- logger15.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
9847
+ logger16.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
9335
9848
  return {
9336
9849
  link: null,
9337
9850
  payloadText: "",
@@ -9354,7 +9867,7 @@ var Share = {
9354
9867
  link: validated,
9355
9868
  payloadText: String(payloadText || "")
9356
9869
  };
9357
- logger15.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
9870
+ logger16.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
9358
9871
  return true;
9359
9872
  };
9360
9873
  const resolveResponseCandidate = (responseText) => {
@@ -9389,7 +9902,7 @@ var Share = {
9389
9902
  try {
9390
9903
  await monitor.stop();
9391
9904
  } catch (error) {
9392
- logger15.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
9905
+ logger16.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
9393
9906
  }
9394
9907
  };
9395
9908
  const onResponse = async (response) => {
@@ -9403,29 +9916,29 @@ var Share = {
9403
9916
  stats.responseSampleUrls.push(url);
9404
9917
  }
9405
9918
  if (stats.responseObserved <= 5) {
9406
- logger15.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
9919
+ logger16.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
9407
9920
  }
9408
9921
  if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
9409
9922
  stats.responseMatched += 1;
9410
9923
  stats.lastMatchedUrl = url;
9411
- logger15.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
9924
+ logger16.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
9412
9925
  const text = await response.text();
9413
9926
  const hit = resolveResponseCandidate(text);
9414
9927
  if (!hit?.link) {
9415
9928
  if (stats.responseMatched <= 3) {
9416
- logger15.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
9929
+ logger16.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
9417
9930
  }
9418
9931
  return;
9419
9932
  }
9420
9933
  stats.responseResolved += 1;
9421
- logger15.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
9934
+ logger16.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
9422
9935
  setCandidate("response", hit.link, hit.payloadText);
9423
9936
  } catch (error) {
9424
- logger15.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
9937
+ logger16.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
9425
9938
  }
9426
9939
  };
9427
9940
  if (share.mode === "dom") {
9428
- logger15.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
9941
+ logger16.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
9429
9942
  domMonitor = await createDomShareMonitor(page, {
9430
9943
  prefix: share.prefix,
9431
9944
  selectors: domSelectors,
@@ -9440,17 +9953,17 @@ var Share = {
9440
9953
  });
9441
9954
  }
9442
9955
  if (share.mode === "response") {
9443
- logger15.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
9956
+ logger16.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
9444
9957
  page.on("response", onResponse);
9445
9958
  }
9446
9959
  if (share.mode === "custom") {
9447
- logger15.info("\u5F53\u524D\u4E3A custom \u6A21\u5F0F\uFF0C\u5C06\u4F7F\u7528 performActions \u8FD4\u56DE\u503C");
9960
+ logger16.info("\u5F53\u524D\u4E3A custom \u6A21\u5F0F\uFF0C\u5C06\u4F7F\u7528 performActions \u8FD4\u56DE\u503C");
9448
9961
  }
9449
9962
  const deadline = timeoutDisabled ? Infinity : Date.now() + timeoutMs;
9450
9963
  const getRemainingMs = () => timeoutDisabled ? Infinity : Math.max(0, deadline - Date.now());
9451
9964
  try {
9452
9965
  const actionTimeout = getRemainingMs();
9453
- logger15.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${timeoutDisabled ? "disabled" : `${actionTimeout}ms`}`);
9966
+ logger16.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${timeoutDisabled ? "disabled" : `${actionTimeout}ms`}`);
9454
9967
  let actionValue;
9455
9968
  if (!isAborted() && actionTimeout > 0) {
9456
9969
  let timer = null;
@@ -9463,30 +9976,30 @@ var Share = {
9463
9976
  ]);
9464
9977
  if (timer) clearTimeout(timer);
9465
9978
  if (actionResult.type === "error") {
9466
- logger15.fail("captureLink.performActions", actionResult.error);
9979
+ logger16.fail("captureLink.performActions", actionResult.error);
9467
9980
  throw actionResult.error;
9468
9981
  }
9469
9982
  if (actionResult.type === "timeout") {
9470
9983
  stats.actionTimedOut = true;
9471
- logger15.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
9984
+ logger16.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
9472
9985
  } else {
9473
9986
  actionValue = actionResult.result;
9474
- logger15.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
9987
+ logger16.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
9475
9988
  }
9476
9989
  }
9477
9990
  if (share.mode === "custom") {
9478
9991
  const customLink = typeof actionValue === "string" ? actionValue : actionValue?.link || actionValue?.payloadText;
9479
9992
  const customPayloadText = typeof actionValue === "string" ? actionValue : actionValue?.payloadText;
9480
9993
  if (setCandidate("custom", customLink, customPayloadText)) {
9481
- logger15.success("captureLink.customResult", `custom \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: link=${candidates.custom.link}`);
9994
+ logger16.success("captureLink.customResult", `custom \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: link=${candidates.custom.link}`);
9482
9995
  } else {
9483
- logger15.warning("performActions \u6267\u884C\u5B8C\u6210\u4F46\u672A\u8FD4\u56DE\u6709\u6548\u5206\u4EAB\u94FE\u63A5");
9996
+ logger16.warning("performActions \u6267\u884C\u5B8C\u6210\u4F46\u672A\u8FD4\u56DE\u6709\u6548\u5206\u4EAB\u94FE\u63A5");
9484
9997
  }
9485
9998
  }
9486
9999
  let nextProgressLogTs = Date.now() + 3e3;
9487
10000
  while (true) {
9488
10001
  if (isAborted()) {
9489
- logger15.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
10002
+ logger16.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
9490
10003
  return {
9491
10004
  link: null,
9492
10005
  payloadText: "",
@@ -9496,7 +10009,7 @@ var Share = {
9496
10009
  }
9497
10010
  const selected = candidates[share.mode];
9498
10011
  if (selected?.link) {
9499
- logger15.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
10012
+ logger16.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
9500
10013
  return {
9501
10014
  link: selected.link,
9502
10015
  payloadText: selected.payloadText,
@@ -9509,19 +10022,19 @@ var Share = {
9509
10022
  if (remaining <= 0) break;
9510
10023
  const now = Date.now();
9511
10024
  if (now >= nextProgressLogTs) {
9512
- logger15.info(
10025
+ logger16.info(
9513
10026
  `captureLink \u7B49\u5F85\u4E2D: remaining=${timeoutDisabled ? "disabled" : `${remaining}ms`}, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
9514
10027
  );
9515
10028
  nextProgressLogTs = now + 5e3;
9516
10029
  }
9517
- await (0, import_delay4.default)(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
10030
+ await (0, import_delay5.default)(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
9518
10031
  }
9519
10032
  if (!timeoutDisabled && share.mode === "response" && stats.responseMatched === 0) {
9520
- logger15.warning(
10033
+ logger16.warning(
9521
10034
  `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
9522
10035
  );
9523
10036
  }
9524
- logger15.warning(
10037
+ logger16.warning(
9525
10038
  `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"}`
9526
10039
  );
9527
10040
  return {
@@ -9533,7 +10046,7 @@ var Share = {
9533
10046
  } finally {
9534
10047
  if (share.mode === "response") {
9535
10048
  page.off("response", onResponse);
9536
- logger15.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
10049
+ logger16.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
9537
10050
  }
9538
10051
  await stopDomMonitor();
9539
10052
  }
@@ -9548,12 +10061,14 @@ var Share = {
9548
10061
  * @param {number} [options.maxBytes] 默认 5MiB,返回 base64 超过后会压缩
9549
10062
  * @param {'jpeg'|'jpg'} [options.type] 压缩输出格式,默认 jpeg
9550
10063
  * @param {boolean|Object} [options.compression] 传 false 可关闭压缩
10064
+ * @param {'default'|'cloak'} [options.mode] 截图水印合成模式,默认取当前 toolkit mode
9551
10065
  * @returns {Promise<string>} base64 image
9552
10066
  */
9553
10067
  async captureScreen(page, options = {}) {
9554
10068
  const restore = options.restore ?? false;
9555
10069
  const screenshotWatermarkify = resolveCaptureScreenWatermarkify(page, options.watermarkify);
9556
10070
  const compression = resolveImageCompression(options);
10071
+ const screenshotMode = options.mode ?? getToolkitMode();
9557
10072
  const captureOptions = {
9558
10073
  restore,
9559
10074
  maxHeight: options.maxHeight,
@@ -9568,7 +10083,9 @@ var Share = {
9568
10083
  ...screenshotWatermarkify,
9569
10084
  capturedAt
9570
10085
  });
9571
- outputBuffer = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta, page);
10086
+ outputBuffer = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta, page, {
10087
+ mode: screenshotMode
10088
+ });
9572
10089
  }
9573
10090
  return await compressImageBufferToBase64(outputBuffer, compression);
9574
10091
  }
@@ -9576,8 +10093,13 @@ var Share = {
9576
10093
 
9577
10094
  // entrys/node.js
9578
10095
  Logger.setLogger(import_crawlee.log);
9579
- var usePlaywrightToolKit = () => {
9580
- return {
10096
+ var ToolkitMode = Object.freeze({
10097
+ default: Mode.Default,
10098
+ cloak: Mode.Cloak
10099
+ });
10100
+ var usePlaywrightToolKit = (mode2 = Mode.Default) => {
10101
+ setToolkitMode(mode2);
10102
+ const toolkit = {
9581
10103
  ApifyKit,
9582
10104
  AntiCheat,
9583
10105
  DeviceInput,
@@ -9597,7 +10119,9 @@ var usePlaywrightToolKit = () => {
9597
10119
  ByPass,
9598
10120
  $Internals: { LOG_TEMPLATES, stripAnsi }
9599
10121
  };
10122
+ return toolkit;
9600
10123
  };
10124
+ usePlaywrightToolKit.Mode = ToolkitMode;
9601
10125
  // Annotate the CommonJS export names for ESM import in node:
9602
10126
  0 && (module.exports = {
9603
10127
  usePlaywrightToolKit