@skrillex1224/playwright-toolkit 2.1.166 → 2.1.167

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
@@ -120,10 +120,10 @@ var createActorInfo = (info) => {
120
120
  xurl
121
121
  };
122
122
  };
123
- const buildLandingUrl = ({ protocol: protocol2, domain: domain2, path: path2 }) => {
123
+ const buildLandingUrl = ({ protocol: protocol2, domain: domain2, path: path3 }) => {
124
124
  const safeProtocol = String(protocol2).trim();
125
125
  const safeDomain = normalizeDomain(domain2);
126
- const safePath = normalizePath(path2);
126
+ const safePath = normalizePath(path3);
127
127
  return `${safeProtocol}://${safeDomain}${safePath}`;
128
128
  };
129
129
  const buildIcon = ({ key }) => {
@@ -131,13 +131,13 @@ var createActorInfo = (info) => {
131
131
  };
132
132
  const protocol = info.protocol || "https";
133
133
  const domain = normalizeDomain(info.domain);
134
- const path = normalizePath(info.path);
134
+ const path2 = normalizePath(info.path);
135
135
  const share = normalizeShare2(info.share);
136
136
  return {
137
137
  ...info,
138
138
  protocol,
139
139
  domain,
140
- path,
140
+ path: path2,
141
141
  share,
142
142
  get icon() {
143
143
  if (info.icon) return info.icon;
@@ -151,7 +151,7 @@ var createActorInfo = (info) => {
151
151
  var ActorInfo = {
152
152
  qbot: createActorInfo({
153
153
  key: "qbot",
154
- name: "\u641C\u72D7QBot",
154
+ name: "QQ\u6D4F\u89C8\u5668AI\u641C",
155
155
  domain: "sogou.com",
156
156
  path: "/web",
157
157
  share: {
@@ -573,20 +573,307 @@ var CrawlerError = class _CrawlerError extends Error {
573
573
  // src/apify-kit.js
574
574
  var import_serialize_error2 = require("serialize-error");
575
575
 
576
- // src/traffic-runtime.js
577
- var trafficMeter = null;
578
- var setTrafficMeter = (meter) => {
579
- trafficMeter = meter || null;
576
+ // src/proxy-meter-runtime.js
577
+ var import_child_process = require("child_process");
578
+ var import_fs = require("fs");
579
+ var import_os = require("os");
580
+ var import_path = __toESM(require("path"), 1);
581
+ var import_url = require("url");
582
+ var import_meta = {};
583
+ var logger2 = createInternalLogger("ProxyMeter");
584
+ var MAX_TOP_DOMAINS = 20;
585
+ var FLUSH_INTERVAL_MS = 2e3;
586
+ var DEFAULT_DEBUG_MAX_EVENTS = 400;
587
+ var runtime = null;
588
+ var cleanupInstalled = false;
589
+ var toSafeInt = (value) => {
590
+ const num = Number(value);
591
+ if (!Number.isFinite(num) || num <= 0) return 0;
592
+ return Math.round(num);
593
+ };
594
+ var toSafeFloat = (value) => {
595
+ const num = Number(value);
596
+ if (!Number.isFinite(num)) return 0;
597
+ return num;
598
+ };
599
+ var resolveScriptPath = () => {
600
+ const baseDir = typeof __dirname !== "undefined" ? __dirname : import_path.default.dirname((0, import_url.fileURLToPath)(import_meta.url));
601
+ return import_path.default.join(baseDir, "proxy-meter.js");
602
+ };
603
+ var pickFreePort = () => {
604
+ const script = [
605
+ 'const net=require("net");',
606
+ "const server=net.createServer();",
607
+ 'server.listen(0,"127.0.0.1",()=>{',
608
+ "const port=server.address().port;",
609
+ "server.close(()=>{console.log(port);});",
610
+ "});"
611
+ ].join("");
612
+ const result = (0, import_child_process.spawnSync)(process.execPath, ["-e", script], { encoding: "utf8" });
613
+ const port = Number(String(result.stdout || "").trim());
614
+ if (result.status === 0 && Number.isFinite(port) && port > 0) {
615
+ return port;
616
+ }
617
+ return 2e4 + Math.floor(Math.random() * 2e4);
618
+ };
619
+ var resolveLogDir = () => {
620
+ const storageDir = process.env.APIFY_STORAGE_DIR || process.env.APIFY_LOCAL_STORAGE_DIR || "";
621
+ if (storageDir) {
622
+ return import_path.default.join(storageDir, "proxy-meter");
623
+ }
624
+ return import_path.default.join((0, import_os.tmpdir)(), "proxy-meter");
580
625
  };
581
- var getTrafficSnapshot = () => {
582
- if (!trafficMeter || typeof trafficMeter.snapshot !== "function") {
626
+ var ensureLogPath = () => {
627
+ const baseDir = resolveLogDir();
628
+ if (!(0, import_fs.existsSync)(baseDir)) {
629
+ try {
630
+ (0, import_fs.mkdirSync)(baseDir, { recursive: true });
631
+ } catch {
632
+ }
633
+ }
634
+ const runId = String(process.env.APIFY_ACTOR_RUN_ID || "").trim();
635
+ const suffix = `${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
636
+ const label = runId ? `proxy-meter-${runId}-${suffix}.json` : `proxy-meter-${process.pid}-${suffix}.json`;
637
+ return import_path.default.join(baseDir, label);
638
+ };
639
+ var readSnapshot = (logPath) => {
640
+ if (!logPath || !(0, import_fs.existsSync)(logPath)) return null;
641
+ try {
642
+ const raw = (0, import_fs.readFileSync)(logPath, "utf8");
643
+ if (!raw) return null;
644
+ return JSON.parse(raw);
645
+ } catch {
583
646
  return null;
584
647
  }
585
- return trafficMeter.snapshot();
648
+ };
649
+ var normalizeDomainRows = (hosts) => {
650
+ const rows = [];
651
+ let requestCount = 0;
652
+ let connectCount = 0;
653
+ for (const [domain, stat] of Object.entries(hosts || {})) {
654
+ if (!stat || typeof stat !== "object") continue;
655
+ const inBytes = toSafeInt(stat.inBytes);
656
+ const outBytes = toSafeInt(stat.outBytes);
657
+ const requests = toSafeInt(stat.requests);
658
+ const connections = toSafeInt(stat.connections);
659
+ const totalBytes = inBytes + outBytes;
660
+ requestCount += requests;
661
+ connectCount += connections;
662
+ if (totalBytes <= 0 && requests <= 0 && connections <= 0) continue;
663
+ rows.push({
664
+ domain,
665
+ inBytes,
666
+ outBytes,
667
+ totalBytes,
668
+ requests,
669
+ connections
670
+ });
671
+ }
672
+ rows.sort((a, b) => {
673
+ if (b.totalBytes !== a.totalBytes) return b.totalBytes - a.totalBytes;
674
+ if (b.requests !== a.requests) return b.requests - a.requests;
675
+ return String(a.domain).localeCompare(String(b.domain));
676
+ });
677
+ return {
678
+ topDomains: rows.slice(0, MAX_TOP_DOMAINS),
679
+ requestCount,
680
+ connectCount
681
+ };
682
+ };
683
+ var normalizeDebugRows = (rows, type) => {
684
+ if (!Array.isArray(rows) || rows.length === 0) return void 0;
685
+ const normalized = rows.map((row) => {
686
+ if (!row || typeof row !== "object") return null;
687
+ return {
688
+ domain: String(row.domain || "").trim(),
689
+ status: String(row.status || "").trim(),
690
+ count: toSafeInt(row.count),
691
+ failedCount: toSafeInt(row.failedCount),
692
+ inBytes: toSafeInt(row.inBytes),
693
+ outBytes: toSafeInt(row.outBytes),
694
+ totalBytes: toSafeInt(row.totalBytes),
695
+ avgDurationMs: toSafeFloat(row.avgDurationMs),
696
+ reconnectCount: toSafeInt(row.reconnectCount),
697
+ largeResponseCount: toSafeInt(row.largeResponseCount),
698
+ failureRatePct: toSafeFloat(row.failureRatePct),
699
+ type
700
+ };
701
+ }).filter((row) => row && row.domain && row.count > 0);
702
+ return normalized.length > 0 ? normalized : void 0;
703
+ };
704
+ var normalizeDebugEvent = (row) => {
705
+ if (!row || typeof row !== "object") return null;
706
+ const host = String(row.host || "").trim();
707
+ if (!host) return null;
708
+ return {
709
+ ts: String(row.ts || ""),
710
+ runId: String(row.runId || ""),
711
+ channel: String(row.channel || ""),
712
+ host,
713
+ method: String(row.method || ""),
714
+ path: String(row.path || ""),
715
+ statusCode: toSafeInt(row.statusCode),
716
+ durationMs: toSafeInt(row.durationMs),
717
+ inBytes: toSafeInt(row.inBytes),
718
+ outBytes: toSafeInt(row.outBytes),
719
+ totalBytes: toSafeInt(row.totalBytes),
720
+ error: String(row.error || "")
721
+ };
722
+ };
723
+ var normalizeDebugSummary = (debug) => {
724
+ if (!debug || typeof debug !== "object" || !debug.summary || typeof debug.summary !== "object") {
725
+ return null;
726
+ }
727
+ const summary = debug.summary;
728
+ const domainStatus = normalizeDebugRows(summary.domainStatus, "domain_status");
729
+ const topFailureDomains = normalizeDebugRows(summary.topFailureDomains, "top_failure");
730
+ const topLargeDomains = normalizeDebugRows(summary.topLargeDomains, "top_large");
731
+ const topReconnectDomains = normalizeDebugRows(summary.topReconnectDomains, "top_reconnect");
732
+ return {
733
+ enabled: Boolean(debug.enabled),
734
+ sampledEvents: toSafeInt(debug.sampledEvents),
735
+ droppedEvents: toSafeInt(debug.droppedEvents),
736
+ totalEvents: toSafeInt(debug.totalEvents),
737
+ largeResponseThresholdBytes: toSafeInt(summary.largeResponseThresholdBytes),
738
+ requestCount: toSafeInt(summary.requestCount),
739
+ failedCount: toSafeInt(summary.failedCount),
740
+ failureRatePct: toSafeFloat(summary.failureRatePct),
741
+ largeResponseCount: toSafeInt(summary.largeResponseCount),
742
+ reconnectCount: toSafeInt(summary.reconnectCount),
743
+ domainStatus,
744
+ topFailureDomains,
745
+ topLargeDomains,
746
+ topReconnectDomains
747
+ };
748
+ };
749
+ var normalizeSnapshot = (raw) => {
750
+ if (!raw || typeof raw !== "object") return null;
751
+ const totalIn = toSafeInt(raw.totalInBytes);
752
+ const totalOut = toSafeInt(raw.totalOutBytes);
753
+ const domains = normalizeDomainRows(raw.hosts && typeof raw.hosts === "object" ? raw.hosts : {});
754
+ const normalized = {
755
+ meter: "proxy-meter-v1",
756
+ totalBytes: totalIn + totalOut,
757
+ uploadBytes: totalOut,
758
+ downloadBytes: totalIn,
759
+ requestCount: domains.requestCount,
760
+ connectCount: domains.connectCount,
761
+ topDomains: domains.topDomains
762
+ };
763
+ const debug = raw.debug && typeof raw.debug === "object" ? raw.debug : null;
764
+ const summary = normalizeDebugSummary(debug);
765
+ const events = Array.isArray(debug?.events) ? debug.events.map(normalizeDebugEvent).filter(Boolean) : [];
766
+ if (summary) {
767
+ normalized.trafficDebugSummary = summary;
768
+ }
769
+ if (events.length > 0) {
770
+ normalized.trafficDebugEvents = events;
771
+ }
772
+ const hasSignal = normalized.totalBytes > 0 || normalized.uploadBytes > 0 || normalized.downloadBytes > 0 || normalized.requestCount > 0 || normalized.connectCount > 0 || normalized.topDomains && normalized.topDomains.length > 0 || Boolean(summary) || events.length > 0;
773
+ if (!hasSignal) return null;
774
+ return normalized;
775
+ };
776
+ var registerCleanup = () => {
777
+ if (cleanupInstalled) return;
778
+ cleanupInstalled = true;
779
+ const shutdown = () => {
780
+ if (!runtime || !runtime.proc) return;
781
+ try {
782
+ runtime.proc.kill("SIGTERM");
783
+ } catch {
784
+ }
785
+ };
786
+ process.once("exit", shutdown);
787
+ process.once("SIGINT", shutdown);
788
+ process.once("SIGTERM", shutdown);
789
+ };
790
+ var startProxyMeter = (options = {}) => {
791
+ const upstreamUrl = String(options.proxyUrl || "").trim();
792
+ if (!upstreamUrl) return null;
793
+ if (runtime && runtime.proc) {
794
+ try {
795
+ runtime.proc.kill("SIGTERM");
796
+ } catch {
797
+ }
798
+ runtime = null;
799
+ }
800
+ const port = pickFreePort();
801
+ const logPath = ensureLogPath();
802
+ const scriptPath = resolveScriptPath();
803
+ const debugMode = Boolean(options.debugMode);
804
+ const debugMaxEvents = Math.max(10, toSafeInt(options.debugMaxEvents) || DEFAULT_DEBUG_MAX_EVENTS);
805
+ const env = {
806
+ ...process.env,
807
+ PROXY_METER_PORT: String(port),
808
+ PROXY_METER_LOG: logPath,
809
+ PROXY_METER_UPSTREAM: upstreamUrl,
810
+ PROXY_METER_FLUSH_MS: String(FLUSH_INTERVAL_MS),
811
+ PROXY_METER_DEBUG: debugMode ? "1" : "0",
812
+ PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents)
813
+ };
814
+ const child = (0, import_child_process.spawn)(process.execPath, [scriptPath], {
815
+ env,
816
+ stdio: ["ignore", "ignore", "ignore"]
817
+ });
818
+ child.once("exit", (code) => {
819
+ if (code && code !== 0) {
820
+ logger2.warn(`[proxy-meter] exited with code ${code}`);
821
+ }
822
+ });
823
+ runtime = {
824
+ proc: child,
825
+ port,
826
+ logPath,
827
+ startedAt: Date.now()
828
+ };
829
+ registerCleanup();
830
+ return { server: `http://127.0.0.1:${port}` };
831
+ };
832
+ var stopProxyMeter = async () => {
833
+ if (!runtime) return null;
834
+ const { proc, logPath } = runtime;
835
+ if (!proc || proc.killed) {
836
+ runtime = null;
837
+ return logPath || null;
838
+ }
839
+ await new Promise((resolve) => {
840
+ const timeout = setTimeout(() => {
841
+ try {
842
+ proc.kill("SIGKILL");
843
+ } catch {
844
+ }
845
+ resolve();
846
+ }, 2e3);
847
+ proc.once("exit", () => {
848
+ clearTimeout(timeout);
849
+ resolve();
850
+ });
851
+ try {
852
+ proc.kill("SIGTERM");
853
+ } catch {
854
+ resolve();
855
+ }
856
+ });
857
+ runtime = null;
858
+ return logPath || null;
859
+ };
860
+ var getProxyMeterSnapshot = async (options = {}) => {
861
+ if (!runtime) return null;
862
+ const finalize = Boolean(options.finalize);
863
+ const logPath = finalize ? await stopProxyMeter() : runtime.logPath;
864
+ const raw = readSnapshot(logPath);
865
+ const snapshot = normalizeSnapshot(raw);
866
+ if (finalize && logPath) {
867
+ try {
868
+ (0, import_fs.rmSync)(logPath, { force: true });
869
+ } catch {
870
+ }
871
+ }
872
+ return snapshot;
586
873
  };
587
874
 
588
875
  // src/apify-kit.js
589
- var logger2 = createInternalLogger("ApifyKit");
876
+ var logger3 = createInternalLogger("ApifyKit");
590
877
  async function createApifyKit() {
591
878
  let apify = null;
592
879
  try {
@@ -614,29 +901,29 @@ async function createApifyKit() {
614
901
  const { times: retryTimes = 0, mode: retryMode = "direct", before: beforeRetry } = retry;
615
902
  const executeAction = async (attemptNumber) => {
616
903
  const attemptLabel = attemptNumber > 0 ? ` (\u91CD\u8BD5 #${attemptNumber})` : "";
617
- logger2.start(`[Step] ${step}${attemptLabel}`);
904
+ logger3.start(`[Step] ${step}${attemptLabel}`);
618
905
  try {
619
906
  const result = await actionFn();
620
- logger2.success(`[Step] ${step}${attemptLabel}`);
907
+ logger3.success(`[Step] ${step}${attemptLabel}`);
621
908
  return { success: true, result };
622
909
  } catch (error) {
623
- logger2.fail(`[Step] ${step}${attemptLabel}`, error);
910
+ logger3.fail(`[Step] ${step}${attemptLabel}`, error);
624
911
  return { success: false, error };
625
912
  }
626
913
  };
627
914
  const prepareForRetry = async (attemptNumber) => {
628
915
  if (typeof beforeRetry === "function") {
629
- logger2.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
916
+ logger3.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
630
917
  await beforeRetry(page, attemptNumber);
631
- logger2.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);
918
+ logger3.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);
632
919
  } else if (retryMode === "refresh") {
633
- logger2.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
920
+ logger3.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
634
921
  await page.reload({ waitUntil: "commit" });
635
- logger2.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);
922
+ logger3.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);
636
923
  } else {
637
- logger2.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
924
+ logger3.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
638
925
  await new Promise((resolve) => setTimeout(resolve, 3e3));
639
- logger2.success(`[RetryStep] \u7B49\u5F85\u5B8C\u6210`);
926
+ logger3.success(`[RetryStep] \u7B49\u5F85\u5B8C\u6210`);
640
927
  }
641
928
  };
642
929
  let lastResult = await executeAction(0);
@@ -644,11 +931,11 @@ async function createApifyKit() {
644
931
  return lastResult.result;
645
932
  }
646
933
  for (let attempt = 1; attempt <= retryTimes; attempt++) {
647
- logger2.start(`[RetryStep] \u51C6\u5907\u7B2C ${attempt}/${retryTimes} \u6B21\u91CD\u8BD5: ${step}`);
934
+ logger3.start(`[RetryStep] \u51C6\u5907\u7B2C ${attempt}/${retryTimes} \u6B21\u91CD\u8BD5: ${step}`);
648
935
  try {
649
936
  await prepareForRetry(attempt);
650
937
  } catch (prepareError) {
651
- logger2.warn(`[RetryStep] \u91CD\u8BD5\u51C6\u5907\u5931\u8D25: ${prepareError.message}`);
938
+ logger3.warn(`[RetryStep] \u91CD\u8BD5\u51C6\u5907\u5931\u8D25: ${prepareError.message}`);
652
939
  continue;
653
940
  }
654
941
  lastResult = await executeAction(attempt);
@@ -669,7 +956,7 @@ async function createApifyKit() {
669
956
  base64 = `data:image/jpeg;base64,${buffer.toString("base64")}`;
670
957
  }
671
958
  } catch (snapErr) {
672
- logger2.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);
959
+ logger3.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);
673
960
  }
674
961
  await this.pushFailed(finalError, {
675
962
  step,
@@ -703,7 +990,7 @@ async function createApifyKit() {
703
990
  * @param {Object} data - 要推送的数据对象
704
991
  */
705
992
  async pushSuccess(data) {
706
- const traffic = getTrafficSnapshot();
993
+ const traffic = await getProxyMeterSnapshot({ finalize: true });
707
994
  await Actor2.pushData({
708
995
  // 固定为0
709
996
  code: Code.Success,
@@ -712,7 +999,7 @@ async function createApifyKit() {
712
999
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
713
1000
  data
714
1001
  });
715
- logger2.success("pushSuccess", "Data pushed");
1002
+ logger3.success("pushSuccess", "Data pushed");
716
1003
  },
717
1004
  /**
718
1005
  * 推送失败数据的通用方法(私有方法,仅供runStep内部使用)
@@ -725,7 +1012,7 @@ async function createApifyKit() {
725
1012
  const isCrawlerError = CrawlerError.isCrawlerError(error);
726
1013
  const code = isCrawlerError ? error.code : Code.UnknownError;
727
1014
  const context = isCrawlerError ? error.context : {};
728
- const traffic = getTrafficSnapshot();
1015
+ const traffic = await getProxyMeterSnapshot({ finalize: true });
729
1016
  await Actor2.pushData({
730
1017
  // 如果是 CrawlerError,使用其 code,否则使用默认 Failed code
731
1018
  code,
@@ -736,7 +1023,7 @@ async function createApifyKit() {
736
1023
  context,
737
1024
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
738
1025
  });
739
- logger2.success("pushFailed", "Error data pushed");
1026
+ logger3.success("pushFailed", "Error data pushed");
740
1027
  }
741
1028
  };
742
1029
  }
@@ -752,7 +1039,7 @@ var ApifyKit = {
752
1039
  };
753
1040
 
754
1041
  // src/internals/utils.js
755
- var logger3 = createInternalLogger("InternalUtils");
1042
+ var logger4 = createInternalLogger("InternalUtils");
756
1043
  var parseCookies = (cookieString, domain) => {
757
1044
  const cookies = [];
758
1045
  const pairs = cookieString.split(";").map((c) => c.trim());
@@ -770,7 +1057,7 @@ var parseCookies = (cookieString, domain) => {
770
1057
  cookies.push(cookie);
771
1058
  }
772
1059
  }
773
- logger3.success("parseCookies", `parsed ${cookies.length} cookies`);
1060
+ logger4.success("parseCookies", `parsed ${cookies.length} cookies`);
774
1061
  return cookies;
775
1062
  };
776
1063
 
@@ -813,7 +1100,7 @@ var Utils = {
813
1100
  };
814
1101
 
815
1102
  // src/anti-cheat.js
816
- var logger4 = createInternalLogger("AntiCheat");
1103
+ var logger5 = createInternalLogger("AntiCheat");
817
1104
  var BASE_CONFIG = Object.freeze({
818
1105
  locale: "zh-CN",
819
1106
  acceptLanguage: "zh-CN,zh;q=0.9",
@@ -875,7 +1162,7 @@ var AntiCheat = {
875
1162
  // src/humanize.js
876
1163
  var import_delay = __toESM(require("delay"), 1);
877
1164
  var import_ghost_cursor_playwright = require("ghost-cursor-playwright");
878
- var logger5 = createInternalLogger("Humanize");
1165
+ var logger6 = createInternalLogger("Humanize");
879
1166
  var $CursorWeakMap = /* @__PURE__ */ new WeakMap();
880
1167
  function $GetCursor(page) {
881
1168
  const cursor = $CursorWeakMap.get(page);
@@ -903,13 +1190,13 @@ var Humanize = {
903
1190
  */
904
1191
  async initializeCursor(page) {
905
1192
  if ($CursorWeakMap.has(page)) {
906
- logger5.debug("initializeCursor: cursor already exists, skipping");
1193
+ logger6.debug("initializeCursor: cursor already exists, skipping");
907
1194
  return;
908
1195
  }
909
- logger5.start("initializeCursor", "creating cursor");
1196
+ logger6.start("initializeCursor", "creating cursor");
910
1197
  const cursor = await (0, import_ghost_cursor_playwright.createCursor)(page);
911
1198
  $CursorWeakMap.set(page, cursor);
912
- logger5.success("initializeCursor", "cursor initialized");
1199
+ logger6.success("initializeCursor", "cursor initialized");
913
1200
  },
914
1201
  /**
915
1202
  * 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
@@ -919,17 +1206,17 @@ var Humanize = {
919
1206
  */
920
1207
  async humanMove(page, target) {
921
1208
  const cursor = $GetCursor(page);
922
- logger5.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
1209
+ logger6.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
923
1210
  try {
924
1211
  if (typeof target === "string") {
925
1212
  const element = await page.$(target);
926
1213
  if (!element) {
927
- logger5.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
1214
+ logger6.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
928
1215
  return false;
929
1216
  }
930
1217
  const box = await element.boundingBox();
931
1218
  if (!box) {
932
- logger5.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
1219
+ logger6.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
933
1220
  return false;
934
1221
  }
935
1222
  const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;
@@ -945,10 +1232,10 @@ var Humanize = {
945
1232
  await cursor.actions.move({ x, y });
946
1233
  }
947
1234
  }
948
- logger5.success("humanMove");
1235
+ logger6.success("humanMove");
949
1236
  return true;
950
1237
  } catch (error) {
951
- logger5.fail("humanMove", error);
1238
+ logger6.fail("humanMove", error);
952
1239
  throw error;
953
1240
  }
954
1241
  },
@@ -972,12 +1259,12 @@ var Humanize = {
972
1259
  maxDurationMs = maxSteps * 220 + 800
973
1260
  } = options;
974
1261
  const targetDesc = typeof target === "string" ? target : "ElementHandle";
975
- logger5.start("humanScroll", `target=${targetDesc}`);
1262
+ logger6.start("humanScroll", `target=${targetDesc}`);
976
1263
  let element;
977
1264
  if (typeof target === "string") {
978
1265
  element = await page.$(target);
979
1266
  if (!element) {
980
- logger5.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
1267
+ logger6.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
981
1268
  return { element: null, didScroll: false };
982
1269
  }
983
1270
  } else {
@@ -1052,26 +1339,26 @@ var Humanize = {
1052
1339
  try {
1053
1340
  for (let i = 0; i < maxSteps; i++) {
1054
1341
  if (Date.now() - startTime > maxDurationMs) {
1055
- logger5.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
1342
+ logger6.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
1056
1343
  return { element, didScroll };
1057
1344
  }
1058
1345
  const status = await checkVisibility();
1059
1346
  if (status.code === "VISIBLE") {
1060
1347
  if (status.isFixed) {
1061
- logger5.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
1348
+ logger6.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
1062
1349
  } else {
1063
- logger5.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
1350
+ logger6.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
1064
1351
  }
1065
- logger5.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
1352
+ logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
1066
1353
  return { element, didScroll };
1067
1354
  }
1068
- logger5.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
1355
+ logger6.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
1069
1356
  if (status.code === "OBSTRUCTED" && status.obstruction) {
1070
- logger5.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
1357
+ logger6.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
1071
1358
  }
1072
1359
  const scrollRect = await getScrollableRect();
1073
1360
  if (!scrollRect && status.isFixed) {
1074
- logger5.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
1361
+ logger6.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
1075
1362
  return { element, didScroll };
1076
1363
  }
1077
1364
  const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
@@ -1107,10 +1394,10 @@ var Humanize = {
1107
1394
  didScroll = true;
1108
1395
  await (0, import_delay.default)(this.jitterMs(20 + Math.random() * 40, 0.2));
1109
1396
  }
1110
- logger5.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
1397
+ logger6.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
1111
1398
  return { element, didScroll };
1112
1399
  } catch (error) {
1113
- logger5.fail("humanScroll", error);
1400
+ logger6.fail("humanScroll", error);
1114
1401
  throw error;
1115
1402
  }
1116
1403
  },
@@ -1128,7 +1415,7 @@ var Humanize = {
1128
1415
  const cursor = $GetCursor(page);
1129
1416
  const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;
1130
1417
  const targetDesc = target == null ? "Current Position" : typeof target === "string" ? target : "ElementHandle";
1131
- logger5.start("humanClick", `target=${targetDesc}`);
1418
+ logger6.start("humanClick", `target=${targetDesc}`);
1132
1419
  const restoreOnce = async () => {
1133
1420
  if (restoreOnce.restored) return;
1134
1421
  restoreOnce.restored = true;
@@ -1137,14 +1424,14 @@ var Humanize = {
1137
1424
  await (0, import_delay.default)(this.jitterMs(1e3));
1138
1425
  await restoreOnce.do();
1139
1426
  } catch (restoreError) {
1140
- logger5.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
1427
+ logger6.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
1141
1428
  }
1142
1429
  };
1143
1430
  try {
1144
1431
  if (target == null) {
1145
1432
  await (0, import_delay.default)(this.jitterMs(reactionDelay, 0.4));
1146
1433
  await cursor.actions.click();
1147
- logger5.success("humanClick", "Clicked current position");
1434
+ logger6.success("humanClick", "Clicked current position");
1148
1435
  return true;
1149
1436
  }
1150
1437
  let element;
@@ -1154,7 +1441,7 @@ var Humanize = {
1154
1441
  if (throwOnMissing) {
1155
1442
  throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);
1156
1443
  }
1157
- logger5.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
1444
+ logger6.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
1158
1445
  return false;
1159
1446
  }
1160
1447
  } else {
@@ -1170,7 +1457,7 @@ var Humanize = {
1170
1457
  if (throwOnMissing) {
1171
1458
  throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
1172
1459
  }
1173
- logger5.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
1460
+ logger6.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
1174
1461
  return false;
1175
1462
  }
1176
1463
  const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
@@ -1179,11 +1466,11 @@ var Humanize = {
1179
1466
  await (0, import_delay.default)(this.jitterMs(reactionDelay, 0.4));
1180
1467
  await cursor.actions.click();
1181
1468
  await restoreOnce();
1182
- logger5.success("humanClick");
1469
+ logger6.success("humanClick");
1183
1470
  return true;
1184
1471
  } catch (error) {
1185
1472
  await restoreOnce();
1186
- logger5.fail("humanClick", error);
1473
+ logger6.fail("humanClick", error);
1187
1474
  throw error;
1188
1475
  }
1189
1476
  },
@@ -1194,9 +1481,9 @@ var Humanize = {
1194
1481
  */
1195
1482
  async randomSleep(baseMs, jitterPercent = 0.3) {
1196
1483
  const ms = this.jitterMs(baseMs, jitterPercent);
1197
- logger5.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
1484
+ logger6.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
1198
1485
  await (0, import_delay.default)(ms);
1199
- logger5.success("randomSleep");
1486
+ logger6.success("randomSleep");
1200
1487
  },
1201
1488
  /**
1202
1489
  * 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
@@ -1206,7 +1493,7 @@ var Humanize = {
1206
1493
  async simulateGaze(page, baseDurationMs = 2500) {
1207
1494
  const cursor = $GetCursor(page);
1208
1495
  const durationMs = this.jitterMs(baseDurationMs, 0.4);
1209
- logger5.start("simulateGaze", `duration=${durationMs}ms`);
1496
+ logger6.start("simulateGaze", `duration=${durationMs}ms`);
1210
1497
  const startTime = Date.now();
1211
1498
  const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
1212
1499
  while (Date.now() - startTime < durationMs) {
@@ -1215,7 +1502,7 @@ var Humanize = {
1215
1502
  await cursor.actions.move({ x, y });
1216
1503
  await (0, import_delay.default)(this.jitterMs(600, 0.5));
1217
1504
  }
1218
- logger5.success("simulateGaze");
1505
+ logger6.success("simulateGaze");
1219
1506
  },
1220
1507
  /**
1221
1508
  * 人类化输入 - 带节奏变化(快-慢-停顿-偶尔加速)
@@ -1228,7 +1515,7 @@ var Humanize = {
1228
1515
  * @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
1229
1516
  */
1230
1517
  async humanType(page, selector, text, options = {}) {
1231
- logger5.start("humanType", `selector=${selector}, textLen=${text.length}`);
1518
+ logger6.start("humanType", `selector=${selector}, textLen=${text.length}`);
1232
1519
  const {
1233
1520
  baseDelay = 180,
1234
1521
  pauseProbability = 0.08,
@@ -1252,13 +1539,13 @@ var Humanize = {
1252
1539
  await (0, import_delay.default)(charDelay);
1253
1540
  if (Math.random() < pauseProbability && i < text.length - 1) {
1254
1541
  const pauseTime = this.jitterMs(pauseBase, 0.5);
1255
- logger5.debug(`\u505C\u987F ${pauseTime}ms...`);
1542
+ logger6.debug(`\u505C\u987F ${pauseTime}ms...`);
1256
1543
  await (0, import_delay.default)(pauseTime);
1257
1544
  }
1258
1545
  }
1259
- logger5.success("humanType");
1546
+ logger6.success("humanType");
1260
1547
  } catch (error) {
1261
- logger5.fail("humanType", error);
1548
+ logger6.fail("humanType", error);
1262
1549
  throw error;
1263
1550
  }
1264
1551
  },
@@ -1268,22 +1555,22 @@ var Humanize = {
1268
1555
  * @param {string} selector - 输入框选择器
1269
1556
  */
1270
1557
  async humanClear(page, selector) {
1271
- logger5.start("humanClear", `selector=${selector}`);
1558
+ logger6.start("humanClear", `selector=${selector}`);
1272
1559
  try {
1273
1560
  const locator = page.locator(selector);
1274
1561
  await locator.click();
1275
1562
  await (0, import_delay.default)(this.jitterMs(200, 0.4));
1276
1563
  const currentValue = await locator.inputValue();
1277
1564
  if (!currentValue || currentValue.length === 0) {
1278
- logger5.success("humanClear", "already empty");
1565
+ logger6.success("humanClear", "already empty");
1279
1566
  return;
1280
1567
  }
1281
1568
  await page.keyboard.press("Meta+A");
1282
1569
  await (0, import_delay.default)(this.jitterMs(100, 0.4));
1283
1570
  await page.keyboard.press("Backspace");
1284
- logger5.success("humanClear");
1571
+ logger6.success("humanClear");
1285
1572
  } catch (error) {
1286
- logger5.fail("humanClear", error);
1573
+ logger6.fail("humanClear", error);
1287
1574
  throw error;
1288
1575
  }
1289
1576
  },
@@ -1295,7 +1582,7 @@ var Humanize = {
1295
1582
  async warmUpBrowsing(page, baseDuration = 3500) {
1296
1583
  const cursor = $GetCursor(page);
1297
1584
  const durationMs = this.jitterMs(baseDuration, 0.4);
1298
- logger5.start("warmUpBrowsing", `duration=${durationMs}ms`);
1585
+ logger6.start("warmUpBrowsing", `duration=${durationMs}ms`);
1299
1586
  const startTime = Date.now();
1300
1587
  const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
1301
1588
  try {
@@ -1314,9 +1601,9 @@ var Humanize = {
1314
1601
  await (0, import_delay.default)(this.jitterMs(800, 0.5));
1315
1602
  }
1316
1603
  }
1317
- logger5.success("warmUpBrowsing");
1604
+ logger6.success("warmUpBrowsing");
1318
1605
  } catch (error) {
1319
- logger5.fail("warmUpBrowsing", error);
1606
+ logger6.fail("warmUpBrowsing", error);
1320
1607
  throw error;
1321
1608
  }
1322
1609
  },
@@ -1330,7 +1617,7 @@ var Humanize = {
1330
1617
  async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
1331
1618
  const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
1332
1619
  const actualDistance = this.jitterMs(distance, 0.15);
1333
- logger5.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
1620
+ logger6.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
1334
1621
  const sign = direction === "down" ? 1 : -1;
1335
1622
  const stepDistance = actualDistance / steps;
1336
1623
  try {
@@ -1342,9 +1629,9 @@ var Humanize = {
1342
1629
  const baseDelay = 60 + i * 25;
1343
1630
  await (0, import_delay.default)(this.jitterMs(baseDelay, 0.3));
1344
1631
  }
1345
- logger5.success("naturalScroll");
1632
+ logger6.success("naturalScroll");
1346
1633
  } catch (error) {
1347
- logger5.fail("naturalScroll", error);
1634
+ logger6.fail("naturalScroll", error);
1348
1635
  throw error;
1349
1636
  }
1350
1637
  }
@@ -1393,690 +1680,6 @@ var findMatchedByPassRule = (rules = [], requestUrl = "") => {
1393
1680
  hostname
1394
1681
  };
1395
1682
  };
1396
- var resolveRouteByProxy = ({
1397
- requestUrl = "",
1398
- enableProxy = false,
1399
- byPassRules = []
1400
- }) => {
1401
- if (!enableProxy) {
1402
- return { route: "direct", matchedRule: null, hostname: "" };
1403
- }
1404
- const matched = findMatchedByPassRule(byPassRules, requestUrl);
1405
- if (!matched) {
1406
- return { route: "proxy", matchedRule: null, hostname: "" };
1407
- }
1408
- if (matched.rule) {
1409
- return { route: "direct", matchedRule: matched.rule, hostname: matched.hostname };
1410
- }
1411
- return { route: "proxy", matchedRule: null, hostname: matched.hostname };
1412
- };
1413
-
1414
- // src/traffic-meter.js
1415
- var logger6 = createInternalLogger("TrafficMeter");
1416
- var encoder = new TextEncoder();
1417
- var MAX_DOMAIN_BUCKETS = 160;
1418
- var MAX_REASON_BUCKETS = 64;
1419
- var MAX_TOP_ITEMS = 12;
1420
- var MAX_HINT_ITEMS = 8;
1421
- var UNKNOWN_DOMAIN = "(unknown)";
1422
- var OTHER_DOMAINS = "(other-domains)";
1423
- var OTHER_REASONS = "(other-reasons)";
1424
- var STATIC_RESOURCE_TYPES = /* @__PURE__ */ new Set([
1425
- "script",
1426
- "stylesheet",
1427
- "image",
1428
- "font",
1429
- "media",
1430
- "manifest"
1431
- ]);
1432
- var BACKEND_RESOURCE_TYPES = /* @__PURE__ */ new Set([
1433
- "xhr",
1434
- "fetch",
1435
- "websocket",
1436
- "eventsource"
1437
- ]);
1438
- var toSafeNumber = (value) => {
1439
- if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return 0;
1440
- return Math.round(value);
1441
- };
1442
- var byteLength = (value) => {
1443
- const text = String(value || "");
1444
- if (!text) return 0;
1445
- try {
1446
- return encoder.encode(text).length;
1447
- } catch {
1448
- return text.length;
1449
- }
1450
- };
1451
- var normalizeHeaderValue = (value) => {
1452
- if (Array.isArray(value)) return value.join(",");
1453
- if (value === null || value === void 0) return "";
1454
- return String(value);
1455
- };
1456
- var estimateRequestBytes = (request = {}) => {
1457
- const method = String(request.method || "GET");
1458
- const url = String(request.url || "");
1459
- let total = byteLength(`${method} ${url} HTTP/1.1\r
1460
- `);
1461
- const headers = request.headers && typeof request.headers === "object" ? request.headers : {};
1462
- Object.entries(headers).forEach(([key, value]) => {
1463
- total += byteLength(`${key}: ${normalizeHeaderValue(value)}\r
1464
- `);
1465
- });
1466
- total += 2;
1467
- if (typeof request.postData === "string" && request.postData) {
1468
- total += byteLength(request.postData);
1469
- }
1470
- return total;
1471
- };
1472
- var createTrafficState = () => ({
1473
- totalRequests: 0,
1474
- proxyRequests: 0,
1475
- directRequests: 0,
1476
- totalUploadBytes: 0,
1477
- proxyUploadBytes: 0,
1478
- directUploadBytes: 0,
1479
- totalDownloadBytes: 0,
1480
- proxyDownloadBytes: 0,
1481
- directDownloadBytes: 0,
1482
- totalFailedRequests: 0,
1483
- proxyFailedRequests: 0,
1484
- directFailedRequests: 0,
1485
- totalCanceledRequests: 0,
1486
- proxyCanceledRequests: 0,
1487
- directCanceledRequests: 0,
1488
- orphanDataReceivedBytes: 0,
1489
- orphanProxyDataReceivedBytes: 0,
1490
- orphanFinishDeltaBytes: 0,
1491
- orphanProxyFinishDeltaBytes: 0,
1492
- domainStats: /* @__PURE__ */ new Map(),
1493
- typeStats: /* @__PURE__ */ new Map(),
1494
- failedReasonStats: /* @__PURE__ */ new Map()
1495
- });
1496
- var ensureRoute = (route) => route === "proxy" ? "proxy" : "direct";
1497
- var normalizeResourceType = (value) => {
1498
- const type = String(value || "").trim().toLowerCase();
1499
- if (!type) return "other";
1500
- if (type === "ws") return "websocket";
1501
- return type;
1502
- };
1503
- var parseHostname = (url = "") => {
1504
- try {
1505
- const hostname = new URL(String(url || "")).hostname.toLowerCase();
1506
- return hostname || "";
1507
- } catch {
1508
- return "";
1509
- }
1510
- };
1511
- var normalizeDomainKey = (domain = "") => {
1512
- const key = String(domain || "").trim().toLowerCase();
1513
- return key || UNKNOWN_DOMAIN;
1514
- };
1515
- var isStaticType = (resourceType = "") => STATIC_RESOURCE_TYPES.has(normalizeResourceType(resourceType));
1516
- var isBackendType = (resourceType = "") => BACKEND_RESOURCE_TYPES.has(normalizeResourceType(resourceType));
1517
- var createDomainBucket = (domain) => ({
1518
- domain,
1519
- requests: 0,
1520
- proxyRequests: 0,
1521
- directRequests: 0,
1522
- uploadBytes: 0,
1523
- downloadBytes: 0,
1524
- totalBytes: 0,
1525
- proxyBytes: 0,
1526
- directBytes: 0,
1527
- failedRequests: 0,
1528
- canceledRequests: 0,
1529
- staticBytes: 0,
1530
- backendBytes: 0
1531
- });
1532
- var createTypeBucket = (resourceType) => ({
1533
- resourceType,
1534
- requests: 0,
1535
- proxyRequests: 0,
1536
- directRequests: 0,
1537
- uploadBytes: 0,
1538
- downloadBytes: 0,
1539
- totalBytes: 0,
1540
- proxyBytes: 0,
1541
- directBytes: 0,
1542
- failedRequests: 0,
1543
- canceledRequests: 0
1544
- });
1545
- var createReasonBucket = (reason) => ({
1546
- reason,
1547
- count: 0,
1548
- canceledCount: 0,
1549
- proxyCount: 0,
1550
- directCount: 0
1551
- });
1552
- var formatBytes = (bytes = 0) => {
1553
- const value = toSafeNumber(bytes);
1554
- if (value <= 0) return "0B";
1555
- const units = ["B", "KB", "MB", "GB", "TB"];
1556
- let size = value;
1557
- let unit = 0;
1558
- while (size >= 1024 && unit < units.length - 1) {
1559
- size /= 1024;
1560
- unit += 1;
1561
- }
1562
- const precision = size >= 100 || unit === 0 ? 0 : 2;
1563
- return `${size.toFixed(precision)}${units[unit]}`;
1564
- };
1565
- var addRequests = (state, route, count = 1) => {
1566
- const c = toSafeNumber(count);
1567
- if (c <= 0) return;
1568
- const normalizedRoute = ensureRoute(route);
1569
- state.totalRequests += c;
1570
- if (normalizedRoute === "proxy") {
1571
- state.proxyRequests += c;
1572
- return;
1573
- }
1574
- state.directRequests += c;
1575
- };
1576
- var addUploadBytes = (state, route, bytes = 0) => {
1577
- const b = toSafeNumber(bytes);
1578
- if (b <= 0) return;
1579
- const normalizedRoute = ensureRoute(route);
1580
- state.totalUploadBytes += b;
1581
- if (normalizedRoute === "proxy") {
1582
- state.proxyUploadBytes += b;
1583
- return;
1584
- }
1585
- state.directUploadBytes += b;
1586
- };
1587
- var addDownloadBytes = (state, route, bytes = 0) => {
1588
- const b = toSafeNumber(bytes);
1589
- if (b <= 0) return;
1590
- const normalizedRoute = ensureRoute(route);
1591
- state.totalDownloadBytes += b;
1592
- if (normalizedRoute === "proxy") {
1593
- state.proxyDownloadBytes += b;
1594
- return;
1595
- }
1596
- state.directDownloadBytes += b;
1597
- };
1598
- var incrementBucketRequests = (bucket, route) => {
1599
- if (!bucket) return;
1600
- bucket.requests += 1;
1601
- if (ensureRoute(route) === "proxy") {
1602
- bucket.proxyRequests += 1;
1603
- return;
1604
- }
1605
- bucket.directRequests += 1;
1606
- };
1607
- var incrementBucketBytes = (bucket, route, bytes = 0, direction = "download", resourceType = "other") => {
1608
- if (!bucket) return;
1609
- const b = toSafeNumber(bytes);
1610
- if (b <= 0) return;
1611
- if (direction === "upload") {
1612
- bucket.uploadBytes += b;
1613
- } else {
1614
- bucket.downloadBytes += b;
1615
- }
1616
- bucket.totalBytes += b;
1617
- if (ensureRoute(route) === "proxy") {
1618
- bucket.proxyBytes += b;
1619
- } else {
1620
- bucket.directBytes += b;
1621
- }
1622
- if (bucket.domain !== void 0) {
1623
- if (isStaticType(resourceType)) {
1624
- bucket.staticBytes += b;
1625
- } else if (isBackendType(resourceType)) {
1626
- bucket.backendBytes += b;
1627
- }
1628
- }
1629
- };
1630
- var incrementBucketFailed = (bucket, canceled = false) => {
1631
- if (!bucket) return;
1632
- bucket.failedRequests += 1;
1633
- if (canceled) {
1634
- bucket.canceledRequests += 1;
1635
- }
1636
- };
1637
- var ensureReasonText = (reason) => {
1638
- const normalized = String(reason || "").trim().toLowerCase();
1639
- return normalized || "unknown";
1640
- };
1641
- var pickDomainBucket = (state, domain = "") => {
1642
- const domainKey = normalizeDomainKey(domain);
1643
- const knownBucket = state.domainStats.get(domainKey);
1644
- if (knownBucket) return knownBucket;
1645
- if (state.domainStats.size < MAX_DOMAIN_BUCKETS) {
1646
- const bucket2 = createDomainBucket(domainKey);
1647
- state.domainStats.set(domainKey, bucket2);
1648
- return bucket2;
1649
- }
1650
- const overflow = state.domainStats.get(OTHER_DOMAINS);
1651
- if (overflow) return overflow;
1652
- const bucket = createDomainBucket(OTHER_DOMAINS);
1653
- state.domainStats.set(OTHER_DOMAINS, bucket);
1654
- return bucket;
1655
- };
1656
- var pickTypeBucket = (state, resourceType = "other") => {
1657
- const typeKey = normalizeResourceType(resourceType);
1658
- const knownBucket = state.typeStats.get(typeKey);
1659
- if (knownBucket) return knownBucket;
1660
- const bucket = createTypeBucket(typeKey);
1661
- state.typeStats.set(typeKey, bucket);
1662
- return bucket;
1663
- };
1664
- var pickReasonBucket = (state, reason = "") => {
1665
- const reasonKey = ensureReasonText(reason);
1666
- const knownBucket = state.failedReasonStats.get(reasonKey);
1667
- if (knownBucket) return knownBucket;
1668
- if (state.failedReasonStats.size < MAX_REASON_BUCKETS) {
1669
- const bucket2 = createReasonBucket(reasonKey);
1670
- state.failedReasonStats.set(reasonKey, bucket2);
1671
- return bucket2;
1672
- }
1673
- const overflow = state.failedReasonStats.get(OTHER_REASONS);
1674
- if (overflow) return overflow;
1675
- const bucket = createReasonBucket(OTHER_REASONS);
1676
- state.failedReasonStats.set(OTHER_REASONS, bucket);
1677
- return bucket;
1678
- };
1679
- var addRequestProfile = (state, route, domain, resourceType, uploadBytes = 0) => {
1680
- const domainBucket = pickDomainBucket(state, domain);
1681
- const typeBucket = pickTypeBucket(state, resourceType);
1682
- incrementBucketRequests(domainBucket, route);
1683
- incrementBucketRequests(typeBucket, route);
1684
- incrementBucketBytes(domainBucket, route, uploadBytes, "upload", resourceType);
1685
- incrementBucketBytes(typeBucket, route, uploadBytes, "upload", resourceType);
1686
- };
1687
- var addUploadProfile = (state, route, domain, resourceType, uploadBytes = 0) => {
1688
- const domainBucket = pickDomainBucket(state, domain);
1689
- const typeBucket = pickTypeBucket(state, resourceType);
1690
- incrementBucketBytes(domainBucket, route, uploadBytes, "upload", resourceType);
1691
- incrementBucketBytes(typeBucket, route, uploadBytes, "upload", resourceType);
1692
- };
1693
- var addDownloadProfile = (state, route, domain, resourceType, downloadBytes = 0) => {
1694
- const domainBucket = pickDomainBucket(state, domain);
1695
- const typeBucket = pickTypeBucket(state, resourceType);
1696
- incrementBucketBytes(domainBucket, route, downloadBytes, "download", resourceType);
1697
- incrementBucketBytes(typeBucket, route, downloadBytes, "download", resourceType);
1698
- };
1699
- var addFailedProfile = (state, route, domain, resourceType, reason = "unknown", canceled = false) => {
1700
- const domainBucket = pickDomainBucket(state, domain);
1701
- const typeBucket = pickTypeBucket(state, resourceType);
1702
- const reasonBucket = pickReasonBucket(state, reason);
1703
- incrementBucketFailed(domainBucket, canceled);
1704
- incrementBucketFailed(typeBucket, canceled);
1705
- reasonBucket.count += 1;
1706
- if (ensureRoute(route) === "proxy") {
1707
- reasonBucket.proxyCount += 1;
1708
- } else {
1709
- reasonBucket.directCount += 1;
1710
- }
1711
- if (canceled) {
1712
- reasonBucket.canceledCount += 1;
1713
- }
1714
- };
1715
- var toRoundedRatio = (numerator, denominator) => {
1716
- if (denominator <= 0) return 0;
1717
- return Number((numerator / denominator * 100).toFixed(2));
1718
- };
1719
- var sortByBytesAndRequests = (left, right) => {
1720
- if (right.totalBytes !== left.totalBytes) return right.totalBytes - left.totalBytes;
1721
- if (right.requests !== left.requests) return right.requests - left.requests;
1722
- return String(left.domain || left.resourceType || "").localeCompare(String(right.domain || right.resourceType || ""));
1723
- };
1724
- var buildTopDomains = (state) => {
1725
- return Array.from(state.domainStats.values()).filter((item) => item && item.totalBytes > 0).sort(sortByBytesAndRequests).slice(0, MAX_TOP_ITEMS).map((item) => ({
1726
- domain: item.domain,
1727
- requests: item.requests,
1728
- proxyRequests: item.proxyRequests,
1729
- directRequests: item.directRequests,
1730
- uploadBytes: item.uploadBytes,
1731
- downloadBytes: item.downloadBytes,
1732
- totalBytes: item.totalBytes,
1733
- proxyBytes: item.proxyBytes,
1734
- directBytes: item.directBytes,
1735
- failedRequests: item.failedRequests,
1736
- canceledRequests: item.canceledRequests,
1737
- staticBytes: item.staticBytes,
1738
- backendBytes: item.backendBytes
1739
- }));
1740
- };
1741
- var buildTopResourceTypes = (state) => {
1742
- return Array.from(state.typeStats.values()).filter((item) => item && (item.totalBytes > 0 || item.requests > 0)).sort(sortByBytesAndRequests).slice(0, MAX_TOP_ITEMS).map((item) => ({
1743
- resourceType: item.resourceType,
1744
- requests: item.requests,
1745
- proxyRequests: item.proxyRequests,
1746
- directRequests: item.directRequests,
1747
- uploadBytes: item.uploadBytes,
1748
- downloadBytes: item.downloadBytes,
1749
- totalBytes: item.totalBytes,
1750
- proxyBytes: item.proxyBytes,
1751
- directBytes: item.directBytes,
1752
- failedRequests: item.failedRequests,
1753
- canceledRequests: item.canceledRequests
1754
- }));
1755
- };
1756
- var buildFailedReasons = (state) => {
1757
- return Array.from(state.failedReasonStats.values()).filter((item) => item && item.count > 0).sort((left, right) => {
1758
- if (right.count !== left.count) return right.count - left.count;
1759
- return String(left.reason || "").localeCompare(String(right.reason || ""));
1760
- }).slice(0, MAX_TOP_ITEMS).map((item) => ({
1761
- reason: item.reason,
1762
- count: item.count,
1763
- canceledCount: item.canceledCount,
1764
- proxyCount: item.proxyCount,
1765
- directCount: item.directCount
1766
- }));
1767
- };
1768
- var buildProxyByPassHints = (state) => {
1769
- return Array.from(state.domainStats.values()).filter((item) => item && item.domain !== UNKNOWN_DOMAIN && item.domain !== OTHER_DOMAINS).filter((item) => item.proxyBytes >= 128 * 1024 && item.proxyRequests >= 2 && item.totalBytes > 0).filter((item) => item.staticBytes > item.backendBytes && toRoundedRatio(item.staticBytes, item.totalBytes) >= 80).sort((left, right) => {
1770
- if (right.proxyBytes !== left.proxyBytes) return right.proxyBytes - left.proxyBytes;
1771
- return right.proxyRequests - left.proxyRequests;
1772
- }).slice(0, MAX_HINT_ITEMS).map((item) => ({
1773
- domain: item.domain,
1774
- proxyBytes: item.proxyBytes,
1775
- proxyRequests: item.proxyRequests,
1776
- totalBytes: item.totalBytes,
1777
- staticBytes: item.staticBytes,
1778
- backendBytes: item.backendBytes,
1779
- staticRatioPct: toRoundedRatio(item.staticBytes, item.totalBytes)
1780
- }));
1781
- };
1782
- var createTrafficMeter = ({
1783
- enableProxy = false,
1784
- byPassRules = [],
1785
- debugMode = false
1786
- } = {}) => {
1787
- const state = createTrafficState();
1788
- const requestMap = /* @__PURE__ */ new Map();
1789
- const orphanReceivedMap = /* @__PURE__ */ new Map();
1790
- const wsRouteMap = /* @__PURE__ */ new Map();
1791
- const attachedPages = /* @__PURE__ */ new WeakSet();
1792
- const attachedContexts = /* @__PURE__ */ new WeakSet();
1793
- const resolveRoute = (url = "") => {
1794
- return resolveRouteByProxy({
1795
- requestUrl: url,
1796
- enableProxy,
1797
- byPassRules
1798
- }).route;
1799
- };
1800
- const fallbackRoute = () => enableProxy ? "proxy" : "direct";
1801
- const debugLog = (message) => {
1802
- if (!debugMode) return;
1803
- logger6.info(`[\u9010\u8BF7\u6C42\u8C03\u8BD5] ${message}`);
1804
- };
1805
- const addFailed = (route, canceled = false) => {
1806
- const normalizedRoute = ensureRoute(route);
1807
- state.totalFailedRequests += 1;
1808
- if (normalizedRoute === "proxy") {
1809
- state.proxyFailedRequests += 1;
1810
- } else {
1811
- state.directFailedRequests += 1;
1812
- }
1813
- if (!canceled) return;
1814
- state.totalCanceledRequests += 1;
1815
- if (normalizedRoute === "proxy") {
1816
- state.proxyCanceledRequests += 1;
1817
- } else {
1818
- state.directCanceledRequests += 1;
1819
- }
1820
- };
1821
- const finalizeByEncodedLength = (requestId, encodedDataLength, source = "finished") => {
1822
- const safeRequestId = String(requestId || "");
1823
- if (!safeRequestId) return;
1824
- const requestState = requestMap.get(safeRequestId);
1825
- const orphanReceived = toSafeNumber(orphanReceivedMap.get(safeRequestId));
1826
- const encoded = toSafeNumber(encodedDataLength);
1827
- if (requestState) {
1828
- const routed2 = ensureRoute(requestState.route);
1829
- const downloaded = toSafeNumber(requestState.downloadBytes);
1830
- const delta2 = Math.max(0, encoded - downloaded);
1831
- if (delta2 > 0) {
1832
- addDownloadBytes(state, routed2, delta2);
1833
- addDownloadProfile(state, routed2, requestState.domain, requestState.resourceType, delta2);
1834
- requestState.downloadBytes = downloaded + delta2;
1835
- }
1836
- const uploadBytes = toSafeNumber(requestState.uploadBytes);
1837
- const total = uploadBytes + toSafeNumber(requestState.downloadBytes);
1838
- debugLog(
1839
- `final id=${safeRequestId} source=${source} status=ok route=${routed2} type=${requestState.resourceType || "other"} upload=${formatBytes(uploadBytes)} (${uploadBytes}) download=${formatBytes(requestState.downloadBytes)} (${requestState.downloadBytes}) total=${formatBytes(total)} (${total}) url=${requestState.url || "-"}`
1840
- );
1841
- requestMap.delete(safeRequestId);
1842
- orphanReceivedMap.delete(safeRequestId);
1843
- return;
1844
- }
1845
- const routed = fallbackRoute();
1846
- const delta = Math.max(0, encoded - orphanReceived);
1847
- if (delta > 0) {
1848
- addDownloadBytes(state, routed, delta);
1849
- addDownloadProfile(state, routed, UNKNOWN_DOMAIN, "other", delta);
1850
- }
1851
- state.orphanFinishDeltaBytes += delta;
1852
- if (routed === "proxy") {
1853
- state.orphanProxyFinishDeltaBytes += delta;
1854
- }
1855
- debugLog(
1856
- `final id=${safeRequestId} source=${source} status=orphan route=${routed} encoded=${formatBytes(encoded)} (${encoded}) delta=${formatBytes(delta)} (${delta})`
1857
- );
1858
- orphanReceivedMap.delete(safeRequestId);
1859
- };
1860
- const recordRequest = (params = {}) => {
1861
- const requestId = String(params.requestId || "");
1862
- const request = params.request && typeof params.request === "object" ? params.request : {};
1863
- const url = String(request.url || "");
1864
- const route = resolveRoute(url);
1865
- const resourceType = normalizeResourceType(params.type || request.type || "other");
1866
- const domain = normalizeDomainKey(parseHostname(url));
1867
- if (requestId && requestMap.has(requestId)) {
1868
- const redirectResponse = params.redirectResponse && typeof params.redirectResponse === "object" ? params.redirectResponse : null;
1869
- finalizeByEncodedLength(
1870
- requestId,
1871
- redirectResponse ? redirectResponse.encodedDataLength : 0,
1872
- "redirect"
1873
- );
1874
- }
1875
- addRequests(state, route, 1);
1876
- const uploadBytes = estimateRequestBytes(request);
1877
- addUploadBytes(state, route, uploadBytes);
1878
- addRequestProfile(state, route, domain, resourceType, uploadBytes);
1879
- if (requestId) {
1880
- requestMap.set(requestId, {
1881
- route: ensureRoute(route),
1882
- resourceType,
1883
- domain,
1884
- url,
1885
- uploadBytes,
1886
- downloadBytes: 0
1887
- });
1888
- }
1889
- debugLog(
1890
- `request id=${requestId || "-"} route=${route} type=${resourceType} upload=${formatBytes(uploadBytes)} (${uploadBytes}) method=${String(request.method || "GET")} url=${url || "-"}`
1891
- );
1892
- };
1893
- const recordDataReceived = (params = {}) => {
1894
- const requestId = String(params.requestId || "");
1895
- const bytes = toSafeNumber(params.encodedDataLength);
1896
- if (bytes <= 0) return;
1897
- if (!requestId) {
1898
- const routed2 = fallbackRoute();
1899
- addDownloadBytes(state, routed2, bytes);
1900
- addDownloadProfile(state, routed2, UNKNOWN_DOMAIN, "other", bytes);
1901
- state.orphanDataReceivedBytes += bytes;
1902
- if (routed2 === "proxy") {
1903
- state.orphanProxyDataReceivedBytes += bytes;
1904
- }
1905
- return;
1906
- }
1907
- const requestState = requestMap.get(requestId);
1908
- if (requestState) {
1909
- requestState.downloadBytes = toSafeNumber(requestState.downloadBytes) + bytes;
1910
- addDownloadBytes(state, requestState.route, bytes);
1911
- addDownloadProfile(state, requestState.route, requestState.domain, requestState.resourceType, bytes);
1912
- return;
1913
- }
1914
- const prev = toSafeNumber(orphanReceivedMap.get(requestId));
1915
- orphanReceivedMap.set(requestId, prev + bytes);
1916
- const routed = fallbackRoute();
1917
- addDownloadBytes(state, routed, bytes);
1918
- addDownloadProfile(state, routed, UNKNOWN_DOMAIN, "other", bytes);
1919
- state.orphanDataReceivedBytes += bytes;
1920
- if (routed === "proxy") {
1921
- state.orphanProxyDataReceivedBytes += bytes;
1922
- }
1923
- };
1924
- const recordLoadingFinished = (params = {}) => {
1925
- finalizeByEncodedLength(params.requestId, params.encodedDataLength, "loadingFinished");
1926
- };
1927
- const recordRequestFailed = (params = {}) => {
1928
- const requestId = String(params.requestId || "");
1929
- const requestState = requestId ? requestMap.get(requestId) : null;
1930
- const canceled = Boolean(params.canceled);
1931
- const reason = ensureReasonText(params.errorText);
1932
- const routed = ensureRoute(requestState?.route || fallbackRoute());
1933
- const resourceType = normalizeResourceType(requestState?.resourceType || "other");
1934
- const domain = normalizeDomainKey(requestState?.domain || "");
1935
- if (requestState) {
1936
- addFailed(routed, canceled);
1937
- addFailedProfile(state, routed, domain, resourceType, reason, canceled);
1938
- const uploadBytes = toSafeNumber(requestState.uploadBytes);
1939
- const downloadBytes = toSafeNumber(requestState.downloadBytes);
1940
- const totalBytes = uploadBytes + downloadBytes;
1941
- debugLog(
1942
- `final id=${requestId || "-"} source=loadingFailed status=failed route=${routed} type=${requestState.resourceType || "other"} upload=${formatBytes(uploadBytes)} (${uploadBytes}) download=${formatBytes(downloadBytes)} (${downloadBytes}) total=${formatBytes(totalBytes)} (${totalBytes}) canceled=${canceled} reason=${reason} url=${requestState.url || "-"}`
1943
- );
1944
- } else {
1945
- const orphanDownload = toSafeNumber(orphanReceivedMap.get(requestId));
1946
- addFailed(routed, canceled);
1947
- addFailedProfile(state, routed, UNKNOWN_DOMAIN, "other", reason, canceled);
1948
- debugLog(
1949
- `final id=${requestId || "-"} source=loadingFailed status=orphan-failed route=${routed} upload=0B (0) download=${formatBytes(orphanDownload)} (${orphanDownload}) total=${formatBytes(orphanDownload)} (${orphanDownload}) canceled=${canceled} reason=${reason} url=-`
1950
- );
1951
- }
1952
- if (requestId) {
1953
- requestMap.delete(requestId);
1954
- orphanReceivedMap.delete(requestId);
1955
- }
1956
- };
1957
- const bindWebSocketRoute = (params = {}) => {
1958
- const requestId = String(params.requestId || "");
1959
- if (!requestId) return;
1960
- const url = String(params.url || "");
1961
- const route = resolveRoute(url);
1962
- wsRouteMap.set(requestId, { route, url, domain: normalizeDomainKey(parseHostname(url)) });
1963
- };
1964
- const clearWebSocketRoute = (params = {}) => {
1965
- const requestId = String(params.requestId || "");
1966
- if (!requestId) return;
1967
- wsRouteMap.delete(requestId);
1968
- };
1969
- const getWebSocketMeta = (requestId = "") => {
1970
- if (!requestId) return { route: fallbackRoute(), url: "", domain: UNKNOWN_DOMAIN };
1971
- const meta = wsRouteMap.get(requestId);
1972
- if (!meta || typeof meta !== "object") {
1973
- return { route: fallbackRoute(), url: "", domain: UNKNOWN_DOMAIN };
1974
- }
1975
- return {
1976
- route: ensureRoute(meta.route),
1977
- url: String(meta.url || ""),
1978
- domain: normalizeDomainKey(meta.domain)
1979
- };
1980
- };
1981
- const recordWebSocketFrameSent = (params = {}) => {
1982
- const requestId = String(params.requestId || "");
1983
- const { route, url, domain } = getWebSocketMeta(requestId);
1984
- const payload = params.response && typeof params.response === "object" ? params.response.payloadData : "";
1985
- const bytes = byteLength(payload || "");
1986
- addUploadBytes(state, route, bytes);
1987
- addUploadProfile(state, route, domain, "websocket", bytes);
1988
- debugLog(`ws-send id=${requestId || "-"} route=${route} bytes=${formatBytes(bytes)} (${bytes}) url=${url || "-"}`);
1989
- };
1990
- const recordWebSocketFrameReceived = (params = {}) => {
1991
- const requestId = String(params.requestId || "");
1992
- const { route, url, domain } = getWebSocketMeta(requestId);
1993
- const payload = params.response && typeof params.response === "object" ? params.response.payloadData : "";
1994
- const bytes = byteLength(payload || "");
1995
- addDownloadBytes(state, route, bytes);
1996
- addDownloadProfile(state, route, domain, "websocket", bytes);
1997
- debugLog(`ws-recv id=${requestId || "-"} route=${route} bytes=${formatBytes(bytes)} (${bytes}) url=${url || "-"}`);
1998
- };
1999
- const attachPage = async (page) => {
2000
- if (!page || typeof page.context !== "function") return;
2001
- if (attachedPages.has(page)) return;
2002
- attachedPages.add(page);
2003
- try {
2004
- const context = page.context();
2005
- if (!context || typeof context.newCDPSession !== "function") {
2006
- return;
2007
- }
2008
- if (!attachedContexts.has(context) && typeof context.on === "function") {
2009
- attachedContexts.add(context);
2010
- context.on("page", (nextPage) => {
2011
- if (!nextPage) return;
2012
- attachPage(nextPage).catch((error) => {
2013
- logger6.warn(`\u5B50\u9875\u9762 CDP \u76D1\u542C\u6CE8\u518C\u5931\u8D25: ${error?.message || error}`);
2014
- });
2015
- });
2016
- }
2017
- const session = await context.newCDPSession(page);
2018
- await session.send("Network.enable");
2019
- session.on("Network.requestWillBeSent", recordRequest);
2020
- session.on("Network.dataReceived", recordDataReceived);
2021
- session.on("Network.loadingFinished", recordLoadingFinished);
2022
- session.on("Network.loadingFailed", recordRequestFailed);
2023
- session.on("Network.webSocketCreated", bindWebSocketRoute);
2024
- session.on("Network.webSocketClosed", clearWebSocketRoute);
2025
- session.on("Network.webSocketFrameSent", recordWebSocketFrameSent);
2026
- session.on("Network.webSocketFrameReceived", recordWebSocketFrameReceived);
2027
- debugLog("CDP \u76D1\u542C\u5DF2\u6CE8\u518C");
2028
- } catch (error) {
2029
- logger6.warn(`CDP \u76D1\u542C\u6CE8\u518C\u5931\u8D25: ${error?.message || error}`);
2030
- }
2031
- };
2032
- const snapshot = () => {
2033
- const totalBytes = state.totalUploadBytes + state.totalDownloadBytes;
2034
- const proxyBytes = state.proxyUploadBytes + state.proxyDownloadBytes;
2035
- const directBytes = state.directUploadBytes + state.directDownloadBytes;
2036
- return {
2037
- meter: "cdp-data-received-v3",
2038
- totalRequests: state.totalRequests,
2039
- proxyRequests: state.proxyRequests,
2040
- directRequests: state.directRequests,
2041
- totalUploadBytes: state.totalUploadBytes,
2042
- proxyUploadBytes: state.proxyUploadBytes,
2043
- directUploadBytes: state.directUploadBytes,
2044
- totalDownloadBytes: state.totalDownloadBytes,
2045
- proxyDownloadBytes: state.proxyDownloadBytes,
2046
- directDownloadBytes: state.directDownloadBytes,
2047
- totalBytes,
2048
- proxyBytes,
2049
- directBytes,
2050
- totalFailedRequests: state.totalFailedRequests,
2051
- proxyFailedRequests: state.proxyFailedRequests,
2052
- directFailedRequests: state.directFailedRequests,
2053
- totalCanceledRequests: state.totalCanceledRequests,
2054
- proxyCanceledRequests: state.proxyCanceledRequests,
2055
- directCanceledRequests: state.directCanceledRequests,
2056
- orphanDataReceivedBytes: state.orphanDataReceivedBytes,
2057
- orphanProxyDataReceivedBytes: state.orphanProxyDataReceivedBytes,
2058
- orphanFinishDeltaBytes: state.orphanFinishDeltaBytes,
2059
- orphanProxyFinishDeltaBytes: state.orphanProxyFinishDeltaBytes,
2060
- openRequestCount: requestMap.size,
2061
- orphanOpenCount: orphanReceivedMap.size,
2062
- topDomains: buildTopDomains(state),
2063
- topResourceTypes: buildTopResourceTypes(state),
2064
- failedReasons: buildFailedReasons(state),
2065
- proxyBypassHints: buildProxyByPassHints(state)
2066
- };
2067
- };
2068
- const reset = () => {
2069
- Object.assign(state, createTrafficState());
2070
- requestMap.clear();
2071
- orphanReceivedMap.clear();
2072
- wsRouteMap.clear();
2073
- };
2074
- return {
2075
- attachPage,
2076
- snapshot,
2077
- reset
2078
- };
2079
- };
2080
1683
 
2081
1684
  // src/launch.js
2082
1685
  var logger7 = createInternalLogger("Launch");
@@ -2091,24 +1694,10 @@ var resolveProxyLaunchOptions = (proxyConfiguration = {}) => {
2091
1694
  const proxyUrl = String(config.proxy_url || "").trim();
2092
1695
  const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
2093
1696
  if (!enableProxy || !proxyUrl) {
2094
- return { launchProxy: null, byPassDomains: [], enableProxy, proxyUrl };
1697
+ return { byPassDomains: [], enableProxy, proxyUrl };
2095
1698
  }
2096
1699
  const byPassDomains = normalizeByPassDomains(config.by_pass_domains);
2097
- let parsedProxyUrl;
2098
- parsedProxyUrl = new URL(proxyUrl);
2099
- const launchProxy = {
2100
- server: `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`
2101
- };
2102
- if (parsedProxyUrl.username) {
2103
- launchProxy.username = decodeURIComponent(parsedProxyUrl.username);
2104
- }
2105
- if (parsedProxyUrl.password) {
2106
- launchProxy.password = decodeURIComponent(parsedProxyUrl.password);
2107
- }
2108
- if (byPassDomains.length > 0) {
2109
- launchProxy.bypass = byPassDomains.join(",");
2110
- }
2111
- return { launchProxy, byPassDomains, enableProxy, proxyUrl };
1700
+ return { byPassDomains, enableProxy, proxyUrl };
2112
1701
  };
2113
1702
  var Launch = {
2114
1703
  getPlaywrightCrawlerOptions(options = {}) {
@@ -2124,14 +1713,13 @@ var Launch = {
2124
1713
  preNavigationHooks = [],
2125
1714
  postNavigationHooks = []
2126
1715
  } = normalizedOptions;
2127
- const { launchProxy, byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);
1716
+ const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);
2128
1717
  const byPassRules = buildByPassDomainRules(byPassDomains);
2129
- const trafficMeter2 = createTrafficMeter({
2130
- enableProxy: Boolean(launchProxy),
2131
- byPassRules,
2132
- debugMode: Boolean(debugMode)
2133
- });
2134
- setTrafficMeter(trafficMeter2);
1718
+ const proxyMeter = enableProxy && proxyUrl ? startProxyMeter({ proxyUrl, debugMode }) : null;
1719
+ const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;
1720
+ if (launchProxy && byPassDomains.length > 0) {
1721
+ launchProxy.bypass = byPassDomains.join(",");
1722
+ }
2135
1723
  const launchOptions = {
2136
1724
  args: [
2137
1725
  ...AntiCheat.getLaunchArgs(),
@@ -2144,8 +1732,14 @@ var Launch = {
2144
1732
  }
2145
1733
  const enableByPassLogger = Boolean(logOptions && logOptions.enable);
2146
1734
  if (enableByPassLogger && launchProxy) {
1735
+ let upstreamLabel = "";
1736
+ try {
1737
+ const parsedProxyUrl = new URL(proxyUrl);
1738
+ upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
1739
+ } catch {
1740
+ }
2147
1741
  logger7.info(
2148
- `[\u4EE3\u7406\u5DF2\u542F\u7528] \u4EE3\u7406\u670D\u52A1=${launchProxy.server} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
1742
+ `[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
2149
1743
  );
2150
1744
  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`);
2151
1745
  } else if (enableByPassLogger && enableProxy && !launchProxy) {
@@ -2165,9 +1759,6 @@ var Launch = {
2165
1759
  const recommendedGotoOptions = {
2166
1760
  waitUntil: "commit"
2167
1761
  };
2168
- if (page && typeof page.on === "function") {
2169
- trafficMeter2.attachPage(page);
2170
- }
2171
1762
  if (!enableByPassLogger || byPassDomains.length === 0 || !page || typeof page.on !== "function") {
2172
1763
  return recommendedGotoOptions;
2173
1764
  }
@@ -2395,7 +1986,7 @@ var Captcha = {
2395
1986
 
2396
1987
  // src/sse.js
2397
1988
  var import_https = __toESM(require("https"), 1);
2398
- var import_url = require("url");
1989
+ var import_url2 = require("url");
2399
1990
  var logger10 = createInternalLogger("Sse");
2400
1991
  var Sse = {
2401
1992
  /**
@@ -2505,7 +2096,7 @@ var Sse = {
2505
2096
  try {
2506
2097
  const headers = await request.allHeaders();
2507
2098
  const postData = request.postData();
2508
- const urlObj = new import_url.URL(request.url());
2099
+ const urlObj = new import_url2.URL(request.url());
2509
2100
  delete headers["accept-encoding"];
2510
2101
  delete headers["content-length"];
2511
2102
  const reqOptions = {
@@ -2860,10 +2451,10 @@ var Mutation = {
2860
2451
  let text = "";
2861
2452
  let html = "";
2862
2453
  let source = "main";
2863
- let path = `${selector}[${index}]`;
2454
+ let path2 = `${selector}[${index}]`;
2864
2455
  if (isIframe) {
2865
2456
  source = "iframe";
2866
- path = `${selector}[${index}]::iframe(${safeFrameId(node)})`;
2457
+ path2 = `${selector}[${index}]::iframe(${safeFrameId(node)})`;
2867
2458
  try {
2868
2459
  const frameDoc = node.contentDocument;
2869
2460
  const frameRoot = frameDoc?.body || frameDoc?.documentElement;
@@ -2881,7 +2472,7 @@ var Mutation = {
2881
2472
  items.push({
2882
2473
  selector,
2883
2474
  source,
2884
- path,
2475
+ path: path2,
2885
2476
  text,
2886
2477
  html,
2887
2478
  snapshot