@skrillex1224/playwright-toolkit 2.1.193 → 2.1.195

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../entrys/node.js", "../src/constants.js", "../src/internals/logger.js", "../src/internals/screenshot.js", "../src/errors.js", "../src/apify-kit.js", "../src/internals/proxy-meter-runtime.js", "../src/runtime-env.js", "../src/internals/utils.js", "../src/utils.js", "../src/anti-cheat.js", "../src/humanize.js", "../src/launch.js", "../src/proxy-bypass.js", "../src/live-view.js", "../src/captcha-monitor.js", "../src/mutation.js", "../src/display.js", "../src/logger.js", "../src/share.js"],
4
- "sourcesContent": ["import { log as crawleeLog } from 'crawlee';\r\nimport { ApifyKit } from '../src/apify-kit';\r\nimport { Utils } from '../src/utils';\r\nimport { AntiCheat } from '../src/anti-cheat';\r\nimport { Humanize } from '../src/humanize';\r\nimport { Launch } from '../src/launch';\r\nimport { LiveView } from '../src/live-view';\r\nimport { Captcha } from '../src/captcha-monitor';\r\nimport { Mutation } from '../src/mutation';\r\nimport { Display } from '../src/display.js';\r\nimport * as Constants from '../src/constants';\r\nimport * as Errors from '../src/errors';\r\nimport { Logger, LOG_TEMPLATES, stripAnsi } from '../src/logger';\r\nimport { Share } from '../src/share';\r\nimport { ByPass } from '../src/proxy-bypass';\r\nimport { RuntimeEnv } from '../src/runtime-env.js';\r\n\r\n// \u4FEE\u6539\u9ED8\u8BA4logger \u4ECEconsole.log \u5230 crawleeLog\r\nLogger.setLogger(crawleeLog);\r\n\r\n// Unified Entry Point\r\nexport const usePlaywrightToolKit = () => {\r\n return {\r\n ApifyKit,\r\n AntiCheat,\r\n Humanize,\r\n Launch,\r\n LiveView,\r\n Constants,\r\n Utils,\r\n RuntimeEnv,\r\n Captcha,\r\n Errors,\r\n Mutation,\r\n Display,\r\n Logger,\r\n Share,\r\n ByPass,\r\n $Internals: { LOG_TEMPLATES, stripAnsi }\r\n };\r\n};\r\n", "export const Code = {\r\n Success: 0,\r\n UnknownError: -1,\r\n NotLogin: 30000001,\r\n Chaptcha: 30000002,\r\n Timeout: 30000003,\r\n InitialTimeout: 30000004,\r\n OverallTimeout: 30000005,\r\n}\r\n\r\nexport const Status = {\r\n Success: 'SUCCESS',\r\n Failed: 'FAILED'\r\n}\r\n\r\nexport const PresetOfLiveViewKey = 'LIVE_VIEW_SCREENSHOT';\r\n\r\n\r\nconst createActorInfo = (info) => {\r\n const normalizeDomain = (value) => {\r\n if (!value) return '';\r\n return String(value).trim().replace(/^https?:\\/\\//, '').replace(/\\/.*$/, '');\r\n };\r\n\r\n const normalizePath = (value) => {\r\n if (!value) return '/';\r\n const raw = String(value).trim();\r\n if (!raw) return '/';\r\n return raw.startsWith('/') ? raw : `/${raw}`;\r\n };\r\n\r\n const normalizeShare = (value) => {\r\n const raw = value && typeof value === 'object' ? value : {};\r\n\r\n const modeRaw = String(raw.mode || 'dom').trim().toLowerCase();\r\n const mode = modeRaw === 'response' ? 'response' : 'dom';\r\n\r\n const prefix = String(raw.prefix || '').trim();\r\n\r\n const rawXurl = Array.isArray(raw.xurl)\r\n ? raw.xurl\r\n : [];\r\n\r\n const normalizeMatcherList = (input) => {\r\n if (Array.isArray(input)) {\r\n return input\r\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\r\n .filter(Boolean);\r\n }\r\n\r\n const single = String(input || '').trim().replace(/\\.+$/, '');\r\n return single ? [single] : [];\r\n };\r\n\r\n const normalizeSegments = (input) => {\r\n if (Array.isArray(input)) {\r\n return input\r\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\r\n .filter(Boolean);\r\n }\r\n\r\n const rawPath = String(input || '').trim();\r\n if (!rawPath) return [];\r\n\r\n return rawPath\r\n .split('.')\r\n .map((segment) => String(segment || '').trim().replace(/\\.+$/, ''))\r\n .filter(Boolean);\r\n };\r\n\r\n const xurl = [];\r\n\r\n const matcherList = normalizeMatcherList(rawXurl[0]);\r\n if (matcherList.length > 0) {\r\n xurl.push(matcherList);\r\n }\r\n\r\n const flatPath = [];\r\n const extraPaths = [];\r\n\r\n rawXurl.slice(1).forEach((item) => {\r\n if (Array.isArray(item)) {\r\n const segments = normalizeSegments(item);\r\n if (segments.length > 0) {\r\n extraPaths.push(segments);\r\n }\r\n return;\r\n }\r\n\r\n const segments = normalizeSegments(item);\r\n if (segments.length > 0) {\r\n flatPath.push(...segments);\r\n }\r\n });\r\n\r\n if (flatPath.length > 0) {\r\n xurl.push(flatPath);\r\n }\r\n\r\n if (extraPaths.length > 0) {\r\n xurl.push(...extraPaths);\r\n }\r\n\r\n return {\r\n mode,\r\n prefix,\r\n xurl,\r\n };\r\n };\r\n\r\n const buildLandingUrl = ({ protocol, domain, path }) => {\r\n const safeProtocol = String(protocol).trim();\r\n const safeDomain = normalizeDomain(domain);\r\n const safePath = normalizePath(path);\r\n return `${safeProtocol}://${safeDomain}${safePath}`;\r\n };\r\n\r\n const buildIcon = ({ key }) => {\r\n return `https://heartbitai.com/general/actors/${key}.png`;\r\n }\r\n\r\n\r\n const protocol = info.protocol || 'https';\r\n const domain = normalizeDomain(info.domain);\r\n const path = normalizePath(info.path);\r\n const share = normalizeShare(info.share);\r\n\r\n return {\r\n ...info,\r\n protocol,\r\n domain,\r\n path,\r\n share,\r\n get icon() {\r\n if (info.icon) return info.icon;\r\n return buildIcon(this);\r\n },\r\n get landingUrl() {\r\n return buildLandingUrl(this);\r\n },\r\n };\r\n};\r\n\r\nexport const ActorInfo = {\r\n qbot: createActorInfo({\r\n key: 'qbot',\r\n name: 'QQ\u6D4F\u89C8\u5668AI\u641C',\r\n domain: 'sogou.com',\r\n path: '/web',\r\n share: {\r\n mode: 'dom',\r\n prefix: '',\r\n xurl: [],\r\n },\r\n }),\r\n douyin: createActorInfo({\r\n key: 'douyin',\r\n name: '\u6296\u97F3AI\u641C',\r\n domain: 'so.douyin.com',\r\n path: '/',\r\n share: {\r\n mode: 'dom',\r\n prefix: '',\r\n xurl: [\r\n ],\r\n },\r\n }),\r\n lingguang: createActorInfo({\r\n key: 'lingguang',\r\n name: '\u7075\u5149',\r\n domain: 'www.lingguang.com',\r\n path: '/',\r\n share: {\r\n mode: 'response',\r\n prefix: 'https://www.lingguang.com/share/',\r\n xurl: [\r\n '/chat/shareChat.json',\r\n 'result',\r\n ],\r\n },\r\n }),\r\n doubao: createActorInfo({\r\n key: 'doubao',\r\n name: '\u8C46\u5305',\r\n domain: 'www.doubao.com',\r\n path: '/',\r\n share: {\r\n mode: 'response',\r\n prefix: 'https://www.doubao.com/thread/',\r\n xurl: [\r\n '/samantha/thread/share/save',\r\n 'data', 'share_id',\r\n ],\r\n },\r\n }),\r\n deepseek: createActorInfo({\r\n key: 'deepseek',\r\n name: 'DeepSeek',\r\n domain: 'chat.deepseek.com',\r\n path: '/',\r\n share: {\r\n mode: 'response',\r\n prefix: 'https://chat.deepseek.com/share/',\r\n xurl: [\r\n '/api/v0/share/create',\r\n 'data', 'biz_data', 'share_id',\r\n ],\r\n },\r\n }),\r\n erine: createActorInfo({\r\n key: 'erine',\r\n name: '\u6587\u5FC3\u4E00\u8A00',\r\n domain: 'yiyan.baidu.com',\r\n path: '/',\r\n share: {\r\n mode: 'response',\r\n prefix: 'https://yiyan.baidu.com/share/',\r\n xurl: [\r\n '/eb/share/key/gen',\r\n 'data', 'key',\r\n ],\r\n },\r\n }),\r\n wenxin: createActorInfo({\r\n key: 'wenxin',\r\n name: '\u6587\u5FC3\u52A9\u624B',\r\n domain: 'chat.baidu.com',\r\n path: '/',\r\n share: {\r\n mode: 'response',\r\n prefix: '',\r\n xurl: [\r\n '/aichat/api/shortURL',\r\n 'data', 'short_url',\r\n ],\r\n },\r\n }),\r\n baidu: createActorInfo({\r\n key: 'baidu',\r\n name: '\u767E\u5EA6AI\u641C',\r\n domain: 'www.baidu.com',\r\n path: '/s',\r\n share: {\r\n mode: 'response',\r\n prefix: '',\r\n xurl: [\r\n '/aichat/api/shortURL',\r\n 'data', 'short_url',\r\n ],\r\n },\r\n }),\r\n yuanbao: createActorInfo({\r\n key: 'yuanbao',\r\n name: '\u5143\u5B9D',\r\n domain: 'yuanbao.tencent.com',\r\n path: '/chat/',\r\n share: {\r\n mode: 'response',\r\n prefix: 'https://yb.tencent.com/s/',\r\n xurl: [\r\n '/api/conversations/v2/share', 'shareId',\r\n ],\r\n },\r\n }),\r\n kimi: createActorInfo({\r\n key: 'kimi',\r\n name: 'Kimi',\r\n domain: 'www.kimi.com',\r\n path: '/',\r\n share: {\r\n mode: 'response',\r\n prefix: 'https://www.kimi.com/share/',\r\n xurl: [\r\n '/kimi.gateway.chat.v1.ChatService/CreateChatShare', 'share', 'id'\r\n ],\r\n },\r\n }),\r\n qwen: createActorInfo({\r\n key: 'qwen',\r\n name: '\u901A\u4E49\u5343\u95EE',\r\n domain: 'www.qianwen.com',\r\n path: '/chat',\r\n share: {\r\n mode: 'response',\r\n prefix: 'https://www.qianwen.com/share/chat/',\r\n xurl: [\r\n '/api/v1/share/create', 'data', 'share_id'\r\n ],\r\n },\r\n }),\r\n nano: createActorInfo({\r\n key: 'nano',\r\n name: '\u7EB3\u7C73',\r\n domain: 'www.n.cn',\r\n path: '/',\r\n share: {\r\n mode: 'response',\r\n prefix: 'https://www.n.cn/share/mcp?id=',\r\n xurl: [\r\n '/api/share/gen', 'data', 'id'\r\n ],\r\n },\r\n }),\r\n}\r\n", "\r\n// =============================================================================\r\n// Core Helpers & State\r\n// =============================================================================\r\n\r\nconst pad = (value, size = 2) => String(value).padStart(size, '0');\r\n\r\nconst FORCED_TIMEZONE_OFFSET_MINUTES = -8 * 60;\r\n\r\nconst formatTimestamp = (date = new Date()) => {\r\n const source = date instanceof Date ? date : new Date(date);\r\n const forcedDate = new Date(source.getTime() - (FORCED_TIMEZONE_OFFSET_MINUTES * 60 * 1000));\r\n\r\n const year = forcedDate.getUTCFullYear();\r\n const month = pad(forcedDate.getUTCMonth() + 1);\r\n const day = pad(forcedDate.getUTCDate());\r\n const hours = pad(forcedDate.getUTCHours());\r\n const minutes = pad(forcedDate.getUTCMinutes());\r\n const seconds = pad(forcedDate.getUTCSeconds());\r\n const millis = pad(forcedDate.getUTCMilliseconds(), 3);\r\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${millis}`;\r\n};\r\n\r\nconst formatLine = (prefix, icon, message) => {\r\n const parts = [];\r\n if (prefix) parts.push(`[${prefix}]`);\r\n if (icon) parts.push(icon);\r\n if (message) parts.push(message);\r\n return parts.join(' ').trim();\r\n};\r\n\r\nconst fallbackLog = {\r\n info: (...args) => console.log(...args),\r\n warning: (...args) => (console.warn ? console.warn(...args) : console.log(...args)),\r\n error: (...args) => console.error(...args),\r\n debug: (...args) => (console.debug ? console.debug(...args) : console.log(...args)),\r\n};\r\n\r\nconst resolveLogMethod = (logger, name) => {\r\n if (logger && typeof logger[name] === 'function') {\r\n return logger[name].bind(logger);\r\n }\r\n if (name === 'warning' && logger && typeof logger.warn === 'function') {\r\n return logger.warn.bind(logger);\r\n }\r\n return fallbackLog[name];\r\n};\r\n\r\nlet defaultLogger = null;\r\n\r\nexport const setDefaultLogger = (logger) => {\r\n defaultLogger = logger;\r\n};\r\n\r\n// Lazy resolver: always checks current state\r\nconst resolveLogger = (explicitLogger) => {\r\n if (explicitLogger && typeof explicitLogger.info === 'function') {\r\n return explicitLogger;\r\n }\r\n if (defaultLogger && typeof defaultLogger.info === 'function') {\r\n return defaultLogger;\r\n }\r\n return fallbackLog;\r\n};\r\n\r\nconst ANSI = {\r\n reset: '\\x1b[0m',\r\n gray: '\\x1b[90m',\r\n red: '\\x1b[31m',\r\n green: '\\x1b[32m',\r\n yellow: '\\x1b[33m',\r\n blue: '\\x1b[34m',\r\n cyan: '\\x1b[36m',\r\n};\r\n\r\nconst colorize = (text, color) => {\r\n if (!text || !color) return text;\r\n return `${color}${text}${ANSI.reset}`;\r\n};\r\n\r\nexport const createBaseLogger = (prefix = '', explicitLogger) => {\r\n const name = prefix ? String(prefix) : '';\r\n\r\n const dispatch = (methodName, icon, message, color) => {\r\n const logger = resolveLogger(explicitLogger);\r\n const logFn = resolveLogMethod(logger, methodName);\r\n const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);\r\n const line = formatLine(name, icon, message);\r\n const coloredLine = colorize(line, color);\r\n logFn(`${timestamp} ${coloredLine}`.trim());\r\n };\r\n\r\n return {\r\n info: (message) => dispatch('info', '\uD83D\uDCD6', message, ANSI.cyan),\r\n success: (message) => dispatch('info', '\u2705', message, ANSI.green),\r\n warning: (message) => dispatch('warning', '\u26A0\uFE0F', message, ANSI.yellow),\r\n warn: (message) => dispatch('warning', '\u26A0\uFE0F', message, ANSI.yellow),\r\n error: (message) => dispatch('error', '\u274C', message, ANSI.red),\r\n debug: (message) => dispatch('debug', '\uD83D\uDD39', message, ANSI.gray),\r\n start: (message) => dispatch('info', '\uD83D\uDD37', message, ANSI.blue),\r\n };\r\n};\r\n\r\n/**\r\n * \u521B\u5EFA\u6A21\u5757\u7EA7\u65E5\u5FD7\u5668\r\n * @param {string} moduleName - \u6A21\u5757\u540D\u79F0\r\n * @param {object} [logger] - \u53EF\u9009\u7684\u663E\u5F0F\u65E5\u5FD7\u5668\uFF0C\u901A\u5E38\u4E0D\u9700\u8981\u4F20\uFF0C\u4F1A\u81EA\u52A8\u4F7F\u7528 setDefaultLogger \u8BBE\u7F6E\u7684\u5168\u5C40\u65E5\u5FD7\u5668\r\n */\r\nexport function createInternalLogger(moduleName, explicitLogger) {\r\n const baseLogger = createBaseLogger(moduleName, explicitLogger);\r\n\r\n return {\r\n start(methodName, params = '') {\r\n const paramStr = params ? ` (${params})` : '';\r\n baseLogger.start(`${methodName} \u5F00\u59CB${paramStr}`);\r\n },\r\n success(methodName, result = '') {\r\n const resultStr = result ? ` (${result})` : '';\r\n baseLogger.success(`${methodName} \u5B8C\u6210${resultStr}`);\r\n },\r\n fail(methodName, error) {\r\n const message = error instanceof Error ? error.message : error;\r\n baseLogger.error(`${methodName} \u5931\u8D25: ${message}`);\r\n },\r\n debug(message) {\r\n baseLogger.debug(message);\r\n },\r\n warn(message) {\r\n baseLogger.warning(message);\r\n },\r\n warning(message) {\r\n baseLogger.warning(message);\r\n },\r\n info(message) {\r\n baseLogger.info(message);\r\n }\r\n };\r\n}\r\n", "import { createInternalLogger } from './logger.js';\r\n\r\nconst logger = createInternalLogger('Screenshot');\r\n\r\nconst DEFAULT_TIMEOUT_MS = 5000;\r\nconst FORCED_FULLPAGE_TYPE = 'jpeg';\r\nconst FORCED_FULLPAGE_QUALITY = 50;\r\nconst SUPPORTED_TYPES = new Set(['png', 'jpeg', 'webp']);\r\n\r\nconst toPositiveNumber = (value, fallback = 0) => {\r\n const n = Number(value);\r\n if (!Number.isFinite(n) || n <= 0) return fallback;\r\n return n;\r\n};\r\n\r\nconst normalizeType = (value) => {\r\n const raw = String(value || 'png').trim().toLowerCase();\r\n if (!SUPPORTED_TYPES.has(raw)) return 'png';\r\n return raw;\r\n};\r\n\r\nconst normalizeQuality = (value, type) => {\r\n if (type !== 'jpeg' && type !== 'webp') return undefined;\r\n const n = Number(value);\r\n if (!Number.isFinite(n)) return undefined;\r\n const rounded = Math.round(n);\r\n if (rounded < 0 || rounded > 100) return undefined;\r\n return rounded;\r\n};\r\n\r\nconst buildFullPageClip = (metrics, viewport, maxClipHeight) => {\r\n const contentSize = metrics && typeof metrics === 'object'\r\n ? metrics.contentSize || null\r\n : null;\r\n\r\n const width = Math.max(1, Math.ceil(contentSize?.width || viewport.width || 1));\r\n let height = Math.max(1, Math.ceil(contentSize?.height || viewport.height || 1));\r\n\r\n if (maxClipHeight > 0) {\r\n height = Math.min(height, maxClipHeight);\r\n }\r\n\r\n return {\r\n x: 0,\r\n y: 0,\r\n width,\r\n height,\r\n scale: 1,\r\n };\r\n};\r\n\r\nexport const capturePageScreenshot = async (page, options = {}) => {\r\n const fullPage = Boolean(options.fullPage);\r\n const type = fullPage ? FORCED_FULLPAGE_TYPE : normalizeType(options.type);\r\n const quality = fullPage\r\n ? FORCED_FULLPAGE_QUALITY\r\n : normalizeQuality(options.quality, type);\r\n const timeout = toPositiveNumber(options.timeout, DEFAULT_TIMEOUT_MS);\r\n const maxClipHeight = Math.round(toPositiveNumber(options.maxClipHeight, 0));\r\n\r\n const fallbackOptions = {\r\n type: type === 'webp' ? 'png' : type,\r\n fullPage,\r\n };\r\n if (quality !== undefined && fallbackOptions.type === 'jpeg') {\r\n fallbackOptions.quality = quality;\r\n }\r\n if (timeout > 0) {\r\n fallbackOptions.timeout = timeout;\r\n }\r\n\r\n try {\r\n const context = page && typeof page.context === 'function' ? page.context() : null;\r\n if (!context || typeof context.newCDPSession !== 'function') {\r\n throw new Error('CDP session is not available');\r\n }\r\n\r\n const session = await context.newCDPSession(page);\r\n try {\r\n const metrics = await session.send('Page.getLayoutMetrics');\r\n const viewport = page.viewportSize() || { width: 1280, height: 720 };\r\n\r\n const captureParams = {\r\n format: type,\r\n fromSurface: true,\r\n captureBeyondViewport: fullPage,\r\n optimizeForSpeed: true,\r\n };\r\n\r\n if (quality !== undefined) {\r\n captureParams.quality = quality;\r\n }\r\n\r\n if (fullPage) {\r\n captureParams.clip = buildFullPageClip(metrics, viewport, maxClipHeight);\r\n }\r\n\r\n const result = await session.send('Page.captureScreenshot', captureParams);\r\n if (!result || typeof result.data !== 'string' || !result.data) {\r\n throw new Error('CDP returned empty screenshot data');\r\n }\r\n\r\n return Buffer.from(result.data, 'base64');\r\n } finally {\r\n if (typeof session.detach === 'function') {\r\n await session.detach().catch(() => { });\r\n }\r\n }\r\n } catch (error) {\r\n logger.warning(`CDP \u622A\u56FE\u5931\u8D25\uFF0C\u56DE\u9000 page.screenshot: ${error?.message || error}`);\r\n return await page.screenshot(fallbackOptions);\r\n }\r\n};\r\n", "/**\r\n * \u722C\u866B\u81EA\u5B9A\u4E49\u9519\u8BEF\u7C7B\r\n * \u7528\u4E8E\u643A\u5E26\u4E0A\u4E0B\u6587\u4FE1\u606F\uFF0C\u5728 pushFailed \u65F6\u81EA\u52A8\u89E3\u6790\r\n */\r\n\r\nimport { serializeError } from \"serialize-error\";\r\nimport { Code } from \"./constants\";\r\n\r\n/**\r\n * CrawlerError - \u81EA\u5B9A\u4E49\u722C\u866B\u9519\u8BEF\u7C7B\r\n * \r\n * @example\r\n * // \u7B80\u5355\u7528\u6CD5 (\u53EA\u6709 message)\r\n * throw new CrawlerError('\u672A\u6355\u83B7 Feed \u63A5\u53E3\u54CD\u5E94');\r\n * \r\n * @example\r\n * // \u5B8C\u6574\u7528\u6CD5 (\u5E26 code \u548C context)\r\n * throw new CrawlerError({\r\n * message: '\u767B\u5F55\u5931\u8D25',\r\n * code: ErrorKeygen.NotLogin,\r\n * context: { url: currentUrl, userId: '123' }\r\n * });\r\n */\r\nexport class CrawlerError extends Error {\r\n /**\r\n * @param {string|Object} info - \u9519\u8BEF\u4FE1\u606F\u5B57\u7B26\u4E32\u6216\u914D\u7F6E\u5BF9\u8C61\r\n * @param {string} info.message - \u9519\u8BEF\u4FE1\u606F\r\n * @param {number} [info.code] - ErrorKeygen \u679A\u4E3E\u503C\uFF08\u7528\u4E8E\u9519\u8BEF\u5206\u7C7B\uFF09\r\n * @param {Object} [info.context] - \u4E0A\u4E0B\u6587\u4FE1\u606F\u5BF9\u8C61\r\n */\r\n constructor(info) {\r\n // \u517C\u5BB9 string\r\n if (typeof info === 'string') {\r\n info = { message: info };\r\n }\r\n\r\n // \u26A0\uFE0F super() \u5FC5\u987B\u5728\u8BBF\u95EE this \u4E4B\u524D\u8C03\u7528\r\n super(info.message);\r\n\r\n this.name = 'CrawlerError';\r\n this.code = info.code ?? Code.UnknownError;\r\n this.context = info.context ?? {};\r\n this.timestamp = new Date().toISOString();\r\n\r\n // \u7EF4\u62A4\u6B63\u786E\u7684\u5806\u6808\u8DDF\u8E2A\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, CrawlerError);\r\n }\r\n }\r\n\r\n /**\r\n * \u8F6C\u6362\u4E3A\u53EF\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\r\n * @returns {Object}\r\n */\r\n toJSON() {\r\n return serializeError(this)\r\n }\r\n\r\n /**\r\n * \u68C0\u67E5\u4E00\u4E2A error \u662F\u5426\u662F CrawlerError\r\n * @param {Error} error\r\n * @returns {boolean}\r\n */\r\n static isCrawlerError(error) {\r\n return error instanceof CrawlerError || error?.name === 'CrawlerError';\r\n }\r\n\r\n /**\r\n * \u4ECE\u666E\u901A Error \u521B\u5EFA CrawlerError\r\n * @param {Error} error - \u539F\u59CB\u9519\u8BEF\r\n * @param {Object} [options={}] - \u9009\u9879\u5BF9\u8C61 (\u5305\u542B code \u548C context)\r\n * @returns {CrawlerError}\r\n */\r\n static from(error, options = {}) {\r\n const crawlerError = new CrawlerError({\r\n message: error.message,\r\n ...options\r\n });\r\n crawlerError.stack = error.stack;\r\n return crawlerError;\r\n }\r\n}\r\n\r\n\r\n", "import { Status, Code } from './constants';\r\nimport { createInternalLogger } from './internals/logger';\r\nimport { capturePageScreenshot } from './internals/screenshot';\r\nimport { CrawlerError } from './errors';\r\nimport { serializeError } from 'serialize-error';\r\nimport { ProxyMeterRuntime } from './internals/proxy-meter-runtime';\r\nimport { RuntimeEnv } from './runtime-env';\r\n\r\nconst logger = createInternalLogger('ApifyKit');\r\n\r\nconst resolveRuntimeContext = (input) => {\r\n const rememberedState = RuntimeEnv.peekRememberedState();\r\n const state = rememberedState || RuntimeEnv.parseInput(input || {});\r\n const envPatch = RuntimeEnv.buildEnvPatch(state) || null;\r\n\r\n return {\r\n actor: state.actor,\r\n runtime: state.runtime,\r\n envPatch,\r\n };\r\n};\r\n\r\nconst isPageLike = (value) => {\r\n if (!value || typeof value !== 'object') return false;\r\n return typeof value.evaluate === 'function' && typeof value.context === 'function';\r\n};\r\n\r\nconst pickPage = (...candidates) => {\r\n for (const candidate of candidates) {\r\n if (isPageLike(candidate)) {\r\n return candidate;\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nconst toSerializable = (value, depth = 0, seen = new WeakSet()) => {\r\n if (depth > 6) return '[MaxDepth]';\r\n if (value == null) return value;\r\n\r\n const valueType = typeof value;\r\n if (valueType === 'string' || valueType === 'number' || valueType === 'boolean') {\r\n return value;\r\n }\r\n if (valueType === 'bigint') {\r\n return value.toString();\r\n }\r\n if (valueType === 'function' || valueType === 'symbol') {\r\n return undefined;\r\n }\r\n if (value instanceof Error) {\r\n return serializeError(value);\r\n }\r\n if (Array.isArray(value)) {\r\n return value\r\n .map((item) => toSerializable(item, depth + 1, seen))\r\n .filter((item) => item !== undefined);\r\n }\r\n if (valueType !== 'object') {\r\n return String(value);\r\n }\r\n\r\n if (seen.has(value)) {\r\n return '[Circular]';\r\n }\r\n seen.add(value);\r\n\r\n const ctorName = String(value?.constructor?.name || '');\r\n if (\r\n ctorName === 'Page' ||\r\n ctorName === 'BrowserContext' ||\r\n ctorName === 'Browser' ||\r\n ctorName === 'Frame' ||\r\n ctorName === 'ElementHandle' ||\r\n ctorName === 'JSHandle'\r\n ) {\r\n return `[${ctorName}]`;\r\n }\r\n\r\n const output = {};\r\n Object.entries(value).forEach(([key, item]) => {\r\n const safeValue = toSerializable(item, depth + 1, seen);\r\n if (safeValue !== undefined) {\r\n output[key] = safeValue;\r\n }\r\n });\r\n return output;\r\n};\r\n\r\nconst sanitizeMeta = (meta) => {\r\n if (!meta || typeof meta !== 'object' || Array.isArray(meta)) {\r\n return {};\r\n }\r\n const result = toSerializable(meta) || {};\r\n if (result && typeof result === 'object' && !Array.isArray(result)) {\r\n delete result.page;\r\n }\r\n return result;\r\n};\r\n\r\nconst captureAutoEnvPatch = async (page, runtimeContext) => {\r\n const currentPage = pickPage(page);\r\n if (!currentPage) return null;\r\n try {\r\n return await RuntimeEnv.captureEnvPatch(\r\n currentPage,\r\n {\r\n actor: runtimeContext.actor,\r\n runtime: runtimeContext.runtime,\r\n },\r\n { actor: runtimeContext.actor },\r\n );\r\n } catch (error) {\r\n logger.warn(`\u81EA\u52A8\u91C7\u96C6 env_patch \u5931\u8D25: ${error?.message || error}`);\r\n return null;\r\n }\r\n};\r\n\r\n/**\r\n * \u521B\u5EFA ApifyKit \u5B9E\u4F8B\r\n * \u5982\u679C apify \u53EF\u7528\uFF0C\u8FD4\u56DE\u5B8C\u6574\u529F\u80FD\u7684 ApifyKit\r\n * \u5982\u679C apify \u4E0D\u53EF\u7528\uFF0C\u8FD4\u56DE\u964D\u7EA7\u7248\u672C\uFF08\u975E apify \u76F8\u5173\u529F\u80FD\u4ECD\u53EF\u7528\uFF09\r\n */\r\nasync function createApifyKit() {\r\n let apify = null;\r\n\r\n // \u5C1D\u8BD5\u52A0\u8F7D apify\r\n try {\r\n apify = await import('apify');\r\n } catch (error) {\r\n // apify \u4E0D\u53EF\u7528\uFF0C\u5C06\u4F7F\u7528\u964D\u7EA7\u7248\u672C\r\n throw new Error('\u26A0\uFE0F apify \u5E93\u672A\u5B89\u88C5\uFF0CApifyKit \u7684 Actor \u76F8\u5173\u529F\u80FD\u4E0D\u53EF\u7528')\r\n }\r\n\r\n const { Actor } = apify;\r\n const actorInput = (await Actor.getInput()) || {};\r\n let lastPage = null;\r\n const getRuntimeContext = () => resolveRuntimeContext(actorInput);\r\n\r\n return {\r\n /**\r\n * \u6838\u5FC3\u5C01\u88C5\uFF1A\u6267\u884C\u6B65\u9AA4\uFF0C\u5E26\u81EA\u52A8\u65E5\u5FD7\u786E\u8BA4\u3001\u5931\u8D25\u622A\u56FE\u5904\u7406\u548C\u91CD\u8BD5\u673A\u5236\r\n * \r\n * @param {string} step - \u6B65\u9AA4\u540D\u79F0\r\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\r\n * @param {Function} actionFn - \u6267\u884C\u7684\u5F02\u6B65\u64CD\u4F5C\r\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\r\n * @param {boolean} [options.failActor=true] - \u5931\u8D25\u65F6\u662F\u5426\u8C03\u7528 Actor.fail\r\n * @param {Object} [options.retry] - \u91CD\u8BD5\u914D\u7F6E\r\n * @param {number} [options.retry.times=0] - \u91CD\u8BD5\u6B21\u6570\r\n * @param {'direct'|'refresh'} [options.retry.mode='direct'] - \u91CD\u8BD5\u6A21\u5F0F\r\n * @param {Function} [options.retry.before] - \u91CD\u8BD5\u524D\u94A9\u5B50\uFF0C\u53EF\u8986\u76D6\u9ED8\u8BA4\u7B49\u5F85\u884C\u4E3A\r\n */\r\n async runStep(step, page, actionFn, options = {}) {\r\n if (isPageLike(page)) {\r\n lastPage = page;\r\n }\r\n const { failActor = true, retry = {} } = options;\r\n const { times: retryTimes = 0, mode: retryMode = 'direct', before: beforeRetry } = retry;\r\n\r\n // \u5185\u90E8\u6267\u884C\u51FD\u6570\r\n const executeAction = async (attemptNumber) => {\r\n const attemptLabel = attemptNumber > 0 ? ` (\u91CD\u8BD5 #${attemptNumber})` : '';\r\n logger.start(`[Step] ${step}${attemptLabel}`);\r\n\r\n try {\r\n const result = await actionFn();\r\n logger.success(`[Step] ${step}${attemptLabel}`);\r\n return { success: true, result };\r\n } catch (error) {\r\n logger.fail(`[Step] ${step}${attemptLabel}`, error);\r\n return { success: false, error };\r\n }\r\n };\r\n\r\n // \u91CD\u8BD5\u524D\u7684\u51C6\u5907\u64CD\u4F5C\r\n const prepareForRetry = async (attemptNumber) => {\r\n if (typeof beforeRetry === 'function') {\r\n // \u4F7F\u7528\u81EA\u5B9A\u4E49\u94A9\u5B50\r\n logger.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\r\n await beforeRetry(page, attemptNumber);\r\n logger.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);\r\n } else if (retryMode === 'refresh') {\r\n // \u5237\u65B0\u6A21\u5F0F\uFF1A\u5237\u65B0\u9875\u9762\u5E76\u7B49\u5F85\u5BFC\u822A commit\uFF0C\u540E\u7EED\u6B65\u9AA4\u81EA\u884C\u505A\u4EA4\u4E92\u5C31\u7EEA\u68C0\u67E5\r\n logger.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\r\n await page.reload({ waitUntil: 'commit' });\r\n logger.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);\r\n } else {\r\n // direct \u6A21\u5F0F\uFF1A\u9ED8\u8BA4\u7B49\u5F85 3 \u79D2\r\n logger.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\r\n await new Promise(resolve => setTimeout(resolve, 3000));\r\n logger.success(`[RetryStep] \u7B49\u5F85\u5B8C\u6210`);\r\n }\r\n };\r\n\r\n // \u9996\u6B21\u6267\u884C\r\n let lastResult = await executeAction(0);\r\n\r\n // \u5982\u679C\u9996\u6B21\u6210\u529F\uFF0C\u76F4\u63A5\u8FD4\u56DE\r\n if (lastResult.success) {\r\n return lastResult.result;\r\n }\r\n\r\n // \u91CD\u8BD5\u903B\u8F91\r\n for (let attempt = 1; attempt <= retryTimes; attempt++) {\r\n logger.start(`[RetryStep] \u51C6\u5907\u7B2C ${attempt}/${retryTimes} \u6B21\u91CD\u8BD5: ${step}`);\r\n\r\n try {\r\n await prepareForRetry(attempt);\r\n } catch (prepareError) {\r\n logger.warn(`[RetryStep] \u91CD\u8BD5\u51C6\u5907\u5931\u8D25: ${prepareError.message}`);\r\n // \u51C6\u5907\u5931\u8D25\uFF0C\u7EE7\u7EED\u5C1D\u8BD5\u4E0B\u4E00\u6B21\u91CD\u8BD5\r\n continue;\r\n }\r\n\r\n lastResult = await executeAction(attempt);\r\n if (lastResult.success) {\r\n return lastResult.result;\r\n }\r\n }\r\n\r\n // \u6240\u6709\u91CD\u8BD5\u90FD\u5931\u8D25\uFF0C\u5904\u7406\u6700\u7EC8\u9519\u8BEF\r\n const finalError = lastResult.error;\r\n if (failActor) {\r\n let base64 = '\u622A\u56FE\u5931\u8D25';\r\n try {\r\n if (page) {\r\n const buffer = await capturePageScreenshot(page, {\r\n fullPage: true,\r\n type: 'jpeg',\r\n quality: 60,\r\n });\r\n base64 = `data:image/jpeg;base64,${buffer.toString('base64')}`;\r\n }\r\n } catch (snapErr) {\r\n logger.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);\r\n }\r\n\r\n await this.pushFailed(\r\n finalError,\r\n {\r\n step,\r\n base64,\r\n retryAttempts: retryTimes,\r\n },\r\n {\r\n page,\r\n options,\r\n },\r\n );\r\n await Actor.fail(`Run Step ${step} \u5931\u8D25 (\u5DF2\u91CD\u8BD5 ${retryTimes} \u6B21): ${finalError.message}`);\r\n } else {\r\n throw finalError;\r\n }\r\n },\r\n\r\n /**\r\n * \u5BBD\u677E\u7248runStep\uFF1A\u5931\u8D25\u65F6\u4E0D\u8C03\u7528Actor.fail\uFF0C\u53EA\u629B\u51FA\u5F02\u5E38\r\n * \u652F\u6301\u900F\u4F20 retry \u7B49\u9009\u9879\uFF08failActor \u59CB\u7EC8\u56FA\u5B9A\u4E3A false\uFF09\r\n *\r\n * @param {string} step - \u6B65\u9AA4\u540D\u79F0\r\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\r\n * @param {Function} fn - \u6267\u884C\u7684\u5F02\u6B65\u64CD\u4F5C\r\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\uFF08\u652F\u6301 retry\uFF09\r\n */\r\n async runStepLoose(step, page, fn, options = {}) {\r\n return await this.runStep(step, page, fn, {\r\n ...options,\r\n failActor: false,\r\n });\r\n },\r\n\r\n /**\r\n * \u63A8\u9001\u6210\u529F\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\u3002\r\n * \u8FD9\u91CC\u4F1A\u81EA\u52A8\u505A\u4E09\u4EF6\u4E8B\uFF1A\r\n * 1. \u91C7\u96C6\u5F53\u524D\u9875\u9762\u7684 env_patch\uFF1B\r\n * 2. \u5408\u5E76\u663E\u5F0F\u4F20\u5165\u7684 env_patch\uFF1B\r\n * 3. \u4E00\u5E76\u5199\u5165 dataset\uFF0C\u4F9B\u540E\u7AEF\u56DE\u5199 runtime_env_json\u3002\r\n * @param {Object} data - \u8981\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\r\n */\r\n async pushSuccess(data, options = {}) {\r\n const runtimeContext = getRuntimeContext();\r\n const page = pickPage(options?.page, data?.page, lastPage);\r\n if (page) {\r\n lastPage = page;\r\n }\r\n\r\n let payloadData = data;\r\n let explicitPatch = null;\r\n if (data && typeof data === 'object' && !Array.isArray(data)) {\r\n payloadData = { ...data };\r\n explicitPatch = payloadData.env_patch;\r\n delete payloadData.env_patch;\r\n delete payloadData.page;\r\n }\r\n\r\n const capturedPatch = await captureAutoEnvPatch(page, runtimeContext);\r\n const envPatch = RuntimeEnv.mergeEnvPatches(runtimeContext.envPatch, capturedPatch, explicitPatch);\r\n const traffic = await ProxyMeterRuntime.getProxyMeterSnapshot({ finalize: true });\r\n const payload = {\r\n code: Code.Success,\r\n status: Status.Success,\r\n ...(traffic ? { traffic } : {}),\r\n timestamp: new Date().toISOString(),\r\n data: payloadData,\r\n };\r\n if (envPatch) {\r\n payload.env_patch = envPatch;\r\n }\r\n await Actor.pushData({\r\n ...payload,\r\n });\r\n logger.success('pushSuccess', 'Data pushed');\r\n },\r\n\r\n /**\r\n * \u63A8\u9001\u5931\u8D25\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\uFF08\u79C1\u6709\u65B9\u6CD5\uFF0C\u4EC5\u4F9B runStep \u5185\u90E8\u4F7F\u7528\uFF09\u3002\r\n * \u5373\u4FBF\u4EFB\u52A1\u5931\u8D25\uFF0C\u8FD9\u91CC\u4E5F\u4F1A\u81EA\u52A8\u56DE\u6536 env_patch\uFF0C\u786E\u4FDD cookies/storage \u7684\u6700\u65B0\u72B6\u6001\u4E0D\u4F1A\u4E22\u3002\r\n * @param {Error|CrawlerError} error - \u9519\u8BEF\u5BF9\u8C61\r\n * @param {Object} [meta] - \u989D\u5916\u7684\u6570\u636E\uFF08\u5982 failedStep\u3001screenshotBase64 \u7B49\uFF09\r\n * @param {Object} [options] - \u9644\u52A0\u9009\u9879\uFF08\u5982 page\uFF09\r\n * @private\r\n */\r\n async pushFailed(error, meta = {}, options = {}) {\r\n const runtimeContext = getRuntimeContext();\r\n const page = pickPage(options?.page, meta?.page, lastPage);\r\n if (page) {\r\n lastPage = page;\r\n }\r\n const capturedPatch = await captureAutoEnvPatch(page, runtimeContext);\r\n const explicitPatch = meta?.env_patch;\r\n const envPatch = RuntimeEnv.mergeEnvPatches(runtimeContext.envPatch, capturedPatch, explicitPatch);\r\n const safeMeta = sanitizeMeta(meta);\r\n delete safeMeta.env_patch;\r\n\r\n // \u5982\u679C\u662F CrawlerError\uFF0C\u63D0\u53D6\u5176 key \u548C context\r\n const isCrawlerError = CrawlerError.isCrawlerError(error);\r\n const code = isCrawlerError ? error.code : Code.UnknownError;\r\n const context = isCrawlerError ? error.context : {};\r\n const traffic = await ProxyMeterRuntime.getProxyMeterSnapshot({ finalize: true });\r\n const payload = {\r\n // \u5982\u679C\u662F CrawlerError\uFF0C\u4F7F\u7528\u5176 code\uFF0C\u5426\u5219\u4F7F\u7528\u9ED8\u8BA4 Failed code\r\n code,\r\n status: Status.Failed,\r\n ...(traffic ? { traffic } : {}),\r\n error: serializeError(error),\r\n meta: safeMeta,\r\n context,\r\n timestamp: new Date().toISOString(),\r\n };\r\n if (envPatch) {\r\n payload.env_patch = envPatch;\r\n }\r\n\r\n await Actor.pushData({\r\n ...payload,\r\n });\r\n logger.success('pushFailed', 'Error data pushed');\r\n }\r\n };\r\n}\r\n\r\n// \u61D2\u52A0\u8F7D\u5355\u4F8B\r\nlet instance = null;\r\n\r\n/**\r\n * \u83B7\u53D6 ApifyKit \u5B9E\u4F8B\uFF08\u61D2\u52A0\u8F7D\uFF09\r\n * @returns {Promise<Object>} ApifyKit \u5B9E\u4F8B\r\n */\r\nasync function useApifyKit() {\r\n if (!instance) {\r\n instance = await createApifyKit();\r\n }\r\n return instance;\r\n}\r\n\r\n// \u4E5F\u5BFC\u51FA\u521D\u59CB\u5316\u51FD\u6570\uFF0C\u4F9B\u9700\u8981\u7684\u7528\u6237\u4F7F\u7528\r\nexport const ApifyKit = {\r\n useApifyKit\r\n};\r\n", "import { spawn, spawnSync } from 'child_process';\r\nimport { existsSync, mkdirSync, readFileSync, rmSync } from 'fs';\r\nimport { tmpdir } from 'os';\r\nimport path from 'path';\r\nimport { fileURLToPath } from 'url';\r\nimport { createInternalLogger } from './logger.js';\r\n\r\nconst logger = createInternalLogger('ProxyMeter');\r\n\r\nconst MAX_TOP_DOMAINS = 20;\r\nconst FLUSH_INTERVAL_MS = 2000;\r\nconst DEFAULT_DEBUG_MAX_EVENTS = 400;\r\n\r\nlet runtime = null;\r\nlet cleanupInstalled = false;\r\nlet observedDomainResourceTypes = new Map();\r\n\r\nconst toSafeInt = (value) => {\r\n const num = Number(value);\r\n if (!Number.isFinite(num) || num <= 0) return 0;\r\n return Math.round(num);\r\n};\r\n\r\nconst toSafeFloat = (value) => {\r\n const num = Number(value);\r\n if (!Number.isFinite(num)) return 0;\r\n return num;\r\n};\r\n\r\nconst normalizeResourceType = (value) => {\r\n const type = String(value || '').trim().toLowerCase();\r\n if (!type) return 'other';\r\n return type;\r\n};\r\n\r\nconst resolveHostname = (requestUrl) => {\r\n const raw = String(requestUrl || '').trim();\r\n if (!raw) return '';\r\n try {\r\n return String(new URL(raw).hostname || '').trim().toLowerCase();\r\n } catch {\r\n return '';\r\n }\r\n};\r\n\r\nconst recordDomainResourceType = (domain, resourceType) => {\r\n const host = String(domain || '').trim().toLowerCase();\r\n if (!host) return;\r\n const type = normalizeResourceType(resourceType);\r\n let byType = observedDomainResourceTypes.get(host);\r\n if (!byType) {\r\n byType = new Map();\r\n observedDomainResourceTypes.set(host, byType);\r\n }\r\n byType.set(type, (byType.get(type) || 0) + 1);\r\n};\r\n\r\nconst resolveResourceTypeMeta = (domain) => {\r\n const host = String(domain || '').trim().toLowerCase();\r\n if (!host) return { resourceType: '', resourceTypeCounts: undefined };\r\n const byType = observedDomainResourceTypes.get(host);\r\n if (!byType || byType.size === 0) {\r\n return { resourceType: '', resourceTypeCounts: undefined };\r\n }\r\n const entries = Array.from(byType.entries())\r\n .filter(([type, count]) => type && Number(count) > 0)\r\n .sort((a, b) => {\r\n if (Number(b[1]) !== Number(a[1])) return Number(b[1]) - Number(a[1]);\r\n return String(a[0]).localeCompare(String(b[0]));\r\n });\r\n if (entries.length === 0) {\r\n return { resourceType: '', resourceTypeCounts: undefined };\r\n }\r\n return {\r\n resourceType: entries[0][0],\r\n resourceTypeCounts: Object.fromEntries(entries.map(([type, count]) => [type, toSafeInt(count)])),\r\n };\r\n};\r\n\r\nconst resolveScriptPath = () => {\r\n const baseDir = typeof __dirname !== 'undefined'\r\n ? __dirname\r\n : path.dirname(fileURLToPath(import.meta.url));\r\n const internalCandidate = path.join(baseDir, 'internals', 'proxy-meter.js');\r\n if (existsSync(internalCandidate)) {\r\n return internalCandidate;\r\n }\r\n return path.join(baseDir, 'proxy-meter.js');\r\n};\r\n\r\nconst pickFreePort = () => {\r\n const script = [\r\n 'const net=require(\"net\");',\r\n 'const server=net.createServer();',\r\n 'server.listen(0,\"127.0.0.1\",()=>{',\r\n 'const port=server.address().port;',\r\n 'server.close(()=>{console.log(port);});',\r\n '});',\r\n ].join('');\r\n const result = spawnSync(process.execPath, ['-e', script], { encoding: 'utf8' });\r\n const port = Number(String(result.stdout || '').trim());\r\n if (result.status === 0 && Number.isFinite(port) && port > 0) {\r\n return port;\r\n }\r\n return 20000 + Math.floor(Math.random() * 20000);\r\n};\r\n\r\nconst resolveLogDir = () => {\r\n const storageDir = process.env.APIFY_STORAGE_DIR || process.env.APIFY_LOCAL_STORAGE_DIR || '';\r\n if (storageDir) {\r\n return path.join(storageDir, 'proxy-meter');\r\n }\r\n return path.join(tmpdir(), 'proxy-meter');\r\n};\r\n\r\nconst ensureLogPath = () => {\r\n const baseDir = resolveLogDir();\r\n if (!existsSync(baseDir)) {\r\n try {\r\n mkdirSync(baseDir, { recursive: true });\r\n } catch {}\r\n }\r\n const runId = String(process.env.APIFY_ACTOR_RUN_ID || '').trim();\r\n const suffix = `${Date.now()}-${Math.floor(Math.random() * 1000000)}`;\r\n const label = runId ? `proxy-meter-${runId}-${suffix}.json` : `proxy-meter-${process.pid}-${suffix}.json`;\r\n return path.join(baseDir, label);\r\n};\r\n\r\nconst readSnapshot = (logPath) => {\r\n if (!logPath || !existsSync(logPath)) return null;\r\n try {\r\n const raw = readFileSync(logPath, 'utf8');\r\n if (!raw) return null;\r\n return JSON.parse(raw);\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\nconst normalizeDomainRows = (hosts) => {\r\n const rows = [];\r\n let requestCount = 0;\r\n let connectCount = 0;\r\n\r\n for (const [domain, stat] of Object.entries(hosts || {})) {\r\n if (!stat || typeof stat !== 'object') continue;\r\n const inBytes = toSafeInt(stat.inBytes);\r\n const outBytes = toSafeInt(stat.outBytes);\r\n const requests = toSafeInt(stat.requests);\r\n const connections = toSafeInt(stat.connections);\r\n const totalBytes = inBytes + outBytes;\r\n requestCount += requests;\r\n connectCount += connections;\r\n if (totalBytes <= 0 && requests <= 0 && connections <= 0) continue;\r\n const resourceTypeMeta = resolveResourceTypeMeta(domain);\r\n rows.push({\r\n domain,\r\n inBytes,\r\n outBytes,\r\n totalBytes,\r\n requests,\r\n connections,\r\n resourceType: resourceTypeMeta.resourceType || undefined,\r\n resourceTypeCounts: resourceTypeMeta.resourceTypeCounts || undefined,\r\n });\r\n }\r\n\r\n rows.sort((a, b) => {\r\n if (b.totalBytes !== a.totalBytes) return b.totalBytes - a.totalBytes;\r\n if (b.requests !== a.requests) return b.requests - a.requests;\r\n return String(a.domain).localeCompare(String(b.domain));\r\n });\r\n\r\n return {\r\n topDomains: rows.slice(0, MAX_TOP_DOMAINS),\r\n requestCount,\r\n connectCount,\r\n };\r\n};\r\n\r\nconst normalizeDebugRows = (rows, type) => {\r\n if (!Array.isArray(rows) || rows.length === 0) return undefined;\r\n const normalized = rows\r\n .map((row) => {\r\n if (!row || typeof row !== 'object') return null;\r\n return {\r\n domain: String(row.domain || '').trim(),\r\n status: String(row.status || '').trim(),\r\n count: toSafeInt(row.count),\r\n failedCount: toSafeInt(row.failedCount),\r\n inBytes: toSafeInt(row.inBytes),\r\n outBytes: toSafeInt(row.outBytes),\r\n totalBytes: toSafeInt(row.totalBytes),\r\n avgDurationMs: toSafeFloat(row.avgDurationMs),\r\n reconnectCount: toSafeInt(row.reconnectCount),\r\n largeResponseCount: toSafeInt(row.largeResponseCount),\r\n failureRatePct: toSafeFloat(row.failureRatePct),\r\n type,\r\n };\r\n })\r\n .filter((row) => row && row.domain && row.count > 0);\r\n return normalized.length > 0 ? normalized : undefined;\r\n};\r\n\r\nconst normalizeDebugEvent = (row) => {\r\n if (!row || typeof row !== 'object') return null;\r\n const host = String(row.host || '').trim();\r\n if (!host) return null;\r\n return {\r\n ts: String(row.ts || ''),\r\n runId: String(row.runId || ''),\r\n channel: String(row.channel || ''),\r\n host,\r\n method: String(row.method || ''),\r\n path: String(row.path || ''),\r\n statusCode: toSafeInt(row.statusCode),\r\n durationMs: toSafeInt(row.durationMs),\r\n inBytes: toSafeInt(row.inBytes),\r\n outBytes: toSafeInt(row.outBytes),\r\n totalBytes: toSafeInt(row.totalBytes),\r\n error: String(row.error || ''),\r\n };\r\n};\r\n\r\nconst normalizeDebugSummary = (debug) => {\r\n if (!debug || typeof debug !== 'object' || !debug.summary || typeof debug.summary !== 'object') {\r\n return null;\r\n }\r\n const summary = debug.summary;\r\n const domainStatus = normalizeDebugRows(summary.domainStatus, 'domain_status');\r\n const topFailureDomains = normalizeDebugRows(summary.topFailureDomains, 'top_failure');\r\n const topLargeDomains = normalizeDebugRows(summary.topLargeDomains, 'top_large');\r\n const topReconnectDomains = normalizeDebugRows(summary.topReconnectDomains, 'top_reconnect');\r\n\r\n return {\r\n enabled: Boolean(debug.enabled),\r\n sampledEvents: toSafeInt(debug.sampledEvents),\r\n droppedEvents: toSafeInt(debug.droppedEvents),\r\n totalEvents: toSafeInt(debug.totalEvents),\r\n largeResponseThresholdBytes: toSafeInt(summary.largeResponseThresholdBytes),\r\n requestCount: toSafeInt(summary.requestCount),\r\n failedCount: toSafeInt(summary.failedCount),\r\n failureRatePct: toSafeFloat(summary.failureRatePct),\r\n largeResponseCount: toSafeInt(summary.largeResponseCount),\r\n reconnectCount: toSafeInt(summary.reconnectCount),\r\n domainStatus,\r\n topFailureDomains,\r\n topLargeDomains,\r\n topReconnectDomains,\r\n };\r\n};\r\n\r\nconst normalizeSnapshot = (raw) => {\r\n if (!raw || typeof raw !== 'object') return null;\r\n const totalIn = toSafeInt(raw.totalInBytes);\r\n const totalOut = toSafeInt(raw.totalOutBytes);\r\n const domains = normalizeDomainRows(raw.hosts && typeof raw.hosts === 'object' ? raw.hosts : {});\r\n\r\n const normalized = {\r\n meter: 'proxy-meter-v1',\r\n totalBytes: totalIn + totalOut,\r\n uploadBytes: totalOut,\r\n downloadBytes: totalIn,\r\n requestCount: domains.requestCount,\r\n connectCount: domains.connectCount,\r\n topDomains: domains.topDomains,\r\n };\r\n\r\n const debug = raw.debug && typeof raw.debug === 'object' ? raw.debug : null;\r\n const summary = normalizeDebugSummary(debug);\r\n const events = Array.isArray(debug?.events)\r\n ? debug.events.map(normalizeDebugEvent).filter(Boolean)\r\n : [];\r\n if (summary) {\r\n normalized.trafficDebugSummary = summary;\r\n }\r\n if (events.length > 0) {\r\n normalized.trafficDebugEvents = events;\r\n }\r\n\r\n const hasSignal = normalized.totalBytes > 0\r\n || normalized.uploadBytes > 0\r\n || normalized.downloadBytes > 0\r\n || normalized.requestCount > 0\r\n || normalized.connectCount > 0\r\n || (normalized.topDomains && normalized.topDomains.length > 0)\r\n || Boolean(summary)\r\n || events.length > 0;\r\n\r\n if (!hasSignal) return null;\r\n return normalized;\r\n};\r\n\r\nconst registerCleanup = () => {\r\n if (cleanupInstalled) return;\r\n cleanupInstalled = true;\r\n const shutdown = () => {\r\n if (!runtime || !runtime.proc) return;\r\n try { runtime.proc.kill('SIGTERM'); } catch {}\r\n };\r\n process.once('exit', shutdown);\r\n process.once('SIGINT', shutdown);\r\n process.once('SIGTERM', shutdown);\r\n};\r\n\r\nconst startProxyMeter = (options = {}) => {\r\n const upstreamUrl = String(options.proxyUrl || '').trim();\r\n if (!upstreamUrl) return null;\r\n\r\n if (runtime && runtime.proc) {\r\n try { runtime.proc.kill('SIGTERM'); } catch {}\r\n runtime = null;\r\n }\r\n observedDomainResourceTypes = new Map();\r\n\r\n const port = pickFreePort();\r\n const logPath = ensureLogPath();\r\n const scriptPath = resolveScriptPath();\r\n const debugMode = Boolean(options.debugMode);\r\n const debugMaxEvents = Math.max(10, toSafeInt(options.debugMaxEvents) || DEFAULT_DEBUG_MAX_EVENTS);\r\n const env = {\r\n ...process.env,\r\n PROXY_METER_PORT: String(port),\r\n PROXY_METER_LOG: logPath,\r\n PROXY_METER_UPSTREAM: upstreamUrl,\r\n PROXY_METER_FLUSH_MS: String(FLUSH_INTERVAL_MS),\r\n PROXY_METER_DEBUG: debugMode ? '1' : '0',\r\n PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents),\r\n };\r\n\r\n const child = spawn(process.execPath, [scriptPath], {\r\n env,\r\n stdio: ['ignore', 'ignore', 'ignore'],\r\n });\r\n\r\n child.once('exit', (code) => {\r\n if (code && code !== 0) {\r\n logger.warn(`[proxy-meter] exited with code ${code}`);\r\n }\r\n });\r\n\r\n runtime = {\r\n proc: child,\r\n port,\r\n logPath,\r\n startedAt: Date.now(),\r\n };\r\n\r\n registerCleanup();\r\n return { server: `http://127.0.0.1:${port}` };\r\n};\r\n\r\nconst recordProxyMeterResourceType = (requestUrl, resourceType) => {\r\n if (!runtime) return;\r\n const host = resolveHostname(requestUrl);\r\n if (!host) return;\r\n recordDomainResourceType(host, resourceType);\r\n};\r\n\r\nconst stopProxyMeter = async () => {\r\n if (!runtime) return null;\r\n const { proc, logPath } = runtime;\r\n if (!proc || proc.killed) {\r\n runtime = null;\r\n return logPath || null;\r\n }\r\n\r\n await new Promise((resolve) => {\r\n const timeout = setTimeout(() => {\r\n try { proc.kill('SIGKILL'); } catch {}\r\n resolve();\r\n }, 2000);\r\n proc.once('exit', () => {\r\n clearTimeout(timeout);\r\n resolve();\r\n });\r\n try { proc.kill('SIGTERM'); } catch { resolve(); }\r\n });\r\n\r\n runtime = null;\r\n return logPath || null;\r\n};\r\n\r\nconst getProxyMeterSnapshot = async (options = {}) => {\r\n if (!runtime) return null;\r\n const finalize = Boolean(options.finalize);\r\n const logPath = finalize ? await stopProxyMeter() : runtime.logPath;\r\n const raw = readSnapshot(logPath);\r\n const snapshot = normalizeSnapshot(raw);\r\n if (finalize && logPath) {\r\n try { rmSync(logPath, { force: true }); } catch {}\r\n }\r\n return snapshot;\r\n};\r\n\r\nexport const ProxyMeterRuntime = {\r\n startProxyMeter,\r\n recordProxyMeterResourceType,\r\n stopProxyMeter,\r\n getProxyMeterSnapshot,\r\n};\r\n", "const BROWSER_PROFILE_SCHEMA_VERSION = 1;\r\n\r\nlet rememberedRuntimeState = null;\r\n\r\nconst isPlainObject = (value) => value && typeof value === 'object' && !Array.isArray(value);\r\n\r\n// \u8FD0\u884C\u6001\u5FEB\u7167\u5728 visitor / toolkit / \u540E\u7AEF\u4E4B\u95F4\u6765\u56DE\u4F20\u9012\uFF0C\r\n// \u6240\u4EE5\u6240\u6709\u5165\u53E3\u90FD\u5148\u8D70 deepClone\uFF0C\u907F\u514D\u5171\u4EAB\u5F15\u7528\u5F15\u53D1\u201C\u8FB9\u8DD1\u8FB9\u6539\u201D\u7684\u9690\u5F0F\u526F\u4F5C\u7528\u3002\r\nconst deepClone = (value) => {\r\n if (value == null) return value;\r\n try {\r\n return JSON.parse(JSON.stringify(value));\r\n } catch {\r\n return value;\r\n\t}\r\n};\r\n\r\n// \u5C1D\u8BD5\u628A runtime / browser_profile \u4E4B\u7C7B\u7684 JSON \u5B57\u6BB5\u89E3\u6790\u6210\u5BF9\u8C61\u3002\r\nconst tryParseJSON = (value) => {\r\n if (value == null) return null;\r\n if (typeof value === 'object') return value;\r\n const raw = String(value || '').trim();\r\n if (!raw) return null;\r\n try {\r\n return JSON.parse(raw);\r\n } catch {\r\n return null;\r\n\t}\r\n};\r\n\r\n// local/session/auth \u7684\u89C4\u8303\u5316\u76EE\u6807\u53EA\u6709\u4E00\u4E2A\uFF1A\u8FC7\u6EE4\u7A7A\u503C\uFF0C\u7EDF\u4E00\u8F6C\u6210\u5B57\u7B26\u4E32\u3002\r\nconst normalizeLocalStorage = (value) => {\r\n const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};\r\n return Object.entries(source).reduce((acc, [key, item]) => {\r\n const safeKey = String(key || '').trim();\r\n const safeValue = String(item ?? '').trim();\r\n if (!safeKey || !safeValue || safeValue === '<nil>') return acc;\r\n acc[safeKey] = safeValue;\r\n return acc;\r\n }, {});\r\n};\r\n\r\nconst normalizeSessionStorage = (value) => {\r\n const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};\r\n return Object.entries(source).reduce((acc, [key, item]) => {\r\n const safeKey = String(key || '').trim();\r\n const safeValue = String(item ?? '').trim();\r\n if (!safeKey || !safeValue || safeValue === '<nil>') return acc;\r\n acc[safeKey] = safeValue;\r\n return acc;\r\n }, {});\r\n};\r\n\r\nconst normalizeAuth = (value) => {\r\n const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};\r\n return Object.entries(source).reduce((acc, [key, item]) => {\r\n const safeKey = String(key || '').trim();\r\n const safeValue = String(item ?? '').trim();\r\n if (!safeKey || !safeValue || safeValue === '<nil>') return acc;\r\n acc[safeKey] = safeValue;\r\n return acc;\r\n }, {});\r\n};\r\n\r\nconst normalizeCookieSameSite = (value) => {\r\n const raw = String(value || '').trim().toLowerCase();\r\n if (!raw) return '';\r\n\r\n switch (raw) {\r\n case 'strict':\r\n return 'Strict';\r\n case 'lax':\r\n return 'Lax';\r\n case 'none':\r\n case 'no_restriction':\r\n return 'None';\r\n case 'unspecified':\r\n default:\r\n return '';\r\n }\r\n};\r\n\r\nconst normalizeCookieExpires = (raw = {}) => {\r\n const source = raw && typeof raw === 'object' ? raw : {};\r\n const session = Boolean(source.session);\r\n if (session) return null;\r\n\r\n const expiresCandidate = Number(source.expires);\r\n if (Number.isFinite(expiresCandidate) && expiresCandidate > 0) {\r\n return expiresCandidate;\r\n }\r\n\r\n const expirationDateCandidate = Number(source.expirationDate);\r\n if (Number.isFinite(expirationDateCandidate) && expirationDateCandidate > 0) {\r\n return expirationDateCandidate;\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst normalizeCookies = (value) => {\r\n if (!Array.isArray(value)) return [];\r\n return value\r\n .map((item) => {\r\n const raw = item && typeof item === 'object' ? item : {};\r\n const name = String(raw.name || '').trim();\r\n const cookieValue = String(raw.value ?? '').trim();\r\n if (!name || !cookieValue || cookieValue === '<nil>') return null;\r\n const domain = String(raw.domain || '').trim();\r\n const url = normalizeHttpUrl(raw.url);\r\n const path = String(raw.path || '').trim() || '/';\r\n const sameSite = normalizeCookieSameSite(raw.sameSite);\r\n const expires = normalizeCookieExpires(raw);\r\n const secure = Boolean(raw.secure);\r\n const httpOnly = Boolean(raw.httpOnly);\r\n const partitionKey = typeof raw.partitionKey === 'string' ? String(raw.partitionKey).trim() : '';\r\n\r\n // \u7EDF\u4E00\u8F93\u51FA Playwright \u53EF\u63A5\u53D7\u7684 Cookie \u7ED3\u6784\uFF0C\u907F\u514D\u628A Chrome \u6269\u5C55\u4FA7\u5B57\u6BB5\u539F\u6837\u900F\u4F20\u8FC7\u53BB\u3002\r\n const normalized = {\r\n name,\r\n value: cookieValue,\r\n path,\r\n ...(domain ? { domain } : {}),\r\n ...(!domain && url ? { url } : {}),\r\n ...(sameSite ? { sameSite } : {}),\r\n ...(secure ? { secure: true } : {}),\r\n ...(httpOnly ? { httpOnly: true } : {}),\r\n ...(expires !== null ? { expires } : {}),\r\n ...(partitionKey ? { partitionKey } : {}),\r\n };\r\n\r\n if (!normalized.domain && !normalized.url) {\r\n return null;\r\n }\r\n\r\n return {\r\n ...normalized,\r\n };\r\n })\r\n .filter(Boolean);\r\n};\r\n\r\nconst buildCookieMap = (cookies) => cookies.reduce((acc, item) => {\r\n\tacc[item.name] = item.value;\r\n\treturn acc;\r\n}, {});\r\n\r\n// \u7EDF\u4E00\u628A\u539F\u59CB URL \u5FEB\u7167\u8FC7\u6EE4\u6210 http/https\uFF0C\u907F\u514D browser/runtime \u4E24\u7AEF\u5404\u81EA\u505A\u4E00\u5957\u5224\u65AD\u3002\r\nconst normalizeHttpUrl = (value) => {\r\n const raw = String(value || '').trim();\r\n if (!raw) return '';\r\n try {\r\n const parsed = new URL(raw);\r\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return '';\r\n parsed.hash = '';\r\n return parsed.toString();\r\n } catch {\r\n return '';\r\n }\r\n};\r\n\r\nconst uniqueStrings = (value) => {\r\n const list = Array.isArray(value) ? value : [];\r\n const seen = new Set();\r\n const result = [];\r\n list.forEach((item) => {\r\n const normalized = String(item || '').trim();\r\n if (!normalized || seen.has(normalized)) return;\r\n seen.add(normalized);\r\n result.push(normalized);\r\n });\r\n return result;\r\n};\r\n\r\nconst normalizeHttpUrlList = (value) => uniqueStrings(\r\n (Array.isArray(value) ? value : [value])\r\n .map((item) => normalizeHttpUrl(item))\r\n .filter(Boolean),\r\n);\r\n\r\nconst normalizeCookieDomain = (value) => String(value || '').trim().replace(/^\\./, '').toLowerCase();\r\n\r\nconst normalizeCookiePath = (value) => {\r\n const raw = String(value || '').trim();\r\n if (!raw) return '/';\r\n return raw.startsWith('/') ? raw : `/${raw}`;\r\n};\r\n\r\nconst doesCookieMatchUrl = (cookie, url) => {\r\n if (!cookie || !url) return false;\r\n try {\r\n const parsed = new URL(url);\r\n const host = String(parsed.hostname || '').trim().toLowerCase();\r\n const pathname = String(parsed.pathname || '/').trim() || '/';\r\n const cookieDomain = normalizeCookieDomain(cookie.domain);\r\n const cookiePath = normalizeCookiePath(cookie.path);\r\n if (!host || !cookieDomain) return false;\r\n const domainMatched = host === cookieDomain || host.endsWith(`.${cookieDomain}`);\r\n if (!domainMatched) return false;\r\n if (cookie.secure && parsed.protocol !== 'https:') return false;\r\n return pathname.startsWith(cookiePath);\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\nconst normalizeRawSnapshot = (value = {}) => {\r\n const source = isPlainObject(value) ? value : {};\r\n const pageUrl = normalizeHttpUrl(source.page_url ?? source.pageUrl);\r\n const frameUrls = normalizeHttpUrlList(source.frame_urls ?? source.frameUrls);\r\n const resourceUrls = normalizeHttpUrlList(source.resource_urls ?? source.resourceUrls);\r\n const browserProfileObservedSource =\r\n source.browser_profile_observed\r\n ?? source.browserProfileObserved\r\n ?? source.browser_profile?.observed\r\n ?? source.browserProfile?.observed\r\n ?? source.browserProfile;\r\n\r\n return {\r\n page_url: pageUrl,\r\n frame_urls: frameUrls,\r\n resource_urls: resourceUrls,\r\n cookies: Array.isArray(source.cookies) ? deepClone(source.cookies) : [],\r\n local_storage: normalizeLocalStorage(source.local_storage ?? source.localStorage),\r\n session_storage: normalizeSessionStorage(source.session_storage ?? source.sessionStorage),\r\n browser_profile_observed: normalizeObservedBrowserProfile(browserProfileObservedSource),\r\n auth: normalizeAuth(source.auth),\r\n };\r\n};\r\n\r\nconst collectCookieUrlsFromSnapshot = (snapshot = {}) => {\r\n const normalized = normalizeRawSnapshot(snapshot);\r\n return uniqueStrings([\r\n normalized.page_url,\r\n ...normalized.frame_urls,\r\n ...normalized.resource_urls,\r\n ].filter(Boolean));\r\n};\r\n\r\nconst filterCookiesBySnapshot = (cookies = [], snapshot = {}) => {\r\n const normalizedCookies = normalizeCookies(cookies);\r\n const cookieUrls = collectCookieUrlsFromSnapshot(snapshot);\r\n if (cookieUrls.length === 0) {\r\n return normalizedCookies;\r\n }\r\n return normalizedCookies.filter((cookie) => cookieUrls.some((url) => doesCookieMatchUrl(cookie, url)));\r\n};\r\n\r\nconst buildEnvPayloadFromSnapshot = (snapshot = {}, options = {}) => {\r\n const normalized = normalizeRawSnapshot(snapshot);\r\n const cookies = filterCookiesBySnapshot(snapshot?.cookies || normalized.cookies, normalized);\r\n const localStorage = normalized.local_storage;\r\n const sessionStorage = normalized.session_storage;\r\n const auth = normalizeAuth(options.auth ?? normalized.auth);\r\n const browserProfileCore = normalizeBrowserProfileCore(\r\n options.browserProfileCore\r\n ?? snapshot?.browser_profile?.core\r\n ?? snapshot?.browserProfile?.core,\r\n );\r\n const browserProfile = buildBrowserProfilePayload(browserProfileCore, normalized.browser_profile_observed);\r\n\r\n const payload = {\r\n ...(cookies.length > 0 ? { cookies } : {}),\r\n ...(Object.keys(localStorage).length > 0 ? { local_storage: localStorage } : {}),\r\n ...(Object.keys(sessionStorage).length > 0 ? { session_storage: sessionStorage } : {}),\r\n ...(Object.keys(auth).length > 0 ? { auth } : {}),\r\n ...(Object.keys(browserProfile).length > 0 ? { browser_profile: browserProfile } : {}),\r\n };\r\n return Object.keys(payload).length > 0 ? payload : null;\r\n};\r\n\r\nconst captureRawSnapshotFromPage = async (page) => {\r\n const frameUrls = typeof page?.frames === 'function'\r\n ? page.frames().map((frame) => {\r\n try {\r\n return frame.url();\r\n } catch {\r\n return '';\r\n }\r\n })\r\n : [];\r\n\r\n const snapshot = await page.evaluate(() => {\r\n const localStorage = {};\r\n const sessionStorage = {};\r\n const resourceUrls = [];\r\n const frameUrls = [];\r\n\r\n try {\r\n for (let i = 0; i < window.localStorage.length; i += 1) {\r\n const key = window.localStorage.key(i);\r\n if (!key) continue;\r\n const value = window.localStorage.getItem(key);\r\n if (value !== null) localStorage[key] = value;\r\n }\r\n } catch {\r\n // ignore\r\n }\r\n\r\n try {\r\n for (let i = 0; i < window.sessionStorage.length; i += 1) {\r\n const key = window.sessionStorage.key(i);\r\n if (!key) continue;\r\n const value = window.sessionStorage.getItem(key);\r\n if (value !== null) sessionStorage[key] = value;\r\n }\r\n } catch {\r\n // ignore\r\n }\r\n\r\n try {\r\n const perfEntries = performance.getEntriesByType('resource') || [];\r\n perfEntries.forEach((entry) => {\r\n const name = String(entry?.name || '').trim();\r\n if (name) resourceUrls.push(name);\r\n });\r\n } catch {\r\n // ignore\r\n }\r\n\r\n try {\r\n document.querySelectorAll('iframe,frame').forEach((node) => {\r\n const src = String(node?.src || '').trim();\r\n if (src) frameUrls.push(src);\r\n });\r\n } catch {\r\n // ignore\r\n }\r\n\r\n const nav = window.navigator || {};\r\n const screen = window.screen || {};\r\n const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || '';\r\n\r\n return {\r\n page_url: window.location.href || '',\r\n frame_urls: frameUrls,\r\n resource_urls: resourceUrls,\r\n local_storage: localStorage,\r\n session_storage: sessionStorage,\r\n browser_profile_observed: {\r\n user_agent: nav.userAgent || '',\r\n platform: nav.platform || '',\r\n language: nav.language || '',\r\n languages: Array.isArray(nav.languages) ? nav.languages : [],\r\n hardware_concurrency: Number(nav.hardwareConcurrency || 0),\r\n device_memory: Number(nav.deviceMemory || 0),\r\n timezone,\r\n viewport: {\r\n width: Number(window.innerWidth || 0),\r\n height: Number(window.innerHeight || 0),\r\n },\r\n screen: {\r\n width: Number(screen.width || 0),\r\n height: Number(screen.height || 0),\r\n avail_width: Number(screen.availWidth || 0),\r\n avail_height: Number(screen.availHeight || 0),\r\n color_depth: Number(screen.colorDepth || 0),\r\n pixel_depth: Number(screen.pixelDepth || 0),\r\n },\r\n },\r\n };\r\n });\r\n\r\n return normalizeRawSnapshot({\r\n ...snapshot,\r\n frame_urls: [...frameUrls, ...(snapshot?.frame_urls || [])],\r\n });\r\n};\r\n\r\n// observed \u53EA\u4FDD\u5B58\u201C\u8FD0\u884C\u540E\u770B\u5230\u7684\u6D4F\u89C8\u5668\u8868\u73B0\u201D\uFF0C\u5B83\u4E0D\u662F\u542F\u52A8\u771F\u6E90\u3002\r\nconst normalizeObservedBrowserProfile = (value) => {\r\n const source = isPlainObject(value) ? value : {};\r\n const profile = {};\r\n\r\n const stringFields = {\r\n user_agent: source.user_agent,\r\n platform: source.platform,\r\n language: source.language,\r\n timezone: source.timezone,\r\n };\r\n Object.entries(stringFields).forEach(([key, item]) => {\r\n const safeValue = String(item || '').trim();\r\n if (safeValue) {\r\n profile[key] = safeValue;\r\n }\r\n });\r\n\r\n if (Array.isArray(source.languages)) {\r\n const languages = source.languages\r\n .map((item) => String(item || '').trim())\r\n .filter(Boolean);\r\n if (languages.length > 0) {\r\n profile.languages = languages;\r\n }\r\n }\r\n\r\n const numericFields = {\r\n hardware_concurrency: Number(source.hardware_concurrency || 0),\r\n device_memory: Number(source.device_memory || 0),\r\n };\r\n Object.entries(numericFields).forEach(([key, item]) => {\r\n if (Number.isFinite(item) && item > 0) {\r\n profile[key] = item;\r\n }\r\n });\r\n\r\n if (isPlainObject(source.viewport)) {\r\n const width = Number(source.viewport.width || 0);\r\n const height = Number(source.viewport.height || 0);\r\n if (width > 0 && height > 0) {\r\n profile.viewport = { width, height };\r\n }\r\n }\r\n\r\n if (isPlainObject(source.screen)) {\r\n const screenProfile = {};\r\n const screenFields = {\r\n width: Number(source.screen.width || 0),\r\n height: Number(source.screen.height || 0),\r\n avail_width: Number(source.screen.avail_width || 0),\r\n avail_height: Number(source.screen.avail_height || 0),\r\n color_depth: Number(source.screen.color_depth || 0),\r\n pixel_depth: Number(source.screen.pixel_depth || 0),\r\n };\r\n Object.entries(screenFields).forEach(([key, item]) => {\r\n if (Number.isFinite(item) && item > 0) {\r\n screenProfile[key] = item;\r\n }\r\n });\r\n if (Object.keys(screenProfile).length > 0) {\r\n profile.screen = screenProfile;\r\n }\r\n }\r\n\r\n\treturn profile;\r\n};\r\n\r\n// core \u662F\u6D4F\u89C8\u5668\u73AF\u5883\u7684\u552F\u4E00\u771F\u6E90\uFF1A\r\n// fingerprint / timezone_id / locale / browser_major_version \u90FD\u5728\u8FD9\u91CC\u3002\r\nconst normalizeBrowserProfileCore = (value) => {\r\n const source = isPlainObject(value) ? value : {};\r\n const profile = {};\r\n\r\n if (isPlainObject(source.fingerprint) && Object.keys(source.fingerprint).length > 0) {\r\n profile.fingerprint = deepClone(source.fingerprint);\r\n }\r\n\r\n const timezoneId = String(source.timezone_id || '').trim();\r\n if (timezoneId) {\r\n profile.timezone_id = timezoneId;\r\n }\r\n\r\n const locale = String(source.locale || '').trim();\r\n if (locale) {\r\n profile.locale = locale;\r\n }\r\n\r\n const browserMajorVersion = Number(source.browser_major_version || 0);\r\n if (Number.isFinite(browserMajorVersion) && browserMajorVersion > 0) {\r\n profile.browser_major_version = browserMajorVersion;\r\n }\r\n\r\n const schemaVersion = Number(source.schema_version || 0);\r\n if (Number.isFinite(schemaVersion) && schemaVersion > 0) {\r\n profile.schema_version = schemaVersion;\r\n } else if (Object.keys(profile).length > 0) {\r\n profile.schema_version = BROWSER_PROFILE_SCHEMA_VERSION;\r\n }\r\n\r\n\treturn profile;\r\n};\r\n\r\n// buildBrowserProfilePayload \u4FDD\u8BC1 browser_profile \u6C38\u8FDC\u53EA\u66B4\u9732 core / observed \u4E24\u5C42\u7ED3\u6784\u3002\r\nconst buildBrowserProfilePayload = (core = {}, observed = {}) => {\r\n const payload = {};\r\n if (isPlainObject(core) && Object.keys(core).length > 0) {\r\n payload.core = core;\r\n }\r\n if (isPlainObject(observed) && Object.keys(observed).length > 0) {\r\n payload.observed = observed;\r\n }\r\n return payload;\r\n};\r\n\r\nconst mergePlainObject = (target = {}, source = {}) => {\r\n const next = isPlainObject(target) ? deepClone(target) : {};\r\n if (!isPlainObject(source)) return next;\r\n\r\n Object.entries(source).forEach(([key, value]) => {\r\n if (!key) return;\r\n if (isPlainObject(value) && isPlainObject(next[key])) {\r\n next[key] = mergePlainObject(next[key], value);\r\n return;\r\n }\r\n next[key] = deepClone(value);\r\n });\r\n\r\n\treturn next;\r\n};\r\n\r\n// mergeBrowserProfilePayload \u7684\u6838\u5FC3\u89C4\u5219\uFF1A\r\n// 1. core \u53EA\u5728\u5F53\u524D\u4E3A\u7A7A\uFF0C\u6216\u6D4F\u89C8\u5668\u5927\u7248\u672C\u51B2\u7A81\u65F6\u624D\u66FF\u6362\uFF1B\r\n// 2. observed \u6BCF\u6B21\u90FD\u5141\u8BB8\u8986\u76D6\u66F4\u65B0\u3002\r\nconst mergeBrowserProfilePayload = (target = {}, source = {}) => {\r\n const current = isPlainObject(target) ? target : {};\r\n const incoming = isPlainObject(source) ? source : {};\r\n const currentCore = normalizeBrowserProfileCore(current.core);\r\n const incomingCore = normalizeBrowserProfileCore(incoming.core);\r\n const currentObserved = normalizeObservedBrowserProfile(current.observed);\r\n const incomingObserved = normalizeObservedBrowserProfile(incoming.observed);\r\n\r\n let mergedCore = currentCore;\r\n if (Object.keys(mergedCore).length === 0 && Object.keys(incomingCore).length > 0) {\r\n mergedCore = incomingCore;\r\n } else if (Object.keys(incomingCore).length > 0) {\r\n const currentVersion = Number(currentCore.browser_major_version || 0);\r\n const incomingVersion = Number(incomingCore.browser_major_version || 0);\r\n if (currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {\r\n mergedCore = incomingCore;\r\n }\r\n }\r\n\r\n const mergedObserved = mergePlainObject(currentObserved, incomingObserved);\r\n\treturn buildBrowserProfilePayload(mergedCore, mergedObserved);\r\n};\r\n\r\n// mergeEnvPatchObjects \u662F visitor \u6210\u529F/\u5931\u8D25\u81EA\u52A8\u56DE\u5199 env_patch \u7684\u5408\u5E76\u5165\u53E3\u3002\r\nconst mergeEnvPatchObjects = (...patches) => {\r\n const merged = {};\r\n\r\n patches.forEach((patch) => {\r\n if (!isPlainObject(patch)) return;\r\n Object.entries(patch).forEach(([key, value]) => {\r\n if (!key) return;\r\n if (key === 'browser_profile') {\r\n const browserProfile = mergeBrowserProfilePayload(merged.browser_profile, value);\r\n if (Object.keys(browserProfile).length > 0) {\r\n merged.browser_profile = browserProfile;\r\n }\r\n return;\r\n }\r\n if (isPlainObject(value) && isPlainObject(merged[key])) {\r\n merged[key] = mergePlainObject(merged[key], value);\r\n return;\r\n }\r\n merged[key] = deepClone(value);\r\n });\r\n });\r\n\r\n return Object.keys(merged).length > 0 ? merged : null;\r\n};\r\n\r\nconst normalizeBrowserProfile = (value) => {\r\n const source = isPlainObject(value) ? value : {};\r\n const coreSource = isPlainObject(source.core) ? source.core : {};\r\n const observedSource = isPlainObject(source.observed) ? source.observed : {};\r\n const core = normalizeBrowserProfileCore(coreSource);\r\n const observed = normalizeObservedBrowserProfile(observedSource);\r\n return {\r\n core,\r\n observed,\r\n payload: buildBrowserProfilePayload(core, observed),\r\n };\r\n};\r\n\r\nconst rememberRuntimeState = (state) => {\r\n rememberedRuntimeState = deepClone(state);\r\n return rememberedRuntimeState;\r\n};\r\n\r\nconst normalizeRuntimeState = (source = {}, actor = '') => {\r\n if (\r\n source &&\r\n typeof source === 'object' &&\r\n source.runtime &&\r\n typeof source.runtime === 'object' &&\r\n !Array.isArray(source.runtime) &&\r\n Object.prototype.hasOwnProperty.call(source, 'browserProfileCore')\r\n ) {\r\n return source;\r\n }\r\n return RuntimeEnv.parseInput(source, actor);\r\n};\r\n\r\nexport const RuntimeEnv = {\r\n tryParseJSON,\r\n normalizeCookies,\r\n normalizeLocalStorage,\r\n normalizeSessionStorage,\r\n normalizeAuth,\r\n normalizeBrowserProfileCore,\r\n normalizeObservedBrowserProfile,\r\n normalizeSnapshot(snapshot = {}) {\r\n return normalizeRawSnapshot(snapshot);\r\n },\r\n collectCookieUrls(snapshot = {}) {\r\n return collectCookieUrlsFromSnapshot(snapshot);\r\n },\r\n buildRuntimeEnvFromSnapshot(snapshot = {}, options = {}) {\r\n return buildEnvPayloadFromSnapshot(snapshot, options);\r\n },\r\n buildEnvPatchFromSnapshot(snapshot = {}, options = {}) {\r\n return buildEnvPayloadFromSnapshot(snapshot, options);\r\n },\r\n mergeEnvPatches(...patches) {\r\n return mergeEnvPatchObjects(...patches);\r\n },\r\n\r\n // parseInput \u628A Actor \u8F93\u5165\u91CC\u7684 runtime \u5B57\u6BB5\u6807\u51C6\u5316\u6210 toolkit \u5185\u90E8\u7EDF\u4E00\u7ED3\u6784\u3002\r\n // \u540E\u7EED visitor \u53EA\u548C\u8FD9\u4E2A state \u4EA4\u4E92\uFF0C\u4E0D\u518D\u81EA\u5DF1\u62FC token/cookie \u903B\u8F91\u3002\r\n parseInput(input = {}, actor = '') {\r\n const runtime = tryParseJSON(input?.runtime) || {};\r\n const resolvedActor = String(actor || input?.actor || '').trim();\r\n const cookies = normalizeCookies(runtime?.cookies);\r\n const cookieMap = buildCookieMap(cookies);\r\n const localStorage = normalizeLocalStorage(runtime?.local_storage);\r\n const sessionStorage = normalizeSessionStorage(runtime?.session_storage);\r\n const auth = normalizeAuth(runtime?.auth);\r\n const browserProfile = normalizeBrowserProfile(runtime?.browser_profile);\r\n const envId = String(input?.env_id || '').trim();\r\n\r\n const normalizedRuntime = {\r\n ...runtime,\r\n ...(cookies.length > 0 ? { cookies } : {}),\r\n ...(Object.keys(localStorage).length > 0 ? { local_storage: localStorage } : {}),\r\n ...(Object.keys(sessionStorage).length > 0 ? { session_storage: sessionStorage } : {}),\r\n ...(Object.keys(auth).length > 0 ? { auth } : {}),\r\n };\r\n if (Object.keys(browserProfile.payload).length > 0) {\r\n normalizedRuntime.browser_profile = browserProfile.payload;\r\n } else {\r\n delete normalizedRuntime.browser_profile;\r\n }\r\n\r\n const state = {\r\n actor: resolvedActor,\r\n runtime: normalizedRuntime,\r\n envId,\r\n auth,\r\n cookies,\r\n cookieMap,\r\n localStorage,\r\n sessionStorage,\r\n browserProfile: browserProfile.payload,\r\n browserProfileCore: browserProfile.core,\r\n browserProfileObserved: browserProfile.observed,\r\n };\r\n rememberRuntimeState(state);\r\n return state;\r\n },\r\n\r\n // buildEnvPatch \u53EA\u6784\u9020\u5141\u8BB8\u56DE\u5199\u5230\u540E\u7AEF env \u7684\u5B57\u6BB5\u96C6\u5408\u3002\r\n buildEnvPatch(source = {}, actor = '') {\r\n const state = normalizeRuntimeState(source, actor);\r\n const browserProfile = buildBrowserProfilePayload(state.browserProfileCore, state.browserProfileObserved);\r\n const envPatch = {\r\n ...(Object.keys(state.auth || {}).length > 0 ? { auth: state.auth } : {}),\r\n ...(Array.isArray(state.cookies) && state.cookies.length > 0 ? { cookies: state.cookies } : {}),\r\n ...(Object.keys(state.localStorage || {}).length > 0 ? { local_storage: state.localStorage } : {}),\r\n ...(Object.keys(state.sessionStorage || {}).length > 0 ? { session_storage: state.sessionStorage } : {}),\r\n ...(Object.keys(browserProfile).length > 0 ? { browser_profile: browserProfile } : {}),\r\n };\r\n return Object.keys(envPatch).length > 0 ? envPatch : null;\r\n },\r\n\r\n // hasLoginState \u7528\u6765\u533A\u5206\u201C\u5FC5\u987B\u9274\u6743\u7684\u5E73\u53F0\u201D\u548C\u201C\u53EF\u533F\u540D\u8FD0\u884C\u7684\u5E73\u53F0\u201D\u3002\r\n hasLoginState(source = {}, actor = '') {\r\n const state = normalizeRuntimeState(source, actor);\r\n return (\r\n (Array.isArray(state.cookies) && state.cookies.length > 0) ||\r\n Object.keys(state.localStorage || {}).length > 0 ||\r\n Object.keys(state.sessionStorage || {}).length > 0 ||\r\n Object.keys(state.auth || {}).length > 0\r\n );\r\n },\r\n\r\n getAuthValue(source = {}, key = '', actor = '') {\r\n const state = normalizeRuntimeState(source, actor);\r\n const safeKey = String(key || '').trim();\r\n if (!safeKey) return '';\r\n return String(state.auth?.[safeKey] ?? '').trim();\r\n },\r\n\r\n rememberState(source = {}) {\r\n const state = normalizeRuntimeState(source);\r\n rememberRuntimeState(state);\r\n return RuntimeEnv.peekRememberedState();\r\n },\r\n\r\n peekRememberedState() {\r\n return rememberedRuntimeState ? deepClone(rememberedRuntimeState) : null;\r\n },\r\n\r\n getBrowserProfileCore(source = {}, actor = '') {\r\n const state = normalizeRuntimeState(source, actor);\r\n return deepClone(state.browserProfileCore || {});\r\n },\r\n\r\n setBrowserProfileCore(source = {}, core = {}, actor = '') {\r\n const state = normalizeRuntimeState(source, actor);\r\n const normalizedCore = normalizeBrowserProfileCore(core);\r\n state.browserProfileCore = normalizedCore;\r\n state.browserProfile = buildBrowserProfilePayload(normalizedCore, state.browserProfileObserved);\r\n if (Object.keys(state.browserProfile).length > 0) {\r\n state.runtime.browser_profile = state.browserProfile;\r\n } else {\r\n delete state.runtime.browser_profile;\r\n }\r\n rememberRuntimeState(state);\r\n return state;\r\n },\r\n\r\n // applyToPage \u53EA\u8D1F\u8D23\u628A\u767B\u5F55\u6001\u76F8\u5173\u5B57\u6BB5\u6CE8\u5165\u9875\u9762\uFF1A\r\n // cookies / localStorage / sessionStorage\u3002\r\n // \u6307\u7EB9\u3001\u65F6\u533A\u3001UA\u3001viewport \u7684\u56DE\u653E\u53D1\u751F\u5728 launch.js \u542F\u52A8\u9636\u6BB5\uFF0C\u4E0D\u5728\u8FD9\u91CC\u505A\u3002\r\n async applyToPage(page, source = {}, options = {}) {\r\n if (!page) return;\r\n const state = normalizeRuntimeState(source, options?.actor || '');\r\n const localStorage = state.localStorage || {};\r\n const sessionStorage = state.sessionStorage || {};\r\n const cookies = (state.cookies || [])\r\n .map((cookie) => {\r\n const normalized = { ...cookie };\r\n if (!normalized.path) {\r\n normalized.path = '/';\r\n }\r\n if (!normalized.domain && !normalized.url) {\r\n return null;\r\n }\r\n return normalized;\r\n })\r\n .filter(Boolean);\r\n\r\n if (cookies.length > 0) {\r\n await page.context().addCookies(cookies);\r\n }\r\n if (Object.keys(localStorage).length > 0) {\r\n await page.addInitScript((payload) => {\r\n try {\r\n Object.entries(payload || {}).forEach(([key, value]) => {\r\n if (!key) return;\r\n window.localStorage.setItem(key, String(value ?? ''));\r\n });\r\n } catch (error) {\r\n // no-op\r\n }\r\n }, localStorage);\r\n }\r\n if (Object.keys(sessionStorage).length > 0) {\r\n await page.addInitScript((payload) => {\r\n try {\r\n Object.entries(payload || {}).forEach(([key, value]) => {\r\n if (!key) return;\r\n window.sessionStorage.setItem(key, String(value ?? ''));\r\n });\r\n } catch (error) {\r\n // no-op\r\n }\r\n }, sessionStorage);\r\n }\r\n },\r\n\r\n // captureEnvPatch \u5728\u4EFB\u52A1\u7ED3\u675F\u65F6\u91C7\u96C6\u6700\u65B0\u73AF\u5883\u5FEB\u7167\uFF0C\u7528\u4E8E pushSuccess / pushFailed \u81EA\u52A8\u56DE\u5199\u3002\r\n async captureEnvPatch(page, source = {}, options = {}) {\r\n const state = normalizeRuntimeState(source, options?.actor || '');\r\n const baseline = RuntimeEnv.buildEnvPatch(state) || {};\r\n if (!page || typeof page.evaluate !== 'function' || typeof page.context !== 'function') {\r\n return Object.keys(baseline).length > 0 ? baseline : null;\r\n }\r\n\r\n try {\r\n const rawSnapshot = await captureRawSnapshotFromPage(page);\r\n const cookieUrls = collectCookieUrlsFromSnapshot(rawSnapshot);\r\n let cookies = [];\r\n try {\r\n cookies = cookieUrls.length > 0\r\n ? await page.context().cookies(cookieUrls)\r\n : await page.context().cookies();\r\n } catch {\r\n cookies = [];\r\n }\r\n const capturedPatch = RuntimeEnv.buildEnvPatchFromSnapshot(\r\n {\r\n ...rawSnapshot,\r\n cookies,\r\n },\r\n {\r\n auth: state.auth,\r\n browserProfileCore: state.browserProfileCore,\r\n },\r\n );\r\n return RuntimeEnv.mergeEnvPatches(baseline, capturedPatch);\r\n } catch {\r\n // ignore\r\n }\r\n return Object.keys(baseline).length > 0 ? baseline : null;\r\n },\r\n};\r\n", "import { createInternalLogger } from './logger.js';\r\n\r\nconst logger = createInternalLogger('InternalUtils');\r\n\r\n/**\r\n * \u89E3\u6790 Cookie \u5B57\u7B26\u4E32\u4E3A Playwright \u683C\u5F0F\u7684 Cookie \u6570\u7EC4\r\n * @param {string} cookieString - Cookie \u5B57\u7B26\u4E32\r\n * @param {string} [domain] - Cookie \u57DF\u540D (\u53EF\u9009)\r\n * @returns {Array} Cookie \u6570\u7EC4\r\n */\r\nexport const parseCookies = (cookieString, domain) => {\r\n const cookies = [];\r\n const pairs = cookieString.split(';').map(c => c.trim());\r\n\r\n for (const pair of pairs) {\r\n const [name, ...valueParts] = pair.split('=');\r\n if (name && valueParts.length > 0) {\r\n const cookie = {\r\n name: name.trim(),\r\n value: valueParts.join('=').trim(),\r\n path: '/',\r\n };\r\n if (domain) {\r\n cookie.domain = domain;\r\n }\r\n cookies.push(cookie);\r\n }\r\n }\r\n logger.success('parseCookies', `parsed ${cookies.length} cookies`);\r\n return cookies;\r\n};\r\n", "import { parseCookies as internalParseCookies } from './internals/utils.js';\r\n\r\nexport const Utils = {\r\n /**\r\n * \u89E3\u6790 Cookie \u5B57\u7B26\u4E32\u4E3A Playwright \u683C\u5F0F\u7684 Cookie \u6570\u7EC4\r\n * @param {string} cookieString - Cookie \u5B57\u7B26\u4E32\r\n * @param {string} [domain] - Cookie \u57DF\u540D (\u53EF\u9009)\r\n * @returns {Array} Cookie \u6570\u7EC4\r\n */\r\n parseCookies(cookieString, domain) {\r\n return internalParseCookies(cookieString, domain);\r\n },\r\n\r\n /**\r\n * \u4ECE\u5B57\u7B26\u4E32\u4E2D\u63D0\u53D6 URL \u94FE\u63A5\r\n * @param {string} text\r\n * @param {Object} [options]\r\n * @param {string} [options.prefix] - \u4EC5\u8FD4\u56DE\u6B64\u524D\u7F00\u5F00\u5934\uFF0C\u4E14\u524D\u7F00\u540E\u81F3\u5C11 1 \u4F4D\u5B57\u7B26\u7684\u94FE\u63A5\r\n * @returns {string[]}\r\n */\r\n parseLinks(text, options = {}) {\r\n const raw = String(text || '');\r\n if (!raw) return [];\r\n\r\n const opts = options && typeof options === 'object' ? options : {};\r\n const prefix = String(opts.prefix || '').trim();\r\n\r\n const matched = raw.match(/https?:\\/\\/[\\w\\-._~:/?#[\\]@!$&'()*+,;=%]+/g) || [];\r\n const unique = new Set();\r\n\r\n for (const item of matched) {\r\n const link = String(item || '').trim().replace(/[\"'\u201C\u201D\u2018\u2019>\\].,\uFF0C\u3002\uFF1B;!\uFF01?\uFF1F]+$/, '');\r\n if (!link || !/^https?:\\/\\//i.test(link)) continue;\r\n\r\n if (prefix) {\r\n if (!link.startsWith(prefix)) continue;\r\n if (link.length <= prefix.length) continue;\r\n }\r\n\r\n unique.add(link);\r\n }\r\n\r\n return Array.from(unique);\r\n },\r\n}\r\n", "import { createInternalLogger } from './internals/logger';\r\n\r\nconst logger = createInternalLogger('AntiCheat');\r\n\r\nconst BASE_CONFIG = Object.freeze({\r\n locale: 'zh-CN',\r\n acceptLanguage: 'zh-CN,zh;q=0.9',\r\n timezoneId: 'Asia/Shanghai',\r\n timezoneOffset: -480,\r\n geolocation: null,\r\n});\r\n\r\n// \u6700\u5C0F\u5316\u542F\u52A8\u53C2\u6570\uFF0C\u4F9D\u8D56 Crawlee/Playwright \u9ED8\u8BA4\u884C\u4E3A\r\nconst DEFAULT_LAUNCH_ARGS = [\r\n // '--disable-blink-features=AutomationControlled', // Crawlee \u53EF\u80FD\u4F1A\u81EA\u52A8\u5904\u7406\uFF0C\u8FC7\u591A\u5E72\u9884\u53CD\u800C\u4F1A\u88AB\u8BC6\u522B\r\n '--no-sandbox',\r\n '--disable-setuid-sandbox',\r\n '--window-position=0,0',\r\n];\r\n\r\nfunction buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0 } = {}) {\r\n const normalizedBrowserMajorVersion = Number(browserMajorVersion || 0);\r\n const browserDescriptor = normalizedBrowserMajorVersion > 0\r\n ? [{ name: 'chrome', minVersion: normalizedBrowserMajorVersion, maxVersion: normalizedBrowserMajorVersion }]\r\n : [{ name: 'chrome', minVersion: 110 }];\r\n\r\n return {\r\n browsers: browserDescriptor,\r\n devices: ['desktop'],\r\n operatingSystems: ['windows', 'macos', 'linux'],\r\n locales: [locale],\r\n };\r\n}\r\n\r\nexport const AntiCheat = {\r\n /**\r\n * \u83B7\u53D6\u7EDF\u4E00\u7684\u57FA\u7840\u914D\u7F6E\r\n */\r\n getBaseConfig() {\r\n return { ...BASE_CONFIG };\r\n },\r\n\r\n /**\r\n * \u7528\u4E8E Crawlee fingerprint generator \u7684\u7EDF\u4E00\u914D\u7F6E\uFF08\u684C\u9762\u7AEF\uFF09\u3002\r\n */\r\n getFingerprintGeneratorOptions(options = {}) {\r\n return buildFingerprintOptions(options);\r\n },\r\n\r\n /**\r\n * \u83B7\u53D6\u57FA\u7840\u542F\u52A8\u53C2\u6570\u3002\r\n */\r\n getLaunchArgs(options = {}) {\r\n const locale = String(options?.locale || BASE_CONFIG.locale).trim() || BASE_CONFIG.locale;\r\n return [...DEFAULT_LAUNCH_ARGS, `--lang=${locale}`];\r\n },\r\n\r\n /**\r\n * \u4E3A got-scraping \u751F\u6210\u4E0E\u6D4F\u89C8\u5668\u4E00\u81F4\u7684 TLS \u6307\u7EB9\u914D\u7F6E\uFF08\u684C\u9762\u7AEF\uFF09\u3002\r\n */\r\n getTlsFingerprintOptions(userAgent = '', acceptLanguage = '') {\r\n // \u7B80\u5316\u903B\u8F91\uFF0C\u4E0D\u518D\u89E3\u6790 acceptLanguage\uFF0C\u4EC5\u63D0\u4F9B\u57FA\u7840\u6307\u7EB9\u914D\u7F6E\r\n return buildFingerprintOptions();\r\n },\r\n\r\n /**\r\n * \u89C4\u8303\u5316\u8BF7\u6C42\u5934\r\n */\r\n applyLocaleHeaders(headers, acceptLanguage = '') {\r\n if (!headers['accept-language']) {\r\n headers['accept-language'] = acceptLanguage || BASE_CONFIG.acceptLanguage;\r\n }\r\n return headers;\r\n },\r\n};\r\n", "import delay from 'delay';\r\nimport { createCursor } from 'ghost-cursor-playwright';\r\nimport { createInternalLogger } from './internals/logger.js';\r\n\r\nconst logger = createInternalLogger('Humanize');\r\n\r\n// \u5185\u90E8 cursor \u5B9E\u4F8B\u7F13\u5B58 (\u6BCF\u4E2A page \u4E00\u4E2A) - \u4E0D\u5BF9\u5916\u66B4\u9732\r\nconst $CursorWeakMap = new WeakMap();\r\n\r\n/**\r\n * \u5185\u90E8\u65B9\u6CD5\uFF1A\u83B7\u53D6\u9875\u9762\u7684 cursor\uFF0C\u5982\u679C\u4E0D\u5B58\u5728\u5219\u629B\u51FA\u9519\u8BEF\r\n */\r\nfunction $GetCursor(page) {\r\n const cursor = $CursorWeakMap.get(page);\r\n if (!cursor) {\r\n throw new Error('Cursor \u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8C03\u7528 Humanize.initializeCursor(page)');\r\n }\r\n return cursor;\r\n}\r\n\r\nexport const Humanize = {\r\n /**\r\n * \u751F\u6210\u5E26\u6296\u52A8\u7684\u6BEB\u79D2\u6570 - \u57FA\u4E8E\u57FA\u7840\u503C\u6DFB\u52A0\u968F\u673A\u6D6E\u52A8 (\u00B130% \u9ED8\u8BA4)\r\n * @param {number} base - \u57FA\u7840\u5EF6\u8FDF (ms)\r\n * @param {number} [jitterPercent=0.3] - \u6296\u52A8\u767E\u5206\u6BD4 (0.3 = \u00B130%)\r\n * @returns {number} \u6296\u52A8\u540E\u7684\u6BEB\u79D2\u6570\r\n */\r\n jitterMs(base, jitterPercent = 0.3) {\r\n const jitter = base * jitterPercent * (Math.random() * 2 - 1);\r\n return Math.max(10, Math.round(base + jitter));\r\n },\r\n\r\n /**\r\n * \u521D\u59CB\u5316\u9875\u9762\u7684 Ghost Cursor\uFF08\u5FC5\u987B\u5728\u4F7F\u7528\u5176\u4ED6 cursor \u76F8\u5173\u65B9\u6CD5\u524D\u8C03\u7528\uFF09\r\n * \r\n * @param {import('playwright').Page} page\r\n * @returns {Promise<void>}\r\n */\r\n async initializeCursor(page) {\r\n if ($CursorWeakMap.has(page)) {\r\n logger.debug('initializeCursor: cursor already exists, skipping');\r\n return;\r\n }\r\n logger.start('initializeCursor', 'creating cursor');\r\n const cursor = await createCursor(page);\r\n $CursorWeakMap.set(page, cursor);\r\n logger.success('initializeCursor', 'cursor initialized');\r\n },\r\n\r\n /**\r\n * \u4EBA\u7C7B\u5316\u9F20\u6807\u79FB\u52A8 - \u4F7F\u7528 ghost-cursor \u79FB\u52A8\u5230\u6307\u5B9A\u4F4D\u7F6E\u6216\u5143\u7D20\r\n * \r\n * @param {import('playwright').Page} page\r\n * @param {string|{x: number, y: number}|import('playwright').ElementHandle} target - CSS\u9009\u62E9\u5668\u3001\u5750\u6807\u5BF9\u8C61\u6216\u5143\u7D20\u53E5\u67C4\r\n */\r\n async humanMove(page, target) {\r\n const cursor = $GetCursor(page);\r\n logger.start('humanMove', `target=${typeof target === 'string' ? target : 'element/coords'}`);\r\n try {\r\n if (typeof target === 'string') {\r\n // CSS \u9009\u62E9\u5668\r\n const element = await page.$(target);\r\n if (!element) {\r\n logger.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);\r\n return false;\r\n }\r\n const box = await element.boundingBox();\r\n if (!box) {\r\n logger.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);\r\n return false;\r\n }\r\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\r\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\r\n await cursor.actions.move({ x, y });\r\n } else if (target && typeof target.x === 'number' && typeof target.y === 'number') {\r\n // \u5750\u6807\u5BF9\u8C61\r\n await cursor.actions.move(target);\r\n } else if (target && typeof target.boundingBox === 'function') {\r\n // ElementHandle\r\n const box = await target.boundingBox();\r\n if (box) {\r\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\r\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\r\n await cursor.actions.move({ x, y });\r\n }\r\n }\r\n logger.success('humanMove');\r\n return true;\r\n } catch (error) {\r\n logger.fail('humanMove', error);\r\n throw error;\r\n }\r\n },\r\n\r\n /**\r\n * \u6E10\u8FDB\u5F0F\u6EDA\u52A8\u5230\u5143\u7D20\u53EF\u89C1\uFF08\u4EC5\u5904\u7406 Y \u8F74\u6EDA\u52A8\uFF09\r\n * \u8FD4\u56DE restore \u65B9\u6CD5\uFF0C\u7528\u4E8E\u5C06\u6EDA\u52A8\u5BB9\u5668\u6062\u590D\u5230\u539F\u4F4D\u7F6E\r\n * \r\n * @param {import('playwright').Page} page\r\n * @param {string|import('playwright').ElementHandle} target - CSS \u9009\u62E9\u5668\u6216\u5143\u7D20\u53E5\u67C4\r\n * @param {Object} [options]\r\n * @param {number} [options.maxSteps=14] - \u6700\u5927\u6EDA\u52A8\u6B65\u6570\r\n * @param {number} [options.minStep=260] - \u5355\u6B21\u6EDA\u52A8\u6700\u5C0F\u6B65\u957F\r\n * @param {number} [options.maxStep=800] - \u5355\u6B21\u6EDA\u52A8\u6700\u5927\u6B65\u957F\r\n * @param {number} [options.maxDurationMs] - \u6700\u957F\u8017\u65F6\u4E0A\u9650 (\u9ED8\u8BA4\u968F maxSteps \u4F30\u7B97)\r\n */\r\n async humanScroll(page, target, options = {}) {\r\n const {\r\n maxSteps = 14,\r\n minStep = 260,\r\n maxStep = 800,\r\n maxDurationMs = maxSteps * 220 + 800\r\n } = options;\r\n const targetDesc = typeof target === 'string' ? target : 'ElementHandle';\r\n\r\n logger.start('humanScroll', `target=${targetDesc}`);\r\n\r\n let element;\r\n if (typeof target === 'string') {\r\n element = await page.$(target);\r\n if (!element) {\r\n logger.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);\r\n return { element: null, didScroll: false };\r\n }\r\n } else {\r\n element = target;\r\n }\r\n\r\n const cursor = $GetCursor(page);\r\n let didScroll = false;\r\n\r\n // \u8F85\u52A9\u51FD\u6570\uFF1A\u68C0\u67E5\u53EF\u89C1\u6027\u548C\u906E\u6321\r\n const checkVisibility = async () => {\r\n return await element.evaluate((el) => {\r\n const rect = el.getBoundingClientRect();\r\n if (!rect || rect.width === 0 || rect.height === 0) {\r\n return { code: 'ZERO_DIMENSIONS', reason: '\u5C3A\u5BF8\u4E3A\u96F6' };\r\n }\r\n\r\n const cx = rect.left + rect.width / 2;\r\n const cy = rect.top + rect.height / 2;\r\n const viewH = window.innerHeight;\r\n const viewW = window.innerWidth;\r\n let isFixed = false;\r\n\r\n for (let node = el; node && node !== document.body; node = node.parentElement) {\r\n const style = window.getComputedStyle(node);\r\n if (style && style.position === 'fixed') {\r\n isFixed = true;\r\n break;\r\n }\r\n }\r\n\r\n // 1. \u68C0\u67E5\u662F\u5426\u5728\u51E0\u4F55\u89C6\u53E3\u5185\r\n if (cy < 0 || cy > viewH || cx < 0 || cx > viewW) {\r\n // \u8BA1\u7B97\u6240\u9700\u65B9\u5411\r\n const direction = cy < 0 ? 'up' : (cy > viewH ? 'down' : 'unknown');\r\n return { code: 'OUT_OF_VIEWPORT', reason: '\u4E0D\u5728\u89C6\u53E3\u5185', direction, cy, viewH, isFixed };\r\n }\r\n\r\n // 2. \u68C0\u67E5\u906E\u6321\r\n const pointElement = document.elementFromPoint(cx, cy);\r\n if (pointElement && !el.contains(pointElement) && !pointElement.contains(el)) {\r\n return {\r\n code: 'OBSTRUCTED',\r\n reason: '\u88AB\u906E\u6321',\r\n obstruction: {\r\n tag: pointElement.tagName,\r\n id: pointElement.id,\r\n className: pointElement.className\r\n },\r\n cy, // Return Center Y for smart direction calculation\r\n viewH,\r\n isFixed\r\n };\r\n }\r\n\r\n return { code: 'VISIBLE', isFixed };\r\n });\r\n };\r\n\r\n const getScrollableRect = async () => {\r\n return await element.evaluate((el) => {\r\n const isScrollable = (node) => {\r\n const style = window.getComputedStyle(node);\r\n if (!style) return false;\r\n const overflowY = style.overflowY;\r\n if (!['auto', 'scroll', 'overlay'].includes(overflowY)) return false;\r\n return node.scrollHeight > node.clientHeight + 1;\r\n };\r\n\r\n let current = el;\r\n while (current && current !== document.body) {\r\n if (isScrollable(current)) {\r\n const rect = current.getBoundingClientRect();\r\n if (rect && rect.width > 0 && rect.height > 0) {\r\n return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };\r\n }\r\n }\r\n current = current.parentElement;\r\n }\r\n\r\n return null;\r\n });\r\n };\r\n\r\n const startTime = Date.now();\r\n\r\n try {\r\n for (let i = 0; i < maxSteps; i++) {\r\n if (Date.now() - startTime > maxDurationMs) {\r\n logger.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);\r\n return { element, didScroll };\r\n }\r\n\r\n const status = await checkVisibility();\r\n\r\n if (status.code === 'VISIBLE') {\r\n if (status.isFixed) {\r\n logger.info('humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8');\r\n } else {\r\n logger.debug('humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321');\r\n }\r\n logger.success('humanScroll', didScroll ? '\u5DF2\u6EDA\u52A8' : '\u65E0\u9700\u6EDA\u52A8');\r\n return { element, didScroll };\r\n }\r\n\r\n logger.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ''}`);\r\n\r\n if (status.code === 'OBSTRUCTED' && status.obstruction) {\r\n logger.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id=\"${status.obstruction.id}\">`);\r\n }\r\n\r\n const scrollRect = await getScrollableRect();\r\n if (!scrollRect && status.isFixed) {\r\n logger.warn('humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8');\r\n return { element, didScroll };\r\n }\r\n\r\n const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;\r\n const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;\r\n\r\n // \u786E\u5B9A\u6EDA\u52A8\u65B9\u5411\u548C\u8DDD\u79BB\r\n let deltaY = 0;\r\n if (status.code === 'OUT_OF_VIEWPORT') {\r\n if (status.direction === 'down') {\r\n deltaY = stepMin + Math.random() * (stepMax - stepMin);\r\n } else if (status.direction === 'up') {\r\n deltaY = -(stepMin + Math.random() * (stepMax - stepMin));\r\n } else {\r\n // \u6C34\u5E73\u95EE\u9898\u6216\u5947\u602A\u72B6\u6001\uFF0C\u5C1D\u8BD5\u5411\u4E0B\u6EDA\u52A8\u4E00\u70B9\r\n deltaY = 100;\r\n }\r\n } else if (status.code === 'OBSTRUCTED') {\r\n // \u667A\u80FD\u907F\u8BA9\u906E\u6321\r\n // \u5982\u679C\u5143\u7D20\u5728\u89C6\u53E3\u4E0B\u534A\u90E8\u5206\u88AB\u906E\u6321\uFF0C\u901A\u5E38\u662F\u88AB\u5E95\u90E8\u56FA\u5B9A\u5143\u7D20\uFF08\u5982 Footer\uFF09\u906E\u6321 -> \u9700\u8981\u5411\u4E0B\u6EDA\u52A8\u66F4\u591A\uFF08\u5185\u5BB9\u4E0A\u79FB\uFF09\r\n // \u5982\u679C\u5143\u7D20\u5728\u89C6\u53E3\u4E0A\u534A\u90E8\u5206\u88AB\u906E\u6321\uFF0C\u901A\u5E38\u662F\u88AB\u9876\u90E8\u56FA\u5B9A\u5143\u7D20\uFF08\u5982 Header\uFF09\u906E\u6321 -> \u9700\u8981\u5411\u4E0A\u6EDA\u52A8\u66F4\u591A\uFF08\u5185\u5BB9\u4E0B\u79FB\uFF09\r\n const halfY = scrollRect ? (scrollRect.y + scrollRect.height / 2) : (status.viewH / 2);\r\n const isBottomHalf = status.cy > halfY;\r\n const direction = isBottomHalf ? 1 : -1;\r\n\r\n // \u57FA\u7840\u6EDA\u52A8\u91CF + \u968F\u673A\u6CE2\u52A8\r\n deltaY = direction * (stepMin + Math.random() * 50);\r\n }\r\n\r\n // \u5C06\u9F20\u6807\u79FB\u52A8\u5230\u53EF\u6EDA\u52A8\u5BB9\u5668\uFF08\u4F18\u5148\uFF09\uFF0C\u5426\u5219\u79FB\u52A8\u5230\u89C6\u53E3\u4E2D\u5FC3\r\n if (i === 0) {\r\n const viewSize = page.viewportSize();\r\n if (scrollRect) {\r\n const safeX = scrollRect.x + scrollRect.width * 0.5 + (Math.random() - 0.5) * Math.min(80, scrollRect.width * 0.4);\r\n const safeY = scrollRect.y + scrollRect.height * 0.5 + (Math.random() - 0.5) * Math.min(80, scrollRect.height * 0.4);\r\n await cursor.actions.move({ x: safeX, y: safeY });\r\n } else if (viewSize) {\r\n const safeX = viewSize.width * 0.5 + (Math.random() - 0.5) * 80;\r\n const safeY = viewSize.height * 0.5 + (Math.random() - 0.5) * 80;\r\n await cursor.actions.move({ x: safeX, y: safeY });\r\n }\r\n }\r\n\r\n // \u6267\u884C\u6EDA\u52A8\r\n await page.mouse.wheel(0, deltaY);\r\n didScroll = true;\r\n\r\n // \u7B49\u5F85\u6EDA\u52A8\u7A33\u5B9A - \u7D27\u51D1\u8282\u594F (20ms - 60ms)\r\n await delay(this.jitterMs(20 + Math.random() * 40, 0.2));\r\n }\r\n\r\n logger.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);\r\n return { element, didScroll };\r\n\r\n } catch (error) {\r\n logger.fail('humanScroll', error);\r\n throw error;\r\n }\r\n },\r\n\r\n /**\r\n * \u4EBA\u7C7B\u5316\u70B9\u51FB - \u4F7F\u7528 ghost-cursor \u6A21\u62DF\u4EBA\u7C7B\u9F20\u6807\u79FB\u52A8\u8F68\u8FF9\u5E76\u70B9\u51FB\r\n * \r\n * @param {import('playwright').Page} page\r\n * @param {string|import('playwright').ElementHandle} [target] - CSS \u9009\u62E9\u5668\u6216\u5143\u7D20\u53E5\u67C4\u3002\u5982\u679C\u4E3A\u7A7A\uFF0C\u5219\u70B9\u51FB\u5F53\u524D\u9F20\u6807\u4F4D\u7F6E\r\n * @param {Object} [options]\r\n * @param {number} [options.reactionDelay=250] - \u53CD\u5E94\u5EF6\u8FDF\u57FA\u7840\u503C (ms)\uFF0C\u5B9E\u9645 \u00B130% \u6296\u52A8\r\n * @param {boolean} [options.throwOnMissing=true] - \u5143\u7D20\u4E0D\u5B58\u5728\u65F6\u662F\u5426\u629B\u51FA\u9519\u8BEF\r\n * @param {boolean} [options.scrollIfNeeded=true] - \u5143\u7D20\u4E0D\u5728\u89C6\u53E3\u65F6\u662F\u5426\u81EA\u52A8\u6EDA\u52A8\r\n */\r\n async humanClick(page, target, options = {}) {\r\n const cursor = $GetCursor(page);\r\n\r\n // \u589E\u52A0 restore \u9009\u9879\uFF0C\u9ED8\u8BA4 false (\u4E0D\u8FD8\u539F\u6EDA\u52A8\u4F4D\u7F6E)\r\n const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;\r\n\r\n const targetDesc = target == null ? 'Current Position' : (typeof target === 'string' ? target : 'ElementHandle');\r\n logger.start('humanClick', `target=${targetDesc}`);\r\n\r\n\r\n const restoreOnce = async () => {\r\n if (restoreOnce.restored) return;\r\n restoreOnce.restored = true;\r\n\r\n if (typeof restoreOnce.do !== 'function') return;\r\n try {\r\n await delay(this.jitterMs(1000));\r\n await restoreOnce.do();\r\n } catch (restoreError) {\r\n logger.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);\r\n }\r\n };\r\n\r\n\r\n try {\r\n // Case 1: \u70B9\u51FB\u5F53\u524D\u4F4D\u7F6E (target \u4E3A null/undefined)\r\n if (target == null) {\r\n // \u4EC5\u6267\u884C\u53CD\u5E94\u5EF6\u8FDF + \u70B9\u51FB\r\n await delay(this.jitterMs(reactionDelay, 0.4));\r\n await cursor.actions.click();\r\n logger.success('humanClick', 'Clicked current position');\r\n return true;\r\n }\r\n\r\n // Case 2: \u70B9\u51FB\u6307\u5B9A\u76EE\u6807\r\n let element;\r\n if (typeof target === 'string') {\r\n element = await page.$(target);\r\n if (!element) {\r\n if (throwOnMissing) {\r\n throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);\r\n }\r\n logger.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);\r\n return false;\r\n }\r\n } else {\r\n element = target;\r\n }\r\n\r\n if (scrollIfNeeded) {\r\n const { restore: restoreFn, didScroll } = await this.humanScroll(page, element);\r\n // \u4EC5\u5728 didScroll \u4E3A true \u4E14 options.restore \u4E3A true \u65F6\u624D\u8FD8\u539F\r\n restoreOnce.do = (didScroll && restore) ? restoreFn : null;\r\n }\r\n\r\n const box = await element.boundingBox();\r\n if (!box) {\r\n await restoreOnce();\r\n if (throwOnMissing) {\r\n throw new Error('\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E');\r\n }\r\n logger.warn('humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB');\r\n return false;\r\n }\r\n\r\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;\r\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;\r\n\r\n await cursor.actions.move({ x, y });\r\n await delay(this.jitterMs(reactionDelay, 0.4));\r\n await cursor.actions.click();\r\n\r\n await restoreOnce();\r\n\r\n logger.success('humanClick');\r\n return true;\r\n } catch (error) {\r\n await restoreOnce();\r\n logger.fail('humanClick', error);\r\n throw error;\r\n }\r\n },\r\n\r\n /**\r\n * \u968F\u673A\u5EF6\u8FDF\u4E00\u6BB5\u6BEB\u79D2\u6570\uFF08\u5E26 \u00B130% \u6296\u52A8\uFF09\r\n * @param {number} baseMs - \u57FA\u7840\u5EF6\u8FDF\u6BEB\u79D2\u6570\r\n * @param {number} [jitterPercent=0.3] - \u6296\u52A8\u767E\u5206\u6BD4\r\n */\r\n async randomSleep(baseMs, jitterPercent = 0.3) {\r\n const ms = this.jitterMs(baseMs, jitterPercent);\r\n logger.start('randomSleep', `base=${baseMs}, actual=${ms}ms`);\r\n await delay(ms);\r\n logger.success('randomSleep');\r\n },\r\n\r\n /**\r\n * \u6A21\u62DF\u4EBA\u7C7B\"\u6CE8\u89C6\"\u6216\"\u9605\u8BFB\"\u884C\u4E3A\uFF1A\u9F20\u6807\u5728\u9875\u9762\u4E0A\u968F\u673A\u5FAE\u52A8\r\n * @param {import('playwright').Page} page\r\n * @param {number} [baseDurationMs=2500] - \u57FA\u7840\u6301\u7EED\u65F6\u95F4 (\u00B140% \u6296\u52A8)\r\n */\r\n async simulateGaze(page, baseDurationMs = 2500) {\r\n const cursor = $GetCursor(page);\r\n const durationMs = this.jitterMs(baseDurationMs, 0.4);\r\n logger.start('simulateGaze', `duration=${durationMs}ms`);\r\n const startTime = Date.now();\r\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\r\n\r\n while (Date.now() - startTime < durationMs) {\r\n // \u5728\u89C6\u53E3\u8303\u56F4\u5185\u968F\u673A\u79FB\u52A8\r\n const x = 100 + Math.random() * (viewportSize.width - 200);\r\n const y = 100 + Math.random() * (viewportSize.height - 200);\r\n await cursor.actions.move({ x, y });\r\n // \u6CE8\u89C6\u505C\u7559 300-1200ms\r\n await delay(this.jitterMs(600, 0.5));\r\n }\r\n logger.success('simulateGaze');\r\n },\r\n\r\n /**\r\n * \u4EBA\u7C7B\u5316\u8F93\u5165 - \u5E26\u8282\u594F\u53D8\u5316\uFF08\u5FEB-\u6162-\u505C\u987F-\u5076\u5C14\u52A0\u901F\uFF09\r\n * @param {import('playwright').Page} page\r\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\r\n * @param {string} text - \u8981\u8F93\u5165\u7684\u6587\u672C\r\n * @param {Object} [options] \r\n * @param {number} [options.baseDelay=180] - \u57FA\u7840\u6309\u952E\u5EF6\u8FDF (ms)\uFF0C\u5B9E\u9645 \u00B140% \u6296\u52A8\r\n * @param {number} [options.pauseProbability=0.08] - \u505C\u987F\u6982\u7387 (0-1)\r\n * @param {number} [options.pauseBase=800] - \u505C\u987F\u65F6\u957F\u57FA\u7840\u503C (ms)\uFF0C\u5B9E\u9645 \u00B150% \u6296\u52A8\r\n */\r\n async humanType(page, selector, text, options = {}) {\r\n logger.start('humanType', `selector=${selector}, textLen=${text.length}`);\r\n const {\r\n baseDelay = 180,\r\n pauseProbability = 0.08,\r\n pauseBase = 800\r\n } = options;\r\n\r\n try {\r\n const locator = page.locator(selector);\r\n await Humanize.humanClick(page, locator);\r\n\r\n // \u70B9\u51FB\u540E\u601D\u8003\u5EF6\u8FDF\r\n await delay(this.jitterMs(200, 0.4));\r\n\r\n for (let i = 0; i < text.length; i++) {\r\n const char = text[i];\r\n let charDelay;\r\n\r\n if (char === ' ') {\r\n // \u7A7A\u683C\u952E\u7A0D\u5FEB\r\n charDelay = this.jitterMs(baseDelay * 0.6, 0.3);\r\n } else if (/[,.!?;:\uFF0C\u3002\uFF01\uFF1F\uFF1B\uFF1A]/.test(char)) {\r\n // \u6807\u70B9\u7B26\u53F7\u540E\u7A0D\u6162\uFF08\u6A21\u62DF\u601D\u8003\uFF09\r\n charDelay = this.jitterMs(baseDelay * 1.5, 0.4);\r\n } else {\r\n // \u666E\u901A\u5B57\u7B26\r\n charDelay = this.jitterMs(baseDelay, 0.4);\r\n }\r\n\r\n await page.keyboard.type(char);\r\n await delay(charDelay);\r\n\r\n // \u968F\u673A\u505C\u987F\uFF08\u6A21\u62DF\u601D\u8003/\u56DE\u987E\uFF09\r\n if (Math.random() < pauseProbability && i < text.length - 1) {\r\n const pauseTime = this.jitterMs(pauseBase, 0.5);\r\n logger.debug(`\u505C\u987F ${pauseTime}ms...`);\r\n await delay(pauseTime);\r\n }\r\n }\r\n logger.success('humanType');\r\n } catch (error) {\r\n logger.fail('humanType', error);\r\n throw error;\r\n }\r\n },\r\n\r\n /**\r\n * \u4EBA\u7C7B\u5316\u6E05\u7A7A\u8F93\u5165\u6846 - \u6A21\u62DF\u4EBA\u7C7B\u5220\u9664\u6587\u672C\u7684\u884C\u4E3A\r\n * @param {import('playwright').Page} page\r\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\r\n */\r\n async humanClear(page, selector) {\r\n logger.start('humanClear', `selector=${selector}`);\r\n try {\r\n const locator = page.locator(selector);\r\n await locator.click();\r\n await delay(this.jitterMs(200, 0.4));\r\n\r\n const currentValue = await locator.inputValue();\r\n if (!currentValue || currentValue.length === 0) {\r\n logger.success('humanClear', 'already empty');\r\n return;\r\n }\r\n\r\n // \u5168\u9009 + \u5220\u9664\r\n await page.keyboard.press('Meta+A');\r\n await delay(this.jitterMs(100, 0.4));\r\n await page.keyboard.press('Backspace');\r\n\r\n logger.success('humanClear');\r\n } catch (error) {\r\n logger.fail('humanClear', error);\r\n throw error;\r\n }\r\n },\r\n\r\n /**\r\n * \u9875\u9762\u9884\u70ED\u6D4F\u89C8 - \u6A21\u62DF\u4EBA\u7C7B\u8FDB\u5165\u9875\u9762\u540E\u7684\u63A2\u7D22\u884C\u4E3A\r\n * @param {import('playwright').Page} page\r\n * @param {number} [baseDuration=3500] - \u9884\u70ED\u65F6\u957F\u57FA\u7840\u503C (\u00B140% \u6296\u52A8)\r\n */\r\n async warmUpBrowsing(page, baseDuration = 3500) {\r\n const cursor = $GetCursor(page);\r\n const durationMs = this.jitterMs(baseDuration, 0.4);\r\n\r\n logger.start('warmUpBrowsing', `duration=${durationMs}ms`);\r\n const startTime = Date.now();\r\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\r\n\r\n try {\r\n while (Date.now() - startTime < durationMs) {\r\n const action = Math.random();\r\n\r\n if (action < 0.4) {\r\n // \u9F20\u6807\u79FB\u52A8\r\n const x = 100 + Math.random() * (viewportSize.width - 200);\r\n const y = 100 + Math.random() * (viewportSize.height - 200);\r\n await cursor.actions.move({ x, y });\r\n await delay(this.jitterMs(350, 0.4));\r\n } else if (action < 0.7) {\r\n // \u6EDA\u52A8\r\n const scrollY = (Math.random() - 0.5) * 200;\r\n await page.mouse.wheel(0, scrollY);\r\n await delay(this.jitterMs(500, 0.4));\r\n } else {\r\n // \u505C\u987F/\u6CE8\u89C6\r\n await delay(this.jitterMs(800, 0.5));\r\n }\r\n }\r\n logger.success('warmUpBrowsing');\r\n } catch (error) {\r\n logger.fail('warmUpBrowsing', error);\r\n throw error;\r\n }\r\n },\r\n\r\n /**\r\n * \u81EA\u7136\u6EDA\u52A8 - \u5E26\u60EF\u6027\u3001\u51CF\u901F\u6548\u679C\u548C\u968F\u673A\u6296\u52A8\r\n * @param {import('playwright').Page} page\r\n * @param {'up' | 'down'} [direction='down'] - \u6EDA\u52A8\u65B9\u5411\r\n * @param {number} [distance=300] - \u603B\u6EDA\u52A8\u8DDD\u79BB\u57FA\u7840\u503C (px)\uFF0C\u00B115% \u6296\u52A8\r\n * @param {number} [baseSteps=5] - \u5206\u51E0\u6B65\u5B8C\u6210\u57FA\u7840\u503C\uFF0C\u00B11 \u968F\u673A\r\n */\r\n async naturalScroll(page, direction = 'down', distance = 300, baseSteps = 5) {\r\n // steps \u52A0\u968F\u673A\u6D6E\u52A8 \u00B11\r\n const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);\r\n // distance \u52A0\u6296\u52A8\r\n const actualDistance = this.jitterMs(distance, 0.15);\r\n\r\n logger.start('naturalScroll', `dir=${direction}, dist=${actualDistance}, steps=${steps}`);\r\n const sign = direction === 'down' ? 1 : -1;\r\n const stepDistance = actualDistance / steps;\r\n\r\n try {\r\n for (let i = 0; i < steps; i++) {\r\n // \u60EF\u6027\u51CF\u901F\u56E0\u5B50\r\n const factor = 1 - (i / steps) * 0.5;\r\n // \u6BCF\u6B65\u52A0 \u00B110% \u6296\u52A8\r\n const jitter = 0.9 + Math.random() * 0.2;\r\n const scrollAmount = stepDistance * factor * sign * jitter;\r\n\r\n await page.mouse.wheel(0, scrollAmount);\r\n\r\n // \u5EF6\u8FDF\u4E5F\u5E26\u6296\u52A8\r\n const baseDelay = 60 + i * 25;\r\n await delay(this.jitterMs(baseDelay, 0.3));\r\n }\r\n logger.success('naturalScroll');\r\n } catch (error) {\r\n logger.fail('naturalScroll', error);\r\n throw error;\r\n }\r\n }\r\n}\r\n", "// \u96C6\u4E2D\u7BA1\u7406\u542F\u52A8\u914D\u7F6E\uFF0C\u53CD\u722C\u53C2\u6570\u4E0E\u6307\u7EB9\u914D\u7F6E\u7EDF\u4E00\u7531 AntiCheat \u63D0\u4F9B\r\nimport { execFileSync } from 'node:child_process';\r\nimport { FingerprintGenerator } from 'fingerprint-generator';\r\nimport { FingerprintInjector } from 'fingerprint-injector';\r\nimport { AntiCheat } from './anti-cheat';\r\nimport { createInternalLogger } from './internals/logger';\r\nimport { ByPass } from './proxy-bypass';\r\nimport { ProxyMeterRuntime } from './internals/proxy-meter-runtime';\r\nimport { RuntimeEnv } from './runtime-env';\r\n\r\nconst logger = createInternalLogger('Launch');\r\nconst REQUEST_HOOK_FLAG = Symbol('playwright-toolkit-request-hook');\r\nconst injectedContexts = new WeakSet();\r\nconst browserMajorVersionCache = new Map();\r\n\r\nconst DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION = 1;\r\nconst DEFAULT_LOCALE = 'zh-CN';\r\n\r\nconst DEFAULT_CRAWLER_BASE_OPTIONS = Object.freeze({\r\n maxConcurrency: 1,\r\n maxRequestRetries: 0,\r\n requestHandlerTimeoutSecs: 240,\r\n navigationTimeoutSecs: 120,\r\n});\r\n\r\nconst fingerprintInjector = new FingerprintInjector();\r\n\r\nconst resolveProxyLaunchOptions = (proxyConfiguration = {}) => {\r\n const config = proxyConfiguration && typeof proxyConfiguration === 'object' && !Array.isArray(proxyConfiguration)\r\n ? proxyConfiguration\r\n : {};\r\n\r\n const proxyUrl = String(config.proxy_url || '').trim();\r\n const enableProxy = typeof config.enable_proxy === 'boolean' ? config.enable_proxy : proxyUrl !== '';\r\n\r\n if (!enableProxy || !proxyUrl) {\r\n return { byPassDomains: [], enableProxy, proxyUrl };\r\n }\r\n const byPassDomains = ByPass.normalizeByPassDomains(config.by_pass_domains);\r\n return { byPassDomains, enableProxy, proxyUrl };\r\n};\r\n\r\nconst parseChromeMajorVersion = (rawValue = '') => {\r\n const match = String(rawValue || '').match(/Chrome\\/(\\d+)/i);\r\n return match ? Number(match[1] || 0) : 0;\r\n};\r\n\r\nconst resolveLauncherExecutablePath = (launcher) => {\r\n if (!launcher || typeof launcher !== 'object') return '';\r\n if (typeof launcher.executablePath === 'function') {\r\n try {\r\n return String(launcher.executablePath() || '').trim();\r\n } catch {\r\n return '';\r\n }\r\n }\r\n return '';\r\n};\r\n\r\nconst detectBrowserMajorVersion = (launcher) => {\r\n\tconst executablePath = resolveLauncherExecutablePath(launcher);\r\n if (!executablePath) return 0;\r\n if (browserMajorVersionCache.has(executablePath)) {\r\n return browserMajorVersionCache.get(executablePath);\r\n }\r\n\r\n let detectedVersion = 0;\r\n try {\r\n const rawVersion = execFileSync(executablePath, ['--version'], {\r\n encoding: 'utf8',\r\n stdio: ['ignore', 'pipe', 'ignore'],\r\n });\r\n detectedVersion = parseChromeMajorVersion(rawVersion);\r\n } catch (error) {\r\n logger.warn(`\u8BFB\u53D6\u6D4F\u89C8\u5668\u7248\u672C\u5931\u8D25: ${error?.message || error}`);\r\n }\r\n\r\n\tbrowserMajorVersionCache.set(executablePath, detectedVersion);\r\n\treturn detectedVersion;\r\n};\r\n\r\n// buildFingerprintGenerator \u53EA\u5728\u201C\u6CA1\u6709\u53EF\u590D\u7528 core.fingerprint\u201D\u65F6\u515C\u5E95\u751F\u6210\u4E00\u6B21\u3002\r\nconst buildFingerprintGenerator = ({ locale, browserMajorVersion }) => {\r\n\treturn new FingerprintGenerator(\r\n AntiCheat.getFingerprintGeneratorOptions({\r\n locale,\r\n browserMajorVersion,\r\n }),\r\n\t);\r\n};\r\n\r\n// buildReplayableBrowserProfile \u8D1F\u8D23\u628A\u201C\u767B\u5F55\u6001 env\u201D\u63D0\u5347\u6210\u201C\u53EF\u8DE8\u673A\u5668\u590D\u7528\u7684\u6D4F\u89C8\u5668\u771F\u6E90\u201D\u3002\r\n// \u89C4\u5219\u662F\uFF1A\r\n// 1. \u6CA1\u6709\u767B\u5F55\u6001\u65F6\uFF0C\u4E0D\u5F3A\u6C42\u751F\u6210\u6301\u4E45\u5316\u6307\u7EB9\uFF1B\r\n// 2. \u6709\u767B\u5F55\u6001\u4F46\u6CA1\u6709 core.fingerprint \u65F6\uFF0C\u9996\u6B21\u751F\u6210\u5E76\u5199\u56DE runtimeState\uFF1B\r\n// 3. \u6D4F\u89C8\u5668\u5927\u7248\u672C\u53D8\u5316\u65F6\uFF0C\u5141\u8BB8\u91CD\u5EFA core\uFF0C\u907F\u514D\u65E7\u6307\u7EB9\u4E0E\u65B0\u5185\u6838\u4E0D\u517C\u5BB9\u3002\r\nconst buildReplayableBrowserProfile = (runtimeState, launcher) => {\r\n if (!runtimeState || !RuntimeEnv.hasLoginState(runtimeState)) {\r\n return { runtimeState, browserProfileCore: null };\r\n }\r\n\r\n let nextState = RuntimeEnv.rememberState(runtimeState);\r\n let browserProfileCore = RuntimeEnv.getBrowserProfileCore(nextState);\r\n const timezoneId = String(browserProfileCore?.timezone_id || '').trim() || AntiCheat.getBaseConfig().timezoneId;\r\n const locale = DEFAULT_LOCALE;\r\n const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);\r\n const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);\r\n const needsRebuild = !browserProfileCore?.fingerprint\r\n || Object.keys(browserProfileCore.fingerprint || {}).length === 0\r\n || (currentBrowserMajorVersion > 0 && storedBrowserMajorVersion > 0 && storedBrowserMajorVersion !== currentBrowserMajorVersion);\r\n\r\n if (needsRebuild) {\r\n const generator = buildFingerprintGenerator({\r\n locale,\r\n browserMajorVersion: currentBrowserMajorVersion,\r\n });\r\n const fingerprint = generator.getFingerprint();\r\n const fingerprintBrowserMajorVersion = parseChromeMajorVersion(fingerprint?.fingerprint?.navigator?.userAgent || '');\r\n browserProfileCore = {\r\n fingerprint,\r\n timezone_id: timezoneId,\r\n locale,\r\n browser_major_version: currentBrowserMajorVersion > 0 ? currentBrowserMajorVersion : fingerprintBrowserMajorVersion,\r\n schema_version: DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION,\r\n };\r\n nextState = RuntimeEnv.setBrowserProfileCore(nextState, browserProfileCore);\r\n logger.info(\r\n `\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || '-')} | version=${browserProfileCore.browser_major_version || '-'} | timezone=${timezoneId}`,\r\n );\r\n return { runtimeState: nextState, browserProfileCore };\r\n }\r\n\r\n const normalizedBrowserProfileCore = {\r\n ...browserProfileCore,\r\n timezone_id: timezoneId,\r\n locale,\r\n schema_version: Number(browserProfileCore.schema_version || 0) > 0\r\n ? Number(browserProfileCore.schema_version || 0)\r\n : DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION,\r\n browser_major_version: currentBrowserMajorVersion > 0\r\n ? currentBrowserMajorVersion\r\n : Number(browserProfileCore.browser_major_version || 0),\r\n };\r\n\r\n const currentCoreRaw = JSON.stringify(browserProfileCore || {});\r\n const nextCoreRaw = JSON.stringify(normalizedBrowserProfileCore);\r\n if (currentCoreRaw !== nextCoreRaw) {\r\n nextState = RuntimeEnv.setBrowserProfileCore(nextState, normalizedBrowserProfileCore);\r\n }\r\n\r\n return {\r\n runtimeState: nextState,\r\n browserProfileCore: normalizedBrowserProfileCore,\r\n\t};\r\n};\r\n\r\n// buildReplayBrowserPoolOptions \u8BA9 BrowserPool / Playwright / FingerprintInjector\r\n// \u90FD\u4ECE\u540C\u4E00\u4EFD core.fingerprint \u6D3E\u751F\u53C2\u6570\uFF0C\u907F\u514D UA / viewport / JS \u6307\u7EB9\u591A\u771F\u6E90\u51B2\u7A81\u3002\r\nconst buildReplayBrowserPoolOptions = (browserProfileCore) => {\r\n const fingerprintWithHeaders = browserProfileCore?.fingerprint;\r\n const fingerprint = fingerprintWithHeaders?.fingerprint;\r\n if (!fingerprintWithHeaders || !fingerprint) {\r\n return null;\r\n }\r\n\r\n return {\r\n useFingerprints: false,\r\n prePageCreateHooks: [\r\n (_pageId, _browserController, pageOptions = {}) => {\r\n if (!pageOptions || typeof pageOptions !== 'object') return;\r\n\r\n const screen = fingerprint.screen || {};\r\n const userAgent = String(fingerprint.navigator?.userAgent || '').trim();\r\n if (userAgent) {\r\n pageOptions.userAgent = userAgent;\r\n }\r\n if (Number(screen.width || 0) > 0 && Number(screen.height || 0) > 0) {\r\n pageOptions.viewport = {\r\n width: Number(screen.width),\r\n height: Number(screen.height),\r\n };\r\n pageOptions.screen = {\r\n width: Number(screen.width),\r\n height: Number(screen.height),\r\n };\r\n }\r\n if (browserProfileCore.locale) {\r\n pageOptions.locale = browserProfileCore.locale;\r\n }\r\n if (browserProfileCore.timezone_id) {\r\n pageOptions.timezoneId = browserProfileCore.timezone_id;\r\n }\r\n },\r\n ],\r\n postPageCreateHooks: [\r\n async (page) => {\r\n const context = page?.context?.();\r\n if (!context) return;\r\n if (!injectedContexts.has(context)) {\r\n await fingerprintInjector.attachFingerprintToPlaywright(context, fingerprintWithHeaders);\r\n injectedContexts.add(context);\r\n }\r\n },\r\n ],\r\n };\r\n};\r\n\r\nexport const Launch = {\r\n getPlaywrightCrawlerOptions(options = {}) {\r\n const normalizedOptions = Array.isArray(options) ? { customArgs: options } : (options || {});\r\n const {\r\n customArgs = [],\r\n proxyConfiguration = {},\r\n log: logOptions = null,\r\n runInHeadfulMode = false,\r\n debugMode = false,\r\n isRunningOnApify = false,\r\n launcher = null,\r\n preNavigationHooks = [],\r\n postNavigationHooks = [],\r\n runtimeState = null,\r\n } = normalizedOptions;\r\n\r\n const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);\r\n const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);\r\n const proxyMeter = enableProxy && proxyUrl\r\n ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode })\r\n : null;\r\n const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;\r\n if (launchProxy && byPassDomains.length > 0) {\r\n launchProxy.bypass = byPassDomains.join(',');\r\n }\r\n\r\n\t\t// \u542F\u52A8\u524D\u5148\u786E\u5B9A\u662F\u5426\u8D70\u201C\u7A33\u5B9A\u56DE\u653E\u6A21\u5F0F\u201D\u3002\r\n\t\tconst replayContext = buildReplayableBrowserProfile(runtimeState, launcher);\r\n\t\tconst replayBrowserPoolOptions = buildReplayBrowserPoolOptions(replayContext.browserProfileCore);\r\n\t\tconst launchLocale = String(replayContext.browserProfileCore?.locale || DEFAULT_LOCALE).trim() || DEFAULT_LOCALE;\r\n\r\n const launchOptions = {\r\n args: [\r\n ...AntiCheat.getLaunchArgs({ locale: launchLocale }),\r\n ...customArgs,\r\n ],\r\n ignoreDefaultArgs: ['--enable-automation'],\r\n };\r\n\r\n if (launchProxy) {\r\n launchOptions.proxy = launchProxy;\r\n }\r\n\r\n const enableByPassLogger = Boolean(logOptions && logOptions.enable);\r\n if (enableByPassLogger && launchProxy) {\r\n let upstreamLabel = '';\r\n try {\r\n const parsedProxyUrl = new URL(proxyUrl.includes('://') ? proxyUrl : `http://${proxyUrl}`);\r\n upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;\r\n } catch {}\r\n logger.info(\r\n `[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || '-'} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(',')}`,\r\n );\r\n logger.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? '\u5F00\u542F' : '\u5173\u95ED'}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);\r\n } else if (enableByPassLogger && enableProxy && !launchProxy) {\r\n logger.info('[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A');\r\n logger.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? '\u5F00\u542F' : '\u5173\u95ED'}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);\r\n } else if (enableByPassLogger && !enableProxy && proxyUrl) {\r\n logger.info('[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E');\r\n logger.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? '\u5F00\u542F' : '\u5173\u95ED'}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);\r\n } else if (enableByPassLogger) {\r\n logger.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? '\u5F00\u542F' : '\u5173\u95ED'}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);\r\n }\r\n\r\n const onPageCreated = (page) => {\r\n const recommendedGotoOptions = {\r\n waitUntil: 'commit',\r\n };\r\n\r\n if (!page || typeof page.on !== 'function') {\r\n return recommendedGotoOptions;\r\n }\r\n if (page[REQUEST_HOOK_FLAG]) {\r\n return recommendedGotoOptions;\r\n }\r\n page[REQUEST_HOOK_FLAG] = true;\r\n\r\n const requestHandler = (req) => {\r\n const requestUrl = req.url();\r\n const resourceType = req.resourceType();\r\n const matched = byPassDomains.length > 0\r\n ? ByPass.findMatchedByPassRule(byPassRules, requestUrl)\r\n : null;\r\n if (launchProxy) {\r\n ProxyMeterRuntime.recordProxyMeterResourceType(requestUrl, resourceType);\r\n }\r\n if (!enableByPassLogger || byPassDomains.length === 0) return;\r\n if (!matched || !matched.rule) return;\r\n logger.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}`);\r\n };\r\n page.on('request', requestHandler);\r\n return recommendedGotoOptions;\r\n };\r\n\r\n const launchContext = {\r\n useIncognitoPages: true,\r\n launchOptions,\r\n };\r\n if (launcher) {\r\n launchContext.launcher = launcher;\r\n }\r\n\r\n const crawlerBaseOptions = {\r\n ...DEFAULT_CRAWLER_BASE_OPTIONS,\r\n headless: !runInHeadfulMode || isRunningOnApify,\r\n\t\t\t// \u6709 core.fingerprint \u65F6\u8D70\u56FA\u5B9A\u56DE\u653E\uFF1B\u5426\u5219\u9000\u56DE Crawlee \u9ED8\u8BA4\u6307\u7EB9\u6A21\u5F0F\u3002\r\n\t\t\tbrowserPoolOptions: replayBrowserPoolOptions || {\r\n\t\t\t\tuseFingerprints: true,\r\n\t\t\t\tfingerprintOptions: {\r\n fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions(),\r\n },\r\n },\r\n launchContext,\r\n };\r\n\r\n const normalizedPreNavigationHooks = Array.isArray(preNavigationHooks) ? preNavigationHooks : [];\r\n const normalizedPostNavigationHooks = Array.isArray(postNavigationHooks) ? postNavigationHooks : [];\r\n\r\n const internalPreNavigationHook = async ({ page }, gotoOptions = {}) => {\r\n const recommendedGotoOptions = onPageCreated(page);\r\n if (recommendedGotoOptions && typeof recommendedGotoOptions === 'object') {\r\n Object.assign(gotoOptions, recommendedGotoOptions);\r\n }\r\n };\r\n\r\n return {\r\n ...crawlerBaseOptions,\r\n preNavigationHooks: [internalPreNavigationHook, ...normalizedPreNavigationHooks],\r\n ...(normalizedPostNavigationHooks.length > 0\r\n ? { postNavigationHooks: normalizedPostNavigationHooks }\r\n : {}),\r\n };\r\n },\r\n};\r\n", "import picomatch from 'picomatch';\r\n\r\nconst normalizeByPassDomains = (domains) => {\r\n if (!Array.isArray(domains)) return [];\r\n return domains\r\n .map((item) => String(item || '').trim())\r\n .filter(Boolean);\r\n};\r\n\r\nconst normalizeHostname = (value = '') => String(value || '').trim().toLowerCase();\r\n\r\nconst buildByPassDomainRule = (rawPattern) => {\r\n const pattern = String(rawPattern || '').trim().toLowerCase();\r\n if (!pattern) return null;\r\n\r\n let matcher;\r\n try {\r\n matcher = picomatch(pattern, { nocase: true });\r\n } catch {\r\n return null;\r\n }\r\n\r\n return {\r\n pattern,\r\n test: (hostname) => matcher(String(hostname || '').toLowerCase()),\r\n };\r\n};\r\n\r\nconst buildByPassDomainRules = (domains = []) => {\r\n return normalizeByPassDomains(domains)\r\n .map((domain) => buildByPassDomainRule(domain))\r\n .filter(Boolean);\r\n};\r\n\r\nconst findMatchedByPassRule = (rules = [], requestUrl = '') => {\r\n let hostname = '';\r\n try {\r\n hostname = normalizeHostname(new URL(String(requestUrl || '')).hostname);\r\n } catch {\r\n return null;\r\n }\r\n\r\n for (const rule of rules) {\r\n if (rule && typeof rule.test === 'function' && rule.test(hostname)) {\r\n return {\r\n rule,\r\n hostname,\r\n };\r\n }\r\n }\r\n\r\n return {\r\n rule: null,\r\n hostname,\r\n };\r\n};\r\n\r\nconst isDomainCoveredByByPass = (domain = '', rules = []) => {\r\n const hostname = normalizeHostname(domain);\r\n if (!hostname) return false;\r\n\r\n for (const rule of rules || []) {\r\n if (!rule || typeof rule.test !== 'function') continue;\r\n if (rule.test(hostname)) return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nconst resolveRouteByProxy = ({\r\n requestUrl = '',\r\n enableProxy = false,\r\n byPassRules = [],\r\n}) => {\r\n if (!enableProxy) {\r\n return { route: 'direct', matchedRule: null, hostname: '' };\r\n }\r\n\r\n const matched = findMatchedByPassRule(byPassRules, requestUrl);\r\n if (!matched) {\r\n return { route: 'proxy', matchedRule: null, hostname: '' };\r\n }\r\n\r\n if (matched.rule) {\r\n return { route: 'direct', matchedRule: matched.rule, hostname: matched.hostname };\r\n }\r\n\r\n return { route: 'proxy', matchedRule: null, hostname: matched.hostname };\r\n};\r\n\r\nexport const ByPass = {\r\n normalizeByPassDomains,\r\n normalizeHostname,\r\n buildByPassDomainRule,\r\n buildByPassDomainRules,\r\n findMatchedByPassRule,\r\n isDomainCoveredByByPass,\r\n resolveRouteByProxy,\r\n};\r\n", "import express from 'express';\r\nimport { Actor } from 'apify';\r\nimport { PresetOfLiveViewKey } from './constants';\r\nimport { createInternalLogger } from './internals/logger';\r\nimport { capturePageScreenshot } from './internals/screenshot';\r\n\r\nconst logger = createInternalLogger('LiveView');\r\n\r\n/**\r\n * \u542F\u52A8\u4E00\u4E2A Web \u670D\u52A1\u5668\u4EE5\u5728 Live View \u9009\u9879\u5361\u4E2D\u663E\u793A\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\u3002\r\n */\r\nasync function startLiveViewServer(liveViewKey) {\r\n const app = express();\r\n\r\n app.get('/', async (req, res) => {\r\n try {\r\n // \u4ECE\u9ED8\u8BA4\u7684 Key-Value Store \u4E2D\u8BFB\u53D6\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\r\n const screenshotBuffer = await Actor.getValue(liveViewKey);\r\n\r\n if (!screenshotBuffer) {\r\n // \u5982\u679C\u8FD8\u6CA1\u6709\u622A\u56FE\uFF0C\u53D1\u9001\u4E00\u4E2A\u81EA\u52A8\u5237\u65B0\u7684\u5360\u4F4D\u9875\u9762\r\n res.send('<html><head><meta http-equiv=\"refresh\" content=\"2\"></head><body>\u7B49\u5F85\u7B2C\u4E00\u4E2A\u5C4F\u5E55\u622A\u56FE...</body></html>');\r\n return;\r\n }\r\n\r\n // \u5C06 Buffer \u8F6C\u6362\u4E3A Base64 \u5B57\u7B26\u4E32\r\n const screenshotBase64 = screenshotBuffer.toString('base64');\r\n\r\n // \u53D1\u9001\u4E00\u4E2A HTML \u9875\u9762\uFF0C\u8BE5\u9875\u9762\u6BCF 1 \u79D2\u81EA\u52A8\u5237\u65B0\u4E00\u6B21\uFF0C\u5E76\u663E\u793A\u622A\u56FE\r\n res.send(`\r\n <html>\r\n <head>\r\n <title>Live View (\u622A\u56FE)</title>\r\n <meta http-equiv=\"refresh\" content=\"1\">\r\n </head>\r\n <body style=\"margin:0; padding:0;\">\r\n <img src=\"data:image/png;base64,${screenshotBase64}\" \r\n alt=\"Live View Screenshot\" \r\n style=\"width: 100%; height: auto;\" />\r\n </body>\r\n </html>\r\n `);\r\n } catch (error) {\r\n logger.fail('Live View Server', error);\r\n res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);\r\n }\r\n });\r\n\r\n // \u76D1\u542C Apify \u5BB9\u5668\u7AEF\u53E3 \r\n const port = process.env.APIFY_CONTAINER_PORT || 4321;\r\n app.listen(port, () => { logger.success('startLiveViewServer', `\u76D1\u542C\u7AEF\u53E3 ${port}`); });\r\n}\r\n\r\n/**\r\n * \u62CD\u6444\u5F53\u524D\u9875\u9762\u7684\u5C4F\u5E55\u622A\u56FE\u5E76\u5C06\u5176\u4FDD\u5B58\u5230 Key-Value Store\u3002\r\n * @param {import('playwright').Page} page\r\n * @param {string} [logMessage] - \u53EF\u9009\u7684\u65E5\u5FD7\u6D88\u606F\u3002\r\n */\r\nasync function takeLiveScreenshot(liveViewKey, page, logMessage) {\r\n try {\r\n const buffer = await capturePageScreenshot(page, { type: 'png' });\r\n await Actor.setValue(liveViewKey, buffer, { contentType: 'image/png' });\r\n if (logMessage) {\r\n logger.info(`(\u622A\u56FE): ${logMessage}`);\r\n }\r\n } catch (e) {\r\n logger.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);\r\n }\r\n}\r\n\r\nconst useLiveView = (liveViewKey = PresetOfLiveViewKey) => {\r\n return {\r\n takeLiveScreenshot: async (page, logMessage) => {\r\n return await takeLiveScreenshot(liveViewKey, page, logMessage)\r\n },\r\n startLiveViewServer: async () => {\r\n return await startLiveViewServer(liveViewKey);\r\n }\r\n }\r\n}\r\n\r\nexport const LiveView = {\r\n useLiveView,\r\n};\r\n", "import { v4 as uuidv4 } from 'uuid';\r\nimport { createInternalLogger } from './internals/logger';\r\n\r\nconst logger = createInternalLogger('Captcha');\r\n\r\n/**\r\n * \u521B\u5EFA\u9A8C\u8BC1\u7801\u76D1\u63A7\u5668 - \u652F\u6301 DOM \u9009\u62E9\u5668 \u548C URL \u6A21\u5F0F \u4E24\u79CD\u68C0\u6D4B\u65B9\u5F0F\r\n * \r\n * \u6CE8\u610F\uFF1A\u76D1\u63A7\u5668\u968F\u9875\u9762\u751F\u547D\u5468\u671F\u81EA\u52A8\u6E05\u7406\uFF0C\u65E0\u9700\u624B\u52A8 cleanup\r\n * \r\n * @param {import('playwright').Page} page\r\n * @param {Object} options\r\n * @param {string} [options.domSelector] - DOM \u5143\u7D20\u9009\u62E9\u5668 (\u5982 '#captcha_container')\r\n * @param {string} [options.urlPattern] - URL \u5339\u914D\u6A21\u5F0F (\u5982 '/captcha')\r\n * @param {Function} options.onDetected - \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u65F6\u7684\u56DE\u8C03 (async function)\r\n */\r\nexport function useCaptchaMonitor(page, options) {\r\n const { domSelector, urlPattern, onDetected } = options;\r\n\r\n if (!domSelector && !urlPattern) {\r\n throw new Error('[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern \u81F3\u5C11\u4E00\u4E2A');\r\n }\r\n\r\n if (!onDetected || typeof onDetected !== 'function') {\r\n throw new Error('[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u4E00\u4E2A\u51FD\u6570');\r\n }\r\n\r\n let isStopped = false;\r\n let isHandling = false;\r\n let frameHandler = null;\r\n let exposedFunctionName = null;\r\n\r\n const triggerDetected = async () => {\r\n if (isStopped || isHandling) return;\r\n isHandling = true;\r\n try {\r\n await onDetected();\r\n } finally {\r\n isHandling = false;\r\n }\r\n };\r\n\r\n const cleanupFns = [];\r\n\r\n // ============================================================\r\n // \u6A21\u5F0F1: DOM \u76D1\u63A7 (\u4F7F\u7528 MutationObserver)\r\n // ============================================================\r\n if (domSelector) {\r\n // \u751F\u6210\u552F\u4E00\u7684\u51FD\u6570\u540D\u907F\u514D\u51B2\u7A81\r\n exposedFunctionName = `__c_d_${uuidv4().replace(/-/g, '_')}`;\r\n // \u751F\u6210\u552F\u4E00\u7684\u6E05\u7406\u51FD\u6570\u540D (\u6302\u8F7D\u5728 window \u4E0A)\r\n const cleanerName = `__c_cleaner_${uuidv4().replace(/-/g, '_')}`;\r\n\r\n // \u66B4\u9732\u56DE\u8C03\u51FD\u6570\u7ED9\u9875\u9762\r\n page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {\r\n // \u5FFD\u7565\u91CD\u590D\u66B4\u9732\u9519\u8BEF\r\n });\r\n\r\n // \u6CE8\u5165 MutationObserver \u76D1\u542C\u811A\u672C\r\n page.addInitScript(({ selector, callbackName, cleanerName }) => {\r\n (() => {\r\n let observer = null;\r\n\r\n const checkAndReport = () => {\r\n const element = document.querySelector(selector);\r\n if (element) {\r\n if (window[callbackName]) {\r\n window[callbackName]();\r\n }\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n // 1. \u7ACB\u5373\u68C0\u67E5\u4E00\u6B21\uFF08\u4E0D\u9000\u51FA\uFF0C\u4FDD\u6301\u6301\u7EED\u76D1\u542C\uFF09\r\n checkAndReport();\r\n\r\n // 2. \u542F\u52A8 MutationObserver\r\n observer = new MutationObserver((mutations) => {\r\n let shouldCheck = false;\r\n for (const mutation of mutations) {\r\n if (mutation.addedNodes.length > 0) {\r\n shouldCheck = true;\r\n break;\r\n }\r\n }\r\n if (shouldCheck && observer) {\r\n checkAndReport();\r\n }\r\n });\r\n\r\n // 3. \u6302\u8F7D\u76D1\u542C\uFF08\u786E\u4FDD DOM \u51C6\u5907\u5C31\u7EEA\uFF09\r\n const mountObserver = () => {\r\n const target = document.documentElement;\r\n if (target && observer) {\r\n observer.observe(target, { childList: true, subtree: true });\r\n }\r\n };\r\n\r\n if (document.readyState === 'loading') {\r\n window.addEventListener('DOMContentLoaded', mountObserver);\r\n } else {\r\n mountObserver();\r\n }\r\n\r\n // 4. \u6CE8\u518C\u6E05\u7406\u51FD\u6570\r\n window[cleanerName] = () => {\r\n if (observer) {\r\n observer.disconnect();\r\n observer = null;\r\n }\r\n };\r\n })();\r\n }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });\r\n\r\n logger.success('useCaptchaMonitor', `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);\r\n\r\n // \u6DFB\u52A0\u6E05\u7406\u903B\u8F91\r\n cleanupFns.push(async () => {\r\n try {\r\n // \u8C03\u7528\u9875\u9762\u5185\u7684\u6E05\u7406\u51FD\u6570\r\n await page.evaluate((name) => {\r\n if (window[name]) {\r\n window[name]();\r\n delete window[name];\r\n }\r\n }, cleanerName);\r\n } catch (e) {\r\n // \u9875\u9762\u53EF\u80FD\u5DF2\u5173\u95ED\u6216\u8DF3\u8F6C\uFF0C\u5FFD\u7565\u9519\u8BEF\r\n }\r\n });\r\n }\r\n\r\n // ============================================================\r\n // \u6A21\u5F0F2: URL \u76D1\u63A7 (\u76D1\u542C framenavigated)\r\n // ============================================================\r\n if (urlPattern) {\r\n frameHandler = async (frame) => {\r\n if (frame === page.mainFrame()) {\r\n const currentUrl = page.url();\r\n if (currentUrl.includes(urlPattern)) {\r\n await triggerDetected();\r\n }\r\n }\r\n };\r\n\r\n page.on('framenavigated', frameHandler);\r\n logger.success('useCaptchaMonitor', `URL \u76D1\u63A7\u5DF2\u542F\u7528: ${urlPattern}`);\r\n\r\n // \u6DFB\u52A0\u6E05\u7406\u903B\u8F91\r\n cleanupFns.push(async () => {\r\n page.off('framenavigated', frameHandler);\r\n });\r\n }\r\n\r\n // \u8FD4\u56DE\u63A7\u5236\u53E5\u67C4\r\n return {\r\n stop: async () => {\r\n logger.info('useCaptchaMonitor', '\u6B63\u5728\u505C\u6B62\u76D1\u63A7...');\r\n for (const fn of cleanupFns) {\r\n await fn();\r\n }\r\n isStopped = true; // \u9632\u6B62\u540E\u7EED\u89E6\u53D1\r\n }\r\n };\r\n}\r\n\r\n// \u6309\u7167 toolkit \u7EDF\u4E00\u7684\u5BFC\u51FA\u6A21\u5F0F\r\nexport const Captcha = {\r\n useCaptchaMonitor\r\n};\r\n", "import { v4 as uuidv4 } from 'uuid';\r\nimport { createInternalLogger } from './internals/logger.js';\r\n\r\nconst logger = createInternalLogger('Mutation');\r\n\r\nconst MUTATION_MONITOR_MODE = Object.freeze({\r\n Added: 'added',\r\n Changed: 'changed',\r\n All: 'all',\r\n});\r\n\r\n/**\r\n * \u751F\u6210\u552F\u4E00\u7684 key \u540D\u79F0\uFF0C\u907F\u514D\u51B2\u7A81\r\n * @returns {string}\r\n */\r\nfunction generateKey(prefix) {\r\n return `__${prefix}_${uuidv4().replace(/-/g, '_')}`;\r\n}\r\n\r\nexport const Mutation = {\r\n Mode: MUTATION_MONITOR_MODE,\r\n /**\r\n * \u7B49\u5F85 DOM \u5143\u7D20\u7A33\u5B9A\uFF08\u65E0\u53D8\u5316\uFF09\r\n * \u4F7F\u7528 MutationObserver \u76D1\u63A7\u6307\u5B9A\u5143\u7D20\uFF0C\u5F53\u5143\u7D20\u6301\u7EED\u4E00\u6BB5\u65F6\u95F4\u65E0\u53D8\u5316\u65F6 resolve\r\n * \r\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\r\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u5355\u4E2A\u6216\u591A\u4E2A\r\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\r\n * @param {number} [options.initialTimeout] - \u7B49\u5F85\u5143\u7D20\u51FA\u73B0\u7684\u8D85\u65F6 (\u6BEB\u79D2, \u9ED8\u8BA4: 30000)\r\n * @param {number} [options.stableTime] - \u65E0\u53D8\u5316\u6301\u7EED\u65F6\u95F4\u540E resolve (\u6BEB\u79D2, \u9ED8\u8BA4: 5000)\r\n * @param {number} [options.timeout] - \u6574\u4F53\u8D85\u65F6\u65F6\u95F4 (\u6BEB\u79D2, \u9ED8\u8BA4: 120000)\r\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\u94A9\u5B50\r\n * \u7B7E\u540D: ({ mutationCount, html, text, mutationNodes }) => any\r\n * \u8FD4\u56DE null/undefined: \u6B63\u5E38\u91CD\u7F6E\u7A33\u5B9A\u8BA1\u65F6\r\n * \u8FD4\u56DE\u5176\u4ED6\u503C: \u6682\u505C\u7A33\u5B9A\u8BA1\u65F6\uFF08timeout \u4ECD\u7136\u751F\u6548\uFF09\r\n * @returns {Promise<{ mutationCount: number, stableTime: number, wasPaused: boolean }>}\r\n */\r\n async waitForStable(page, selectors, options = {}) {\r\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\r\n const initialTimeout = options.initialTimeout ?? 30 * 1000;\r\n const stableTime = options.stableTime ?? 5 * 1000;\r\n const timeout = options.timeout ?? 120 * 1000;\r\n const onMutation = options.onMutation;\r\n\r\n logger.start('waitForStable', `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);\r\n\r\n if (initialTimeout > 0) {\r\n const selectorQuery = selectorList.join(',');\r\n try {\r\n await page.waitForSelector(selectorQuery, { timeout: initialTimeout });\r\n logger.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);\r\n } catch (e) {\r\n logger.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);\r\n throw e;\r\n }\r\n }\r\n\r\n // \u751F\u6210\u552F\u4E00\u7684\u56DE\u8C03\u540D\r\n const callbackName = generateKey('pk_mut_cb');\r\n\r\n // \u5982\u679C\u6709 onMutation \u56DE\u8C03\uFF0C\u66B4\u9732\u51FD\u6570\u5E76\u8FD4\u56DE\u7ED3\u679C\r\n if (onMutation) {\r\n try {\r\n await page.exposeFunction(callbackName, async (context) => {\r\n try {\r\n const result = await onMutation(context);\r\n const paused = !(result === null || result === undefined);\r\n // \u8FD4\u56DE null/undefined \u8868\u793A\u6B63\u5E38\u8BA1\u65F6\uFF0C\u5176\u4ED6\u503C\u8868\u793A\u6682\u505C\r\n return paused ? '__PAUSE__' : '__CONTINUE__';\r\n } catch (e) {\r\n // \u56DE\u8C03\u51FA\u9519\u65F6\u9ED8\u8BA4\u7EE7\u7EED\u8BA1\u65F6\r\n return '__CONTINUE__';\r\n }\r\n });\r\n logger.info('waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03');\r\n } catch (e) {\r\n // \u53EF\u80FD\u5DF2\u7ECF\u66B4\u9732\u8FC7\uFF0C\u5FFD\u7565\r\n }\r\n }\r\n\r\n const result = await page.evaluate(\r\n async ({ selectorList, stableTime, timeout, callbackName, hasCallback }) => {\r\n return new Promise((resolve, reject) => {\r\n let mutationCount = 0;\r\n let stableTimer = null;\r\n let timeoutTimer = null;\r\n let isPaused = false;\r\n let wasPaused = false;\r\n const observers = [];\r\n\r\n // \u6E05\u7406\u51FD\u6570\r\n const cleanup = () => {\r\n observers.forEach(obs => obs.disconnect());\r\n if (stableTimer) clearTimeout(stableTimer);\r\n if (timeoutTimer) clearTimeout(timeoutTimer);\r\n };\r\n\r\n // \u91CD\u7F6E\u7A33\u5B9A\u8BA1\u65F6\u5668\r\n const resetStableTimer = () => {\r\n if (stableTimer) clearTimeout(stableTimer);\r\n if (isPaused) return;\r\n stableTimer = setTimeout(() => {\r\n cleanup();\r\n resolve({ mutationCount, stableTime, wasPaused });\r\n }, stableTime);\r\n };\r\n\r\n const setPaused = (nextPaused) => {\r\n if (isPaused === nextPaused) return;\r\n isPaused = nextPaused;\r\n if (isPaused) {\r\n if (stableTimer) clearTimeout(stableTimer);\r\n stableTimer = null;\r\n wasPaused = true;\r\n return;\r\n }\r\n resetStableTimer();\r\n };\r\n\r\n // \u6574\u4F53\u8D85\u65F6\uFF08\u59CB\u7EC8\u751F\u6548\uFF0C\u4E0D\u53D7\u6682\u505C\u5F71\u54CD\uFF09\r\n timeoutTimer = setTimeout(() => {\r\n cleanup();\r\n reject(new Error(`waitForStable \u8D85\u65F6 (${timeout}ms), \u5DF2\u68C0\u6D4B\u5230 ${mutationCount} \u6B21\u53D8\u5316, isPaused=${isPaused}`));\r\n }, timeout);\r\n\r\n // \u4E3A\u6BCF\u4E2A\u9009\u62E9\u5668\u521B\u5EFA MutationObserver\r\n selectorList.forEach(selector => {\r\n const elements = document.querySelectorAll(selector);\r\n elements.forEach(element => {\r\n const observer = new MutationObserver(async (mutations) => {\r\n mutationCount += mutations.length;\r\n\r\n if (hasCallback && window[callbackName]) {\r\n // \u83B7\u53D6\u5143\u7D20\u5185\u5BB9\r\n const html = element.outerHTML || '';\r\n const text = element.innerText || element.textContent || '';\r\n const mutationNodes = [{ html, text, mutationType: 'stable' }];\r\n\r\n try {\r\n const signal = await window[callbackName]({\r\n mutationCount,\r\n html,\r\n text,\r\n mutationNodes\r\n });\r\n\r\n const shouldPause = signal === '__PAUSE__';\r\n setPaused(shouldPause);\r\n if (!shouldPause) {\r\n resetStableTimer();\r\n }\r\n } catch (e) {\r\n // \u56DE\u8C03\u51FA\u9519\u65F6\u7EE7\u7EED\u8BA1\u65F6\r\n setPaused(false);\r\n resetStableTimer();\r\n }\r\n } else {\r\n // \u6CA1\u6709\u56DE\u8C03\uFF0C\u4FDD\u6301\u539F\u6709\u884C\u4E3A\r\n resetStableTimer();\r\n }\r\n });\r\n\r\n observer.observe(element, {\r\n childList: true,\r\n subtree: true,\r\n characterData: true,\r\n attributes: true\r\n });\r\n\r\n observers.push(observer);\r\n });\r\n });\r\n\r\n // \u5982\u679C\u6CA1\u6709\u627E\u5230\u4EFB\u4F55\u5143\u7D20\uFF0C\u76F4\u63A5\u8FD4\u56DE\r\n if (observers.length === 0) {\r\n cleanup();\r\n resolve({ mutationCount: 0, stableTime: 0, wasPaused: false });\r\n return;\r\n }\r\n\r\n // \u521D\u59CB\u68C0\u67E5\uFF1A\u6302\u8F7D\u540E\u7ACB\u5373\u6267\u884C\u4E00\u6B21\u56DE\u8C03\uFF0C\u5224\u65AD\u662F\u5426\u9700\u8981\u6682\u505C\r\n const runInitialCheck = async () => {\r\n if (hasCallback && window[callbackName]) {\r\n // \u83B7\u53D6\u7B2C\u4E00\u4E2A\u76D1\u63A7\u5143\u7D20\u7684\u5185\u5BB9\r\n const firstSelector = selectorList[0];\r\n const firstElement = document.querySelector(firstSelector);\r\n if (firstElement) {\r\n const html = firstElement.outerHTML || '';\r\n const text = firstElement.innerText || firstElement.textContent || '';\r\n const mutationNodes = [{ html, text, mutationType: 'stable' }];\r\n\r\n try {\r\n const signal = await window[callbackName]({\r\n mutationCount: 0,\r\n html,\r\n text,\r\n mutationNodes\r\n });\r\n\r\n if (signal === '__PAUSE__') {\r\n setPaused(true);\r\n return; // \u6682\u505C\u65F6\u4E0D\u542F\u52A8\u521D\u59CB\u8BA1\u65F6\r\n }\r\n } catch (e) {\r\n // \u56DE\u8C03\u51FA\u9519\u65F6\u7EE7\u7EED\r\n }\r\n }\r\n }\r\n // \u542F\u52A8\u521D\u59CB\u7A33\u5B9A\u8BA1\u65F6\u5668\r\n resetStableTimer();\r\n };\r\n\r\n runInitialCheck();\r\n });\r\n },\r\n { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }\r\n );\r\n\r\n if (result.mutationCount === 0 && result.stableTime === 0) {\r\n logger.warning('waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20');\r\n }\r\n logger.success('waitForStable', `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ', \u66FE\u6682\u505C\u8BA1\u65F6' : ''}`);\r\n return result;\r\n },\r\n /**\r\n * \u7B49\u5F85\u8DE8 root DOM \u5143\u7D20\u7A33\u5B9A\uFF08\u4E3B\u6587\u6863 + iframe \u5185\u5BB9\uFF09\r\n * \u901A\u8FC7\u8F6E\u8BE2\u5FEB\u7167\u68C0\u6D4B\u53D8\u5316\uFF0C\u9002\u914D iframe / shadow \u573A\u666F\r\n *\r\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\r\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u5355\u4E2A\u6216\u591A\u4E2A\uFF08\u5EFA\u8BAE\u4F20 iframe \u9009\u62E9\u5668\uFF09\r\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\uFF08\u7B7E\u540D\u4E0E waitForStable \u4FDD\u6301\u4E00\u81F4\uFF09\r\n * @param {number} [options.initialTimeout] - \u7B49\u5F85\u5143\u7D20\u51FA\u73B0\u7684\u8D85\u65F6 (\u6BEB\u79D2, \u9ED8\u8BA4: 60000)\r\n * @param {number} [options.stableTime] - \u65E0\u53D8\u5316\u6301\u7EED\u65F6\u95F4\u540E resolve (\u6BEB\u79D2, \u9ED8\u8BA4: 10000)\r\n * @param {number} [options.timeout] - \u6574\u4F53\u8D85\u65F6\u65F6\u95F4 (\u6BEB\u79D2, \u9ED8\u8BA4: 180000)\r\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\u94A9\u5B50\r\n * @returns {Promise<{ mutationCount: number, stableTime: number, wasPaused: boolean }>}\r\n */\r\n async waitForStableAcrossRoots(page, selectors, options = {}) {\r\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\r\n const selectorQuery = selectorList.join(',');\r\n const initialTimeout = options.initialTimeout ?? 60 * 1000;\r\n const waitForStableTime = options.stableTime ?? 10 * 1000;\r\n const overallTimeout = options.timeout ?? 180 * 1000;\r\n const onMutation = options.onMutation;\r\n const pollInterval = 500;\r\n\r\n const sleep = (ms) => new Promise((resolve) => {\r\n setTimeout(resolve, ms);\r\n });\r\n\r\n const truncate = (value, max = 800) => {\r\n const text = String(value || '');\r\n if (text.length <= max) return text;\r\n return `${text.slice(0, max)}...`;\r\n };\r\n\r\n const buildState = async () => {\r\n return await page.evaluate(({ selectorList }) => {\r\n const normalizeText = (value) => String(value || '').replace(/\\s+/g, ' ').trim();\r\n const tail = (value, max = 512) => {\r\n const text = String(value || '');\r\n if (text.length <= max) return text;\r\n return text.slice(text.length - max);\r\n };\r\n const safeFrameId = (frameEl) => {\r\n const id = String(frameEl?.id || '').trim();\r\n if (id) return id;\r\n const name = String(frameEl?.name || '').trim();\r\n if (name) return name;\r\n return 'no-id';\r\n };\r\n\r\n const items = [];\r\n\r\n selectorList.forEach((selector) => {\r\n let nodes = [];\r\n try {\r\n nodes = Array.from(document.querySelectorAll(selector));\r\n } catch {\r\n return;\r\n }\r\n\r\n nodes.forEach((node, index) => {\r\n const isIframe = node?.tagName === 'IFRAME';\r\n let text = '';\r\n let html = '';\r\n let source = 'main';\r\n let path = `${selector}[${index}]`;\r\n\r\n if (isIframe) {\r\n source = 'iframe';\r\n path = `${selector}[${index}]::iframe(${safeFrameId(node)})`;\r\n try {\r\n const frameDoc = node.contentDocument;\r\n const frameRoot = frameDoc?.body || frameDoc?.documentElement;\r\n if (frameRoot) {\r\n text = normalizeText(frameRoot.innerText || frameRoot.textContent || '');\r\n html = normalizeText(frameRoot.innerHTML || '');\r\n }\r\n } catch {\r\n // ignore cross-origin iframe\r\n }\r\n } else {\r\n text = normalizeText(node?.innerText || node?.textContent || '');\r\n html = normalizeText(node?.innerHTML || node?.outerHTML || '');\r\n }\r\n\r\n const snapshot = text || html;\r\n items.push({\r\n selector,\r\n source,\r\n path,\r\n text,\r\n html,\r\n snapshot,\r\n });\r\n });\r\n });\r\n\r\n const snapshotKey = items\r\n .map((item) => `${item.path}:${item.snapshot.length}:${tail(item.snapshot, 512)}`)\r\n .join('||');\r\n const summaryText = items.map((item) => item.snapshot || item.text).join('\\n').trim();\r\n const summaryHtml = items.map((item) => item.html).join('\\n');\r\n const hasMatched = items.length > 0;\r\n const primary = items.length > 0 ? items[items.length - 1] : null;\r\n\r\n return {\r\n hasMatched,\r\n snapshotKey,\r\n text: summaryText,\r\n html: summaryHtml,\r\n snapshotLength: summaryText.length,\r\n itemCount: items.length,\r\n primaryPath: primary?.path || '',\r\n mutationNodes: items.map((item) => ({\r\n html: item.html,\r\n text: item.snapshot || item.text,\r\n mutationType: item.source,\r\n })),\r\n };\r\n }, { selectorList });\r\n };\r\n\r\n const invokeMutationCallback = async (context) => {\r\n if (!onMutation) return '__CONTINUE__';\r\n try {\r\n const result = await onMutation(context);\r\n return (result === null || result === undefined) ? '__CONTINUE__' : '__PAUSE__';\r\n } catch {\r\n return '__CONTINUE__';\r\n }\r\n };\r\n\r\n logger.start(\r\n 'waitForStableAcrossRoots',\r\n `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`\r\n );\r\n\r\n if (initialTimeout > 0) {\r\n try {\r\n await page.waitForSelector(selectorQuery, { timeout: initialTimeout });\r\n logger.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);\r\n } catch (e) {\r\n logger.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);\r\n throw e;\r\n }\r\n }\r\n\r\n let state = await buildState();\r\n if (!state?.hasMatched) {\r\n logger.warning('waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20');\r\n return { mutationCount: 0, stableTime: 0, wasPaused: false };\r\n }\r\n\r\n let mutationCount = 0;\r\n let stableSince = 0;\r\n let isPaused = false;\r\n let wasPaused = false;\r\n let lastSnapshotKey = state.snapshotKey;\r\n\r\n const applyPauseSignal = (signal) => {\r\n const nextPaused = signal === '__PAUSE__';\r\n if (nextPaused) {\r\n if (!isPaused) wasPaused = true;\r\n isPaused = true;\r\n stableSince = 0;\r\n return;\r\n }\r\n\r\n isPaused = false;\r\n stableSince = Date.now();\r\n };\r\n\r\n const initialSignal = await invokeMutationCallback({\r\n mutationCount: 0,\r\n html: state.html || '',\r\n text: state.text || '',\r\n mutationNodes: state.mutationNodes || [],\r\n });\r\n applyPauseSignal(initialSignal);\r\n\r\n const deadline = Date.now() + overallTimeout;\r\n let lastState = state;\r\n\r\n while (Date.now() < deadline) {\r\n await sleep(pollInterval);\r\n lastState = await buildState();\r\n\r\n if (!lastState?.hasMatched) {\r\n continue;\r\n }\r\n\r\n if (lastState.snapshotKey !== lastSnapshotKey) {\r\n lastSnapshotKey = lastState.snapshotKey;\r\n mutationCount += 1;\r\n\r\n logger.info(\r\n `waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || 'unknown'}, preview=\"${truncate(lastState.text, 120)}\"`\r\n );\r\n\r\n const signal = await invokeMutationCallback({\r\n mutationCount,\r\n html: lastState.html || '',\r\n text: lastState.text || '',\r\n mutationNodes: lastState.mutationNodes || [],\r\n });\r\n applyPauseSignal(signal);\r\n continue;\r\n }\r\n\r\n if (!isPaused && stableSince > 0 && (Date.now() - stableSince) >= waitForStableTime) {\r\n logger.success('waitForStableAcrossRoots', `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ', \u66FE\u6682\u505C\u8BA1\u65F6' : ''}`);\r\n return {\r\n mutationCount,\r\n stableTime: waitForStableTime,\r\n wasPaused,\r\n };\r\n }\r\n }\r\n\r\n throw new Error(`waitForStableAcrossRoots \u8D85\u65F6 (${overallTimeout}ms), \u5DF2\u68C0\u6D4B\u5230 ${mutationCount} \u6B21\u53D8\u5316, isPaused=${isPaused}`);\r\n },\r\n\r\n /**\r\n * \u521B\u5EFA\u4E00\u4E2A\u6301\u7EED\u76D1\u63A7 DOM \u53D8\u5316\u7684\u76D1\u63A7\u5668\uFF08\u9ED8\u8BA4\u4EC5\u76D1\u542C\u65B0\u589E DOM\uFF09\r\n *\r\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\r\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u652F\u6301 'document.documentElement'\r\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\r\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\r\n * \u7B7E\u540D: ({ mutationCount, html, text, mutationNodes }) => void\r\n * \u6240\u6709\u6A21\u5F0F\u90FD\u8FD4\u56DE\u672C\u6B21\u5168\u90E8\u53D8\u5316\u8282\u70B9\u5FEB\u7167 mutationNodes\r\n * @param {'added' | 'changed' | 'all'} [options.mode='added'] - \u76D1\u63A7\u6A21\u5F0F\r\n * @returns {Promise<{ stop: () => Promise<{ totalMutations: number }> }>} - \u8FD4\u56DE\u505C\u6B62\u51FD\u6570\r\n */\r\n async useMonitor(page, selectors, options = {}) {\r\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\r\n const onMutation = options.onMutation;\r\n const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();\r\n const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode)\r\n ? rawMode\r\n : MUTATION_MONITOR_MODE.Added;\r\n\r\n logger.start('useMonitor', `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);\r\n\r\n const monitorKey = generateKey('pk_mon');\r\n const callbackName = generateKey('pk_mon_cb');\r\n const cleanerName = generateKey('pk_mon_clean');\r\n\r\n if (onMutation) {\r\n try {\r\n await page.exposeFunction(callbackName, (payload) => {\r\n try {\r\n onMutation(payload);\r\n } catch (e) {\r\n // \u5FFD\u7565\u56DE\u8C03\u9519\u8BEF\r\n }\r\n });\r\n } catch (e) {\r\n // \u53EF\u80FD\u5DF2\u7ECF\u66B4\u9732\u8FC7\uFF0C\u5FFD\u7565\r\n }\r\n }\r\n\r\n await page.evaluate(({ selectorList, monitorKey, callbackName, cleanerName, hasCallback, mode }) => {\r\n const monitor = {\r\n observers: [],\r\n totalMutations: 0,\r\n running: true,\r\n };\r\n\r\n const resolveTargets = (selector) => {\r\n const key = String(selector || '').trim();\r\n if (!key) return [];\r\n\r\n if (key === 'document.documentElement' || key === 'documentElement' || key === 'document') {\r\n return document.documentElement ? [document.documentElement] : [];\r\n }\r\n\r\n if (key === 'document.body') {\r\n return document.body ? [document.body] : [];\r\n }\r\n\r\n return Array.from(document.querySelectorAll(key));\r\n };\r\n\r\n const serializeNode = (node, mutationType = 'unknown') => {\r\n if (!node) {\r\n return { html: '', text: '', mutationType };\r\n }\r\n\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n return {\r\n html: node.outerHTML || '',\r\n text: node.innerText || node.textContent || '',\r\n mutationType,\r\n };\r\n }\r\n\r\n if (node.nodeType === Node.TEXT_NODE) {\r\n const text = node.textContent || '';\r\n return { html: text, text, mutationType };\r\n }\r\n\r\n if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\r\n const nodes = Array.from(node.childNodes || []);\r\n const html = nodes\r\n .map(item => item?.nodeType === Node.ELEMENT_NODE ? (item.outerHTML || '') : (item?.textContent || ''))\r\n .join('\\n');\r\n const text = node.textContent || '';\r\n return { html: html || text, text, mutationType };\r\n }\r\n\r\n const text = node.textContent || '';\r\n return { html: text, text, mutationType };\r\n };\r\n\r\n const collectMutationNodes = (mutations) => {\r\n const mutationNodes = [];\r\n\r\n for (const mutation of mutations) {\r\n if (mode === 'added') {\r\n if (mutation.type !== 'childList') continue;\r\n const added = Array.from(mutation.addedNodes || []);\r\n for (const node of added) {\r\n mutationNodes.push(serializeNode(node, 'added'));\r\n }\r\n continue;\r\n }\r\n\r\n if (mode === 'changed') {\r\n if (mutation.type === 'attributes' || mutation.type === 'characterData') {\r\n mutationNodes.push(serializeNode(mutation.target, mutation.type));\r\n } else if (mutation.type === 'childList') {\r\n const added = Array.from(mutation.addedNodes || []);\r\n const removed = Array.from(mutation.removedNodes || []);\r\n\r\n for (const node of added) {\r\n mutationNodes.push(serializeNode(node, 'added'));\r\n }\r\n for (const node of removed) {\r\n mutationNodes.push(serializeNode(node, 'removed'));\r\n }\r\n\r\n if (added.length === 0 && removed.length === 0) {\r\n mutationNodes.push(serializeNode(mutation.target, 'childList'));\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n if (mutation.type === 'childList') {\r\n const added = Array.from(mutation.addedNodes || []);\r\n const removed = Array.from(mutation.removedNodes || []);\r\n\r\n for (const node of added) {\r\n mutationNodes.push(serializeNode(node, 'added'));\r\n }\r\n for (const node of removed) {\r\n mutationNodes.push(serializeNode(node, 'removed'));\r\n }\r\n\r\n if (added.length === 0 && removed.length === 0) {\r\n mutationNodes.push(serializeNode(mutation.target, 'childList'));\r\n }\r\n } else if (mutation.type === 'attributes' || mutation.type === 'characterData') {\r\n mutationNodes.push(serializeNode(mutation.target, mutation.type));\r\n } else {\r\n mutationNodes.push(serializeNode(mutation.target, mutation.type || 'unknown'));\r\n }\r\n }\r\n\r\n return mutationNodes;\r\n };\r\n\r\n selectorList.forEach(selector => {\r\n const elements = resolveTargets(selector);\r\n elements.forEach(element => {\r\n const observer = new MutationObserver((mutations) => {\r\n if (!monitor.running) return;\r\n\r\n const mutationNodes = collectMutationNodes(mutations);\r\n if (mutationNodes.length <= 0) return;\r\n\r\n monitor.totalMutations += mutationNodes.length;\r\n\r\n if (hasCallback && window[callbackName]) {\r\n const html = mutationNodes.map(item => item.html || '').join('\\n');\r\n const text = mutationNodes.map(item => item.text || '').join('\\n');\r\n\r\n window[callbackName]({\r\n mutationCount: monitor.totalMutations,\r\n html,\r\n text,\r\n mutationNodes,\r\n });\r\n }\r\n });\r\n\r\n observer.observe(element, {\r\n childList: true,\r\n subtree: true,\r\n characterData: mode !== 'added',\r\n attributes: mode !== 'added',\r\n });\r\n\r\n monitor.observers.push(observer);\r\n });\r\n });\r\n\r\n window[monitorKey] = monitor;\r\n window[cleanerName] = () => {\r\n monitor.running = false;\r\n monitor.observers.forEach(obs => obs.disconnect());\r\n const total = monitor.totalMutations;\r\n delete window[monitorKey];\r\n delete window[cleanerName];\r\n return total;\r\n };\r\n }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });\r\n\r\n logger.success('useMonitor', '\u76D1\u63A7\u5668\u5DF2\u542F\u52A8');\r\n\r\n return {\r\n stop: async () => {\r\n let totalMutations = 0;\r\n try {\r\n totalMutations = await page.evaluate((cleanerName) => {\r\n if (window[cleanerName]) {\r\n return window[cleanerName]();\r\n }\r\n return 0;\r\n }, cleanerName);\r\n } catch (e) {\r\n // \u9875\u9762\u53EF\u80FD\u5DF2\u5173\u95ED\uFF0C\u5FFD\u7565\r\n }\r\n logger.success('useMonitor.stop', `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);\r\n return { totalMutations };\r\n }\r\n };\r\n }\r\n};\r\n", "export const Display = {\r\n parseTokenDisplayName(value) {\r\n if (!value) {\r\n return { owner: '', envType: '', note: '' };\r\n }\r\n const parts = String(value).split(':');\r\n const owner = (parts[0] || '').trim();\r\n const envType = (parts[1] || '').trim();\r\n const note = parts.length > 2 ? parts.slice(2).join(':').trim() : '';\r\n return { owner, envType, note };\r\n },\r\n\r\n parseEnvDisplayName(value) {\r\n if (!value) {\r\n return { env: '', owner: '', envType: '', note: '' };\r\n }\r\n const parts = String(value).split(':');\r\n const env = (parts[0] || '').trim();\r\n const owner = (parts[1] || '').trim();\r\n const envType = (parts[2] || '').trim();\r\n const note = parts.length > 3 ? parts.slice(3).join(':').trim() : '';\r\n return { env, owner, envType, note };\r\n },\r\n\r\n buildTokenDisplayName({ owner, envType, note } = {}) {\r\n const trimmedOwner = owner?.trim() || '';\r\n const trimmedType = envType?.trim() || '';\r\n const trimmedNote = note?.trim() || '';\r\n const parts = [trimmedOwner, trimmedType];\r\n if (trimmedNote) {\r\n parts.push(trimmedNote);\r\n }\r\n return parts.filter(Boolean).join(':');\r\n },\r\n\r\n shortId(value, max = 8) {\r\n const clean = String(value || '').trim();\r\n if (!clean) return '';\r\n if (clean.length <= max) return clean;\r\n return clean.slice(0, max);\r\n },\r\n\r\n resolveTokenIdentity(displayName, tokenId) {\r\n const cleanName = String(displayName || '').trim();\r\n const cleanId = String(tokenId || '').trim();\r\n const short = this.shortId(cleanId, 8);\r\n const hasName = cleanName !== '' && cleanName !== cleanId;\r\n const primary = hasName ? cleanName : (short || '-');\r\n const secondary = hasName && short ? short : '';\r\n return { primary, secondary, fullId: cleanId, shortId: short };\r\n },\r\n\r\n resolveEnvIdentity(displayName, envId) {\r\n const parts = this.parseEnvDisplayName(displayName);\r\n const cleanId = String(envId || '').trim();\r\n const short = this.shortId(cleanId, 8);\r\n const hasName = parts.env !== '' && parts.env !== cleanId;\r\n const primary = hasName ? parts.env : (short || '-');\r\n const secondary = hasName && short ? short : '';\r\n return { primary, secondary, parts, fullId: cleanId, shortId: short };\r\n },\r\n};\r\n", "import { createBaseLogger, setDefaultLogger } from './internals/logger.js';\r\n\r\nexport const stripAnsi = (input) => {\r\n if (!input) return '';\r\n return String(input).replace(/\\x1b\\[[0-9;]*m/g, '');\r\n};\r\n\r\n// =============================================================================\r\n// Log Templates & Definitions\r\n// =============================================================================\r\n\r\nconst STEP_PREFIX = '\u6B65\u9AA4:';\r\nconst STEP_SEPARATOR = ' | ';\r\nconst STEP_EMOJIS = [\r\n { match: '\u4EFB\u52A1', emoji: '\uD83E\uDDED' },\r\n { match: '\u8FD0\u884C\u6A21\u5F0F', emoji: '\uD83E\uDDE9' },\r\n { match: '\u6A21\u677F\u8BC6\u522B', emoji: '\uD83E\uDDF1' },\r\n { match: '\u767B\u5F55', emoji: '\uD83D\uDD10' },\r\n { match: '\u73AF\u5883', emoji: '\uD83E\uDDEA' },\r\n { match: '\u8F93\u5165', emoji: '\u2328\uFE0F' },\r\n { match: '\u53D1\u9001', emoji: '\uD83D\uDCE4' },\r\n { match: '\u54CD\u5E94\u76D1\u542C', emoji: '\uD83D\uDCE1' },\r\n { match: '\u7B49\u5F85\u54CD\u5E94', emoji: '\u23F3' },\r\n { match: '\u6D41\u5F0F', emoji: '\uD83E\uDDF5' },\r\n { match: '\u5F15\u7528', emoji: '\uD83D\uDCCE' },\r\n { match: '\u622A\u56FE', emoji: '\uD83D\uDDBC\uFE0F' },\r\n { match: '\u5206\u4EAB\u94FE\u63A5', emoji: '\uD83D\uDD17' },\r\n { match: '\u6570\u636E\u63A8\u9001', emoji: '\uD83D\uDCE6' },\r\n { match: '\u5F39\u7A97', emoji: '\uD83E\uDE9F' },\r\n];\r\nconst STATUS_EMOJIS = [\r\n { match: '\u5F00\u59CB', emoji: '\uD83D\uDE80' },\r\n { match: '\u5B8C\u6210', emoji: '\u2705' },\r\n { match: '\u6210\u529F', emoji: '\u2705' },\r\n { match: '\u5931\u8D25', emoji: '\u274C' },\r\n { match: '\u8DF3\u8FC7', emoji: '\u23ED\uFE0F' },\r\n { match: '\u8D85\u65F6', emoji: '\u23F1\uFE0F' },\r\n { match: '\u91CD\u8BD5', emoji: '\uD83D\uDD01' },\r\n { match: '\u7ED3\u675F', emoji: '\uD83C\uDFC1' },\r\n { match: '\u5DF2\u914D\u7F6E', emoji: '\uD83E\uDDF7' },\r\n { match: '\u5DF2\u68C0\u6D4B', emoji: '\uD83D\uDD0E' },\r\n];\r\n\r\nconst toErrorMessage = (error) => {\r\n if (!error) return '';\r\n if (error instanceof Error) return error.message;\r\n if (typeof error === 'string') return error;\r\n try {\r\n return JSON.stringify(error);\r\n } catch {\r\n return String(error);\r\n }\r\n};\r\n\r\nconst decorateLabel = (label, mappings) => {\r\n if (!label) return '';\r\n const mapping = mappings.find((item) => label.includes(item.match));\r\n if (!mapping) return label;\r\n return `${mapping.emoji} ${label}`;\r\n};\r\n\r\nconst normalizeSnippet = (snippet, maxLen = 120) => {\r\n if (!snippet) return '';\r\n const text = String(snippet).replace(/\\s+/g, ' ').trim();\r\n if (!text) return '';\r\n const cleaned = text.replace(/\"/g, \"'\");\r\n if (cleaned.length <= maxLen) return cleaned;\r\n return `${cleaned.slice(0, maxLen)}...`;\r\n};\r\n\r\nconst LOG_TAG_PREFIX = '[#log:';\r\nconst LOG_TAG_SUFFIX = ']';\r\n\r\nconst buildLogTag = (key) => `${LOG_TAG_PREFIX}${key}${LOG_TAG_SUFFIX}`;\r\n\r\nconst escapeRegExp = (value) => String(value).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n\r\nconst buildStepPattern = (step, status) => {\r\n if (!step) return null;\r\n let pattern = `\u6B65\u9AA4: .*${escapeRegExp(step)}`;\r\n if (status) {\r\n pattern += `.*${escapeRegExp(status)}`;\r\n }\r\n return new RegExp(pattern);\r\n};\r\n\r\nconst buildDefinitionPatterns = (definition) => {\r\n const patterns = [new RegExp(`\\\\[#log:${escapeRegExp(definition.key)}\\\\]`)];\r\n const fallback = buildStepPattern(definition.step, definition.status);\r\n if (fallback) patterns.push(fallback);\r\n if (Array.isArray(definition.extraPatterns)) {\r\n patterns.push(...definition.extraPatterns);\r\n }\r\n return patterns;\r\n};\r\n\r\nconst ATTENTION_RANK = {\r\n low: 1,\r\n medium: 2,\r\n high: 3,\r\n critical: 4,\r\n};\r\nconst DEFAULT_ATTENTION_RANK = ATTENTION_RANK.high;\r\n\r\nconst LOG_DEFINITIONS = [\r\n {\r\n key: 'task_start',\r\n method: 'taskStart',\r\n label: '\u4EFB\u52A1\u5F00\u59CB',\r\n group: '\u4EFB\u52A1',\r\n step: '\u4EFB\u52A1',\r\n status: '\u5F00\u59CB',\r\n level: 'start',\r\n attention: 'low',\r\n buildDetails: (url) => [url ? `url=${url}` : ''],\r\n },\r\n {\r\n key: 'task_success',\r\n method: 'taskSuccess',\r\n label: '\u4EFB\u52A1\u5B8C\u6210',\r\n group: '\u4EFB\u52A1',\r\n step: '\u4EFB\u52A1',\r\n status: '\u5B8C\u6210',\r\n level: 'success',\r\n attention: 'high',\r\n },\r\n {\r\n key: 'task_fail',\r\n method: 'taskFail',\r\n label: '\u4EFB\u52A1\u5931\u8D25',\r\n group: '\u4EFB\u52A1',\r\n step: '\u4EFB\u52A1',\r\n status: '\u5931\u8D25',\r\n level: 'error',\r\n attention: 'critical',\r\n buildDetails: (url, err) => [\r\n url ? `url=${url}` : '',\r\n err ? `err=${toErrorMessage(err)}` : ''\r\n ],\r\n },\r\n {\r\n key: 'runtime_headless',\r\n method: 'runtimeHeadless',\r\n label: '\u8FD0\u884C\u6A21\u5F0F\u5F3A\u5236\u65E0\u5934',\r\n group: '\u8FD0\u884C\u6A21\u5F0F',\r\n step: '\u8FD0\u884C\u6A21\u5F0F',\r\n status: 'Apify \u73AF\u5883\u5F3A\u5236\u65E0\u5934',\r\n level: 'warning',\r\n attention: 'medium',\r\n },\r\n {\r\n key: 'login_inject_success',\r\n method: 'loginInjectSuccess',\r\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u6210\u529F',\r\n group: '\u767B\u5F55',\r\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\r\n status: '\u6210\u529F',\r\n level: 'success',\r\n attention: 'medium',\r\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\r\n },\r\n {\r\n key: 'login_inject_skip',\r\n method: 'loginInjectSkip',\r\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u8DF3\u8FC7',\r\n group: '\u767B\u5F55',\r\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\r\n status: '\u8DF3\u8FC7',\r\n level: 'warning',\r\n attention: 'medium',\r\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\r\n },\r\n {\r\n key: 'login_inject_fail',\r\n method: 'loginInjectFail',\r\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u5931\u8D25',\r\n group: '\u767B\u5F55',\r\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\r\n status: '\u5931\u8D25',\r\n level: 'error',\r\n attention: 'high',\r\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\r\n },\r\n {\r\n key: 'login_verify_success',\r\n method: 'loginVerifySuccess',\r\n label: '\u767B\u5F55\u9A8C\u8BC1\u6210\u529F',\r\n group: '\u767B\u5F55',\r\n step: '\u767B\u5F55\u9A8C\u8BC1',\r\n status: '\u6210\u529F',\r\n level: 'success',\r\n attention: 'high',\r\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\r\n },\r\n {\r\n key: 'login_verify_skip',\r\n method: 'loginVerifySkip',\r\n label: '\u767B\u5F55\u9A8C\u8BC1\u8DF3\u8FC7',\r\n group: '\u767B\u5F55',\r\n step: '\u767B\u5F55\u9A8C\u8BC1',\r\n status: '\u8DF3\u8FC7',\r\n level: 'warning',\r\n attention: 'medium',\r\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\r\n },\r\n {\r\n key: 'login_verify_fail',\r\n method: 'loginVerifyFail',\r\n label: '\u767B\u5F55\u9A8C\u8BC1\u5931\u8D25',\r\n group: '\u767B\u5F55',\r\n step: '\u767B\u5F55\u9A8C\u8BC1',\r\n status: '\u5931\u8D25',\r\n level: 'error',\r\n attention: 'critical',\r\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\r\n },\r\n {\r\n key: 'env_check_success',\r\n method: 'envCheckSuccess',\r\n label: '\u73AF\u5883\u68C0\u67E5\u6210\u529F',\r\n group: '\u73AF\u5883',\r\n step: '\u73AF\u5883\u68C0\u67E5',\r\n status: '\u6210\u529F',\r\n level: 'success',\r\n attention: 'medium',\r\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\r\n },\r\n {\r\n key: 'env_check_fail',\r\n method: 'envCheckFail',\r\n label: '\u73AF\u5883\u68C0\u67E5\u5931\u8D25',\r\n group: '\u73AF\u5883',\r\n step: '\u73AF\u5883\u68C0\u67E5',\r\n status: '\u5931\u8D25',\r\n level: 'error',\r\n attention: 'high',\r\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\r\n },\r\n {\r\n key: 'input_query_start',\r\n method: 'inputQuery',\r\n label: '\u8F93\u5165\u67E5\u8BE2\u5F00\u59CB',\r\n group: '\u8F93\u5165',\r\n step: '\u8F93\u5165\u67E5\u8BE2',\r\n status: '\u5F00\u59CB',\r\n level: 'start',\r\n attention: 'low',\r\n buildDetails: (query) => [query ? `query=${query}` : ''],\r\n },\r\n {\r\n key: 'send_action',\r\n method: 'sendAction',\r\n label: '\u53D1\u9001\u8BF7\u6C42',\r\n group: '\u53D1\u9001',\r\n step: '\u53D1\u9001\u8BF7\u6C42',\r\n status: '\u70B9\u51FB\u53D1\u9001',\r\n level: 'info',\r\n attention: 'low',\r\n },\r\n {\r\n key: 'response_listen_start',\r\n method: 'responseListenStart',\r\n label: '\u54CD\u5E94\u76D1\u542C\u5F00\u59CB',\r\n group: '\u54CD\u5E94\u76D1\u542C',\r\n step: '\u54CD\u5E94\u76D1\u542C',\r\n status: '\u5F00\u59CB',\r\n level: 'start',\r\n attention: 'low',\r\n buildDetails: (label, timeoutSec) => [\r\n label ? `\u76EE\u6807=${label}` : '',\r\n timeoutSec ? `timeout=${timeoutSec}s` : ''\r\n ],\r\n },\r\n {\r\n key: 'response_listen_ready',\r\n method: 'responseListenReady',\r\n label: '\u54CD\u5E94\u76D1\u542C\u5DF2\u914D\u7F6E',\r\n group: '\u54CD\u5E94\u76D1\u542C',\r\n step: '\u54CD\u5E94\u76D1\u542C',\r\n status: '\u5DF2\u914D\u7F6E',\r\n level: 'info',\r\n attention: 'medium',\r\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\r\n },\r\n {\r\n key: 'response_listen_detected',\r\n method: 'responseListenDetected',\r\n label: '\u54CD\u5E94\u76D1\u542C\u5DF2\u68C0\u6D4B',\r\n group: '\u54CD\u5E94\u76D1\u542C',\r\n step: '\u54CD\u5E94\u76D1\u542C',\r\n status: '\u5DF2\u68C0\u6D4B',\r\n level: 'success',\r\n attention: 'medium',\r\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\r\n },\r\n {\r\n key: 'response_listen_timeout',\r\n method: 'responseListenTimeout',\r\n label: '\u54CD\u5E94\u76D1\u542C\u8D85\u65F6',\r\n group: '\u54CD\u5E94\u76D1\u542C',\r\n step: '\u54CD\u5E94\u76D1\u542C',\r\n status: '\u8D85\u65F6',\r\n level: 'error',\r\n attention: 'high',\r\n buildDetails: (label, err) => [\r\n label ? `\u76EE\u6807=${label}` : '',\r\n err ? `err=${toErrorMessage(err)}` : ''\r\n ],\r\n },\r\n {\r\n key: 'response_listen_end',\r\n method: 'responseListenEnd',\r\n label: '\u54CD\u5E94\u76D1\u542C\u7ED3\u675F',\r\n group: '\u54CD\u5E94\u76D1\u542C',\r\n step: '\u54CD\u5E94\u76D1\u542C',\r\n status: '\u7ED3\u675F',\r\n level: 'info',\r\n attention: 'low',\r\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\r\n },\r\n {\r\n key: 'response_wait_start',\r\n method: 'responseWaitStart',\r\n label: '\u7B49\u5F85\u54CD\u5E94\u5F00\u59CB',\r\n group: '\u7B49\u5F85\u54CD\u5E94',\r\n step: '\u7B49\u5F85\u54CD\u5E94',\r\n status: '\u5F00\u59CB',\r\n level: 'start',\r\n attention: 'low',\r\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\r\n },\r\n {\r\n key: 'response_wait_success',\r\n method: 'responseWaitSuccess',\r\n label: '\u7B49\u5F85\u54CD\u5E94\u5B8C\u6210',\r\n group: '\u7B49\u5F85\u54CD\u5E94',\r\n step: '\u7B49\u5F85\u54CD\u5E94',\r\n status: '\u5B8C\u6210',\r\n level: 'success',\r\n attention: 'medium',\r\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\r\n },\r\n {\r\n key: 'response_wait_fail',\r\n method: 'responseWaitFail',\r\n label: '\u7B49\u5F85\u54CD\u5E94\u5931\u8D25',\r\n group: '\u7B49\u5F85\u54CD\u5E94',\r\n step: '\u7B49\u5F85\u54CD\u5E94',\r\n status: '\u5931\u8D25',\r\n level: 'warning',\r\n attention: 'high',\r\n buildDetails: (label, err) => [\r\n label ? `\u76EE\u6807=${label}` : '',\r\n err ? `err=${toErrorMessage(err)}` : ''\r\n ],\r\n },\r\n {\r\n key: 'response_wait_retry',\r\n method: 'responseWaitRetry',\r\n label: '\u7B49\u5F85\u54CD\u5E94\u91CD\u8BD5',\r\n group: '\u7B49\u5F85\u54CD\u5E94',\r\n step: '\u7B49\u5F85\u54CD\u5E94',\r\n status: '\u91CD\u8BD5',\r\n level: 'warning',\r\n attention: 'medium',\r\n buildDetails: (label, attempt) => [\r\n label ? `\u76EE\u6807=${label}` : '',\r\n attempt !== undefined ? `\u5C1D\u8BD5=${attempt}` : ''\r\n ],\r\n },\r\n {\r\n key: 'dom_wait_start',\r\n method: 'domWaitStart',\r\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5F00\u59CB',\r\n group: 'DOM',\r\n step: 'DOM\u7A33\u5B9A',\r\n status: '\u5F00\u59CB',\r\n level: 'start',\r\n attention: 'low',\r\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\r\n },\r\n {\r\n key: 'dom_wait_fail',\r\n method: 'domWaitFail',\r\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5931\u8D25',\r\n group: 'DOM',\r\n step: 'DOM\u7A33\u5B9A',\r\n status: '\u5931\u8D25',\r\n level: 'warning',\r\n attention: 'high',\r\n buildDetails: (label, err) => [\r\n label ? `\u76EE\u6807=${label}` : '',\r\n err ? `err=${toErrorMessage(err)}` : ''\r\n ],\r\n },\r\n {\r\n key: 'dom_chunk',\r\n method: 'domChunk',\r\n label: 'DOM\u7247\u6BB5',\r\n group: 'DOM',\r\n step: 'DOM\u7247\u6BB5',\r\n status: '',\r\n level: 'info',\r\n attention: 'low',\r\n throttleKey: 'dom-chunk',\r\n throttleMs: 2000,\r\n buildDetails: (length, snippet, paused) => [\r\n length !== undefined ? `len=${length}` : '',\r\n snippet ? `preview=\"${normalizeSnippet(snippet)}\"` : '',\r\n paused ? 'paused=1' : ''\r\n ],\r\n },\r\n {\r\n key: 'dom_wait_success',\r\n method: 'domWaitSuccess',\r\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5B8C\u6210',\r\n group: 'DOM',\r\n step: 'DOM\u7A33\u5B9A',\r\n status: '\u5B8C\u6210',\r\n level: 'success',\r\n attention: 'medium',\r\n buildDetails: (mutationCount, stableTime, wasPaused) => [\r\n mutationCount !== undefined ? `mutations=${mutationCount}` : '',\r\n stableTime !== undefined ? `stableTime=${stableTime}ms` : '',\r\n wasPaused ? 'paused=1' : ''\r\n ],\r\n },\r\n {\r\n key: 'stream_chunk',\r\n method: 'streamChunk',\r\n label: '\u6D41\u5F0F\u7247\u6BB5',\r\n group: '\u6D41\u5F0F',\r\n step: '\u6D41\u5F0F\u7247\u6BB5',\r\n status: '',\r\n level: 'info',\r\n attention: 'low',\r\n throttleKey: 'stream-chunk',\r\n throttleMs: 2000,\r\n buildDetails: (length, snippet) => [\r\n length !== undefined ? `len=${length}` : '',\r\n snippet ? `preview=\"${normalizeSnippet(snippet)}\"` : ''\r\n ],\r\n },\r\n {\r\n key: 'stream_events_parsed',\r\n method: 'streamEventsParsed',\r\n label: '\u6D41\u5F0F\u4E8B\u4EF6\u89E3\u6790\u5B8C\u6210',\r\n group: '\u6D41\u5F0F',\r\n step: '\u6D41\u5F0F\u4E8B\u4EF6\u89E3\u6790',\r\n status: '\u5B8C\u6210',\r\n level: 'info',\r\n attention: 'low',\r\n throttleKey: 'stream-events',\r\n throttleMs: 4000,\r\n buildDetails: (count) => [count !== undefined ? `count=${count}` : ''],\r\n },\r\n {\r\n key: 'stream_complete_event',\r\n method: 'streamCompleteEvent',\r\n label: '\u6D41\u5F0F\u5B8C\u6210\u4E8B\u4EF6\u6355\u83B7',\r\n group: '\u6D41\u5F0F',\r\n step: '\u6D41\u5F0F\u4E8B\u4EF6',\r\n status: '\u5B8C\u6210\u4E8B\u4EF6\u5DF2\u6355\u83B7',\r\n level: 'success',\r\n attention: 'medium',\r\n },\r\n {\r\n key: 'stream_end',\r\n method: 'streamEnd',\r\n label: '\u6D41\u5F0F\u54CD\u5E94\u7ED3\u675F',\r\n group: '\u6D41\u5F0F',\r\n step: '\u6D41\u5F0F\u54CD\u5E94',\r\n status: '\u7ED3\u675F',\r\n level: 'info',\r\n attention: 'low',\r\n },\r\n {\r\n key: 'reference_expand_start',\r\n method: 'referenceExpandStart',\r\n label: '\u5F15\u7528\u5C55\u5F00\u5F00\u59CB',\r\n group: '\u5F15\u7528',\r\n step: '\u5F15\u7528\u5C55\u5F00',\r\n status: '\u5F00\u59CB',\r\n level: 'start',\r\n attention: 'low',\r\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\r\n },\r\n {\r\n key: 'reference_expand_fail',\r\n method: 'referenceExpandFail',\r\n label: '\u5F15\u7528\u5C55\u5F00\u5931\u8D25',\r\n group: '\u5F15\u7528',\r\n step: '\u5F15\u7528\u5C55\u5F00',\r\n status: '\u5931\u8D25',\r\n level: 'warning',\r\n attention: 'medium',\r\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\r\n },\r\n {\r\n key: 'screenshot_start',\r\n method: 'screenshotStart',\r\n label: '\u622A\u56FE\u5F00\u59CB',\r\n group: '\u622A\u56FE',\r\n step: '\u622A\u56FE',\r\n status: '\u5F00\u59CB',\r\n level: 'start',\r\n attention: 'low',\r\n },\r\n {\r\n key: 'screenshot_success',\r\n method: 'screenshotSuccess',\r\n label: '\u622A\u56FE\u6210\u529F',\r\n group: '\u622A\u56FE',\r\n step: '\u622A\u56FE',\r\n status: '\u6210\u529F',\r\n level: 'success',\r\n attention: 'high',\r\n },\r\n {\r\n key: 'screenshot_fail',\r\n method: 'screenshotFail',\r\n label: '\u622A\u56FE\u5931\u8D25',\r\n group: '\u622A\u56FE',\r\n step: '\u622A\u56FE',\r\n status: '\u5931\u8D25',\r\n level: 'warning',\r\n attention: 'high',\r\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\r\n },\r\n {\r\n key: 'share_start',\r\n method: 'shareStart',\r\n label: '\u5206\u4EAB\u94FE\u63A5\u5F00\u59CB',\r\n group: '\u5206\u4EAB',\r\n step: '\u5206\u4EAB\u94FE\u63A5',\r\n status: '\u5F00\u59CB',\r\n level: 'start',\r\n attention: 'low',\r\n },\r\n {\r\n key: 'share_progress',\r\n method: 'shareProgress',\r\n label: '\u5206\u4EAB\u94FE\u63A5\u6B65\u9AA4',\r\n group: '\u5206\u4EAB',\r\n step: '\u5206\u4EAB\u94FE\u63A5',\r\n status: '\u6B65\u9AA4',\r\n level: 'info',\r\n attention: 'low',\r\n buildDetails: (label) => [label ? `\u6B65\u9AA4=${label}` : ''],\r\n },\r\n {\r\n key: 'share_dom_hit',\r\n method: 'shareDomHit',\r\n label: '\u5206\u4EAB\u94FE\u63A5DOM\u547D\u4E2D',\r\n group: '\u5206\u4EAB',\r\n step: '\u5206\u4EAB\u94FE\u63A5',\r\n status: 'DOM\u547D\u4E2D',\r\n level: 'info',\r\n attention: 'low',\r\n buildDetails: (link, domSnapshot) => [\r\n link ? `\u94FE\u63A5=${link}` : '',\r\n domSnapshot ? `DOM=${normalizeSnippet(domSnapshot, 220)}` : ''\r\n ],\r\n },\r\n {\r\n key: 'share_source',\r\n method: 'shareSource',\r\n label: '\u5206\u4EAB\u94FE\u63A5\u6765\u6E90',\r\n group: '\u5206\u4EAB',\r\n step: '\u5206\u4EAB\u94FE\u63A5',\r\n status: '\u6765\u6E90',\r\n level: 'info',\r\n attention: 'low',\r\n buildDetails: (source, link, domSnapshot) => [\r\n source ? `\u6765\u6E90=${source}` : '',\r\n link ? `\u94FE\u63A5=${link}` : '',\r\n source === 'dom' && domSnapshot ? `DOM=${normalizeSnippet(domSnapshot, 220)}` : ''\r\n ],\r\n },\r\n {\r\n key: 'share_success',\r\n method: 'shareSuccess',\r\n label: '\u5206\u4EAB\u94FE\u63A5\u6210\u529F',\r\n group: '\u5206\u4EAB',\r\n step: '\u5206\u4EAB\u94FE\u63A5',\r\n status: '\u6210\u529F',\r\n level: 'success',\r\n attention: 'high',\r\n buildDetails: (link) => [link ? `\u94FE\u63A5=${link}` : ''],\r\n },\r\n {\r\n key: 'share_fail',\r\n method: 'shareFail',\r\n label: '\u5206\u4EAB\u94FE\u63A5\u5931\u8D25',\r\n group: '\u5206\u4EAB',\r\n step: '\u5206\u4EAB\u94FE\u63A5',\r\n status: '\u5931\u8D25',\r\n level: 'warning',\r\n attention: 'high',\r\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\r\n },\r\n {\r\n key: 'share_skip',\r\n method: 'shareSkip',\r\n label: '\u5206\u4EAB\u94FE\u63A5\u8DF3\u8FC7',\r\n group: '\u5206\u4EAB',\r\n step: '\u5206\u4EAB\u94FE\u63A5',\r\n status: '\u8DF3\u8FC7',\r\n level: 'warning',\r\n attention: 'medium',\r\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\r\n },\r\n {\r\n key: 'ai_search_card_detect_attempt',\r\n method: 'aiSearchCardDetectAttempt',\r\n label: 'AI Search \u5361\u7247\u8BC6\u522B\u5C1D\u8BD5',\r\n group: 'AI Search',\r\n step: 'AI Search \u5361\u7247\u8BC6\u522B',\r\n status: '\u5C1D\u8BD5',\r\n level: 'info',\r\n attention: 'low',\r\n buildDetails: (attempt = 1, maxAttempts = 1, url = '') => [\r\n `attempt=${attempt}/${maxAttempts}`,\r\n url ? `url=${url}` : '',\r\n ],\r\n },\r\n {\r\n key: 'ai_search_card_detect_success',\r\n method: 'aiSearchCardDetectSuccess',\r\n label: 'AI Search \u5361\u7247\u8BC6\u522B\u6210\u529F',\r\n group: 'AI Search',\r\n step: 'AI Search \u5361\u7247\u8BC6\u522B',\r\n status: '\u6210\u529F',\r\n level: 'success',\r\n attention: 'high',\r\n buildDetails: (cardType = '', attempts = 1, refreshCount = 0, url = '') => [\r\n cardType ? `cardType=${cardType}` : '',\r\n `attempts=${attempts}`,\r\n `refreshCount=${refreshCount}`,\r\n url ? `url=${url}` : '',\r\n ],\r\n },\r\n {\r\n key: 'ai_search_card_empty_result_success',\r\n method: 'aiSearchCardEmptyResultSuccess',\r\n label: 'AI Search \u7A7A\u7ED3\u679C\u6210\u529F',\r\n group: 'AI Search',\r\n step: 'AI Search \u7A7A\u7ED3\u679C',\r\n status: '\u6210\u529F',\r\n level: 'success',\r\n attention: 'high',\r\n buildDetails: (contentLeftTpls = [], targetTpls = [], url = '', attempts = 0, refreshCount = 0) => [\r\n Array.isArray(contentLeftTpls) ? `contentLeftTpls=${normalizeSnippet(contentLeftTpls.join(','), 200)}` : '',\r\n Array.isArray(targetTpls) ? `targetTpls=${normalizeSnippet(targetTpls.join(','), 200)}` : '',\r\n `attempts=${attempts}`,\r\n `refreshCount=${refreshCount}`,\r\n url ? `url=${url}` : '',\r\n ],\r\n },\r\n {\r\n key: 'data_push_success',\r\n method: 'dataPushSuccess',\r\n label: '\u6570\u636E\u63A8\u9001\u6210\u529F',\r\n group: '\u6570\u636E\u63A8\u9001',\r\n step: '\u6570\u636E\u63A8\u9001',\r\n status: '\u6210\u529F',\r\n level: 'success',\r\n attention: 'medium',\r\n buildDetails: (label) => [label ? `\u8BF4\u660E=${label}` : ''],\r\n },\r\n {\r\n key: 'data_push_fail',\r\n method: 'dataPushFail',\r\n label: '\u6570\u636E\u63A8\u9001\u5931\u8D25',\r\n group: '\u6570\u636E\u63A8\u9001',\r\n step: '\u6570\u636E\u63A8\u9001',\r\n status: '\u5931\u8D25',\r\n level: 'error',\r\n attention: 'high',\r\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\r\n },\r\n {\r\n key: 'popup_detected',\r\n method: 'popupDetected',\r\n label: '\u5F39\u7A97\u68C0\u6D4B',\r\n group: '\u5F39\u7A97',\r\n step: '\u5F39\u7A97\u5904\u7406',\r\n status: '\u68C0\u6D4B\u5230\u906E\u7F69',\r\n level: 'warning',\r\n attention: 'medium',\r\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\r\n },\r\n {\r\n key: 'popup_close_attempt',\r\n method: 'popupCloseAttempt',\r\n label: '\u5F39\u7A97\u5173\u95ED\u5C1D\u8BD5',\r\n group: '\u5F39\u7A97',\r\n step: '\u5F39\u7A97\u5904\u7406',\r\n status: '\u5C1D\u8BD5\u5173\u95ED',\r\n level: 'info',\r\n attention: 'low',\r\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\r\n },\r\n {\r\n key: 'popup_close_success',\r\n method: 'popupCloseSuccess',\r\n label: '\u5F39\u7A97\u5173\u95ED\u5B8C\u6210',\r\n group: '\u5F39\u7A97',\r\n step: '\u5F39\u7A97\u5904\u7406',\r\n status: '\u5173\u95ED\u5B8C\u6210',\r\n level: 'success',\r\n attention: 'medium',\r\n },\r\n {\r\n key: 'popup_close_fail',\r\n method: 'popupCloseFail',\r\n label: '\u5F39\u7A97\u5173\u95ED\u5931\u8D25',\r\n group: '\u5F39\u7A97',\r\n step: '\u5F39\u7A97\u5904\u7406',\r\n status: '\u5173\u95ED\u5931\u8D25',\r\n level: 'warning',\r\n attention: 'medium',\r\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\r\n },\r\n];\r\n\r\nexport const LOG_TEMPLATES = LOG_DEFINITIONS.map((definition) => {\r\n const attention = definition.attention || 'medium';\r\n const attentionRank = ATTENTION_RANK[attention] || ATTENTION_RANK.medium;\r\n const defaultSelected = attentionRank >= DEFAULT_ATTENTION_RANK;\r\n return {\r\n key: definition.key,\r\n label: definition.label,\r\n group: definition.group,\r\n attention,\r\n patterns: buildDefinitionPatterns(definition),\r\n defaultSelected,\r\n };\r\n});\r\n\r\nconst buildStepLine = (step, status, details = []) => {\r\n const parts = [];\r\n const decoratedStep = step ? decorateLabel(step, STEP_EMOJIS) : '';\r\n const base = decoratedStep ? `${STEP_PREFIX} ${decoratedStep}` : STEP_PREFIX;\r\n parts.push(base.trim());\r\n if (status) parts.push(decorateLabel(status, STATUS_EMOJIS));\r\n const detailParts = details.filter(Boolean);\r\n if (detailParts.length > 0) {\r\n parts.push(...detailParts);\r\n }\r\n return parts.join(STEP_SEPARATOR);\r\n};\r\n\r\nconst createThrottle = () => {\r\n const lastMap = new Map();\r\n return (key, intervalMs, fn) => {\r\n const now = Date.now();\r\n const last = lastMap.get(key) || 0;\r\n if (now - last >= intervalMs) {\r\n lastMap.set(key, now);\r\n fn();\r\n }\r\n };\r\n};\r\n\r\nexport const createTemplateLogger = (baseLogger = createBaseLogger()) => {\r\n const throttle = createThrottle();\r\n\r\n const info = (line) => baseLogger.info(line);\r\n const success = (line) => baseLogger.success(line);\r\n const warning = (line) => baseLogger.warning(line);\r\n const error = (line) => baseLogger.error(line);\r\n const debug = (line) => baseLogger.debug(line);\r\n const start = (line) => baseLogger.start(line);\r\n\r\n const stepInfo = (step, status, details = []) => info(buildStepLine(step, status, details));\r\n const stepSuccess = (step, status, details = []) => success(buildStepLine(step, status, details));\r\n const stepWarn = (step, status, details = []) => warning(buildStepLine(step, status, details));\r\n const stepError = (step, status, details = []) => error(buildStepLine(step, status, details));\r\n const stepStart = (step, status, details = []) => start(buildStepLine(step, status, details));\r\n\r\n const stepHandlers = {\r\n info: stepInfo,\r\n success: stepSuccess,\r\n warning: stepWarn,\r\n error: stepError,\r\n start: stepStart,\r\n };\r\n\r\n const logFromDefinition = (definition, details = []) => {\r\n const handler = stepHandlers[definition.level] || stepInfo;\r\n const payload = [...details, buildLogTag(definition.key)];\r\n const emit = () => handler(definition.step, definition.status, payload);\r\n if (definition.throttleMs) {\r\n throttle(definition.throttleKey || definition.key, definition.throttleMs, emit);\r\n return;\r\n }\r\n emit();\r\n };\r\n\r\n const definitionMethods = {};\r\n LOG_DEFINITIONS.forEach((definition) => {\r\n if (!definition.method) return;\r\n definitionMethods[definition.method] = (...args) => {\r\n const details = definition.buildDetails ? definition.buildDetails(...args) : [];\r\n logFromDefinition(definition, details);\r\n };\r\n });\r\n\r\n return {\r\n step: (step, status, details, level = 'info') => {\r\n if (level === 'error') return stepError(step, status, details);\r\n if (level === 'warn' || level === 'warning') return stepWarn(step, status, details);\r\n if (level === 'start') return stepStart(step, status, details);\r\n if (level === 'success') return stepSuccess(step, status, details);\r\n return stepInfo(step, status, details);\r\n },\r\n info: (message) => info(message),\r\n success: (message) => success(message),\r\n warning: (message) => warning(message),\r\n warn: (message) => warning(message),\r\n error: (message) => error(message),\r\n debug: (message) => debug(message),\r\n start: (message) => start(message),\r\n ...definitionMethods,\r\n };\r\n};\r\n\r\nconst getDefaultBaseLogger = () => createBaseLogger('');\r\n\r\nexport const Logger = {\r\n setLogger: (logger) => setDefaultLogger(logger),\r\n info: (message) => getDefaultBaseLogger().info(message),\r\n success: (message) => getDefaultBaseLogger().success(message),\r\n warning: (message) => getDefaultBaseLogger().warning(message),\r\n warn: (message) => getDefaultBaseLogger().warning(message),\r\n error: (message) => getDefaultBaseLogger().error(message),\r\n debug: (message) => getDefaultBaseLogger().debug(message),\r\n start: (message) => getDefaultBaseLogger().start(message),\r\n useTemplate: (logger) => {\r\n if (logger) return createTemplateLogger(createBaseLogger('', logger));\r\n return createTemplateLogger();\r\n },\r\n};\r\n", "import delay from 'delay';\r\nimport { Utils } from './utils.js';\r\nimport { Mutation } from './mutation.js';\r\nimport { createInternalLogger } from './internals/logger.js';\r\nimport { capturePageScreenshot } from './internals/screenshot.js';\r\n\r\nconst logger = createInternalLogger('Share');\r\n\r\nconst DEFAULT_TIMEOUT_MS = 50 * 1000;\r\nconst DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;\r\nconst DEFAULT_POLL_INTERVAL_MS = 120;\r\n\r\nconst normalizePrefix = (value) => value == null ? undefined : String(value).trim();\r\n\r\nconst toSnapshot = (value, maxLen) => {\r\n const text = String(value || '');\r\n if (!text) return '';\r\n return text.replace(/\\s+/g, ' ').trim().slice(0, maxLen);\r\n};\r\n\r\nconst toInline = (value, maxLen = 200) => {\r\n const text = String(value || '');\r\n if (!text) return '';\r\n return text.replace(/\\s+/g, ' ').trim().slice(0, maxLen);\r\n};\r\n\r\nconst toJsonInline = (value, maxLen = 260) => {\r\n try {\r\n return toInline(JSON.stringify(value), maxLen);\r\n } catch {\r\n return '[\u4E0D\u53EF\u5E8F\u5217\u5316]';\r\n }\r\n};\r\n\r\nconst normalizeXurl = (value) => {\r\n if (!Array.isArray(value)) return [];\r\n\r\n const normalizeMatcherList = (input) => {\r\n if (Array.isArray(input)) {\r\n return input\r\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\r\n .filter(Boolean);\r\n }\r\n\r\n const single = String(input || '').trim().replace(/\\.+$/, '');\r\n return single ? [single] : [];\r\n };\r\n\r\n const normalizeSegments = (input) => {\r\n if (Array.isArray(input)) {\r\n return input\r\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\r\n .filter(Boolean);\r\n }\r\n\r\n const raw = String(input || '').trim();\r\n if (!raw) return [];\r\n\r\n return raw\r\n .split('.')\r\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\r\n .filter(Boolean);\r\n };\r\n\r\n const normalized = [];\r\n\r\n const apiMatchers = normalizeMatcherList(value[0]);\r\n if (apiMatchers.length > 0) {\r\n normalized.push(apiMatchers);\r\n }\r\n\r\n const flattenedPath = [];\r\n const extraPaths = [];\r\n\r\n value.slice(1).forEach((item) => {\r\n if (Array.isArray(item)) {\r\n const segments = normalizeSegments(item);\r\n if (segments.length > 0) {\r\n extraPaths.push(segments);\r\n }\r\n return;\r\n }\r\n\r\n const segments = normalizeSegments(item);\r\n if (segments.length > 0) {\r\n flattenedPath.push(...segments);\r\n }\r\n });\r\n\r\n if (flattenedPath.length > 0) {\r\n normalized.push(flattenedPath);\r\n }\r\n\r\n if (extraPaths.length > 0) {\r\n normalized.push(...extraPaths);\r\n }\r\n\r\n return normalized;\r\n};\r\n\r\nconst normalizeShare = (share) => {\r\n const source = share && typeof share === 'object' ? share : {};\r\n const modeRaw = String(source.mode || 'dom').trim().toLowerCase();\r\n const mode = modeRaw === 'response' ? 'response' : 'dom';\r\n\r\n return {\r\n mode,\r\n prefix: normalizePrefix(source.prefix),\r\n xurl: normalizeXurl(source.xurl),\r\n };\r\n};\r\n\r\nconst getByPathSegments = (source, pathSegments) => {\r\n if (!Array.isArray(pathSegments) || pathSegments.length === 0) return undefined;\r\n\r\n let current = source;\r\n\r\n for (const rawSegment of pathSegments) {\r\n const segment = String(rawSegment || '').trim();\r\n if (!segment) return undefined;\r\n if (current == null) return undefined;\r\n\r\n if (Array.isArray(current) && /^\\d+$/.test(segment)) {\r\n current = current[Number(segment)];\r\n continue;\r\n }\r\n\r\n current = current[segment];\r\n }\r\n\r\n return current;\r\n};\r\n\r\nconst buildShareLink = (prefix, value) => {\n const raw = String(value || '').trim();\n if (!raw) return '';\n\n if (/^https?:\\/\\//i.test(raw)) {\n return raw;\r\n }\r\n\n const safePrefix = normalizePrefix(prefix);\n if (!safePrefix) return '';\n\n const valueNoSlash = raw.replace(/^\\/+/, '');\n\n if (/[?&=]$/.test(safePrefix)) {\n return `${safePrefix}${valueNoSlash}`;\n }\n\n const prefixNoSlash = safePrefix.replace(/\\/+$/, '');\n return `${prefixNoSlash}/${valueNoSlash}`;\n};\n\r\nconst parseJsonSafely = (text) => {\r\n const raw = String(text || '').trim();\r\n if (!raw) return null;\r\n\r\n try {\r\n return JSON.parse(raw);\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\nconst createDomShareMonitor = async (page, options = {}) => {\r\n const prefix = normalizePrefix(options.prefix);\r\n const selectors = options.selectors ?? 'html';\r\n const mode = options.mode ?? Mutation.Mode.All;\r\n const onMatch = typeof options.onMatch === 'function' ? options.onMatch : null;\r\n const onTelemetry = typeof options.onTelemetry === 'function' ? options.onTelemetry : null;\r\n\r\n let matched = false;\r\n\r\n logger.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);\r\n\r\n const monitor = await Mutation.useMonitor(page, selectors, {\r\n mode,\r\n onMutation: (context = {}) => {\r\n if (matched) return;\r\n\r\n const mutationCount = Number(context.mutationCount || 0);\r\n const mutationNodes = Array.isArray(context.mutationNodes) ? context.mutationNodes : [];\r\n const html = String(context.html || '');\r\n const text = String(context.text || '');\r\n const rawDom = `${html}\\n${text}`;\r\n\r\n if (onTelemetry) {\r\n onTelemetry({\r\n mutationCount,\r\n mutationNodesCount: mutationNodes.length,\r\n });\r\n }\r\n\r\n if (mutationCount <= 5 || mutationCount % 50 === 0) {\r\n logger.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);\r\n }\r\n\r\n const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];\r\n if (!candidate) return;\r\n\r\n matched = true;\r\n logger.success('captureLink.domHit', `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);\r\n\r\n if (onMatch) {\r\n onMatch({\r\n link: candidate,\r\n rawDom,\r\n mutationCount,\r\n html,\r\n text,\r\n mutationNodes,\r\n });\r\n }\r\n },\r\n });\r\n\r\n return {\r\n stop: async () => {\r\n const result = await monitor.stop();\r\n logger.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);\r\n return result;\r\n },\r\n };\r\n};\r\n\r\nexport const Share = {\r\n /**\r\n * \u6355\u83B7\u5206\u4EAB\u94FE\u63A5\uFF08\u5355\u6A21\u5F0F\uFF09\r\n * - mode='dom': \u4EC5 DOM \u76D1\u542C\r\n * - mode='response': \u4EC5\u63A5\u53E3\u76D1\u542C\r\n *\r\n * @param {import('playwright').Page} page\r\n * @param {Object} [options]\r\n * @param {{ mode?: 'dom' | 'response', prefix: string, xurl?: Array<string | string[]> }} options.share\r\n * @param {number} [options.timeoutMs=50000]\r\n * @param {number} [options.payloadSnapshotMaxLen=500]\r\n * @param {string | string[]} [options.domSelectors='html']\r\n * @param {'added' | 'changed' | 'all'} [options.domMode='all']\r\n * @param {() => Promise<void>} [options.performActions]\r\n * @returns {Promise<{ link: string | null; payloadText: string; payloadSnapshot: string; source: 'dom' | 'response' | 'none' }>}\r\n */\r\n async captureLink(page, options = {}) {\r\n const share = normalizeShare(options.share);\r\n const timeoutMs = Math.max(0, Number(options.timeoutMs ?? DEFAULT_TIMEOUT_MS) || 0);\r\n const payloadSnapshotMaxLen = options.payloadSnapshotMaxLen ?? DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN;\r\n const domSelectors = options.domSelectors ?? 'html';\r\n const domMode = options.domMode ?? Mutation.Mode.All;\r\n const performActions = typeof options.performActions === 'function' ? options.performActions : async () => { };\r\n\r\n if (share.prefix === undefined) {\r\n throw new Error('Share.captureLink requires options.share.prefix');\r\n }\r\n\r\n if (share.mode !== 'dom' && share.mode !== 'response') {\r\n throw new Error(`Share.captureLink unsupported share.mode: ${share.mode}`);\r\n }\r\n\r\n const apiMatchers = share.mode === 'response' ? (share.xurl[0] || []) : [];\r\n const fieldPaths = share.mode === 'response' ? share.xurl.slice(1) : [];\r\n\r\n if (share.mode === 'response' && apiMatchers.length === 0) {\r\n throw new Error('Share.captureLink requires share.xurl[0] api matcher when mode=response');\r\n }\r\n\r\n logger.start('captureLink', `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);\r\n logger.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);\r\n\r\n const stats = {\r\n actionTimedOut: false,\r\n domMutationCount: 0,\r\n domMutationNodes: 0,\r\n responseObserved: 0,\r\n responseMatched: 0,\r\n responseResolved: 0,\r\n lastMatchedUrl: '',\r\n responseSampleUrls: [],\r\n };\r\n\r\n const candidates = {\r\n dom: null,\r\n response: null,\r\n };\r\n\r\n const setCandidate = (source, link, payloadText = '') => {\r\n const safe = String(link || '').trim();\r\n if (!safe) return false;\r\n\r\n const [validated] = Utils.parseLinks(safe, { prefix: share.prefix }) || [];\r\n if (!validated) return false;\r\n\r\n if (candidates[source]?.link) return false;\r\n\r\n candidates[source] = {\r\n link: validated,\r\n payloadText: String(payloadText || ''),\r\n };\r\n\r\n logger.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);\r\n return true;\r\n };\r\n\r\n const resolveResponseCandidate = (responseText) => {\r\n const rawText = String(responseText || '');\r\n if (!rawText) return null;\r\n\r\n const [direct] = Utils.parseLinks(rawText, { prefix: share.prefix }) || [];\r\n if (direct) {\r\n return { link: direct, payloadText: rawText };\r\n }\r\n\r\n if (fieldPaths.length === 0) return null;\r\n\r\n const payload = parseJsonSafely(rawText);\r\n if (!payload || typeof payload !== 'object') return null;\r\n\r\n for (const pathSegments of fieldPaths) {\r\n const value = getByPathSegments(payload, pathSegments);\r\n if (value == null || value === '') continue;\r\n\r\n const composed = buildShareLink(share.prefix, value);\r\n if (!composed) continue;\r\n\r\n const [validated] = Utils.parseLinks(composed, { prefix: share.prefix }) || [];\r\n if (!validated) continue;\r\n\r\n return {\r\n link: validated,\r\n payloadText: rawText,\r\n };\r\n }\r\n\r\n return null;\r\n };\r\n\r\n let domMonitor = null;\r\n\r\n const stopDomMonitor = async () => {\r\n if (!domMonitor) return;\r\n const monitor = domMonitor;\r\n domMonitor = null;\r\n try {\r\n await monitor.stop();\r\n } catch (error) {\r\n logger.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);\r\n }\r\n };\r\n\r\n const onResponse = async (response) => {\r\n if (share.mode !== 'response') return;\r\n if (candidates.response?.link) return;\r\n\r\n stats.responseObserved += 1;\r\n\r\n try {\r\n const url = String(response.url() || '');\r\n\r\n if (url && stats.responseSampleUrls.length < 8 && !stats.responseSampleUrls.includes(url)) {\r\n stats.responseSampleUrls.push(url);\r\n }\r\n\r\n if (stats.responseObserved <= 5) {\r\n logger.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);\r\n }\r\n\r\n if (!apiMatchers.some((matcher) => url.includes(matcher))) return;\r\n\r\n stats.responseMatched += 1;\r\n stats.lastMatchedUrl = url;\r\n logger.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);\r\n\r\n const text = await response.text();\r\n const hit = resolveResponseCandidate(text);\r\n if (!hit?.link) {\r\n if (stats.responseMatched <= 3) {\r\n logger.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);\r\n }\r\n return;\r\n }\r\n\r\n stats.responseResolved += 1;\r\n logger.success('captureLink.responseHit', `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);\r\n setCandidate('response', hit.link, hit.payloadText);\r\n } catch (error) {\r\n logger.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);\r\n }\r\n };\r\n\r\n if (share.mode === 'dom') {\r\n logger.info('\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C');\r\n domMonitor = await createDomShareMonitor(page, {\r\n prefix: share.prefix,\r\n selectors: domSelectors,\r\n mode: domMode,\r\n onTelemetry: ({ mutationCount, mutationNodesCount }) => {\r\n stats.domMutationCount = mutationCount;\r\n stats.domMutationNodes = mutationNodesCount;\r\n },\r\n onMatch: ({ link, rawDom }) => {\r\n setCandidate('dom', link, rawDom);\r\n },\r\n });\r\n }\r\n\r\n if (share.mode === 'response') {\r\n logger.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);\r\n page.on('response', onResponse);\r\n }\r\n\r\n const deadline = Date.now() + timeoutMs;\r\n const getRemainingMs = () => Math.max(0, deadline - Date.now());\r\n\r\n try {\r\n const actionTimeout = getRemainingMs();\r\n logger.start('captureLink.performActions', `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);\r\n\r\n if (actionTimeout > 0) {\r\n let timer = null;\r\n let actionError = null;\r\n\r\n const actionPromise = Promise.resolve()\r\n .then(() => performActions())\r\n .then(() => '__ACTION_DONE__')\r\n .catch((error) => {\r\n actionError = error;\r\n return '__ACTION_ERROR__';\r\n });\r\n\r\n const timeoutPromise = new Promise((resolve) => {\r\n timer = setTimeout(() => resolve('__ACTION_TIMEOUT__'), actionTimeout);\r\n });\r\n\r\n const actionResult = await Promise.race([actionPromise, timeoutPromise]);\r\n if (timer) clearTimeout(timer);\r\n\r\n if (actionResult === '__ACTION_ERROR__') {\r\n logger.fail('captureLink.performActions', actionError);\r\n throw actionError;\r\n }\r\n\r\n if (actionResult === '__ACTION_TIMEOUT__') {\r\n stats.actionTimedOut = true;\r\n logger.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);\r\n } else {\r\n logger.success('captureLink.performActions', '\u6267\u884C\u52A8\u4F5C\u5B8C\u6210');\r\n }\r\n }\r\n\r\n let nextProgressLogTs = Date.now() + 3000;\r\n\r\n while (true) {\r\n const selected = share.mode === 'dom' ? candidates.dom : candidates.response;\r\n if (selected?.link) {\r\n logger.success('captureLink', `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);\r\n return {\r\n link: selected.link,\r\n payloadText: selected.payloadText,\r\n payloadSnapshot: toSnapshot(selected.payloadText, payloadSnapshotMaxLen),\r\n source: share.mode,\r\n };\r\n }\r\n\r\n const remaining = getRemainingMs();\r\n if (remaining <= 0) break;\r\n\r\n const now = Date.now();\r\n if (now >= nextProgressLogTs) {\r\n logger.info(\r\n `captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`\r\n );\r\n nextProgressLogTs = now + 5000;\r\n }\r\n\r\n await delay(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));\r\n }\r\n\r\n if (share.mode === 'response' && stats.responseMatched === 0) {\r\n logger.warning(\r\n `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`\r\n );\r\n }\r\n\r\n logger.warning(\r\n `captureLink \u8D85\u65F6\u672A\u62FF\u5230\u94FE\u63A5: mode=${share.mode}, actionTimedOut=${stats.actionTimedOut}, domMutationCount=${stats.domMutationCount}, responseObserved=${stats.responseObserved}, responseMatched=${stats.responseMatched}, lastMatchedUrl=${stats.lastMatchedUrl || 'none'}`\r\n );\r\n\r\n return {\r\n link: null,\r\n payloadText: '',\r\n payloadSnapshot: '',\r\n source: 'none',\r\n };\r\n } finally {\r\n if (share.mode === 'response') {\r\n page.off('response', onResponse);\r\n logger.info('response \u76D1\u542C\u5DF2\u5378\u8F7D');\r\n }\r\n await stopDomMonitor();\r\n }\r\n },\r\n\r\n\r\n /**\r\n * \u5168\u9875\u9762\u6EDA\u52A8\u622A\u56FE\uFF08\u57FA\u7840\u80FD\u529B\uFF09\r\n *\r\n * @param {import('playwright').Page} page\r\n * @param {Object} [options]\r\n * @param {number} [options.buffer]\r\n * @param {boolean} [options.restore]\r\n * @param {number} [options.maxHeight]\r\n * @returns {Promise<string>} base64 png\r\n */\r\n async captureScreen(page, options = {}) {\r\n const originalViewport = page.viewportSize();\r\n const defaultBuffer = Math.round((originalViewport?.height || 1080) / 2);\r\n const buffer = options.buffer ?? defaultBuffer;\r\n const restore = options.restore ?? false;\r\n const maxHeight = options.maxHeight ?? 8000;\r\n\r\n try {\r\n const maxScrollHeight = await page.evaluate(() => {\r\n let maxHeight = document.body.scrollHeight;\r\n\r\n document.querySelectorAll('*').forEach(el => {\r\n const style = window.getComputedStyle(el);\r\n const overflowY = style.overflowY;\r\n\r\n if ((overflowY === 'auto' || overflowY === 'scroll') &&\r\n el.scrollHeight > el.clientHeight) {\r\n if (el.scrollHeight > maxHeight) {\r\n maxHeight = el.scrollHeight;\r\n }\r\n\r\n el.dataset.pkOrigOverflow = el.style.overflow;\r\n el.dataset.pkOrigHeight = el.style.height;\r\n el.dataset.pkOrigMaxHeight = el.style.maxHeight;\r\n el.classList.add('__pk_expanded__');\r\n\r\n el.style.overflow = 'visible';\r\n el.style.height = 'auto';\r\n el.style.maxHeight = 'none';\r\n }\r\n });\r\n\r\n return maxHeight;\r\n });\r\n\r\n const targetHeight = Math.min(maxScrollHeight + buffer, maxHeight);\r\n\r\n await page.setViewportSize({\r\n width: originalViewport?.width || 1280,\r\n height: targetHeight,\r\n });\r\n\r\n await delay(1000);\r\n const buffer_ = await capturePageScreenshot(page, {\r\n fullPage: true,\r\n type: 'png',\r\n maxClipHeight: targetHeight,\r\n });\r\n\r\n return buffer_.toString('base64');\r\n } finally {\r\n if (restore) {\r\n await page.evaluate(() => {\r\n document.querySelectorAll('.__pk_expanded__').forEach(el => {\r\n el.style.overflow = el.dataset.pkOrigOverflow || '';\r\n el.style.height = el.dataset.pkOrigHeight || '';\r\n el.style.maxHeight = el.dataset.pkOrigMaxHeight || '';\r\n\r\n delete el.dataset.pkOrigOverflow;\r\n delete el.dataset.pkOrigHeight;\r\n delete el.dataset.pkOrigMaxHeight;\r\n el.classList.remove('__pk_expanded__');\r\n });\r\n });\r\n\r\n if (originalViewport) {\r\n await page.setViewportSize(originalViewport);\r\n }\r\n }\r\n }\r\n },\r\n};\r\n"],
4
+ "sourcesContent": ["import { log as crawleeLog } from 'crawlee';\nimport { ApifyKit } from '../src/apify-kit';\nimport { Utils } from '../src/utils';\nimport { AntiCheat } from '../src/anti-cheat';\nimport { Humanize } from '../src/humanize';\nimport { Launch } from '../src/launch';\nimport { LiveView } from '../src/live-view';\nimport { Captcha } from '../src/captcha-monitor';\nimport { Mutation } from '../src/mutation';\nimport { Display } from '../src/display.js';\nimport * as Constants from '../src/constants';\nimport * as Errors from '../src/errors';\nimport { Logger, LOG_TEMPLATES, stripAnsi } from '../src/logger';\nimport { Share } from '../src/share';\nimport { ByPass } from '../src/proxy-bypass';\nimport { RuntimeEnv } from '../src/runtime-env.js';\n\n// \u4FEE\u6539\u9ED8\u8BA4logger \u4ECEconsole.log \u5230 crawleeLog\nLogger.setLogger(crawleeLog);\n\n// Unified Entry Point\nexport const usePlaywrightToolKit = () => {\n return {\n ApifyKit,\n AntiCheat,\n Humanize,\n Launch,\n LiveView,\n Constants,\n Utils,\n RuntimeEnv,\n Captcha,\n Errors,\n Mutation,\n Display,\n Logger,\n Share,\n ByPass,\n $Internals: { LOG_TEMPLATES, stripAnsi }\n };\n};\n", "export const Code = {\n Success: 0,\n UnknownError: -1,\n NotLogin: 30000001,\n Chaptcha: 30000002,\n Timeout: 30000003,\n InitialTimeout: 30000004,\n OverallTimeout: 30000005,\n}\n\nexport const Status = {\n Success: 'SUCCESS',\n Failed: 'FAILED'\n}\n\nexport const PresetOfLiveViewKey = 'LIVE_VIEW_SCREENSHOT';\n\n\nconst createActorInfo = (info) => {\n const normalizeDomain = (value) => {\n if (!value) return '';\n return String(value).trim().replace(/^https?:\\/\\//, '').replace(/\\/.*$/, '');\n };\n\n const normalizePath = (value) => {\n if (!value) return '/';\n const raw = String(value).trim();\n if (!raw) return '/';\n return raw.startsWith('/') ? raw : `/${raw}`;\n };\n\n const normalizeShare = (value) => {\n const raw = value && typeof value === 'object' ? value : {};\n\n const modeRaw = String(raw.mode || 'dom').trim().toLowerCase();\n const mode = modeRaw === 'response' ? 'response' : 'dom';\n\n const prefix = String(raw.prefix || '').trim();\n\n const rawXurl = Array.isArray(raw.xurl)\n ? raw.xurl\n : [];\n\n const normalizeMatcherList = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const single = String(input || '').trim().replace(/\\.+$/, '');\n return single ? [single] : [];\n };\n\n const normalizeSegments = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const rawPath = String(input || '').trim();\n if (!rawPath) return [];\n\n return rawPath\n .split('.')\n .map((segment) => String(segment || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n };\n\n const xurl = [];\n\n const matcherList = normalizeMatcherList(rawXurl[0]);\n if (matcherList.length > 0) {\n xurl.push(matcherList);\n }\n\n const flatPath = [];\n const extraPaths = [];\n\n rawXurl.slice(1).forEach((item) => {\n if (Array.isArray(item)) {\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n extraPaths.push(segments);\n }\n return;\n }\n\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n flatPath.push(...segments);\n }\n });\n\n if (flatPath.length > 0) {\n xurl.push(flatPath);\n }\n\n if (extraPaths.length > 0) {\n xurl.push(...extraPaths);\n }\n\n return {\n mode,\n prefix,\n xurl,\n };\n };\n\n const buildLandingUrl = ({ protocol, domain, path }) => {\n const safeProtocol = String(protocol).trim();\n const safeDomain = normalizeDomain(domain);\n const safePath = normalizePath(path);\n return `${safeProtocol}://${safeDomain}${safePath}`;\n };\n\n const buildIcon = ({ key }) => {\n return `https://heartbitai.com/general/actors/${key}.png`;\n }\n\n\n const protocol = info.protocol || 'https';\n const domain = normalizeDomain(info.domain);\n const path = normalizePath(info.path);\n const share = normalizeShare(info.share);\n\n return {\n ...info,\n protocol,\n domain,\n path,\n share,\n get icon() {\n if (info.icon) return info.icon;\n return buildIcon(this);\n },\n get landingUrl() {\n return buildLandingUrl(this);\n },\n };\n};\n\nexport const ActorInfo = {\n qbot: createActorInfo({\n key: 'qbot',\n name: 'QQ\u6D4F\u89C8\u5668AI\u641C',\n domain: 'sogou.com',\n path: '/web',\n share: {\n mode: 'dom',\n prefix: '',\n xurl: [],\n },\n }),\n douyin: createActorInfo({\n key: 'douyin',\n name: '\u6296\u97F3AI\u641C',\n domain: 'so.douyin.com',\n path: '/',\n share: {\n mode: 'dom',\n prefix: '',\n xurl: [\n ],\n },\n }),\n lingguang: createActorInfo({\n key: 'lingguang',\n name: '\u7075\u5149',\n domain: 'www.lingguang.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://www.lingguang.com/share/',\n xurl: [\n '/chat/shareChat.json',\n 'result',\n ],\n },\n }),\n doubao: createActorInfo({\n key: 'doubao',\n name: '\u8C46\u5305',\n domain: 'www.doubao.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://www.doubao.com/thread/',\n xurl: [\n '/samantha/thread/share/save',\n 'data', 'share_id',\n ],\n },\n }),\n deepseek: createActorInfo({\n key: 'deepseek',\n name: 'DeepSeek',\n domain: 'chat.deepseek.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://chat.deepseek.com/share/',\n xurl: [\n '/api/v0/share/create',\n 'data', 'biz_data', 'share_id',\n ],\n },\n }),\n erine: createActorInfo({\n key: 'erine',\n name: '\u6587\u5FC3\u4E00\u8A00',\n domain: 'yiyan.baidu.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://yiyan.baidu.com/share/',\n xurl: [\n '/eb/share/key/gen',\n 'data', 'key',\n ],\n },\n }),\n wenxin: createActorInfo({\n key: 'wenxin',\n name: '\u6587\u5FC3\u52A9\u624B',\n domain: 'chat.baidu.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: '',\n xurl: [\n '/aichat/api/shortURL',\n 'data', 'short_url',\n ],\n },\n }),\n baidu: createActorInfo({\n key: 'baidu',\n name: '\u767E\u5EA6AI\u641C',\n domain: 'www.baidu.com',\n path: '/s',\n share: {\n mode: 'response',\n prefix: '',\n xurl: [\n '/aichat/api/shortURL',\n 'data', 'short_url',\n ],\n },\n }),\n yuanbao: createActorInfo({\n key: 'yuanbao',\n name: '\u5143\u5B9D',\n domain: 'yuanbao.tencent.com',\n path: '/chat/',\n share: {\n mode: 'response',\n prefix: 'https://yb.tencent.com/s/',\n xurl: [\n '/api/conversations/v2/share', 'shareId',\n ],\n },\n }),\n kimi: createActorInfo({\n key: 'kimi',\n name: 'Kimi',\n domain: 'www.kimi.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://www.kimi.com/share/',\n xurl: [\n '/kimi.gateway.chat.v1.ChatService/CreateChatShare', 'share', 'id'\n ],\n },\n }),\n qwen: createActorInfo({\n key: 'qwen',\n name: '\u901A\u4E49\u5343\u95EE',\n domain: 'www.qianwen.com',\n path: '/chat',\n share: {\n mode: 'response',\n prefix: 'https://www.qianwen.com/share/chat/',\n xurl: [\n '/api/v1/share/create', 'data', 'share_id'\n ],\n },\n }),\n nano: createActorInfo({\n key: 'nano',\n name: '\u7EB3\u7C73',\n domain: 'www.n.cn',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://www.n.cn/share/mcp?id=',\n xurl: [\n '/api/share/gen', 'data', 'id'\n ],\n },\n }),\n}\n", "\n// =============================================================================\n// Core Helpers & State\n// =============================================================================\n\nconst pad = (value, size = 2) => String(value).padStart(size, '0');\n\nconst FORCED_TIMEZONE_OFFSET_MINUTES = -8 * 60;\n\nconst formatTimestamp = (date = new Date()) => {\n const source = date instanceof Date ? date : new Date(date);\n const forcedDate = new Date(source.getTime() - (FORCED_TIMEZONE_OFFSET_MINUTES * 60 * 1000));\n\n const year = forcedDate.getUTCFullYear();\n const month = pad(forcedDate.getUTCMonth() + 1);\n const day = pad(forcedDate.getUTCDate());\n const hours = pad(forcedDate.getUTCHours());\n const minutes = pad(forcedDate.getUTCMinutes());\n const seconds = pad(forcedDate.getUTCSeconds());\n const millis = pad(forcedDate.getUTCMilliseconds(), 3);\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${millis}`;\n};\n\nconst formatLine = (prefix, icon, message) => {\n const parts = [];\n if (prefix) parts.push(`[${prefix}]`);\n if (icon) parts.push(icon);\n if (message) parts.push(message);\n return parts.join(' ').trim();\n};\n\nconst fallbackLog = {\n info: (...args) => console.log(...args),\n warning: (...args) => (console.warn ? console.warn(...args) : console.log(...args)),\n error: (...args) => console.error(...args),\n debug: (...args) => (console.debug ? console.debug(...args) : console.log(...args)),\n};\n\nconst resolveLogMethod = (logger, name) => {\n if (logger && typeof logger[name] === 'function') {\n return logger[name].bind(logger);\n }\n if (name === 'warning' && logger && typeof logger.warn === 'function') {\n return logger.warn.bind(logger);\n }\n return fallbackLog[name];\n};\n\nlet defaultLogger = null;\n\nexport const setDefaultLogger = (logger) => {\n defaultLogger = logger;\n};\n\n// Lazy resolver: always checks current state\nconst resolveLogger = (explicitLogger) => {\n if (explicitLogger && typeof explicitLogger.info === 'function') {\n return explicitLogger;\n }\n if (defaultLogger && typeof defaultLogger.info === 'function') {\n return defaultLogger;\n }\n return fallbackLog;\n};\n\nconst ANSI = {\n reset: '\\x1b[0m',\n gray: '\\x1b[90m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n};\n\nconst colorize = (text, color) => {\n if (!text || !color) return text;\n return `${color}${text}${ANSI.reset}`;\n};\n\nexport const createBaseLogger = (prefix = '', explicitLogger) => {\n const name = prefix ? String(prefix) : '';\n\n const dispatch = (methodName, icon, message, color) => {\n const logger = resolveLogger(explicitLogger);\n const logFn = resolveLogMethod(logger, methodName);\n const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);\n const line = formatLine(name, icon, message);\n const coloredLine = colorize(line, color);\n logFn(`${timestamp} ${coloredLine}`.trim());\n };\n\n return {\n info: (message) => dispatch('info', '\uD83D\uDCD6', message, ANSI.cyan),\n success: (message) => dispatch('info', '\u2705', message, ANSI.green),\n warning: (message) => dispatch('warning', '\u26A0\uFE0F', message, ANSI.yellow),\n warn: (message) => dispatch('warning', '\u26A0\uFE0F', message, ANSI.yellow),\n error: (message) => dispatch('error', '\u274C', message, ANSI.red),\n debug: (message) => dispatch('debug', '\uD83D\uDD39', message, ANSI.gray),\n start: (message) => dispatch('info', '\uD83D\uDD37', message, ANSI.blue),\n };\n};\n\n/**\n * \u521B\u5EFA\u6A21\u5757\u7EA7\u65E5\u5FD7\u5668\n * @param {string} moduleName - \u6A21\u5757\u540D\u79F0\n * @param {object} [logger] - \u53EF\u9009\u7684\u663E\u5F0F\u65E5\u5FD7\u5668\uFF0C\u901A\u5E38\u4E0D\u9700\u8981\u4F20\uFF0C\u4F1A\u81EA\u52A8\u4F7F\u7528 setDefaultLogger \u8BBE\u7F6E\u7684\u5168\u5C40\u65E5\u5FD7\u5668\n */\nexport function createInternalLogger(moduleName, explicitLogger) {\n const baseLogger = createBaseLogger(moduleName, explicitLogger);\n\n return {\n start(methodName, params = '') {\n const paramStr = params ? ` (${params})` : '';\n baseLogger.start(`${methodName} \u5F00\u59CB${paramStr}`);\n },\n success(methodName, result = '') {\n const resultStr = result ? ` (${result})` : '';\n baseLogger.success(`${methodName} \u5B8C\u6210${resultStr}`);\n },\n fail(methodName, error) {\n const message = error instanceof Error ? error.message : error;\n baseLogger.error(`${methodName} \u5931\u8D25: ${message}`);\n },\n debug(message) {\n baseLogger.debug(message);\n },\n warn(message) {\n baseLogger.warning(message);\n },\n warning(message) {\n baseLogger.warning(message);\n },\n info(message) {\n baseLogger.info(message);\n }\n };\n}\n", "import { createInternalLogger } from './logger.js';\n\nconst logger = createInternalLogger('Screenshot');\n\nconst DEFAULT_TIMEOUT_MS = 5000;\nconst FORCED_FULLPAGE_TYPE = 'jpeg';\nconst FORCED_FULLPAGE_QUALITY = 50;\nconst SUPPORTED_TYPES = new Set(['png', 'jpeg', 'webp']);\n\nconst toPositiveNumber = (value, fallback = 0) => {\n const n = Number(value);\n if (!Number.isFinite(n) || n <= 0) return fallback;\n return n;\n};\n\nconst normalizeType = (value) => {\n const raw = String(value || 'png').trim().toLowerCase();\n if (!SUPPORTED_TYPES.has(raw)) return 'png';\n return raw;\n};\n\nconst normalizeQuality = (value, type) => {\n if (type !== 'jpeg' && type !== 'webp') return undefined;\n const n = Number(value);\n if (!Number.isFinite(n)) return undefined;\n const rounded = Math.round(n);\n if (rounded < 0 || rounded > 100) return undefined;\n return rounded;\n};\n\nconst buildFullPageClip = (metrics, viewport, maxClipHeight) => {\n const contentSize = metrics && typeof metrics === 'object'\n ? metrics.contentSize || null\n : null;\n\n const width = Math.max(1, Math.ceil(contentSize?.width || viewport.width || 1));\n let height = Math.max(1, Math.ceil(contentSize?.height || viewport.height || 1));\n\n if (maxClipHeight > 0) {\n height = Math.min(height, maxClipHeight);\n }\n\n return {\n x: 0,\n y: 0,\n width,\n height,\n scale: 1,\n };\n};\n\nexport const capturePageScreenshot = async (page, options = {}) => {\n const fullPage = Boolean(options.fullPage);\n const type = fullPage ? FORCED_FULLPAGE_TYPE : normalizeType(options.type);\n const quality = fullPage\n ? FORCED_FULLPAGE_QUALITY\n : normalizeQuality(options.quality, type);\n const timeout = toPositiveNumber(options.timeout, DEFAULT_TIMEOUT_MS);\n const maxClipHeight = Math.round(toPositiveNumber(options.maxClipHeight, 0));\n\n const fallbackOptions = {\n type: type === 'webp' ? 'png' : type,\n fullPage,\n };\n if (quality !== undefined && fallbackOptions.type === 'jpeg') {\n fallbackOptions.quality = quality;\n }\n if (timeout > 0) {\n fallbackOptions.timeout = timeout;\n }\n\n try {\n const context = page && typeof page.context === 'function' ? page.context() : null;\n if (!context || typeof context.newCDPSession !== 'function') {\n throw new Error('CDP session is not available');\n }\n\n const session = await context.newCDPSession(page);\n try {\n const metrics = await session.send('Page.getLayoutMetrics');\n const viewport = page.viewportSize() || { width: 1280, height: 720 };\n\n const captureParams = {\n format: type,\n fromSurface: true,\n captureBeyondViewport: fullPage,\n optimizeForSpeed: true,\n };\n\n if (quality !== undefined) {\n captureParams.quality = quality;\n }\n\n if (fullPage) {\n captureParams.clip = buildFullPageClip(metrics, viewport, maxClipHeight);\n }\n\n const result = await session.send('Page.captureScreenshot', captureParams);\n if (!result || typeof result.data !== 'string' || !result.data) {\n throw new Error('CDP returned empty screenshot data');\n }\n\n return Buffer.from(result.data, 'base64');\n } finally {\n if (typeof session.detach === 'function') {\n await session.detach().catch(() => { });\n }\n }\n } catch (error) {\n logger.warning(`CDP \u622A\u56FE\u5931\u8D25\uFF0C\u56DE\u9000 page.screenshot: ${error?.message || error}`);\n return await page.screenshot(fallbackOptions);\n }\n};\n", "/**\n * \u722C\u866B\u81EA\u5B9A\u4E49\u9519\u8BEF\u7C7B\n * \u7528\u4E8E\u643A\u5E26\u4E0A\u4E0B\u6587\u4FE1\u606F\uFF0C\u5728 pushFailed \u65F6\u81EA\u52A8\u89E3\u6790\n */\n\nimport { serializeError } from \"serialize-error\";\nimport { Code } from \"./constants\";\n\n/**\n * CrawlerError - \u81EA\u5B9A\u4E49\u722C\u866B\u9519\u8BEF\u7C7B\n * \n * @example\n * // \u7B80\u5355\u7528\u6CD5 (\u53EA\u6709 message)\n * throw new CrawlerError('\u672A\u6355\u83B7 Feed \u63A5\u53E3\u54CD\u5E94');\n * \n * @example\n * // \u5B8C\u6574\u7528\u6CD5 (\u5E26 code \u548C context)\n * throw new CrawlerError({\n * message: '\u767B\u5F55\u5931\u8D25',\n * code: ErrorKeygen.NotLogin,\n * context: { url: currentUrl, userId: '123' }\n * });\n */\nexport class CrawlerError extends Error {\n /**\n * @param {string|Object} info - \u9519\u8BEF\u4FE1\u606F\u5B57\u7B26\u4E32\u6216\u914D\u7F6E\u5BF9\u8C61\n * @param {string} info.message - \u9519\u8BEF\u4FE1\u606F\n * @param {number} [info.code] - ErrorKeygen \u679A\u4E3E\u503C\uFF08\u7528\u4E8E\u9519\u8BEF\u5206\u7C7B\uFF09\n * @param {Object} [info.context] - \u4E0A\u4E0B\u6587\u4FE1\u606F\u5BF9\u8C61\n */\n constructor(info) {\n // \u517C\u5BB9 string\n if (typeof info === 'string') {\n info = { message: info };\n }\n\n // \u26A0\uFE0F super() \u5FC5\u987B\u5728\u8BBF\u95EE this \u4E4B\u524D\u8C03\u7528\n super(info.message);\n\n this.name = 'CrawlerError';\n this.code = info.code ?? Code.UnknownError;\n this.context = info.context ?? {};\n this.timestamp = new Date().toISOString();\n\n // \u7EF4\u62A4\u6B63\u786E\u7684\u5806\u6808\u8DDF\u8E2A\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, CrawlerError);\n }\n }\n\n /**\n * \u8F6C\u6362\u4E3A\u53EF\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\n * @returns {Object}\n */\n toJSON() {\n return serializeError(this)\n }\n\n /**\n * \u68C0\u67E5\u4E00\u4E2A error \u662F\u5426\u662F CrawlerError\n * @param {Error} error\n * @returns {boolean}\n */\n static isCrawlerError(error) {\n return error instanceof CrawlerError || error?.name === 'CrawlerError';\n }\n\n /**\n * \u4ECE\u666E\u901A Error \u521B\u5EFA CrawlerError\n * @param {Error} error - \u539F\u59CB\u9519\u8BEF\n * @param {Object} [options={}] - \u9009\u9879\u5BF9\u8C61 (\u5305\u542B code \u548C context)\n * @returns {CrawlerError}\n */\n static from(error, options = {}) {\n const crawlerError = new CrawlerError({\n message: error.message,\n ...options\n });\n crawlerError.stack = error.stack;\n return crawlerError;\n }\n}\n\n\n", "import { Status, Code } from './constants';\nimport { createInternalLogger } from './internals/logger';\nimport { capturePageScreenshot } from './internals/screenshot';\nimport { CrawlerError } from './errors';\nimport { serializeError } from 'serialize-error';\nimport { ProxyMeterRuntime } from './internals/proxy-meter-runtime';\nimport { RuntimeEnv } from './runtime-env';\n\nconst logger = createInternalLogger('ApifyKit');\n\nconst resolveRuntimeContext = (input) => {\n const rememberedState = RuntimeEnv.peekRememberedState();\n const state = rememberedState || RuntimeEnv.parseInput(input || {});\n const envPatch = RuntimeEnv.buildEnvPatch(state) || null;\n\n return {\n actor: state.actor,\n runtime: state.runtime,\n envPatch,\n };\n};\n\nconst isPageLike = (value) => {\n if (!value || typeof value !== 'object') return false;\n return typeof value.evaluate === 'function' && typeof value.context === 'function';\n};\n\nconst pickPage = (...candidates) => {\n for (const candidate of candidates) {\n if (isPageLike(candidate)) {\n return candidate;\n }\n }\n return null;\n};\n\nconst toSerializable = (value, depth = 0, seen = new WeakSet()) => {\n if (depth > 6) return '[MaxDepth]';\n if (value == null) return value;\n\n const valueType = typeof value;\n if (valueType === 'string' || valueType === 'number' || valueType === 'boolean') {\n return value;\n }\n if (valueType === 'bigint') {\n return value.toString();\n }\n if (valueType === 'function' || valueType === 'symbol') {\n return undefined;\n }\n if (value instanceof Error) {\n return serializeError(value);\n }\n if (Array.isArray(value)) {\n return value\n .map((item) => toSerializable(item, depth + 1, seen))\n .filter((item) => item !== undefined);\n }\n if (valueType !== 'object') {\n return String(value);\n }\n\n if (seen.has(value)) {\n return '[Circular]';\n }\n seen.add(value);\n\n const ctorName = String(value?.constructor?.name || '');\n if (\n ctorName === 'Page' ||\n ctorName === 'BrowserContext' ||\n ctorName === 'Browser' ||\n ctorName === 'Frame' ||\n ctorName === 'ElementHandle' ||\n ctorName === 'JSHandle'\n ) {\n return `[${ctorName}]`;\n }\n\n const output = {};\n Object.entries(value).forEach(([key, item]) => {\n const safeValue = toSerializable(item, depth + 1, seen);\n if (safeValue !== undefined) {\n output[key] = safeValue;\n }\n });\n return output;\n};\n\nconst sanitizeMeta = (meta) => {\n if (!meta || typeof meta !== 'object' || Array.isArray(meta)) {\n return {};\n }\n const result = toSerializable(meta) || {};\n if (result && typeof result === 'object' && !Array.isArray(result)) {\n delete result.page;\n }\n return result;\n};\n\nconst captureAutoEnvPatch = async (page, runtimeContext) => {\n const currentPage = pickPage(page);\n if (!currentPage) return null;\n try {\n return await RuntimeEnv.captureEnvPatch(\n currentPage,\n {\n actor: runtimeContext.actor,\n runtime: runtimeContext.runtime,\n },\n { actor: runtimeContext.actor },\n );\n } catch (error) {\n logger.warn(`\u81EA\u52A8\u91C7\u96C6 env_patch \u5931\u8D25: ${error?.message || error}`);\n return null;\n }\n};\n\n/**\n * \u521B\u5EFA ApifyKit \u5B9E\u4F8B\n * \u5982\u679C apify \u53EF\u7528\uFF0C\u8FD4\u56DE\u5B8C\u6574\u529F\u80FD\u7684 ApifyKit\n * \u5982\u679C apify \u4E0D\u53EF\u7528\uFF0C\u8FD4\u56DE\u964D\u7EA7\u7248\u672C\uFF08\u975E apify \u76F8\u5173\u529F\u80FD\u4ECD\u53EF\u7528\uFF09\n */\nasync function createApifyKit() {\n let apify = null;\n\n // \u5C1D\u8BD5\u52A0\u8F7D apify\n try {\n apify = await import('apify');\n } catch (error) {\n // apify \u4E0D\u53EF\u7528\uFF0C\u5C06\u4F7F\u7528\u964D\u7EA7\u7248\u672C\n throw new Error('\u26A0\uFE0F apify \u5E93\u672A\u5B89\u88C5\uFF0CApifyKit \u7684 Actor \u76F8\u5173\u529F\u80FD\u4E0D\u53EF\u7528')\n }\n\n const { Actor } = apify;\n const actorInput = (await Actor.getInput()) || {};\n let lastPage = null;\n const getRuntimeContext = () => resolveRuntimeContext(actorInput);\n\n return {\n /**\n * \u6838\u5FC3\u5C01\u88C5\uFF1A\u6267\u884C\u6B65\u9AA4\uFF0C\u5E26\u81EA\u52A8\u65E5\u5FD7\u786E\u8BA4\u3001\u5931\u8D25\u622A\u56FE\u5904\u7406\u548C\u91CD\u8BD5\u673A\u5236\n * \n * @param {string} step - \u6B65\u9AA4\u540D\u79F0\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {Function} actionFn - \u6267\u884C\u7684\u5F02\u6B65\u64CD\u4F5C\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {boolean} [options.failActor=true] - \u5931\u8D25\u65F6\u662F\u5426\u8C03\u7528 Actor.fail\n * @param {Object} [options.retry] - \u91CD\u8BD5\u914D\u7F6E\n * @param {number} [options.retry.times=0] - \u91CD\u8BD5\u6B21\u6570\n * @param {'direct'|'refresh'} [options.retry.mode='direct'] - \u91CD\u8BD5\u6A21\u5F0F\n * @param {Function} [options.retry.before] - \u91CD\u8BD5\u524D\u94A9\u5B50\uFF0C\u53EF\u8986\u76D6\u9ED8\u8BA4\u7B49\u5F85\u884C\u4E3A\n */\n async runStep(step, page, actionFn, options = {}) {\n if (isPageLike(page)) {\n lastPage = page;\n }\n const { failActor = true, retry = {} } = options;\n const { times: retryTimes = 0, mode: retryMode = 'direct', before: beforeRetry } = retry;\n\n // \u5185\u90E8\u6267\u884C\u51FD\u6570\n const executeAction = async (attemptNumber) => {\n const attemptLabel = attemptNumber > 0 ? ` (\u91CD\u8BD5 #${attemptNumber})` : '';\n logger.start(`[Step] ${step}${attemptLabel}`);\n\n try {\n const result = await actionFn();\n logger.success(`[Step] ${step}${attemptLabel}`);\n return { success: true, result };\n } catch (error) {\n logger.fail(`[Step] ${step}${attemptLabel}`, error);\n return { success: false, error };\n }\n };\n\n // \u91CD\u8BD5\u524D\u7684\u51C6\u5907\u64CD\u4F5C\n const prepareForRetry = async (attemptNumber) => {\n if (typeof beforeRetry === 'function') {\n // \u4F7F\u7528\u81EA\u5B9A\u4E49\u94A9\u5B50\n logger.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\n await beforeRetry(page, attemptNumber);\n logger.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);\n } else if (retryMode === 'refresh') {\n // \u5237\u65B0\u6A21\u5F0F\uFF1A\u5237\u65B0\u9875\u9762\u5E76\u7B49\u5F85\u5BFC\u822A commit\uFF0C\u540E\u7EED\u6B65\u9AA4\u81EA\u884C\u505A\u4EA4\u4E92\u5C31\u7EEA\u68C0\u67E5\n logger.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\n await page.reload({ waitUntil: 'commit' });\n logger.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);\n } else {\n // direct \u6A21\u5F0F\uFF1A\u9ED8\u8BA4\u7B49\u5F85 3 \u79D2\n logger.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\n await new Promise(resolve => setTimeout(resolve, 3000));\n logger.success(`[RetryStep] \u7B49\u5F85\u5B8C\u6210`);\n }\n };\n\n // \u9996\u6B21\u6267\u884C\n let lastResult = await executeAction(0);\n\n // \u5982\u679C\u9996\u6B21\u6210\u529F\uFF0C\u76F4\u63A5\u8FD4\u56DE\n if (lastResult.success) {\n return lastResult.result;\n }\n\n // \u91CD\u8BD5\u903B\u8F91\n for (let attempt = 1; attempt <= retryTimes; attempt++) {\n logger.start(`[RetryStep] \u51C6\u5907\u7B2C ${attempt}/${retryTimes} \u6B21\u91CD\u8BD5: ${step}`);\n\n try {\n await prepareForRetry(attempt);\n } catch (prepareError) {\n logger.warn(`[RetryStep] \u91CD\u8BD5\u51C6\u5907\u5931\u8D25: ${prepareError.message}`);\n // \u51C6\u5907\u5931\u8D25\uFF0C\u7EE7\u7EED\u5C1D\u8BD5\u4E0B\u4E00\u6B21\u91CD\u8BD5\n continue;\n }\n\n lastResult = await executeAction(attempt);\n if (lastResult.success) {\n return lastResult.result;\n }\n }\n\n // \u6240\u6709\u91CD\u8BD5\u90FD\u5931\u8D25\uFF0C\u5904\u7406\u6700\u7EC8\u9519\u8BEF\n const finalError = lastResult.error;\n if (failActor) {\n let base64 = '\u622A\u56FE\u5931\u8D25';\n try {\n if (page) {\n const buffer = await capturePageScreenshot(page, {\n fullPage: true,\n type: 'jpeg',\n quality: 60,\n });\n base64 = `data:image/jpeg;base64,${buffer.toString('base64')}`;\n }\n } catch (snapErr) {\n logger.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);\n }\n\n await this.pushFailed(\n finalError,\n {\n step,\n base64,\n retryAttempts: retryTimes,\n },\n {\n page,\n options,\n },\n );\n await Actor.fail(`Run Step ${step} \u5931\u8D25 (\u5DF2\u91CD\u8BD5 ${retryTimes} \u6B21): ${finalError.message}`);\n } else {\n throw finalError;\n }\n },\n\n /**\n * \u5BBD\u677E\u7248runStep\uFF1A\u5931\u8D25\u65F6\u4E0D\u8C03\u7528Actor.fail\uFF0C\u53EA\u629B\u51FA\u5F02\u5E38\n * \u652F\u6301\u900F\u4F20 retry \u7B49\u9009\u9879\uFF08failActor \u59CB\u7EC8\u56FA\u5B9A\u4E3A false\uFF09\n *\n * @param {string} step - \u6B65\u9AA4\u540D\u79F0\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {Function} fn - \u6267\u884C\u7684\u5F02\u6B65\u64CD\u4F5C\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\uFF08\u652F\u6301 retry\uFF09\n */\n async runStepLoose(step, page, fn, options = {}) {\n return await this.runStep(step, page, fn, {\n ...options,\n failActor: false,\n });\n },\n\n /**\n * \u63A8\u9001\u6210\u529F\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\u3002\n * \u8FD9\u91CC\u4F1A\u81EA\u52A8\u505A\u4E09\u4EF6\u4E8B\uFF1A\n * 1. \u91C7\u96C6\u5F53\u524D\u9875\u9762\u7684 env_patch\uFF1B\n * 2. \u5408\u5E76\u663E\u5F0F\u4F20\u5165\u7684 env_patch\uFF1B\n * 3. \u4E00\u5E76\u5199\u5165 dataset\uFF0C\u4F9B\u540E\u7AEF\u56DE\u5199 runtime_env_json\u3002\n * @param {Object} data - \u8981\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\n */\n async pushSuccess(data, options = {}) {\n const runtimeContext = getRuntimeContext();\n const page = pickPage(options?.page, data?.page, lastPage);\n if (page) {\n lastPage = page;\n }\n\n let payloadData = data;\n let explicitPatch = null;\n if (data && typeof data === 'object' && !Array.isArray(data)) {\n payloadData = { ...data };\n explicitPatch = payloadData.env_patch;\n delete payloadData.env_patch;\n delete payloadData.page;\n }\n\n const capturedPatch = await captureAutoEnvPatch(page, runtimeContext);\n const envPatch = RuntimeEnv.mergeEnvPatches(runtimeContext.envPatch, capturedPatch, explicitPatch);\n const traffic = await ProxyMeterRuntime.getProxyMeterSnapshot({ finalize: true });\n const payload = {\n code: Code.Success,\n status: Status.Success,\n ...(traffic ? { traffic } : {}),\n timestamp: new Date().toISOString(),\n data: payloadData,\n };\n if (envPatch) {\n payload.env_patch = envPatch;\n }\n await Actor.pushData({\n ...payload,\n });\n logger.success('pushSuccess', 'Data pushed');\n },\n\n /**\n * \u63A8\u9001\u5931\u8D25\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\uFF08\u79C1\u6709\u65B9\u6CD5\uFF0C\u4EC5\u4F9B runStep \u5185\u90E8\u4F7F\u7528\uFF09\u3002\n * \u5373\u4FBF\u4EFB\u52A1\u5931\u8D25\uFF0C\u8FD9\u91CC\u4E5F\u4F1A\u81EA\u52A8\u56DE\u6536 env_patch\uFF0C\u786E\u4FDD cookies/storage \u7684\u6700\u65B0\u72B6\u6001\u4E0D\u4F1A\u4E22\u3002\n * @param {Error|CrawlerError} error - \u9519\u8BEF\u5BF9\u8C61\n * @param {Object} [meta] - \u989D\u5916\u7684\u6570\u636E\uFF08\u5982 failedStep\u3001screenshotBase64 \u7B49\uFF09\n * @param {Object} [options] - \u9644\u52A0\u9009\u9879\uFF08\u5982 page\uFF09\n * @private\n */\n async pushFailed(error, meta = {}, options = {}) {\n const runtimeContext = getRuntimeContext();\n const page = pickPage(options?.page, meta?.page, lastPage);\n if (page) {\n lastPage = page;\n }\n const capturedPatch = await captureAutoEnvPatch(page, runtimeContext);\n const explicitPatch = meta?.env_patch;\n const envPatch = RuntimeEnv.mergeEnvPatches(runtimeContext.envPatch, capturedPatch, explicitPatch);\n const safeMeta = sanitizeMeta(meta);\n delete safeMeta.env_patch;\n\n // \u5982\u679C\u662F CrawlerError\uFF0C\u63D0\u53D6\u5176 key \u548C context\n const isCrawlerError = CrawlerError.isCrawlerError(error);\n const code = isCrawlerError ? error.code : Code.UnknownError;\n const context = isCrawlerError ? error.context : {};\n const traffic = await ProxyMeterRuntime.getProxyMeterSnapshot({ finalize: true });\n const payload = {\n // \u5982\u679C\u662F CrawlerError\uFF0C\u4F7F\u7528\u5176 code\uFF0C\u5426\u5219\u4F7F\u7528\u9ED8\u8BA4 Failed code\n code,\n status: Status.Failed,\n ...(traffic ? { traffic } : {}),\n error: serializeError(error),\n meta: safeMeta,\n context,\n timestamp: new Date().toISOString(),\n };\n if (envPatch) {\n payload.env_patch = envPatch;\n }\n\n await Actor.pushData({\n ...payload,\n });\n logger.success('pushFailed', 'Error data pushed');\n }\n };\n}\n\n// \u61D2\u52A0\u8F7D\u5355\u4F8B\nlet instance = null;\n\n/**\n * \u83B7\u53D6 ApifyKit \u5B9E\u4F8B\uFF08\u61D2\u52A0\u8F7D\uFF09\n * @returns {Promise<Object>} ApifyKit \u5B9E\u4F8B\n */\nasync function useApifyKit() {\n if (!instance) {\n instance = await createApifyKit();\n }\n return instance;\n}\n\n// \u4E5F\u5BFC\u51FA\u521D\u59CB\u5316\u51FD\u6570\uFF0C\u4F9B\u9700\u8981\u7684\u7528\u6237\u4F7F\u7528\nexport const ApifyKit = {\n useApifyKit\n};\n", "import { spawn, spawnSync } from 'child_process';\nimport { existsSync, mkdirSync, readFileSync, rmSync } from 'fs';\nimport { tmpdir } from 'os';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { createInternalLogger } from './logger.js';\n\nconst logger = createInternalLogger('ProxyMeter');\n\nconst MAX_TOP_DOMAINS = 20;\nconst FLUSH_INTERVAL_MS = 2000;\nconst DEFAULT_DEBUG_MAX_EVENTS = 400;\n\nlet runtime = null;\nlet cleanupInstalled = false;\nlet observedDomainResourceTypes = new Map();\n\nconst toSafeInt = (value) => {\n const num = Number(value);\n if (!Number.isFinite(num) || num <= 0) return 0;\n return Math.round(num);\n};\n\nconst toSafeFloat = (value) => {\n const num = Number(value);\n if (!Number.isFinite(num)) return 0;\n return num;\n};\n\nconst normalizeResourceType = (value) => {\n const type = String(value || '').trim().toLowerCase();\n if (!type) return 'other';\n return type;\n};\n\nconst resolveHostname = (requestUrl) => {\n const raw = String(requestUrl || '').trim();\n if (!raw) return '';\n try {\n return String(new URL(raw).hostname || '').trim().toLowerCase();\n } catch {\n return '';\n }\n};\n\nconst recordDomainResourceType = (domain, resourceType) => {\n const host = String(domain || '').trim().toLowerCase();\n if (!host) return;\n const type = normalizeResourceType(resourceType);\n let byType = observedDomainResourceTypes.get(host);\n if (!byType) {\n byType = new Map();\n observedDomainResourceTypes.set(host, byType);\n }\n byType.set(type, (byType.get(type) || 0) + 1);\n};\n\nconst resolveResourceTypeMeta = (domain) => {\n const host = String(domain || '').trim().toLowerCase();\n if (!host) return { resourceType: '', resourceTypeCounts: undefined };\n const byType = observedDomainResourceTypes.get(host);\n if (!byType || byType.size === 0) {\n return { resourceType: '', resourceTypeCounts: undefined };\n }\n const entries = Array.from(byType.entries())\n .filter(([type, count]) => type && Number(count) > 0)\n .sort((a, b) => {\n if (Number(b[1]) !== Number(a[1])) return Number(b[1]) - Number(a[1]);\n return String(a[0]).localeCompare(String(b[0]));\n });\n if (entries.length === 0) {\n return { resourceType: '', resourceTypeCounts: undefined };\n }\n return {\n resourceType: entries[0][0],\n resourceTypeCounts: Object.fromEntries(entries.map(([type, count]) => [type, toSafeInt(count)])),\n };\n};\n\nconst resolveScriptPath = () => {\n const baseDir = typeof __dirname !== 'undefined'\n ? __dirname\n : path.dirname(fileURLToPath(import.meta.url));\n const internalCandidate = path.join(baseDir, 'internals', 'proxy-meter.js');\n if (existsSync(internalCandidate)) {\n return internalCandidate;\n }\n return path.join(baseDir, 'proxy-meter.js');\n};\n\nconst pickFreePort = () => {\n const script = [\n 'const net=require(\"net\");',\n 'const server=net.createServer();',\n 'server.listen(0,\"127.0.0.1\",()=>{',\n 'const port=server.address().port;',\n 'server.close(()=>{console.log(port);});',\n '});',\n ].join('');\n const result = spawnSync(process.execPath, ['-e', script], { encoding: 'utf8' });\n const port = Number(String(result.stdout || '').trim());\n if (result.status === 0 && Number.isFinite(port) && port > 0) {\n return port;\n }\n return 20000 + Math.floor(Math.random() * 20000);\n};\n\nconst resolveLogDir = () => {\n const storageDir = process.env.APIFY_STORAGE_DIR || process.env.APIFY_LOCAL_STORAGE_DIR || '';\n if (storageDir) {\n return path.join(storageDir, 'proxy-meter');\n }\n return path.join(tmpdir(), 'proxy-meter');\n};\n\nconst ensureLogPath = () => {\n const baseDir = resolveLogDir();\n if (!existsSync(baseDir)) {\n try {\n mkdirSync(baseDir, { recursive: true });\n } catch {}\n }\n const runId = String(process.env.APIFY_ACTOR_RUN_ID || '').trim();\n const suffix = `${Date.now()}-${Math.floor(Math.random() * 1000000)}`;\n const label = runId ? `proxy-meter-${runId}-${suffix}.json` : `proxy-meter-${process.pid}-${suffix}.json`;\n return path.join(baseDir, label);\n};\n\nconst readSnapshot = (logPath) => {\n if (!logPath || !existsSync(logPath)) return null;\n try {\n const raw = readFileSync(logPath, 'utf8');\n if (!raw) return null;\n return JSON.parse(raw);\n } catch {\n return null;\n }\n};\n\nconst normalizeDomainRows = (hosts) => {\n const rows = [];\n let requestCount = 0;\n let connectCount = 0;\n\n for (const [domain, stat] of Object.entries(hosts || {})) {\n if (!stat || typeof stat !== 'object') continue;\n const inBytes = toSafeInt(stat.inBytes);\n const outBytes = toSafeInt(stat.outBytes);\n const requests = toSafeInt(stat.requests);\n const connections = toSafeInt(stat.connections);\n const totalBytes = inBytes + outBytes;\n requestCount += requests;\n connectCount += connections;\n if (totalBytes <= 0 && requests <= 0 && connections <= 0) continue;\n const resourceTypeMeta = resolveResourceTypeMeta(domain);\n rows.push({\n domain,\n inBytes,\n outBytes,\n totalBytes,\n requests,\n connections,\n resourceType: resourceTypeMeta.resourceType || undefined,\n resourceTypeCounts: resourceTypeMeta.resourceTypeCounts || undefined,\n });\n }\n\n rows.sort((a, b) => {\n if (b.totalBytes !== a.totalBytes) return b.totalBytes - a.totalBytes;\n if (b.requests !== a.requests) return b.requests - a.requests;\n return String(a.domain).localeCompare(String(b.domain));\n });\n\n return {\n topDomains: rows.slice(0, MAX_TOP_DOMAINS),\n requestCount,\n connectCount,\n };\n};\n\nconst normalizeDebugRows = (rows, type) => {\n if (!Array.isArray(rows) || rows.length === 0) return undefined;\n const normalized = rows\n .map((row) => {\n if (!row || typeof row !== 'object') return null;\n return {\n domain: String(row.domain || '').trim(),\n status: String(row.status || '').trim(),\n count: toSafeInt(row.count),\n failedCount: toSafeInt(row.failedCount),\n inBytes: toSafeInt(row.inBytes),\n outBytes: toSafeInt(row.outBytes),\n totalBytes: toSafeInt(row.totalBytes),\n avgDurationMs: toSafeFloat(row.avgDurationMs),\n reconnectCount: toSafeInt(row.reconnectCount),\n largeResponseCount: toSafeInt(row.largeResponseCount),\n failureRatePct: toSafeFloat(row.failureRatePct),\n type,\n };\n })\n .filter((row) => row && row.domain && row.count > 0);\n return normalized.length > 0 ? normalized : undefined;\n};\n\nconst normalizeDebugEvent = (row) => {\n if (!row || typeof row !== 'object') return null;\n const host = String(row.host || '').trim();\n if (!host) return null;\n return {\n ts: String(row.ts || ''),\n runId: String(row.runId || ''),\n channel: String(row.channel || ''),\n host,\n method: String(row.method || ''),\n path: String(row.path || ''),\n statusCode: toSafeInt(row.statusCode),\n durationMs: toSafeInt(row.durationMs),\n inBytes: toSafeInt(row.inBytes),\n outBytes: toSafeInt(row.outBytes),\n totalBytes: toSafeInt(row.totalBytes),\n error: String(row.error || ''),\n };\n};\n\nconst normalizeDebugSummary = (debug) => {\n if (!debug || typeof debug !== 'object' || !debug.summary || typeof debug.summary !== 'object') {\n return null;\n }\n const summary = debug.summary;\n const domainStatus = normalizeDebugRows(summary.domainStatus, 'domain_status');\n const topFailureDomains = normalizeDebugRows(summary.topFailureDomains, 'top_failure');\n const topLargeDomains = normalizeDebugRows(summary.topLargeDomains, 'top_large');\n const topReconnectDomains = normalizeDebugRows(summary.topReconnectDomains, 'top_reconnect');\n\n return {\n enabled: Boolean(debug.enabled),\n sampledEvents: toSafeInt(debug.sampledEvents),\n droppedEvents: toSafeInt(debug.droppedEvents),\n totalEvents: toSafeInt(debug.totalEvents),\n largeResponseThresholdBytes: toSafeInt(summary.largeResponseThresholdBytes),\n requestCount: toSafeInt(summary.requestCount),\n failedCount: toSafeInt(summary.failedCount),\n failureRatePct: toSafeFloat(summary.failureRatePct),\n largeResponseCount: toSafeInt(summary.largeResponseCount),\n reconnectCount: toSafeInt(summary.reconnectCount),\n domainStatus,\n topFailureDomains,\n topLargeDomains,\n topReconnectDomains,\n };\n};\n\nconst normalizeSnapshot = (raw) => {\n if (!raw || typeof raw !== 'object') return null;\n const totalIn = toSafeInt(raw.totalInBytes);\n const totalOut = toSafeInt(raw.totalOutBytes);\n const domains = normalizeDomainRows(raw.hosts && typeof raw.hosts === 'object' ? raw.hosts : {});\n\n const normalized = {\n meter: 'proxy-meter-v1',\n totalBytes: totalIn + totalOut,\n uploadBytes: totalOut,\n downloadBytes: totalIn,\n requestCount: domains.requestCount,\n connectCount: domains.connectCount,\n topDomains: domains.topDomains,\n };\n\n const debug = raw.debug && typeof raw.debug === 'object' ? raw.debug : null;\n const summary = normalizeDebugSummary(debug);\n const events = Array.isArray(debug?.events)\n ? debug.events.map(normalizeDebugEvent).filter(Boolean)\n : [];\n if (summary) {\n normalized.trafficDebugSummary = summary;\n }\n if (events.length > 0) {\n normalized.trafficDebugEvents = events;\n }\n\n const hasSignal = normalized.totalBytes > 0\n || normalized.uploadBytes > 0\n || normalized.downloadBytes > 0\n || normalized.requestCount > 0\n || normalized.connectCount > 0\n || (normalized.topDomains && normalized.topDomains.length > 0)\n || Boolean(summary)\n || events.length > 0;\n\n if (!hasSignal) return null;\n return normalized;\n};\n\nconst registerCleanup = () => {\n if (cleanupInstalled) return;\n cleanupInstalled = true;\n const shutdown = () => {\n if (!runtime || !runtime.proc) return;\n try { runtime.proc.kill('SIGTERM'); } catch {}\n };\n process.once('exit', shutdown);\n process.once('SIGINT', shutdown);\n process.once('SIGTERM', shutdown);\n};\n\nconst startProxyMeter = (options = {}) => {\n const upstreamUrl = String(options.proxyUrl || '').trim();\n if (!upstreamUrl) return null;\n\n if (runtime && runtime.proc) {\n try { runtime.proc.kill('SIGTERM'); } catch {}\n runtime = null;\n }\n observedDomainResourceTypes = new Map();\n\n const port = pickFreePort();\n const logPath = ensureLogPath();\n const scriptPath = resolveScriptPath();\n const debugMode = Boolean(options.debugMode);\n const debugMaxEvents = Math.max(10, toSafeInt(options.debugMaxEvents) || DEFAULT_DEBUG_MAX_EVENTS);\n const env = {\n ...process.env,\n PROXY_METER_PORT: String(port),\n PROXY_METER_LOG: logPath,\n PROXY_METER_UPSTREAM: upstreamUrl,\n PROXY_METER_FLUSH_MS: String(FLUSH_INTERVAL_MS),\n PROXY_METER_DEBUG: debugMode ? '1' : '0',\n PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents),\n };\n\n const child = spawn(process.execPath, [scriptPath], {\n env,\n stdio: ['ignore', 'ignore', 'ignore'],\n });\n\n child.once('exit', (code) => {\n if (code && code !== 0) {\n logger.warn(`[proxy-meter] exited with code ${code}`);\n }\n });\n\n runtime = {\n proc: child,\n port,\n logPath,\n startedAt: Date.now(),\n };\n\n registerCleanup();\n return { server: `http://127.0.0.1:${port}` };\n};\n\nconst recordProxyMeterResourceType = (requestUrl, resourceType) => {\n if (!runtime) return;\n const host = resolveHostname(requestUrl);\n if (!host) return;\n recordDomainResourceType(host, resourceType);\n};\n\nconst stopProxyMeter = async () => {\n if (!runtime) return null;\n const { proc, logPath } = runtime;\n if (!proc || proc.killed) {\n runtime = null;\n return logPath || null;\n }\n\n await new Promise((resolve) => {\n const timeout = setTimeout(() => {\n try { proc.kill('SIGKILL'); } catch {}\n resolve();\n }, 2000);\n proc.once('exit', () => {\n clearTimeout(timeout);\n resolve();\n });\n try { proc.kill('SIGTERM'); } catch { resolve(); }\n });\n\n runtime = null;\n return logPath || null;\n};\n\nconst getProxyMeterSnapshot = async (options = {}) => {\n if (!runtime) return null;\n const finalize = Boolean(options.finalize);\n const logPath = finalize ? await stopProxyMeter() : runtime.logPath;\n const raw = readSnapshot(logPath);\n const snapshot = normalizeSnapshot(raw);\n if (finalize && logPath) {\n try { rmSync(logPath, { force: true }); } catch {}\n }\n return snapshot;\n};\n\nexport const ProxyMeterRuntime = {\n startProxyMeter,\n recordProxyMeterResourceType,\n stopProxyMeter,\n getProxyMeterSnapshot,\n};\n", "const BROWSER_PROFILE_SCHEMA_VERSION = 1;\n\nlet rememberedRuntimeState = null;\n\nconst isPlainObject = (value) => value && typeof value === 'object' && !Array.isArray(value);\n\n// \u8FD0\u884C\u6001\u5FEB\u7167\u5728 visitor / toolkit / \u540E\u7AEF\u4E4B\u95F4\u6765\u56DE\u4F20\u9012\uFF0C\n// \u6240\u4EE5\u6240\u6709\u5165\u53E3\u90FD\u5148\u8D70 deepClone\uFF0C\u907F\u514D\u5171\u4EAB\u5F15\u7528\u5F15\u53D1\u201C\u8FB9\u8DD1\u8FB9\u6539\u201D\u7684\u9690\u5F0F\u526F\u4F5C\u7528\u3002\nconst deepClone = (value) => {\n if (value == null) return value;\n try {\n return JSON.parse(JSON.stringify(value));\n } catch {\n return value;\n\t}\n};\n\n// \u5C1D\u8BD5\u628A runtime / browser_profile \u4E4B\u7C7B\u7684 JSON \u5B57\u6BB5\u89E3\u6790\u6210\u5BF9\u8C61\u3002\nconst tryParseJSON = (value) => {\n if (value == null) return null;\n if (typeof value === 'object') return value;\n const raw = String(value || '').trim();\n if (!raw) return null;\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n\t}\n};\n\n// local/session/auth \u7684\u89C4\u8303\u5316\u76EE\u6807\u53EA\u6709\u4E00\u4E2A\uFF1A\u8FC7\u6EE4\u7A7A\u503C\uFF0C\u7EDF\u4E00\u8F6C\u6210\u5B57\u7B26\u4E32\u3002\nconst normalizeLocalStorage = (value) => {\n const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};\n return Object.entries(source).reduce((acc, [key, item]) => {\n const safeKey = String(key || '').trim();\n const safeValue = String(item ?? '').trim();\n if (!safeKey || !safeValue || safeValue === '<nil>') return acc;\n acc[safeKey] = safeValue;\n return acc;\n }, {});\n};\n\nconst normalizeSessionStorage = (value) => {\n const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};\n return Object.entries(source).reduce((acc, [key, item]) => {\n const safeKey = String(key || '').trim();\n const safeValue = String(item ?? '').trim();\n if (!safeKey || !safeValue || safeValue === '<nil>') return acc;\n acc[safeKey] = safeValue;\n return acc;\n }, {});\n};\n\nconst normalizeAuth = (value) => {\n const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};\n return Object.entries(source).reduce((acc, [key, item]) => {\n const safeKey = String(key || '').trim();\n const safeValue = String(item ?? '').trim();\n if (!safeKey || !safeValue || safeValue === '<nil>') return acc;\n acc[safeKey] = safeValue;\n return acc;\n }, {});\n};\n\nconst normalizeCookieSameSite = (value) => {\n const raw = String(value || '').trim().toLowerCase();\n if (!raw) return '';\n\n switch (raw) {\n case 'strict':\n return 'Strict';\n case 'lax':\n return 'Lax';\n case 'none':\n case 'no_restriction':\n return 'None';\n case 'unspecified':\n default:\n return '';\n }\n};\n\nconst normalizeCookieExpires = (raw = {}) => {\n const source = raw && typeof raw === 'object' ? raw : {};\n const session = Boolean(source.session);\n if (session) return null;\n\n const expiresCandidate = Number(source.expires);\n if (Number.isFinite(expiresCandidate) && expiresCandidate > 0) {\n return expiresCandidate;\n }\n\n const expirationDateCandidate = Number(source.expirationDate);\n if (Number.isFinite(expirationDateCandidate) && expirationDateCandidate > 0) {\n return expirationDateCandidate;\n }\n\n return null;\n};\n\nconst normalizeCookies = (value) => {\n if (!Array.isArray(value)) return [];\n return value\n .map((item) => {\n const raw = item && typeof item === 'object' ? item : {};\n const name = String(raw.name || '').trim();\n const cookieValue = String(raw.value ?? '').trim();\n if (!name || !cookieValue || cookieValue === '<nil>') return null;\n const domain = String(raw.domain || '').trim();\n const url = normalizeHttpUrl(raw.url);\n const path = String(raw.path || '').trim() || '/';\n const sameSite = normalizeCookieSameSite(raw.sameSite);\n const expires = normalizeCookieExpires(raw);\n const secure = Boolean(raw.secure);\n const httpOnly = Boolean(raw.httpOnly);\n const partitionKey = typeof raw.partitionKey === 'string' ? String(raw.partitionKey).trim() : '';\n\n // \u7EDF\u4E00\u8F93\u51FA Playwright \u53EF\u63A5\u53D7\u7684 Cookie \u7ED3\u6784\uFF0C\u907F\u514D\u628A Chrome \u6269\u5C55\u4FA7\u5B57\u6BB5\u539F\u6837\u900F\u4F20\u8FC7\u53BB\u3002\n const normalized = {\n name,\n value: cookieValue,\n path,\n ...(domain ? { domain } : {}),\n ...(!domain && url ? { url } : {}),\n ...(sameSite ? { sameSite } : {}),\n ...(secure ? { secure: true } : {}),\n ...(httpOnly ? { httpOnly: true } : {}),\n ...(expires !== null ? { expires } : {}),\n ...(partitionKey ? { partitionKey } : {}),\n };\n\n if (!normalized.domain && !normalized.url) {\n return null;\n }\n\n return {\n ...normalized,\n };\n })\n .filter(Boolean);\n};\n\nconst buildCookieMap = (cookies) => cookies.reduce((acc, item) => {\n\tacc[item.name] = item.value;\n\treturn acc;\n}, {});\n\n// \u7EDF\u4E00\u628A\u539F\u59CB URL \u5FEB\u7167\u8FC7\u6EE4\u6210 http/https\uFF0C\u907F\u514D browser/runtime \u4E24\u7AEF\u5404\u81EA\u505A\u4E00\u5957\u5224\u65AD\u3002\nconst normalizeHttpUrl = (value) => {\n const raw = String(value || '').trim();\n if (!raw) return '';\n try {\n const parsed = new URL(raw);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return '';\n parsed.hash = '';\n return parsed.toString();\n } catch {\n return '';\n }\n};\n\nconst uniqueStrings = (value) => {\n const list = Array.isArray(value) ? value : [];\n const seen = new Set();\n const result = [];\n list.forEach((item) => {\n const normalized = String(item || '').trim();\n if (!normalized || seen.has(normalized)) return;\n seen.add(normalized);\n result.push(normalized);\n });\n return result;\n};\n\nconst normalizeHttpUrlList = (value) => uniqueStrings(\n (Array.isArray(value) ? value : [value])\n .map((item) => normalizeHttpUrl(item))\n .filter(Boolean),\n);\n\nconst normalizeCookieDomain = (value) => String(value || '').trim().replace(/^\\./, '').toLowerCase();\n\nconst normalizeCookiePath = (value) => {\n const raw = String(value || '').trim();\n if (!raw) return '/';\n return raw.startsWith('/') ? raw : `/${raw}`;\n};\n\nconst doesCookieMatchUrl = (cookie, url) => {\n if (!cookie || !url) return false;\n try {\n const parsed = new URL(url);\n const host = String(parsed.hostname || '').trim().toLowerCase();\n const pathname = String(parsed.pathname || '/').trim() || '/';\n const cookieDomain = normalizeCookieDomain(cookie.domain);\n const cookiePath = normalizeCookiePath(cookie.path);\n if (!host || !cookieDomain) return false;\n const domainMatched = host === cookieDomain || host.endsWith(`.${cookieDomain}`);\n if (!domainMatched) return false;\n if (cookie.secure && parsed.protocol !== 'https:') return false;\n return pathname.startsWith(cookiePath);\n } catch {\n return false;\n }\n};\n\nconst normalizeRawSnapshot = (value = {}) => {\n const source = isPlainObject(value) ? value : {};\n const pageUrl = normalizeHttpUrl(source.page_url ?? source.pageUrl);\n const frameUrls = normalizeHttpUrlList(source.frame_urls ?? source.frameUrls);\n const resourceUrls = normalizeHttpUrlList(source.resource_urls ?? source.resourceUrls);\n const browserProfileObservedSource =\n source.browser_profile_observed\n ?? source.browserProfileObserved\n ?? source.browser_profile?.observed\n ?? source.browserProfile?.observed\n ?? source.browserProfile;\n\n return {\n page_url: pageUrl,\n frame_urls: frameUrls,\n resource_urls: resourceUrls,\n cookies: Array.isArray(source.cookies) ? deepClone(source.cookies) : [],\n local_storage: normalizeLocalStorage(source.local_storage ?? source.localStorage),\n session_storage: normalizeSessionStorage(source.session_storage ?? source.sessionStorage),\n browser_profile_observed: normalizeObservedBrowserProfile(browserProfileObservedSource),\n auth: normalizeAuth(source.auth),\n };\n};\n\nconst collectCookieUrlsFromSnapshot = (snapshot = {}) => {\n const normalized = normalizeRawSnapshot(snapshot);\n return uniqueStrings([\n normalized.page_url,\n ...normalized.frame_urls,\n ...normalized.resource_urls,\n ].filter(Boolean));\n};\n\nconst filterCookiesBySnapshot = (cookies = [], snapshot = {}) => {\n const normalizedCookies = normalizeCookies(cookies);\n const cookieUrls = collectCookieUrlsFromSnapshot(snapshot);\n if (cookieUrls.length === 0) {\n return normalizedCookies;\n }\n return normalizedCookies.filter((cookie) => cookieUrls.some((url) => doesCookieMatchUrl(cookie, url)));\n};\n\nconst buildEnvPayloadFromSnapshot = (snapshot = {}, options = {}) => {\n const normalized = normalizeRawSnapshot(snapshot);\n const cookies = filterCookiesBySnapshot(snapshot?.cookies || normalized.cookies, normalized);\n const localStorage = normalized.local_storage;\n const sessionStorage = normalized.session_storage;\n const auth = normalizeAuth(options.auth ?? normalized.auth);\n const browserProfileCore = normalizeBrowserProfileCore(\n options.browserProfileCore\n ?? snapshot?.browser_profile?.core\n ?? snapshot?.browserProfile?.core,\n );\n const browserProfile = buildBrowserProfilePayload(browserProfileCore, normalized.browser_profile_observed);\n\n const payload = {\n ...(cookies.length > 0 ? { cookies } : {}),\n ...(Object.keys(localStorage).length > 0 ? { local_storage: localStorage } : {}),\n ...(Object.keys(sessionStorage).length > 0 ? { session_storage: sessionStorage } : {}),\n ...(Object.keys(auth).length > 0 ? { auth } : {}),\n ...(Object.keys(browserProfile).length > 0 ? { browser_profile: browserProfile } : {}),\n };\n return Object.keys(payload).length > 0 ? payload : null;\n};\n\nconst captureRawSnapshotFromPage = async (page) => {\n const frameUrls = typeof page?.frames === 'function'\n ? page.frames().map((frame) => {\n try {\n return frame.url();\n } catch {\n return '';\n }\n })\n : [];\n\n const snapshot = await page.evaluate(() => {\n const localStorage = {};\n const sessionStorage = {};\n const resourceUrls = [];\n const frameUrls = [];\n\n try {\n for (let i = 0; i < window.localStorage.length; i += 1) {\n const key = window.localStorage.key(i);\n if (!key) continue;\n const value = window.localStorage.getItem(key);\n if (value !== null) localStorage[key] = value;\n }\n } catch {\n // ignore\n }\n\n try {\n for (let i = 0; i < window.sessionStorage.length; i += 1) {\n const key = window.sessionStorage.key(i);\n if (!key) continue;\n const value = window.sessionStorage.getItem(key);\n if (value !== null) sessionStorage[key] = value;\n }\n } catch {\n // ignore\n }\n\n try {\n const perfEntries = performance.getEntriesByType('resource') || [];\n perfEntries.forEach((entry) => {\n const name = String(entry?.name || '').trim();\n if (name) resourceUrls.push(name);\n });\n } catch {\n // ignore\n }\n\n try {\n document.querySelectorAll('iframe,frame').forEach((node) => {\n const src = String(node?.src || '').trim();\n if (src) frameUrls.push(src);\n });\n } catch {\n // ignore\n }\n\n const nav = window.navigator || {};\n const screen = window.screen || {};\n const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || '';\n\n return {\n page_url: window.location.href || '',\n frame_urls: frameUrls,\n resource_urls: resourceUrls,\n local_storage: localStorage,\n session_storage: sessionStorage,\n browser_profile_observed: {\n user_agent: nav.userAgent || '',\n platform: nav.platform || '',\n language: nav.language || '',\n languages: Array.isArray(nav.languages) ? nav.languages : [],\n hardware_concurrency: Number(nav.hardwareConcurrency || 0),\n device_memory: Number(nav.deviceMemory || 0),\n timezone,\n viewport: {\n width: Number(window.innerWidth || 0),\n height: Number(window.innerHeight || 0),\n },\n screen: {\n width: Number(screen.width || 0),\n height: Number(screen.height || 0),\n avail_width: Number(screen.availWidth || 0),\n avail_height: Number(screen.availHeight || 0),\n color_depth: Number(screen.colorDepth || 0),\n pixel_depth: Number(screen.pixelDepth || 0),\n },\n },\n };\n });\n\n return normalizeRawSnapshot({\n ...snapshot,\n frame_urls: [...frameUrls, ...(snapshot?.frame_urls || [])],\n });\n};\n\n// observed \u53EA\u4FDD\u5B58\u201C\u8FD0\u884C\u540E\u770B\u5230\u7684\u6D4F\u89C8\u5668\u8868\u73B0\u201D\uFF0C\u5B83\u4E0D\u662F\u542F\u52A8\u771F\u6E90\u3002\nconst normalizeObservedBrowserProfile = (value) => {\n const source = isPlainObject(value) ? value : {};\n const profile = {};\n\n const stringFields = {\n user_agent: source.user_agent,\n platform: source.platform,\n language: source.language,\n timezone: source.timezone,\n };\n Object.entries(stringFields).forEach(([key, item]) => {\n const safeValue = String(item || '').trim();\n if (safeValue) {\n profile[key] = safeValue;\n }\n });\n\n if (Array.isArray(source.languages)) {\n const languages = source.languages\n .map((item) => String(item || '').trim())\n .filter(Boolean);\n if (languages.length > 0) {\n profile.languages = languages;\n }\n }\n\n const numericFields = {\n hardware_concurrency: Number(source.hardware_concurrency || 0),\n device_memory: Number(source.device_memory || 0),\n };\n Object.entries(numericFields).forEach(([key, item]) => {\n if (Number.isFinite(item) && item > 0) {\n profile[key] = item;\n }\n });\n\n if (isPlainObject(source.viewport)) {\n const width = Number(source.viewport.width || 0);\n const height = Number(source.viewport.height || 0);\n if (width > 0 && height > 0) {\n profile.viewport = { width, height };\n }\n }\n\n if (isPlainObject(source.screen)) {\n const screenProfile = {};\n const screenFields = {\n width: Number(source.screen.width || 0),\n height: Number(source.screen.height || 0),\n avail_width: Number(source.screen.avail_width || 0),\n avail_height: Number(source.screen.avail_height || 0),\n color_depth: Number(source.screen.color_depth || 0),\n pixel_depth: Number(source.screen.pixel_depth || 0),\n };\n Object.entries(screenFields).forEach(([key, item]) => {\n if (Number.isFinite(item) && item > 0) {\n screenProfile[key] = item;\n }\n });\n if (Object.keys(screenProfile).length > 0) {\n profile.screen = screenProfile;\n }\n }\n\n\treturn profile;\n};\n\n// core \u662F\u6D4F\u89C8\u5668\u73AF\u5883\u7684\u552F\u4E00\u771F\u6E90\uFF1A\n// fingerprint / timezone_id / locale / browser_major_version \u90FD\u5728\u8FD9\u91CC\u3002\nconst normalizeBrowserProfileCore = (value) => {\n const source = isPlainObject(value) ? value : {};\n const profile = {};\n\n if (isPlainObject(source.fingerprint) && Object.keys(source.fingerprint).length > 0) {\n profile.fingerprint = deepClone(source.fingerprint);\n }\n\n const timezoneId = String(source.timezone_id || '').trim();\n if (timezoneId) {\n profile.timezone_id = timezoneId;\n }\n\n const locale = String(source.locale || '').trim();\n if (locale) {\n profile.locale = locale;\n }\n\n const browserMajorVersion = Number(source.browser_major_version || 0);\n if (Number.isFinite(browserMajorVersion) && browserMajorVersion > 0) {\n profile.browser_major_version = browserMajorVersion;\n }\n\n const schemaVersion = Number(source.schema_version || 0);\n if (Number.isFinite(schemaVersion) && schemaVersion > 0) {\n profile.schema_version = schemaVersion;\n } else if (Object.keys(profile).length > 0) {\n profile.schema_version = BROWSER_PROFILE_SCHEMA_VERSION;\n }\n\n\treturn profile;\n};\n\n// buildBrowserProfilePayload \u4FDD\u8BC1 browser_profile \u6C38\u8FDC\u53EA\u66B4\u9732 core / observed \u4E24\u5C42\u7ED3\u6784\u3002\nconst buildBrowserProfilePayload = (core = {}, observed = {}) => {\n const payload = {};\n if (isPlainObject(core) && Object.keys(core).length > 0) {\n payload.core = core;\n }\n if (isPlainObject(observed) && Object.keys(observed).length > 0) {\n payload.observed = observed;\n }\n return payload;\n};\n\nconst mergePlainObject = (target = {}, source = {}) => {\n const next = isPlainObject(target) ? deepClone(target) : {};\n if (!isPlainObject(source)) return next;\n\n Object.entries(source).forEach(([key, value]) => {\n if (!key) return;\n if (isPlainObject(value) && isPlainObject(next[key])) {\n next[key] = mergePlainObject(next[key], value);\n return;\n }\n next[key] = deepClone(value);\n });\n\n\treturn next;\n};\n\n// mergeBrowserProfilePayload \u7684\u6838\u5FC3\u89C4\u5219\uFF1A\n// 1. core \u53EA\u5728\u5F53\u524D\u4E3A\u7A7A\uFF0C\u6216\u6D4F\u89C8\u5668\u5927\u7248\u672C\u51B2\u7A81\u65F6\u624D\u66FF\u6362\uFF1B\n// 2. observed \u6BCF\u6B21\u90FD\u5141\u8BB8\u8986\u76D6\u66F4\u65B0\u3002\nconst mergeBrowserProfilePayload = (target = {}, source = {}) => {\n const current = isPlainObject(target) ? target : {};\n const incoming = isPlainObject(source) ? source : {};\n const currentCore = normalizeBrowserProfileCore(current.core);\n const incomingCore = normalizeBrowserProfileCore(incoming.core);\n const currentObserved = normalizeObservedBrowserProfile(current.observed);\n const incomingObserved = normalizeObservedBrowserProfile(incoming.observed);\n\n let mergedCore = currentCore;\n if (Object.keys(mergedCore).length === 0 && Object.keys(incomingCore).length > 0) {\n mergedCore = incomingCore;\n } else if (Object.keys(incomingCore).length > 0) {\n const currentVersion = Number(currentCore.browser_major_version || 0);\n const incomingVersion = Number(incomingCore.browser_major_version || 0);\n if (currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {\n mergedCore = incomingCore;\n }\n }\n\n const mergedObserved = mergePlainObject(currentObserved, incomingObserved);\n\treturn buildBrowserProfilePayload(mergedCore, mergedObserved);\n};\n\n// mergeEnvPatchObjects \u662F visitor \u6210\u529F/\u5931\u8D25\u81EA\u52A8\u56DE\u5199 env_patch \u7684\u5408\u5E76\u5165\u53E3\u3002\nconst mergeEnvPatchObjects = (...patches) => {\n const merged = {};\n\n patches.forEach((patch) => {\n if (!isPlainObject(patch)) return;\n Object.entries(patch).forEach(([key, value]) => {\n if (!key) return;\n if (key === 'browser_profile') {\n const browserProfile = mergeBrowserProfilePayload(merged.browser_profile, value);\n if (Object.keys(browserProfile).length > 0) {\n merged.browser_profile = browserProfile;\n }\n return;\n }\n if (isPlainObject(value) && isPlainObject(merged[key])) {\n merged[key] = mergePlainObject(merged[key], value);\n return;\n }\n merged[key] = deepClone(value);\n });\n });\n\n return Object.keys(merged).length > 0 ? merged : null;\n};\n\nconst normalizeBrowserProfile = (value) => {\n const source = isPlainObject(value) ? value : {};\n const coreSource = isPlainObject(source.core) ? source.core : {};\n const observedSource = isPlainObject(source.observed) ? source.observed : {};\n const core = normalizeBrowserProfileCore(coreSource);\n const observed = normalizeObservedBrowserProfile(observedSource);\n return {\n core,\n observed,\n payload: buildBrowserProfilePayload(core, observed),\n };\n};\n\nconst rememberRuntimeState = (state) => {\n rememberedRuntimeState = deepClone(state);\n return rememberedRuntimeState;\n};\n\nconst normalizeRuntimeState = (source = {}, actor = '') => {\n if (\n source &&\n typeof source === 'object' &&\n source.runtime &&\n typeof source.runtime === 'object' &&\n !Array.isArray(source.runtime) &&\n Object.prototype.hasOwnProperty.call(source, 'browserProfileCore')\n ) {\n return source;\n }\n return RuntimeEnv.parseInput(source, actor);\n};\n\nexport const RuntimeEnv = {\n tryParseJSON,\n normalizeCookies,\n normalizeLocalStorage,\n normalizeSessionStorage,\n normalizeAuth,\n normalizeBrowserProfileCore,\n normalizeObservedBrowserProfile,\n normalizeSnapshot(snapshot = {}) {\n return normalizeRawSnapshot(snapshot);\n },\n collectCookieUrls(snapshot = {}) {\n return collectCookieUrlsFromSnapshot(snapshot);\n },\n buildRuntimeEnvFromSnapshot(snapshot = {}, options = {}) {\n return buildEnvPayloadFromSnapshot(snapshot, options);\n },\n buildEnvPatchFromSnapshot(snapshot = {}, options = {}) {\n return buildEnvPayloadFromSnapshot(snapshot, options);\n },\n mergeEnvPatches(...patches) {\n return mergeEnvPatchObjects(...patches);\n },\n\n // parseInput \u628A Actor \u8F93\u5165\u91CC\u7684 runtime \u5B57\u6BB5\u6807\u51C6\u5316\u6210 toolkit \u5185\u90E8\u7EDF\u4E00\u7ED3\u6784\u3002\n // \u540E\u7EED visitor \u53EA\u548C\u8FD9\u4E2A state \u4EA4\u4E92\uFF0C\u4E0D\u518D\u81EA\u5DF1\u62FC token/cookie \u903B\u8F91\u3002\n parseInput(input = {}, actor = '') {\n const runtime = tryParseJSON(input?.runtime) || {};\n const resolvedActor = String(actor || input?.actor || '').trim();\n const cookies = normalizeCookies(runtime?.cookies);\n const cookieMap = buildCookieMap(cookies);\n const localStorage = normalizeLocalStorage(runtime?.local_storage);\n const sessionStorage = normalizeSessionStorage(runtime?.session_storage);\n const auth = normalizeAuth(runtime?.auth);\n const browserProfile = normalizeBrowserProfile(runtime?.browser_profile);\n const envId = String(input?.env_id || '').trim();\n\n const normalizedRuntime = {\n ...runtime,\n ...(cookies.length > 0 ? { cookies } : {}),\n ...(Object.keys(localStorage).length > 0 ? { local_storage: localStorage } : {}),\n ...(Object.keys(sessionStorage).length > 0 ? { session_storage: sessionStorage } : {}),\n ...(Object.keys(auth).length > 0 ? { auth } : {}),\n };\n if (Object.keys(browserProfile.payload).length > 0) {\n normalizedRuntime.browser_profile = browserProfile.payload;\n } else {\n delete normalizedRuntime.browser_profile;\n }\n\n const state = {\n actor: resolvedActor,\n runtime: normalizedRuntime,\n envId,\n auth,\n cookies,\n cookieMap,\n localStorage,\n sessionStorage,\n browserProfile: browserProfile.payload,\n browserProfileCore: browserProfile.core,\n browserProfileObserved: browserProfile.observed,\n };\n rememberRuntimeState(state);\n return state;\n },\n\n // buildEnvPatch \u53EA\u6784\u9020\u5141\u8BB8\u56DE\u5199\u5230\u540E\u7AEF env \u7684\u5B57\u6BB5\u96C6\u5408\u3002\n buildEnvPatch(source = {}, actor = '') {\n const state = normalizeRuntimeState(source, actor);\n const browserProfile = buildBrowserProfilePayload(state.browserProfileCore, state.browserProfileObserved);\n const envPatch = {\n ...(Object.keys(state.auth || {}).length > 0 ? { auth: state.auth } : {}),\n ...(Array.isArray(state.cookies) && state.cookies.length > 0 ? { cookies: state.cookies } : {}),\n ...(Object.keys(state.localStorage || {}).length > 0 ? { local_storage: state.localStorage } : {}),\n ...(Object.keys(state.sessionStorage || {}).length > 0 ? { session_storage: state.sessionStorage } : {}),\n ...(Object.keys(browserProfile).length > 0 ? { browser_profile: browserProfile } : {}),\n };\n return Object.keys(envPatch).length > 0 ? envPatch : null;\n },\n\n // hasLoginState \u7528\u6765\u533A\u5206\u201C\u5FC5\u987B\u9274\u6743\u7684\u5E73\u53F0\u201D\u548C\u201C\u53EF\u533F\u540D\u8FD0\u884C\u7684\u5E73\u53F0\u201D\u3002\n hasLoginState(source = {}, actor = '') {\n const state = normalizeRuntimeState(source, actor);\n return (\n (Array.isArray(state.cookies) && state.cookies.length > 0) ||\n Object.keys(state.localStorage || {}).length > 0 ||\n Object.keys(state.sessionStorage || {}).length > 0 ||\n Object.keys(state.auth || {}).length > 0\n );\n },\n\n getAuthValue(source = {}, key = '', actor = '') {\n const state = normalizeRuntimeState(source, actor);\n const safeKey = String(key || '').trim();\n if (!safeKey) return '';\n return String(state.auth?.[safeKey] ?? '').trim();\n },\n\n rememberState(source = {}) {\n const state = normalizeRuntimeState(source);\n rememberRuntimeState(state);\n return RuntimeEnv.peekRememberedState();\n },\n\n peekRememberedState() {\n return rememberedRuntimeState ? deepClone(rememberedRuntimeState) : null;\n },\n\n getBrowserProfileCore(source = {}, actor = '') {\n const state = normalizeRuntimeState(source, actor);\n return deepClone(state.browserProfileCore || {});\n },\n\n setBrowserProfileCore(source = {}, core = {}, actor = '') {\n const state = normalizeRuntimeState(source, actor);\n const normalizedCore = normalizeBrowserProfileCore(core);\n state.browserProfileCore = normalizedCore;\n state.browserProfile = buildBrowserProfilePayload(normalizedCore, state.browserProfileObserved);\n if (Object.keys(state.browserProfile).length > 0) {\n state.runtime.browser_profile = state.browserProfile;\n } else {\n delete state.runtime.browser_profile;\n }\n rememberRuntimeState(state);\n return state;\n },\n\n // applyToPage \u53EA\u8D1F\u8D23\u628A\u767B\u5F55\u6001\u76F8\u5173\u5B57\u6BB5\u6CE8\u5165\u9875\u9762\uFF1A\n // cookies / localStorage / sessionStorage\u3002\n // \u6307\u7EB9\u3001\u65F6\u533A\u3001UA\u3001viewport \u7684\u56DE\u653E\u53D1\u751F\u5728 launch.js \u542F\u52A8\u9636\u6BB5\uFF0C\u4E0D\u5728\u8FD9\u91CC\u505A\u3002\n async applyToPage(page, source = {}, options = {}) {\n if (!page) return;\n const state = normalizeRuntimeState(source, options?.actor || '');\n const localStorage = state.localStorage || {};\n const sessionStorage = state.sessionStorage || {};\n const cookies = (state.cookies || [])\n .map((cookie) => {\n const normalized = { ...cookie };\n if (!normalized.path) {\n normalized.path = '/';\n }\n if (!normalized.domain && !normalized.url) {\n return null;\n }\n return normalized;\n })\n .filter(Boolean);\n\n if (cookies.length > 0) {\n await page.context().addCookies(cookies);\n }\n if (Object.keys(localStorage).length > 0) {\n await page.addInitScript((payload) => {\n try {\n Object.entries(payload || {}).forEach(([key, value]) => {\n if (!key) return;\n window.localStorage.setItem(key, String(value ?? ''));\n });\n } catch (error) {\n // no-op\n }\n }, localStorage);\n }\n if (Object.keys(sessionStorage).length > 0) {\n await page.addInitScript((payload) => {\n try {\n Object.entries(payload || {}).forEach(([key, value]) => {\n if (!key) return;\n window.sessionStorage.setItem(key, String(value ?? ''));\n });\n } catch (error) {\n // no-op\n }\n }, sessionStorage);\n }\n },\n\n // captureEnvPatch \u5728\u4EFB\u52A1\u7ED3\u675F\u65F6\u91C7\u96C6\u6700\u65B0\u73AF\u5883\u5FEB\u7167\uFF0C\u7528\u4E8E pushSuccess / pushFailed \u81EA\u52A8\u56DE\u5199\u3002\n async captureEnvPatch(page, source = {}, options = {}) {\n const state = normalizeRuntimeState(source, options?.actor || '');\n const baseline = RuntimeEnv.buildEnvPatch(state) || {};\n if (!page || typeof page.evaluate !== 'function' || typeof page.context !== 'function') {\n return Object.keys(baseline).length > 0 ? baseline : null;\n }\n\n try {\n const rawSnapshot = await captureRawSnapshotFromPage(page);\n const cookieUrls = collectCookieUrlsFromSnapshot(rawSnapshot);\n let cookies = [];\n try {\n cookies = cookieUrls.length > 0\n ? await page.context().cookies(cookieUrls)\n : await page.context().cookies();\n } catch {\n cookies = [];\n }\n const capturedPatch = RuntimeEnv.buildEnvPatchFromSnapshot(\n {\n ...rawSnapshot,\n cookies,\n },\n {\n auth: state.auth,\n browserProfileCore: state.browserProfileCore,\n },\n );\n return RuntimeEnv.mergeEnvPatches(baseline, capturedPatch);\n } catch {\n // ignore\n }\n return Object.keys(baseline).length > 0 ? baseline : null;\n },\n};\n", "import { createInternalLogger } from './logger.js';\n\nconst logger = createInternalLogger('InternalUtils');\n\n/**\n * \u89E3\u6790 Cookie \u5B57\u7B26\u4E32\u4E3A Playwright \u683C\u5F0F\u7684 Cookie \u6570\u7EC4\n * @param {string} cookieString - Cookie \u5B57\u7B26\u4E32\n * @param {string} [domain] - Cookie \u57DF\u540D (\u53EF\u9009)\n * @returns {Array} Cookie \u6570\u7EC4\n */\nexport const parseCookies = (cookieString, domain) => {\n const cookies = [];\n const pairs = cookieString.split(';').map(c => c.trim());\n\n for (const pair of pairs) {\n const [name, ...valueParts] = pair.split('=');\n if (name && valueParts.length > 0) {\n const cookie = {\n name: name.trim(),\n value: valueParts.join('=').trim(),\n path: '/',\n };\n if (domain) {\n cookie.domain = domain;\n }\n cookies.push(cookie);\n }\n }\n logger.success('parseCookies', `parsed ${cookies.length} cookies`);\n return cookies;\n};\n", "import { parseCookies as internalParseCookies } from './internals/utils.js';\n\nexport const Utils = {\n /**\n * \u89E3\u6790 Cookie \u5B57\u7B26\u4E32\u4E3A Playwright \u683C\u5F0F\u7684 Cookie \u6570\u7EC4\n * @param {string} cookieString - Cookie \u5B57\u7B26\u4E32\n * @param {string} [domain] - Cookie \u57DF\u540D (\u53EF\u9009)\n * @returns {Array} Cookie \u6570\u7EC4\n */\n parseCookies(cookieString, domain) {\n return internalParseCookies(cookieString, domain);\n },\n\n /**\n * \u4ECE\u5B57\u7B26\u4E32\u4E2D\u63D0\u53D6 URL \u94FE\u63A5\n * @param {string} text\n * @param {Object} [options]\n * @param {string} [options.prefix] - \u4EC5\u8FD4\u56DE\u6B64\u524D\u7F00\u5F00\u5934\uFF0C\u4E14\u524D\u7F00\u540E\u81F3\u5C11 1 \u4F4D\u5B57\u7B26\u7684\u94FE\u63A5\n * @returns {string[]}\n */\n parseLinks(text, options = {}) {\n const raw = String(text || '');\n if (!raw) return [];\n\n const opts = options && typeof options === 'object' ? options : {};\n const prefix = String(opts.prefix || '').trim();\n\n const matched = raw.match(/https?:\\/\\/[\\w\\-._~:/?#[\\]@!$&'()*+,;=%]+/g) || [];\n const unique = new Set();\n\n for (const item of matched) {\n const link = String(item || '').trim().replace(/[\"'\u201C\u201D\u2018\u2019>\\].,\uFF0C\u3002\uFF1B;!\uFF01?\uFF1F]+$/, '');\n if (!link || !/^https?:\\/\\//i.test(link)) continue;\n\n if (prefix) {\n if (!link.startsWith(prefix)) continue;\n if (link.length <= prefix.length) continue;\n }\n\n unique.add(link);\n }\n\n return Array.from(unique);\n },\n}\n", "import { createInternalLogger } from './internals/logger';\n\nconst logger = createInternalLogger('AntiCheat');\n\nconst BASE_CONFIG = Object.freeze({\n locale: 'zh-CN',\n acceptLanguage: 'zh-CN,zh;q=0.9',\n timezoneId: 'Asia/Shanghai',\n timezoneOffset: -480,\n geolocation: null,\n});\n\n// \u6700\u5C0F\u5316\u542F\u52A8\u53C2\u6570\uFF0C\u4F9D\u8D56 Crawlee/Playwright \u9ED8\u8BA4\u884C\u4E3A\nconst DEFAULT_LAUNCH_ARGS = [\n // '--disable-blink-features=AutomationControlled', // Crawlee \u53EF\u80FD\u4F1A\u81EA\u52A8\u5904\u7406\uFF0C\u8FC7\u591A\u5E72\u9884\u53CD\u800C\u4F1A\u88AB\u8BC6\u522B\n '--no-sandbox',\n '--disable-setuid-sandbox',\n '--window-position=0,0',\n];\n\nfunction buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0 } = {}) {\n const normalizedBrowserMajorVersion = Number(browserMajorVersion || 0);\n const browserDescriptor = normalizedBrowserMajorVersion > 0\n ? [{ name: 'chrome', minVersion: normalizedBrowserMajorVersion, maxVersion: normalizedBrowserMajorVersion }]\n : [{ name: 'chrome', minVersion: 110 }];\n\n return {\n browsers: browserDescriptor,\n devices: ['desktop'],\n operatingSystems: ['windows', 'macos', 'linux'],\n locales: [locale],\n };\n}\n\nexport const AntiCheat = {\n /**\n * \u83B7\u53D6\u7EDF\u4E00\u7684\u57FA\u7840\u914D\u7F6E\n */\n getBaseConfig() {\n return { ...BASE_CONFIG };\n },\n\n /**\n * \u7528\u4E8E Crawlee fingerprint generator \u7684\u7EDF\u4E00\u914D\u7F6E\uFF08\u684C\u9762\u7AEF\uFF09\u3002\n */\n getFingerprintGeneratorOptions(options = {}) {\n return buildFingerprintOptions(options);\n },\n\n /**\n * \u83B7\u53D6\u57FA\u7840\u542F\u52A8\u53C2\u6570\u3002\n */\n getLaunchArgs(options = {}) {\n const locale = String(options?.locale || BASE_CONFIG.locale).trim() || BASE_CONFIG.locale;\n return [...DEFAULT_LAUNCH_ARGS, `--lang=${locale}`];\n },\n\n /**\n * \u4E3A got-scraping \u751F\u6210\u4E0E\u6D4F\u89C8\u5668\u4E00\u81F4\u7684 TLS \u6307\u7EB9\u914D\u7F6E\uFF08\u684C\u9762\u7AEF\uFF09\u3002\n */\n getTlsFingerprintOptions(userAgent = '', acceptLanguage = '') {\n // \u7B80\u5316\u903B\u8F91\uFF0C\u4E0D\u518D\u89E3\u6790 acceptLanguage\uFF0C\u4EC5\u63D0\u4F9B\u57FA\u7840\u6307\u7EB9\u914D\u7F6E\n return buildFingerprintOptions();\n },\n\n /**\n * \u89C4\u8303\u5316\u8BF7\u6C42\u5934\n */\n applyLocaleHeaders(headers, acceptLanguage = '') {\n if (!headers['accept-language']) {\n headers['accept-language'] = acceptLanguage || BASE_CONFIG.acceptLanguage;\n }\n return headers;\n },\n};\n", "import delay from 'delay';\nimport { createCursor } from 'ghost-cursor-playwright';\nimport { createInternalLogger } from './internals/logger.js';\n\nconst logger = createInternalLogger('Humanize');\n\n// \u5185\u90E8 cursor \u5B9E\u4F8B\u7F13\u5B58 (\u6BCF\u4E2A page \u4E00\u4E2A) - \u4E0D\u5BF9\u5916\u66B4\u9732\nconst $CursorWeakMap = new WeakMap();\n\n/**\n * \u5185\u90E8\u65B9\u6CD5\uFF1A\u83B7\u53D6\u9875\u9762\u7684 cursor\uFF0C\u5982\u679C\u4E0D\u5B58\u5728\u5219\u629B\u51FA\u9519\u8BEF\n */\nfunction $GetCursor(page) {\n const cursor = $CursorWeakMap.get(page);\n if (!cursor) {\n throw new Error('Cursor \u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8C03\u7528 Humanize.initializeCursor(page)');\n }\n return cursor;\n}\n\nexport const Humanize = {\n /**\n * \u751F\u6210\u5E26\u6296\u52A8\u7684\u6BEB\u79D2\u6570 - \u57FA\u4E8E\u57FA\u7840\u503C\u6DFB\u52A0\u968F\u673A\u6D6E\u52A8 (\u00B130% \u9ED8\u8BA4)\n * @param {number} base - \u57FA\u7840\u5EF6\u8FDF (ms)\n * @param {number} [jitterPercent=0.3] - \u6296\u52A8\u767E\u5206\u6BD4 (0.3 = \u00B130%)\n * @returns {number} \u6296\u52A8\u540E\u7684\u6BEB\u79D2\u6570\n */\n jitterMs(base, jitterPercent = 0.3) {\n const jitter = base * jitterPercent * (Math.random() * 2 - 1);\n return Math.max(10, Math.round(base + jitter));\n },\n\n /**\n * \u521D\u59CB\u5316\u9875\u9762\u7684 Ghost Cursor\uFF08\u5FC5\u987B\u5728\u4F7F\u7528\u5176\u4ED6 cursor \u76F8\u5173\u65B9\u6CD5\u524D\u8C03\u7528\uFF09\n * \n * @param {import('playwright').Page} page\n * @returns {Promise<void>}\n */\n async initializeCursor(page) {\n if ($CursorWeakMap.has(page)) {\n logger.debug('initializeCursor: cursor already exists, skipping');\n return;\n }\n logger.start('initializeCursor', 'creating cursor');\n const cursor = await createCursor(page);\n $CursorWeakMap.set(page, cursor);\n logger.success('initializeCursor', 'cursor initialized');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u9F20\u6807\u79FB\u52A8 - \u4F7F\u7528 ghost-cursor \u79FB\u52A8\u5230\u6307\u5B9A\u4F4D\u7F6E\u6216\u5143\u7D20\n * \n * @param {import('playwright').Page} page\n * @param {string|{x: number, y: number}|import('playwright').ElementHandle} target - CSS\u9009\u62E9\u5668\u3001\u5750\u6807\u5BF9\u8C61\u6216\u5143\u7D20\u53E5\u67C4\n */\n async humanMove(page, target) {\n const cursor = $GetCursor(page);\n logger.start('humanMove', `target=${typeof target === 'string' ? target : 'element/coords'}`);\n try {\n if (typeof target === 'string') {\n // CSS \u9009\u62E9\u5668\n const element = await page.$(target);\n if (!element) {\n logger.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);\n return false;\n }\n const box = await element.boundingBox();\n if (!box) {\n logger.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);\n return false;\n }\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n } else if (target && typeof target.x === 'number' && typeof target.y === 'number') {\n // \u5750\u6807\u5BF9\u8C61\n await cursor.actions.move(target);\n } else if (target && typeof target.boundingBox === 'function') {\n // ElementHandle\n const box = await target.boundingBox();\n if (box) {\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n }\n }\n logger.success('humanMove');\n return true;\n } catch (error) {\n logger.fail('humanMove', error);\n throw error;\n }\n },\n\n /**\n * \u6E10\u8FDB\u5F0F\u6EDA\u52A8\u5230\u5143\u7D20\u53EF\u89C1\uFF08\u4EC5\u5904\u7406 Y \u8F74\u6EDA\u52A8\uFF09\n * \u8FD4\u56DE restore \u65B9\u6CD5\uFF0C\u7528\u4E8E\u5C06\u6EDA\u52A8\u5BB9\u5668\u6062\u590D\u5230\u539F\u4F4D\u7F6E\n * \n * @param {import('playwright').Page} page\n * @param {string|import('playwright').ElementHandle} target - CSS \u9009\u62E9\u5668\u6216\u5143\u7D20\u53E5\u67C4\n * @param {Object} [options]\n * @param {number} [options.maxSteps=14] - \u6700\u5927\u6EDA\u52A8\u6B65\u6570\n * @param {number} [options.minStep=260] - \u5355\u6B21\u6EDA\u52A8\u6700\u5C0F\u6B65\u957F\n * @param {number} [options.maxStep=800] - \u5355\u6B21\u6EDA\u52A8\u6700\u5927\u6B65\u957F\n * @param {number} [options.maxDurationMs] - \u6700\u957F\u8017\u65F6\u4E0A\u9650 (\u9ED8\u8BA4\u968F maxSteps \u4F30\u7B97)\n */\n async humanScroll(page, target, options = {}) {\n const {\n maxSteps = 14,\n minStep = 260,\n maxStep = 800,\n maxDurationMs = maxSteps * 220 + 800\n } = options;\n const targetDesc = typeof target === 'string' ? target : 'ElementHandle';\n\n logger.start('humanScroll', `target=${targetDesc}`);\n\n let element;\n if (typeof target === 'string') {\n element = await page.$(target);\n if (!element) {\n logger.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);\n return { element: null, didScroll: false };\n }\n } else {\n element = target;\n }\n\n const cursor = $GetCursor(page);\n let didScroll = false;\n\n // \u8F85\u52A9\u51FD\u6570\uFF1A\u68C0\u67E5\u53EF\u89C1\u6027\u548C\u906E\u6321\n const checkVisibility = async () => {\n return await element.evaluate((el) => {\n const rect = el.getBoundingClientRect();\n if (!rect || rect.width === 0 || rect.height === 0) {\n return { code: 'ZERO_DIMENSIONS', reason: '\u5C3A\u5BF8\u4E3A\u96F6' };\n }\n\n const cx = rect.left + rect.width / 2;\n const cy = rect.top + rect.height / 2;\n const viewH = window.innerHeight;\n const viewW = window.innerWidth;\n let isFixed = false;\n\n for (let node = el; node && node !== document.body; node = node.parentElement) {\n const style = window.getComputedStyle(node);\n if (style && style.position === 'fixed') {\n isFixed = true;\n break;\n }\n }\n\n // 1. \u68C0\u67E5\u662F\u5426\u5728\u51E0\u4F55\u89C6\u53E3\u5185\n if (cy < 0 || cy > viewH || cx < 0 || cx > viewW) {\n // \u8BA1\u7B97\u6240\u9700\u65B9\u5411\n const direction = cy < 0 ? 'up' : (cy > viewH ? 'down' : 'unknown');\n return { code: 'OUT_OF_VIEWPORT', reason: '\u4E0D\u5728\u89C6\u53E3\u5185', direction, cy, viewH, isFixed };\n }\n\n // 2. \u68C0\u67E5\u906E\u6321\n const pointElement = document.elementFromPoint(cx, cy);\n if (pointElement && !el.contains(pointElement) && !pointElement.contains(el)) {\n return {\n code: 'OBSTRUCTED',\n reason: '\u88AB\u906E\u6321',\n obstruction: {\n tag: pointElement.tagName,\n id: pointElement.id,\n className: pointElement.className\n },\n cy, // Return Center Y for smart direction calculation\n viewH,\n isFixed\n };\n }\n\n return { code: 'VISIBLE', isFixed };\n });\n };\n\n const getScrollableRect = async () => {\n return await element.evaluate((el) => {\n const isScrollable = (node) => {\n const style = window.getComputedStyle(node);\n if (!style) return false;\n const overflowY = style.overflowY;\n if (!['auto', 'scroll', 'overlay'].includes(overflowY)) return false;\n return node.scrollHeight > node.clientHeight + 1;\n };\n\n let current = el;\n while (current && current !== document.body) {\n if (isScrollable(current)) {\n const rect = current.getBoundingClientRect();\n if (rect && rect.width > 0 && rect.height > 0) {\n return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };\n }\n }\n current = current.parentElement;\n }\n\n return null;\n });\n };\n\n const startTime = Date.now();\n\n try {\n for (let i = 0; i < maxSteps; i++) {\n if (Date.now() - startTime > maxDurationMs) {\n logger.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);\n return { element, didScroll };\n }\n\n const status = await checkVisibility();\n\n if (status.code === 'VISIBLE') {\n if (status.isFixed) {\n logger.info('humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8');\n } else {\n logger.debug('humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321');\n }\n logger.success('humanScroll', didScroll ? '\u5DF2\u6EDA\u52A8' : '\u65E0\u9700\u6EDA\u52A8');\n return { element, didScroll };\n }\n\n logger.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ''}`);\n\n if (status.code === 'OBSTRUCTED' && status.obstruction) {\n logger.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id=\"${status.obstruction.id}\">`);\n }\n\n const scrollRect = await getScrollableRect();\n if (!scrollRect && status.isFixed) {\n logger.warn('humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8');\n return { element, didScroll };\n }\n\n const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;\n const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;\n\n // \u786E\u5B9A\u6EDA\u52A8\u65B9\u5411\u548C\u8DDD\u79BB\n let deltaY = 0;\n if (status.code === 'OUT_OF_VIEWPORT') {\n if (status.direction === 'down') {\n deltaY = stepMin + Math.random() * (stepMax - stepMin);\n } else if (status.direction === 'up') {\n deltaY = -(stepMin + Math.random() * (stepMax - stepMin));\n } else {\n // \u6C34\u5E73\u95EE\u9898\u6216\u5947\u602A\u72B6\u6001\uFF0C\u5C1D\u8BD5\u5411\u4E0B\u6EDA\u52A8\u4E00\u70B9\n deltaY = 100;\n }\n } else if (status.code === 'OBSTRUCTED') {\n // \u667A\u80FD\u907F\u8BA9\u906E\u6321\n // \u5982\u679C\u5143\u7D20\u5728\u89C6\u53E3\u4E0B\u534A\u90E8\u5206\u88AB\u906E\u6321\uFF0C\u901A\u5E38\u662F\u88AB\u5E95\u90E8\u56FA\u5B9A\u5143\u7D20\uFF08\u5982 Footer\uFF09\u906E\u6321 -> \u9700\u8981\u5411\u4E0B\u6EDA\u52A8\u66F4\u591A\uFF08\u5185\u5BB9\u4E0A\u79FB\uFF09\n // \u5982\u679C\u5143\u7D20\u5728\u89C6\u53E3\u4E0A\u534A\u90E8\u5206\u88AB\u906E\u6321\uFF0C\u901A\u5E38\u662F\u88AB\u9876\u90E8\u56FA\u5B9A\u5143\u7D20\uFF08\u5982 Header\uFF09\u906E\u6321 -> \u9700\u8981\u5411\u4E0A\u6EDA\u52A8\u66F4\u591A\uFF08\u5185\u5BB9\u4E0B\u79FB\uFF09\n const halfY = scrollRect ? (scrollRect.y + scrollRect.height / 2) : (status.viewH / 2);\n const isBottomHalf = status.cy > halfY;\n const direction = isBottomHalf ? 1 : -1;\n\n // \u57FA\u7840\u6EDA\u52A8\u91CF + \u968F\u673A\u6CE2\u52A8\n deltaY = direction * (stepMin + Math.random() * 50);\n }\n\n // \u5C06\u9F20\u6807\u79FB\u52A8\u5230\u53EF\u6EDA\u52A8\u5BB9\u5668\uFF08\u4F18\u5148\uFF09\uFF0C\u5426\u5219\u79FB\u52A8\u5230\u89C6\u53E3\u4E2D\u5FC3\n if (i === 0) {\n const viewSize = page.viewportSize();\n if (scrollRect) {\n const safeX = scrollRect.x + scrollRect.width * 0.5 + (Math.random() - 0.5) * Math.min(80, scrollRect.width * 0.4);\n const safeY = scrollRect.y + scrollRect.height * 0.5 + (Math.random() - 0.5) * Math.min(80, scrollRect.height * 0.4);\n await cursor.actions.move({ x: safeX, y: safeY });\n } else if (viewSize) {\n const safeX = viewSize.width * 0.5 + (Math.random() - 0.5) * 80;\n const safeY = viewSize.height * 0.5 + (Math.random() - 0.5) * 80;\n await cursor.actions.move({ x: safeX, y: safeY });\n }\n }\n\n // \u6267\u884C\u6EDA\u52A8\n await page.mouse.wheel(0, deltaY);\n didScroll = true;\n\n // \u7B49\u5F85\u6EDA\u52A8\u7A33\u5B9A - \u7D27\u51D1\u8282\u594F (20ms - 60ms)\n await delay(this.jitterMs(20 + Math.random() * 40, 0.2));\n }\n\n logger.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);\n return { element, didScroll };\n\n } catch (error) {\n logger.fail('humanScroll', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u70B9\u51FB - \u4F7F\u7528 ghost-cursor \u6A21\u62DF\u4EBA\u7C7B\u9F20\u6807\u79FB\u52A8\u8F68\u8FF9\u5E76\u70B9\u51FB\n * \n * @param {import('playwright').Page} page\n * @param {string|import('playwright').ElementHandle} [target] - CSS \u9009\u62E9\u5668\u6216\u5143\u7D20\u53E5\u67C4\u3002\u5982\u679C\u4E3A\u7A7A\uFF0C\u5219\u70B9\u51FB\u5F53\u524D\u9F20\u6807\u4F4D\u7F6E\n * @param {Object} [options]\n * @param {number} [options.reactionDelay=250] - \u53CD\u5E94\u5EF6\u8FDF\u57FA\u7840\u503C (ms)\uFF0C\u5B9E\u9645 \u00B130% \u6296\u52A8\n * @param {boolean} [options.throwOnMissing=true] - \u5143\u7D20\u4E0D\u5B58\u5728\u65F6\u662F\u5426\u629B\u51FA\u9519\u8BEF\n * @param {boolean} [options.scrollIfNeeded=true] - \u5143\u7D20\u4E0D\u5728\u89C6\u53E3\u65F6\u662F\u5426\u81EA\u52A8\u6EDA\u52A8\n */\n async humanClick(page, target, options = {}) {\n const cursor = $GetCursor(page);\n\n // \u589E\u52A0 restore \u9009\u9879\uFF0C\u9ED8\u8BA4 false (\u4E0D\u8FD8\u539F\u6EDA\u52A8\u4F4D\u7F6E)\n const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;\n\n const targetDesc = target == null ? 'Current Position' : (typeof target === 'string' ? target : 'ElementHandle');\n logger.start('humanClick', `target=${targetDesc}`);\n\n\n const restoreOnce = async () => {\n if (restoreOnce.restored) return;\n restoreOnce.restored = true;\n\n if (typeof restoreOnce.do !== 'function') return;\n try {\n await delay(this.jitterMs(1000));\n await restoreOnce.do();\n } catch (restoreError) {\n logger.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);\n }\n };\n\n\n try {\n // Case 1: \u70B9\u51FB\u5F53\u524D\u4F4D\u7F6E (target \u4E3A null/undefined)\n if (target == null) {\n // \u4EC5\u6267\u884C\u53CD\u5E94\u5EF6\u8FDF + \u70B9\u51FB\n await delay(this.jitterMs(reactionDelay, 0.4));\n await cursor.actions.click();\n logger.success('humanClick', 'Clicked current position');\n return true;\n }\n\n // Case 2: \u70B9\u51FB\u6307\u5B9A\u76EE\u6807\n let element;\n if (typeof target === 'string') {\n element = await page.$(target);\n if (!element) {\n if (throwOnMissing) {\n throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);\n }\n logger.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);\n return false;\n }\n } else {\n element = target;\n }\n\n if (scrollIfNeeded) {\n const { restore: restoreFn, didScroll } = await this.humanScroll(page, element);\n // \u4EC5\u5728 didScroll \u4E3A true \u4E14 options.restore \u4E3A true \u65F6\u624D\u8FD8\u539F\n restoreOnce.do = (didScroll && restore) ? restoreFn : null;\n }\n\n const box = await element.boundingBox();\n if (!box) {\n await restoreOnce();\n if (throwOnMissing) {\n throw new Error('\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E');\n }\n logger.warn('humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB');\n return false;\n }\n\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;\n\n await cursor.actions.move({ x, y });\n await delay(this.jitterMs(reactionDelay, 0.4));\n await cursor.actions.click();\n\n await restoreOnce();\n\n logger.success('humanClick');\n return true;\n } catch (error) {\n await restoreOnce();\n logger.fail('humanClick', error);\n throw error;\n }\n },\n\n /**\n * \u968F\u673A\u5EF6\u8FDF\u4E00\u6BB5\u6BEB\u79D2\u6570\uFF08\u5E26 \u00B130% \u6296\u52A8\uFF09\n * @param {number} baseMs - \u57FA\u7840\u5EF6\u8FDF\u6BEB\u79D2\u6570\n * @param {number} [jitterPercent=0.3] - \u6296\u52A8\u767E\u5206\u6BD4\n */\n async randomSleep(baseMs, jitterPercent = 0.3) {\n const ms = this.jitterMs(baseMs, jitterPercent);\n logger.start('randomSleep', `base=${baseMs}, actual=${ms}ms`);\n await delay(ms);\n logger.success('randomSleep');\n },\n\n /**\n * \u6A21\u62DF\u4EBA\u7C7B\"\u6CE8\u89C6\"\u6216\"\u9605\u8BFB\"\u884C\u4E3A\uFF1A\u9F20\u6807\u5728\u9875\u9762\u4E0A\u968F\u673A\u5FAE\u52A8\n * @param {import('playwright').Page} page\n * @param {number} [baseDurationMs=2500] - \u57FA\u7840\u6301\u7EED\u65F6\u95F4 (\u00B140% \u6296\u52A8)\n */\n async simulateGaze(page, baseDurationMs = 2500) {\n const cursor = $GetCursor(page);\n const durationMs = this.jitterMs(baseDurationMs, 0.4);\n logger.start('simulateGaze', `duration=${durationMs}ms`);\n const startTime = Date.now();\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\n\n while (Date.now() - startTime < durationMs) {\n // \u5728\u89C6\u53E3\u8303\u56F4\u5185\u968F\u673A\u79FB\u52A8\n const x = 100 + Math.random() * (viewportSize.width - 200);\n const y = 100 + Math.random() * (viewportSize.height - 200);\n await cursor.actions.move({ x, y });\n // \u6CE8\u89C6\u505C\u7559 300-1200ms\n await delay(this.jitterMs(600, 0.5));\n }\n logger.success('simulateGaze');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u8F93\u5165 - \u5E26\u8282\u594F\u53D8\u5316\uFF08\u5FEB-\u6162-\u505C\u987F-\u5076\u5C14\u52A0\u901F\uFF09\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n * @param {string} text - \u8981\u8F93\u5165\u7684\u6587\u672C\n * @param {Object} [options] \n * @param {number} [options.baseDelay=180] - \u57FA\u7840\u6309\u952E\u5EF6\u8FDF (ms)\uFF0C\u5B9E\u9645 \u00B140% \u6296\u52A8\n * @param {number} [options.pauseProbability=0.08] - \u505C\u987F\u6982\u7387 (0-1)\n * @param {number} [options.pauseBase=800] - \u505C\u987F\u65F6\u957F\u57FA\u7840\u503C (ms)\uFF0C\u5B9E\u9645 \u00B150% \u6296\u52A8\n */\n async humanType(page, selector, text, options = {}) {\n logger.start('humanType', `selector=${selector}, textLen=${text.length}`);\n const {\n baseDelay = 180,\n pauseProbability = 0.08,\n pauseBase = 800\n } = options;\n\n try {\n const locator = page.locator(selector);\n await Humanize.humanClick(page, locator);\n\n // \u70B9\u51FB\u540E\u601D\u8003\u5EF6\u8FDF\n await delay(this.jitterMs(200, 0.4));\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n let charDelay;\n\n if (char === ' ') {\n // \u7A7A\u683C\u952E\u7A0D\u5FEB\n charDelay = this.jitterMs(baseDelay * 0.6, 0.3);\n } else if (/[,.!?;:\uFF0C\u3002\uFF01\uFF1F\uFF1B\uFF1A]/.test(char)) {\n // \u6807\u70B9\u7B26\u53F7\u540E\u7A0D\u6162\uFF08\u6A21\u62DF\u601D\u8003\uFF09\n charDelay = this.jitterMs(baseDelay * 1.5, 0.4);\n } else {\n // \u666E\u901A\u5B57\u7B26\n charDelay = this.jitterMs(baseDelay, 0.4);\n }\n\n await page.keyboard.type(char);\n await delay(charDelay);\n\n // \u968F\u673A\u505C\u987F\uFF08\u6A21\u62DF\u601D\u8003/\u56DE\u987E\uFF09\n if (Math.random() < pauseProbability && i < text.length - 1) {\n const pauseTime = this.jitterMs(pauseBase, 0.5);\n logger.debug(`\u505C\u987F ${pauseTime}ms...`);\n await delay(pauseTime);\n }\n }\n logger.success('humanType');\n } catch (error) {\n logger.fail('humanType', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u6E05\u7A7A\u8F93\u5165\u6846 - \u6A21\u62DF\u4EBA\u7C7B\u5220\u9664\u6587\u672C\u7684\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n */\n async humanClear(page, selector) {\n logger.start('humanClear', `selector=${selector}`);\n try {\n const locator = page.locator(selector);\n await locator.click();\n await delay(this.jitterMs(200, 0.4));\n\n const currentValue = await locator.inputValue();\n if (!currentValue || currentValue.length === 0) {\n logger.success('humanClear', 'already empty');\n return;\n }\n\n // \u5168\u9009 + \u5220\u9664\n await page.keyboard.press('Meta+A');\n await delay(this.jitterMs(100, 0.4));\n await page.keyboard.press('Backspace');\n\n logger.success('humanClear');\n } catch (error) {\n logger.fail('humanClear', error);\n throw error;\n }\n },\n\n /**\n * \u9875\u9762\u9884\u70ED\u6D4F\u89C8 - \u6A21\u62DF\u4EBA\u7C7B\u8FDB\u5165\u9875\u9762\u540E\u7684\u63A2\u7D22\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {number} [baseDuration=3500] - \u9884\u70ED\u65F6\u957F\u57FA\u7840\u503C (\u00B140% \u6296\u52A8)\n */\n async warmUpBrowsing(page, baseDuration = 3500) {\n const cursor = $GetCursor(page);\n const durationMs = this.jitterMs(baseDuration, 0.4);\n\n logger.start('warmUpBrowsing', `duration=${durationMs}ms`);\n const startTime = Date.now();\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\n\n try {\n while (Date.now() - startTime < durationMs) {\n const action = Math.random();\n\n if (action < 0.4) {\n // \u9F20\u6807\u79FB\u52A8\n const x = 100 + Math.random() * (viewportSize.width - 200);\n const y = 100 + Math.random() * (viewportSize.height - 200);\n await cursor.actions.move({ x, y });\n await delay(this.jitterMs(350, 0.4));\n } else if (action < 0.7) {\n // \u6EDA\u52A8\n const scrollY = (Math.random() - 0.5) * 200;\n await page.mouse.wheel(0, scrollY);\n await delay(this.jitterMs(500, 0.4));\n } else {\n // \u505C\u987F/\u6CE8\u89C6\n await delay(this.jitterMs(800, 0.5));\n }\n }\n logger.success('warmUpBrowsing');\n } catch (error) {\n logger.fail('warmUpBrowsing', error);\n throw error;\n }\n },\n\n /**\n * \u81EA\u7136\u6EDA\u52A8 - \u5E26\u60EF\u6027\u3001\u51CF\u901F\u6548\u679C\u548C\u968F\u673A\u6296\u52A8\n * @param {import('playwright').Page} page\n * @param {'up' | 'down'} [direction='down'] - \u6EDA\u52A8\u65B9\u5411\n * @param {number} [distance=300] - \u603B\u6EDA\u52A8\u8DDD\u79BB\u57FA\u7840\u503C (px)\uFF0C\u00B115% \u6296\u52A8\n * @param {number} [baseSteps=5] - \u5206\u51E0\u6B65\u5B8C\u6210\u57FA\u7840\u503C\uFF0C\u00B11 \u968F\u673A\n */\n async naturalScroll(page, direction = 'down', distance = 300, baseSteps = 5) {\n // steps \u52A0\u968F\u673A\u6D6E\u52A8 \u00B11\n const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);\n // distance \u52A0\u6296\u52A8\n const actualDistance = this.jitterMs(distance, 0.15);\n\n logger.start('naturalScroll', `dir=${direction}, dist=${actualDistance}, steps=${steps}`);\n const sign = direction === 'down' ? 1 : -1;\n const stepDistance = actualDistance / steps;\n\n try {\n for (let i = 0; i < steps; i++) {\n // \u60EF\u6027\u51CF\u901F\u56E0\u5B50\n const factor = 1 - (i / steps) * 0.5;\n // \u6BCF\u6B65\u52A0 \u00B110% \u6296\u52A8\n const jitter = 0.9 + Math.random() * 0.2;\n const scrollAmount = stepDistance * factor * sign * jitter;\n\n await page.mouse.wheel(0, scrollAmount);\n\n // \u5EF6\u8FDF\u4E5F\u5E26\u6296\u52A8\n const baseDelay = 60 + i * 25;\n await delay(this.jitterMs(baseDelay, 0.3));\n }\n logger.success('naturalScroll');\n } catch (error) {\n logger.fail('naturalScroll', error);\n throw error;\n }\n }\n}\n", "// \u96C6\u4E2D\u7BA1\u7406\u542F\u52A8\u914D\u7F6E\uFF0C\u53CD\u722C\u53C2\u6570\u4E0E\u6307\u7EB9\u914D\u7F6E\u7EDF\u4E00\u7531 AntiCheat \u63D0\u4F9B\nimport { execFileSync } from 'node:child_process';\nimport { FingerprintGenerator } from 'fingerprint-generator';\nimport { FingerprintInjector } from 'fingerprint-injector';\nimport { AntiCheat } from './anti-cheat';\nimport { createInternalLogger } from './internals/logger';\nimport { ByPass } from './proxy-bypass';\nimport { ProxyMeterRuntime } from './internals/proxy-meter-runtime';\nimport { RuntimeEnv } from './runtime-env';\n\nconst logger = createInternalLogger('Launch');\nconst REQUEST_HOOK_FLAG = Symbol('playwright-toolkit-request-hook');\nconst injectedContexts = new WeakSet();\nconst browserMajorVersionCache = new Map();\n\nconst DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION = 1;\nconst DEFAULT_LOCALE = 'zh-CN';\n\nconst DEFAULT_CRAWLER_BASE_OPTIONS = Object.freeze({\n maxConcurrency: 1,\n maxRequestRetries: 0,\n requestHandlerTimeoutSecs: 240,\n navigationTimeoutSecs: 120,\n});\n\nconst fingerprintInjector = new FingerprintInjector();\n\nconst resolveProxyLaunchOptions = (proxyConfiguration = {}) => {\n const config = proxyConfiguration && typeof proxyConfiguration === 'object' && !Array.isArray(proxyConfiguration)\n ? proxyConfiguration\n : {};\n\n const proxyUrl = String(config.proxy_url || '').trim();\n const enableProxy = typeof config.enable_proxy === 'boolean' ? config.enable_proxy : proxyUrl !== '';\n\n if (!enableProxy || !proxyUrl) {\n return { byPassDomains: [], enableProxy, proxyUrl };\n }\n const byPassDomains = ByPass.normalizeByPassDomains(config.by_pass_domains);\n return { byPassDomains, enableProxy, proxyUrl };\n};\n\nconst parseChromeMajorVersion = (rawValue = '') => {\n const match = String(rawValue || '').match(/Chrome\\/(\\d+)/i);\n return match ? Number(match[1] || 0) : 0;\n};\n\nconst resolveLauncherExecutablePath = (launcher) => {\n if (!launcher || typeof launcher !== 'object') return '';\n if (typeof launcher.executablePath === 'function') {\n try {\n return String(launcher.executablePath() || '').trim();\n } catch {\n return '';\n }\n }\n return '';\n};\n\nconst detectBrowserMajorVersion = (launcher) => {\n\tconst executablePath = resolveLauncherExecutablePath(launcher);\n if (!executablePath) return 0;\n if (browserMajorVersionCache.has(executablePath)) {\n return browserMajorVersionCache.get(executablePath);\n }\n\n let detectedVersion = 0;\n try {\n const rawVersion = execFileSync(executablePath, ['--version'], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n detectedVersion = parseChromeMajorVersion(rawVersion);\n } catch (error) {\n logger.warn(`\u8BFB\u53D6\u6D4F\u89C8\u5668\u7248\u672C\u5931\u8D25: ${error?.message || error}`);\n }\n\n\tbrowserMajorVersionCache.set(executablePath, detectedVersion);\n\treturn detectedVersion;\n};\n\n// buildFingerprintGenerator \u53EA\u5728\u201C\u6CA1\u6709\u53EF\u590D\u7528 core.fingerprint\u201D\u65F6\u515C\u5E95\u751F\u6210\u4E00\u6B21\u3002\nconst buildFingerprintGenerator = ({ locale, browserMajorVersion }) => {\n\treturn new FingerprintGenerator(\n AntiCheat.getFingerprintGeneratorOptions({\n locale,\n browserMajorVersion,\n }),\n\t);\n};\n\n// buildReplayableBrowserProfile \u8D1F\u8D23\u628A\u201C\u767B\u5F55\u6001 env\u201D\u63D0\u5347\u6210\u201C\u53EF\u8DE8\u673A\u5668\u590D\u7528\u7684\u6D4F\u89C8\u5668\u771F\u6E90\u201D\u3002\n// \u89C4\u5219\u662F\uFF1A\n// 1. \u6CA1\u6709\u767B\u5F55\u6001\u65F6\uFF0C\u4E0D\u5F3A\u6C42\u751F\u6210\u6301\u4E45\u5316\u6307\u7EB9\uFF1B\n// 2. \u6709\u767B\u5F55\u6001\u4F46\u6CA1\u6709 core.fingerprint \u65F6\uFF0C\u9996\u6B21\u751F\u6210\u5E76\u5199\u56DE runtimeState\uFF1B\n// 3. \u6D4F\u89C8\u5668\u5927\u7248\u672C\u53D8\u5316\u65F6\uFF0C\u5141\u8BB8\u91CD\u5EFA core\uFF0C\u907F\u514D\u65E7\u6307\u7EB9\u4E0E\u65B0\u5185\u6838\u4E0D\u517C\u5BB9\u3002\nconst buildReplayableBrowserProfile = (runtimeState, launcher) => {\n if (!runtimeState || !RuntimeEnv.hasLoginState(runtimeState)) {\n return { runtimeState, browserProfileCore: null };\n }\n\n let nextState = RuntimeEnv.rememberState(runtimeState);\n let browserProfileCore = RuntimeEnv.getBrowserProfileCore(nextState);\n const timezoneId = String(browserProfileCore?.timezone_id || '').trim() || AntiCheat.getBaseConfig().timezoneId;\n const locale = DEFAULT_LOCALE;\n const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);\n const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);\n const needsRebuild = !browserProfileCore?.fingerprint\n || Object.keys(browserProfileCore.fingerprint || {}).length === 0\n || (currentBrowserMajorVersion > 0 && storedBrowserMajorVersion > 0 && storedBrowserMajorVersion !== currentBrowserMajorVersion);\n\n if (needsRebuild) {\n const generator = buildFingerprintGenerator({\n locale,\n browserMajorVersion: currentBrowserMajorVersion,\n });\n const fingerprint = generator.getFingerprint();\n const fingerprintBrowserMajorVersion = parseChromeMajorVersion(fingerprint?.fingerprint?.navigator?.userAgent || '');\n browserProfileCore = {\n fingerprint,\n timezone_id: timezoneId,\n locale,\n browser_major_version: currentBrowserMajorVersion > 0 ? currentBrowserMajorVersion : fingerprintBrowserMajorVersion,\n schema_version: DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION,\n };\n nextState = RuntimeEnv.setBrowserProfileCore(nextState, browserProfileCore);\n logger.info(\n `\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || '-')} | version=${browserProfileCore.browser_major_version || '-'} | timezone=${timezoneId}`,\n );\n return { runtimeState: nextState, browserProfileCore };\n }\n\n const normalizedBrowserProfileCore = {\n ...browserProfileCore,\n timezone_id: timezoneId,\n locale,\n schema_version: Number(browserProfileCore.schema_version || 0) > 0\n ? Number(browserProfileCore.schema_version || 0)\n : DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION,\n browser_major_version: currentBrowserMajorVersion > 0\n ? currentBrowserMajorVersion\n : Number(browserProfileCore.browser_major_version || 0),\n };\n\n const currentCoreRaw = JSON.stringify(browserProfileCore || {});\n const nextCoreRaw = JSON.stringify(normalizedBrowserProfileCore);\n if (currentCoreRaw !== nextCoreRaw) {\n nextState = RuntimeEnv.setBrowserProfileCore(nextState, normalizedBrowserProfileCore);\n }\n\n return {\n runtimeState: nextState,\n browserProfileCore: normalizedBrowserProfileCore,\n\t};\n};\n\n// buildReplayBrowserPoolOptions \u8BA9 BrowserPool / Playwright / FingerprintInjector\n// \u90FD\u4ECE\u540C\u4E00\u4EFD core.fingerprint \u6D3E\u751F\u53C2\u6570\uFF0C\u907F\u514D UA / viewport / JS \u6307\u7EB9\u591A\u771F\u6E90\u51B2\u7A81\u3002\nconst buildReplayBrowserPoolOptions = (browserProfileCore) => {\n const fingerprintWithHeaders = browserProfileCore?.fingerprint;\n const fingerprint = fingerprintWithHeaders?.fingerprint;\n if (!fingerprintWithHeaders || !fingerprint) {\n return null;\n }\n\n return {\n useFingerprints: false,\n prePageCreateHooks: [\n (_pageId, _browserController, pageOptions = {}) => {\n if (!pageOptions || typeof pageOptions !== 'object') return;\n\n const screen = fingerprint.screen || {};\n const userAgent = String(fingerprint.navigator?.userAgent || '').trim();\n if (userAgent) {\n pageOptions.userAgent = userAgent;\n }\n if (Number(screen.width || 0) > 0 && Number(screen.height || 0) > 0) {\n pageOptions.viewport = {\n width: Number(screen.width),\n height: Number(screen.height),\n };\n pageOptions.screen = {\n width: Number(screen.width),\n height: Number(screen.height),\n };\n }\n if (browserProfileCore.locale) {\n pageOptions.locale = browserProfileCore.locale;\n }\n if (browserProfileCore.timezone_id) {\n pageOptions.timezoneId = browserProfileCore.timezone_id;\n }\n },\n ],\n postPageCreateHooks: [\n async (page) => {\n const context = page?.context?.();\n if (!context) return;\n if (!injectedContexts.has(context)) {\n await fingerprintInjector.attachFingerprintToPlaywright(context, fingerprintWithHeaders);\n injectedContexts.add(context);\n }\n },\n ],\n };\n};\n\nexport const Launch = {\n getPlaywrightCrawlerOptions(options = {}) {\n const normalizedOptions = Array.isArray(options) ? { customArgs: options } : (options || {});\n const {\n customArgs = [],\n proxyConfiguration = {},\n log: logOptions = null,\n runInHeadfulMode = false,\n debugMode = false,\n isRunningOnApify = false,\n launcher = null,\n preNavigationHooks = [],\n postNavigationHooks = [],\n runtimeState = null,\n } = normalizedOptions;\n\n const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);\n const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);\n const proxyMeter = enableProxy && proxyUrl\n ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode })\n : null;\n const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;\n if (launchProxy && byPassDomains.length > 0) {\n launchProxy.bypass = byPassDomains.join(',');\n }\n\n\t\t// \u542F\u52A8\u524D\u5148\u786E\u5B9A\u662F\u5426\u8D70\u201C\u7A33\u5B9A\u56DE\u653E\u6A21\u5F0F\u201D\u3002\n\t\tconst replayContext = buildReplayableBrowserProfile(runtimeState, launcher);\n\t\tconst replayBrowserPoolOptions = buildReplayBrowserPoolOptions(replayContext.browserProfileCore);\n\t\tconst launchLocale = String(replayContext.browserProfileCore?.locale || DEFAULT_LOCALE).trim() || DEFAULT_LOCALE;\n\n const launchOptions = {\n args: [\n ...AntiCheat.getLaunchArgs({ locale: launchLocale }),\n ...customArgs,\n ],\n ignoreDefaultArgs: ['--enable-automation'],\n };\n\n if (launchProxy) {\n launchOptions.proxy = launchProxy;\n }\n\n const enableByPassLogger = Boolean(logOptions && logOptions.enable);\n if (enableByPassLogger && launchProxy) {\n let upstreamLabel = '';\n try {\n const parsedProxyUrl = new URL(proxyUrl.includes('://') ? proxyUrl : `http://${proxyUrl}`);\n upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;\n } catch {}\n logger.info(\n `[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || '-'} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(',')}`,\n );\n logger.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? '\u5F00\u542F' : '\u5173\u95ED'}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);\n } else if (enableByPassLogger && enableProxy && !launchProxy) {\n logger.info('[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A');\n logger.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? '\u5F00\u542F' : '\u5173\u95ED'}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);\n } else if (enableByPassLogger && !enableProxy && proxyUrl) {\n logger.info('[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E');\n logger.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? '\u5F00\u542F' : '\u5173\u95ED'}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);\n } else if (enableByPassLogger) {\n logger.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? '\u5F00\u542F' : '\u5173\u95ED'}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);\n }\n\n const onPageCreated = (page) => {\n const recommendedGotoOptions = {\n waitUntil: 'commit',\n };\n\n if (!page || typeof page.on !== 'function') {\n return recommendedGotoOptions;\n }\n if (page[REQUEST_HOOK_FLAG]) {\n return recommendedGotoOptions;\n }\n page[REQUEST_HOOK_FLAG] = true;\n\n const requestHandler = (req) => {\n const requestUrl = req.url();\n const resourceType = req.resourceType();\n const matched = byPassDomains.length > 0\n ? ByPass.findMatchedByPassRule(byPassRules, requestUrl)\n : null;\n if (launchProxy) {\n ProxyMeterRuntime.recordProxyMeterResourceType(requestUrl, resourceType);\n }\n if (!enableByPassLogger || byPassDomains.length === 0) return;\n if (!matched || !matched.rule) return;\n logger.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}`);\n };\n page.on('request', requestHandler);\n return recommendedGotoOptions;\n };\n\n const launchContext = {\n useIncognitoPages: true,\n launchOptions,\n };\n if (launcher) {\n launchContext.launcher = launcher;\n }\n\n const crawlerBaseOptions = {\n ...DEFAULT_CRAWLER_BASE_OPTIONS,\n headless: !runInHeadfulMode || isRunningOnApify,\n\t\t\t// \u6709 core.fingerprint \u65F6\u8D70\u56FA\u5B9A\u56DE\u653E\uFF1B\u5426\u5219\u9000\u56DE Crawlee \u9ED8\u8BA4\u6307\u7EB9\u6A21\u5F0F\u3002\n\t\t\tbrowserPoolOptions: replayBrowserPoolOptions || {\n\t\t\t\tuseFingerprints: true,\n\t\t\t\tfingerprintOptions: {\n fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions(),\n },\n },\n launchContext,\n };\n\n const normalizedPreNavigationHooks = Array.isArray(preNavigationHooks) ? preNavigationHooks : [];\n const normalizedPostNavigationHooks = Array.isArray(postNavigationHooks) ? postNavigationHooks : [];\n\n const internalPreNavigationHook = async ({ page }, gotoOptions = {}) => {\n const recommendedGotoOptions = onPageCreated(page);\n if (recommendedGotoOptions && typeof recommendedGotoOptions === 'object') {\n Object.assign(gotoOptions, recommendedGotoOptions);\n }\n };\n\n return {\n ...crawlerBaseOptions,\n preNavigationHooks: [internalPreNavigationHook, ...normalizedPreNavigationHooks],\n ...(normalizedPostNavigationHooks.length > 0\n ? { postNavigationHooks: normalizedPostNavigationHooks }\n : {}),\n };\n },\n};\n", "import picomatch from 'picomatch';\n\nconst normalizeByPassDomains = (domains) => {\n if (!Array.isArray(domains)) return [];\n return domains\n .map((item) => String(item || '').trim())\n .filter(Boolean);\n};\n\nconst normalizeHostname = (value = '') => String(value || '').trim().toLowerCase();\n\nconst buildByPassDomainRule = (rawPattern) => {\n const pattern = String(rawPattern || '').trim().toLowerCase();\n if (!pattern) return null;\n\n let matcher;\n try {\n matcher = picomatch(pattern, { nocase: true });\n } catch {\n return null;\n }\n\n return {\n pattern,\n test: (hostname) => matcher(String(hostname || '').toLowerCase()),\n };\n};\n\nconst buildByPassDomainRules = (domains = []) => {\n return normalizeByPassDomains(domains)\n .map((domain) => buildByPassDomainRule(domain))\n .filter(Boolean);\n};\n\nconst findMatchedByPassRule = (rules = [], requestUrl = '') => {\n let hostname = '';\n try {\n hostname = normalizeHostname(new URL(String(requestUrl || '')).hostname);\n } catch {\n return null;\n }\n\n for (const rule of rules) {\n if (rule && typeof rule.test === 'function' && rule.test(hostname)) {\n return {\n rule,\n hostname,\n };\n }\n }\n\n return {\n rule: null,\n hostname,\n };\n};\n\nconst isDomainCoveredByByPass = (domain = '', rules = []) => {\n const hostname = normalizeHostname(domain);\n if (!hostname) return false;\n\n for (const rule of rules || []) {\n if (!rule || typeof rule.test !== 'function') continue;\n if (rule.test(hostname)) return true;\n }\n\n return false;\n};\n\nconst resolveRouteByProxy = ({\n requestUrl = '',\n enableProxy = false,\n byPassRules = [],\n}) => {\n if (!enableProxy) {\n return { route: 'direct', matchedRule: null, hostname: '' };\n }\n\n const matched = findMatchedByPassRule(byPassRules, requestUrl);\n if (!matched) {\n return { route: 'proxy', matchedRule: null, hostname: '' };\n }\n\n if (matched.rule) {\n return { route: 'direct', matchedRule: matched.rule, hostname: matched.hostname };\n }\n\n return { route: 'proxy', matchedRule: null, hostname: matched.hostname };\n};\n\nexport const ByPass = {\n normalizeByPassDomains,\n normalizeHostname,\n buildByPassDomainRule,\n buildByPassDomainRules,\n findMatchedByPassRule,\n isDomainCoveredByByPass,\n resolveRouteByProxy,\n};\n", "import express from 'express';\nimport { Actor } from 'apify';\nimport { PresetOfLiveViewKey } from './constants';\nimport { createInternalLogger } from './internals/logger';\nimport { capturePageScreenshot } from './internals/screenshot';\n\nconst logger = createInternalLogger('LiveView');\n\n/**\n * \u542F\u52A8\u4E00\u4E2A Web \u670D\u52A1\u5668\u4EE5\u5728 Live View \u9009\u9879\u5361\u4E2D\u663E\u793A\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\u3002\n */\nasync function startLiveViewServer(liveViewKey) {\n const app = express();\n\n app.get('/', async (req, res) => {\n try {\n // \u4ECE\u9ED8\u8BA4\u7684 Key-Value Store \u4E2D\u8BFB\u53D6\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\n const screenshotBuffer = await Actor.getValue(liveViewKey);\n\n if (!screenshotBuffer) {\n // \u5982\u679C\u8FD8\u6CA1\u6709\u622A\u56FE\uFF0C\u53D1\u9001\u4E00\u4E2A\u81EA\u52A8\u5237\u65B0\u7684\u5360\u4F4D\u9875\u9762\n res.send('<html><head><meta http-equiv=\"refresh\" content=\"2\"></head><body>\u7B49\u5F85\u7B2C\u4E00\u4E2A\u5C4F\u5E55\u622A\u56FE...</body></html>');\n return;\n }\n\n // \u5C06 Buffer \u8F6C\u6362\u4E3A Base64 \u5B57\u7B26\u4E32\n const screenshotBase64 = screenshotBuffer.toString('base64');\n\n // \u53D1\u9001\u4E00\u4E2A HTML \u9875\u9762\uFF0C\u8BE5\u9875\u9762\u6BCF 1 \u79D2\u81EA\u52A8\u5237\u65B0\u4E00\u6B21\uFF0C\u5E76\u663E\u793A\u622A\u56FE\n res.send(`\n <html>\n <head>\n <title>Live View (\u622A\u56FE)</title>\n <meta http-equiv=\"refresh\" content=\"1\">\n </head>\n <body style=\"margin:0; padding:0;\">\n <img src=\"data:image/png;base64,${screenshotBase64}\" \n alt=\"Live View Screenshot\" \n style=\"width: 100%; height: auto;\" />\n </body>\n </html>\n `);\n } catch (error) {\n logger.fail('Live View Server', error);\n res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);\n }\n });\n\n // \u76D1\u542C Apify \u5BB9\u5668\u7AEF\u53E3 \n const port = process.env.APIFY_CONTAINER_PORT || 4321;\n app.listen(port, () => { logger.success('startLiveViewServer', `\u76D1\u542C\u7AEF\u53E3 ${port}`); });\n}\n\n/**\n * \u62CD\u6444\u5F53\u524D\u9875\u9762\u7684\u5C4F\u5E55\u622A\u56FE\u5E76\u5C06\u5176\u4FDD\u5B58\u5230 Key-Value Store\u3002\n * @param {import('playwright').Page} page\n * @param {string} [logMessage] - \u53EF\u9009\u7684\u65E5\u5FD7\u6D88\u606F\u3002\n */\nasync function takeLiveScreenshot(liveViewKey, page, logMessage) {\n try {\n const buffer = await capturePageScreenshot(page, { type: 'png' });\n await Actor.setValue(liveViewKey, buffer, { contentType: 'image/png' });\n if (logMessage) {\n logger.info(`(\u622A\u56FE): ${logMessage}`);\n }\n } catch (e) {\n logger.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);\n }\n}\n\nconst useLiveView = (liveViewKey = PresetOfLiveViewKey) => {\n return {\n takeLiveScreenshot: async (page, logMessage) => {\n return await takeLiveScreenshot(liveViewKey, page, logMessage)\n },\n startLiveViewServer: async () => {\n return await startLiveViewServer(liveViewKey);\n }\n }\n}\n\nexport const LiveView = {\n useLiveView,\n};\n", "import { v4 as uuidv4 } from 'uuid';\nimport { createInternalLogger } from './internals/logger';\n\nconst logger = createInternalLogger('Captcha');\n\n/**\n * \u521B\u5EFA\u9A8C\u8BC1\u7801\u76D1\u63A7\u5668 - \u652F\u6301 DOM \u9009\u62E9\u5668 \u548C URL \u6A21\u5F0F \u4E24\u79CD\u68C0\u6D4B\u65B9\u5F0F\n * \n * \u6CE8\u610F\uFF1A\u76D1\u63A7\u5668\u968F\u9875\u9762\u751F\u547D\u5468\u671F\u81EA\u52A8\u6E05\u7406\uFF0C\u65E0\u9700\u624B\u52A8 cleanup\n * \n * @param {import('playwright').Page} page\n * @param {Object} options\n * @param {string} [options.domSelector] - DOM \u5143\u7D20\u9009\u62E9\u5668 (\u5982 '#captcha_container')\n * @param {string} [options.urlPattern] - URL \u5339\u914D\u6A21\u5F0F (\u5982 '/captcha')\n * @param {Function} options.onDetected - \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u65F6\u7684\u56DE\u8C03 (async function)\n */\nexport function useCaptchaMonitor(page, options) {\n const { domSelector, urlPattern, onDetected } = options;\n\n if (!domSelector && !urlPattern) {\n throw new Error('[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern \u81F3\u5C11\u4E00\u4E2A');\n }\n\n if (!onDetected || typeof onDetected !== 'function') {\n throw new Error('[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u4E00\u4E2A\u51FD\u6570');\n }\n\n let isStopped = false;\n let isHandling = false;\n let frameHandler = null;\n let exposedFunctionName = null;\n\n const triggerDetected = async () => {\n if (isStopped || isHandling) return;\n isHandling = true;\n try {\n await onDetected();\n } finally {\n isHandling = false;\n }\n };\n\n const cleanupFns = [];\n\n // ============================================================\n // \u6A21\u5F0F1: DOM \u76D1\u63A7 (\u4F7F\u7528 MutationObserver)\n // ============================================================\n if (domSelector) {\n // \u751F\u6210\u552F\u4E00\u7684\u51FD\u6570\u540D\u907F\u514D\u51B2\u7A81\n exposedFunctionName = `__c_d_${uuidv4().replace(/-/g, '_')}`;\n // \u751F\u6210\u552F\u4E00\u7684\u6E05\u7406\u51FD\u6570\u540D (\u6302\u8F7D\u5728 window \u4E0A)\n const cleanerName = `__c_cleaner_${uuidv4().replace(/-/g, '_')}`;\n\n // \u66B4\u9732\u56DE\u8C03\u51FD\u6570\u7ED9\u9875\u9762\n page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {\n // \u5FFD\u7565\u91CD\u590D\u66B4\u9732\u9519\u8BEF\n });\n\n // \u6CE8\u5165 MutationObserver \u76D1\u542C\u811A\u672C\n page.addInitScript(({ selector, callbackName, cleanerName }) => {\n (() => {\n let observer = null;\n\n const checkAndReport = () => {\n const element = document.querySelector(selector);\n if (element) {\n if (window[callbackName]) {\n window[callbackName]();\n }\n return true;\n }\n return false;\n };\n\n // 1. \u7ACB\u5373\u68C0\u67E5\u4E00\u6B21\uFF08\u4E0D\u9000\u51FA\uFF0C\u4FDD\u6301\u6301\u7EED\u76D1\u542C\uFF09\n checkAndReport();\n\n // 2. \u542F\u52A8 MutationObserver\n observer = new MutationObserver((mutations) => {\n let shouldCheck = false;\n for (const mutation of mutations) {\n if (mutation.addedNodes.length > 0) {\n shouldCheck = true;\n break;\n }\n }\n if (shouldCheck && observer) {\n checkAndReport();\n }\n });\n\n // 3. \u6302\u8F7D\u76D1\u542C\uFF08\u786E\u4FDD DOM \u51C6\u5907\u5C31\u7EEA\uFF09\n const mountObserver = () => {\n const target = document.documentElement;\n if (target && observer) {\n observer.observe(target, { childList: true, subtree: true });\n }\n };\n\n if (document.readyState === 'loading') {\n window.addEventListener('DOMContentLoaded', mountObserver);\n } else {\n mountObserver();\n }\n\n // 4. \u6CE8\u518C\u6E05\u7406\u51FD\u6570\n window[cleanerName] = () => {\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n };\n })();\n }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });\n\n logger.success('useCaptchaMonitor', `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);\n\n // \u6DFB\u52A0\u6E05\u7406\u903B\u8F91\n cleanupFns.push(async () => {\n try {\n // \u8C03\u7528\u9875\u9762\u5185\u7684\u6E05\u7406\u51FD\u6570\n await page.evaluate((name) => {\n if (window[name]) {\n window[name]();\n delete window[name];\n }\n }, cleanerName);\n } catch (e) {\n // \u9875\u9762\u53EF\u80FD\u5DF2\u5173\u95ED\u6216\u8DF3\u8F6C\uFF0C\u5FFD\u7565\u9519\u8BEF\n }\n });\n }\n\n // ============================================================\n // \u6A21\u5F0F2: URL \u76D1\u63A7 (\u76D1\u542C framenavigated)\n // ============================================================\n if (urlPattern) {\n frameHandler = async (frame) => {\n if (frame === page.mainFrame()) {\n const currentUrl = page.url();\n if (currentUrl.includes(urlPattern)) {\n await triggerDetected();\n }\n }\n };\n\n page.on('framenavigated', frameHandler);\n logger.success('useCaptchaMonitor', `URL \u76D1\u63A7\u5DF2\u542F\u7528: ${urlPattern}`);\n\n // \u6DFB\u52A0\u6E05\u7406\u903B\u8F91\n cleanupFns.push(async () => {\n page.off('framenavigated', frameHandler);\n });\n }\n\n // \u8FD4\u56DE\u63A7\u5236\u53E5\u67C4\n return {\n stop: async () => {\n logger.info('useCaptchaMonitor', '\u6B63\u5728\u505C\u6B62\u76D1\u63A7...');\n for (const fn of cleanupFns) {\n await fn();\n }\n isStopped = true; // \u9632\u6B62\u540E\u7EED\u89E6\u53D1\n }\n };\n}\n\n// \u6309\u7167 toolkit \u7EDF\u4E00\u7684\u5BFC\u51FA\u6A21\u5F0F\nexport const Captcha = {\n useCaptchaMonitor\n};\n", "import { v4 as uuidv4 } from 'uuid';\nimport { createInternalLogger } from './internals/logger.js';\n\nconst logger = createInternalLogger('Mutation');\n\nconst MUTATION_MONITOR_MODE = Object.freeze({\n Added: 'added',\n Changed: 'changed',\n All: 'all',\n});\n\n/**\n * \u751F\u6210\u552F\u4E00\u7684 key \u540D\u79F0\uFF0C\u907F\u514D\u51B2\u7A81\n * @returns {string}\n */\nfunction generateKey(prefix) {\n return `__${prefix}_${uuidv4().replace(/-/g, '_')}`;\n}\n\nexport const Mutation = {\n Mode: MUTATION_MONITOR_MODE,\n /**\n * \u7B49\u5F85 DOM \u5143\u7D20\u7A33\u5B9A\uFF08\u65E0\u53D8\u5316\uFF09\n * \u4F7F\u7528 MutationObserver \u76D1\u63A7\u6307\u5B9A\u5143\u7D20\uFF0C\u5F53\u5143\u7D20\u6301\u7EED\u4E00\u6BB5\u65F6\u95F4\u65E0\u53D8\u5316\u65F6 resolve\n * \n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u5355\u4E2A\u6216\u591A\u4E2A\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {number} [options.initialTimeout] - \u7B49\u5F85\u5143\u7D20\u51FA\u73B0\u7684\u8D85\u65F6 (\u6BEB\u79D2, \u9ED8\u8BA4: 30000)\n * @param {number} [options.stableTime] - \u65E0\u53D8\u5316\u6301\u7EED\u65F6\u95F4\u540E resolve (\u6BEB\u79D2, \u9ED8\u8BA4: 5000)\n * @param {number} [options.timeout] - \u6574\u4F53\u8D85\u65F6\u65F6\u95F4 (\u6BEB\u79D2, \u9ED8\u8BA4: 120000)\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\u94A9\u5B50\n * \u7B7E\u540D: ({ mutationCount, html, text, mutationNodes }) => any\n * \u8FD4\u56DE null/undefined: \u6B63\u5E38\u91CD\u7F6E\u7A33\u5B9A\u8BA1\u65F6\n * \u8FD4\u56DE\u5176\u4ED6\u503C: \u6682\u505C\u7A33\u5B9A\u8BA1\u65F6\uFF08timeout \u4ECD\u7136\u751F\u6548\uFF09\n * @returns {Promise<{ mutationCount: number, stableTime: number, wasPaused: boolean }>}\n */\n async waitForStable(page, selectors, options = {}) {\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\n const initialTimeout = options.initialTimeout ?? 30 * 1000;\n const stableTime = options.stableTime ?? 5 * 1000;\n const timeout = options.timeout ?? 120 * 1000;\n const onMutation = options.onMutation;\n\n logger.start('waitForStable', `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);\n\n if (initialTimeout > 0) {\n const selectorQuery = selectorList.join(',');\n try {\n await page.waitForSelector(selectorQuery, { timeout: initialTimeout });\n logger.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);\n } catch (e) {\n logger.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);\n throw e;\n }\n }\n\n // \u751F\u6210\u552F\u4E00\u7684\u56DE\u8C03\u540D\n const callbackName = generateKey('pk_mut_cb');\n\n // \u5982\u679C\u6709 onMutation \u56DE\u8C03\uFF0C\u66B4\u9732\u51FD\u6570\u5E76\u8FD4\u56DE\u7ED3\u679C\n if (onMutation) {\n try {\n await page.exposeFunction(callbackName, async (context) => {\n try {\n const result = await onMutation(context);\n const paused = !(result === null || result === undefined);\n // \u8FD4\u56DE null/undefined \u8868\u793A\u6B63\u5E38\u8BA1\u65F6\uFF0C\u5176\u4ED6\u503C\u8868\u793A\u6682\u505C\n return paused ? '__PAUSE__' : '__CONTINUE__';\n } catch (e) {\n // \u56DE\u8C03\u51FA\u9519\u65F6\u9ED8\u8BA4\u7EE7\u7EED\u8BA1\u65F6\n return '__CONTINUE__';\n }\n });\n logger.info('waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03');\n } catch (e) {\n // \u53EF\u80FD\u5DF2\u7ECF\u66B4\u9732\u8FC7\uFF0C\u5FFD\u7565\n }\n }\n\n const result = await page.evaluate(\n async ({ selectorList, stableTime, timeout, callbackName, hasCallback }) => {\n return new Promise((resolve, reject) => {\n let mutationCount = 0;\n let stableTimer = null;\n let timeoutTimer = null;\n let isPaused = false;\n let wasPaused = false;\n const observers = [];\n\n // \u6E05\u7406\u51FD\u6570\n const cleanup = () => {\n observers.forEach(obs => obs.disconnect());\n if (stableTimer) clearTimeout(stableTimer);\n if (timeoutTimer) clearTimeout(timeoutTimer);\n };\n\n // \u91CD\u7F6E\u7A33\u5B9A\u8BA1\u65F6\u5668\n const resetStableTimer = () => {\n if (stableTimer) clearTimeout(stableTimer);\n if (isPaused) return;\n stableTimer = setTimeout(() => {\n cleanup();\n resolve({ mutationCount, stableTime, wasPaused });\n }, stableTime);\n };\n\n const setPaused = (nextPaused) => {\n if (isPaused === nextPaused) return;\n isPaused = nextPaused;\n if (isPaused) {\n if (stableTimer) clearTimeout(stableTimer);\n stableTimer = null;\n wasPaused = true;\n return;\n }\n resetStableTimer();\n };\n\n // \u6574\u4F53\u8D85\u65F6\uFF08\u59CB\u7EC8\u751F\u6548\uFF0C\u4E0D\u53D7\u6682\u505C\u5F71\u54CD\uFF09\n timeoutTimer = setTimeout(() => {\n cleanup();\n reject(new Error(`waitForStable \u8D85\u65F6 (${timeout}ms), \u5DF2\u68C0\u6D4B\u5230 ${mutationCount} \u6B21\u53D8\u5316, isPaused=${isPaused}`));\n }, timeout);\n\n // \u4E3A\u6BCF\u4E2A\u9009\u62E9\u5668\u521B\u5EFA MutationObserver\n selectorList.forEach(selector => {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n const observer = new MutationObserver(async (mutations) => {\n mutationCount += mutations.length;\n\n if (hasCallback && window[callbackName]) {\n // \u83B7\u53D6\u5143\u7D20\u5185\u5BB9\n const html = element.outerHTML || '';\n const text = element.innerText || element.textContent || '';\n const mutationNodes = [{ html, text, mutationType: 'stable' }];\n\n try {\n const signal = await window[callbackName]({\n mutationCount,\n html,\n text,\n mutationNodes\n });\n\n const shouldPause = signal === '__PAUSE__';\n setPaused(shouldPause);\n if (!shouldPause) {\n resetStableTimer();\n }\n } catch (e) {\n // \u56DE\u8C03\u51FA\u9519\u65F6\u7EE7\u7EED\u8BA1\u65F6\n setPaused(false);\n resetStableTimer();\n }\n } else {\n // \u6CA1\u6709\u56DE\u8C03\uFF0C\u4FDD\u6301\u539F\u6709\u884C\u4E3A\n resetStableTimer();\n }\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true\n });\n\n observers.push(observer);\n });\n });\n\n // \u5982\u679C\u6CA1\u6709\u627E\u5230\u4EFB\u4F55\u5143\u7D20\uFF0C\u76F4\u63A5\u8FD4\u56DE\n if (observers.length === 0) {\n cleanup();\n resolve({ mutationCount: 0, stableTime: 0, wasPaused: false });\n return;\n }\n\n // \u521D\u59CB\u68C0\u67E5\uFF1A\u6302\u8F7D\u540E\u7ACB\u5373\u6267\u884C\u4E00\u6B21\u56DE\u8C03\uFF0C\u5224\u65AD\u662F\u5426\u9700\u8981\u6682\u505C\n const runInitialCheck = async () => {\n if (hasCallback && window[callbackName]) {\n // \u83B7\u53D6\u7B2C\u4E00\u4E2A\u76D1\u63A7\u5143\u7D20\u7684\u5185\u5BB9\n const firstSelector = selectorList[0];\n const firstElement = document.querySelector(firstSelector);\n if (firstElement) {\n const html = firstElement.outerHTML || '';\n const text = firstElement.innerText || firstElement.textContent || '';\n const mutationNodes = [{ html, text, mutationType: 'stable' }];\n\n try {\n const signal = await window[callbackName]({\n mutationCount: 0,\n html,\n text,\n mutationNodes\n });\n\n if (signal === '__PAUSE__') {\n setPaused(true);\n return; // \u6682\u505C\u65F6\u4E0D\u542F\u52A8\u521D\u59CB\u8BA1\u65F6\n }\n } catch (e) {\n // \u56DE\u8C03\u51FA\u9519\u65F6\u7EE7\u7EED\n }\n }\n }\n // \u542F\u52A8\u521D\u59CB\u7A33\u5B9A\u8BA1\u65F6\u5668\n resetStableTimer();\n };\n\n runInitialCheck();\n });\n },\n { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }\n );\n\n if (result.mutationCount === 0 && result.stableTime === 0) {\n logger.warning('waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20');\n }\n logger.success('waitForStable', `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ', \u66FE\u6682\u505C\u8BA1\u65F6' : ''}`);\n return result;\n },\n /**\n * \u7B49\u5F85\u8DE8 root DOM \u5143\u7D20\u7A33\u5B9A\uFF08\u4E3B\u6587\u6863 + iframe \u5185\u5BB9\uFF09\n * \u901A\u8FC7\u8F6E\u8BE2\u5FEB\u7167\u68C0\u6D4B\u53D8\u5316\uFF0C\u9002\u914D iframe / shadow \u573A\u666F\n *\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u5355\u4E2A\u6216\u591A\u4E2A\uFF08\u5EFA\u8BAE\u4F20 iframe \u9009\u62E9\u5668\uFF09\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\uFF08\u7B7E\u540D\u4E0E waitForStable \u4FDD\u6301\u4E00\u81F4\uFF09\n * @param {number} [options.initialTimeout] - \u7B49\u5F85\u5143\u7D20\u51FA\u73B0\u7684\u8D85\u65F6 (\u6BEB\u79D2, \u9ED8\u8BA4: 60000)\n * @param {number} [options.stableTime] - \u65E0\u53D8\u5316\u6301\u7EED\u65F6\u95F4\u540E resolve (\u6BEB\u79D2, \u9ED8\u8BA4: 10000)\n * @param {number} [options.timeout] - \u6574\u4F53\u8D85\u65F6\u65F6\u95F4 (\u6BEB\u79D2, \u9ED8\u8BA4: 180000)\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\u94A9\u5B50\n * @returns {Promise<{ mutationCount: number, stableTime: number, wasPaused: boolean }>}\n */\n async waitForStableAcrossRoots(page, selectors, options = {}) {\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\n const selectorQuery = selectorList.join(',');\n const initialTimeout = options.initialTimeout ?? 60 * 1000;\n const waitForStableTime = options.stableTime ?? 10 * 1000;\n const overallTimeout = options.timeout ?? 180 * 1000;\n const onMutation = options.onMutation;\n const pollInterval = 500;\n\n const sleep = (ms) => new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n\n const truncate = (value, max = 800) => {\n const text = String(value || '');\n if (text.length <= max) return text;\n return `${text.slice(0, max)}...`;\n };\n\n const buildState = async () => {\n return await page.evaluate(({ selectorList }) => {\n const normalizeText = (value) => String(value || '').replace(/\\s+/g, ' ').trim();\n const tail = (value, max = 512) => {\n const text = String(value || '');\n if (text.length <= max) return text;\n return text.slice(text.length - max);\n };\n const safeFrameId = (frameEl) => {\n const id = String(frameEl?.id || '').trim();\n if (id) return id;\n const name = String(frameEl?.name || '').trim();\n if (name) return name;\n return 'no-id';\n };\n\n const items = [];\n\n selectorList.forEach((selector) => {\n let nodes = [];\n try {\n nodes = Array.from(document.querySelectorAll(selector));\n } catch {\n return;\n }\n\n nodes.forEach((node, index) => {\n const isIframe = node?.tagName === 'IFRAME';\n let text = '';\n let html = '';\n let source = 'main';\n let path = `${selector}[${index}]`;\n\n if (isIframe) {\n source = 'iframe';\n path = `${selector}[${index}]::iframe(${safeFrameId(node)})`;\n try {\n const frameDoc = node.contentDocument;\n const frameRoot = frameDoc?.body || frameDoc?.documentElement;\n if (frameRoot) {\n text = normalizeText(frameRoot.innerText || frameRoot.textContent || '');\n html = normalizeText(frameRoot.innerHTML || '');\n }\n } catch {\n // ignore cross-origin iframe\n }\n } else {\n text = normalizeText(node?.innerText || node?.textContent || '');\n html = normalizeText(node?.innerHTML || node?.outerHTML || '');\n }\n\n const snapshot = text || html;\n items.push({\n selector,\n source,\n path,\n text,\n html,\n snapshot,\n });\n });\n });\n\n const snapshotKey = items\n .map((item) => `${item.path}:${item.snapshot.length}:${tail(item.snapshot, 512)}`)\n .join('||');\n const summaryText = items.map((item) => item.snapshot || item.text).join('\\n').trim();\n const summaryHtml = items.map((item) => item.html).join('\\n');\n const hasMatched = items.length > 0;\n const primary = items.length > 0 ? items[items.length - 1] : null;\n\n return {\n hasMatched,\n snapshotKey,\n text: summaryText,\n html: summaryHtml,\n snapshotLength: summaryText.length,\n itemCount: items.length,\n primaryPath: primary?.path || '',\n mutationNodes: items.map((item) => ({\n html: item.html,\n text: item.snapshot || item.text,\n mutationType: item.source,\n })),\n };\n }, { selectorList });\n };\n\n const invokeMutationCallback = async (context) => {\n if (!onMutation) return '__CONTINUE__';\n try {\n const result = await onMutation(context);\n return (result === null || result === undefined) ? '__CONTINUE__' : '__PAUSE__';\n } catch {\n return '__CONTINUE__';\n }\n };\n\n logger.start(\n 'waitForStableAcrossRoots',\n `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`\n );\n\n if (initialTimeout > 0) {\n try {\n await page.waitForSelector(selectorQuery, { timeout: initialTimeout });\n logger.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);\n } catch (e) {\n logger.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);\n throw e;\n }\n }\n\n let state = await buildState();\n if (!state?.hasMatched) {\n logger.warning('waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20');\n return { mutationCount: 0, stableTime: 0, wasPaused: false };\n }\n\n let mutationCount = 0;\n let stableSince = 0;\n let isPaused = false;\n let wasPaused = false;\n let lastSnapshotKey = state.snapshotKey;\n\n const applyPauseSignal = (signal) => {\n const nextPaused = signal === '__PAUSE__';\n if (nextPaused) {\n if (!isPaused) wasPaused = true;\n isPaused = true;\n stableSince = 0;\n return;\n }\n\n isPaused = false;\n stableSince = Date.now();\n };\n\n const initialSignal = await invokeMutationCallback({\n mutationCount: 0,\n html: state.html || '',\n text: state.text || '',\n mutationNodes: state.mutationNodes || [],\n });\n applyPauseSignal(initialSignal);\n\n const deadline = Date.now() + overallTimeout;\n let lastState = state;\n\n while (Date.now() < deadline) {\n await sleep(pollInterval);\n lastState = await buildState();\n\n if (!lastState?.hasMatched) {\n continue;\n }\n\n if (lastState.snapshotKey !== lastSnapshotKey) {\n lastSnapshotKey = lastState.snapshotKey;\n mutationCount += 1;\n\n logger.info(\n `waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || 'unknown'}, preview=\"${truncate(lastState.text, 120)}\"`\n );\n\n const signal = await invokeMutationCallback({\n mutationCount,\n html: lastState.html || '',\n text: lastState.text || '',\n mutationNodes: lastState.mutationNodes || [],\n });\n applyPauseSignal(signal);\n continue;\n }\n\n if (!isPaused && stableSince > 0 && (Date.now() - stableSince) >= waitForStableTime) {\n logger.success('waitForStableAcrossRoots', `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ', \u66FE\u6682\u505C\u8BA1\u65F6' : ''}`);\n return {\n mutationCount,\n stableTime: waitForStableTime,\n wasPaused,\n };\n }\n }\n\n throw new Error(`waitForStableAcrossRoots \u8D85\u65F6 (${overallTimeout}ms), \u5DF2\u68C0\u6D4B\u5230 ${mutationCount} \u6B21\u53D8\u5316, isPaused=${isPaused}`);\n },\n\n /**\n * \u521B\u5EFA\u4E00\u4E2A\u6301\u7EED\u76D1\u63A7 DOM \u53D8\u5316\u7684\u76D1\u63A7\u5668\uFF08\u9ED8\u8BA4\u4EC5\u76D1\u542C\u65B0\u589E DOM\uFF09\n *\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u652F\u6301 'document.documentElement'\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\n * \u7B7E\u540D: ({ mutationCount, html, text, mutationNodes }) => void\n * \u6240\u6709\u6A21\u5F0F\u90FD\u8FD4\u56DE\u672C\u6B21\u5168\u90E8\u53D8\u5316\u8282\u70B9\u5FEB\u7167 mutationNodes\n * @param {'added' | 'changed' | 'all'} [options.mode='added'] - \u76D1\u63A7\u6A21\u5F0F\n * @returns {Promise<{ stop: () => Promise<{ totalMutations: number }> }>} - \u8FD4\u56DE\u505C\u6B62\u51FD\u6570\n */\n async useMonitor(page, selectors, options = {}) {\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\n const onMutation = options.onMutation;\n const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();\n const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode)\n ? rawMode\n : MUTATION_MONITOR_MODE.Added;\n\n logger.start('useMonitor', `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);\n\n const monitorKey = generateKey('pk_mon');\n const callbackName = generateKey('pk_mon_cb');\n const cleanerName = generateKey('pk_mon_clean');\n\n if (onMutation) {\n try {\n await page.exposeFunction(callbackName, (payload) => {\n try {\n onMutation(payload);\n } catch (e) {\n // \u5FFD\u7565\u56DE\u8C03\u9519\u8BEF\n }\n });\n } catch (e) {\n // \u53EF\u80FD\u5DF2\u7ECF\u66B4\u9732\u8FC7\uFF0C\u5FFD\u7565\n }\n }\n\n await page.evaluate(({ selectorList, monitorKey, callbackName, cleanerName, hasCallback, mode }) => {\n const monitor = {\n observers: [],\n totalMutations: 0,\n running: true,\n };\n\n const resolveTargets = (selector) => {\n const key = String(selector || '').trim();\n if (!key) return [];\n\n if (key === 'document.documentElement' || key === 'documentElement' || key === 'document') {\n return document.documentElement ? [document.documentElement] : [];\n }\n\n if (key === 'document.body') {\n return document.body ? [document.body] : [];\n }\n\n return Array.from(document.querySelectorAll(key));\n };\n\n const serializeNode = (node, mutationType = 'unknown') => {\n if (!node) {\n return { html: '', text: '', mutationType };\n }\n\n if (node.nodeType === Node.ELEMENT_NODE) {\n return {\n html: node.outerHTML || '',\n text: node.innerText || node.textContent || '',\n mutationType,\n };\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent || '';\n return { html: text, text, mutationType };\n }\n\n if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n const nodes = Array.from(node.childNodes || []);\n const html = nodes\n .map(item => item?.nodeType === Node.ELEMENT_NODE ? (item.outerHTML || '') : (item?.textContent || ''))\n .join('\\n');\n const text = node.textContent || '';\n return { html: html || text, text, mutationType };\n }\n\n const text = node.textContent || '';\n return { html: text, text, mutationType };\n };\n\n const collectMutationNodes = (mutations) => {\n const mutationNodes = [];\n\n for (const mutation of mutations) {\n if (mode === 'added') {\n if (mutation.type !== 'childList') continue;\n const added = Array.from(mutation.addedNodes || []);\n for (const node of added) {\n mutationNodes.push(serializeNode(node, 'added'));\n }\n continue;\n }\n\n if (mode === 'changed') {\n if (mutation.type === 'attributes' || mutation.type === 'characterData') {\n mutationNodes.push(serializeNode(mutation.target, mutation.type));\n } else if (mutation.type === 'childList') {\n const added = Array.from(mutation.addedNodes || []);\n const removed = Array.from(mutation.removedNodes || []);\n\n for (const node of added) {\n mutationNodes.push(serializeNode(node, 'added'));\n }\n for (const node of removed) {\n mutationNodes.push(serializeNode(node, 'removed'));\n }\n\n if (added.length === 0 && removed.length === 0) {\n mutationNodes.push(serializeNode(mutation.target, 'childList'));\n }\n }\n continue;\n }\n\n if (mutation.type === 'childList') {\n const added = Array.from(mutation.addedNodes || []);\n const removed = Array.from(mutation.removedNodes || []);\n\n for (const node of added) {\n mutationNodes.push(serializeNode(node, 'added'));\n }\n for (const node of removed) {\n mutationNodes.push(serializeNode(node, 'removed'));\n }\n\n if (added.length === 0 && removed.length === 0) {\n mutationNodes.push(serializeNode(mutation.target, 'childList'));\n }\n } else if (mutation.type === 'attributes' || mutation.type === 'characterData') {\n mutationNodes.push(serializeNode(mutation.target, mutation.type));\n } else {\n mutationNodes.push(serializeNode(mutation.target, mutation.type || 'unknown'));\n }\n }\n\n return mutationNodes;\n };\n\n selectorList.forEach(selector => {\n const elements = resolveTargets(selector);\n elements.forEach(element => {\n const observer = new MutationObserver((mutations) => {\n if (!monitor.running) return;\n\n const mutationNodes = collectMutationNodes(mutations);\n if (mutationNodes.length <= 0) return;\n\n monitor.totalMutations += mutationNodes.length;\n\n if (hasCallback && window[callbackName]) {\n const html = mutationNodes.map(item => item.html || '').join('\\n');\n const text = mutationNodes.map(item => item.text || '').join('\\n');\n\n window[callbackName]({\n mutationCount: monitor.totalMutations,\n html,\n text,\n mutationNodes,\n });\n }\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n characterData: mode !== 'added',\n attributes: mode !== 'added',\n });\n\n monitor.observers.push(observer);\n });\n });\n\n window[monitorKey] = monitor;\n window[cleanerName] = () => {\n monitor.running = false;\n monitor.observers.forEach(obs => obs.disconnect());\n const total = monitor.totalMutations;\n delete window[monitorKey];\n delete window[cleanerName];\n return total;\n };\n }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });\n\n logger.success('useMonitor', '\u76D1\u63A7\u5668\u5DF2\u542F\u52A8');\n\n return {\n stop: async () => {\n let totalMutations = 0;\n try {\n totalMutations = await page.evaluate((cleanerName) => {\n if (window[cleanerName]) {\n return window[cleanerName]();\n }\n return 0;\n }, cleanerName);\n } catch (e) {\n // \u9875\u9762\u53EF\u80FD\u5DF2\u5173\u95ED\uFF0C\u5FFD\u7565\n }\n logger.success('useMonitor.stop', `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);\n return { totalMutations };\n }\n };\n }\n};\n", "export const Display = {\n parseTokenDisplayName(value) {\n if (!value) {\n return { owner: '', envType: '', note: '' };\n }\n const parts = String(value).split(':');\n const owner = (parts[0] || '').trim();\n const envType = (parts[1] || '').trim();\n const note = parts.length > 2 ? parts.slice(2).join(':').trim() : '';\n return { owner, envType, note };\n },\n\n parseEnvDisplayName(value) {\n if (!value) {\n return { env: '', owner: '', envType: '', note: '' };\n }\n const parts = String(value).split(':');\n const env = (parts[0] || '').trim();\n const owner = (parts[1] || '').trim();\n const envType = (parts[2] || '').trim();\n const note = parts.length > 3 ? parts.slice(3).join(':').trim() : '';\n return { env, owner, envType, note };\n },\n\n buildTokenDisplayName({ owner, envType, note } = {}) {\n const trimmedOwner = owner?.trim() || '';\n const trimmedType = envType?.trim() || '';\n const trimmedNote = note?.trim() || '';\n const parts = [trimmedOwner, trimmedType];\n if (trimmedNote) {\n parts.push(trimmedNote);\n }\n return parts.filter(Boolean).join(':');\n },\n\n shortId(value, max = 8) {\n const clean = String(value || '').trim();\n if (!clean) return '';\n if (clean.length <= max) return clean;\n return clean.slice(0, max);\n },\n\n resolveTokenIdentity(displayName, tokenId) {\n const cleanName = String(displayName || '').trim();\n const cleanId = String(tokenId || '').trim();\n const short = this.shortId(cleanId, 8);\n const hasName = cleanName !== '' && cleanName !== cleanId;\n const primary = hasName ? cleanName : (short || '-');\n const secondary = hasName && short ? short : '';\n return { primary, secondary, fullId: cleanId, shortId: short };\n },\n\n resolveEnvIdentity(displayName, envId) {\n const parts = this.parseEnvDisplayName(displayName);\n const cleanId = String(envId || '').trim();\n const short = this.shortId(cleanId, 8);\n const hasName = parts.env !== '' && parts.env !== cleanId;\n const primary = hasName ? parts.env : (short || '-');\n const secondary = hasName && short ? short : '';\n return { primary, secondary, parts, fullId: cleanId, shortId: short };\n },\n};\n", "import { createBaseLogger, setDefaultLogger } from './internals/logger.js';\n\nexport const stripAnsi = (input) => {\n if (!input) return '';\n return String(input).replace(/\\x1b\\[[0-9;]*m/g, '');\n};\n\n// =============================================================================\n// Log Templates & Definitions\n// =============================================================================\n\nconst STEP_PREFIX = '\u6B65\u9AA4:';\nconst STEP_SEPARATOR = ' | ';\nconst STEP_EMOJIS = [\n { match: '\u4EFB\u52A1', emoji: '\uD83E\uDDED' },\n { match: '\u8FD0\u884C\u6A21\u5F0F', emoji: '\uD83E\uDDE9' },\n { match: '\u6A21\u677F\u8BC6\u522B', emoji: '\uD83E\uDDF1' },\n { match: '\u767B\u5F55', emoji: '\uD83D\uDD10' },\n { match: '\u73AF\u5883', emoji: '\uD83E\uDDEA' },\n { match: '\u8F93\u5165', emoji: '\u2328\uFE0F' },\n { match: '\u53D1\u9001', emoji: '\uD83D\uDCE4' },\n { match: '\u54CD\u5E94\u76D1\u542C', emoji: '\uD83D\uDCE1' },\n { match: '\u7B49\u5F85\u54CD\u5E94', emoji: '\u23F3' },\n { match: '\u6D41\u5F0F', emoji: '\uD83E\uDDF5' },\n { match: '\u5F15\u7528', emoji: '\uD83D\uDCCE' },\n { match: '\u622A\u56FE', emoji: '\uD83D\uDDBC\uFE0F' },\n { match: '\u5206\u4EAB\u94FE\u63A5', emoji: '\uD83D\uDD17' },\n { match: '\u6570\u636E\u63A8\u9001', emoji: '\uD83D\uDCE6' },\n { match: '\u5F39\u7A97', emoji: '\uD83E\uDE9F' },\n];\nconst STATUS_EMOJIS = [\n { match: '\u5F00\u59CB', emoji: '\uD83D\uDE80' },\n { match: '\u5B8C\u6210', emoji: '\u2705' },\n { match: '\u6210\u529F', emoji: '\u2705' },\n { match: '\u5931\u8D25', emoji: '\u274C' },\n { match: '\u8DF3\u8FC7', emoji: '\u23ED\uFE0F' },\n { match: '\u8D85\u65F6', emoji: '\u23F1\uFE0F' },\n { match: '\u91CD\u8BD5', emoji: '\uD83D\uDD01' },\n { match: '\u7ED3\u675F', emoji: '\uD83C\uDFC1' },\n { match: '\u5DF2\u914D\u7F6E', emoji: '\uD83E\uDDF7' },\n { match: '\u5DF2\u68C0\u6D4B', emoji: '\uD83D\uDD0E' },\n];\n\nconst toErrorMessage = (error) => {\n if (!error) return '';\n if (error instanceof Error) return error.message;\n if (typeof error === 'string') return error;\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n};\n\nconst decorateLabel = (label, mappings) => {\n if (!label) return '';\n const mapping = mappings.find((item) => label.includes(item.match));\n if (!mapping) return label;\n return `${mapping.emoji} ${label}`;\n};\n\nconst normalizeSnippet = (snippet, maxLen = 120) => {\n if (!snippet) return '';\n const text = String(snippet).replace(/\\s+/g, ' ').trim();\n if (!text) return '';\n const cleaned = text.replace(/\"/g, \"'\");\n if (cleaned.length <= maxLen) return cleaned;\n return `${cleaned.slice(0, maxLen)}...`;\n};\n\nconst LOG_TAG_PREFIX = '[#log:';\nconst LOG_TAG_SUFFIX = ']';\n\nconst buildLogTag = (key) => `${LOG_TAG_PREFIX}${key}${LOG_TAG_SUFFIX}`;\n\nconst escapeRegExp = (value) => String(value).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nconst buildStepPattern = (step, status) => {\n if (!step) return null;\n let pattern = `\u6B65\u9AA4: .*${escapeRegExp(step)}`;\n if (status) {\n pattern += `.*${escapeRegExp(status)}`;\n }\n return new RegExp(pattern);\n};\n\nconst buildDefinitionPatterns = (definition) => {\n const patterns = [new RegExp(`\\\\[#log:${escapeRegExp(definition.key)}\\\\]`)];\n const fallback = buildStepPattern(definition.step, definition.status);\n if (fallback) patterns.push(fallback);\n if (Array.isArray(definition.extraPatterns)) {\n patterns.push(...definition.extraPatterns);\n }\n return patterns;\n};\n\nconst ATTENTION_RANK = {\n low: 1,\n medium: 2,\n high: 3,\n critical: 4,\n};\nconst DEFAULT_ATTENTION_RANK = ATTENTION_RANK.high;\n\nconst LOG_DEFINITIONS = [\n {\n key: 'task_start',\n method: 'taskStart',\n label: '\u4EFB\u52A1\u5F00\u59CB',\n group: '\u4EFB\u52A1',\n step: '\u4EFB\u52A1',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (url) => [url ? `url=${url}` : ''],\n },\n {\n key: 'task_success',\n method: 'taskSuccess',\n label: '\u4EFB\u52A1\u5B8C\u6210',\n group: '\u4EFB\u52A1',\n step: '\u4EFB\u52A1',\n status: '\u5B8C\u6210',\n level: 'success',\n attention: 'high',\n },\n {\n key: 'task_fail',\n method: 'taskFail',\n label: '\u4EFB\u52A1\u5931\u8D25',\n group: '\u4EFB\u52A1',\n step: '\u4EFB\u52A1',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'critical',\n buildDetails: (url, err) => [\n url ? `url=${url}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'runtime_headless',\n method: 'runtimeHeadless',\n label: '\u8FD0\u884C\u6A21\u5F0F\u5F3A\u5236\u65E0\u5934',\n group: '\u8FD0\u884C\u6A21\u5F0F',\n step: '\u8FD0\u884C\u6A21\u5F0F',\n status: 'Apify \u73AF\u5883\u5F3A\u5236\u65E0\u5934',\n level: 'warning',\n attention: 'medium',\n },\n {\n key: 'login_inject_success',\n method: 'loginInjectSuccess',\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u6210\u529F',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'medium',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'login_inject_skip',\n method: 'loginInjectSkip',\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u8DF3\u8FC7',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\n status: '\u8DF3\u8FC7',\n level: 'warning',\n attention: 'medium',\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\n },\n {\n key: 'login_inject_fail',\n method: 'loginInjectFail',\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u5931\u8D25',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'login_verify_success',\n method: 'loginVerifySuccess',\n label: '\u767B\u5F55\u9A8C\u8BC1\u6210\u529F',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u9A8C\u8BC1',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'login_verify_skip',\n method: 'loginVerifySkip',\n label: '\u767B\u5F55\u9A8C\u8BC1\u8DF3\u8FC7',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u9A8C\u8BC1',\n status: '\u8DF3\u8FC7',\n level: 'warning',\n attention: 'medium',\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\n },\n {\n key: 'login_verify_fail',\n method: 'loginVerifyFail',\n label: '\u767B\u5F55\u9A8C\u8BC1\u5931\u8D25',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u9A8C\u8BC1',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'critical',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'env_check_success',\n method: 'envCheckSuccess',\n label: '\u73AF\u5883\u68C0\u67E5\u6210\u529F',\n group: '\u73AF\u5883',\n step: '\u73AF\u5883\u68C0\u67E5',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'medium',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'env_check_fail',\n method: 'envCheckFail',\n label: '\u73AF\u5883\u68C0\u67E5\u5931\u8D25',\n group: '\u73AF\u5883',\n step: '\u73AF\u5883\u68C0\u67E5',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'input_query_start',\n method: 'inputQuery',\n label: '\u8F93\u5165\u67E5\u8BE2\u5F00\u59CB',\n group: '\u8F93\u5165',\n step: '\u8F93\u5165\u67E5\u8BE2',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (query) => [query ? `query=${query}` : ''],\n },\n {\n key: 'send_action',\n method: 'sendAction',\n label: '\u53D1\u9001\u8BF7\u6C42',\n group: '\u53D1\u9001',\n step: '\u53D1\u9001\u8BF7\u6C42',\n status: '\u70B9\u51FB\u53D1\u9001',\n level: 'info',\n attention: 'low',\n },\n {\n key: 'response_listen_start',\n method: 'responseListenStart',\n label: '\u54CD\u5E94\u76D1\u542C\u5F00\u59CB',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label, timeoutSec) => [\n label ? `\u76EE\u6807=${label}` : '',\n timeoutSec ? `timeout=${timeoutSec}s` : ''\n ],\n },\n {\n key: 'response_listen_ready',\n method: 'responseListenReady',\n label: '\u54CD\u5E94\u76D1\u542C\u5DF2\u914D\u7F6E',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u5DF2\u914D\u7F6E',\n level: 'info',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_listen_detected',\n method: 'responseListenDetected',\n label: '\u54CD\u5E94\u76D1\u542C\u5DF2\u68C0\u6D4B',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u5DF2\u68C0\u6D4B',\n level: 'success',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_listen_timeout',\n method: 'responseListenTimeout',\n label: '\u54CD\u5E94\u76D1\u542C\u8D85\u65F6',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u8D85\u65F6',\n level: 'error',\n attention: 'high',\n buildDetails: (label, err) => [\n label ? `\u76EE\u6807=${label}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'response_listen_end',\n method: 'responseListenEnd',\n label: '\u54CD\u5E94\u76D1\u542C\u7ED3\u675F',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u7ED3\u675F',\n level: 'info',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_wait_start',\n method: 'responseWaitStart',\n label: '\u7B49\u5F85\u54CD\u5E94\u5F00\u59CB',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_wait_success',\n method: 'responseWaitSuccess',\n label: '\u7B49\u5F85\u54CD\u5E94\u5B8C\u6210',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u5B8C\u6210',\n level: 'success',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_wait_fail',\n method: 'responseWaitFail',\n label: '\u7B49\u5F85\u54CD\u5E94\u5931\u8D25',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (label, err) => [\n label ? `\u76EE\u6807=${label}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'response_wait_retry',\n method: 'responseWaitRetry',\n label: '\u7B49\u5F85\u54CD\u5E94\u91CD\u8BD5',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u91CD\u8BD5',\n level: 'warning',\n attention: 'medium',\n buildDetails: (label, attempt) => [\n label ? `\u76EE\u6807=${label}` : '',\n attempt !== undefined ? `\u5C1D\u8BD5=${attempt}` : ''\n ],\n },\n {\n key: 'dom_wait_start',\n method: 'domWaitStart',\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5F00\u59CB',\n group: 'DOM',\n step: 'DOM\u7A33\u5B9A',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'dom_wait_fail',\n method: 'domWaitFail',\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5931\u8D25',\n group: 'DOM',\n step: 'DOM\u7A33\u5B9A',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (label, err) => [\n label ? `\u76EE\u6807=${label}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'dom_chunk',\n method: 'domChunk',\n label: 'DOM\u7247\u6BB5',\n group: 'DOM',\n step: 'DOM\u7247\u6BB5',\n status: '',\n level: 'info',\n attention: 'low',\n throttleKey: 'dom-chunk',\n throttleMs: 2000,\n buildDetails: (length, snippet, paused) => [\n length !== undefined ? `len=${length}` : '',\n snippet ? `preview=\"${normalizeSnippet(snippet)}\"` : '',\n paused ? 'paused=1' : ''\n ],\n },\n {\n key: 'dom_wait_success',\n method: 'domWaitSuccess',\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5B8C\u6210',\n group: 'DOM',\n step: 'DOM\u7A33\u5B9A',\n status: '\u5B8C\u6210',\n level: 'success',\n attention: 'medium',\n buildDetails: (mutationCount, stableTime, wasPaused) => [\n mutationCount !== undefined ? `mutations=${mutationCount}` : '',\n stableTime !== undefined ? `stableTime=${stableTime}ms` : '',\n wasPaused ? 'paused=1' : ''\n ],\n },\n {\n key: 'stream_chunk',\n method: 'streamChunk',\n label: '\u6D41\u5F0F\u7247\u6BB5',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u7247\u6BB5',\n status: '',\n level: 'info',\n attention: 'low',\n throttleKey: 'stream-chunk',\n throttleMs: 2000,\n buildDetails: (length, snippet) => [\n length !== undefined ? `len=${length}` : '',\n snippet ? `preview=\"${normalizeSnippet(snippet)}\"` : ''\n ],\n },\n {\n key: 'stream_events_parsed',\n method: 'streamEventsParsed',\n label: '\u6D41\u5F0F\u4E8B\u4EF6\u89E3\u6790\u5B8C\u6210',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u4E8B\u4EF6\u89E3\u6790',\n status: '\u5B8C\u6210',\n level: 'info',\n attention: 'low',\n throttleKey: 'stream-events',\n throttleMs: 4000,\n buildDetails: (count) => [count !== undefined ? `count=${count}` : ''],\n },\n {\n key: 'stream_complete_event',\n method: 'streamCompleteEvent',\n label: '\u6D41\u5F0F\u5B8C\u6210\u4E8B\u4EF6\u6355\u83B7',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u4E8B\u4EF6',\n status: '\u5B8C\u6210\u4E8B\u4EF6\u5DF2\u6355\u83B7',\n level: 'success',\n attention: 'medium',\n },\n {\n key: 'stream_end',\n method: 'streamEnd',\n label: '\u6D41\u5F0F\u54CD\u5E94\u7ED3\u675F',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u54CD\u5E94',\n status: '\u7ED3\u675F',\n level: 'info',\n attention: 'low',\n },\n {\n key: 'reference_expand_start',\n method: 'referenceExpandStart',\n label: '\u5F15\u7528\u5C55\u5F00\u5F00\u59CB',\n group: '\u5F15\u7528',\n step: '\u5F15\u7528\u5C55\u5F00',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'reference_expand_fail',\n method: 'referenceExpandFail',\n label: '\u5F15\u7528\u5C55\u5F00\u5931\u8D25',\n group: '\u5F15\u7528',\n step: '\u5F15\u7528\u5C55\u5F00',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'medium',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'screenshot_start',\n method: 'screenshotStart',\n label: '\u622A\u56FE\u5F00\u59CB',\n group: '\u622A\u56FE',\n step: '\u622A\u56FE',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n },\n {\n key: 'screenshot_success',\n method: 'screenshotSuccess',\n label: '\u622A\u56FE\u6210\u529F',\n group: '\u622A\u56FE',\n step: '\u622A\u56FE',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n },\n {\n key: 'screenshot_fail',\n method: 'screenshotFail',\n label: '\u622A\u56FE\u5931\u8D25',\n group: '\u622A\u56FE',\n step: '\u622A\u56FE',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'share_start',\n method: 'shareStart',\n label: '\u5206\u4EAB\u94FE\u63A5\u5F00\u59CB',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n },\n {\n key: 'share_progress',\n method: 'shareProgress',\n label: '\u5206\u4EAB\u94FE\u63A5\u6B65\u9AA4',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u6B65\u9AA4',\n level: 'info',\n attention: 'low',\n buildDetails: (label) => [label ? `\u6B65\u9AA4=${label}` : ''],\n },\n {\n key: 'share_dom_hit',\n method: 'shareDomHit',\n label: '\u5206\u4EAB\u94FE\u63A5DOM\u547D\u4E2D',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: 'DOM\u547D\u4E2D',\n level: 'info',\n attention: 'low',\n buildDetails: (link, domSnapshot) => [\n link ? `\u94FE\u63A5=${link}` : '',\n domSnapshot ? `DOM=${normalizeSnippet(domSnapshot, 220)}` : ''\n ],\n },\n {\n key: 'share_source',\n method: 'shareSource',\n label: '\u5206\u4EAB\u94FE\u63A5\u6765\u6E90',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u6765\u6E90',\n level: 'info',\n attention: 'low',\n buildDetails: (source, link, domSnapshot) => [\n source ? `\u6765\u6E90=${source}` : '',\n link ? `\u94FE\u63A5=${link}` : '',\n source === 'dom' && domSnapshot ? `DOM=${normalizeSnippet(domSnapshot, 220)}` : ''\n ],\n },\n {\n key: 'share_success',\n method: 'shareSuccess',\n label: '\u5206\u4EAB\u94FE\u63A5\u6210\u529F',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n buildDetails: (link) => [link ? `\u94FE\u63A5=${link}` : ''],\n },\n {\n key: 'share_fail',\n method: 'shareFail',\n label: '\u5206\u4EAB\u94FE\u63A5\u5931\u8D25',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'share_skip',\n method: 'shareSkip',\n label: '\u5206\u4EAB\u94FE\u63A5\u8DF3\u8FC7',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u8DF3\u8FC7',\n level: 'warning',\n attention: 'medium',\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\n },\n {\n key: 'ai_search_card_detect_attempt',\n method: 'aiSearchCardDetectAttempt',\n label: 'AI Search \u5361\u7247\u8BC6\u522B\u5C1D\u8BD5',\n group: 'AI Search',\n step: 'AI Search \u5361\u7247\u8BC6\u522B',\n status: '\u5C1D\u8BD5',\n level: 'info',\n attention: 'low',\n buildDetails: (attempt = 1, maxAttempts = 1, url = '') => [\n `attempt=${attempt}/${maxAttempts}`,\n url ? `url=${url}` : '',\n ],\n },\n {\n key: 'ai_search_card_detect_success',\n method: 'aiSearchCardDetectSuccess',\n label: 'AI Search \u5361\u7247\u8BC6\u522B\u6210\u529F',\n group: 'AI Search',\n step: 'AI Search \u5361\u7247\u8BC6\u522B',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n buildDetails: (cardType = '', attempts = 1, refreshCount = 0, url = '') => [\n cardType ? `cardType=${cardType}` : '',\n `attempts=${attempts}`,\n `refreshCount=${refreshCount}`,\n url ? `url=${url}` : '',\n ],\n },\n {\n key: 'ai_search_card_empty_result_success',\n method: 'aiSearchCardEmptyResultSuccess',\n label: 'AI Search \u7A7A\u7ED3\u679C\u6210\u529F',\n group: 'AI Search',\n step: 'AI Search \u7A7A\u7ED3\u679C',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n buildDetails: (contentLeftTpls = [], targetTpls = [], url = '', attempts = 0, refreshCount = 0) => [\n Array.isArray(contentLeftTpls) ? `contentLeftTpls=${normalizeSnippet(contentLeftTpls.join(','), 200)}` : '',\n Array.isArray(targetTpls) ? `targetTpls=${normalizeSnippet(targetTpls.join(','), 200)}` : '',\n `attempts=${attempts}`,\n `refreshCount=${refreshCount}`,\n url ? `url=${url}` : '',\n ],\n },\n {\n key: 'data_push_success',\n method: 'dataPushSuccess',\n label: '\u6570\u636E\u63A8\u9001\u6210\u529F',\n group: '\u6570\u636E\u63A8\u9001',\n step: '\u6570\u636E\u63A8\u9001',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u8BF4\u660E=${label}` : ''],\n },\n {\n key: 'data_push_fail',\n method: 'dataPushFail',\n label: '\u6570\u636E\u63A8\u9001\u5931\u8D25',\n group: '\u6570\u636E\u63A8\u9001',\n step: '\u6570\u636E\u63A8\u9001',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'popup_detected',\n method: 'popupDetected',\n label: '\u5F39\u7A97\u68C0\u6D4B',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u68C0\u6D4B\u5230\u906E\u7F69',\n level: 'warning',\n attention: 'medium',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'popup_close_attempt',\n method: 'popupCloseAttempt',\n label: '\u5F39\u7A97\u5173\u95ED\u5C1D\u8BD5',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u5C1D\u8BD5\u5173\u95ED',\n level: 'info',\n attention: 'low',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'popup_close_success',\n method: 'popupCloseSuccess',\n label: '\u5F39\u7A97\u5173\u95ED\u5B8C\u6210',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u5173\u95ED\u5B8C\u6210',\n level: 'success',\n attention: 'medium',\n },\n {\n key: 'popup_close_fail',\n method: 'popupCloseFail',\n label: '\u5F39\u7A97\u5173\u95ED\u5931\u8D25',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u5173\u95ED\u5931\u8D25',\n level: 'warning',\n attention: 'medium',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n];\n\nexport const LOG_TEMPLATES = LOG_DEFINITIONS.map((definition) => {\n const attention = definition.attention || 'medium';\n const attentionRank = ATTENTION_RANK[attention] || ATTENTION_RANK.medium;\n const defaultSelected = attentionRank >= DEFAULT_ATTENTION_RANK;\n return {\n key: definition.key,\n label: definition.label,\n group: definition.group,\n attention,\n patterns: buildDefinitionPatterns(definition),\n defaultSelected,\n };\n});\n\nconst buildStepLine = (step, status, details = []) => {\n const parts = [];\n const decoratedStep = step ? decorateLabel(step, STEP_EMOJIS) : '';\n const base = decoratedStep ? `${STEP_PREFIX} ${decoratedStep}` : STEP_PREFIX;\n parts.push(base.trim());\n if (status) parts.push(decorateLabel(status, STATUS_EMOJIS));\n const detailParts = details.filter(Boolean);\n if (detailParts.length > 0) {\n parts.push(...detailParts);\n }\n return parts.join(STEP_SEPARATOR);\n};\n\nconst createThrottle = () => {\n const lastMap = new Map();\n return (key, intervalMs, fn) => {\n const now = Date.now();\n const last = lastMap.get(key) || 0;\n if (now - last >= intervalMs) {\n lastMap.set(key, now);\n fn();\n }\n };\n};\n\nexport const createTemplateLogger = (baseLogger = createBaseLogger()) => {\n const throttle = createThrottle();\n\n const info = (line) => baseLogger.info(line);\n const success = (line) => baseLogger.success(line);\n const warning = (line) => baseLogger.warning(line);\n const error = (line) => baseLogger.error(line);\n const debug = (line) => baseLogger.debug(line);\n const start = (line) => baseLogger.start(line);\n\n const stepInfo = (step, status, details = []) => info(buildStepLine(step, status, details));\n const stepSuccess = (step, status, details = []) => success(buildStepLine(step, status, details));\n const stepWarn = (step, status, details = []) => warning(buildStepLine(step, status, details));\n const stepError = (step, status, details = []) => error(buildStepLine(step, status, details));\n const stepStart = (step, status, details = []) => start(buildStepLine(step, status, details));\n\n const stepHandlers = {\n info: stepInfo,\n success: stepSuccess,\n warning: stepWarn,\n error: stepError,\n start: stepStart,\n };\n\n const logFromDefinition = (definition, details = []) => {\n const handler = stepHandlers[definition.level] || stepInfo;\n const payload = [...details, buildLogTag(definition.key)];\n const emit = () => handler(definition.step, definition.status, payload);\n if (definition.throttleMs) {\n throttle(definition.throttleKey || definition.key, definition.throttleMs, emit);\n return;\n }\n emit();\n };\n\n const definitionMethods = {};\n LOG_DEFINITIONS.forEach((definition) => {\n if (!definition.method) return;\n definitionMethods[definition.method] = (...args) => {\n const details = definition.buildDetails ? definition.buildDetails(...args) : [];\n logFromDefinition(definition, details);\n };\n });\n\n return {\n step: (step, status, details, level = 'info') => {\n if (level === 'error') return stepError(step, status, details);\n if (level === 'warn' || level === 'warning') return stepWarn(step, status, details);\n if (level === 'start') return stepStart(step, status, details);\n if (level === 'success') return stepSuccess(step, status, details);\n return stepInfo(step, status, details);\n },\n info: (message) => info(message),\n success: (message) => success(message),\n warning: (message) => warning(message),\n warn: (message) => warning(message),\n error: (message) => error(message),\n debug: (message) => debug(message),\n start: (message) => start(message),\n ...definitionMethods,\n };\n};\n\nconst getDefaultBaseLogger = () => createBaseLogger('');\n\nexport const Logger = {\n setLogger: (logger) => setDefaultLogger(logger),\n info: (message) => getDefaultBaseLogger().info(message),\n success: (message) => getDefaultBaseLogger().success(message),\n warning: (message) => getDefaultBaseLogger().warning(message),\n warn: (message) => getDefaultBaseLogger().warning(message),\n error: (message) => getDefaultBaseLogger().error(message),\n debug: (message) => getDefaultBaseLogger().debug(message),\n start: (message) => getDefaultBaseLogger().start(message),\n useTemplate: (logger) => {\n if (logger) return createTemplateLogger(createBaseLogger('', logger));\n return createTemplateLogger();\n },\n};\n", "import delay from 'delay';\nimport { Utils } from './utils.js';\nimport { Mutation } from './mutation.js';\nimport { createInternalLogger } from './internals/logger.js';\nimport { capturePageScreenshot } from './internals/screenshot.js';\n\nconst logger = createInternalLogger('Share');\n\nconst DEFAULT_TIMEOUT_MS = 50 * 1000;\nconst DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;\nconst DEFAULT_POLL_INTERVAL_MS = 120;\n\nconst normalizePrefix = (value) => value == null ? undefined : String(value).trim();\n\nconst toSnapshot = (value, maxLen) => {\n const text = String(value || '');\n if (!text) return '';\n return text.replace(/\\s+/g, ' ').trim().slice(0, maxLen);\n};\n\nconst toInline = (value, maxLen = 200) => {\n const text = String(value || '');\n if (!text) return '';\n return text.replace(/\\s+/g, ' ').trim().slice(0, maxLen);\n};\n\nconst toJsonInline = (value, maxLen = 260) => {\n try {\n return toInline(JSON.stringify(value), maxLen);\n } catch {\n return '[\u4E0D\u53EF\u5E8F\u5217\u5316]';\n }\n};\n\nconst normalizeXurl = (value) => {\n if (!Array.isArray(value)) return [];\n\n const normalizeMatcherList = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const single = String(input || '').trim().replace(/\\.+$/, '');\n return single ? [single] : [];\n };\n\n const normalizeSegments = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const raw = String(input || '').trim();\n if (!raw) return [];\n\n return raw\n .split('.')\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n };\n\n const normalized = [];\n\n const apiMatchers = normalizeMatcherList(value[0]);\n if (apiMatchers.length > 0) {\n normalized.push(apiMatchers);\n }\n\n const flattenedPath = [];\n const extraPaths = [];\n\n value.slice(1).forEach((item) => {\n if (Array.isArray(item)) {\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n extraPaths.push(segments);\n }\n return;\n }\n\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n flattenedPath.push(...segments);\n }\n });\n\n if (flattenedPath.length > 0) {\n normalized.push(flattenedPath);\n }\n\n if (extraPaths.length > 0) {\n normalized.push(...extraPaths);\n }\n\n return normalized;\n};\n\nconst normalizeShare = (share) => {\n const source = share && typeof share === 'object' ? share : {};\n const modeRaw = String(source.mode || 'dom').trim().toLowerCase();\n const mode = modeRaw === 'response' ? 'response' : 'dom';\n\n return {\n mode,\n prefix: normalizePrefix(source.prefix),\n xurl: normalizeXurl(source.xurl),\n };\n};\n\nconst getByPathSegments = (source, pathSegments) => {\n if (!Array.isArray(pathSegments) || pathSegments.length === 0) return undefined;\n\n let current = source;\n\n for (const rawSegment of pathSegments) {\n const segment = String(rawSegment || '').trim();\n if (!segment) return undefined;\n if (current == null) return undefined;\n\n if (Array.isArray(current) && /^\\d+$/.test(segment)) {\n current = current[Number(segment)];\n continue;\n }\n\n current = current[segment];\n }\n\n return current;\n};\n\nconst buildShareLink = (prefix, value) => {\n const raw = String(value || '').trim();\n if (!raw) return '';\n\n if (/^https?:\\/\\//i.test(raw)) {\n return raw;\n }\n\n const safePrefix = normalizePrefix(prefix);\n if (!safePrefix) return '';\n\n const valueNoSlash = raw.replace(/^\\/+/, '');\n\n if (/[?&=]$/.test(safePrefix)) {\n return `${safePrefix}${valueNoSlash}`;\n }\n\n const prefixNoSlash = safePrefix.replace(/\\/+$/, '');\n return `${prefixNoSlash}/${valueNoSlash}`;\n};\n\nconst parseJsonSafely = (text) => {\n const raw = String(text || '').trim();\n if (!raw) return null;\n\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n};\n\nconst createDomShareMonitor = async (page, options = {}) => {\n const prefix = normalizePrefix(options.prefix);\n const selectors = options.selectors ?? 'html';\n const mode = options.mode ?? Mutation.Mode.All;\n const onMatch = typeof options.onMatch === 'function' ? options.onMatch : null;\n const onTelemetry = typeof options.onTelemetry === 'function' ? options.onTelemetry : null;\n\n let matched = false;\n\n logger.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);\n\n const monitor = await Mutation.useMonitor(page, selectors, {\n mode,\n onMutation: (context = {}) => {\n if (matched) return;\n\n const mutationCount = Number(context.mutationCount || 0);\n const mutationNodes = Array.isArray(context.mutationNodes) ? context.mutationNodes : [];\n const html = String(context.html || '');\n const text = String(context.text || '');\n const rawDom = `${html}\\n${text}`;\n\n if (onTelemetry) {\n onTelemetry({\n mutationCount,\n mutationNodesCount: mutationNodes.length,\n });\n }\n\n if (mutationCount <= 5 || mutationCount % 50 === 0) {\n logger.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);\n }\n\n const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];\n if (!candidate) return;\n\n matched = true;\n logger.success('captureLink.domHit', `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);\n\n if (onMatch) {\n onMatch({\n link: candidate,\n rawDom,\n mutationCount,\n html,\n text,\n mutationNodes,\n });\n }\n },\n });\n\n return {\n stop: async () => {\n const result = await monitor.stop();\n logger.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);\n return result;\n },\n };\n};\n\nexport const Share = {\n /**\n * \u6355\u83B7\u5206\u4EAB\u94FE\u63A5\uFF08\u5355\u6A21\u5F0F\uFF09\n * - mode='dom': \u4EC5 DOM \u76D1\u542C\n * - mode='response': \u4EC5\u63A5\u53E3\u76D1\u542C\n *\n * @param {import('playwright').Page} page\n * @param {Object} [options]\n * @param {{ mode?: 'dom' | 'response', prefix: string, xurl?: Array<string | string[]> }} options.share\n * @param {number} [options.timeoutMs=50000]\n * @param {number} [options.payloadSnapshotMaxLen=500]\n * @param {string | string[]} [options.domSelectors='html']\n * @param {'added' | 'changed' | 'all'} [options.domMode='all']\n * @param {() => Promise<void>} [options.performActions]\n * @returns {Promise<{ link: string | null; payloadText: string; payloadSnapshot: string; source: 'dom' | 'response' | 'none' }>}\n */\n async captureLink(page, options = {}) {\n const share = normalizeShare(options.share);\n const timeoutMs = Math.max(0, Number(options.timeoutMs ?? DEFAULT_TIMEOUT_MS) || 0);\n const payloadSnapshotMaxLen = options.payloadSnapshotMaxLen ?? DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN;\n const domSelectors = options.domSelectors ?? 'html';\n const domMode = options.domMode ?? Mutation.Mode.All;\n const performActions = typeof options.performActions === 'function' ? options.performActions : async () => { };\n\n if (share.prefix === undefined) {\n throw new Error('Share.captureLink requires options.share.prefix');\n }\n\n if (share.mode !== 'dom' && share.mode !== 'response') {\n throw new Error(`Share.captureLink unsupported share.mode: ${share.mode}`);\n }\n\n const apiMatchers = share.mode === 'response' ? (share.xurl[0] || []) : [];\n const fieldPaths = share.mode === 'response' ? share.xurl.slice(1) : [];\n\n if (share.mode === 'response' && apiMatchers.length === 0) {\n throw new Error('Share.captureLink requires share.xurl[0] api matcher when mode=response');\n }\n\n logger.start('captureLink', `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);\n logger.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);\n\n const stats = {\n actionTimedOut: false,\n domMutationCount: 0,\n domMutationNodes: 0,\n responseObserved: 0,\n responseMatched: 0,\n responseResolved: 0,\n lastMatchedUrl: '',\n responseSampleUrls: [],\n };\n\n const candidates = {\n dom: null,\n response: null,\n };\n\n const setCandidate = (source, link, payloadText = '') => {\n const safe = String(link || '').trim();\n if (!safe) return false;\n\n const [validated] = Utils.parseLinks(safe, { prefix: share.prefix }) || [];\n if (!validated) return false;\n\n if (candidates[source]?.link) return false;\n\n candidates[source] = {\n link: validated,\n payloadText: String(payloadText || ''),\n };\n\n logger.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);\n return true;\n };\n\n const resolveResponseCandidate = (responseText) => {\n const rawText = String(responseText || '');\n if (!rawText) return null;\n\n const [direct] = Utils.parseLinks(rawText, { prefix: share.prefix }) || [];\n if (direct) {\n return { link: direct, payloadText: rawText };\n }\n\n if (fieldPaths.length === 0) return null;\n\n const payload = parseJsonSafely(rawText);\n if (!payload || typeof payload !== 'object') return null;\n\n for (const pathSegments of fieldPaths) {\n const value = getByPathSegments(payload, pathSegments);\n if (value == null || value === '') continue;\n\n const composed = buildShareLink(share.prefix, value);\n if (!composed) continue;\n\n const [validated] = Utils.parseLinks(composed, { prefix: share.prefix }) || [];\n if (!validated) continue;\n\n return {\n link: validated,\n payloadText: rawText,\n };\n }\n\n return null;\n };\n\n let domMonitor = null;\n\n const stopDomMonitor = async () => {\n if (!domMonitor) return;\n const monitor = domMonitor;\n domMonitor = null;\n try {\n await monitor.stop();\n } catch (error) {\n logger.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n\n const onResponse = async (response) => {\n if (share.mode !== 'response') return;\n if (candidates.response?.link) return;\n\n stats.responseObserved += 1;\n\n try {\n const url = String(response.url() || '');\n\n if (url && stats.responseSampleUrls.length < 8 && !stats.responseSampleUrls.includes(url)) {\n stats.responseSampleUrls.push(url);\n }\n\n if (stats.responseObserved <= 5) {\n logger.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);\n }\n\n if (!apiMatchers.some((matcher) => url.includes(matcher))) return;\n\n stats.responseMatched += 1;\n stats.lastMatchedUrl = url;\n logger.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);\n\n const text = await response.text();\n const hit = resolveResponseCandidate(text);\n if (!hit?.link) {\n if (stats.responseMatched <= 3) {\n logger.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);\n }\n return;\n }\n\n stats.responseResolved += 1;\n logger.success('captureLink.responseHit', `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);\n setCandidate('response', hit.link, hit.payloadText);\n } catch (error) {\n logger.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n\n if (share.mode === 'dom') {\n logger.info('\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C');\n domMonitor = await createDomShareMonitor(page, {\n prefix: share.prefix,\n selectors: domSelectors,\n mode: domMode,\n onTelemetry: ({ mutationCount, mutationNodesCount }) => {\n stats.domMutationCount = mutationCount;\n stats.domMutationNodes = mutationNodesCount;\n },\n onMatch: ({ link, rawDom }) => {\n setCandidate('dom', link, rawDom);\n },\n });\n }\n\n if (share.mode === 'response') {\n logger.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);\n page.on('response', onResponse);\n }\n\n const deadline = Date.now() + timeoutMs;\n const getRemainingMs = () => Math.max(0, deadline - Date.now());\n\n try {\n const actionTimeout = getRemainingMs();\n logger.start('captureLink.performActions', `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);\n\n if (actionTimeout > 0) {\n let timer = null;\n let actionError = null;\n\n const actionPromise = Promise.resolve()\n .then(() => performActions())\n .then(() => '__ACTION_DONE__')\n .catch((error) => {\n actionError = error;\n return '__ACTION_ERROR__';\n });\n\n const timeoutPromise = new Promise((resolve) => {\n timer = setTimeout(() => resolve('__ACTION_TIMEOUT__'), actionTimeout);\n });\n\n const actionResult = await Promise.race([actionPromise, timeoutPromise]);\n if (timer) clearTimeout(timer);\n\n if (actionResult === '__ACTION_ERROR__') {\n logger.fail('captureLink.performActions', actionError);\n throw actionError;\n }\n\n if (actionResult === '__ACTION_TIMEOUT__') {\n stats.actionTimedOut = true;\n logger.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);\n } else {\n logger.success('captureLink.performActions', '\u6267\u884C\u52A8\u4F5C\u5B8C\u6210');\n }\n }\n\n let nextProgressLogTs = Date.now() + 3000;\n\n while (true) {\n const selected = share.mode === 'dom' ? candidates.dom : candidates.response;\n if (selected?.link) {\n logger.success('captureLink', `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);\n return {\n link: selected.link,\n payloadText: selected.payloadText,\n payloadSnapshot: toSnapshot(selected.payloadText, payloadSnapshotMaxLen),\n source: share.mode,\n };\n }\n\n const remaining = getRemainingMs();\n if (remaining <= 0) break;\n\n const now = Date.now();\n if (now >= nextProgressLogTs) {\n logger.info(\n `captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`\n );\n nextProgressLogTs = now + 5000;\n }\n\n await delay(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));\n }\n\n if (share.mode === 'response' && stats.responseMatched === 0) {\n logger.warning(\n `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`\n );\n }\n\n logger.warning(\n `captureLink \u8D85\u65F6\u672A\u62FF\u5230\u94FE\u63A5: mode=${share.mode}, actionTimedOut=${stats.actionTimedOut}, domMutationCount=${stats.domMutationCount}, responseObserved=${stats.responseObserved}, responseMatched=${stats.responseMatched}, lastMatchedUrl=${stats.lastMatchedUrl || 'none'}`\n );\n\n return {\n link: null,\n payloadText: '',\n payloadSnapshot: '',\n source: 'none',\n };\n } finally {\n if (share.mode === 'response') {\n page.off('response', onResponse);\n logger.info('response \u76D1\u542C\u5DF2\u5378\u8F7D');\n }\n await stopDomMonitor();\n }\n },\n\n\n /**\n * \u5168\u9875\u9762\u6EDA\u52A8\u622A\u56FE\uFF08\u57FA\u7840\u80FD\u529B\uFF09\n *\n * @param {import('playwright').Page} page\n * @param {Object} [options]\n * @param {number} [options.buffer]\n * @param {boolean} [options.restore]\n * @param {number} [options.maxHeight]\n * @returns {Promise<string>} base64 png\n */\n async captureScreen(page, options = {}) {\n const originalViewport = page.viewportSize();\n const defaultBuffer = Math.round((originalViewport?.height || 1080) / 2);\n const buffer = options.buffer ?? defaultBuffer;\n const restore = options.restore ?? false;\n const maxHeight = options.maxHeight ?? 8000;\n\n try {\n const maxScrollHeight = await page.evaluate(() => {\n let maxHeight = document.body.scrollHeight;\n\n document.querySelectorAll('*').forEach(el => {\n const style = window.getComputedStyle(el);\n const overflowY = style.overflowY;\n\n if ((overflowY === 'auto' || overflowY === 'scroll') &&\n el.scrollHeight > el.clientHeight) {\n if (el.scrollHeight > maxHeight) {\n maxHeight = el.scrollHeight;\n }\n\n el.dataset.pkOrigOverflow = el.style.overflow;\n el.dataset.pkOrigHeight = el.style.height;\n el.dataset.pkOrigMaxHeight = el.style.maxHeight;\n el.classList.add('__pk_expanded__');\n\n el.style.overflow = 'visible';\n el.style.height = 'auto';\n el.style.maxHeight = 'none';\n }\n });\n\n return maxHeight;\n });\n\n const targetHeight = Math.min(maxScrollHeight + buffer, maxHeight);\n\n await page.setViewportSize({\n width: originalViewport?.width || 1280,\n height: targetHeight,\n });\n\n await delay(1000);\n const buffer_ = await capturePageScreenshot(page, {\n fullPage: true,\n type: 'png',\n maxClipHeight: targetHeight,\n });\n\n return buffer_.toString('base64');\n } finally {\n if (restore) {\n await page.evaluate(() => {\n document.querySelectorAll('.__pk_expanded__').forEach(el => {\n el.style.overflow = el.dataset.pkOrigOverflow || '';\n el.style.height = el.dataset.pkOrigHeight || '';\n el.style.maxHeight = el.dataset.pkOrigMaxHeight || '';\n\n delete el.dataset.pkOrigOverflow;\n delete el.dataset.pkOrigHeight;\n delete el.dataset.pkOrigMaxHeight;\n el.classList.remove('__pk_expanded__');\n });\n });\n\n if (originalViewport) {\n await page.setViewportSize(originalViewport);\n }\n }\n }\n },\n};\n"],
5
5
  "mappings": "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",
6
6
  "names": ["normalizeShare", "segments", "protocol", "domain", "path", "logger", "import_serialize_error", "logger", "path", "path", "frameUrls", "runtime", "logger", "Actor", "logger", "logger", "logger", "delay", "picomatch", "logger", "logger", "express", "logger", "uuidv4", "cleanerName", "import_uuid", "logger", "uuidv4", "result", "selectorList", "stableTime", "timeout", "callbackName", "path", "monitorKey", "cleanerName", "mode", "text", "logger", "import_delay", "logger", "DEFAULT_TIMEOUT_MS", "segments", "delay", "maxHeight", "crawleeLog"]
7
7
  }