@mearl/native-host 2.9.1 → 2.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +34 -31
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -457,9 +457,12 @@ Next steps:
|
|
|
457
457
|
|
|
458
458
|
Verify:
|
|
459
459
|
mearl get_requests --payload '{"count":1}'
|
|
460
|
-
`),success2?0:1}var DEFAULT_EXTENSION_ID,__filename,__dirname2,ALL_MODES,init_install=__esm({"src/install.ts"(){"use strict";init_nativeHost();DEFAULT_EXTENSION_ID="aoehhjnofngknnjefamjbplchbolghkm",__filename=fileURLToPath4(import.meta.url),__dirname2=path20.dirname(__filename),ALL_MODES=["skills","mcp"]}});var runtimeArgs_exports={};__export(runtimeArgs_exports,{parseNativeHostRuntimeArgs:()=>parseNativeHostRuntimeArgs});function stripNativeMessagingLaunchArgs(argv){let[origin,parentWindow,...rest]=argv;return/^chrome-extension:\/\/[a-z]{32}\/$/.test(origin??"")?/^--parent-window=\d+$/.test(parentWindow??"")?rest:argv.slice(1):argv}async function parseNativeHostRuntimeArgs(argv,minimumIdleReleaseMinutes){let args=stripNativeMessagingLaunchArgs(argv),options={},readValue=(index,name)=>{let argument=args[index];if(argument===name){let value=args[index+1];if(value===void 0||value.startsWith("-"))throw new Error(`argument missing for option '${name}'`);return{nextIndex:index+1,value}}return argument?.startsWith(`${name}=`)?{nextIndex:index,value:argument.slice(name.length+1)}:null},parseInteger=(value,label,minimum,maximum)=>{let parsed=Number(value);if(!Number.isInteger(parsed)||parsed<minimum||parsed>maximum)throw new Error(`${label} must be an integer from ${minimum} to ${maximum}`);return parsed};for(let index=0;index<args.length;index+=1){let argument=args[index];if(argument==="--daemon"){options.daemon=!0;continue}if(argument==="--skip-browser-registration"){options.skipBrowserRegistration=!0;continue}if(argument==="--version"||argument==="-v"){options.version=!0;continue}if(argument==="--help"||argument==="-h"){options.help=!0;continue}let cdpPort=readValue(index,"--cdp-port");if(cdpPort){options.cdpPort=parseInteger(cdpPort.value,"cdp-port",1,65535),index=cdpPort.nextIndex;continue}let idleRelease=readValue(index,"--agentbay-idle-release-minutes");if(idleRelease){options.agentBayIdleReleaseMinutes=parseInteger(idleRelease.value,"agentbay-idle-release-minutes",minimumIdleReleaseMinutes,Number.MAX_SAFE_INTEGER),index=idleRelease.nextIndex;continue}let stringOptions=[["--cdp-user-data-dir","cdpUserDataDir"],["--agentbay-session-id","agentBaySessionId"],["--browser-id","browserId"],["--browser-name","browserName"]],matchedStringOption=!1;for(let[name,property]of stringOptions){let parsed=readValue(index,name);if(parsed){options[property]=parsed.value,index=parsed.nextIndex,matchedStringOption=!0;break}}if(!matchedStringOption)throw new Error(argument?.startsWith("-")?`unknown option '${argument}'`:`unexpected argument '${argument}'`)}return{...options.agentBayIdleReleaseMinutes!==void 0?{agentBayIdleReleaseMinutes:options.agentBayIdleReleaseMinutes}:{},...options.agentBaySessionId?{agentBaySessionId:options.agentBaySessionId}:{},browserId:options.browserId??"cdp",browserName:options.browserName??"CDP",cdpPort:options.cdpPort??9222,...options.cdpUserDataDir?{cdpUserDataDir:options.cdpUserDataDir}:{},daemon:options.daemon===!0,help:options.help===!0,skipBrowserRegistration:options.skipBrowserRegistration===!0,version:options.version===!0}}var init_runtimeArgs=__esm({"src/runtimeArgs.ts"(){"use strict"}});import net2 from"node:net";import fs20 from"node:fs";import http4 from"node:http";import os10 from"node:os";import path21 from"node:path";import{fileURLToPath as fileURLToPath5}from"node:url";import http2 from"node:http";import WebSocket from"ws";var CdpChildSession=class{constructor(parent,sessionId){this.parent=parent;this.sessionId=sessionId}sendCommand(method,params,timeoutMs=3e4){return this.parent.sendCommandInSession(this.sessionId,method,params,timeoutMs)}on(method,callback){return this.parent.onSession(this.sessionId,method,callback)}createChildSession(sessionId){return this.parent.createChildSession(sessionId)}get closed(){return this.parent.closed}close(){}},CdpClient=class _CdpClient{constructor(socket){this.socket=socket;socket.on("message",data=>this.consumeMessage(data)),socket.on("close",()=>this.handleClosed()),socket.on("error",()=>this.handleClosed())}nextId=1;pending=new Map;eventHandlers=new Map;sessionEventHandlers=new Map;_closed=!1;static connect(wsUrl){return new Promise((resolve3,reject)=>{let url2;try{url2=new URL(wsUrl)}catch{reject(new Error("Invalid CDP WebSocket URL"));return}if(url2.protocol!=="ws:"&&url2.protocol!=="wss:"){reject(new Error(`Unsupported CDP WebSocket protocol: ${url2.protocol}`));return}let socket=new WebSocket(url2,{handshakeTimeout:5e3,maxPayload:64*1024*1024,perMessageDeflate:!1}),settled=!1,fail=error48=>{settled||(settled=!0,socket.terminate(),reject(error48))};socket.once("open",()=>{settled||(settled=!0,resolve3(new _CdpClient(socket)))}),socket.once("error",fail),socket.once("unexpected-response",(_request,response)=>{response.resume(),fail(new Error(`CDP WebSocket upgrade failed with status ${response.statusCode??0}`))})})}createChildSession(sessionId){return new CdpChildSession(this,sessionId)}sendCommandInSession(sessionId,method,params,timeoutMs=3e4){return this.sendRequest(method,params,timeoutMs,sessionId)}onSession(sessionId,method,callback){this.sessionEventHandlers.has(sessionId)||this.sessionEventHandlers.set(sessionId,new Map);let sessionMap=this.sessionEventHandlers.get(sessionId);return sessionMap.has(method)||sessionMap.set(method,new Set),sessionMap.get(method).add(callback),()=>sessionMap.get(method)?.delete(callback)}sendCommand(method,params,timeoutMs=3e4){return this.sendRequest(method,params,timeoutMs)}on(method,callback){return this.eventHandlers.has(method)||this.eventHandlers.set(method,new Set),this.eventHandlers.get(method).add(callback),()=>this.eventHandlers.get(method)?.delete(callback)}close(){this._closed||(this._closed=!0,this.socket.terminate(),this.rejectPending("CDP connection closed"))}get closed(){return this._closed}sendRequest(method,params,timeoutMs,sessionId){return new Promise((resolve3,reject)=>{if(this._closed||this.socket.readyState!==WebSocket.OPEN){reject(new Error("CDP client is closed"));return}let id=this.nextId++,timer=setTimeout(()=>{this.pending.delete(id),reject(new Error(`CDP command timeout: ${method}`))},timeoutMs);this.pending.set(id,{resolve:resolve3,reject,timer,sessionId}),this.socket.send(JSON.stringify({id,method,params:params??{},...sessionId?{sessionId}:{}}),error48=>{if(!error48)return;let pending=this.pending.get(id);pending&&(clearTimeout(pending.timer),this.pending.delete(id),pending.reject(error48))})})}consumeMessage(data){try{let text=Array.isArray(data)?Buffer.concat(data).toString("utf8"):Buffer.isBuffer(data)?data.toString("utf8"):Buffer.from(data).toString("utf8");this.handleMessage(JSON.parse(text))}catch{}}handleMessage(msg){if(msg.id!==void 0){let pending=this.pending.get(msg.id);if(!pending)return;clearTimeout(pending.timer),this.pending.delete(msg.id),msg.error?pending.reject(new Error(msg.error.message??JSON.stringify(msg.error))):pending.resolve(msg.result??{});return}if(!msg.method)return;let handlers=msg.sessionId?this.sessionEventHandlers.get(msg.sessionId)?.get(msg.method):this.eventHandlers.get(msg.method);if(handlers)for(let callback of handlers)try{callback(msg.params)}catch{}}handleClosed(){this._closed||(this._closed=!0,this.rejectPending("CDP connection closed"))}rejectPending(message){for(let[id,pending]of this.pending)clearTimeout(pending.timer),pending.reject(new Error(message)),this.pending.delete(id)}};function md5(input){function rotateLeft(v,s){return v<<s|v>>>32-s}function addUnsigned(x,y){let lsw=(x&65535)+(y&65535);return(x>>16)+(y>>16)+(lsw>>16)<<16|lsw&65535}function cmn(q,a2,b2,x,s,t){return addUnsigned(rotateLeft(addUnsigned(addUnsigned(a2,q),addUnsigned(x,t)),s),b2)}function ff(a2,b2,c2,d2,x,s,t){return cmn(b2&c2|~b2&d2,a2,b2,x,s,t)}function gg(a2,b2,c2,d2,x,s,t){return cmn(b2&d2|c2&~d2,a2,b2,x,s,t)}function hh(a2,b2,c2,d2,x,s,t){return cmn(b2^c2^d2,a2,b2,x,s,t)}function ii(a2,b2,c2,d2,x,s,t){return cmn(c2^(b2|~d2),a2,b2,x,s,t)}let str=input.replace(/\r\n/g,`
|
|
461
|
-
`),encoded="";for(let n=0;n<str.length;n++){let c2=str.charCodeAt(n);c2<128?encoded+=String.fromCharCode(c2):c2<2048?(encoded+=String.fromCharCode(c2>>6|192),encoded+=String.fromCharCode(c2&63|128)):(encoded+=String.fromCharCode(c2>>12|224),encoded+=String.fromCharCode(c2>>6&63|128),encoded+=String.fromCharCode(c2&63|128))}str=encoded;let len=str.length,nw=(len+8>>>6)+1<<4,words=new Array(nw).fill(0);for(let i=0;i<len;i++)words[i>>2]|=str.charCodeAt(i)<<i%4*8;words[len>>2]|=128<<len%4*8,words[nw-2]=len<<3,words[nw-1]=len>>>29;let a=1732584193,b=4023233417,c=2562383102,d=271733878;for(let k=0;k<words.length;k+=16){let aa=a,bb=b,cc=c,dd=d;a=ff(a,b,c,d,words[k],7,3614090360),d=ff(d,a,b,c,words[k+1],12,3905402710),c=ff(c,d,a,b,words[k+2],17,606105819),b=ff(b,c,d,a,words[k+3],22,3250441966),a=ff(a,b,c,d,words[k+4],7,4118548399),d=ff(d,a,b,c,words[k+5],12,1200080426),c=ff(c,d,a,b,words[k+6],17,2821735955),b=ff(b,c,d,a,words[k+7],22,4249261313),a=ff(a,b,c,d,words[k+8],7,1770035416),d=ff(d,a,b,c,words[k+9],12,2336552879),c=ff(c,d,a,b,words[k+10],17,4294925233),b=ff(b,c,d,a,words[k+11],22,2304563134),a=ff(a,b,c,d,words[k+12],7,1804603682),d=ff(d,a,b,c,words[k+13],12,4254626195),c=ff(c,d,a,b,words[k+14],17,2792965006),b=ff(b,c,d,a,words[k+15],22,1236535329),a=gg(a,b,c,d,words[k+1],5,4129170786),d=gg(d,a,b,c,words[k+6],9,3225465664),c=gg(c,d,a,b,words[k+11],14,643717713),b=gg(b,c,d,a,words[k],20,3921069994),a=gg(a,b,c,d,words[k+5],5,3593408605),d=gg(d,a,b,c,words[k+10],9,38016083),c=gg(c,d,a,b,words[k+15],14,3634488961),b=gg(b,c,d,a,words[k+4],20,3889429448),a=gg(a,b,c,d,words[k+9],5,568446438),d=gg(d,a,b,c,words[k+14],9,3275163606),c=gg(c,d,a,b,words[k+3],14,4107603335),b=gg(b,c,d,a,words[k+8],20,1163531501),a=gg(a,b,c,d,words[k+13],5,2850285829),d=gg(d,a,b,c,words[k+2],9,4243563512),c=gg(c,d,a,b,words[k+7],14,1735328473),b=gg(b,c,d,a,words[k+12],20,2368359562),a=hh(a,b,c,d,words[k+5],4,4294588738),d=hh(d,a,b,c,words[k+8],11,2272392833),c=hh(c,d,a,b,words[k+11],16,1839030562),b=hh(b,c,d,a,words[k+14],23,4259657740),a=hh(a,b,c,d,words[k+1],4,2763975236),d=hh(d,a,b,c,words[k+4],11,1272893353),c=hh(c,d,a,b,words[k+7],16,4139469664),b=hh(b,c,d,a,words[k+10],23,3200236656),a=hh(a,b,c,d,words[k+13],4,681279174),d=hh(d,a,b,c,words[k],11,3936430074),c=hh(c,d,a,b,words[k+3],16,3572445317),b=hh(b,c,d,a,words[k+6],23,76029189),a=hh(a,b,c,d,words[k+9],4,3654602809),d=hh(d,a,b,c,words[k+12],11,3873151461),c=hh(c,d,a,b,words[k+15],16,530742520),b=hh(b,c,d,a,words[k+2],23,3299628645),a=ii(a,b,c,d,words[k],6,4096336452),d=ii(d,a,b,c,words[k+7],10,1126891415),c=ii(c,d,a,b,words[k+14],15,2878612391),b=ii(b,c,d,a,words[k+5],21,4237533241),a=ii(a,b,c,d,words[k+12],6,1700485571),d=ii(d,a,b,c,words[k+3],10,2399980690),c=ii(c,d,a,b,words[k+10],15,4293915773),b=ii(b,c,d,a,words[k+1],21,2240044497),a=ii(a,b,c,d,words[k+8],6,1873313359),d=ii(d,a,b,c,words[k+15],10,4264355552),c=ii(c,d,a,b,words[k+6],15,2734768916),b=ii(b,c,d,a,words[k+13],21,1309151649),a=ii(a,b,c,d,words[k+4],6,4149444226),d=ii(d,a,b,c,words[k+11],10,3174756917),c=ii(c,d,a,b,words[k+2],15,718787259),b=ii(b,c,d,a,words[k+9],21,3951481745),a=addUnsigned(a,aa),b=addUnsigned(b,bb),c=addUnsigned(c,cc),d=addUnsigned(d,dd)}let hex3=v=>{let s="";for(let i=0;i<=3;i++){let byte=v>>>i*8&255;s+=("0"+byte.toString(16)).slice(-2)}return s};return(hex3(a)+hex3(b)+hex3(c)+hex3(d)).toLowerCase()}function extractMtopToken(cookieMap,isMopen){if(isMopen){let mTk=cookieMap.get("m_tk"),tbToken=cookieMap.get("_tb_token_");if(mTk)return mTk.split("_")[0]||"";if(tbToken)return tbToken;throw new Error("Missing m_tk or _tb_token_ cookie. Please ensure the user is logged in.")}let h5Tk=cookieMap.get("_m_h5_tk");if(h5Tk)return h5Tk.split("_")[0]||"";throw new Error("Missing _m_h5_tk cookie. Please ensure the user is logged in.")}function computeMtopSign(params){let{api,version:version2,timestamp,appKey,token,dataStr,isMopen}=params;return md5(isMopen?`${api}&${version2}&${timestamp}&${appKey}&${token}&${md5(dataStr)}`:`${token}&${timestamp}&${appKey}&${dataStr}`)}var MTOP_HOST_MAP={online:"h5api.m.taobao.com",pre:"h5api.wapa.taobao.com"};function buildCookieHeaderValue(cookieMap){return[...cookieMap.entries()].map(([k,v])=>`${k}=${v}`).join("; ")}var APLUS_URL_PATTERN=/\.mmstat\.com\//,RUM_URL_PATTERN=/\.rum\.aliyuncs\.com\//,ARMS_URL_PATTERN=/arms-retcode\.aliyuncs\.com\//;function isTrackingUrl(url2){return APLUS_URL_PATTERN.test(url2)||RUM_URL_PATTERN.test(url2)||ARMS_URL_PATTERN.test(url2)||/retcode\.alicdn\.com|beacon\.taobao\.com|tbsec\./i.test(url2)}var aplusCounter=0,armsCounter=0,rumCounter=0;function formatTimestamp(ms){let d=new Date(ms),pad=n=>String(n).padStart(2,"0");return`${d.getFullYear()}/${pad(d.getMonth()+1)}/${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`}function parseParams(value){let params={};return value.split("&").forEach(pair=>{let eqIndex=pair.indexOf("=");if(eqIndex===-1)return;let rawKey=pair.slice(0,eqIndex),rawValue=pair.slice(eqIndex+1);try{params[decodeURIComponent(rawKey)]=rawValue}catch{params[rawKey]=rawValue}}),params}function decodeParamValue(value){try{return decodeURIComponent(value)}catch{return value}}function parseUrlParams(search){let encodedParams=parseParams(search.startsWith("?")?search.slice(1):search);return Object.fromEntries(Object.entries(encodedParams).map(([key,value])=>[key,decodeParamValue(value)]))}function extractSpmFromUrl(spmOrUrl){if(!/^https?:\/\//i.test(spmOrUrl))return spmOrUrl;try{return new URL(spmOrUrl).searchParams.get("spm")??spmOrUrl}catch{return spmOrUrl}}function resolveAplusSpm(eventType,raw){let expSpm=(Array.isArray(raw.expdata)?raw.expdata:[])[0]?.spm||"",gokeyParams=parseParams(raw.gokey||""),gokeySpm=decodeParamValue(gokeyParams.spm||""),rawSpmUrl=raw["spm-url"]||decodeParamValue(gokeyParams["spm-url"]||""),spmUrl=extractSpmFromUrl(rawSpmUrl),pointSpm;switch(eventType){case"CLK":pointSpm=gokeySpm||expSpm;break;case"EXP":pointSpm=expSpm;break;case"PV":pointSpm=spmUrl;break;default:pointSpm=gokeySpm||expSpm}return{mainSpm:pointSpm,highlightSpm:pointSpm}}function parseAplusRequest(url2,options={}){if(!APLUS_URL_PATTERN.test(url2))return null;let urlObj;try{urlObj=new URL(url2)}catch{return null}let params=parseUrlParams(urlObj.search),gmkey=params.gmkey??"UNKNOWN",urlPathName=urlObj.pathname.slice(1),eventType=urlPathName.split(".")[1]==="selfdefine"?"SDF":gmkey,gokeyRaw=params.gokey??"",gokeyParams=parseParams(gokeyRaw),expdata=[];try{gokeyParams.expdata&&(expdata=JSON.parse(decodeParamValue(gokeyParams.expdata)),expdata=expdata.map(item=>{if(!item?.exargs||typeof item.exargs!="object")return item;let decoded={};for(let[key,value]of Object.entries(item.exargs)){if(typeof value!="string"){decoded[key]=value;continue}try{decoded[key]=JSON.parse(decodeURIComponent(value))}catch{decoded[key]=value}}return{...item,exargs:decoded}}))}catch{}let pageUrl=params._p_url??(gokeyParams._p_url?decodeParamValue(gokeyParams._p_url):""),{gokey:rawGokey,...topLevelParams}=params,rawData={...topLevelParams,_path:urlPathName,_url:url2,gokey:rawGokey,...expdata.length>0?{expdata}:{}},spm=resolveAplusSpm(eventType,rawData).mainSpm,pathName=urlPathName.split(".").slice(1).join("."),eventName=eventType==="SDF"?pathName:spm||pathName||pageUrl,now=options.now??Date.now();return{id:`aplus-${options.sequence??++aplusCounter}-${now}`,source:"aplus",batchId:0,batchTimestampMs:now,batchTimestamp:formatTimestamp(now),event_type:eventType,name:eventName,url:url2,timestamp:now,_raw:rawData,_context:{requestUrl:url2,app:{},user:{...params.uidaplus?{uidaplus:params.uidaplus}:{},...params._gr_uid_?{_gr_uid_:params._gr_uid_}:{}},session:{},view:{...params["spm-url"]?{"spm-url":params["spm-url"]}:{},...params["spm-pre"]?{"spm-pre":params["spm-pre"]}:{},...params["spm-cnt"]?{"spm-cnt":params["spm-cnt"]}:{},...pageUrl?{page_url:pageUrl}:{}},properties:{},os:{},net:{}}}}var RUM_TYPE_ALIAS={cst:"custom"},I18N_TRACKER_TYPE_MAP={"i18n-tracker-exp":"EXP","i18n-tracker-clk":"CLK"};function parseRumBody(postData){if(!postData)return null;if(typeof postData=="object")return postData;try{return JSON.parse(postData)}catch{return null}}function tryConvertI18nTracker(event,base){let normalizedType=RUM_TYPE_ALIAS[event.type]??event.type;if(event.event_type!=="action"||normalizedType!=="custom")return null;let snapshots;try{snapshots=typeof event.snapshots=="string"?JSON.parse(event.snapshots):event.snapshots}catch{return null}if(!snapshots||typeof snapshots!="object")return null;let eventType=I18N_TRACKER_TYPE_MAP[snapshots.message];if(!eventType)return null;let spm=[snapshots.c1??"",snapshots.c2??""].filter(Boolean).join("."),exargs={};typeof snapshots.c3=="string"&&snapshots.c3.split("&").forEach(pair=>{let eqIndex=pair.indexOf("=");if(eqIndex===-1)return;let key=pair.slice(0,eqIndex),rawValue=pair.slice(eqIndex+1);try{exargs[key]=JSON.parse(decodeURIComponent(rawValue))}catch{exargs[key]=rawValue}});let dataAttrs=snapshots.trackerInfo?.dataAttrs;if(dataAttrs&&typeof dataAttrs=="object"&&dataAttrs["data-biz-args"]&&!exargs.bizArgs)try{exargs.bizArgs=JSON.parse(dataAttrs["data-biz-args"])}catch{exargs.bizArgs=dataAttrs["data-biz-args"]}return{...base,event_type:eventType,name:spm,_raw:{...event,expdata:[{spm,...Object.keys(exargs).length>0?{exargs}:{}}],"spm-url":spm}}}function parseRumRequest(url2,postData,options={}){if(!RUM_URL_PATTERN.test(url2))return[];let parsed=parseRumBody(postData),rawEvents=Array.isArray(parsed?.events)?parsed.events:[];if(rawEvents.length===0)return[];let now=options.now??Date.now(),batchId=options.sequence??++rumCounter,context={requestUrl:url2,app:parsed?.app??{},user:parsed?.user??{},session:parsed?.session??{},view:parsed?.view??{},properties:parsed?.properties??{},os:parsed?.os??{},net:parsed?.net??{}};return rawEvents.flatMap((rawEvent,index)=>{if(!rawEvent||typeof rawEvent!="object"||Array.isArray(rawEvent))return[];let event=rawEvent,normalizedType=RUM_TYPE_ALIAS[event.type]??event.type,base={id:`${batchId}-${event.event_id??index}`,batchId,batchTimestampMs:now,batchTimestamp:formatTimestamp(now),type:normalizedType,url:event.url,timestamp:event.timestamp??now,success:event.success,status_code:event.status_code,method:event.method,duration:event.duration,source:"rum",_context:context},converted=tryConvertI18nTracker(event,base);return converted?[converted]:[{...base,event_type:event.event_type??"unknown",name:event.name,_raw:event}]})}function parseArmsRequest(url2,options={}){if(!ARMS_URL_PATTERN.test(url2))return null;let urlObj;try{urlObj=new URL(url2)}catch{return null}let params={};urlObj.searchParams.forEach((value,key)=>{params[key]=value});let eventType=(params.t??"unknown").toLowerCase(),page=params.page??"",now=options.now??Date.now(),sequence=options.sequence??++armsCounter,parsedTimestamp2=params.begin?Number.parseInt(params.begin,10):now,timestamp=Number.isFinite(parsedTimestamp2)?parsedTimestamp2:now;return{id:`arms-${sequence}-${now}`,source:"arms",batchId:0,batchTimestampMs:now,batchTimestamp:formatTimestamp(now),event_type:eventType,name:page||url2,url:url2,timestamp,_raw:{...params,_url:url2},_context:{requestUrl:url2,app:{...params.pid?{pid:params.pid}:{},...params.release?{release:params.release}:{},...params.environment?{environment:params.environment}:{},...params._v?{sdk_version:params._v}:{}},user:{...params.uid?{uid:params.uid}:{}},session:{...params.sid?{sid:params.sid}:{}},view:{...page?{page}:{},...params.tag?{tag:params.tag}:{}},properties:{},os:{},net:{...params.ct?{ct:params.ct}:{}}}}}function parseTrackingRequest(url2,postData,options={}){let rumEvents=parseRumRequest(url2,postData,options);if(rumEvents.length>0)return rumEvents;let aplusEvent=parseAplusRequest(url2,options);if(aplusEvent)return[aplusEvent];let armsEvent=parseArmsRequest(url2,options);return armsEvent?[armsEvent]:[]}var CURSOR_PREFIX="mearl-capture-v1";function createCaptureGeneration(){return crypto.randomUUID()}function encodeCaptureCursor(cursor){return`${CURSOR_PREFIX}:${cursor.tabId}:${cursor.generation}:${cursor.scope}:${cursor.sequence}`}function decodeCaptureCursor(value){let match=value.match(/^mearl-capture-v1:(\d+):([^:]+):(all|logs|requests|events):(\d+)$/);if(!match)throw new Error("Invalid capture cursor");let tabId=Number(match[1]),sequence=Number(match[4]);if(!Number.isSafeInteger(tabId)||!Number.isSafeInteger(sequence))throw new Error("Invalid capture cursor");return{tabId,generation:match[2],scope:match[3],sequence}}function captureCheckpoint(state){return encodeCaptureCursor({tabId:state.tabId,generation:state.generation,sequence:state.currentSequence,scope:"all"})}function nextCaptureSequence(state){return state.currentSequence+=1,state.currentSequence}function resolveAfterSequence(after,state,scope){if(!after)return 0;let cursor=decodeCaptureCursor(after);if(cursor.tabId!==state.tabId)throw new Error(`Capture cursor belongs to tab ${cursor.tabId}, not tab ${state.tabId}`);if(cursor.generation!==state.generation)throw new Error("Capture cursor expired because the tab collector was restarted");if(cursor.scope!=="all"&&cursor.scope!==scope)throw new Error(`Capture cursor is scoped to ${cursor.scope}, not ${scope}`);if(cursor.sequence>state.currentSequence)throw new Error("Capture cursor is ahead of the current collector state");return cursor.sequence}function queryCapturedEntries(buffer,state,options,matches,droppedThroughSequence=0,scope="all"){let{after,since,now=Date.now()}=options,limit=Math.max(1,Math.floor(options.limit??100)),afterSequence=resolveAfterSequence(after,state,scope),sinceTimestampMs=since===void 0?void 0:now-since*1e3,matched=buffer.filter(entry=>entry.captureSequence>afterSequence&&(sinceTimestampMs===void 0||entry.timestampMs>=sinceTimestampMs)&&matches(entry)),hasMore=matched.length>limit,entries=after?matched.slice(0,limit):matched.slice(-limit),nextSequence=after&&hasMore&&entries.length>0?entries[entries.length-1].captureSequence:state.currentSequence;return{entries,totalMatched:matched.length,nextCursor:encodeCaptureCursor({tabId:state.tabId,generation:state.generation,sequence:nextSequence,scope}),hasMore,gap:after!==void 0&&afterSequence<droppedThroughSequence}}var TRACKING_CAPTURE_ARMED_HINT="Event capture is active, but this tab has no captured history yet. Reload the current tab or repeat the triggering action, then call get_events again.";function compileTextPattern(value){try{return{regex:new RegExp(value,"i"),fallback:""}}catch{return{regex:null,fallback:value.toLowerCase()}}}function matchesTextPattern(value,pattern){return value?pattern.regex?pattern.regex.test(value):value.toLowerCase().includes(pattern.fallback):!1}function compactEventUrl(value){if(value)try{let url2=new URL(value);return url2.origin==="null"?value.split(/[?#]/,1)[0]:`${url2.origin}${url2.pathname}`}catch{return value.split(/[?#]/,1)[0]}}function formatTrackingEvent(event,includeRaw=!1){let{captureSequence:_discardedCaptureSequence,...publicEvent}=event;if(includeRaw)return publicEvent;let{_raw:_discardedRaw,_context,url:url2,...summary}=publicEvent,compactUrl=compactEventUrl(url2??_context.requestUrl);return{...summary,...compactUrl?{url:compactUrl}:{}}}function matchesTrackingEvent(event,options){let{source="all",event_type,filter}=options;if(source!=="all"&&event.source!==source||event_type&&!matchesTextPattern(event.event_type,compileTextPattern(event_type)))return!1;if(filter){let pattern=compileTextPattern(filter);if(!matchesTextPattern(event.name,pattern)&&!matchesTextPattern(event.url,pattern))return!1}return!0}function queryTrackingEvents(buffer,options={}){let{source="all",event_type,filter,since,limit=20,now=Date.now()}=options,events=[...buffer].reverse();if(source!=="all"&&(events=events.filter(event=>event.source===source)),since!==void 0){let sinceTimestamp=now-since*1e3;events=events.filter(event=>event.batchTimestampMs>=sinceTimestamp)}if(event_type){let pattern=compileTextPattern(event_type);events=events.filter(event=>matchesTextPattern(event.event_type,pattern))}if(filter){let pattern=compileTextPattern(filter);events=events.filter(event=>matchesTextPattern(event.name,pattern)||matchesTextPattern(event.url,pattern))}return{events:events.slice(0,limit),totalMatched:events.length,totalInBuffer:buffer.length}}function appendCapturedTrackingBatch(buffer,events,maxSize){if(events.length===0)return[];let captureSequence=events[0].captureSequence,insertionIndex=Number.isSafeInteger(captureSequence)?buffer.findIndex(event=>Number.isSafeInteger(event.captureSequence)&&event.captureSequence>captureSequence):-1;if(buffer.splice(insertionIndex<0?buffer.length:insertionIndex,0,...events),buffer.length<=maxSize)return[];let removeCount=buffer.length-maxSize,boundarySequence=buffer[removeCount-1]?.captureSequence;for(;boundarySequence!==void 0&&buffer[removeCount]?.captureSequence===boundarySequence;)removeCount+=1;return buffer.splice(0,removeCount)}function queryCapturedTrackingEvents(buffer,state,options={},droppedThroughSequence=0){let limit=Math.max(1,Math.floor(options.limit??20));if(!options.after){let snapshot=queryTrackingEvents(buffer,options);return{...snapshot,nextCursor:encodeCaptureCursor({tabId:state.tabId,generation:state.generation,sequence:state.currentSequence,scope:"events"}),hasMore:snapshot.totalMatched>limit,gap:!1}}let sinceTimestampMs=options.since===void 0?void 0:(options.now??Date.now())-options.since*1e3,batchesBySequence=new Map;for(let event of buffer){if(!Number.isSafeInteger(event.captureSequence)||sinceTimestampMs!==void 0&&event.batchTimestampMs<sinceTimestampMs||!matchesTrackingEvent(event,options))continue;let captureSequence=event.captureSequence,batch=batchesBySequence.get(captureSequence);batch?batch.events.push(event):batchesBySequence.set(captureSequence,{captureSequence,timestampMs:event.batchTimestampMs,events:[event]})}let batches=[...batchesBySequence.values()].sort((left,right)=>left.captureSequence-right.captureSequence),captured=queryCapturedEntries(batches,state,{after:options.after,limit:Number.MAX_SAFE_INTEGER},()=>!0,droppedThroughSequence,"events"),selected=[],selectedCount=0;for(let batch of captured.entries){if(selected.length>0&&selectedCount+batch.events.length>limit)break;selected.push(batch),selectedCount+=batch.events.length}let hasMore=selected.length<captured.entries.length,nextSequence=hasMore?selected[selected.length-1].captureSequence:state.currentSequence;return{events:selected.flatMap(batch=>batch.events),totalMatched:captured.entries.reduce((total,batch)=>total+batch.events.length,0),totalInBuffer:buffer.length,nextCursor:encodeCaptureCursor({tabId:state.tabId,generation:state.generation,sequence:nextSequence,scope:"events"}),hasMore,gap:captured.gap}}function parsePath(path23){if(path23.length>1e3)throw new Error("Path too long: maximum 1000 characters allowed");let keys=[],current="";for(let i=0;i<path23.length;i++){let char=path23[i];if(char===".")current&&(keys.push(current),current="");else if(char==="["){current&&(keys.push(current),current="");let j=i+1;for(;j<path23.length&&path23[j]!=="]";)j++;if(j<path23.length){let index=parseInt(path23.substring(i+1,j),10);if(!isNaN(index)){if(index<0||index>1e5)throw new Error(`Array index out of safe range: ${index}`);keys.push(index)}i=j}}else current+=char}if(current&&keys.push(current),keys.length>50)throw new Error("Path too deep: maximum 50 levels allowed");return keys}function getValueByPath(obj,path23){let keys=parsePath(path23),current=obj;for(let key of keys){if(current==null)return;current=current[key]}return current}function setValueByPath(obj,path23,value){let keys=parsePath(path23),current=obj;for(let i=0;i<keys.length-1;i++){let key=keys[i],nextKey=keys[i+1];(current[key]===null||current[key]===void 0)&&(current[key]=typeof nextKey=="number"?[]:{}),current=current[key]}current[keys[keys.length-1]]=value}function getStructure(data,maxDepth=5,currentDepth=0){if(currentDepth>=maxDepth)return"<max depth reached>";if(data===null)return"null";if(data===void 0)return"undefined";let type=typeof data;if(type==="string"||type==="number"||type==="boolean")return type;if(Array.isArray(data))return data.length===0?"array[0]":{_type:`array[${data.length}]`,_sample:getStructure(data[0],maxDepth,currentDepth+1)};if(type==="object"){let structure={};for(let key in data)Object.prototype.hasOwnProperty.call(data,key)&&(structure[key]=getStructure(data[key],maxDepth,currentDepth+1));return structure}return type}function truncateData(data,maxSize){let str=JSON.stringify(data);if(str.length<=maxSize)return data;let truncated=str.substring(0,maxSize);return`<truncated: ${str.length} bytes, showing first ${maxSize} chars>
|
|
462
|
-
|
|
460
|
+
`),success2?0:1}var DEFAULT_EXTENSION_ID,__filename,__dirname2,ALL_MODES,init_install=__esm({"src/install.ts"(){"use strict";init_nativeHost();DEFAULT_EXTENSION_ID="aoehhjnofngknnjefamjbplchbolghkm",__filename=fileURLToPath4(import.meta.url),__dirname2=path20.dirname(__filename),ALL_MODES=["skills","mcp"]}});var runtimeArgs_exports={};__export(runtimeArgs_exports,{parseNativeHostRuntimeArgs:()=>parseNativeHostRuntimeArgs});function stripNativeMessagingLaunchArgs(argv){let[origin,parentWindow,...rest]=argv;return/^chrome-extension:\/\/[a-z]{32}\/$/.test(origin??"")?/^--parent-window=\d+$/.test(parentWindow??"")?rest:argv.slice(1):argv}async function parseNativeHostRuntimeArgs(argv,minimumIdleReleaseMinutes){let args=stripNativeMessagingLaunchArgs(argv),options={},readValue=(index,name)=>{let argument=args[index];if(argument===name){let value=args[index+1];if(value===void 0||value.startsWith("-"))throw new Error(`argument missing for option '${name}'`);return{nextIndex:index+1,value}}return argument?.startsWith(`${name}=`)?{nextIndex:index,value:argument.slice(name.length+1)}:null},parseInteger=(value,label,minimum,maximum)=>{let parsed=Number(value);if(!Number.isInteger(parsed)||parsed<minimum||parsed>maximum)throw new Error(`${label} must be an integer from ${minimum} to ${maximum}`);return parsed};for(let index=0;index<args.length;index+=1){let argument=args[index];if(argument==="--daemon"){options.daemon=!0;continue}if(argument==="--skip-browser-registration"){options.skipBrowserRegistration=!0;continue}if(argument==="--version"||argument==="-v"){options.version=!0;continue}if(argument==="--help"||argument==="-h"){options.help=!0;continue}let cdpPort=readValue(index,"--cdp-port");if(cdpPort){options.cdpPort=parseInteger(cdpPort.value,"cdp-port",1,65535),index=cdpPort.nextIndex;continue}let idleRelease=readValue(index,"--agentbay-idle-release-minutes");if(idleRelease){options.agentBayIdleReleaseMinutes=parseInteger(idleRelease.value,"agentbay-idle-release-minutes",minimumIdleReleaseMinutes,Number.MAX_SAFE_INTEGER),index=idleRelease.nextIndex;continue}let stringOptions=[["--cdp-user-data-dir","cdpUserDataDir"],["--agentbay-session-id","agentBaySessionId"],["--browser-id","browserId"],["--browser-name","browserName"]],matchedStringOption=!1;for(let[name,property]of stringOptions){let parsed=readValue(index,name);if(parsed){options[property]=parsed.value,index=parsed.nextIndex,matchedStringOption=!0;break}}if(!matchedStringOption)throw new Error(argument?.startsWith("-")?`unknown option '${argument}'`:`unexpected argument '${argument}'`)}return{...options.agentBayIdleReleaseMinutes!==void 0?{agentBayIdleReleaseMinutes:options.agentBayIdleReleaseMinutes}:{},...options.agentBaySessionId?{agentBaySessionId:options.agentBaySessionId}:{},browserId:options.browserId??"cdp",browserName:options.browserName??"CDP",cdpPort:options.cdpPort??9222,...options.cdpUserDataDir?{cdpUserDataDir:options.cdpUserDataDir}:{},daemon:options.daemon===!0,help:options.help===!0,skipBrowserRegistration:options.skipBrowserRegistration===!0,version:options.version===!0}}var init_runtimeArgs=__esm({"src/runtimeArgs.ts"(){"use strict"}});import net2 from"node:net";import fs20 from"node:fs";import http4 from"node:http";import os10 from"node:os";import path21 from"node:path";import{fileURLToPath as fileURLToPath5}from"node:url";import http2 from"node:http";import WebSocket from"ws";var CdpChildSession=class{constructor(parent,sessionId){this.parent=parent;this.sessionId=sessionId}sendCommand(method,params,timeoutMs=3e4){return this.parent.sendCommandInSession(this.sessionId,method,params,timeoutMs)}on(method,callback){return this.parent.onSession(this.sessionId,method,callback)}createChildSession(sessionId){return this.parent.createChildSession(sessionId)}get closed(){return this.parent.closed}close(){}},CdpClient=class _CdpClient{constructor(socket){this.socket=socket;socket.on("message",data=>this.consumeMessage(data)),socket.on("close",()=>this.handleClosed()),socket.on("error",()=>this.handleClosed())}nextId=1;pending=new Map;eventHandlers=new Map;sessionEventHandlers=new Map;_closed=!1;static connect(wsUrl){return new Promise((resolve3,reject)=>{let url2;try{url2=new URL(wsUrl)}catch{reject(new Error("Invalid CDP WebSocket URL"));return}if(url2.protocol!=="ws:"&&url2.protocol!=="wss:"){reject(new Error(`Unsupported CDP WebSocket protocol: ${url2.protocol}`));return}let socket=new WebSocket(url2,{handshakeTimeout:5e3,maxPayload:64*1024*1024,perMessageDeflate:!1}),settled=!1,fail=error48=>{settled||(settled=!0,socket.terminate(),reject(error48))};socket.once("open",()=>{settled||(settled=!0,resolve3(new _CdpClient(socket)))}),socket.once("error",fail),socket.once("unexpected-response",(_request,response)=>{response.resume(),fail(new Error(`CDP WebSocket upgrade failed with status ${response.statusCode??0}`))})})}createChildSession(sessionId){return new CdpChildSession(this,sessionId)}sendCommandInSession(sessionId,method,params,timeoutMs=3e4){return this.sendRequest(method,params,timeoutMs,sessionId)}onSession(sessionId,method,callback){this.sessionEventHandlers.has(sessionId)||this.sessionEventHandlers.set(sessionId,new Map);let sessionMap=this.sessionEventHandlers.get(sessionId);return sessionMap.has(method)||sessionMap.set(method,new Set),sessionMap.get(method).add(callback),()=>sessionMap.get(method)?.delete(callback)}sendCommand(method,params,timeoutMs=3e4){return this.sendRequest(method,params,timeoutMs)}on(method,callback){return this.eventHandlers.has(method)||this.eventHandlers.set(method,new Set),this.eventHandlers.get(method).add(callback),()=>this.eventHandlers.get(method)?.delete(callback)}close(){this._closed||(this._closed=!0,this.socket.terminate(),this.rejectPending("CDP connection closed"))}get closed(){return this._closed}sendRequest(method,params,timeoutMs,sessionId){return new Promise((resolve3,reject)=>{if(this._closed||this.socket.readyState!==WebSocket.OPEN){reject(new Error("CDP client is closed"));return}let id=this.nextId++,timer=setTimeout(()=>{this.pending.delete(id),reject(new Error(`CDP command timeout: ${method}`))},timeoutMs);this.pending.set(id,{resolve:resolve3,reject,timer,sessionId}),this.socket.send(JSON.stringify({id,method,params:params??{},...sessionId?{sessionId}:{}}),error48=>{if(!error48)return;let pending=this.pending.get(id);pending&&(clearTimeout(pending.timer),this.pending.delete(id),pending.reject(error48))})})}consumeMessage(data){try{let text=Array.isArray(data)?Buffer.concat(data).toString("utf8"):Buffer.isBuffer(data)?data.toString("utf8"):Buffer.from(data).toString("utf8");this.handleMessage(JSON.parse(text))}catch{}}handleMessage(msg){if(msg.id!==void 0){let pending=this.pending.get(msg.id);if(!pending)return;clearTimeout(pending.timer),this.pending.delete(msg.id),msg.error?pending.reject(new Error(msg.error.message??JSON.stringify(msg.error))):pending.resolve(msg.result??{});return}if(!msg.method)return;let handlers=msg.sessionId?this.sessionEventHandlers.get(msg.sessionId)?.get(msg.method):this.eventHandlers.get(msg.method);if(handlers)for(let callback of handlers)try{callback(msg.params)}catch{}}handleClosed(){this._closed||(this._closed=!0,this.rejectPending("CDP connection closed"))}rejectPending(message){for(let[id,pending]of this.pending)clearTimeout(pending.timer),pending.reject(new Error(message)),this.pending.delete(id)}};import{TextDecoder as TextDecoder2}from"node:util";function md5(input){function rotateLeft(v,s){return v<<s|v>>>32-s}function addUnsigned(x,y){let lsw=(x&65535)+(y&65535);return(x>>16)+(y>>16)+(lsw>>16)<<16|lsw&65535}function cmn(q,a2,b2,x,s,t){return addUnsigned(rotateLeft(addUnsigned(addUnsigned(a2,q),addUnsigned(x,t)),s),b2)}function ff(a2,b2,c2,d2,x,s,t){return cmn(b2&c2|~b2&d2,a2,b2,x,s,t)}function gg(a2,b2,c2,d2,x,s,t){return cmn(b2&d2|c2&~d2,a2,b2,x,s,t)}function hh(a2,b2,c2,d2,x,s,t){return cmn(b2^c2^d2,a2,b2,x,s,t)}function ii(a2,b2,c2,d2,x,s,t){return cmn(c2^(b2|~d2),a2,b2,x,s,t)}let str=input.replace(/\r\n/g,`
|
|
461
|
+
`),encoded="";for(let n=0;n<str.length;n++){let c2=str.charCodeAt(n);c2<128?encoded+=String.fromCharCode(c2):c2<2048?(encoded+=String.fromCharCode(c2>>6|192),encoded+=String.fromCharCode(c2&63|128)):(encoded+=String.fromCharCode(c2>>12|224),encoded+=String.fromCharCode(c2>>6&63|128),encoded+=String.fromCharCode(c2&63|128))}str=encoded;let len=str.length,nw=(len+8>>>6)+1<<4,words=new Array(nw).fill(0);for(let i=0;i<len;i++)words[i>>2]|=str.charCodeAt(i)<<i%4*8;words[len>>2]|=128<<len%4*8,words[nw-2]=len<<3,words[nw-1]=len>>>29;let a=1732584193,b=4023233417,c=2562383102,d=271733878;for(let k=0;k<words.length;k+=16){let aa=a,bb=b,cc=c,dd=d;a=ff(a,b,c,d,words[k],7,3614090360),d=ff(d,a,b,c,words[k+1],12,3905402710),c=ff(c,d,a,b,words[k+2],17,606105819),b=ff(b,c,d,a,words[k+3],22,3250441966),a=ff(a,b,c,d,words[k+4],7,4118548399),d=ff(d,a,b,c,words[k+5],12,1200080426),c=ff(c,d,a,b,words[k+6],17,2821735955),b=ff(b,c,d,a,words[k+7],22,4249261313),a=ff(a,b,c,d,words[k+8],7,1770035416),d=ff(d,a,b,c,words[k+9],12,2336552879),c=ff(c,d,a,b,words[k+10],17,4294925233),b=ff(b,c,d,a,words[k+11],22,2304563134),a=ff(a,b,c,d,words[k+12],7,1804603682),d=ff(d,a,b,c,words[k+13],12,4254626195),c=ff(c,d,a,b,words[k+14],17,2792965006),b=ff(b,c,d,a,words[k+15],22,1236535329),a=gg(a,b,c,d,words[k+1],5,4129170786),d=gg(d,a,b,c,words[k+6],9,3225465664),c=gg(c,d,a,b,words[k+11],14,643717713),b=gg(b,c,d,a,words[k],20,3921069994),a=gg(a,b,c,d,words[k+5],5,3593408605),d=gg(d,a,b,c,words[k+10],9,38016083),c=gg(c,d,a,b,words[k+15],14,3634488961),b=gg(b,c,d,a,words[k+4],20,3889429448),a=gg(a,b,c,d,words[k+9],5,568446438),d=gg(d,a,b,c,words[k+14],9,3275163606),c=gg(c,d,a,b,words[k+3],14,4107603335),b=gg(b,c,d,a,words[k+8],20,1163531501),a=gg(a,b,c,d,words[k+13],5,2850285829),d=gg(d,a,b,c,words[k+2],9,4243563512),c=gg(c,d,a,b,words[k+7],14,1735328473),b=gg(b,c,d,a,words[k+12],20,2368359562),a=hh(a,b,c,d,words[k+5],4,4294588738),d=hh(d,a,b,c,words[k+8],11,2272392833),c=hh(c,d,a,b,words[k+11],16,1839030562),b=hh(b,c,d,a,words[k+14],23,4259657740),a=hh(a,b,c,d,words[k+1],4,2763975236),d=hh(d,a,b,c,words[k+4],11,1272893353),c=hh(c,d,a,b,words[k+7],16,4139469664),b=hh(b,c,d,a,words[k+10],23,3200236656),a=hh(a,b,c,d,words[k+13],4,681279174),d=hh(d,a,b,c,words[k],11,3936430074),c=hh(c,d,a,b,words[k+3],16,3572445317),b=hh(b,c,d,a,words[k+6],23,76029189),a=hh(a,b,c,d,words[k+9],4,3654602809),d=hh(d,a,b,c,words[k+12],11,3873151461),c=hh(c,d,a,b,words[k+15],16,530742520),b=hh(b,c,d,a,words[k+2],23,3299628645),a=ii(a,b,c,d,words[k],6,4096336452),d=ii(d,a,b,c,words[k+7],10,1126891415),c=ii(c,d,a,b,words[k+14],15,2878612391),b=ii(b,c,d,a,words[k+5],21,4237533241),a=ii(a,b,c,d,words[k+12],6,1700485571),d=ii(d,a,b,c,words[k+3],10,2399980690),c=ii(c,d,a,b,words[k+10],15,4293915773),b=ii(b,c,d,a,words[k+1],21,2240044497),a=ii(a,b,c,d,words[k+8],6,1873313359),d=ii(d,a,b,c,words[k+15],10,4264355552),c=ii(c,d,a,b,words[k+6],15,2734768916),b=ii(b,c,d,a,words[k+13],21,1309151649),a=ii(a,b,c,d,words[k+4],6,4149444226),d=ii(d,a,b,c,words[k+11],10,3174756917),c=ii(c,d,a,b,words[k+2],15,718787259),b=ii(b,c,d,a,words[k+9],21,3951481745),a=addUnsigned(a,aa),b=addUnsigned(b,bb),c=addUnsigned(c,cc),d=addUnsigned(d,dd)}let hex3=v=>{let s="";for(let i=0;i<=3;i++){let byte=v>>>i*8&255;s+=("0"+byte.toString(16)).slice(-2)}return s};return(hex3(a)+hex3(b)+hex3(c)+hex3(d)).toLowerCase()}function extractMtopToken(cookieMap,isMopen){if(isMopen){let mTk=cookieMap.get("m_tk"),tbToken=cookieMap.get("_tb_token_");if(mTk)return mTk.split("_")[0]||"";if(tbToken)return tbToken;throw new Error("Missing m_tk or _tb_token_ cookie. Please ensure the user is logged in.")}let h5Tk=cookieMap.get("_m_h5_tk");if(h5Tk)return h5Tk.split("_")[0]||"";throw new Error("Missing _m_h5_tk cookie. Please ensure the user is logged in.")}function computeMtopSign(params){let{api,version:version2,timestamp,appKey,token,dataStr,isMopen}=params;return md5(isMopen?`${api}&${version2}&${timestamp}&${appKey}&${token}&${md5(dataStr)}`:`${token}&${timestamp}&${appKey}&${dataStr}`)}var MTOP_HOST_MAP={online:"h5api.m.taobao.com",pre:"h5api.wapa.taobao.com"};function buildCookieHeaderValue(cookieMap){return[...cookieMap.entries()].map(([k,v])=>`${k}=${v}`).join("; ")}function parseSseDataValue(value){try{return JSON.parse(value)}catch{return value}}function createSseEventParser(){let buffer="",eventName="",lastEventId,dataLines=[],hasData=!1,dispatch=()=>{if(!hasData)return eventName="",dataLines=[],[];let rawData=dataLines.join(`
|
|
462
|
+
`);if(eventName=eventName||"message",dataLines=[],hasData=!1,rawData==="[DONE]")return eventName="",[];let event={event:eventName,data:parseSseDataValue(rawData),...lastEventId!==void 0?{eventId:lastEventId}:{}};return eventName="",[event]},consumeLine=line=>{if(line==="")return dispatch();if(line.startsWith(":"))return[];let separator=line.indexOf(":"),field=separator===-1?line:line.slice(0,separator),value=separator===-1?"":line.slice(separator+1);return value.startsWith(" ")&&(value=value.slice(1)),field==="data"?(dataLines.push(value),hasData=!0):field==="event"?eventName=value:field==="id"&&!value.includes("\0")&&(lastEventId=value),[]},drain=final=>{let events=[];for(;buffer.length>0;){let newlineIndex=-1;for(let index=0;index<buffer.length;index++)if(buffer[index]===`
|
|
463
|
+
`||buffer[index]==="\r"){newlineIndex=index;break}if(newlineIndex===-1){final&&(events.push(...consumeLine(buffer)),buffer="");break}if(buffer[newlineIndex]==="\r"&&newlineIndex===buffer.length-1&&!final)break;let line=buffer.slice(0,newlineIndex),separatorLength=buffer[newlineIndex]==="\r"&&buffer[newlineIndex+1]===`
|
|
464
|
+
`?2:1;buffer=buffer.slice(newlineIndex+separatorLength),events.push(...consumeLine(line))}return final&&events.push(...dispatch()),events};return{push(chunk){return buffer+=chunk,drain(!1)},finish(){return drain(!0)}}}function resolveMtopRequest(data){let{api,data:requestData={},version:version2="1.0",method="GET",appKey="12574478",env="online",timeout=1e4,headers:customHeaders={},ttid}=data;if(!api||typeof api!="string"||api.trim()==="")throw new Error('Invalid api: api must be a non-empty string (e.g. "mtop.trade.order.create")');let baseHost=MTOP_HOST_MAP[env.toLowerCase()];if(!baseHost)throw new Error(`Invalid env: "${env}". Supported values: ${Object.keys(MTOP_HOST_MAP).join(", ")}`);let normalizedMethod=method.toUpperCase();if(normalizedMethod!=="GET"&&normalizedMethod!=="POST")throw new Error(`Invalid method: ${method}. mtop only supports GET or POST`);if(!Number.isFinite(timeout)||timeout<=0)throw new Error("Invalid timeout: timeout must be a positive number");return{api,requestData,dataStr:typeof requestData=="string"?requestData:JSON.stringify(requestData),version:version2,normalizedMethod,appKey,gatewayUrl:new URL(`https://${baseHost}/h5/${api}/${version2}/`),customHeaders,ttid,timeout,isMopen:api.startsWith("mopen.")}}function prepareSignedMtopRequest(resolved,cookieMap,stream=!1,timestamp=Date.now()){let token=extractMtopToken(cookieMap,resolved.isMopen),sign=computeMtopSign({api:resolved.api,version:resolved.version,timestamp,appKey:resolved.appKey,token,dataStr:resolved.dataStr,isMopen:resolved.isMopen}),targetUrl=new URL(resolved.gatewayUrl),queryParams={jsv:"2.7.2",appKey:resolved.appKey,t:timestamp.toString(),sign,api:resolved.api,v:resolved.version,type:"originaljson",dataType:"json"};stream&&(queryParams.xAcceptStream="true"),resolved.ttid&&(queryParams.ttid=resolved.ttid),resolved.normalizedMethod==="GET"&&(queryParams.data=resolved.dataStr);for(let[name,value]of Object.entries(queryParams))targetUrl.searchParams.set(name,value);let requestHeaders={Accept:stream?"text/event-stream":"application/json",...resolved.customHeaders},body;return resolved.normalizedMethod==="POST"&&(body=new URLSearchParams({data:resolved.dataStr}).toString(),requestHeaders["Content-Type"]="application/x-www-form-urlencoded"),{...resolved,targetUrl,requestHeaders,cookieHeader:buildCookieHeaderValue(cookieMap),body}}function parseMtopResponseText(text){try{return JSON.parse(text)}catch{let jsonpMatch=text.match(/^[^(]*\((.*)\)\s*;?\s*$/s);if(!jsonpMatch?.[1])return text;try{return JSON.parse(jsonpMatch[1])}catch{return text}}}function summarizeMtopStreamError(body){if(body&&typeof body=="object"){let record2=body;if(Array.isArray(record2.ret))return record2.ret.map(String).join(", ");if(typeof record2.message=="string")return record2.message}return((typeof body=="string"?body:JSON.stringify(body))??String(body)).slice(0,500)}async function consumeMtopSseResponse(response,onReceive){let contentType=response.headers.get("content-type")??"";if(!response.ok||!response.body||!contentType.includes("text/event-stream")){let body=parseMtopResponseText(await response.text());throw new Error(`Unexpected MTOP stream response: ${summarizeMtopStreamError(body)}`)}let reader=response.body.getReader(),decoder=new TextDecoder,parser=createSseEventParser(),lastData=null,emit=async(text,finished=!1)=>{let events=[...parser.push(text),...finished?parser.finish():[]];for(let event of events)lastData=event.data,await onReceive(event)};for(;;){let{done,value}=await reader.read();if(done)return await emit(decoder.decode(),!0),lastData;await emit(decoder.decode(value,{stream:!0}))}}function parseRequestData(data){if(typeof data!="string")return data;try{return JSON.parse(data)}catch{return data}}function parseQueryString(url2){let queryString=[];try{new URL(url2).searchParams.forEach((value,name)=>queryString.push({name,value}))}catch{}return queryString}function redactSensitiveHeaders(headers){let sensitiveNames=new Set(["authorization","cookie","proxy-authorization"]);return headers.map(header=>sensitiveNames.has(header.name.toLowerCase())?{...header,value:"<redacted>"}:header)}function createMtopStreamCapture(data){let timestampMs2=data.timestampMs??Date.now(),url2=data.url??`mtop://${data.api}/`;return{startTimeMs:timestampMs2,request:{id:data.id,timestamp:new Date(timestampMs2).toISOString(),timestampMs:timestampMs2,method:data.method,url:url2,apiName:data.api,status:0,statusText:"SSE Streaming",headers:redactSensitiveHeaders(data.requestHeaders??[]),responseHeaders:[],queryString:parseQueryString(url2),postData:parseRequestData(data.requestData??null),responseBody:[],isProxy:!0,proxyRequestUrl:null,proxyData:null,isSSE:!0,isPending:!0,...data.tabId!==void 0?{tabId:data.tabId}:{},source:"mtop",resourceType:"fetch",captureSequence:data.captureSequence}}}function updateMtopStreamCaptureResponse(capture,response){capture.request.status=response.status,capture.request.statusText=response.statusText,capture.request.responseHeaders=response.responseHeaders}function appendMtopStreamCaptureChunk(capture,data,timestampMs2=Date.now()){return Array.isArray(capture.request.responseBody)?(capture.request.responseBody.push({event:"message",data,timestamp:timestampMs2,duration:capture.lastMessageTimeMs===void 0?0:timestampMs2-capture.lastMessageTimeMs}),capture.lastMessageTimeMs=timestampMs2,!0):!1}function finishMtopStreamCapture(capture,options={}){let timestampMs2=options.timestampMs??Date.now();if(capture.request.isPending=!1,capture.request.duration=Math.max(0,timestampMs2-capture.startTimeMs),options.error){capture.request.statusText=options.error,Array.isArray(capture.request.responseBody)&&capture.request.responseBody.length===0&&(capture.request.responseBody={error:options.error});return}capture.request.status===0&&(capture.request.status=200),(!capture.request.statusText||capture.request.statusText==="SSE Streaming")&&(capture.request.statusText="OK")}function isAppProfileUserInfoUrl(url2){try{let target=new URL(url2);return(target.protocol==="http:"||target.protocol==="https:")&&(target.hostname==="taobao.com"||target.hostname.endsWith(".taobao.com"))}catch{return!1}}function decodeCookieValue(raw){let value=raw;for(let index=0;index<2;index+=1)try{let decoded=decodeURIComponent(value);if(decoded===value)break;value=decoded}catch{break}return value.replace(/\\u([0-9a-f]{4})/gi,(_match,hex3)=>String.fromCharCode(Number.parseInt(hex3,16)))}function firstCookieValue(cookies,name){let value=cookies.find(cookie=>cookie.name===name&&cookie.value&&cookie.value!=="null")?.value;return value?decodeCookieValue(value):""}function resolveAppProfileUserInfo(url2,cookies){if(!isAppProfileUserInfoUrl(url2))return{};let userId=firstCookieValue(cookies,"unb"),userName=["_w_tb_nick","_nk_","snk","tracknick"].map(name=>firstCookieValue(cookies,name)).find(Boolean);return{...userId&&{userId},...userName&&{userName}}}var APLUS_URL_PATTERN=/\.mmstat\.com\//,RUM_URL_PATTERN=/\.rum\.aliyuncs\.com\//,ARMS_URL_PATTERN=/arms-retcode\.aliyuncs\.com\//;function isTrackingUrl(url2){return APLUS_URL_PATTERN.test(url2)||RUM_URL_PATTERN.test(url2)||ARMS_URL_PATTERN.test(url2)||/retcode\.alicdn\.com|beacon\.taobao\.com|tbsec\./i.test(url2)}var aplusCounter=0,armsCounter=0,rumCounter=0;function formatTimestamp(ms){let d=new Date(ms),pad=n=>String(n).padStart(2,"0");return`${d.getFullYear()}/${pad(d.getMonth()+1)}/${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`}function parseParams(value){let params={};return value.split("&").forEach(pair=>{let eqIndex=pair.indexOf("=");if(eqIndex===-1)return;let rawKey=pair.slice(0,eqIndex),rawValue=pair.slice(eqIndex+1);try{params[decodeURIComponent(rawKey)]=rawValue}catch{params[rawKey]=rawValue}}),params}function decodeParamValue(value){try{return decodeURIComponent(value)}catch{return value}}function parseJsonParamValue(value){try{return JSON.parse(value)}catch{let decoded=decodeParamValue(value);if(decoded===value)return;try{return JSON.parse(decoded)}catch{return}}}function parseUrlParams(search){let encodedParams=parseParams(search.startsWith("?")?search.slice(1):search);return Object.fromEntries(Object.entries(encodedParams).map(([key,value])=>[key,decodeParamValue(value)]))}function extractSpmFromUrl(spmOrUrl){if(!/^https?:\/\//i.test(spmOrUrl))return spmOrUrl;try{return new URL(spmOrUrl).searchParams.get("spm")??spmOrUrl}catch{return spmOrUrl}}function resolveAplusSpm(eventType,raw){let expSpm=(Array.isArray(raw.expdata)?raw.expdata:[])[0]?.spm||"",gokeyParams=parseParams(raw.gokey||""),gokeySpm=decodeParamValue(gokeyParams.spm||""),rawSpmUrl=raw["spm-url"]||decodeParamValue(gokeyParams["spm-url"]||""),spmUrl=extractSpmFromUrl(rawSpmUrl),pointSpm;switch(eventType){case"CLK":pointSpm=gokeySpm||expSpm;break;case"EXP":pointSpm=expSpm;break;case"PV":pointSpm=spmUrl;break;default:pointSpm=gokeySpm||expSpm}return{mainSpm:pointSpm,highlightSpm:pointSpm}}function parseAplusRequest(url2,options={}){if(!APLUS_URL_PATTERN.test(url2))return null;let urlObj;try{urlObj=new URL(url2)}catch{return null}let params=parseUrlParams(urlObj.search),gmkey=params.gmkey??"UNKNOWN",urlPathName=urlObj.pathname.slice(1),eventType=urlPathName.split(".")[1]==="selfdefine"?"SDF":gmkey,gokeyRaw=params.gokey??"",gokeyParams=parseParams(gokeyRaw),expdata=[];if(gokeyParams.expdata){let parsedExpdata=parseJsonParamValue(gokeyParams.expdata);Array.isArray(parsedExpdata)&&(expdata=parsedExpdata.map(item=>{if(!item?.exargs||typeof item.exargs!="object")return item;let decoded={};for(let[key,value]of Object.entries(item.exargs)){if(typeof value!="string"){decoded[key]=value;continue}let parsedValue=parseJsonParamValue(value);decoded[key]=parsedValue===void 0?value:parsedValue}return{...item,exargs:decoded}}))}let rawBizArgs=gokeyParams.bizArgs,parsedBizArgs=rawBizArgs===void 0?void 0:parseJsonParamValue(rawBizArgs),bizArgs=parsedBizArgs===void 0?rawBizArgs:parsedBizArgs,pageUrl=params._p_url??(gokeyParams._p_url?decodeParamValue(gokeyParams._p_url):""),{gokey:rawGokey,...topLevelParams}=params,rawData={...topLevelParams,_path:urlPathName,_url:url2,gokey:rawGokey,...expdata.length>0?{expdata}:{},...bizArgs!==void 0?{bizArgs}:{}},spm=resolveAplusSpm(eventType,rawData).mainSpm,pathName=urlPathName.split(".").slice(1).join("."),eventName=eventType==="SDF"?pathName:spm||pathName||pageUrl,now=options.now??Date.now();return{id:`aplus-${options.sequence??++aplusCounter}-${now}`,source:"aplus",batchId:0,batchTimestampMs:now,batchTimestamp:formatTimestamp(now),event_type:eventType,name:eventName,url:url2,timestamp:now,_raw:rawData,_context:{requestUrl:url2,app:{},user:{...params.uidaplus?{uidaplus:params.uidaplus}:{},...params._gr_uid_?{_gr_uid_:params._gr_uid_}:{}},session:{},view:{...params["spm-url"]?{"spm-url":params["spm-url"]}:{},...params["spm-pre"]?{"spm-pre":params["spm-pre"]}:{},...params["spm-cnt"]?{"spm-cnt":params["spm-cnt"]}:{},...pageUrl?{page_url:pageUrl}:{}},properties:{},os:{},net:{}}}}var RUM_TYPE_ALIAS={cst:"custom"},I18N_TRACKER_TYPE_MAP={"i18n-tracker-exp":"EXP","i18n-tracker-clk":"CLK"};function parseRumBody(postData){if(!postData)return null;if(typeof postData=="object")return postData;try{return JSON.parse(postData)}catch{return null}}function tryConvertI18nTracker(event,base){let normalizedType=RUM_TYPE_ALIAS[event.type]??event.type;if(event.event_type!=="action"||normalizedType!=="custom")return null;let snapshots;try{snapshots=typeof event.snapshots=="string"?JSON.parse(event.snapshots):event.snapshots}catch{return null}if(!snapshots||typeof snapshots!="object")return null;let eventType=I18N_TRACKER_TYPE_MAP[snapshots.message];if(!eventType)return null;let spm=[snapshots.c1??"",snapshots.c2??""].filter(Boolean).join("."),exargs={};typeof snapshots.c3=="string"&&snapshots.c3.split("&").forEach(pair=>{let eqIndex=pair.indexOf("=");if(eqIndex===-1)return;let key=pair.slice(0,eqIndex),rawValue=pair.slice(eqIndex+1);try{exargs[key]=JSON.parse(decodeURIComponent(rawValue))}catch{exargs[key]=rawValue}});let dataAttrs=snapshots.trackerInfo?.dataAttrs;if(dataAttrs&&typeof dataAttrs=="object"&&dataAttrs["data-biz-args"]&&!exargs.bizArgs)try{exargs.bizArgs=JSON.parse(dataAttrs["data-biz-args"])}catch{exargs.bizArgs=dataAttrs["data-biz-args"]}return{...base,event_type:eventType,name:spm,_raw:{...event,expdata:[{spm,...Object.keys(exargs).length>0?{exargs}:{}}],"spm-url":spm}}}function parseRumRequest(url2,postData,options={}){if(!RUM_URL_PATTERN.test(url2))return[];let parsed=parseRumBody(postData),rawEvents=Array.isArray(parsed?.events)?parsed.events:[];if(rawEvents.length===0)return[];let now=options.now??Date.now(),batchId=options.sequence??++rumCounter,context={requestUrl:url2,app:parsed?.app??{},user:parsed?.user??{},session:parsed?.session??{},view:parsed?.view??{},properties:parsed?.properties??{},os:parsed?.os??{},net:parsed?.net??{}};return rawEvents.flatMap((rawEvent,index)=>{if(!rawEvent||typeof rawEvent!="object"||Array.isArray(rawEvent))return[];let event=rawEvent,normalizedType=RUM_TYPE_ALIAS[event.type]??event.type,base={id:`${batchId}-${event.event_id??index}`,batchId,batchTimestampMs:now,batchTimestamp:formatTimestamp(now),type:normalizedType,url:event.url,timestamp:event.timestamp??now,success:event.success,status_code:event.status_code,method:event.method,duration:event.duration,source:"rum",_context:context},converted=tryConvertI18nTracker(event,base);return converted?[converted]:[{...base,event_type:event.event_type??"unknown",name:event.name,_raw:event}]})}function parseArmsRequest(url2,options={}){if(!ARMS_URL_PATTERN.test(url2))return null;let urlObj;try{urlObj=new URL(url2)}catch{return null}let params={};urlObj.searchParams.forEach((value,key)=>{params[key]=value});let eventType=(params.t??"unknown").toLowerCase(),page=params.page??"",now=options.now??Date.now(),sequence=options.sequence??++armsCounter,parsedTimestamp2=params.begin?Number.parseInt(params.begin,10):now,timestamp=Number.isFinite(parsedTimestamp2)?parsedTimestamp2:now;return{id:`arms-${sequence}-${now}`,source:"arms",batchId:0,batchTimestampMs:now,batchTimestamp:formatTimestamp(now),event_type:eventType,name:page||url2,url:url2,timestamp,_raw:{...params,_url:url2},_context:{requestUrl:url2,app:{...params.pid?{pid:params.pid}:{},...params.release?{release:params.release}:{},...params.environment?{environment:params.environment}:{},...params._v?{sdk_version:params._v}:{}},user:{...params.uid?{uid:params.uid}:{}},session:{...params.sid?{sid:params.sid}:{}},view:{...page?{page}:{},...params.tag?{tag:params.tag}:{}},properties:{},os:{},net:{...params.ct?{ct:params.ct}:{}}}}}function parseTrackingRequest(url2,postData,options={}){let rumEvents=parseRumRequest(url2,postData,options);if(rumEvents.length>0)return rumEvents;let aplusEvent=parseAplusRequest(url2,options);if(aplusEvent)return[aplusEvent];let armsEvent=parseArmsRequest(url2,options);return armsEvent?[armsEvent]:[]}var CURSOR_PREFIX="mearl-capture-v1";function createCaptureGeneration(){return crypto.randomUUID()}function encodeCaptureCursor(cursor){return`${CURSOR_PREFIX}:${cursor.tabId}:${cursor.generation}:${cursor.scope}:${cursor.sequence}`}function decodeCaptureCursor(value){let match=value.match(/^mearl-capture-v1:(\d+):([^:]+):(all|logs|requests|events):(\d+)$/);if(!match)throw new Error("Invalid capture cursor");let tabId=Number(match[1]),sequence=Number(match[4]);if(!Number.isSafeInteger(tabId)||!Number.isSafeInteger(sequence))throw new Error("Invalid capture cursor");return{tabId,generation:match[2],scope:match[3],sequence}}function captureCheckpoint(state){return encodeCaptureCursor({tabId:state.tabId,generation:state.generation,sequence:state.currentSequence,scope:"all"})}function nextCaptureSequence(state){return state.currentSequence+=1,state.currentSequence}function resolveAfterSequence(after,state,scope){if(!after)return 0;let cursor=decodeCaptureCursor(after);if(cursor.tabId!==state.tabId)throw new Error(`Capture cursor belongs to tab ${cursor.tabId}, not tab ${state.tabId}`);if(cursor.generation!==state.generation)throw new Error("Capture cursor expired because the tab collector was restarted");if(cursor.scope!=="all"&&cursor.scope!==scope)throw new Error(`Capture cursor is scoped to ${cursor.scope}, not ${scope}`);if(cursor.sequence>state.currentSequence)throw new Error("Capture cursor is ahead of the current collector state");return cursor.sequence}function queryCapturedEntries(buffer,state,options,matches,droppedThroughSequence=0,scope="all"){let{after,since,now=Date.now()}=options,limit=Math.max(1,Math.floor(options.limit??100)),afterSequence=resolveAfterSequence(after,state,scope),sinceTimestampMs=since===void 0?void 0:now-since*1e3,matched=buffer.filter(entry=>entry.captureSequence>afterSequence&&(sinceTimestampMs===void 0||entry.timestampMs>=sinceTimestampMs)&&matches(entry)),hasMore=matched.length>limit,entries=after?matched.slice(0,limit):matched.slice(-limit),nextSequence=after&&hasMore&&entries.length>0?entries[entries.length-1].captureSequence:state.currentSequence;return{entries,totalMatched:matched.length,nextCursor:encodeCaptureCursor({tabId:state.tabId,generation:state.generation,sequence:nextSequence,scope}),hasMore,gap:after!==void 0&&afterSequence<droppedThroughSequence}}var TRACKING_CAPTURE_ARMED_HINT="Event capture is active, but this tab has no captured history yet. Reload the current tab or repeat the triggering action, then call get_events again.";function compileTextPattern(value){try{return{regex:new RegExp(value,"i"),fallback:""}}catch{return{regex:null,fallback:value.toLowerCase()}}}function matchesTextPattern(value,pattern){return value?pattern.regex?pattern.regex.test(value):value.toLowerCase().includes(pattern.fallback):!1}function compactEventUrl(value){if(value)try{let url2=new URL(value);return url2.origin==="null"?value.split(/[?#]/,1)[0]:`${url2.origin}${url2.pathname}`}catch{return value.split(/[?#]/,1)[0]}}function formatTrackingEvent(event,includeRaw=!1){let{captureSequence:_discardedCaptureSequence,...publicEvent}=event;if(includeRaw)return publicEvent;let{_raw:_discardedRaw,_context,url:url2,...summary}=publicEvent,compactUrl=compactEventUrl(url2??_context.requestUrl);return{...summary,...compactUrl?{url:compactUrl}:{}}}function matchesTrackingEvent(event,options){let{source="all",event_type,filter}=options;if(source!=="all"&&event.source!==source||event_type&&!matchesTextPattern(event.event_type,compileTextPattern(event_type)))return!1;if(filter){let pattern=compileTextPattern(filter);if(!matchesTextPattern(event.name,pattern)&&!matchesTextPattern(event.url,pattern))return!1}return!0}function queryTrackingEvents(buffer,options={}){let{source="all",event_type,filter,since,limit=20,now=Date.now()}=options,events=[...buffer].reverse();if(source!=="all"&&(events=events.filter(event=>event.source===source)),since!==void 0){let sinceTimestamp=now-since*1e3;events=events.filter(event=>event.batchTimestampMs>=sinceTimestamp)}if(event_type){let pattern=compileTextPattern(event_type);events=events.filter(event=>matchesTextPattern(event.event_type,pattern))}if(filter){let pattern=compileTextPattern(filter);events=events.filter(event=>matchesTextPattern(event.name,pattern)||matchesTextPattern(event.url,pattern))}return{events:events.slice(0,limit),totalMatched:events.length,totalInBuffer:buffer.length}}function appendCapturedTrackingBatch(buffer,events,maxSize){if(events.length===0)return[];let captureSequence=events[0].captureSequence,insertionIndex=Number.isSafeInteger(captureSequence)?buffer.findIndex(event=>Number.isSafeInteger(event.captureSequence)&&event.captureSequence>captureSequence):-1;if(buffer.splice(insertionIndex<0?buffer.length:insertionIndex,0,...events),buffer.length<=maxSize)return[];let removeCount=buffer.length-maxSize,boundarySequence=buffer[removeCount-1]?.captureSequence;for(;boundarySequence!==void 0&&buffer[removeCount]?.captureSequence===boundarySequence;)removeCount+=1;return buffer.splice(0,removeCount)}function queryCapturedTrackingEvents(buffer,state,options={},droppedThroughSequence=0){let limit=Math.max(1,Math.floor(options.limit??20));if(!options.after){let snapshot=queryTrackingEvents(buffer,options);return{...snapshot,nextCursor:encodeCaptureCursor({tabId:state.tabId,generation:state.generation,sequence:state.currentSequence,scope:"events"}),hasMore:snapshot.totalMatched>limit,gap:!1}}let sinceTimestampMs=options.since===void 0?void 0:(options.now??Date.now())-options.since*1e3,batchesBySequence=new Map;for(let event of buffer){if(!Number.isSafeInteger(event.captureSequence)||sinceTimestampMs!==void 0&&event.batchTimestampMs<sinceTimestampMs||!matchesTrackingEvent(event,options))continue;let captureSequence=event.captureSequence,batch=batchesBySequence.get(captureSequence);batch?batch.events.push(event):batchesBySequence.set(captureSequence,{captureSequence,timestampMs:event.batchTimestampMs,events:[event]})}let batches=[...batchesBySequence.values()].sort((left,right)=>left.captureSequence-right.captureSequence),captured=queryCapturedEntries(batches,state,{after:options.after,limit:Number.MAX_SAFE_INTEGER},()=>!0,droppedThroughSequence,"events"),selected=[],selectedCount=0;for(let batch of captured.entries){if(selected.length>0&&selectedCount+batch.events.length>limit)break;selected.push(batch),selectedCount+=batch.events.length}let hasMore=selected.length<captured.entries.length,nextSequence=hasMore?selected[selected.length-1].captureSequence:state.currentSequence;return{events:selected.flatMap(batch=>batch.events),totalMatched:captured.entries.reduce((total,batch)=>total+batch.events.length,0),totalInBuffer:buffer.length,nextCursor:encodeCaptureCursor({tabId:state.tabId,generation:state.generation,sequence:nextSequence,scope:"events"}),hasMore,gap:captured.gap}}function parsePath(path23){if(path23.length>1e3)throw new Error("Path too long: maximum 1000 characters allowed");let keys=[],current="";for(let i=0;i<path23.length;i++){let char=path23[i];if(char===".")current&&(keys.push(current),current="");else if(char==="["){current&&(keys.push(current),current="");let j=i+1;for(;j<path23.length&&path23[j]!=="]";)j++;if(j<path23.length){let index=parseInt(path23.substring(i+1,j),10);if(!isNaN(index)){if(index<0||index>1e5)throw new Error(`Array index out of safe range: ${index}`);keys.push(index)}i=j}}else current+=char}if(current&&keys.push(current),keys.length>50)throw new Error("Path too deep: maximum 50 levels allowed");return keys}function getValueByPath(obj,path23){let keys=parsePath(path23),current=obj;for(let key of keys){if(current==null)return;current=current[key]}return current}function setValueByPath(obj,path23,value){let keys=parsePath(path23),current=obj;for(let i=0;i<keys.length-1;i++){let key=keys[i],nextKey=keys[i+1];(current[key]===null||current[key]===void 0)&&(current[key]=typeof nextKey=="number"?[]:{}),current=current[key]}current[keys[keys.length-1]]=value}function getStructure(data,maxDepth=5,currentDepth=0){if(currentDepth>=maxDepth)return"<max depth reached>";if(data===null)return"null";if(data===void 0)return"undefined";let type=typeof data;if(type==="string"||type==="number"||type==="boolean")return type;if(Array.isArray(data))return data.length===0?"array[0]":{_type:`array[${data.length}]`,_sample:getStructure(data[0],maxDepth,currentDepth+1)};if(type==="object"){let structure={};for(let key in data)Object.prototype.hasOwnProperty.call(data,key)&&(structure[key]=getStructure(data[key],maxDepth,currentDepth+1));return structure}return type}function truncateData(data,maxSize){let str=JSON.stringify(data);if(str.length<=maxSize)return data;let truncated=str.substring(0,maxSize);return`<truncated: ${str.length} bytes, showing first ${maxSize} chars>
|
|
465
|
+
${truncated}...`}function extractFields(data,fields){if(fields.length>100)throw new Error("Too many fields: maximum 100 fields allowed");let result={};for(let fieldPath of fields)try{result[fieldPath]=getValueByPath(data,fieldPath)}catch(error48){result[fieldPath]=`<error: ${error48 instanceof Error?error48.message:"field not found"}>`}return result}function serializeRequest(request,options={}){let{includeBody=!0,includeHeaders=!1,maxBodySize=5e4,fields,keysOnly=!1}=options,result={id:request.id,timestamp:request.timestamp,timestampMs:request.timestampMs,method:request.method,url:request.url,apiName:request.apiName,status:request.status,statusText:request.statusText,queryString:request.queryString,duration:request.duration,captureSequence:request.captureSequence,isPending:request.isPending,isSSE:request.isSSE,source:request.source,resourceType:request.resourceType};return includeHeaders&&(result.headers=request.headers,result.responseHeaders=request.responseHeaders),keysOnly?(result.postDataStructure=request.postData?getStructure(request.postData):null,result.responseBodyStructure=request.responseBody?getStructure(request.responseBody):null,result):(includeBody&&request.postData!==null&&request.postData!==void 0?result.postData=truncateData(request.postData,maxBodySize):includeBody?result.postData=request.postData:result.postData="<omitted>",includeBody&&request.responseBody!==null&&request.responseBody!==void 0?result.responseBody=truncateData(request.responseBody,maxBodySize):includeBody?result.responseBody=request.responseBody:result.responseBody="<omitted>",fields&&fields.length>0&&(result.extractedFields=extractFields(request.responseBody,fields)),result)}function serializeRecordingRequests(requests){return requests.map(r=>({api:r.apiName||r.url,method:r.method,status:r.status,timestampMs:r.timestampMs}))}function annotateActionsWithRequests(actions,requests,endTime){return actions.map((action,idx)=>{let cutoff=idx+1>=actions.length?Math.min(action.timestamp+3e3,endTime):actions[idx+1].timestamp,seen=new Set;for(let r of requests){if(r.timestampMs<action.timestamp||r.timestampMs>cutoff)continue;let key=r.apiName||r.url;key&&seen.add(key)}return seen.size===0?action:{...action,triggeredRequests:Array.from(seen)}})}var textEncoder=new TextEncoder;function byteLength(value){return textEncoder.encode(value).byteLength}function serializeForStorage(value){if(typeof value=="string")return value;try{return JSON.stringify(value)}catch{return String(value)}}function truncateUtf8(value,maxBytes){if(byteLength(value)<=maxBytes)return value;let low=0,high=Math.min(value.length,maxBytes);for(;low<high;){let middle=Math.ceil((low+high)/2);byteLength(value.slice(0,middle))<=maxBytes?low=middle:high=middle-1}return value.slice(0,low)}function limitBufferedField(value,maxBytes){if(value==null)return value;let serialized=serializeForStorage(value),originalBytes=byteLength(serialized);if(originalBytes<=maxBytes)return value;let marker=`<truncated: ${originalBytes} bytes, buffered preview>
|
|
463
466
|
`;if(byteLength(marker)+3>maxBytes)return truncateUtf8(`${marker}...`,maxBytes);let previewBudget=Math.max(0,maxBytes-byteLength(marker)-3);return`${marker}${truncateUtf8(serialized,previewBudget)}...`}function estimateRequestBufferBytes(request){try{return byteLength(JSON.stringify(request))}catch{return byteLength(String(request))}}function createRequestBufferAccounting(){return{sizes:[],totalBytes:0}}function synchronizeAccounting(requests,accounting){accounting.sizes.length!==requests.length&&(accounting.sizes=requests.map(estimateRequestBufferBytes),accounting.totalBytes=accounting.sizes.reduce((total,size)=>total+size,0))}function applyFieldLimits(request,maxFieldBytes){request.postData=limitBufferedField(request.postData,maxFieldBytes),request.responseBody=limitBufferedField(request.responseBody,maxFieldBytes)}function trimRequestBuffer(requests,accounting,maxEntries,maxBytes){let removed=[];for(;requests.length>1&&(requests.length>maxEntries||accounting.totalBytes>maxBytes);){let request=requests.shift();request&&removed.push(request),accounting.totalBytes-=accounting.sizes.shift()??0}return removed}function appendRequestToBuffer(requests,accounting,request,limits={}){let{maxEntries=500,maxBytes=33554432,maxFieldBytes=8388608}=limits;synchronizeAccounting(requests,accounting),applyFieldLimits(request,maxFieldBytes);let size=estimateRequestBufferBytes(request);return requests.push(request),accounting.sizes.push(size),accounting.totalBytes+=size,trimRequestBuffer(requests,accounting,maxEntries,maxBytes)}function refreshRequestInBuffer(requests,accounting,request,limits={}){let{maxEntries=500,maxBytes=33554432,maxFieldBytes=8388608}=limits,index=requests.indexOf(request);if(index===-1)return[];synchronizeAccounting(requests,accounting),applyFieldLimits(request,maxFieldBytes);let previousSize=accounting.sizes[index]??0,nextSize=estimateRequestBufferBytes(request);return accounting.sizes[index]=nextSize,accounting.totalBytes+=nextSize-previousSize,trimRequestBuffer(requests,accounting,maxEntries,maxBytes)}var ALLOWED_ORIGINS=["*://localhost/*","*://127.0.0.1/*","*://*.alibaba.com/*","*://*.alibaba-inc.com/*","*://*.taobao.com/*","*://*.antfin.com/*","*://*.tmall.com/*","*://*.fliggy.com/*","*://*.alitrip.com/*","*://*.aliexpress.com/*","*://*.atatech.org/*","*://*.dingtalk.com/*","*://*.ele.me/*","*://*.effirst.com/*","*://*.example.com/*","*://*.figma.com/*"],ALLOWED_ORIGINS_LIST=[...ALLOWED_ORIGINS];function typeIntoElement(el,inputValue,shouldClear){if(!el)return{typed:!1,tag:"",error:"Element is null"};if(!el.isConnected)return{typed:!1,tag:"",error:"Element is detached from the document"};let tagName=el.tagName?el.tagName.toLowerCase():"",isInput=el instanceof HTMLInputElement,isTextArea=el instanceof HTMLTextAreaElement,isFormField=isInput||isTextArea,htmlEl=el,isEditable=!isFormField&&(htmlEl.isContentEditable||el.getAttribute("contenteditable")==="true");if(!isFormField&&!isEditable)return{typed:!1,tag:tagName,error:"Element <"+tagName+"> is neither an input/textarea nor contenteditable"};if(isFormField){let f=el;if(f.disabled)return{typed:!1,tag:tagName,error:"Element is disabled"};if(f.readOnly)return{typed:!1,tag:tagName,error:"Element is readOnly"}}if(htmlEl.scrollIntoView({block:"center",behavior:"instant"}),htmlEl.focus(),isFormField){let f=el,proto=isTextArea?HTMLTextAreaElement.prototype:HTMLInputElement.prototype,nativeSetter=Object.getOwnPropertyDescriptor(proto,"value")?.set,setVal=v=>{nativeSetter?nativeSetter.call(f,v):f.value=v};return shouldClear&&f.value!==""&&(setVal(""),f.dispatchEvent(new Event("input",{bubbles:!0}))),setVal(inputValue),f.dispatchEvent(new InputEvent("beforeinput",{bubbles:!0,cancelable:!0,data:inputValue,inputType:"insertText"})),f.dispatchEvent(new InputEvent("input",{bubbles:!0,data:inputValue,inputType:"insertText"})),f.dispatchEvent(new Event("change",{bubbles:!0})),{typed:!0,tag:tagName}}let selection=window.getSelection();if(shouldClear){if(selection){let range=document.createRange();range.selectNodeContents(htmlEl),selection.removeAllRanges(),selection.addRange(range)}let cleared;try{cleared=document.execCommand("delete")}catch{cleared=!1}cleared||(htmlEl.textContent="")}else if(selection){let range=document.createRange();range.selectNodeContents(htmlEl),range.collapse(!1),selection.removeAllRanges(),selection.addRange(range)}htmlEl.dispatchEvent(new InputEvent("beforeinput",{bubbles:!0,cancelable:!0,data:inputValue,inputType:"insertText"}));let inserted;try{inserted=document.execCommand("insertText",!1,inputValue)}catch{inserted=!1}return inserted||(htmlEl.textContent=(htmlEl.textContent??"")+inputValue),htmlEl.dispatchEvent(new InputEvent("input",{bubbles:!0,data:inputValue,inputType:"insertText"})),{typed:!0,tag:tagName}}var UNSUPPORTED_NATIVE_SELECTOR_PSEUDOS=[":has-text",":text(",":text-is(",":text-matches(",":visible",":hidden",":nth-match(",":light(",":above(",":below(",":near(",":left-of(",":right-of(",":contains("],INVALID_NATIVE_SELECTOR_HINT='Only native CSS is supported (no Playwright extensions like :has-text/:visible). Use page_snapshot to get an "@eN" ref for complex matching.';function validatePageElementSelector(selector,toolName){if(!selector||typeof selector!="string")throw new Error(`${toolName}: "selector" must be a non-empty string. Pass a native CSS selector (e.g. "[aria-label='提交']") or a snapshot ref like "@e3". Note: the field name is "selector", not "ref".`);if(/^e\d+$/.test(selector))throw new Error(`${toolName}: selector "${selector}" looks like a snapshot ref but is missing the "@" prefix. Use "@${selector}" instead. If you don't have refs yet, call page_snapshot first.`);for(let pseudo of UNSUPPORTED_NATIVE_SELECTOR_PSEUDOS)if(selector.includes(pseudo))throw new Error(`${toolName}: selector contains unsupported pseudo "${pseudo}". Only native CSS selectors are supported (no Playwright/jQuery extensions). For text-based matching, run page_snapshot and use the returned "@eN" ref. For attribute matching, prefer "[aria-label='...']", "[title='...']", "[data-testid='...']" etc.`)}function resolvePageScrollInput(data){let{direction,distance,selector,containerPolicy="self"}=data;if(typeof direction!="string"||!["up","down","top","bottom"].includes(direction))throw new Error("Invalid direction: must be one of up, down, top, bottom");if(distance!==void 0&&(typeof distance!="number"||!Number.isFinite(distance)))throw new Error('"distance" must be a finite number');if(selector!==void 0&&validatePageElementSelector(selector,"page_scroll"),containerPolicy!=="self"&&containerPolicy!=="nearest")throw new Error('"containerPolicy" must be one of self, nearest');return{direction,distance:Math.abs(distance??600),containerPolicy,...selector!==void 0?{selector}:{}}}function scrollElementInPage(direction,distance,targetLabel,containerPolicy="self"){let element=this?.nodeType===3?this.parentElement:this;if(element?.nodeType===9&&(element=element.scrollingElement),!element||element.isConnected===!1)return{error:"Cannot resolve scroll container: "+targetLabel};let startingElement=element,ancestorDistance=0;function scrollMetrics(candidate){let scrollTop=Number(candidate?.scrollTop),scrollHeight=Number(candidate?.scrollHeight),clientHeight=Number(candidate?.clientHeight);if(!Number.isFinite(scrollTop)||!Number.isFinite(scrollHeight)||!Number.isFinite(clientHeight))return null;let ownerDocument=candidate.ownerDocument,isRootScroller=!!ownerDocument&&candidate===ownerDocument.scrollingElement,maxScrollTop=Math.max(0,scrollHeight-clientHeight),overflowAllowsScroll=!0;try{let overflowY=ownerDocument?.defaultView?.getComputedStyle(candidate).overflowY;!isRootScroller&&(overflowY==="visible"||overflowY==="clip")&&(overflowAllowsScroll=!1)}catch{}return{scrollTop,scrollHeight,clientHeight,maxScrollTop,isRootScroller,usable:isRootScroller||maxScrollTop>0&&overflowAllowsScroll}}let metrics=scrollMetrics(element);if(!metrics)return{error:"Element is not scrollable: "+targetLabel};if(!metrics.usable&&containerPolicy==="nearest"){let candidate=element.parentElement;for(;candidate;){ancestorDistance+=1;let candidateMetrics=scrollMetrics(candidate);if(candidateMetrics?.usable){element=candidate,metrics=candidateMetrics;break}candidate=candidate.parentElement}}if(!metrics.usable&&!metrics.isRootScroller)return{error:"Element is not scrollable: "+targetLabel+(containerPolicy==="nearest"?" (no scrollable ancestor found)":"")};let targetTop;switch(direction){case"top":targetTop=0;break;case"bottom":targetTop=metrics.maxScrollTop;break;case"up":targetTop=Math.max(0,metrics.scrollTop-Math.abs(distance));break;default:targetTop=Math.min(metrics.maxScrollTop,metrics.scrollTop+Math.abs(distance));break}if(typeof element.scrollTo=="function")try{element.scrollTo({top:targetTop,left:Number(element.scrollLeft)||0,behavior:"instant"})}catch{element.scrollTop=targetTop}else element.scrollTop=targetTop;let actualScrollTop=Number(element.scrollTop);return!metrics.isRootScroller&&targetTop!==metrics.scrollTop&&actualScrollTop===metrics.scrollTop?{error:"Element is not scrollable: "+targetLabel}:{scrollY:Math.round(actualScrollTop),scrollHeight:metrics.scrollHeight,clientHeight:metrics.clientHeight,maxScrollY:Math.round(metrics.maxScrollTop),scrollYBefore:Math.round(metrics.scrollTop),scrollYAfter:Math.round(actualScrollTop),moved:actualScrollTop!==metrics.scrollTop,atTop:actualScrollTop<=0,atBottom:actualScrollTop>=metrics.maxScrollTop,target:targetLabel,resolvedContainer:element===startingElement?"self":"nearest-scrollable-ancestor",ancestorDistance}}var SCROLL_ELEMENT_IN_PAGE_SOURCE=scrollElementInPage.toString();function buildPageScrollExpression(input){return`(() => {
|
|
464
467
|
const dir = ${JSON.stringify(input.direction)};
|
|
465
468
|
const dist = ${JSON.stringify(input.distance)};
|
|
@@ -492,8 +495,8 @@ ${truncated}...`}function extractFields(data,fields){if(fields.length>100)throw
|
|
|
492
495
|
`};function createControlledFaviconDataUrl(source){let svg=`<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" data-control-source="${source}">
|
|
493
496
|
${BASE_ICON}
|
|
494
497
|
${SOURCE_BADGES[source]}
|
|
495
|
-
</svg>`;return`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`}var enabledDomains=new WeakMap;function ensureCdpDomain(client2,domain2,params={}){let domains=enabledDomains.get(client2);domains||(domains=new Map,enabledDomains.set(client2,domains));let existing=domains.get(domain2);if(existing)return existing;let enabling=client2.sendCommand(`${domain2}.enable`,params).then(()=>{}).catch(error48=>{throw domains?.get(domain2)===enabling&&domains.delete(domain2),error48});return domains.set(domain2,enabling),enabling}var MAX_LOGS=500,MAX_EVENTS=500,COLLECTED_RESOURCE_TYPES=new Set(["xhr","fetch","document"]);function createBuffers(tabId=0){return{requests:[],logs:[],events:[],pending:new Map,requestCounter:0,requestBufferAccounting:createRequestBufferAccounting(),capture:{tabId,generation:createCaptureGeneration(),currentSequence:0,droppedRequestsThroughSequence:0,droppedLogsThroughSequence:0,droppedEventsThroughSequence:0}}}function parseQueryString(url2){try{let u=new URL(url2),result=[];return u.searchParams.forEach((value,name)=>result.push({name,value})),result}catch{return[]}}function headersObjToArray(obj){return Object.entries(obj).map(([name,value])=>({name,value}))}function extractMtopApiName(url2,postData){try{let u=new URL(url2),pathMatch=u.pathname.match(/\/h5\/([\w.]+)\//);if(pathMatch)return pathMatch[1];let proxyMatch=u.searchParams.get("requestUrl")?.match(/\b(?:mtop|mopen)\.[\w.]+/);if(proxyMatch)return proxyMatch[0]}catch{}let urlMatch=url2.match(/\b(?:mtop|mopen)\.[\w.]+/);if(urlMatch)return urlMatch[0];if(!postData)return null;try{let parsed=JSON.parse(postData),proxyMatch=(typeof parsed?.requestUrl=="string"?parsed.requestUrl:void 0)?.match(/\b(?:mtop|mopen)\.[\w.]+/);if(proxyMatch)return proxyMatch[0]}catch{let proxyMatch=new URLSearchParams(postData).get("requestUrl")?.match(/\b(?:mtop|mopen)\.[\w.]+/);if(proxyMatch)return proxyMatch[0]}return null}function requestDisplayName(url2){try{return new URL(url2).pathname}catch{return url2}}function parsePostData(postData){if(!postData)return null;try{return JSON.parse(postData)}catch{try{let params={};return new URLSearchParams(postData).forEach((v,k)=>params[k]=v),params}catch{return postData}}}function appendTrackingEvents(buffers,url2,postData,batchSequence,captureSequence){let events=parseTrackingRequest(url2,postData,{sequence:batchSequence,now:Date.now()}).map(event=>({...event,captureSequence}));if(events.length===0)return!1;let removed=appendCapturedTrackingBatch(buffers.events,events,MAX_EVENTS);for(let event of removed)event.captureSequence!==void 0&&(buffers.capture.droppedEventsThroughSequence=Math.max(buffers.capture.droppedEventsThroughSequence,event.captureSequence));return!0}function recordDroppedRequests(buffers,removed){for(let request of removed)request.captureSequence!==void 0&&(buffers.capture.droppedRequestsThroughSequence=Math.max(buffers.capture.droppedRequestsThroughSequence,request.captureSequence))}function appendCapturedRequest(buffers,request){recordDroppedRequests(buffers,appendRequestToBuffer(buffers.requests,buffers.requestBufferAccounting,request))}function refreshCapturedRequest(buffers,request){recordDroppedRequests(buffers,refreshRequestInBuffer(buffers.requests,buffers.requestBufferAccounting,request))}function appendCapturedLog(buffers,log3){if(buffers.logs.push({...log3,captureSequence:nextCaptureSequence(buffers.capture)}),buffers.logs.length>MAX_LOGS){let removed=buffers.logs.shift();removed&&(buffers.capture.droppedLogsThroughSequence=removed.captureSequence)}}async function setupBufferListeners(client2,buffers){client2.on("Network.requestWillBeSent",params=>{let url2=params.request?.url??"";if(!url2.startsWith("http"))return;if(isTrackingUrl(url2)){let batchSequence=++buffers.requestCounter,captureSequence2=nextCaptureSequence(buffers.capture);!appendTrackingEvents(buffers,url2,params.request?.postData,batchSequence,captureSequence2)&¶ms.request?.hasPostData&&!params.request?.postData&&client2.sendCommand("Network.getRequestPostData",{requestId:params.requestId},1e4).then(result=>appendTrackingEvents(buffers,url2,result?.postData,batchSequence,captureSequence2)).catch(()=>{});return}let resourceType=String(params.type??"").toLowerCase(),mtopApiName=extractMtopApiName(url2,params.request?.postData),isMtop=mtopApiName!==null;if(!isMtop&&!COLLECTED_RESOURCE_TYPES.has(resourceType))return;let ts=params.timestamp,timestampMs2=params.wallTime!==void 0?Math.floor(params.wallTime*1e3):Date.now(),redirected=buffers.pending.get(params.requestId);redirected&¶ms.redirectResponse&&(redirected.status=params.redirectResponse.status??0,redirected.statusText=params.redirectResponse.statusText??"",redirected.duration=ts!==void 0&&redirected.startTs!==void 0?Math.round((ts-redirected.startTs)*1e3):void 0,redirected.isPending=!1,refreshCapturedRequest(buffers,redirected),buffers.pending.delete(params.requestId));let id=++buffers.requestCounter,captureSequence=nextCaptureSequence(buffers.capture),partial2={id,requestId:params.requestId,timestamp:new Date(timestampMs2).toISOString(),timestampMs:timestampMs2,method:params.request?.method??"GET",url:url2,apiName:mtopApiName??requestDisplayName(url2),headers:headersObjToArray(params.request?.headers??{}),postData:parsePostData(params.request?.postData),queryString:parseQueryString(url2),status:0,statusText:"",responseHeaders:[],responseBody:null,isProxy:!1,proxyRequestUrl:null,proxyData:null,startTs:ts,captureSequence,isPending:!0,source:isMtop?"mtop":"requests",resourceType};buffers.pending.set(params.requestId,partial2),appendCapturedRequest(buffers,partial2)}),client2.on("Network.responseReceived",params=>{let partial2=buffers.pending.get(params.requestId);partial2&&(partial2.status=params.response?.status??0,partial2.statusText=params.response?.statusText??"",partial2.responseHeaders=headersObjToArray(params.response?.headers??{}),refreshCapturedRequest(buffers,partial2))}),client2.on("Network.loadingFinished",params=>{let partial2=buffers.pending.get(params.requestId);if(!partial2)return;buffers.pending.delete(params.requestId);let endTs=params.timestamp,duration3=endTs!==void 0&&partial2.startTs!==void 0?Math.round((endTs-partial2.startTs)*1e3):void 0;partial2.duration=duration3,partial2.isPending=!1,refreshCapturedRequest(buffers,partial2),client2.sendCommand("Network.getResponseBody",{requestId:params.requestId},1e4).then(result=>{if(partial2.responseBody=result.base64Encoded?Buffer.from(result.body,"base64").toString("utf-8"):result.body,typeof partial2.responseBody=="string")try{partial2.responseBody=JSON.parse(partial2.responseBody)}catch{}refreshCapturedRequest(buffers,partial2)}).catch(()=>{})}),client2.on("Network.loadingFailed",params=>{let partial2=buffers.pending.get(params.requestId);partial2&&(buffers.pending.delete(params.requestId),partial2.status=0,partial2.statusText=params.errorText??"Failed",partial2.duration=params.timestamp!==void 0&&partial2.startTs!==void 0?Math.round((params.timestamp-partial2.startTs)*1e3):void 0,partial2.isPending=!1,refreshCapturedRequest(buffers,partial2))}),client2.on("Runtime.consoleAPICalled",params=>{let level={warning:"warn",debug:"debug",info:"info",error:"error",assert:"error"}[params.type]??"log",args=(params.args??[]).map(arg=>arg.type==="string"?arg.value:arg.value!==void 0?String(arg.value):arg.description!==void 0?arg.description:JSON.stringify(arg));appendCapturedLog(buffers,{level,message:args.join(" "),timestampMs:params.timestamp??Date.now(),source:params.stackTrace?.callFrames?.[0]?.url?`${params.stackTrace.callFrames[0].url.split("/").pop()||params.stackTrace.callFrames[0].url}:${params.stackTrace.callFrames[0].lineNumber+1}`:"console",args,origin:"console"})}),client2.on("Runtime.exceptionThrown",params=>{let details=params.exceptionDetails??{},exception=details.exception,message=exception?.description??(exception?.value!==void 0?String(exception.value):void 0)??details.text??"Uncaught exception",topFrame=details.stackTrace?.callFrames?.[0],url2=topFrame?.url||details.url,lineNumber=topFrame?.lineNumber??details.lineNumber,source=url2?`${url2.split("/").pop()||url2}${lineNumber!==void 0?`:${lineNumber+1}`:""}`:void 0;appendCapturedLog(buffers,{level:"error",message,timestampMs:params.timestamp??Date.now(),...source?{source}:{},args:[message],origin:"exception"})}),client2.on("Log.entryAdded",params=>{let entry=params.entry??{},levelMap={verbose:"log",info:"info",warning:"warn",error:"error"},args=(entry.args??[]).map(arg=>arg.value!==void 0?String(arg.value):arg.description??`[${arg.type||"Object"}]`),message=entry.text||args.join(" ");appendCapturedLog(buffers,{level:levelMap[entry.level]??entry.level??"log",message,timestampMs:entry.timestamp??Date.now(),source:entry.url?`${entry.url.split("/").pop()||entry.url}${entry.lineNumber!==void 0?`:${entry.lineNumber+1}`:""}`:entry.source??"other",args:args.length>0?args:[message],origin:"browser"})}),await Promise.all([ensureCdpDomain(client2,"Network",{maxTotalBufferSize:10*1024*1024,maxPostDataSize:5*1024*1024}),ensureCdpDomain(client2,"Runtime"),ensureCdpDomain(client2,"Log")])}import fs from"node:fs";import http from"node:http";import os from"node:os";import path from"node:path";function chromeUserDataDir(){let platform=process.platform,home=os.homedir();return platform==="darwin"?path.join(home,"Library","Application Support","Google","Chrome"):platform==="win32"?path.join(process.env.LOCALAPPDATA??home,"Google","Chrome","User Data"):path.join(home,".config","google-chrome")}function readDevToolsActivePort(userDataDir=chromeUserDataDir()){try{let filePath=path.join(userDataDir,"DevToolsActivePort"),lines=fs.readFileSync(filePath,"utf8").trim().split(`
|
|
496
|
-
`).map(l=>l.trim()),port=parseInt(lines[0],10),browserWsPath=lines[1]??"/devtools/browser";return isNaN(port)?null:{port,browserWsPath}}catch{return null}}async function discoverTargets(port=9222){return new Promise((resolve3,reject)=>{let req=http.get(`http://localhost:${port}/json`,res=>{let data="";res.on("data",chunk=>data+=chunk),res.on("end",()=>{try{resolve3(JSON.parse(data))}catch(e){reject(new Error(`Failed to parse CDP targets: ${e}`))}})});req.on("error",reject),req.setTimeout(3e3,()=>{req.destroy(),reject(new Error("CDP discover timeout"))})})}var CdpSession=class{port;userDataDir;endpointUrl;endpointResolver;browserClient=null;browserClientPromise=null;pageSessions=new Map;tabIdMap=new Map;nextTabId=1e3;constructor(options=9222){if(typeof options=="number"){this.port=options;return}this.port=options.port??9222,this.userDataDir=options.userDataDir,this.endpointUrl=options.endpointUrl,this.endpointResolver=options.endpointResolver}async getBrowserClient(){if(this.browserClient&&!this.browserClient.closed)return this.browserClient;this.browserClientPromise||(this.browserClientPromise=this.connectBrowserClient());let pending=this.browserClientPromise;try{return await pending}finally{this.browserClientPromise===pending&&(this.browserClientPromise=null)}}async getPageSession(virtualTabId){let targetId;if(virtualTabId!==void 0&&(targetId=this.tabIdMap.get(virtualTabId),!targetId))throw new Error(`Tab ${virtualTabId} not found. Open a tab first with tab_open.`);if(targetId){let
|
|
498
|
+
</svg>`;return`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`}var enabledDomains=new WeakMap;function ensureCdpDomain(client2,domain2,params={}){let domains=enabledDomains.get(client2);domains||(domains=new Map,enabledDomains.set(client2,domains));let existing=domains.get(domain2);if(existing)return existing;let enabling=client2.sendCommand(`${domain2}.enable`,params).then(()=>{}).catch(error48=>{throw domains?.get(domain2)===enabling&&domains.delete(domain2),error48});return domains.set(domain2,enabling),enabling}var MAX_LOGS=500,MAX_EVENTS=500,COLLECTED_RESOURCE_TYPES=new Set(["xhr","fetch","document","eventsource"]);function createBuffers(tabId=0){return{requests:[],logs:[],events:[],pending:new Map,sseStreams:new Map,requestCounter:0,requestBufferAccounting:createRequestBufferAccounting(),capture:{tabId,generation:createCaptureGeneration(),currentSequence:0,droppedRequestsThroughSequence:0,droppedLogsThroughSequence:0,droppedEventsThroughSequence:0}}}function parseQueryString2(url2){try{let u=new URL(url2),result=[];return u.searchParams.forEach((value,name)=>result.push({name,value})),result}catch{return[]}}function headersObjToArray(obj){return Object.entries(obj).map(([name,value])=>({name,value:String(value)}))}function getHeaderValue(headers,targetName){let target=targetName.toLowerCase(),entry=Object.entries(headers).find(([name])=>name.toLowerCase()===target);return entry?String(entry[1]):""}function extractMtopApiName(url2,postData){try{let u=new URL(url2),pathMatch=u.pathname.match(/\/h5\/([\w.]+)\//);if(pathMatch)return pathMatch[1];let proxyMatch=u.searchParams.get("requestUrl")?.match(/\b(?:mtop|mopen)\.[\w.]+/);if(proxyMatch)return proxyMatch[0]}catch{}let urlMatch=url2.match(/\b(?:mtop|mopen)\.[\w.]+/);if(urlMatch)return urlMatch[0];if(!postData)return null;try{let parsed=JSON.parse(postData),proxyMatch=(typeof parsed?.requestUrl=="string"?parsed.requestUrl:void 0)?.match(/\b(?:mtop|mopen)\.[\w.]+/);if(proxyMatch)return proxyMatch[0]}catch{let proxyMatch=new URLSearchParams(postData).get("requestUrl")?.match(/\b(?:mtop|mopen)\.[\w.]+/);if(proxyMatch)return proxyMatch[0]}return null}function requestDisplayName(url2){try{return new URL(url2).pathname}catch{return url2}}function parsePostData(postData){if(!postData)return null;try{return JSON.parse(postData)}catch{try{let params={};return new URLSearchParams(postData).forEach((v,k)=>params[k]=v),params}catch{return postData}}}function appendTrackingEvents(buffers,url2,postData,batchSequence,captureSequence){let events=parseTrackingRequest(url2,postData,{sequence:batchSequence,now:Date.now()}).map(event=>({...event,captureSequence}));if(events.length===0)return!1;let removed=appendCapturedTrackingBatch(buffers.events,events,MAX_EVENTS);for(let event of removed)event.captureSequence!==void 0&&(buffers.capture.droppedEventsThroughSequence=Math.max(buffers.capture.droppedEventsThroughSequence,event.captureSequence));return!0}function recordDroppedRequests(buffers,removed){for(let request of removed)request.captureSequence!==void 0&&(buffers.capture.droppedRequestsThroughSequence=Math.max(buffers.capture.droppedRequestsThroughSequence,request.captureSequence))}function appendCapturedRequest(buffers,request){recordDroppedRequests(buffers,appendRequestToBuffer(buffers.requests,buffers.requestBufferAccounting,request))}function refreshCapturedRequest(buffers,request){recordDroppedRequests(buffers,refreshRequestInBuffer(buffers.requests,buffers.requestBufferAccounting,request))}function recordCdpMtopStreamStart(buffers,data){let capture=createMtopStreamCapture({...data,id:++buffers.requestCounter,tabId:buffers.capture.tabId,captureSequence:nextCaptureSequence(buffers.capture)});return appendCapturedRequest(buffers,capture.request),capture}function recordCdpMtopStreamResponse(buffers,capture,response){updateMtopStreamCaptureResponse(capture,response),refreshCapturedRequest(buffers,capture.request)}function recordCdpMtopStreamChunk(buffers,capture,data,timestampMs2=Date.now()){appendMtopStreamCaptureChunk(capture,data,timestampMs2)&&refreshCapturedRequest(buffers,capture.request)}function recordCdpMtopStreamEnd(buffers,capture,options={}){finishMtopStreamCapture(capture,options),refreshCapturedRequest(buffers,capture.request)}function requestEventTimestamp(partial2,monotonicTimestamp){return monotonicTimestamp!==void 0&&partial2.startTs!==void 0?Math.round(partial2.timestampMs+(monotonicTimestamp-partial2.startTs)*1e3):Date.now()}function ensurePageSseStream(buffers,partial2,mode){partial2.isSSE=!0,Array.isArray(partial2.responseBody)||(partial2.responseBody=[]);let existing=buffers.sseStreams.get(partial2.requestId);if(existing)return existing;let stream={parser:createSseEventParser(),decoder:new TextDecoder2,mode};return buffers.sseStreams.set(partial2.requestId,stream),stream}function appendPageSseEvents(buffers,partial2,stream,events,timestampMs2){if(Array.isArray(partial2.responseBody)){for(let event of events)partial2.responseBody.push({event:event.event,data:event.data,...event.eventId!==void 0?{eventId:event.eventId}:{},timestamp:timestampMs2,duration:stream.lastMessageTimeMs===void 0?0:timestampMs2-stream.lastMessageTimeMs}),stream.lastMessageTimeMs=timestampMs2;events.length>0&&refreshCapturedRequest(buffers,partial2)}}function consumePageSseBytes(buffers,partial2,stream,bytes,timestampMs2){let text=stream.decoder.decode(bytes,{stream:!0});appendPageSseEvents(buffers,partial2,stream,stream.parser.push(text),timestampMs2)}function finishPageSseStream(buffers,partial2,stream,timestampMs2){let tail=stream.decoder.decode(),events=[...stream.parser.push(tail),...stream.parser.finish()];appendPageSseEvents(buffers,partial2,stream,events,timestampMs2)}function replaceWithParsedSseBody(partial2,body,timestampMs2){let parser=createSseEventParser();partial2.responseBody=[...parser.push(body),...parser.finish()].map(event=>({event:event.event,data:event.data,...event.eventId!==void 0?{eventId:event.eventId}:{},timestamp:timestampMs2,duration:0}))}function appendCapturedLog(buffers,log3){if(buffers.logs.push({...log3,captureSequence:nextCaptureSequence(buffers.capture)}),buffers.logs.length>MAX_LOGS){let removed=buffers.logs.shift();removed&&(buffers.capture.droppedLogsThroughSequence=removed.captureSequence)}}async function setupBufferListeners(client2,buffers){client2.on("Network.requestWillBeSent",params=>{let url2=params.request?.url??"";if(!url2.startsWith("http"))return;if(isTrackingUrl(url2)){let batchSequence=++buffers.requestCounter,captureSequence2=nextCaptureSequence(buffers.capture);!appendTrackingEvents(buffers,url2,params.request?.postData,batchSequence,captureSequence2)&¶ms.request?.hasPostData&&!params.request?.postData&&client2.sendCommand("Network.getRequestPostData",{requestId:params.requestId},1e4).then(result=>appendTrackingEvents(buffers,url2,result?.postData,batchSequence,captureSequence2)).catch(()=>{});return}let resourceType=String(params.type??"").toLowerCase(),mtopApiName=extractMtopApiName(url2,params.request?.postData),isMtop=mtopApiName!==null;if(!isMtop&&!COLLECTED_RESOURCE_TYPES.has(resourceType))return;let ts=params.timestamp,timestampMs2=params.wallTime!==void 0?Math.floor(params.wallTime*1e3):Date.now(),redirected=buffers.pending.get(params.requestId);redirected&¶ms.redirectResponse&&(redirected.status=params.redirectResponse.status??0,redirected.statusText=params.redirectResponse.statusText??"",redirected.duration=ts!==void 0&&redirected.startTs!==void 0?Math.round((ts-redirected.startTs)*1e3):void 0,redirected.isPending=!1,refreshCapturedRequest(buffers,redirected),buffers.pending.delete(params.requestId),buffers.sseStreams.delete(params.requestId));let id=++buffers.requestCounter,captureSequence=nextCaptureSequence(buffers.capture),partial2={id,requestId:params.requestId,timestamp:new Date(timestampMs2).toISOString(),timestampMs:timestampMs2,method:params.request?.method??"GET",url:url2,apiName:mtopApiName??requestDisplayName(url2),headers:headersObjToArray(params.request?.headers??{}),postData:parsePostData(params.request?.postData),queryString:parseQueryString2(url2),status:0,statusText:"",responseHeaders:[],responseBody:resourceType==="eventsource"?[]:null,isProxy:!1,proxyRequestUrl:null,proxyData:null,startTs:ts,captureSequence,isPending:!0,isSSE:resourceType==="eventsource",source:isMtop?"mtop":"requests",resourceType};buffers.pending.set(params.requestId,partial2),appendCapturedRequest(buffers,partial2)}),client2.on("Network.responseReceived",params=>{let partial2=buffers.pending.get(params.requestId);if(!partial2)return;partial2.status=params.response?.status??0,partial2.statusText=params.response?.statusText??"",partial2.responseHeaders=headersObjToArray(params.response?.headers??{});let contentType=getHeaderValue(params.response?.headers??{},"content-type");if(partial2.resourceType==="eventsource"||contentType.toLowerCase().includes("text/event-stream")){let mode=partial2.resourceType==="eventsource"?"eventsource":"resource",stream=ensurePageSseStream(buffers,partial2,mode);mode==="resource"&&client2.sendCommand("Network.streamResourceContent",{requestId:params.requestId},1e4).then(result=>{buffers.sseStreams.get(params.requestId)===stream&&typeof result?.bufferedData=="string"&&result.bufferedData&&consumePageSseBytes(buffers,partial2,stream,Buffer.from(result.bufferedData,"base64"),requestEventTimestamp(partial2,params.timestamp))}).catch(()=>{buffers.sseStreams.get(params.requestId)===stream&&(stream.mode="fallback")})}refreshCapturedRequest(buffers,partial2)}),client2.on("Network.dataReceived",params=>{let partial2=buffers.pending.get(params.requestId),stream=buffers.sseStreams.get(params.requestId);!partial2||stream?.mode!=="resource"||typeof params.data!="string"||consumePageSseBytes(buffers,partial2,stream,Buffer.from(params.data,"base64"),requestEventTimestamp(partial2,params.timestamp))}),client2.on("Network.eventSourceMessageReceived",params=>{let partial2=buffers.pending.get(params.requestId);if(!partial2)return;let stream=ensurePageSseStream(buffers,partial2,"eventsource");appendPageSseEvents(buffers,partial2,stream,[{event:typeof params.eventName=="string"&¶ms.eventName?params.eventName:"message",data:parseSseDataValue(String(params.data??"")),...typeof params.eventId=="string"&¶ms.eventId?{eventId:params.eventId}:{}}],requestEventTimestamp(partial2,params.timestamp))}),client2.on("Network.loadingFinished",params=>{let partial2=buffers.pending.get(params.requestId);if(!partial2)return;buffers.pending.delete(params.requestId);let endTs=params.timestamp,duration3=endTs!==void 0&&partial2.startTs!==void 0?Math.round((endTs-partial2.startTs)*1e3):void 0,stream=buffers.sseStreams.get(params.requestId);stream?.mode==="resource"&&finishPageSseStream(buffers,partial2,stream,requestEventTimestamp(partial2,params.timestamp)),buffers.sseStreams.delete(params.requestId),partial2.duration=duration3,partial2.isPending=!1,refreshCapturedRequest(buffers,partial2),!(partial2.isSSE&&Array.isArray(partial2.responseBody)&&partial2.responseBody.length>0)&&client2.sendCommand("Network.getResponseBody",{requestId:params.requestId},1e4).then(result=>{let responseBody=result.base64Encoded?Buffer.from(result.body,"base64").toString("utf-8"):result.body;if(partial2.isSSE&&typeof responseBody=="string"){replaceWithParsedSseBody(partial2,responseBody,requestEventTimestamp(partial2,params.timestamp)),refreshCapturedRequest(buffers,partial2);return}if(partial2.responseBody=responseBody,typeof partial2.responseBody=="string")try{partial2.responseBody=JSON.parse(partial2.responseBody)}catch{}refreshCapturedRequest(buffers,partial2)}).catch(()=>{})}),client2.on("Network.loadingFailed",params=>{let partial2=buffers.pending.get(params.requestId);partial2&&(buffers.pending.delete(params.requestId),buffers.sseStreams.delete(params.requestId),partial2.status=0,partial2.statusText=params.errorText??"Failed",partial2.duration=params.timestamp!==void 0&&partial2.startTs!==void 0?Math.round((params.timestamp-partial2.startTs)*1e3):void 0,partial2.isPending=!1,partial2.isSSE&&Array.isArray(partial2.responseBody)&&partial2.responseBody.length===0&&(partial2.responseBody={error:partial2.statusText}),refreshCapturedRequest(buffers,partial2))}),client2.on("Runtime.consoleAPICalled",params=>{let level={warning:"warn",debug:"debug",info:"info",error:"error",assert:"error"}[params.type]??"log",args=(params.args??[]).map(arg=>arg.type==="string"?arg.value:arg.value!==void 0?String(arg.value):arg.description!==void 0?arg.description:JSON.stringify(arg));appendCapturedLog(buffers,{level,message:args.join(" "),timestampMs:params.timestamp??Date.now(),source:params.stackTrace?.callFrames?.[0]?.url?`${params.stackTrace.callFrames[0].url.split("/").pop()||params.stackTrace.callFrames[0].url}:${params.stackTrace.callFrames[0].lineNumber+1}`:"console",args,origin:"console"})}),client2.on("Runtime.exceptionThrown",params=>{let details=params.exceptionDetails??{},exception=details.exception,message=exception?.description??(exception?.value!==void 0?String(exception.value):void 0)??details.text??"Uncaught exception",topFrame=details.stackTrace?.callFrames?.[0],url2=topFrame?.url||details.url,lineNumber=topFrame?.lineNumber??details.lineNumber,source=url2?`${url2.split("/").pop()||url2}${lineNumber!==void 0?`:${lineNumber+1}`:""}`:void 0;appendCapturedLog(buffers,{level:"error",message,timestampMs:params.timestamp??Date.now(),...source?{source}:{},args:[message],origin:"exception"})}),client2.on("Log.entryAdded",params=>{let entry=params.entry??{},levelMap={verbose:"log",info:"info",warning:"warn",error:"error"},args=(entry.args??[]).map(arg=>arg.value!==void 0?String(arg.value):arg.description??`[${arg.type||"Object"}]`),message=entry.text||args.join(" ");appendCapturedLog(buffers,{level:levelMap[entry.level]??entry.level??"log",message,timestampMs:entry.timestamp??Date.now(),source:entry.url?`${entry.url.split("/").pop()||entry.url}${entry.lineNumber!==void 0?`:${entry.lineNumber+1}`:""}`:entry.source??"other",args:args.length>0?args:[message],origin:"browser"})}),await Promise.all([ensureCdpDomain(client2,"Network",{maxTotalBufferSize:10*1024*1024,maxPostDataSize:5*1024*1024}),ensureCdpDomain(client2,"Runtime"),ensureCdpDomain(client2,"Log")])}import fs from"node:fs";import http from"node:http";import os from"node:os";import path from"node:path";function chromeUserDataDir(){let platform=process.platform,home=os.homedir();return platform==="darwin"?path.join(home,"Library","Application Support","Google","Chrome"):platform==="win32"?path.join(process.env.LOCALAPPDATA??home,"Google","Chrome","User Data"):path.join(home,".config","google-chrome")}function readDevToolsActivePort(userDataDir=chromeUserDataDir()){try{let filePath=path.join(userDataDir,"DevToolsActivePort"),lines=fs.readFileSync(filePath,"utf8").trim().split(`
|
|
499
|
+
`).map(l=>l.trim()),port=parseInt(lines[0],10),browserWsPath=lines[1]??"/devtools/browser";return isNaN(port)?null:{port,browserWsPath}}catch{return null}}async function discoverTargets(port=9222){return new Promise((resolve3,reject)=>{let req=http.get(`http://localhost:${port}/json`,res=>{let data="";res.on("data",chunk=>data+=chunk),res.on("end",()=>{try{resolve3(JSON.parse(data))}catch(e){reject(new Error(`Failed to parse CDP targets: ${e}`))}})});req.on("error",reject),req.setTimeout(3e3,()=>{req.destroy(),reject(new Error("CDP discover timeout"))})})}var CdpSession=class{port;userDataDir;endpointUrl;endpointResolver;browserClient=null;browserClientPromise=null;pageSessions=new Map;tabIdMap=new Map;nextTabId=1e3;constructor(options=9222){if(typeof options=="number"){this.port=options;return}this.port=options.port??9222,this.userDataDir=options.userDataDir,this.endpointUrl=options.endpointUrl,this.endpointResolver=options.endpointResolver}async getBrowserClient(){if(this.browserClient&&!this.browserClient.closed)return this.browserClient;this.browserClientPromise||(this.browserClientPromise=this.connectBrowserClient());let pending=this.browserClientPromise;try{return await pending}finally{this.browserClientPromise===pending&&(this.browserClientPromise=null)}}async getPageSession(virtualTabId){let targetId;if(virtualTabId!==void 0&&(targetId=this.tabIdMap.get(virtualTabId),!targetId))throw new Error(`Tab ${virtualTabId} not found. Open a tab first with tab_open.`);if(targetId){let existing2=this.pageSessions.get(targetId);if(existing2&&!existing2.client.closed)return existing2}let target=targetId?await this.findTargetById(targetId):await this.findDefaultPageTarget();if(!target)throw new Error(virtualTabId?`CDP target for tab ${virtualTabId} is no longer available`:"No active page target found. Open a web page in Chrome with remote debugging enabled.");let existing=this.pageSessions.get(target.id);return existing&&!existing.client.closed?existing:this.createPageSession(target)}async registerTarget(targetId){let virtualId=this.nextTabId++;this.tabIdMap.set(virtualId,targetId);let target=await this.findTargetById(targetId);return target&&await this.createPageSession(target),virtualId}async ensureTargetRegistered(targetId){for(let[virtualId2,registeredTargetId]of this.tabIdMap)if(registeredTargetId===targetId)return virtualId2;let virtualId=this.nextTabId++;return this.tabIdMap.set(virtualId,targetId),virtualId}async connectBrowserClient(){let wsUrl=await this.resolveBrowserWsUrl();if(!wsUrl)throw new Error("No browser-level WebSocket URL available from CDP");let client2=await CdpClient.connect(wsUrl);return this.browserClient=client2,client2.on("Target.targetDestroyed",params=>{for(let[virtualId,targetId]of this.tabIdMap)if(targetId===params.targetId){this.tabIdMap.delete(virtualId);break}this.pageSessions.delete(params.targetId)}),client2}async createPageSession(target){let client2;try{let browser=await this.getBrowserClient(),{sessionId}=await browser.sendCommand("Target.attachToTarget",{targetId:target.id,flatten:!0},5e3);client2=browser.createChildSession(sessionId)}catch(error48){if(this.isRemote())throw new Error(`Failed to attach to remote CDP target ${target.id}: ${error48 instanceof Error?error48.message:String(error48)}`,{cause:error48});client2=await CdpClient.connect(target.webSocketDebuggerUrl)}let tabId;for(let[virtualId,registeredTargetId]of this.tabIdMap)if(registeredTargetId===target.id){tabId=virtualId;break}tabId===void 0&&(tabId=this.nextTabId++,this.tabIdMap.set(tabId,target.id));let buffers=createBuffers(tabId);await setupBufferListeners(client2,buffers);let session={tabId,client:client2,buffers,targetId:target.id,url:target.url};return this.pageSessions.set(target.id,session),client2.on("Inspector.detached",()=>{this.pageSessions.delete(target.id)}),session}async findTargetById(targetId){if(this.isRemote())return this.findTargetByIdViaCdp(targetId);try{return(await discoverTargets(this.effectivePort())).find(t=>t.id===targetId&&t.webSocketDebuggerUrl)??null}catch{return this.findTargetByIdViaCdp(targetId)}}async findDefaultPageTarget(){if(this.isRemote())return this.findDefaultPageTargetViaCdp();try{return(await discoverTargets(this.effectivePort())).find(t=>t.type==="page"&&t.webSocketDebuggerUrl&&!t.url.startsWith("chrome-extension://")&&!t.url.startsWith("about:")&&!t.url.startsWith("chrome://"))??null}catch{return this.findDefaultPageTargetViaCdp()}}effectivePort(){return readDevToolsActivePort(this.userDataDir)?.port??this.port}async resolveBrowserWsUrl(){let configuredEndpoint=this.endpointResolver?await this.endpointResolver():this.endpointUrl;if(configuredEndpoint){let url2=new URL(configuredEndpoint);if(url2.protocol!=="ws:"&&url2.protocol!=="wss:")throw new Error(`Unsupported CDP endpoint protocol: ${url2.protocol}`);return url2.toString()}let fileInfo=readDevToolsActivePort(this.userDataDir);if(fileInfo)return`ws://localhost:${fileInfo.port}${fileInfo.browserWsPath}`;try{return(await this.fetchVersionInfo()).webSocketDebuggerUrl??null}catch{return null}}pageWsUrl(targetId){return`ws://localhost:${this.effectivePort()}/devtools/page/${targetId}`}isRemote(){return!!(this.endpointUrl||this.endpointResolver)}async findTargetByIdViaCdp(targetId){try{let info=(await(await this.getBrowserClient()).sendCommand("Target.getTargets",{})).targetInfos.find(t=>t.targetId===targetId);return info?{id:info.targetId,title:info.title??"",type:info.type??"page",url:info.url??"",webSocketDebuggerUrl:this.pageWsUrl(info.targetId)}:null}catch{return null}}async findDefaultPageTargetViaCdp(){try{let info=(await(await this.getBrowserClient()).sendCommand("Target.getTargets",{})).targetInfos.find(t=>t.type==="page"&&!t.url.startsWith("chrome-extension://")&&!t.url.startsWith("about:")&&!t.url.startsWith("chrome://"));return info?{id:info.targetId,title:info.title??"",type:info.type??"page",url:info.url??"",webSocketDebuggerUrl:this.pageWsUrl(info.targetId)}:null}catch{return null}}fetchVersionInfo(){return new Promise((resolve3,reject)=>{let req=http2.get(`http://localhost:${this.port}/json/version`,res=>{let data="";res.on("data",chunk=>data+=chunk),res.on("end",()=>{try{resolve3(JSON.parse(data))}catch(e){reject(new Error(`Failed to parse CDP version info: ${e}`))}})});req.on("error",reject),req.setTimeout(3e3,()=>{req.destroy(),reject(new Error("CDP version info timeout"))})})}async isAvailable(){try{return await(await this.getBrowserClient()).sendCommand("Target.getTargets",{},3e3),!0}catch{return this.browserClient?.close(),this.browserClient=null,!1}}hasActiveConnections(){return this.browserClient!==null&&!this.browserClient.closed||Array.from(this.pageSessions.values()).some(session=>!session.client.closed)}listOpenPageSessions(){return Array.from(this.pageSessions.values()).filter(session=>!session.client.closed)}listRegisteredTabIds(targetIds){return Array.from(this.tabIdMap.entries()).filter(([,targetId])=>!targetIds||targetIds.has(targetId)).map(([tabId])=>tabId)}close(){this.browserClient?.close(),this.browserClient=null;for(let session of this.pageSessions.values())session.client.close();this.pageSessions.clear(),this.tabIdMap.clear()}};var injectedSessions=new WeakMap,indicatorQueues=new WeakMap;function enqueueIndicatorOperation(session,operation){let queued=(indicatorQueues.get(session)??Promise.resolve()).catch(()=>{}).then(operation);return indicatorQueues.set(session,queued),queued.finally(()=>{indicatorQueues.get(session)===queued&&indicatorQueues.delete(session)})}function createFaviconScript(controlSource){let iconDataUrl=createControlledFaviconDataUrl(controlSource);return`(() => {
|
|
497
500
|
if (window !== window.top) return;
|
|
498
501
|
const ICON = ${JSON.stringify(iconDataUrl)};
|
|
499
502
|
const existing = window.__mearlControlledFavicon__;
|
|
@@ -745,7 +748,7 @@ ${SOURCE_BADGES[source]}
|
|
|
745
748
|
#back svg{width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}#title{position:absolute;left:80px;right:80px;top:0;height:42px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center;font-size:18px;font-weight:700;line-height:22px}
|
|
746
749
|
</style><div id="surface"><div id="nav"><button id="back" type="button" aria-label="返回"><svg viewBox="0 0 28 28" aria-hidden="true"><path d="M19.5 3.5 9 14l10.5 10.5"/></svg></button><div id="title"></div></div></div>`;let surface=shadow.getElementById("surface"),title=shadow.getElementById("title"),back=shadow.getElementById("back");return back.addEventListener("click",onBack),{root,surface,title,back}},createStatusBarView=()=>{let root=document.createElement("div");root.setAttribute("data-mearl-app-statusbar",config2.profile),root.style.cssText=`position:fixed;left:0;right:0;top:0;height:${config2.statusBarHeight}px;z-index:2147483600;overflow:visible;box-sizing:border-box;pointer-events:none;`;let shadow=root.attachShadow({mode:"open"}),deviceModel=config2.globals.__DEVICE_MODEL__??"",hasDynamicIsland=config2.platform==="iOS"&&/^iPhone(?:15|16|17|18),/.test(deviceModel);shadow.innerHTML=`<style>
|
|
747
750
|
:host{all:initial}#surface{position:relative;width:100%;height:calc(100% + 1px);box-sizing:border-box;color:#0f131a;-webkit-font-smoothing:antialiased;text-rendering:geometricPrecision}#surface[data-platform="ios"]{font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text","Helvetica Neue","PingFang SC",sans-serif}#status{height:${config2.statusBarHeight}px;box-sizing:border-box;position:relative;display:flex;align-items:center;justify-content:space-between;padding:0 21px 0 27px;font-size:15px;font-weight:600;line-height:1;font-variant-numeric:tabular-nums;letter-spacing:-.25px}#time{min-width:54px;position:relative;z-index:1;text-align:left}#indicators{height:14px;display:flex;align-items:center;gap:6.5px;position:relative;z-index:1}#indicators svg{display:block;overflow:visible;fill:none;stroke:currentColor}#signal{width:18px;height:12px;fill:currentColor!important;stroke:none!important}#wifi{width:18px;height:14px;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}#battery{width:28px;height:13px;stroke-width:1.25}#battery-outline{opacity:.42}#battery-level{fill:currentColor;stroke:none}#battery-cap{fill:currentColor;stroke:none;opacity:.45}#device-cutout{display:none;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:126px;height:37px;border-radius:19px;background:#000;box-shadow:inset 0 0 0 .5px rgba(255,255,255,.08);z-index:2}#surface[data-cutout="true"] #device-cutout{display:var(--mearl-device-cutout-display,block)}#surface[data-platform="android"]{font-family:Roboto,"Noto Sans SC",sans-serif}#surface[data-platform="android"] #status{padding:0 12px;font-size:12px;font-weight:500;letter-spacing:0}#surface[data-platform="android"] #indicators{gap:5px;transform:scale(.86);transform-origin:right center}
|
|
748
|
-
</style><div id="surface" data-platform="${config2.platform.toLowerCase()}" data-cutout="${String(hasDynamicIsland)}"><div id="status"><span id="time"></span><span id="device-cutout" aria-hidden="true"></span><span id="indicators" aria-hidden="true"><svg id="signal" viewBox="0 0 18 12"><rect x="0" y="8" width="3" height="4" rx="1"/><rect x="5" y="6" width="3" height="6" rx="1"/><rect x="10" y="3" width="3" height="9" rx="1"/><rect x="15" y="0" width="3" height="12" rx="1"/></svg><svg id="wifi" viewBox="1 3.8 22 17.2"><path d="M2 8.82a15 15 0 0 1 20 0"/><path d="M5 12.859a10 10 0 0 1 14 0"/><path d="M8.5 16.429a5 5 0 0 1 7 0"/><path d="M12 20h.01"/></svg><svg id="battery" viewBox="0 0 28 13"><rect id="battery-outline" x=".65" y=".65" width="23" height="11.7" rx="3.1"/><rect id="battery-level" x="2.35" y="2.35" width="19.6" height="8.3" rx="1.7"/><path id="battery-cap" d="M25 4.1c1.1.35 1.7 1.15 1.7 2.4s-.6 2.05-1.7 2.4z"/></svg></span></div></div>`;let surface=shadow.getElementById("surface"),time3=shadow.getElementById("time"),updateTime=()=>{let now=new Date;time3&&(time3.textContent=`${String(now.getHours()).padStart(2,"0")}:${String(now.getMinutes()).padStart(2,"0")}`)};return updateTime(),{root,surface,timeTimer:window.setInterval(updateTime,3e4)}},install=()=>{let titleBar=config2.titleBar;if(!titleBar||!isContainerFrame||!simulateSystemBars)return;let observeState=()=>{new MutationObserver(syncSimulatedTitleBar).observe(document.head??document.documentElement,{subtree:!0,childList:!0,characterData:!0,attributes:!0,attributeFilter:["content","value"]}),window.addEventListener("popstate",syncSimulatedTitleBar),window.addEventListener("hashchange",syncSimulatedTitleBar),document.readyState==="loading"&&document.addEventListener("DOMContentLoaded",syncSimulatedTitleBar,{once:!0});try{let pushState=history.pushState.bind(history),replaceState=history.replaceState.bind(history);history.pushState=function(...args){pushState(...args),syncSimulatedTitleBar()},history.replaceState=function(...args){replaceState(...args),syncSimulatedTitleBar()}}catch{}};if(!isTop){observeState(),syncSimulatedTitleBar();return}let mount=()=>{if(titleBarRoot||!document.body)return;let totalHeight=config2.statusBarHeight+titleBar.navigationBarHeight,navigationView=createNavigationBarView("root",host.requestNativeBack),statusView=createStatusBarView(),spacer=document.createElement("div");if(spacer.setAttribute("data-mearl-app-titlebar-spacer",""),spacer.style.cssText=`display:block;width:100%;height:${totalHeight}px;min-height:${totalHeight}px;flex:none;`,document.body.insertBefore(spacer,document.body.firstChild),document.body.append(navigationView.root,statusView.root),safeAreaInsets.bottom>0){let bottomRoot=document.createElement("div");bottomRoot.setAttribute("data-mearl-app-system-bottom",config2.profile),bottomRoot.style.cssText=`position:fixed;left:0;right:0;bottom:0;height:${safeAreaInsets.bottom}px;z-index:2147483600;box-sizing:border-box;pointer-events:none;color:#111111;`;let bottomShadow=bottomRoot.attachShadow({mode:"open"});bottomShadow.innerHTML=`<style>:host{all:initial}#surface{appearance:none;border:0;padding:0;width:166px;max-width:100%;height:24px;position:absolute;left:50%;bottom:0;transform:translateX(-50%);display:block;box-sizing:border-box;pointer-events:auto;color:#111;background:transparent;cursor:pointer;-webkit-tap-highlight-color:transparent}#surface:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}#indicator{position:absolute;left:50%;bottom:8px;transform:translateX(-50%);width:134px;height:5px;border-radius:999px;background:currentColor;opacity:.92;transition:transform 120ms ease,opacity 120ms ease}#surface:hover #indicator{opacity:1;transform:translateX(-50%) scaleX(1.05)}#surface[data-platform="android"] #indicator{bottom:6px;width:108px;height:4px;opacity:.82}</style><button id="surface" type="button" aria-label="打开桥模拟配置" title="桥模拟配置" data-platform="${config2.platform.toLowerCase()}"><span id="indicator" aria-hidden="true"></span></button>`,document.body.appendChild(bottomRoot),systemBottomRoot=bottomRoot,systemBottomSurface=bottomShadow.getElementById("surface"),systemBottomSurface?.addEventListener("click",()=>{window.postMessage({source:SRC,type:"showBridgeConfig",profile:config2.profile,actions:config2.actions},"*")})}rootTitleBarView=navigationView,systemStatusView=statusView,titleBarRoot=navigationView.root,titleBarSpacer=spacer,syncSimulatedTitleBar(),observeState()};document.body?mount():document.addEventListener("DOMContentLoaded",mount,{once:!0})},service={initialLayerTitleBarState,resolvedTitleBarState,parseReportedTitleBarState,setPresentedRootTitleBarState:state=>{presentedRootTitleBarState=state,syncSimulatedTitleBar()},markStateExplicit:()=>{titleBarStateExplicit=!0},applyNavigationBarState,applyStatusBarState,createNavigationBarView,destroyNavigationBarView:view=>view?.root.remove(),syncLayerViewport,syncActiveSystemBars,syncSimulatedTitleBar};return install(),service}function installAppProfilePageTransport(config2,environment){let{SRC,TAG,log:log3}=environment,appToast=null,appToastHideTimer=null,appToastRemoveTimer=null;function showAppToast(params){let p=params&&typeof params=="object"?params:{},messageValue=[p.message,p.msg,p.content,p.text].find(value=>typeof value=="string"&&value.trim().length>0);if(typeof messageValue!="string")return"missing message";let durationValue=Number(p.milliseconds??p.duration),duration3=Number.isFinite(durationValue)&&durationValue>0?durationValue:2e3,hideAfter=Math.min(6e4,Math.max(300,Math.round(duration3)));appToastHideTimer!==null&&window.clearTimeout(appToastHideTimer),appToastRemoveTimer!==null&&window.clearTimeout(appToastRemoveTimer);let toast=appToast?.isConnected===!0?appToast:document.createElement("div");return toast!==appToast&&(appToast=toast,toast.setAttribute("data-mearl-app-toast",""),toast.setAttribute("role","status"),toast.setAttribute("aria-live","polite"),Object.assign(toast.style,{position:"fixed",left:"50%",top:"50%",zIndex:"2147483647",maxWidth:"calc(100vw - 64px)",boxSizing:"border-box",padding:"14px 20px",borderRadius:"12px",background:"rgba(20, 20, 20, 0.88)",color:"#ffffff",fontFamily:'-apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif',fontSize:"16px",fontWeight:"400",lineHeight:"24px",textAlign:"center",whiteSpace:"pre-wrap",overflowWrap:"anywhere",pointerEvents:"none",opacity:"0",transform:"translate(-50%, -50%) scale(0.96)",transition:"opacity 180ms ease, transform 180ms ease"}),(document.body??document.documentElement).appendChild(toast)),toast.textContent=messageValue,toast.style.opacity="0",toast.style.transform="translate(-50%, -50%) scale(0.96)",toast.offsetWidth,toast.style.opacity="1",toast.style.transform="translate(-50%, -50%) scale(1)",appToastHideTimer=window.setTimeout(()=>{appToastHideTimer=null,toast.style.opacity="0",toast.style.transform="translate(-50%, -50%) scale(0.96)",appToastRemoveTimer=window.setTimeout(()=>{appToastRemoveTimer=null,appToast===toast&&(appToast=null),toast.remove()},180)},hideAfter),null}let bridgeRequestSeq=0,pendingMtop={},pendingMtopStreams={},pendingUserInfo={};function callMtop(params,succ,fail){let id=++bridgeRequestSeq;pendingMtop[id]={succ,fail};let post=params.post,rawTimeout=params.timeout??params.timer,timeout=typeof rawTimeout=="number"?rawTimeout:typeof rawTimeout=="string"&&rawTimeout.trim()!==""?Number(rawTimeout):void 0,payload={...params,data:params.data!==void 0?params.data:params.param??{},method:params.method??(post===!0||post===1||post==="1"||post==="true"?"POST":"GET"),env:params.env??(/(^|\.)wapa\.taobao\.com$/i.test(location.hostname)?"pre":"online"),...Number.isFinite(timeout)&&{timeout}};window.postMessage({source:SRC,type:"mtop",requestId:id,payload},"*"),log3("mtop 代发 →",params.api)}function callMtopAsync(params){return new Promise((resolve3,reject)=>callMtop(params,resolve3,reject))}function callMtopStream(params,succ,fail){let sessionId=typeof params.id=="string"?params.id:String(params.id??""),request=params.request&&typeof params.request=="object"?params.request:null;if(!sessionId||!request||typeof request.api!="string"){fail?.("invalid mtop_stream params");return}let requestId=++bridgeRequestSeq;pendingMtopStreams[requestId]={sessionId},window.postMessage({source:SRC,type:"mtopStream",requestId,payload:{...request,timeout:params.timeout,method:params.method??request.method,env:/(^|\.)wapa\.taobao\.com$/i.test(location.hostname)?"pre":"online"}},"*"),succ?.({}),log3("mtop 流式代发 →",request.api)}function callUserInfo(fallback,succ){if(fallback.userId){succ?.(fallback);return}let requestId=++bridgeRequestSeq,timer=setTimeout(()=>{let pending=pendingUserInfo[requestId];pending&&(delete pendingUserInfo[requestId],pending.succ?.(pending.fallback))},1e3);pendingUserInfo[requestId]={fallback,succ,timer},window.postMessage({source:SRC,type:"userInfo",requestId},"*")}function emitMtopStreamEvent(sessionId,eventType,data){let detail=data&&typeof data=="object"?{...data,eventType}:{data,eventType};document.dispatchEvent(new CustomEvent(`mtop_stream${sessionId}`,{detail}))}function createUploadId(){try{if(typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch{}return`${Date.now()}-${Math.random().toString(36).slice(2)}`}function pickDirectUploadTarget(response){if(!response||typeof response!="object")return null;let data=response.data;if(data?.success===!1)return null;let result=data?.result,target=Array.isArray(result?.urls)?result.urls[0]:void 0;if(!target||typeof target!="object")return null;let item=target;if(typeof item.put!="string"||!item.put||typeof item.get!="string"||!item.get)return null;let rawHeaders=item.putHeaders&&typeof item.putHeaders=="object"?item.putHeaders:{},putHeaders=Object.fromEntries(Object.entries(rawHeaders).map(([key,value])=>[key,String(value)]));return{put:item.put,get:item.get,putHeaders}}async function uploadImage(file2){let uploader=config2.imagePicker;if(!uploader)throw new Error("图片上传能力未配置");let env=/(^|\.)wapa\.taobao\.com$/i.test(location.hostname)?"pre":"online",response=await callMtopAsync({api:uploader.api,v:uploader.version,method:"POST",env,timeout:6e4,data:{fcId:uploader.fcId,fcGroup:uploader.fcGroup,fcName:uploader.uploadUrlFunction,fcData:JSON.stringify({requestType:"url",mimes:[file2.type||"image/jpeg"],prefix:uploader.prefix,region:uploader.region,uploadNumber:1}),fcConfig:JSON.stringify({timeout:6e4,disasterRecover:!0})}}),target=pickDirectUploadTarget(response);if(!target)throw new Error("获取图片上传地址失败");let uploadUrl=`${target.put}${target.put.includes("?")?"&":"?"}getAvatar=1`,uploadResponse=await fetch(uploadUrl,{method:"PUT",headers:target.putHeaders,body:file2});if(uploadResponse.status!==200)throw new Error(`图片直传失败: HTTP ${uploadResponse.status}`);return target.get}function openImagePicker(callbackCommandFn){let input=document.createElement("input");input.type="file",input.accept="image/*",input.style.display="none";let settled=!1,finish=()=>{settled=!0,input.remove()};input.addEventListener("cancel",finish,{once:!0}),input.addEventListener("change",()=>{let file2=input.files?.[0];if(!file2){finish();return}if(!file2.type.startsWith("image/")){finish(),console.error(TAG,"仅支持选择图片文件");return}uploadImage(file2).then(pic=>{typeof callbackCommandFn=="function"&&callbackCommandFn({pic,uuid:createUploadId(),timeStamp:Date.now()}),log3("图片选择并上传完成:",pic)}).catch(error48=>console.error(TAG,"图片上传失败:",error48)).finally(finish)},{once:!0}),(document.body??document.documentElement).appendChild(input),input.click(),window.addEventListener("focus",()=>{setTimeout(()=>{!settled&&!input.files?.length&&finish()},1e3)},{once:!0})}function showPaymentDialog(api,params,succeed,failed){let overlay=document.createElement("div");overlay.setAttribute("data-mearl-payment-dialog","true"),Object.assign(overlay.style,{position:"fixed",inset:"0",zIndex:"2147483647",display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)"});let card=document.createElement("div");Object.assign(card.style,{background:"#fff",borderRadius:"12px",padding:"24px",width:"300px",textAlign:"center",fontFamily:"system-ui, sans-serif"});let title=document.createElement("div");Object.assign(title.style,{fontSize:"17px",fontWeight:"600",marginBottom:"8px"}),title.textContent="支付确认";let desc=document.createElement("div");Object.assign(desc.style,{fontSize:"14px",color:"#666",marginBottom:"20px"}),desc.textContent=`模拟 ${api} 支付,请选择操作`;let btnRow=document.createElement("div");Object.assign(btnRow.style,{display:"flex",gap:"12px"});let btnBase=(text,bg,color,action)=>{let btn=document.createElement("button");return btn.textContent=text,btn.setAttribute("data-mearl-action",action),Object.assign(btn.style,{flex:"1",padding:"10px 0",border:"none",borderRadius:"8px",fontSize:"15px",fontWeight:"500",cursor:"pointer",background:bg,color}),btn},confirmBtn=btnBase("完成支付","#1677ff","#fff","payment-confirm"),cancelBtn=btnBase("取消支付","#f5f5f5","#333","payment-cancel"),cleanup=()=>{overlay.remove()};confirmBtn.addEventListener("click",()=>{cleanup(),log3("用户完成支付",api),succeed({ResultStatus:"9000",resultStatus:"9000"})}),cancelBtn.addEventListener("click",()=>{cleanup(),log3("用户取消支付",api),failed({ResultStatus:"6001",resultStatus:"6001"})}),btnRow.appendChild(cancelBtn),btnRow.appendChild(confirmBtn),card.appendChild(title),card.appendChild(desc),card.appendChild(btnRow),overlay.appendChild(card),(document.body??document.documentElement).appendChild(overlay)}function handleMessage(msg){if(msg.source==="mearl-content"&&msg.type==="APP_BRIDGE_MTOP_RESPONSE"){let pending=pendingMtop[msg.requestId];if(!pending)return!0;delete pendingMtop[msg.requestId];let result=msg.result;return result?.success?pending.succ?.(result.response):pending.fail?.(result?.error??"mtop delegate failed"),!0}if(msg.source==="mearl-content"&&msg.type==="APP_BRIDGE_USER_INFO_RESPONSE"){let requestId=msg.requestId,pending=pendingUserInfo[requestId];if(!pending)return!0;delete pendingUserInfo[requestId],clearTimeout(pending.timer);let result=msg.result,response=result?.success&&result.response&&typeof result.response=="object"?result.response:{};return pending.succ?.({...pending.fallback,...response}),!0}if(msg.source==="mearl-content"&&msg.type==="APP_BRIDGE_MTOP_STREAM_EVENT"){let requestId=msg.requestId,pending=pendingMtopStreams[requestId];if(!pending)return!0;let eventType=msg.eventType;return emitMtopStreamEvent(pending.sessionId,eventType,msg.data),(eventType==="onFinish"||eventType==="onError")&&delete pendingMtopStreams[requestId],!0}return!1}return{showAppToast,callMtop,callMtopStream,callUserInfo,openImagePicker,showPaymentDialog,handleMessage}}function installAppProfileBridgeProtocol(config2,environment,host){let{w,SRC,TAG,isTop,log:log3}=environment,{pageTransport,systemBars,requestOpen,requestClose,requestCloseAll,requestContainerData}=host,{showAppToast,callMtop,callMtopStream,callUserInfo,openImagePicker,showPaymentDialog}=pageTransport,{applyNavigationBarState,applyStatusBarState,syncSimulatedTitleBar}=systemBars,NOT_IMPLEMENTED_PAYLOAD=JSON.stringify({ret:["HY_FAILED"],msg:"not implemented"}),FPT_STORAGE_KEY=`__mearl_app_fpt__:${config2.profile}`,CALENDAR_STORAGE_KEY=`__mearl_app_calendar_events__:${config2.profile}`,unsupportedNativeInputNotified=!1,stopNetworkQualityMonitor=null,simulatedPageHidden=!1,simulatedVisibilityInstalled=!1,notificationListeners=new Map,megaListenerSeq=0,megaBroadcastListeners=new Map,megaLifeCycleListeners=new Set,megaPageCloseListeners=new Set,megaSystemBackListener=null,megaKVMutationVersion=0,MEGA_KV_TOTAL_SIZE=5*1024*1024,MEGA_KV_STORAGE_KEY=`__mearl_mega_kv__:${config2.profile}`;function readMegaKVStorage(){let storage=new Map;try{let parsed=JSON.parse(localStorage.getItem(MEGA_KV_STORAGE_KEY)??"{}");if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return storage;for(let[bizId,rawEntries]of Object.entries(parsed)){if(!rawEntries||typeof rawEntries!="object"||Array.isArray(rawEntries))continue;let entries=new Map;for(let[key,value]of Object.entries(rawEntries))typeof value=="string"&&entries.set(key,value);storage.set(bizId,entries)}}catch{}return storage}let megaKVStorage=readMegaKVStorage();function megaKVSnapshot(){let snapshot={};for(let[bizId,values]of megaKVStorage)snapshot[bizId]=Object.fromEntries(values);return snapshot}function persistMegaKVStorage(){try{localStorage.setItem(MEGA_KV_STORAGE_KEY,JSON.stringify(megaKVSnapshot()))}catch{}}function replaceMegaKVStorage(value){if(!(!value||typeof value!="object"||Array.isArray(value))){megaKVStorage.clear();for(let[bizId,rawEntries]of Object.entries(value)){if(!rawEntries||typeof rawEntries!="object"||Array.isArray(rawEntries))continue;let entries=new Map;for(let[key,entryValue]of Object.entries(rawEntries))typeof entryValue=="string"&&entries.set(key,entryValue);megaKVStorage.set(bizId,entries)}persistMegaKVStorage()}}function applyMegaKVMutation(payload){let operation=typeof payload.operation=="string"?payload.operation:"",bizId=typeof payload.bizId=="string"?payload.bizId:"",key=typeof payload.key=="string"?payload.key:"";if(bizId){if(operation==="set"&&key&&typeof payload.value=="string"){let entries=megaKVStorage.get(bizId)??new Map;entries.set(key,payload.value),megaKVStorage.set(bizId,entries)}else if(operation==="remove"&&key){let entries=megaKVStorage.get(bizId);entries?.delete(key),entries?.size===0&&megaKVStorage.delete(bizId)}else if(operation==="clear")megaKVStorage.delete(bizId);else return;megaKVMutationVersion+=1,persistMegaKVStorage()}}function emitMegaCallback(callback,value){callback&&setTimeout(()=>callback(value),0)}function megaBroadcastBizId(value){return typeof value=="string"&&value?value:"__MEGA_GLOBAL_MESSAGE__"}function dispatchMegaBroadcast(payload){let bizId=megaBroadcastBizId(payload.bizId),eventName=typeof payload.eventName=="string"?payload.eventName:"";if(eventName)for(let listener of Array.from(megaBroadcastListeners.values()))listener.bizId!==bizId||listener.eventName!==eventName||(listener.once&&megaBroadcastListeners.delete(listener.id),emitMegaCallback(listener.callback,{statusCode:1,type:"onEvent",data:{detail:payload.detail}}),listener.once&&emitMegaCallback(listener.callback,{statusCode:99,type:"finish"}))}let documentPrototype=typeof Document=="function"?Document.prototype:null,nativeHiddenDescriptor=documentPrototype?Object.getOwnPropertyDescriptor(documentPrototype,"hidden"):void 0,nativeVisibilityDescriptor=documentPrototype?Object.getOwnPropertyDescriptor(documentPrototype,"visibilityState"):void 0;function installSimulatedVisibilityState(){if(!simulatedVisibilityInstalled){simulatedVisibilityInstalled=!0;try{Object.defineProperty(document,"hidden",{configurable:!0,get:()=>simulatedPageHidden||!!(nativeHiddenDescriptor?.get?.call(document)??!1)}),Object.defineProperty(document,"visibilityState",{configurable:!0,get:()=>simulatedPageHidden?"hidden":nativeVisibilityDescriptor?.get?.call(document)??"visible"})}catch{}}}function dispatchPageTransitionEvent(type){try{let event=typeof PageTransitionEvent=="function"?new PageTransitionEvent(type,{persisted:!1}):new Event(type);window.dispatchEvent(event)}catch{}}function dispatchActiveEvents(){for(let name of config2.activeEvents)try{document.dispatchEvent(new Event(name))}catch{}}function handlePageVisibility(hidden){if(hidden===simulatedPageHidden)return;installSimulatedVisibilityState(),simulatedPageHidden=hidden;let lifeCycleType=hidden?"onPageDisappear":"onPageAppear";for(let callback of megaLifeCycleListeners)emitMegaCallback(callback,{statusCode:1,type:lifeCycleType,data:{pageId:location.href}});try{document.dispatchEvent(new Event("visibilitychange"))}catch{}if(hidden){try{window.dispatchEvent(new Event("blur"))}catch{}dispatchPageTransitionEvent("pagehide");return}dispatchPageTransitionEvent("pageshow");try{window.dispatchEvent(new Event("focus"))}catch{}dispatchActiveEvents()}function resolveWindowFunction(path23){let parts=path23.split(".").filter(Boolean),owner=w;for(let index=0;index<parts.length-1;index+=1){let next=owner[parts[index]];if(!next||typeof next!="object")return null;owner=next}let fn=owner[parts[parts.length-1]];return typeof fn=="function"?fn.bind(owner):null}function handleNativeBack(){let megaHandled=!1;for(let callback of megaPageCloseListeners)megaHandled=!0,emitMegaCallback(callback,{statusCode:1,type:"onClose",data:{}});if(megaSystemBackListener&&(megaHandled=!0,emitMegaCallback(megaSystemBackListener,{statusCode:1,type:"onSuccess",data:{}})),megaHandled)return!0;let nativeBack=config2.nativeBack;if(!nativeBack)return!1;if(nativeBack.handler){let handler=resolveWindowFunction(nativeBack.handler);if(!handler)return!1;try{return handler(),!0}catch{return!1}}let controlled=!1;if(nativeBack.controlFunction){let control=resolveWindowFunction(nativeBack.controlFunction);if(!control)return!1;try{controlled=control()===!0}catch{return!1}if(!controlled)return!1}if(!nativeBack.event)return controlled;try{let event=new Event(nativeBack.event,{cancelable:!0});return document.dispatchEvent(event),controlled||event.defaultPrevented}catch{return controlled}}function handleAppMessage(message){if(!message||typeof message!="object")return;let payload=message;if(payload.kind==="megaBroadcast"){dispatchMegaBroadcast(payload);return}if(payload.kind==="megaKVStorage"){applyMegaKVMutation(payload);return}if(payload.kind==="legacyBroadcast"&&typeof payload.instanceId=="string"){try{let event=new CustomEvent(`Broadcast.Message.${payload.instanceId}`,{detail:payload.message});Object.defineProperty(event,"param",{configurable:!0,value:payload.message}),document.dispatchEvent(event)}catch{}return}if(payload.kind==="notification"&&typeof payload.name=="string"){let listener=notificationListeners.get(payload.name);listener&&setTimeout(()=>listener(payload.data),0);return}if(!(payload.kind!=="message"||!config2.messageEvent))try{document.dispatchEvent(new CustomEvent(config2.messageEvent,{detail:{data:payload.data}}))}catch{}}function sendAppMessage(message){if(isTop){handleAppMessage(message);return}window.top?.postMessage({source:SRC,type:"appMessageToOpener",message},"*")}function applyRuntimeResponses(responses){let current=config2.actions.responses??{};for(let[api,response]of Object.entries(responses))!response||typeof response!="object"||Array.isArray(response)||(current[api]=response);config2.actions.responses=current}function parseFpt(value){let entries=[],normalized=value.trim();if(!normalized)return entries;let pattern=/([0-9A-Za-z._-]+)\(([0-9A-Za-z._-]+)\)/g,consumed="";for(let match of normalized.matchAll(pattern))consumed+=match[0],entries.push([match[1],match[2]]);return consumed===normalized?entries:[]}function setFptEntry(entries,key,value){entries.delete(key),entries.set(key,value)}function readInitialFptEntries(){let entries=new Map;try{for(let[key,value]of parseFpt(sessionStorage.getItem(FPT_STORAGE_KEY)??""))setFptEntry(entries,key,value)}catch{}try{let currentFpt=new URL(location.href).searchParams.get("fpt")??"";for(let[key,value]of parseFpt(currentFpt))setFptEntry(entries,key,value)}catch{}return entries}let fptEntries=readInitialFptEntries();function serializeFpt(entries){return Array.from(entries,([key,value])=>`${key}(${value})`).join("")}function persistFpt(){try{let value=serializeFpt(fptEntries);value?sessionStorage.setItem(FPT_STORAGE_KEY,value):sessionStorage.removeItem(FPT_STORAGE_KEY)}catch{}}function decorateUrlWithFpt(rawUrl){if(fptEntries.size===0)return rawUrl;try{let url2=new URL(rawUrl,location.href);if(url2.protocol!=="http:"&&url2.protocol!=="https:")return rawUrl;let merged=new Map(fptEntries);for(let[key,value]of parseFpt(url2.searchParams.get("fpt")??""))setFptEntry(merged,key,value);return url2.searchParams.set("fpt",serializeFpt(merged)),url2.href}catch{return rawUrl}}function classify(api){let a=config2.actions;return a.open.includes(api)?"open":a.close.includes(api)?"close":a.title.includes(api)?"title":a.navigationBar?.includes(api)?"navigationBar":a.statusBar?.includes(api)?"statusBar":a.systemInfo.includes(api)?"systemInfo":a.mtop.includes(api)?"mtop":a.kvGet?.includes(api)?"kvGet":a.kvSet?.includes(api)?"kvSet":a.kvDelete?.includes(api)?"kvDelete":a.pageContext?.includes(api)?"pageContext":a.responses&&Object.prototype.hasOwnProperty.call(a.responses,api)?"response":a.behaviors&&Object.prototype.hasOwnProperty.call(a.behaviors,api)?a.behaviors[api]:a.noop.includes(api)?"noop":"unknown"}function pickUrl(params){if(!params||typeof params!="object")return null;let p=params,candidates=[p.url,p.data?.url,p.param?.url,p.value?.params?.url];for(let c of candidates)if(typeof c=="string"&&c)return c;return null}function pickCloseData(params){if(params&&typeof params=="object"){let p=params;if("data"in p&&p.data!==void 0)return p.data;if(Object.keys(p).length>0)return p}}function decodeCookieValue(raw){let value=raw;for(let i=0;i<2;i+=1)try{let decoded=decodeURIComponent(value);if(decoded===value)break;value=decoded}catch{break}return value.replace(/\\u([0-9a-f]{4})/gi,(_match,hex3)=>String.fromCharCode(Number.parseInt(hex3,16)))}function readCookie(name){let prefix=`${name}=`,pair=document.cookie.split(";").map(value=>value.trim()).find(value=>value.startsWith(prefix));return pair?decodeCookieValue(pair.slice(prefix.length)):""}function readUserCookie(name){let pageUserCookie=w.userCookie;if(!pageUserCookie||typeof pageUserCookie!="object")return"";let value=pageUserCookie[name];return typeof value=="string"?decodeCookieValue(value):""}function readFirstUserCookie(names){for(let name of names){let value=readCookie(name)||readUserCookie(name);if(value&&value!=="null")return value}return""}let cbSeq=0,callbacks={};function stashCallback(fn){if(typeof fn!="function")return 0;let id=++cbSeq;return callbacks[id]=fn,id}function extractQuery(url2,param){let q=url2.indexOf("?");if(q===-1)return null;for(let pair of url2.slice(q+1).split("&")){let eq=pair.indexOf("=");if(eq>0&&pair.slice(0,eq)===param)return pair.slice(eq+1)}return null}function resolveSchemeValue(raw,depth){if(depth>3)return null;let value=raw;try{value=decodeURIComponent(raw)}catch{}if(value.startsWith("{"))try{let found=pickUrl(JSON.parse(value));if(!found)return null;value=found}catch{return null}if(/^https?:/i.test(value))return value;if(/^[a-z][a-z0-9+.-]*:/i.test(value))return mapScheme(value,depth+1);let nestedUrl=extractQuery(value,"url");return nestedUrl?resolveSchemeValue(nestedUrl,depth+1):null}function mapScheme(url2,depth=0){if(depth>3)return null;let lower=url2.toLowerCase();for(let rule of config2.schemes){if(!lower.startsWith(rule.match))continue;if(rule.targetPath){let suffix=url2.slice(rule.match.length);if(suffix&&!suffix.startsWith("?")&&!suffix.startsWith("#"))continue;try{let source=new URL(url2),origin=location.origin;if(rule.targetHostPrefix){let hostname3=location.hostname.toLowerCase(),domainSuffix=hostname3==="wapa.taobao.com"||hostname3.endsWith(".wapa.taobao.com")?"wapa.taobao.com":hostname3==="m.taobao.com"||hostname3.endsWith(".m.taobao.com")?"m.taobao.com":"";domainSuffix&&(origin=`https://${rule.targetHostPrefix}.${domainSuffix}`)}let target=new URL(rule.targetPath,`${origin}/`);target.search=source.search,target.hash=source.hash;for(let[key,value]of Object.entries(rule.targetParams??{}))target.searchParams.has(key)||target.searchParams.set(key,value);return target.href}catch{return null}}if(!rule.param)continue;let raw=extractQuery(url2,rule.param);return raw?resolveSchemeValue(raw,depth):null}return null}function matchesImagePickerScheme(url2){let lower=url2.toLowerCase();return config2.imagePicker?.schemes.some(scheme=>lower.startsWith(scheme))===!0}function handleMaybeScheme(url2){if(typeof url2!="string"||!url2||!/^[a-z][a-z0-9+.-]*:/i.test(url2)||/^(https?|about|blob|data|javascript):/i.test(url2))return!1;let mapped=mapScheme(url2);return mapped?(log3("scheme 映射为 H5 open:",url2,"→",mapped),requestOpen(decorateUrlWithFpt(mapped),0,!1)):log3("外部 scheme 已拦截(真机表现为唤端):",url2),!0}function handleResume(msg){let{data,storageId,callbackId,final,gotoEvent}=msg;if(gotoEvent&&dispatchGotoEvent(data),callbackId&&callbacks[callbackId]){try{callbacks[callbackId]({backdata:data})}catch(e){console.error(TAG,"callbackCommand 执行失败",e)}final&&delete callbacks[callbackId]}if(data&&typeof data=="object"&&storageId)try{let d={...data};d.__$data=!0,d.__$storageId=String(storageId),localStorage.setItem("XPI_BACK_LISTENER_DATA_STORAGE",JSON.stringify(d))}catch{}simulatedPageHidden?handlePageVisibility(!1):dispatchActiveEvents()}function dispatchGotoEvent(data){if(data!==void 0)try{document.dispatchEvent(new CustomEvent("WV.GotoEvent",{detail:{data}}))}catch{}}function sendUserTrack(params){if(!params||typeof params!="object")return;let p=params,logkey=typeof p.logkey=="string"?p.logkey:"",gmkey=typeof p.gmkey=="string"?p.gmkey:typeof p.event=="string"?p.event:"",gokey=typeof p.gokey=="string"?p.gokey:"";if(!/^\/[0-9A-Za-z._/-]+$/.test(logkey)||!/^[0-9A-Za-z_-]+$/.test(gmkey))return;let pageWindow=w,aplus=pageWindow.goldlog??pageWindow.aplus;if(typeof aplus?.send!="function")return;let configuredHost=aplus.getMetaInfo?.("aplus-rhost-g"),host2=(typeof configuredHost=="string"?configuredHost:"gm.mmstat.com").replace(/^https?:\/\//i,"").replace(/^\/\//,"").split("/")[0];if(!(!host2||!/^[0-9A-Za-z.-]+$/.test(host2)))try{aplus.send(`//${host2}${logkey}`,`gmkey=${encodeURIComponent(gmkey)}&gokey=${gokey}&ts=${Date.now()}`,"GET")}catch{}}function readNetworkState(){let connection=navigator.connection;return navigator.onLine?connection?.type==="wifi"?"wifi":connection?.effectiveType??"unknown":"fail"}function networkTypeNumber(state){return{wifi:2,"slow-2g":3,"2g":3,"3g":4,"4g":5,"5g":6,fail:7}[state]??0}function calendarTimestamp(value){if(typeof value=="number"&&Number.isFinite(value))return value;if(typeof value!="string"||!value.trim())return null;let numeric=Number(value);if(Number.isFinite(numeric)&&numeric>0)return numeric;let parsed=Date.parse(value);return Number.isFinite(parsed)?parsed:null}function calendarEventFromParams(params){let p=params&&typeof params=="object"?params:{},stringValue=(...values)=>values.find(value=>typeof value=="string")??"";return{title:stringValue(p.calendar_title,p.title),startTime:calendarTimestamp(p.calendar_start_ms??p.start_time??p.calendar_start_datetime),endTime:calendarTimestamp(p.calendar_end_ms??p.end_time??p.calendar_end_datetime),url:stringValue(p.calendar_url,p.url),note:stringValue(p.calendar_note,p.note),location:stringValue(p.calendar_location,p.location)}}function readCalendarEvents(){try{let parsed=JSON.parse(localStorage.getItem(CALENDAR_STORAGE_KEY)??"[]");return Array.isArray(parsed)?parsed.filter(event=>event!==null&&typeof event=="object"&&typeof event.title=="string"):[]}catch{return[]}}function writeCalendarEvents(events){try{return localStorage.setItem(CALENDAR_STORAGE_KEY,JSON.stringify(events)),!0}catch{return!1}}function sameCalendarEvent(stored,candidate){return candidate.url?stored.url===candidate.url:!!candidate.title&&stored.title===candidate.title&&(candidate.startTime===null||stored.startTime===candidate.startTime)&&(candidate.endTime===null||stored.endTime===candidate.endTime)}function calendarEventResponse(event){return{title:event.title,start_time:event.startTime,end_time:event.endTime,url:event.url,note:event.note,location:event.location}}function dispatch(api,params,onSuccess,onFailure,callbackCommandFn){let succeed=value=>{onSuccess&&setTimeout(()=>onSuccess(value),0)},failed=reason=>{onFailure&&setTimeout(()=>onFailure(reason),0)},kind=classify(api),silent=config2.actions.silent?.includes(api)===!0;if(silent||log3("桥调用",api,`(${kind})`,params??""),kind==="open"||kind==="navigate"){let p=params&&typeof params=="object"?params:{},navigationData=p.data&&typeof p.data=="object"?p.data:void 0;if(kind==="navigate"&&navigationData?.type==="back"){isTop?requestCloseAll(navigationData.data,!0)||dispatchGotoEvent(navigationData.data):window.top?.postMessage({source:SRC,type:"closeAll",data:navigationData.data,gotoEvent:!0},"*"),succeed({});return}let url2=pickUrl(params);if(!url2){failed("missing url");return}if(matchesImagePickerScheme(url2)){openImagePicker(callbackCommandFn),succeed({});return}let wd=p.useWebdialog===!0||p.useWebdialog==="true"||p.useWebdialog===1||p.useWebdialog==="1";requestOpen(decorateUrlWithFpt(url2),stashCallback(callbackCommandFn),wd,p),succeed({});return}if(kind==="closeAll"){isTop?requestCloseAll(void 0):window.top?.postMessage({source:SRC,type:"closeAll"},"*"),succeed({});return}if(kind==="closeBackData"){let p=params&&typeof params=="object"?params:{};requestClose(Object.prototype.hasOwnProperty.call(p,"backdata")?p.backdata:pickCloseData(p)),succeed({});return}if(kind==="close"){requestClose(pickCloseData(params)),succeed({});return}if(kind==="postMessage"){let p=params&&typeof params=="object"?params:{};sendAppMessage({kind:"message",data:p.data??p}),succeed({});return}if(kind==="notifySubscribe"){let p=params&&typeof params=="object"?params:{};if(typeof p.name!="string"||!p.name){failed("missing notification name");return}onSuccess&¬ificationListeners.set(p.name,onSuccess);return}if(kind==="notifyUnsubscribe"){let p=params&&typeof params=="object"?params:{};typeof p.name=="string"&¬ificationListeners.delete(p.name),succeed({});return}if(kind==="notifyPost"){let p=params&&typeof params=="object"?params:{};if(typeof p.name!="string"||!p.name){failed("missing notification name");return}sendAppMessage({kind:"notification",name:p.name,data:p.data}),succeed({});return}if(kind==="sharedFileRead"||kind==="sharedFileWrite"||kind==="sharedDataGet"||kind==="sharedDataSet"){requestContainerData(kind,params&&typeof params=="object"?params:{},succeed,failed);return}if(kind==="legacyBroadcastCreate"||kind==="legacyBroadcastPost"||kind==="legacyBroadcastClose"){requestContainerData(kind,params&&typeof params=="object"?params:{},succeed,failed);return}if(kind==="title"){let title=params&&typeof params=="object"?params.title??params.name:void 0;if(typeof title=="string"&&title){systemBars.markStateExplicit();try{document.title=title,syncSimulatedTitleBar()}catch{}isTop||window.top?.postMessage({source:SRC,type:"title",title},"*")}succeed({});return}if(kind==="navigationBar"){applyNavigationBarState(api,params),succeed({});return}if(kind==="statusBar"){applyStatusBarState(params),succeed({});return}if(kind==="systemInfo"){let model=config2.globals.__DEVICE_MODEL__||"iPhone";succeed({language:config2.language,model,systemVersion:config2.systemVersion,statusBarHeight:config2.statusBarHeight,platform:config2.platform,brand:config2.platform==="iOS"?"Apple":"Android",client_version:config2.globals.__APP_VERSION__??"",client_type:config2.clientType});return}if(kind==="mtop"){callMtop(params??{},onSuccess,onFailure);return}if(kind==="mtopStream"){callMtopStream(params??{},succeed,failed);return}if(kind==="kvGet"||kind==="kvSet"||kind==="kvDelete"){let p=params&&typeof params=="object"?params:{},key=typeof p.key=="string"?p.key:"";if(!key){failed("missing key");return}try{let storageKey=`__mearl_app_kv__:${key}`;if(kind==="kvGet"){let stored=localStorage.getItem(storageKey);stored!==null?succeed(stored):failed(JSON.stringify({ret:["HY_FAILED"],msg:"key not found"}))}else if(kind==="kvSet"){let value=typeof p.value=="string"?p.value:p.value===void 0?"":JSON.stringify(p.value);localStorage.setItem(storageKey,value),succeed({})}else localStorage.removeItem(storageKey),succeed({})}catch{failed(JSON.stringify({ret:["HY_FAILED"],msg:"kv storage unavailable"}))}return}if(kind==="pageContext"){succeed({pageContext:void 0});return}if(kind==="memoryGet"||kind==="memorySet"||kind==="memoryDelete"){let p=params&&typeof params=="object"?params:{},key=typeof p.key=="string"?p.key:"";if(!key){failed({error_message:"missing key"});return}try{let storageKey=`__mearl_app_memory__:${key}`;if(kind==="memoryGet"){let value=sessionStorage.getItem(storageKey);succeed(value===null?{}:{value})}else if(kind==="memorySet"){let value=typeof p.value=="string"?p.value:p.value===void 0?"":JSON.stringify(p.value);sessionStorage.setItem(storageKey,value),succeed({key,success:!0})}else sessionStorage.removeItem(storageKey),succeed({key,success:!0})}catch{failed({error_message:"memory cache unavailable"})}return}if(kind==="availabilityMap"){let p=params&&typeof params=="object"?params:{},channels=Array.isArray(p.data)?p.data.filter(value=>typeof value=="string"):[];succeed({res:"success",data:Object.fromEntries(channels.map(channel=>[channel,!1]))});return}if(kind==="userInfo"){let userId=readFirstUserCookie(["unb"]),userName=readFirstUserCookie(["_w_tb_nick","_nk_","snk","tracknick"]);callUserInfo({...userId&&{userId},...userName&&{userName}},succeed);return}if(kind==="networkInfo"){let state=readNetworkState();if(api==="WVNetwork.getNetworkType"){succeed({type:{wifi:"WIFI","slow-2g":"2G","2g":"2G","3g":"3G","4g":"4G"}[state]??"UNKNOWN"});return}if(config2.profile==="alipay"||config2.profile==="koubei"){succeed({networkAvailable:state!=="fail",networkType:{wifi:"WIFI","slow-2g":"2G","2g":"2G","3g":"3G","4g":"4G",fail:"NOTREACHABLE"}[state]??"UNKNOWN"});return}let type=networkTypeNumber(state);succeed({type,state:state==="slow-2g"?"2g":state});return}if(kind==="networkQualityMonitor"){let p=params&&typeof params=="object"?params:{},action=typeof p.action=="string"?p.action:"";if(action==="add_notify_network_quality"){if(!stopNetworkQualityMonitor){let notify=()=>{try{document.dispatchEvent(new CustomEvent("WV.NETWORK_TYPE_CHANGED",{detail:{new_network_type:networkTypeNumber(readNetworkState())}}))}catch{}},connection=navigator.connection;window.addEventListener("online",notify),window.addEventListener("offline",notify),connection?.addEventListener?.("change",notify),stopNetworkQualityMonitor=()=>{window.removeEventListener("online",notify),window.removeEventListener("offline",notify),connection?.removeEventListener?.("change",notify)}}succeed({});return}if(action==="remove_notify_network_quality"){stopNetworkQualityMonitor?.(),stopNetworkQualityMonitor=null,succeed({});return}failed({error_message:"unsupported network quality monitor action"});return}if(kind==="beaconRequest"){let url2=pickUrl(params);if(!url2){failed({error_message:"missing url"});return}try{let resolved=new URL(url2,location.href);if(resolved.protocol!=="http:"&&resolved.protocol!=="https:"){failed({error_message:"unsupported request protocol"});return}let image=new Image;image.referrerPolicy="no-referrer-when-downgrade",image.src=resolved.href,succeed({})}catch{failed({error_message:"invalid url"})}return}if(kind==="calendar"){let p=params&&typeof params=="object"?params:{},events=readCalendarEvents();if(api==="store_calendar_event"){let event=calendarEventFromParams(p);if(!event.title||event.startTime===null){failed({error_message:"calendar title and start time are required"});return}let next=events.filter(stored=>!sameCalendarEvent(stored,event));if(next.push(event),!writeCalendarEvents(next)){failed({error_message:"calendar storage unavailable"});return}succeed({success:!0});return}if(api==="remove_calendar_event"){let candidate=calendarEventFromParams(p),next=events.filter(stored=>!sameCalendarEvent(stored,candidate));if(!writeCalendarEvents(next)){failed({error_message:"calendar storage unavailable"});return}succeed({success:!0,removed:events.length-next.length});return}if(api==="check_batch_calendar"){let batch=Array.isArray(p.batch)?p.batch:[];succeed({batch:batch.map(item=>{let candidate=calendarEventFromParams(item);return{...item&&typeof item=="object"?item:{},success:events.some(stored=>sameCalendarEvent(stored,candidate))}})});return}let urls=Array.isArray(p.urls)?p.urls.filter(value=>typeof value=="string"):typeof p.url=="string"?[p.url]:[],titles=Array.isArray(p.calendar_titles)?p.calendar_titles.filter(value=>typeof value=="string"):typeof p.calendar_title=="string"?[p.calendar_title]:[],matched=events.filter(event=>(urls.length===0||urls.includes(event.url))&&(titles.length===0||titles.includes(event.title)));succeed({events:matched.map(calendarEventResponse)});return}if(kind==="geolocation"){if(!navigator.geolocation){failed({errorCode:2,errorMsg:"geolocation unavailable"});return}let locate=()=>navigator.geolocation.getCurrentPosition(position=>{let{latitude,longitude,accuracy,altitude,altitudeAccuracy,heading,speed}=position.coords;succeed({latitude,longitude,accuracy,altitude,altitudeAccuracy,heading,speed,timestamp:position.timestamp})},error48=>failed({errorCode:error48.code,errorMsg:error48.message}),{enableHighAccuracy:!1,timeout:1e4,maximumAge:3e5});navigator.permissions?.query?navigator.permissions.query({name:"geolocation"}).then(status=>{status.state==="granted"?locate():failed({errorCode:1,errorMsg:"location permission not granted"})}).catch(locate):locate();return}if(kind==="permission"){let p=params&&typeof params=="object"?params:{},action=typeof p.action=="string"?p.action:"",permission=typeof p.permission=="string"?p.permission:"",permissionFailed=message=>failed({error_code:-1,error_message:message});if(permission==="album"||permission==="MODIFY_AUDIO_SETTINGS"){action==="check"||action==="request"?succeed({}):permissionFailed("unsupported permission action");return}let browserPermission=permission==="mic"?"microphone":permission==="camera"?"camera":permission==="lbs"?"geolocation":"";if(!browserPermission){permissionFailed("unsupported permission");return}if(action==="check"&&navigator.permissions?.query){navigator.permissions.query({name:browserPermission}).then(status=>{status.state==="granted"?succeed({}):permissionFailed("permission not granted")}).catch(()=>permissionFailed("permission check failed"));return}if(action==="request"&&(permission==="mic"||permission==="camera")){if(!navigator.mediaDevices?.getUserMedia){permissionFailed("media permission unavailable");return}navigator.mediaDevices.getUserMedia({audio:permission==="mic",video:permission==="camera"}).then(stream=>{for(let track of stream.getTracks())track.stop();succeed({})}).catch(()=>permissionFailed("permission denied"));return}if(action==="request"&&permission==="lbs"&&navigator.geolocation){navigator.geolocation.getCurrentPosition(()=>succeed({}),()=>permissionFailed("permission denied"),{timeout:1e4});return}permissionFailed("unsupported permission action");return}if(kind==="prefetch"){let p=params&&typeof params=="object"?params:{},url2=typeof p.url=="string"?p.url:"";if(!url2){failed({code:-1,errorMsg:"url is empty"});return}let resolvedUrl;try{resolvedUrl=new URL(url2,location.href).href}catch{failed({code:-1,errorMsg:"invalid url"});return}if(!Array.from(document.querySelectorAll('link[rel="prefetch"]')).some(link=>link.href===resolvedUrl)){let link=document.createElement("link");link.rel="prefetch",link.href=url2,(document.head??document.documentElement).appendChild(link)}succeed({});return}if(kind==="fptTrack"){let p=params&&typeof params=="object"?params:{},action=typeof p.action=="string"?p.action:"",actionParams=p.params&&typeof p.params=="object"?p.params:{},key=typeof actionParams.key=="string"?actionParams.key:"";if(action==="setFpt"){let value=typeof actionParams.value=="string"?actionParams.value:"";if(!key||!value||!/^[0-9A-Za-z._-]+$/.test(key)||!/^[0-9A-Za-z._-]+$/.test(value)||`${key}(${value})`.length>100){failed({error_message:"invalid fpt key or value"});return}setFptEntry(fptEntries,key,value),persistFpt()}else action==="deleteFpt"&&key&&(fptEntries.delete(key),persistFpt());succeed({});return}if(kind==="previewFile"){let p=params&&typeof params=="object"?params:{},fileUrl=typeof p.file_url=="string"?p.file_url:"",remoteUrl=typeof p.file_remote_url=="string"?p.file_remote_url:"",url2=(fileUrl.startsWith("http")?fileUrl:remoteUrl)||fileUrl||remoteUrl;url2?(requestOpen(url2,0,!1),succeed({})):failed({code:-1,errorMsg:"file_url is empty"});return}if(kind==="toast"){let error48=showAppToast(params);error48?failed({error_message:error48}):succeed({});return}if(kind==="unsupportedNativeInput"){let containerType="";try{containerType=new URL(location.href).searchParams.get("containerType")??""}catch{}!unsupportedNativeInputNotified&&(containerType==="h5_dx"||containerType==="flutter_h5")&&(unsupportedNativeInputNotified=!0,showAppToast({message:"当前页面使用原生输入框,请移除 URL 中的 containerType 参数以正常操作",milliseconds:4e3})),succeed({});return}if(kind==="payment"){log3("桥调用支付,等待用户确认",api,params),showPaymentDialog(api,params,succeed,failed);return}if(kind==="userTrack"){sendUserTrack(params),succeed({});return}if(kind==="response"){succeed(config2.actions.responses?.[api]);return}if(kind==="noop"){succeed({});return}silent||log3("未覆盖桥方法,回调 failure(页面库将走 H5 兜底):",api),failed(NOT_IMPLEMENTED_PAYLOAD)}let MEGA_SUPPORTED_APIS={stdPop:["showWeex2","showWeex","showH5","changeSize","close"],broadcast:["addEventListener","dispatchEvent","removeEventListener"],kvStorage:["setItem","getItem","removeItem","getAllKeys","clear","getCurrentInfo","getCurrentInfoAndKeys"],LifeCycle:["addPageLifeCycleListener","removePageLifeCycleListener"],Container:["interceptPageClose","disableInterceptPageClose"],navigator:["openURL","close","replace","setSystemBackBlockListener","removeSystemBackBlockListener"],NavBar:["setTitle"],Router:["popPage"]};function isMegaApiSupported(ability,api){return typeof ability=="string"&&typeof api=="string"&&MEGA_SUPPORTED_APIS[ability]?.includes(api)===!0}function megaParams(value){return value&&typeof value=="object"&&!Array.isArray(value)?value:{}}function megaError(callback,statusCode,message){emitMegaCallback(callback,{statusCode,type:"result",data:{errorMessage:typeof message=="string"?message:String(message??"")}})}function cloneMegaDetail(value){if(value===void 0)return{success:!0,value:void 0};try{return{success:!0,value:JSON.parse(JSON.stringify(value))}}catch{return{success:!1}}}function megaSuccess(data={}){return{statusCode:0,type:"result",data}}function megaFailure(message){return{statusCode:500,type:"result",data:{errorMessage:message}}}function megaKVParams(params){return{bizId:typeof params.bizID=="string"?params.bizID:typeof params.bizId=="string"?params.bizId:"",key:typeof params.key=="string"?params.key:"",value:typeof params.value=="string"?params.value:null}}function megaStringByteLength(value){try{return typeof TextEncoder=="function"?new TextEncoder().encode(value).length:value.length}catch{return value.length}}function megaKVUsedSize(entries){let size=0;for(let value of entries.values())size+=megaStringByteLength(value);return size}function reportMegaKVMutation(operation,bizId,key="",value,onSuccess,onFailure){requestContainerData("megaKVMutation",{operation,bizId,key,...value===void 0?{}:{value}},()=>onSuccess?.(),reason=>{log3("KVStorage 容器同步失败:",reason),onFailure?.(reason)})}function completeMegaKVMutation(operation,bizId,key,value,synchronous,callback){let result=megaSuccess();return reportMegaKVMutation(operation,bizId,key,value,synchronous?void 0:()=>emitMegaCallback(callback,result),synchronous?void 0:reason=>emitMegaCallback(callback,megaFailure(String(reason??"container sync failed")))),synchronous?result:null}function executeMegaKVStorage(api,params,synchronous,callback){let{bizId,key,value}=megaKVParams(params);if(!bizId)return megaFailure("missing bizID");let entries=megaKVStorage.get(bizId)??new Map;if(api==="setItem"){if(!key)return megaFailure("missing key");if(value===null||value==="")return megaFailure("missing value");let previousSize=megaStringByteLength(entries.get(key)??"");return megaKVUsedSize(entries)-previousSize+megaStringByteLength(value)>MEGA_KV_TOTAL_SIZE?megaFailure("KVStorage quota exceeded"):(entries.set(key,value),megaKVStorage.set(bizId,entries),megaKVMutationVersion+=1,persistMegaKVStorage(),completeMegaKVMutation("set",bizId,key,value,synchronous,callback))}if(api==="getItem"){if(!key)return megaFailure("missing key");let result=entries.get(key)??"";return megaSuccess(synchronous?{result}:result)}if(api==="removeItem")return key?(entries.delete(key),entries.size===0&&megaKVStorage.delete(bizId),megaKVMutationVersion+=1,persistMegaKVStorage(),completeMegaKVMutation("remove",bizId,key,void 0,synchronous,callback)):megaFailure("missing key");if(api==="getAllKeys"){let result=Array.from(entries.keys());return megaSuccess(synchronous?{result}:result)}if(api==="clear")return megaKVStorage.delete(bizId),megaKVMutationVersion+=1,persistMegaKVStorage(),completeMegaKVMutation("clear",bizId,"",void 0,synchronous,callback);if(api==="getCurrentInfo"||api==="getCurrentInfoAndKeys"){let data={totalSize:MEGA_KV_TOTAL_SIZE,freeSize:Math.max(MEGA_KV_TOTAL_SIZE-megaKVUsedSize(entries),0)};return api==="getCurrentInfoAndKeys"&&(data.keys=Array.from(entries.keys())),megaSuccess(data)}return{statusCode:405,type:"result",data:{}}}function handleMegaLifeCycle(api,callback){if(api==="addPageLifeCycleListener"){callback&&megaLifeCycleListeners.add(callback),emitMegaCallback(callback,megaSuccess());return}if(api==="removePageLifeCycleListener"){let listeners=Array.from(megaLifeCycleListeners);megaLifeCycleListeners.clear(),emitMegaCallback(callback,megaSuccess());for(let listener of listeners)emitMegaCallback(listener,{statusCode:99,type:"finish",data:{}});return}megaError(callback,405,`LifeCycle.${api} is not supported`)}function handleMegaContainer(api,callback){if(api==="interceptPageClose"){callback&&megaPageCloseListeners.add(callback),emitMegaCallback(callback,megaSuccess());return}if(api==="disableInterceptPageClose"){let listeners=Array.from(megaPageCloseListeners);megaPageCloseListeners.clear(),emitMegaCallback(callback,megaSuccess());for(let listener of listeners)emitMegaCallback(listener,{statusCode:99,type:"finish",data:{}});return}megaError(callback,405,`Container.${api} is not supported`)}function megaNavigationUrl(params){let rawUrl=pickUrl(params);if(!rawUrl)return null;if(!params.extQuery||typeof params.extQuery!="object"||Array.isArray(params.extQuery))return rawUrl;try{let target=new URL(rawUrl,location.href);for(let[key,value]of Object.entries(params.extQuery))value!=null&&target.searchParams.set(key,String(value));return target.href}catch{return rawUrl}}function handleMegaNavigator(api,params,callback){if(api==="openURL"||api==="replace"){let url2=megaNavigationUrl(params);if(!url2){megaError(callback,500,"missing url");return}let callbackId=api==="openURL"&&callback?stashCallback(value=>{let backdata=value&&typeof value=="object"?value.backdata:void 0;emitMegaCallback(callback,{statusCode:1,type:"onResult",data:{result:!0,...backdata===void 0?{}:{data:backdata}}}),emitMegaCallback(callback,{statusCode:99,type:"finish",data:{}})}):0;requestOpen(url2,callbackId,!1,{...params,...api==="replace"?{__mearlReplace:!0}:{}}),emitMegaCallback(callback,megaSuccess());return}if(api==="close"){emitMegaCallback(callback,megaSuccess()),requestClose(void 0);return}if(api==="setSystemBackBlockListener"){megaSystemBackListener&&megaSystemBackListener!==callback&&emitMegaCallback(megaSystemBackListener,{statusCode:99,type:"finish",data:{}}),megaSystemBackListener=callback??null,emitMegaCallback(callback,megaSuccess());return}if(api==="removeSystemBackBlockListener"){let listener=megaSystemBackListener;megaSystemBackListener=null,emitMegaCallback(callback,megaSuccess()),listener&&emitMegaCallback(listener,{statusCode:99,type:"finish",data:{}});return}megaError(callback,405,`navigator.${api} is not supported`)}function handleMegaNavBar(api,params,callback){if(api!=="setTitle"){megaError(callback,405,`NavBar.${api} is not supported`);return}applyNavigationBarState(api,params),emitMegaCallback(callback,megaSuccess())}function handleMegaRouter(api,callback){if(api!=="popPage"){megaError(callback,405,`Router.${api} is not supported`);return}emitMegaCallback(callback,megaSuccess()),requestClose(void 0)}function handleMegaStdPop(api,params,callback){if(api==="showH5"||api==="showWeex2"||api==="showWeex"){let url2=pickUrl(params),popId=typeof params.popId=="string"?params.popId.trim():"";if(!url2||!popId){megaError(callback,500,url2?"missing popId":"missing url");return}let callbackId=stashCallback(value=>{let result=value&&typeof value=="object"&&"backdata"in value?value.backdata:void 0;emitMegaCallback(callback,{statusCode:1,type:"onClose",data:result}),emitMegaCallback(callback,{statusCode:99,type:"finish"})});requestOpen(url2,callbackId,!0,{...params,__mearlMegaPopId:popId}),emitMegaCallback(callback,{statusCode:0,type:"result",data:{}});return}if(api==="close"){let popId=typeof params.popId=="string"?params.popId.trim():"";if(!popId){megaError(callback,500,"missing popId");return}let cloned=cloneMegaDetail(params.result);if(!cloned.success){megaError(callback,500,"result is not serializable");return}requestContainerData("megaPopClose",{popId,result:cloned.value},()=>emitMegaCallback(callback,{statusCode:0,type:"result",data:{}}),reason=>megaError(callback,500,reason));return}if(api==="changeSize"){let popId=typeof params.popId=="string"?params.popId.trim():"";if(!popId){megaError(callback,500,"missing popId");return}requestContainerData("megaPopResize",{...params,popId},()=>emitMegaCallback(callback,{statusCode:0,type:"result",data:{}}),reason=>megaError(callback,500,reason));return}megaError(callback,405,`stdPop.${api} is not supported`)}function handleMegaBroadcast(api,params,callback){let bizId=megaBroadcastBizId(params.bizId),eventName=typeof params.eventName=="string"?params.eventName.trim():"";if(!eventName){megaError(callback,500,"missing eventName");return}if(api==="addEventListener"){if(!callback)return;let id=`mearl-mega-listener-${++megaListenerSeq}`;megaBroadcastListeners.set(id,{id,bizId,eventName,once:params.once===!0,callback}),emitMegaCallback(callback,{statusCode:0,type:"result",data:{}}),emitMegaCallback(callback,{statusCode:1,type:"onAdd",data:{listenerId:id}});return}if(api==="dispatchEvent"){let detail=cloneMegaDetail(params.detail);if(!detail.success){megaError(callback,500,"detail is not serializable");return}requestContainerData("megaBroadcast",{message:{kind:"megaBroadcast",bizId,eventName,detail:detail.value}},()=>emitMegaCallback(callback,{statusCode:0,type:"result",data:{}}),reason=>megaError(callback,500,reason));return}if(api==="removeEventListener"){let listenerId=typeof params.listenerId=="string"?params.listenerId:"",removed=[];for(let listener of Array.from(megaBroadcastListeners.values()))listener.bizId!==bizId||listener.eventName!==eventName||listenerId&&listener.id!==listenerId||(megaBroadcastListeners.delete(listener.id),removed.push(listener));emitMegaCallback(callback,{statusCode:0,type:"result",data:{}});for(let listener of removed)emitMegaCallback(listener.callback,{statusCode:99,type:"finish"});return}megaError(callback,405,`broadcast.${api} is not supported`)}function makeMegaBridge(){return{asyncCall:(ability,api,rawParams,callback)=>{let params=megaParams(rawParams);if(ability==="ability"&&api==="available"){emitMegaCallback(callback,{statusCode:0,type:isMegaApiSupported(params.ability,params.api)?"YES":"NO",data:{}});return}if(ability==="ability"&&api==="batchFinishTrace"){emitMegaCallback(callback,{statusCode:0,type:"result",data:{}});return}if(!isMegaApiSupported(ability,api)){megaError(callback,405,`${ability}.${api} is not supported`);return}if(ability==="stdPop")handleMegaStdPop(api,params,callback);else if(ability==="broadcast")handleMegaBroadcast(api,params,callback);else if(ability==="kvStorage"){let result=executeMegaKVStorage(api,params,!1,callback);result&&emitMegaCallback(callback,result)}else ability==="LifeCycle"?handleMegaLifeCycle(api,callback):ability==="Container"?handleMegaContainer(api,callback):ability==="navigator"?handleMegaNavigator(api,params,callback):ability==="NavBar"?handleMegaNavBar(api,params,callback):handleMegaRouter(api,callback)},syncCall:(ability,api,rawParams)=>{let params=megaParams(rawParams);return ability==="ability"&&api==="available"?{statusCode:0,type:isMegaApiSupported(params.ability,params.api)?"YES":"NO",data:{}}:ability==="kvStorage"&&isMegaApiSupported(ability,api)?executeMegaKVStorage(api,params,!0)??megaFailure("container sync pending"):{statusCode:405,type:"result",data:{}}}}}function makeBridge(style){if(style==="mega")return makeMegaBridge();if(style==="easybikeNative"){let callNative=rawPayload=>{let payload;try{payload=typeof rawPayload=="string"?JSON.parse(rawPayload):rawPayload??{}}catch{return}let classMap=typeof payload.classMap=="string"?payload.classMap:"",method=typeof payload.method=="string"?payload.method:"",callbackId=typeof payload.callbackId=="string"||typeof payload.callbackId=="number"?String(payload.callbackId):"",params;try{params=typeof payload.params=="string"?payload.params?JSON.parse(payload.params):{}:payload.params??{}}catch{params={}}let complete=(code,data,msg="")=>{let callback=resolveWindowFunction("callBack");callbackId&&callback&&callback({callbackId,code,data,msg})};dispatch(`${classMap}.${method}`,params,value=>complete(0,value),error48=>complete(1,void 0,typeof error48=="string"?error48:String(error48??"")))};return{postMessage:callNative,callNative}}if(style==="windvane")return{isAvailable:!0,version:"8.7.0",call:(cls,method,params,succ,fail)=>dispatch(`${cls}.${method}`,params,succ,fail)};if(style==="fliggy"||style==="alipay"||style==="callback"){let bridge={call:(api,params,succ,fail)=>{typeof params=="function"&&(fail=succ,succ=params,params=void 0);let p=params&&typeof params=="object"?params:{},successFn=succ??(typeof p.success_callback=="function"?p.success_callback:void 0)??(typeof p.successCallback=="function"?p.successCallback:void 0),failureFn=fail??(typeof p.fail_callback=="function"?p.fail_callback:void 0)??(typeof p.failure_callback=="function"?p.failure_callback:void 0)??(typeof p.failCallback=="function"?p.failCallback:void 0)??(typeof p.failureCallback=="function"?p.failureCallback:void 0);dispatch(api,p,res=>successFn?.(res),err=>{failureFn?failureFn(err):successFn?.({error:err})},p.callbackCommand??p.callback_command)},pushBack:(prefixOrApi,apiOrParams,paramsOrSucc,succ)=>{let api=prefixOrApi,params=apiOrParams,success2=paramsOrSucc;typeof apiOrParams=="string"&&(api=apiOrParams,params=paramsOrSucc,success2=succ);let p=params??{},successFn=(typeof success2=="function"?success2:void 0)??(typeof p.successCallback=="function"?p.successCallback:void 0);return dispatch(api,p,res=>successFn?.(res),void 0,p.callbackCommand??p.callback_command),bridge},sendUriScheme:uri=>(handleMaybeScheme(uri),bridge)};if(style==="fliggy"){let normalizedAppName=(config2.globals.__APP_NAME__??"").toUpperCase(),os11=config2.clientType==="iphone"?"ios":"android",isAliApp=name=>normalizedAppName===name.toUpperCase();Object.assign(bridge,{version:"1.0.21",device:{os:os11,OS:config2.platform,type:os11,version:config2.systemVersion,model:config2.globals.__DEVICE_MODEL__??""},platform:os11,isAliApp,isTmall:isAliApp("TM"),isTaobao:isAliApp("TB"),isAlipay:isAliApp("AP"),isAlitrip:isAliApp("LX"),isKoubei:isAliApp("KB"),isElm:isAliApp("ELMC"),isGaode:isAliApp("amap"),isUC:/UCBrowser/i.test(config2.userAgent),isWeibo:/Weibo/i.test(config2.userAgent),isWeixin:/MicroMessenger/i.test(config2.userAgent),isWindVane:config2.bridges.some(item=>item.style==="windvane"),isAlipayClient:/AlipayClient/i.test(config2.userAgent)})}return bridge}if(style==="btrip")return{call:(api,params)=>dispatch(api,params??{},void 0,void 0)};if(style==="invoke")return{invoke:(api,params)=>{let p=params??{};dispatch(api,p,p.success,p.fail)}};if(style==="callHandler")return{callHandler:(api,params)=>dispatch(api,params??{},void 0,void 0)};if(style==="amap")return{ready:cb=>cb?.(),send:(msg,cb)=>{let m=msg??{};dispatch(typeof m.action=="string"?m.action:"",m,res=>cb?.(res),err=>cb?.({error:err}))}};if(style==="didi")return{openPage:params=>dispatch("openPage",params??{},void 0,void 0),closePage:params=>dispatch("closePage",params??{},void 0,void 0)};if(style==="wechatMiniProgram"){let invoke2=(api,params)=>{let p=params&&typeof params=="object"?params:{};dispatch(api,p,value=>{p.success?.(value),p.complete?.(value)},error48=>{p.fail?.(error48),p.complete?.(error48)})};return{navigateTo:params=>invoke2("navigateTo",params),redirectTo:params=>invoke2("redirectTo",params),switchTab:params=>invoke2("switchTab",params),reLaunch:params=>invoke2("reLaunch",params),navigateBack:params=>invoke2("navigateBack",params),postMessage:params=>invoke2("postMessage",params),getEnv:callback=>{callback&&setTimeout(()=>callback({miniprogram:!0}),0)}}}return{}}function setGlobal(path23,value){let parts=path23.split("."),obj=w;for(let i=0;i<parts.length-1;i++){let cur=obj[parts[i]];(!cur||typeof cur!="object")&&(obj[parts[i]]={}),obj=obj[parts[i]]}obj[parts[parts.length-1]]=value}if(config2.bridges.some(spec=>spec.style==="mega")){let hydrationVersion=megaKVMutationVersion;requestContainerData("megaKVSnapshot",{},value=>{let entries=value&&typeof value=="object"?value.entries:void 0;megaKVMutationVersion===hydrationVersion&&replaceMegaKVStorage(entries)},()=>{})}for(let spec of config2.bridges)try{setGlobal(spec.global,makeBridge(spec.style))}catch(e){console.error(TAG,"桥安装失败:",spec.global,e)}return{mapScheme,handleMaybeScheme,handleAppMessage,handleNativeBack,handleResume,handlePageVisibility,applyRuntimeResponses}}function installAppProfileContainerStack(config2,environment,links){let{SRC,TAG,simulateSystemBars,ROOT_FRAME_NAME,LAYER_FRAME_NAME,isTop,isRootFrame,isLayerFrame,isContainerFrame,usesRootContainer,log:log3}=environment,{pageTransport}=links,initialLayerTitleBarState=url2=>links.getSystemBars().initialLayerTitleBarState(url2),resolvedTitleBarState=layer=>links.getSystemBars().resolvedTitleBarState(layer),parseReportedTitleBarState=value=>links.getSystemBars().parseReportedTitleBarState(value),createSimulatedNavigationBarView=(placement,onBack)=>links.getSystemBars().createNavigationBarView(placement,onBack),destroySimulatedNavigationBarView=view=>links.getSystemBars().destroyNavigationBarView(view),syncLayerViewport=(layer,state)=>links.getSystemBars().syncLayerViewport(layer,state),syncActiveSystemBars=()=>links.getSystemBars().syncActiveSystemBars(),syncSimulatedTitleBar=()=>links.getSystemBars().syncSimulatedTitleBar(),rootContainerActive=!1,rootFrame=null,rootBusinessUrl=location.href,webViewEnvironmentRequestSeq=0,simulatedPageHidden=!1,runtimeResponses=null;function syncSimulatorStateToWindow(target){target&&(runtimeResponses&&target.postMessage({source:SRC,type:"runtimeResponses",profile:config2.profile,responses:runtimeResponses},"*"),simulatedPageHidden&&target.postMessage({source:SRC,type:"simulatorVisibility",hidden:!0},"*"))}function startPreparedWebViewNavigation(frame,target,canCommit,registerCleanup){let insets=config2.safeAreaInsets??{top:config2.statusBarHeight,right:0,bottom:0,left:0};if(!usesRootContainer||!Object.values(insets).some(value=>value>0)){canCommit()&&(frame.src=target);return}let requestId=++webViewEnvironmentRequestSeq,settled=!1,fallbackTimer=0,cleanup=()=>{settled||(settled=!0,clearTimeout(fallbackTimer),window.removeEventListener("message",handleResponse),registerCleanup?.(null))},commitNavigation=fallbackReason=>{cleanup(),fallbackReason&&console.warn(TAG,"WebView 环境准备未完成,降级提交导航",{target,requestId,reason:fallbackReason}),canCommit()&&(frame.src=target)},handleResponse=event=>{if(event.source!==window||event.data?.source!=="mearl-content"||event.data?.type!=="APP_BRIDGE_PREPARE_WEBVIEW_RESPONSE"||event.data?.requestId!==requestId)return;let result=event.data.result;result?.success===!0?commitNavigation():commitNavigation(String(result?.error??"unknown preparation failure"))};registerCleanup?.(cleanup),window.addEventListener("message",handleResponse),fallbackTimer=setTimeout(()=>commitNavigation("preparation timed out after 500ms"),500);try{window.postMessage({source:SRC,type:"prepareWebView",requestId},"*")}catch(error48){commitNavigation(error48 instanceof Error?error48.message:String(error48))}}function installRootContainer(){if(!usesRootContainer||!/^https?:$/i.test(location.protocol))return;let shellRoot,frame;try{for(let cookie of config2.rootContainer?.initialCookies??[]){if(!cookie.name)continue;let parts=[`${encodeURIComponent(cookie.name)}=${encodeURIComponent(cookie.value)}`,`Path=${cookie.path??"/"}`];cookie.domain&&parts.push(`Domain=${cookie.domain}`),document.cookie=parts.join("; ")}shellRoot=document.createElement("html");let shellHead=document.createElement("head"),charset=document.createElement("meta"),viewport=document.createElement("meta"),title=document.createElement("title"),shellBody=document.createElement("body");frame=document.createElement("iframe"),shellRoot.setAttribute("data-mearl-app-shell",""),shellBody.setAttribute("data-mearl-app-shell",""),charset.setAttribute("charset","utf-8"),viewport.name="viewport",viewport.content="width=device-width,initial-scale=1,viewport-fit=cover",shellHead.append(charset,viewport,title),shellRoot.append(shellHead,shellBody),shellRoot.style.cssText="width:100%;height:100%;margin:0;overflow:hidden;background:#fff;",shellBody.style.cssText="width:100%;height:100%;margin:0;overflow:hidden;background:#fff;",frame.name=ROOT_FRAME_NAME,frame.setAttribute("data-mearl-root-webview",config2.profile),frame.style.cssText="position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;border:0;display:block;background:#fff;z-index:0;opacity:1;",frame.addEventListener("load",()=>{let committedSrc=frame.getAttribute("src");!committedSrc||committedSrc==="about:blank"||(syncSimulatorStateToWindow(frame.contentWindow),requestAnimationFrame(()=>{rootFrame!==frame||!frame.isConnected||(frame.setAttribute("data-mearl-webview-ready",""),syncSimulatedTitleBar())}))}),shellBody.appendChild(frame);let currentRoot=document.documentElement;currentRoot?document.replaceChild(shellRoot,currentRoot):document.appendChild(shellRoot)}catch(error48){console.warn(TAG,"根 WebView 容器创建失败,保留当前页面",error48),rootFrame=null;return}rootFrame=frame,rootContainerActive=!0;try{typeof window.stop=="function"&&window.stop()}catch(error48){console.warn(TAG,"停止外层文档加载失败,继续启动根 WebView",error48)}try{startPreparedWebViewNavigation(frame,rootBusinessUrl,()=>rootFrame===frame&&frame.isConnected)}catch(error48){console.warn(TAG,"根 WebView 环境准备启动失败,直接提交业务导航",error48),rootFrame===frame&&frame.isConnected&&(frame.src=rootBusinessUrl)}}installRootContainer();function normalizeProxyPathPrefix(prefix){let withLeadingSlash=prefix.startsWith("/")?prefix:`/${prefix}`;return withLeadingSlash.endsWith("/")?withLeadingSlash:`${withLeadingSlash}/`}function matchesProxyTarget(hostname3,suffixes){return suffixes.some(suffix=>hostname3===suffix||hostname3.endsWith(`.${suffix}`))}function mapLayerFrameUrl(url2){let proxy=config2.layerUrlProxy;if(!proxy||!location.hostname.startsWith(proxy.sourceHostPrefix))return url2;try{let target=new URL(url2,location.href);if(!/^https?:$/.test(target.protocol))return url2;let prefix=normalizeProxyPathPrefix(proxy.pathPrefix);if(target.hostname===location.hostname){if(target.pathname.startsWith(prefix))return url2;let derivedHost=location.pathname.startsWith(prefix)?location.pathname.slice(prefix.length).split("/")[0]:proxy.defaultTargetHost;return!derivedHost||!matchesProxyTarget(derivedHost,proxy.targetHostSuffixes)?url2:`${location.origin}${prefix}${derivedHost}${target.pathname}${target.search}${target.hash}`}return matchesProxyTarget(target.hostname,proxy.targetHostSuffixes)?`${location.origin}${prefix}${target.host}${target.pathname}${target.search}${target.hash}`:url2}catch{return url2}}function restoreLayerBusinessUrl(url2){let proxy=config2.layerUrlProxy;if(!proxy)return url2;try{let current=new URL(url2,location.href),prefix=normalizeProxyPathPrefix(proxy.pathPrefix);if(current.origin!==location.origin||!current.pathname.startsWith(prefix))return url2;let rest=current.pathname.slice(prefix.length),slash=rest.indexOf("/"),host=slash===-1?rest:rest.slice(0,slash);if(!host)return url2;let hostname3=new URL(`${current.protocol}//${host}`).hostname;if(!matchesProxyTarget(hostname3,proxy.targetHostSuffixes))return url2;let pathname=slash===-1?"/":rest.slice(slash);return`${current.protocol}//${host}${pathname}${current.search}${current.hash}`}catch{return url2}}let ANIM_MS=config2.animationMs??300;function boolParam(value,fallback){return value===!0||value===1||value==="1"||value==="true"?!0:value===!1||value===0||value==="0"||value==="false"?!1:value===""?!0:fallback}function numberParam(value,fallback,min,max){let parsed=typeof value=="number"?value:Number(value);return Number.isFinite(parsed)?Math.min(Math.max(parsed,min),max):fallback}function resolveOverlayPresentation(url2,params,explicitWebdialog){let query=null;try{query=new URL(url2,location.href).searchParams}catch{}let records=[],addRecord=value=>{value&&typeof value=="object"&&!Array.isArray(value)&&records.push(value)};addRecord(params?.pageParams),addRecord(params?.page_params),addRecord(params?.popConfig),addRecord(params?.data),addRecord(params?.param),addRecord(params);let read=key=>{for(let record2 of records)if(Object.prototype.hasOwnProperty.call(record2,key))return record2[key];return query?.has(key)?query.get(key):void 0},protocol=config2.overlay;if(!explicitWebdialog&&(!protocol||!boolParam(read(protocol.enabledParam),!1)))return null;let configuredTopRatio=protocol?read(protocol.topRatioParam):void 0,configuredHeightRatio=protocol?.heightRatioParam?read(protocol.heightRatioParam):void 0,configuredMaxHeight=read("maxHeight")??configuredHeightRatio,defaultTopRatio=protocol?.defaultTopRatio??.2;return{topRatio:configuredTopRatio!==void 0?numberParam(configuredTopRatio,defaultTopRatio,0,1):configuredMaxHeight!==void 0?1-numberParam(configuredMaxHeight,1-defaultTopRatio,0,1):defaultTopRatio,widthRatio:numberParam(read("maxWidth"),1,0,1),radius:numberParam((protocol?read(protocol.radiusParam):void 0)??read("cornerRadius"),protocol?.defaultRadius??0,0,50),maskAlpha:numberParam(protocol?read(protocol.maskAlphaParam):void 0,protocol?.defaultMaskAlpha??.3,0,1),tapClose:boolParam((protocol?read(protocol.tapCloseParam):void 0)??read("tapEnable"),protocol?.defaultTapClose??!0)}}function requestsPopBeforeOpen(url2,params){if(params?.__mearlReplace===!0)return!0;let key=config2.popBeforeOpenParam;if(!key)return!1;let records=[params?.pageParams,params?.page_params,params?.data,params?.param,params];for(let value of records){if(!value||typeof value!="object"||Array.isArray(value))continue;let record2=value;if(Object.prototype.hasOwnProperty.call(record2,key))return boolParam(record2[key],!1)}try{let query=new URL(url2,location.href).searchParams;return query.has(key)&&boolParam(query.get(key),!1)}catch{return!1}}let layers=[],forwardStack=[],layerSeq=0,enteringLayerCount=0,closingLayerCount=0,explicitLayerTitleBarStates=new Map,rootScrollStyles=null,pendingClose=null,nativeBackRequestSeq=0,pendingNativeBack=null,containerDataRequestSeq=0,containerDataCallbacks=new Map,sharedFiles=new Map,sharedData=new Map,legacyBroadcastChannels=new Set,MEGA_KV_STORAGE_KEY=`__mearl_mega_kv__:${config2.profile}`;function readMegaKVStorage(){let storage=new Map;try{let parsed=JSON.parse(localStorage.getItem(MEGA_KV_STORAGE_KEY)??"{}");if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return storage;for(let[bizId,rawEntries]of Object.entries(parsed)){if(!rawEntries||typeof rawEntries!="object"||Array.isArray(rawEntries))continue;let entries=new Map;for(let[key,value]of Object.entries(rawEntries))typeof value=="string"&&entries.set(key,value);storage.set(bizId,entries)}}catch{}return storage}let megaKVStorage=readMegaKVStorage();function megaKVSnapshot(){let snapshot={};for(let[bizId,values]of megaKVStorage)snapshot[bizId]=Object.fromEntries(values);return snapshot}function persistMegaKVStorage(){try{localStorage.setItem(MEGA_KV_STORAGE_KEY,JSON.stringify(megaKVSnapshot()))}catch{}}let PENDING_CLOSE_TIMEOUT_MS=400,pendingRootHistoryDepth=null;function clearPendingClose(){pendingClose&&(clearTimeout(pendingClose.timer),pendingClose=null)}function clearPendingNativeBack(){pendingNativeBack&&(clearTimeout(pendingNativeBack.timer),pendingNativeBack=null)}function clearPendingRootHistoryDepth(){pendingRootHistoryDepth&&(clearTimeout(pendingRootHistoryDepth.timer),pendingRootHistoryDepth=null)}function armPendingClose(data,retries){clearPendingClose();let timer=setTimeout(()=>{pendingClose=null,log3("close 未等到 popstate,直接关栈顶兜底"),closeToDepth(Math.max(layers.length-1,0),data,!0)},PENDING_CLOSE_TIMEOUT_MS);pendingClose={data,retries,timer},history.back()}function parseStorageId(url2){try{return new URL(url2,location.href).searchParams.get("__storage_id")}catch{return null}}function titleBarStateCacheKey(url2){try{let parsed=new URL(url2,location.href);return parsed.hash="",parsed.href}catch{return url2}}function cacheExplicitTitleBarState(layer,state){explicitLayerTitleBarStates.set(titleBarStateCacheKey(layer.entryUrl),state),explicitLayerTitleBarStates.set(titleBarStateCacheKey(layer.url),state)}function readDepth(state){if(state&&typeof state=="object"){let d=state.__mearl_layer__;if(typeof d=="number")return d}return null}function mapUrlForSync(url2){let suffixes=config2.urlSyncHostSuffixes??[];try{let u=new URL(url2,location.href);if(!/^https?:$/.test(u.protocol)||!(suffixes.length===0||suffixes.some(s=>u.host===s||u.host.endsWith(`.${s}`))))return;let proxy=config2.layerUrlProxy;return proxy&&location.hostname.startsWith(proxy.sourceHostPrefix)&&matchesProxyTarget(u.hostname,proxy.targetHostSuffixes)?`${normalizeProxyPathPrefix(proxy.pathPrefix)}${u.host}${u.pathname}${u.search}${u.hash}`:u.pathname+u.search+u.hash}catch{return}}function createLayerEl(overlay,id){let el=document.createElement("div");el.setAttribute("data-mearl-layer",String(id)),el.style.cssText=`position:fixed;inset:0;z-index:${2147483e3+id%100*2};`;let frame=document.createElement("iframe");if(frame.name=LAYER_FRAME_NAME,frame.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-modals allow-downloads allow-popups"),frame.style.cssText="position:absolute;inset:0;width:100%;height:100%;border:0;display:block;background:#fff;z-index:0;opacity:1;",overlay){el.style.pointerEvents="none";let mask=document.createElement("div");mask.style.cssText=`position:absolute;inset:0;background:rgba(0,0,0,${overlay.maskAlpha});opacity:0;pointer-events:auto;`;let sheet=document.createElement("div"),width=overlay.widthRatio*100,left=(1-overlay.widthRatio)/2*100;return sheet.style.cssText=`position:absolute;left:${left}%;right:auto;bottom:0;width:${width}%;height:${(1-overlay.topRatio)*100}%;background:#fff;border-radius:${overlay.radius}px ${overlay.radius}px 0 0;overflow:hidden;pointer-events:auto;`,sheet.appendChild(frame),el.appendChild(mask),el.appendChild(sheet),{el,frame,animEl:sheet,mask}}return el.style.background="#fff",el.appendChild(frame),{el,frame,animEl:el,mask:null}}function setLayerInteractive(layer,interactive){layer.frame.style.pointerEvents=interactive?"":"none",layer.titleBarView&&(layer.titleBarView.root.style.pointerEvents=interactive?"":"none"),interactive?(layer.frame.removeAttribute("inert"),layer.frame.removeAttribute("aria-hidden"),layer.frame.removeAttribute("tabindex")):(layer.frame.setAttribute("inert",""),layer.frame.setAttribute("aria-hidden","true"),layer.frame.setAttribute("tabindex","-1"),layer.frame.blur()),layer.overlay?(layer.el.style.pointerEvents="none",layer.animEl.style.pointerEvents=interactive?"auto":"none",layer.mask&&(layer.mask.style.pointerEvents=interactive?"auto":"none")):layer.el.style.pointerEvents=interactive?"":"none"}function setRootFrameInteractive(interactive){rootFrame&&(rootFrame.style.pointerEvents=interactive?"":"none",interactive?(rootFrame.removeAttribute("inert"),rootFrame.removeAttribute("aria-hidden"),rootFrame.removeAttribute("tabindex")):(rootFrame.setAttribute("inert",""),rootFrame.setAttribute("aria-hidden","true"),rootFrame.setAttribute("tabindex","-1"),rootFrame.blur()))}function blockClosingLayerInteractions(layer){setLayerInteractive(layer,!1),layer.el.style.pointerEvents="auto"}function syncRootScrollLock(locked){let body=document.body;if(locked&&!rootScrollStyles){rootScrollStyles={html:document.documentElement.style.overflow,body:body?.style.overflow??null},document.documentElement.style.overflow="hidden",body&&(body.style.overflow="hidden");return}!locked&&rootScrollStyles&&(document.documentElement.style.overflow=rootScrollStyles.html,body&&rootScrollStyles.body!==null&&(body.style.overflow=rootScrollStyles.body),rootScrollStyles=null)}function syncLayerInteractivity(){let activeLayer=closingLayerCount===0&&enteringLayerCount===0?layers[layers.length-1]:void 0;for(let layer of layers)setLayerInteractive(layer,layer===activeLayer),!activeLayer&&layer===layers[layers.length-1]&&(layer.el.style.pointerEvents="auto");setRootFrameInteractive(layers.length===0&&enteringLayerCount===0&&closingLayerCount===0),syncRootScrollLock(layers.length>0||enteringLayerCount>0||closingLayerCount>0)}function finishLayerEntry(layer){layer.entering&&(layer.entering=!1,layer.enterTimer!==null&&clearTimeout(layer.enterTimer),layer.enterTimer=null,layer.enterTransitionEnd&&(layer.animEl.removeEventListener("transitionend",layer.enterTransitionEnd),layer.enterTransitionEnd=null),enteringLayerCount=Math.max(enteringLayerCount-1,0),syncLayerInteractivity())}function animateIn(layer){let t=layer.animEl;if(t.style.transform=layer.overlay?"translateY(100%)":"translateX(100%)",t.offsetWidth,t.style.transition=`transform ${ANIM_MS}ms ease`,t.style.transform="translate(0px, 0px)",layer.mask&&(layer.mask.style.transition=`opacity ${ANIM_MS}ms ease`,layer.mask.style.opacity="1"),ANIM_MS<=0){finishLayerEntry(layer);return}layer.enterTransitionEnd=event=>{event.target===t&&event.propertyName==="transform"&&finishLayerEntry(layer)},t.addEventListener("transitionend",layer.enterTransitionEnd),layer.enterTimer=setTimeout(()=>finishLayerEntry(layer),ANIM_MS+60)}function animateOut(layer,done){let t=layer.animEl;if(ANIM_MS<=0){t.style.transform=layer.overlay?"translateY(100%)":"translateX(100%)",layer.mask&&(layer.mask.style.opacity="0"),setTimeout(done,0);return}let settled=!1,fallbackTimer=0,finish=()=>{settled||(settled=!0,t.removeEventListener("transitionend",onTransitionEnd),clearTimeout(fallbackTimer),done())},onTransitionEnd=event=>{event.target===t&&event.propertyName==="transform"&&finish()};t.addEventListener("transitionend",onTransitionEnd),t.style.transition=`transform ${ANIM_MS}ms ease`,t.style.transform=layer.overlay?"translateY(100%)":"translateX(100%)",layer.mask&&(layer.mask.style.opacity="0"),fallbackTimer=setTimeout(finish,ANIM_MS+60)}function startLayerNavigation(layer,target){startPreparedWebViewNavigation(layer.frame,target,()=>!layer.closing&&layer.el.isConnected,cleanup=>{layer.navigationPreparationCleanup=cleanup})}function setPageVisibility(target,hidden){if(target===window){links.getBridgeProtocol().handlePageVisibility(hidden);return}try{target.postMessage({source:SRC,type:"simulatorVisibility",hidden},"*")}catch{}}function openLayer(url2,callbackId,overlay,openerWin,pushHistory,popId=null){clearPendingClose();let target=url2;if(!/^https?:/i.test(target)){let mapped=links.getBridgeProtocol().mapScheme(target);if(!mapped)return log3("open 失败,scheme 未映射:",url2),null;target=mapped}location.protocol==="https:"&&target.startsWith("http:")&&(target="https:"+target.slice(5));let presentation=overlay??resolveOverlayPresentation(target,void 0,!1);log3("open →",presentation?"(webdialog) ":"",target);let parts=createLayerEl(presentation,++layerSeq),restoredTitleBarState=explicitLayerTitleBarStates.get(titleBarStateCacheKey(target)),layer={id:layerSeq,win:parts.frame.contentWindow,frame:parts.frame,entryUrl:target,url:target,overlay:presentation,openerWin,callbackId,storageId:parseStorageId(target),popId,el:parts.el,animEl:parts.animEl,mask:parts.mask,entering:!0,enterTimer:null,enterTransitionEnd:null,closing:!1,navigationPreparationCleanup:null,titleBarState:restoredTitleBarState??initialLayerTitleBarState(target),titleBarStateExplicit:restoredTitleBarState!==void 0,titleBarStateReady:restoredTitleBarState!==void 0,titleBarView:null};if(popId&&layer.el.setAttribute("data-mearl-pop-id",popId),layer.mask&&presentation?.tapClose&&layer.mask.addEventListener("click",()=>requestOverlayClose(layer)),!presentation&&simulateSystemBars&&config2.titleBar&&(layer.titleBarView=createSimulatedNavigationBarView("layer",()=>requestNativeBack()),layer.titleBarView.root.setAttribute("data-mearl-layer-titlebar",String(layer.id)),parts.el.appendChild(layer.titleBarView.root)),layers.push(layer),setPageVisibility(openerWin,!0),enteringLayerCount+=1,syncLayerViewport(layer,layer.titleBarState),syncLayerInteractivity(),parts.frame.addEventListener("load",()=>{layer.win=parts.frame.contentWindow,parts.frame.name=LAYER_FRAME_NAME;let committedSrc=parts.frame.getAttribute("src");!committedSrc||committedSrc==="about:blank"||(syncSimulatorStateToWindow(parts.frame.contentWindow),requestAnimationFrame(()=>{layer.titleBarStateReady||layer.closing||!layer.el.isConnected||(layer.titleBarStateReady=!0,syncLayerViewport(layer,resolvedTitleBarState(layer)))}))}),(document.body??document.documentElement).appendChild(parts.el),layer.win=parts.frame.contentWindow,startLayerNavigation(layer,mapLayerFrameUrl(target)),animateIn(layer),pushHistory){forwardStack.length=0;try{history.pushState({__mearl_layer__:layers.length},"",mapUrlForSync(target))}catch{}}return layer}function replaceLayer(sourceLayer,url2,callbackId,overlay,popId=null){if(sourceLayer.closing||layers[layers.length-1]!==sourceLayer){openLayer(url2,callbackId,overlay,sourceLayer.win??window,!0,popId);return}let replacement=openLayer(url2,callbackId,overlay,sourceLayer.openerWin,!1,popId);if(!replacement)return;sourceLayer.navigationPreparationCleanup?.(),sourceLayer.navigationPreparationCleanup=null,sourceLayer.entering&&(sourceLayer.entering=!1,enteringLayerCount=Math.max(enteringLayerCount-1,0),sourceLayer.enterTimer!==null&&clearTimeout(sourceLayer.enterTimer),sourceLayer.enterTransitionEnd&&sourceLayer.animEl.removeEventListener("transitionend",sourceLayer.enterTransitionEnd));let sourceIndex=layers.indexOf(sourceLayer);sourceIndex>=0&&layers.splice(sourceIndex,1),destroySimulatedNavigationBarView(sourceLayer.titleBarView),sourceLayer.el.remove(),forwardStack.length=0,syncLayerInteractivity(),syncActiveSystemBars();try{history.replaceState({__mearl_layer__:layers.length},"",mapUrlForSync(replacement.url))}catch{}}function closeLayer(layer,data,final,gotoEvent=!1,resumeOpener=!0){if(layer.closing)return;layer.navigationPreparationCleanup?.(),layer.navigationPreparationCleanup=null,layer.entering&&(layer.entering=!1,enteringLayerCount=Math.max(enteringLayerCount-1,0),layer.enterTimer!==null&&clearTimeout(layer.enterTimer),layer.enterTimer=null,layer.enterTransitionEnd&&(layer.animEl.removeEventListener("transitionend",layer.enterTransitionEnd),layer.enterTransitionEnd=null)),layer.closing=!0;let idx=layers.indexOf(layer);idx>=0&&layers.splice(idx,1),closingLayerCount+=1,blockClosingLayerInteractions(layer),syncLayerInteractivity(),syncActiveSystemBars(),final?forwardStack.length=0:forwardStack.push({url:layer.url,overlay:layer.overlay,openerWin:layer.openerWin,callbackId:layer.callbackId,storageId:layer.storageId,popId:layer.popId}),log3("close ←",layer.url,data===void 0?"":data),animateOut(layer,()=>{if(destroySimulatedNavigationBarView(layer.titleBarView),layer.el.remove(),closingLayerCount=Math.max(closingLayerCount-1,0),syncLayerInteractivity(),syncActiveSystemBars(),!!resumeOpener)if(layer.openerWin===window)links.getBridgeProtocol().handleResume({data,storageId:layer.storageId,callbackId:layer.callbackId,final,gotoEvent});else try{layer.openerWin.postMessage({source:SRC,type:"resume",data,storageId:layer.storageId,callbackId:layer.callbackId,final,gotoEvent},"*")}catch{}})}function closeToDepth(depth,data,final){for(;layers.length>depth;){let revealsTarget=layers.length===depth+1;closeLayer(layers[layers.length-1],revealsTarget?data:void 0,final,!1,revealsTarget)}}function closeAllLayers(data,gotoEvent=!1){let depth=layers.length;for(;layers.length>0;){let isRootmostLayer=layers.length===1;closeLayer(layers[layers.length-1],isRootmostLayer?data:void 0,!0,isRootmostLayer&&gotoEvent,isRootmostLayer)}if(depth>0)try{history.go(-depth)}catch{}return depth>0}function requestOverlayClose(layer){if(!(layer.closing||layers[layers.length-1]!==layer)){for(let selector of config2.overlay?.tapCloseSelectors??[])try{let control=layer.frame.contentDocument?.querySelector(selector);if(typeof control?.click!="function")continue;control.click();return}catch{}requestCloseOnTop(void 0)}}function forwardToDepth(depth){for(;layers.length<depth&&forwardStack.length>0;){let entry=forwardStack.pop();openLayer(entry.url,entry.callbackId,entry.overlay,entry.openerWin,!1,entry.popId)}}function requestCloseOnTop(data){if(layers.length===0){history.back();return}if(rootContainerActive){clearPendingRootHistoryDepth(),closeLayer(layers[layers.length-1],data,!0);let depth=layers.length,timer=setTimeout(()=>{pendingRootHistoryDepth=null,console.warn(TAG,"WebView 已出栈,但浏览器历史未在预期时间内同步",{depth})},PENDING_CLOSE_TIMEOUT_MS);pendingRootHistoryDepth={depth,timer},history.back();return}armPendingClose(data,8)}function isActiveBusinessWindow(target){let topLayer=layers[layers.length-1];return topLayer?topLayer.frame.contentWindow===target:rootFrame?rootFrame.contentWindow===target:target===window}function finishNativeBack(requestId,target,handled){pendingNativeBack?.requestId!==requestId||pendingNativeBack.target!==target||(clearPendingNativeBack(),!handled&&isActiveBusinessWindow(target)&&requestCloseOnTop(void 0))}function requestNativeBack(){if(!isTop||pendingNativeBack)return;let target=layers[layers.length-1]?.frame.contentWindow??rootFrame?.contentWindow??window;if(!target||target===window){links.getBridgeProtocol().handleNativeBack()||requestCloseOnTop(void 0);return}let requestId=++nativeBackRequestSeq,timer=setTimeout(()=>finishNativeBack(requestId,target,!1),120);pendingNativeBack={requestId,target,timer};try{target.postMessage({source:SRC,type:"nativeBack",requestId},"*")}catch{finishNativeBack(requestId,target,!1)}}function layerForWindow(source){if(source)for(let layer of layers){if(layer.win===source)return layer;let currentWindow=layer.frame.contentWindow;if(currentWindow&¤tWindow===source)return layer.win=currentWindow,layer}}if(isTop){if(!rootContainerActive){let rawPushState=history.pushState.bind(history),rawReplaceState=history.replaceState.bind(history),withDepth=state=>state==null?{__mearl_layer__:layers.length}:typeof state=="object"&&!Array.isArray(state)?{...state,__mearl_layer__:layers.length}:state;try{history.pushState=function(...args){rawPushState(withDepth(args[0]),args[1],args[2])},history.replaceState=function(...args){rawReplaceState(withDepth(args[0]),args[1],args[2])}}catch{}}try{readDepth(history.state)===null&&history.replaceState({__mearl_layer__:0},"")}catch{}window.addEventListener("popstate",e=>{let depth=readDepth(e.state);if(rootContainerActive){if(pendingRootHistoryDepth){let expectedDepth=pendingRootHistoryDepth.depth;if(clearPendingRootHistoryDepth(),depth===expectedDepth)return;console.warn(TAG,"浏览器历史深度与 WebView 出栈事务不一致",{expectedDepth,actualDepth:depth})}if(depth===null)return;depth<layers.length?closeToDepth(depth,void 0,!1):depth>layers.length&&forwardToDepth(depth);return}if(pendingClose){if(depth!==null&&depth<layers.length){let{data}=pendingClose;clearPendingClose(),closeToDepth(depth,data,!0)}else if(pendingClose.retries>0)armPendingClose(pendingClose.data,pendingClose.retries-1);else{let{data}=pendingClose;clearPendingClose(),closeToDepth(layers.length-1,data,!0)}return}depth!==null&&(depth<layers.length?closeToDepth(depth,void 0,!1):depth>layers.length&&forwardToDepth(depth))})}function broadcastAppMessage(message){links.getBridgeProtocol().handleAppMessage(message);let targets=[rootFrame?.contentWindow??null,...layers.filter(layer=>!layer.closing).map(layer=>layer.frame.contentWindow)];for(let target of targets)if(!(!target||target===window))try{target.postMessage({source:SRC,type:"appMessage",message},"*")}catch{}}function closeMegaPop(popId,data){let index=layers.findIndex(layer=>layer.popId===popId&&!layer.closing);if(index<0)return!1;let closingDepth=layers.length-index;closeToDepth(index,data,!0);try{history.go(-closingDepth)}catch{}return!0}function resizeMegaPop(popId,params){let layer=layers.find(candidate=>candidate.popId===popId&&!candidate.closing);if(!layer?.overlay)return!1;if(params.maxHeight!==void 0){let maxHeight=numberParam(params.maxHeight,1-layer.overlay.topRatio,0,1);layer.overlay.topRatio=1-maxHeight,layer.animEl.style.height=`${maxHeight*100}%`}if(params.maxWidth!==void 0){let maxWidth=numberParam(params.maxWidth,1,0,1);layer.overlay.widthRatio=maxWidth,layer.animEl.style.width=`${maxWidth*100}%`,layer.animEl.style.left=`${(1-maxWidth)/2*100}%`,layer.animEl.style.right="auto"}return params.animated===!0&&(layer.animEl.style.transition="height 200ms ease, width 200ms ease, left 200ms ease"),!0}function executeContainerData(action,params){if(action==="sharedFileRead"||action==="sharedFileWrite"){let fileName=typeof params.fileName=="string"?params.fileName:"";if(!fileName)return{success:!1,value:"missing fileName"};if(action==="sharedFileRead")return{success:!0,value:{data:sharedFiles.get(fileName)??""}};let data=typeof params.data=="string"?params.data:String(params.data??"");return sharedFiles.set(fileName,data),{success:!0,value:{}}}if(action==="sharedDataGet"){let keys=Array.isArray(params.keys)?params.keys.filter(key=>typeof key=="string"):[],data={};for(let key of keys)sharedData.has(key)&&(data[key]=sharedData.get(key));return{success:!0,value:{data}}}if(action==="sharedDataSet"){if(!params.data||typeof params.data!="object"||Array.isArray(params.data))return{success:!1,value:"missing shared data"};for(let[key,value]of Object.entries(params.data))value==null?sharedData.delete(key):sharedData.set(key,value);return{success:!0,value:{}}}if(action==="megaBroadcast")return!params.message||typeof params.message!="object"||Array.isArray(params.message)?{success:!1,value:"missing broadcast message"}:(broadcastAppMessage(params.message),{success:!0,value:{}});if(action==="megaKVSnapshot")return{success:!0,value:{entries:megaKVSnapshot()}};if(action==="megaKVMutation"){let operation=typeof params.operation=="string"?params.operation:"",bizId=typeof params.bizId=="string"?params.bizId:"";if(!bizId)return{success:!1,value:"missing bizID"};let key=typeof params.key=="string"?params.key:"";if((operation==="set"||operation==="remove")&&!key)return{success:!1,value:"missing key"};if(operation==="set"){if(typeof params.value!="string")return{success:!1,value:"missing value"};let entries=megaKVStorage.get(bizId)??new Map;entries.set(key,params.value),megaKVStorage.set(bizId,entries)}else if(operation==="remove"){let entries=megaKVStorage.get(bizId);entries?.delete(key),entries?.size===0&&megaKVStorage.delete(bizId)}else if(operation==="clear")megaKVStorage.delete(bizId);else return{success:!1,value:"unsupported KVStorage operation"};return persistMegaKVStorage(),broadcastAppMessage({kind:"megaKVStorage",operation,bizId,key,value:params.value}),{success:!0,value:{}}}if(action==="legacyBroadcastCreate"){let instanceId=typeof params.instanceId=="string"?params.instanceId:"";return instanceId?(legacyBroadcastChannels.add(instanceId),{success:!0,value:{}}):{success:!1,value:"missing instanceId"}}if(action==="legacyBroadcastPost"){let instanceId=typeof params.instanceId=="string"?params.instanceId:"";return instanceId?legacyBroadcastChannels.has(instanceId)?(broadcastAppMessage({kind:"legacyBroadcast",instanceId,message:params.message}),{success:!0,value:{}}):{success:!1,value:"broadcast channel not found"}:{success:!1,value:"missing instanceId"}}if(action==="legacyBroadcastClose"){let instanceId=typeof params.instanceId=="string"?params.instanceId:"";return instanceId?(legacyBroadcastChannels.delete(instanceId),{success:!0,value:{}}):{success:!1,value:"missing instanceId"}}if(action==="megaPopClose"){let popId=typeof params.popId=="string"?params.popId:"";return popId?closeMegaPop(popId,params.result)?{success:!0,value:{}}:{success:!1,value:"popId not found"}:{success:!1,value:"missing popId"}}if(action==="megaPopResize"){let popId=typeof params.popId=="string"?params.popId:"";return popId?resizeMegaPop(popId,params)?{success:!0,value:{}}:{success:!1,value:"popId not found"}:{success:!1,value:"missing popId"}}return{success:!1,value:"unsupported container data action"}}function requestContainerData(action,params,onSuccess,onFailure){if(isTop){let result=executeContainerData(action,params);setTimeout(()=>result.success?onSuccess(result.value):onFailure(result.value),0);return}let requestId=++containerDataRequestSeq;containerDataCallbacks.set(requestId,{success:onSuccess,failure:onFailure});try{window.top?.postMessage({source:SRC,type:"containerDataRequest",requestId,action,params},"*")}catch(error48){containerDataCallbacks.delete(requestId),onFailure(error48 instanceof Error?error48.message:String(error48))}}function requestOpen(url2,callbackId,webdialog,params){let overlay=resolveOverlayPresentation(url2,params,webdialog),popBeforeOpen=requestsPopBeforeOpen(url2,params),popId=typeof params?.__mearlMegaPopId=="string"?params.__mearlMegaPopId:null;isTop?openLayer(url2,callbackId,overlay,window,!0,popId):window.top?.postMessage({source:SRC,type:"open",url:url2,callbackId,overlay,popBeforeOpen,popId},"*")}function requestClose(data){let payload;try{payload=data===void 0?void 0:JSON.parse(JSON.stringify(data))}catch{payload=void 0}isTop?requestCloseOnTop(payload):window.top?.postMessage({source:SRC,type:"close",data:payload},"*")}if(window.addEventListener("message",event=>{let msg=event.data;if(!(!msg||typeof msg!="object")){if(msg.source==="mearl-content"&&(msg.type==="APP_BRIDGE_SIMULATOR_VISIBILITY"||msg.type==="APP_BRIDGE_RUNTIME_RESPONSES")){if(!isTop||event.source!==window)return;if(msg.type==="APP_BRIDGE_SIMULATOR_VISIBILITY"&&typeof msg.hidden=="boolean"){simulatedPageHidden=msg.hidden,links.getBridgeProtocol().handlePageVisibility(msg.hidden);let lifecycleMessage={source:SRC,type:"simulatorVisibility",hidden:msg.hidden};rootFrame?.contentWindow?.postMessage(lifecycleMessage,"*");for(let layer of layers)layer.closing||layer.frame.contentWindow?.postMessage(lifecycleMessage,"*")}else if(msg.type==="APP_BRIDGE_RUNTIME_RESPONSES"&&msg.profile===config2.profile&&msg.responses&&typeof msg.responses=="object"&&!Array.isArray(msg.responses)){let responses=msg.responses;runtimeResponses={...runtimeResponses??{},...responses},links.getBridgeProtocol().applyRuntimeResponses(responses);let configMessage={source:SRC,type:"runtimeResponses",profile:config2.profile,responses};rootFrame?.contentWindow?.postMessage(configMessage,"*");for(let layer of layers)layer.closing||layer.frame.contentWindow?.postMessage(configMessage,"*")}return}if(msg.source===SRC){if(isTop){let sourceLayer=layerForWindow(event.source),sourceIsRoot=!!(rootFrame?.contentWindow&&rootFrame.contentWindow===event.source);if(!sourceLayer&&!sourceIsRoot)return;if(msg.type==="open"&&typeof msg.url=="string"){let rawOverlay=msg.overlay&&typeof msg.overlay=="object"?msg.overlay:void 0,overlay=rawOverlay?{topRatio:numberParam(rawOverlay.topRatio,.2,0,1),widthRatio:numberParam(rawOverlay.widthRatio,1,0,1),radius:numberParam(rawOverlay.radius,0,0,50),maskAlpha:numberParam(rawOverlay.maskAlpha,.3,0,1),tapClose:boolParam(rawOverlay.tapClose,!0)}:resolveOverlayPresentation(msg.url,void 0,!1),callbackId=typeof msg.callbackId=="number"?msg.callbackId:0,popId=typeof msg.popId=="string"&&msg.popId?msg.popId:null;msg.popBeforeOpen===!0&&sourceLayer?replaceLayer(sourceLayer,msg.url,callbackId,overlay,popId):openLayer(msg.url,callbackId,overlay,event.source??window,!0,popId)}else if(msg.type==="close")requestCloseOnTop(msg.data);else if(msg.type==="closeAll"){let gotoEvent=msg.gotoEvent===!0;if(gotoEvent&&sourceIsRoot&&layers.length===0&&msg.data!==void 0)try{event.source.postMessage({source:SRC,type:"resume",data:msg.data,storageId:null,callbackId:0,final:!0,gotoEvent:!0},"*")}catch{}else closeAllLayers(msg.data,gotoEvent)}else if(msg.type==="appMessageToOpener"&&sourceLayer){let target=sourceLayer.openerWin;if(target===window)links.getBridgeProtocol().handleAppMessage(msg.message);else try{target.postMessage({source:SRC,type:"appMessage",message:msg.message},"*")}catch{}}else if(msg.type==="containerDataRequest"&&typeof msg.requestId=="number"&&typeof msg.action=="string"&&msg.params&&typeof msg.params=="object"&&!Array.isArray(msg.params)&&event.source){let result=executeContainerData(msg.action,msg.params);try{event.source.postMessage({source:SRC,type:"containerDataResponse",requestId:msg.requestId,success:result.success,value:result.value},"*")}catch{}}else if(msg.type==="nativeBackResult"&&typeof msg.requestId=="number"&&typeof msg.handled=="boolean"&&event.source)finishNativeBack(msg.requestId,event.source,msg.handled);else if(msg.type==="urlChanged"&&typeof msg.url=="string"){let topLayer=layers[layers.length-1];if(sourceIsRoot&&!topLayer){rootBusinessUrl=msg.url;let mapped=mapUrlForSync(msg.url);if(mapped)try{history.replaceState({__mearl_layer__:0},"",mapped)}catch{}}else if(topLayer&&!topLayer.closing&&sourceLayer===topLayer){topLayer.url=msg.url,topLayer.titleBarStateExplicit&&topLayer.titleBarState&&cacheExplicitTitleBarState(topLayer,topLayer.titleBarState);let mapped=mapUrlForSync(msg.url);if(mapped)try{history.replaceState({__mearl_layer__:layers.length},"",mapped)}catch{}}}else if(msg.type==="title"&&typeof msg.title=="string"){let topLayer=layers[layers.length-1];if(sourceIsRoot&&!topLayer)try{document.title=msg.title,syncSimulatedTitleBar()}catch{}else if(topLayer&&sourceLayer===topLayer){document.title=msg.title;let state=resolvedTitleBarState(topLayer);topLayer.titleBarState={...state,title:msg.title},syncLayerViewport(topLayer,topLayer.titleBarState)}}else if(msg.type==="titleBarState"){let state=parseReportedTitleBarState(msg.state);if(state&&sourceIsRoot)links.getSystemBars().setPresentedRootTitleBarState(state);else if(state&&sourceLayer){let explicit=msg.explicit===!0;sourceLayer.titleBarStateReady=!0,explicit?(sourceLayer.titleBarState=state,sourceLayer.titleBarStateExplicit=!0,cacheExplicitTitleBarState(sourceLayer,state)):sourceLayer.titleBarStateExplicit||(sourceLayer.titleBarState=state);let resolvedState=sourceLayer.titleBarState??state;syncLayerViewport(sourceLayer,resolvedState)}}}else if(msg.type==="simulatorVisibility"&&typeof msg.hidden=="boolean"){if(event.source!==window.top)return;links.getBridgeProtocol().handlePageVisibility(msg.hidden)}else if(msg.type==="appMessage"){if(event.source!==window.top)return;links.getBridgeProtocol().handleAppMessage(msg.message)}else if(msg.type==="nativeBack"&&typeof msg.requestId=="number"){if(event.source!==window.top)return;let handled=links.getBridgeProtocol().handleNativeBack();window.top?.postMessage({source:SRC,type:"nativeBackResult",requestId:msg.requestId,handled},"*")}else if(msg.type==="containerDataResponse"&&typeof msg.requestId=="number"){if(event.source!==window.top)return;let callback=containerDataCallbacks.get(msg.requestId);if(!callback)return;containerDataCallbacks.delete(msg.requestId),msg.success===!0?callback.success(msg.value):callback.failure(msg.value)}else if(msg.type==="runtimeResponses"&&msg.profile===config2.profile&&msg.responses&&typeof msg.responses=="object"&&!Array.isArray(msg.responses)){if(event.source!==window.top)return;links.getBridgeProtocol().applyRuntimeResponses(msg.responses)}else if(msg.type==="resume"){if(event.source!==window.top)return;links.getBridgeProtocol().handleResume({data:msg.data,storageId:msg.storageId??null,callbackId:typeof msg.callbackId=="number"?msg.callbackId:0,final:msg.final===!0,gotoEvent:msg.gotoEvent===!0})}else event.source!==window.top&&window.top?.postMessage(msg,"*");return}pageTransport.handleMessage(msg)}}),!isTop&&isContainerFrame){let reportUrl=()=>{try{window.top?.postMessage({source:SRC,type:"urlChanged",url:restoreLayerBusinessUrl(location.href)},"*")}catch{}};try{let origPushState=history.pushState.bind(history),origReplaceState=history.replaceState.bind(history);history.pushState=function(...args){origPushState(...args),reportUrl()},history.replaceState=function(...args){origReplaceState(...args),reportUrl()},window.addEventListener("popstate",reportUrl),window.addEventListener("hashchange",reportUrl)}catch{}}if(isContainerFrame){let requestProxyLocationOpen=url2=>{if(links.getBridgeProtocol().handleMaybeScheme(url2))return!0;try{let current=new URL(restoreLayerBusinessUrl(location.href)),target=new URL(url2,current);return!/^https?:$/.test(target.protocol)||target.origin===current.origin&&target.pathname===current.pathname&&target.search===current.search?!1:(requestOpen(target.href,0,!1),!0)}catch{return!1}};Object.defineProperty(window,"__PROXY_LOCATION__",{value:{get href(){return location.href},set href(url2){requestProxyLocationOpen(url2)||(location.href=mapLayerFrameUrl(url2))},replace(url2){links.getBridgeProtocol().handleMaybeScheme(url2)||location.replace(mapLayerFrameUrl(url2))},assign(url2){requestProxyLocationOpen(url2)||location.assign(mapLayerFrameUrl(url2))}},writable:!1,configurable:!0})}if(isContainerFrame){document.addEventListener("click",event=>{let el=event.target;for(;el&&el.tagName!=="A";)el=el.parentElement;if(!el)return;let href=el.getAttribute("href");if(href){if(links.getBridgeProtocol().handleMaybeScheme(href)){event.preventDefault(),event.stopPropagation();return}/^https?:/i.test(href)&&el.getAttribute("target")==="_blank"&&(event.preventDefault(),event.stopPropagation(),requestOpen(href,0,!1))}},!0);let origOpen=window.open;window.open=function(url2,target,features){let urlStr=typeof url2=="string"?url2:url2 instanceof URL?url2.href:"";return links.getBridgeProtocol().handleMaybeScheme(urlStr)?null:/^https?:/i.test(urlStr)?(requestOpen(urlStr,0,!1),null):origOpen?origOpen.call(window,url2,target,features):null};try{let proto=Location.prototype,origAssign=proto.assign,origReplace=proto.replace;origAssign&&(proto.assign=function(url2){if(links.getBridgeProtocol().handleMaybeScheme(url2))return;let upgraded=location.protocol==="https:"&&url2.startsWith("http:")?"https:"+url2.slice(5):url2;origAssign.call(this,upgraded)}),origReplace&&(proto.replace=function(url2){if(links.getBridgeProtocol().handleMaybeScheme(url2))return;let upgraded=location.protocol==="https:"&&url2.startsWith("http:")?"https:"+url2.slice(5):url2;origReplace.call(this,upgraded)})}catch{}}return log3("容器环境已就绪",isTop?"(top)":isRootFrame?"(root)":isLayerFrame?"(layer)":"(iframe,仅桥)"),{getRootFrame:()=>rootFrame,getLayers:()=>layers,getClosingLayerCount:()=>closingLayerCount,requestOpen,requestClose,requestNativeBack,requestContainerData,closeAllLayers}}var APP_PROFILE_RUNTIME_FACTORIES={environment:installAppProfileEnvironment,containerStack:installAppProfileContainerStack,bridgeProtocol:installAppProfileBridgeProtocol,pageTransport:installAppProfilePageTransport,systemBars:installAppProfileSystemBars};function buildAppProfileRuntimeCallSource(configExpression){return`(${installAppProfileRuntime.toString()})(${configExpression},{environment:${installAppProfileEnvironment.toString()},pageTransport:${installAppProfilePageTransport.toString()},containerStack:${installAppProfileContainerStack.toString()},systemBars:${installAppProfileSystemBars.toString()},bridgeProtocol:${installAppProfileBridgeProtocol.toString()}})`}function installAppProfileRuntime(config2,factories=APP_PROFILE_RUNTIME_FACTORIES){let environment=factories.environment(config2);if(!environment)return;let pageTransport=factories.pageTransport(config2,environment),containerStack=factories.containerStack(config2,environment,{pageTransport,getSystemBars:()=>systemBars,getBridgeProtocol:()=>bridgeProtocol}),systemBars=factories.systemBars(config2,environment,{getRootFrame:containerStack.getRootFrame,getLayers:containerStack.getLayers,getClosingLayerCount:containerStack.getClosingLayerCount,requestClose:containerStack.requestClose,requestNativeBack:containerStack.requestNativeBack}),bridgeProtocol=factories.bridgeProtocol(config2,environment,{pageTransport,systemBars,requestOpen:containerStack.requestOpen,requestClose:containerStack.requestClose,requestCloseAll:containerStack.closeAllLayers,requestContainerData:containerStack.requestContainerData})}import https from"node:https";import http3 from"node:http";var TYPE_INTO_ELEMENT_SRC=typeIntoElement.toString(),CLICK_ELEMENT_VIA_JS_SRC=clickElementViaJS.toString(),GET_CLICK_COORDS_FROM_NODE_SRC=getClickCoordsFromNode.toString();function nodeFetch(urlStr,options={}){return new Promise((resolve3,reject)=>{let url2=new URL(urlStr),isHttps=url2.protocol==="https:",lib=isHttps?https:http3,{method="GET",headers={},body,timeoutMs=3e4}=options,req=lib.request({host:url2.hostname,port:url2.port||(isHttps?443:80),path:url2.pathname+url2.search,method,headers},res=>{let responseHeaders={};for(let[key,value]of Object.entries(res.headers))typeof value=="string"?responseHeaders[key]=value:Array.isArray(value)&&(responseHeaders[key]=value.join(", "));let chunks=[];res.on("data",chunk=>chunks.push(Buffer.from(chunk))),res.on("end",()=>{let bodyBuffer=Buffer.concat(chunks);resolve3({status:res.statusCode??0,statusText:res.statusMessage??"",headers:responseHeaders,body:bodyBuffer.toString("utf-8"),bodyBuffer})})});req.on("error",reject),req.setTimeout(timeoutMs,()=>{req.destroy(),reject(new Error(`Request timeout: ${urlStr}`))}),body&&req.write(body),req.end()})}async function getCookiesForUrl(session,targetUrl){let result=await session.client.sendCommand("Network.getCookies",{urls:[targetUrl]}),map2=new Map;for(let cookie of result.cookies??[])map2.set(cookie.name,cookie.value);return map2}function decodeTracknick(raw){if(!raw)return"";try{return decodeURIComponent(raw).replace(/\\u([0-9a-fA-F]{4})/g,(_match,hex3)=>String.fromCharCode(parseInt(hex3,16)))}catch{return raw}}function buildMultipartFormBody(fields){let boundary=`----mearl-${Date.now()}-${Math.random().toString(36).slice(2)}`,body=[...Object.entries(fields).map(([name,value])=>`--${boundary}\r
|
|
751
|
+
</style><div id="surface" data-platform="${config2.platform.toLowerCase()}" data-cutout="${String(hasDynamicIsland)}"><div id="status"><span id="time"></span><span id="device-cutout" aria-hidden="true"></span><span id="indicators" aria-hidden="true"><svg id="signal" viewBox="0 0 18 12"><rect x="0" y="8" width="3" height="4" rx="1"/><rect x="5" y="6" width="3" height="6" rx="1"/><rect x="10" y="3" width="3" height="9" rx="1"/><rect x="15" y="0" width="3" height="12" rx="1"/></svg><svg id="wifi" viewBox="1 3.8 22 17.2"><path d="M2 8.82a15 15 0 0 1 20 0"/><path d="M5 12.859a10 10 0 0 1 14 0"/><path d="M8.5 16.429a5 5 0 0 1 7 0"/><path d="M12 20h.01"/></svg><svg id="battery" viewBox="0 0 28 13"><rect id="battery-outline" x=".65" y=".65" width="23" height="11.7" rx="3.1"/><rect id="battery-level" x="2.35" y="2.35" width="19.6" height="8.3" rx="1.7"/><path id="battery-cap" d="M25 4.1c1.1.35 1.7 1.15 1.7 2.4s-.6 2.05-1.7 2.4z"/></svg></span></div></div>`;let surface=shadow.getElementById("surface"),time3=shadow.getElementById("time"),updateTime=()=>{let now=new Date;time3&&(time3.textContent=`${String(now.getHours()).padStart(2,"0")}:${String(now.getMinutes()).padStart(2,"0")}`)};return updateTime(),{root,surface,timeTimer:window.setInterval(updateTime,3e4)}},install=()=>{let titleBar=config2.titleBar;if(!titleBar||!isContainerFrame||!simulateSystemBars)return;let observeState=()=>{new MutationObserver(syncSimulatedTitleBar).observe(document.head??document.documentElement,{subtree:!0,childList:!0,characterData:!0,attributes:!0,attributeFilter:["content","value"]}),window.addEventListener("popstate",syncSimulatedTitleBar),window.addEventListener("hashchange",syncSimulatedTitleBar),document.readyState==="loading"&&document.addEventListener("DOMContentLoaded",syncSimulatedTitleBar,{once:!0});try{let pushState=history.pushState.bind(history),replaceState=history.replaceState.bind(history);history.pushState=function(...args){pushState(...args),syncSimulatedTitleBar()},history.replaceState=function(...args){replaceState(...args),syncSimulatedTitleBar()}}catch{}};if(!isTop){observeState(),syncSimulatedTitleBar();return}let mount=()=>{if(titleBarRoot||!document.body)return;let totalHeight=config2.statusBarHeight+titleBar.navigationBarHeight,navigationView=createNavigationBarView("root",host.requestNativeBack),statusView=createStatusBarView(),spacer=document.createElement("div");if(spacer.setAttribute("data-mearl-app-titlebar-spacer",""),spacer.style.cssText=`display:block;width:100%;height:${totalHeight}px;min-height:${totalHeight}px;flex:none;`,document.body.insertBefore(spacer,document.body.firstChild),document.body.append(navigationView.root,statusView.root),safeAreaInsets.bottom>0){let bottomRoot=document.createElement("div");bottomRoot.setAttribute("data-mearl-app-system-bottom",config2.profile),bottomRoot.style.cssText=`position:fixed;left:0;right:0;bottom:0;height:${safeAreaInsets.bottom}px;z-index:2147483600;box-sizing:border-box;pointer-events:none;color:#111111;`;let bottomShadow=bottomRoot.attachShadow({mode:"open"});bottomShadow.innerHTML=`<style>:host{all:initial}#surface{appearance:none;border:0;padding:0;width:166px;max-width:100%;height:24px;position:absolute;left:50%;bottom:0;transform:translateX(-50%);display:block;box-sizing:border-box;pointer-events:auto;color:#111;background:transparent;cursor:pointer;-webkit-tap-highlight-color:transparent}#surface:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}#indicator{position:absolute;left:50%;bottom:8px;transform:translateX(-50%);width:134px;height:5px;border-radius:999px;background:currentColor;opacity:.92;transition:transform 120ms ease,opacity 120ms ease}#surface:hover #indicator{opacity:1;transform:translateX(-50%) scaleX(1.05)}#surface[data-platform="android"] #indicator{bottom:6px;width:108px;height:4px;opacity:.82}</style><button id="surface" type="button" aria-label="打开桥模拟配置" title="桥模拟配置" data-platform="${config2.platform.toLowerCase()}"><span id="indicator" aria-hidden="true"></span></button>`,document.body.appendChild(bottomRoot),systemBottomRoot=bottomRoot,systemBottomSurface=bottomShadow.getElementById("surface"),systemBottomSurface?.addEventListener("click",()=>{window.postMessage({source:SRC,type:"showBridgeConfig",profile:config2.profile,actions:config2.actions},"*")})}rootTitleBarView=navigationView,systemStatusView=statusView,titleBarRoot=navigationView.root,titleBarSpacer=spacer,syncSimulatedTitleBar(),observeState()};document.body?mount():document.addEventListener("DOMContentLoaded",mount,{once:!0})},service={initialLayerTitleBarState,resolvedTitleBarState,parseReportedTitleBarState,setPresentedRootTitleBarState:state=>{presentedRootTitleBarState=state,syncSimulatedTitleBar()},markStateExplicit:()=>{titleBarStateExplicit=!0},applyNavigationBarState,applyStatusBarState,createNavigationBarView,destroyNavigationBarView:view=>view?.root.remove(),syncLayerViewport,syncActiveSystemBars,syncSimulatedTitleBar};return install(),service}function installAppProfilePageTransport(config2,environment){let{SRC,TAG,log:log3}=environment,appToast=null,appToastHideTimer=null,appToastRemoveTimer=null;function showAppToast(params){let p=params&&typeof params=="object"?params:{},messageValue=[p.message,p.msg,p.content,p.text].find(value=>typeof value=="string"&&value.trim().length>0);if(typeof messageValue!="string")return"missing message";let durationValue=Number(p.milliseconds??p.duration),duration3=Number.isFinite(durationValue)&&durationValue>0?durationValue:2e3,hideAfter=Math.min(6e4,Math.max(300,Math.round(duration3)));appToastHideTimer!==null&&window.clearTimeout(appToastHideTimer),appToastRemoveTimer!==null&&window.clearTimeout(appToastRemoveTimer);let toast=appToast?.isConnected===!0?appToast:document.createElement("div");return toast!==appToast&&(appToast=toast,toast.setAttribute("data-mearl-app-toast",""),toast.setAttribute("role","status"),toast.setAttribute("aria-live","polite"),Object.assign(toast.style,{position:"fixed",left:"50%",top:"50%",zIndex:"2147483647",maxWidth:"calc(100vw - 64px)",boxSizing:"border-box",padding:"14px 20px",borderRadius:"12px",background:"rgba(20, 20, 20, 0.88)",color:"#ffffff",fontFamily:'-apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif',fontSize:"16px",fontWeight:"400",lineHeight:"24px",textAlign:"center",whiteSpace:"pre-wrap",overflowWrap:"anywhere",pointerEvents:"none",opacity:"0",transform:"translate(-50%, -50%) scale(0.96)",transition:"opacity 180ms ease, transform 180ms ease"}),(document.body??document.documentElement).appendChild(toast)),toast.textContent=messageValue,toast.style.opacity="0",toast.style.transform="translate(-50%, -50%) scale(0.96)",toast.offsetWidth,toast.style.opacity="1",toast.style.transform="translate(-50%, -50%) scale(1)",appToastHideTimer=window.setTimeout(()=>{appToastHideTimer=null,toast.style.opacity="0",toast.style.transform="translate(-50%, -50%) scale(0.96)",appToastRemoveTimer=window.setTimeout(()=>{appToastRemoveTimer=null,appToast===toast&&(appToast=null),toast.remove()},180)},hideAfter),null}let bridgeRequestSeq=0,pendingMtop={},pendingMtopStreams={},pendingUserInfo={};function callMtop(params,succ,fail){let id=++bridgeRequestSeq;pendingMtop[id]={succ,fail};let post=params.post,rawTimeout=params.timeout??params.timer,timeout=typeof rawTimeout=="number"?rawTimeout:typeof rawTimeout=="string"&&rawTimeout.trim()!==""?Number(rawTimeout):void 0,payload={...params,data:params.data!==void 0?params.data:params.param??{},method:params.method??(post===!0||post===1||post==="1"||post==="true"?"POST":"GET"),env:params.env??(/(^|\.)wapa\.taobao\.com$/i.test(location.hostname)?"pre":"online"),...Number.isFinite(timeout)&&{timeout}};window.postMessage({source:SRC,type:"mtop",requestId:id,payload},"*"),log3("mtop 代发 →",params.api)}function callMtopAsync(params){return new Promise((resolve3,reject)=>callMtop(params,resolve3,reject))}function callMtopStream(params,succ,fail){let sessionId=typeof params.id=="string"?params.id:String(params.id??""),request=params.request&&typeof params.request=="object"?params.request:null;if(!sessionId||!request||typeof request.api!="string"){fail?.("invalid mtop_stream params");return}let requestId=++bridgeRequestSeq;pendingMtopStreams[requestId]={sessionId},window.postMessage({source:SRC,type:"mtopStream",requestId,payload:{...request,timeout:params.timeout,method:params.method??request.method,env:/(^|\.)wapa\.taobao\.com$/i.test(location.hostname)?"pre":"online"}},"*"),succ?.({}),log3("mtop 流式代发 →",request.api)}function callUserInfo(fallback,succ){if(fallback.userId){succ?.(fallback);return}let requestId=++bridgeRequestSeq,timer=setTimeout(()=>{let pending=pendingUserInfo[requestId];pending&&(delete pendingUserInfo[requestId],pending.succ?.(pending.fallback))},1e3);pendingUserInfo[requestId]={fallback,succ,timer},window.postMessage({source:SRC,type:"userInfo",requestId},"*")}function emitMtopStreamEvent(sessionId,eventType,data){let detail=data&&typeof data=="object"?{...data,eventType}:{data,eventType};document.dispatchEvent(new CustomEvent(`mtop_stream${sessionId}`,{detail}))}function createUploadId(){try{if(typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch{}return`${Date.now()}-${Math.random().toString(36).slice(2)}`}function pickDirectUploadTarget(response){if(!response||typeof response!="object")return null;let data=response.data;if(data?.success===!1)return null;let result=data?.result,target=Array.isArray(result?.urls)?result.urls[0]:void 0;if(!target||typeof target!="object")return null;let item=target;if(typeof item.put!="string"||!item.put||typeof item.get!="string"||!item.get)return null;let rawHeaders=item.putHeaders&&typeof item.putHeaders=="object"?item.putHeaders:{},putHeaders=Object.fromEntries(Object.entries(rawHeaders).map(([key,value])=>[key,String(value)]));return{put:item.put,get:item.get,putHeaders}}async function uploadImage(file2){let uploader=config2.imagePicker;if(!uploader)throw new Error("图片上传能力未配置");let env=/(^|\.)wapa\.taobao\.com$/i.test(location.hostname)?"pre":"online",response=await callMtopAsync({api:uploader.api,v:uploader.version,method:"POST",env,timeout:6e4,data:{fcId:uploader.fcId,fcGroup:uploader.fcGroup,fcName:uploader.uploadUrlFunction,fcData:JSON.stringify({requestType:"url",mimes:[file2.type||"image/jpeg"],prefix:uploader.prefix,region:uploader.region,uploadNumber:1}),fcConfig:JSON.stringify({timeout:6e4,disasterRecover:!0})}}),target=pickDirectUploadTarget(response);if(!target)throw new Error("获取图片上传地址失败");let uploadUrl=`${target.put}${target.put.includes("?")?"&":"?"}getAvatar=1`,uploadResponse=await fetch(uploadUrl,{method:"PUT",headers:target.putHeaders,body:file2});if(uploadResponse.status!==200)throw new Error(`图片直传失败: HTTP ${uploadResponse.status}`);return target.get}function openImagePicker(callbackCommandFn){let input=document.createElement("input");input.type="file",input.accept="image/*",input.style.display="none";let settled=!1,finish=()=>{settled=!0,input.remove()};input.addEventListener("cancel",finish,{once:!0}),input.addEventListener("change",()=>{let file2=input.files?.[0];if(!file2){finish();return}if(!file2.type.startsWith("image/")){finish(),console.error(TAG,"仅支持选择图片文件");return}uploadImage(file2).then(pic=>{typeof callbackCommandFn=="function"&&callbackCommandFn({pic,uuid:createUploadId(),timeStamp:Date.now()}),log3("图片选择并上传完成:",pic)}).catch(error48=>console.error(TAG,"图片上传失败:",error48)).finally(finish)},{once:!0}),(document.body??document.documentElement).appendChild(input),input.click(),window.addEventListener("focus",()=>{setTimeout(()=>{!settled&&!input.files?.length&&finish()},1e3)},{once:!0})}function showPaymentDialog(api,params,succeed,failed){let overlay=document.createElement("div");overlay.setAttribute("data-mearl-payment-dialog","true"),Object.assign(overlay.style,{position:"fixed",inset:"0",zIndex:"2147483647",display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)"});let card=document.createElement("div");Object.assign(card.style,{background:"#fff",borderRadius:"12px",padding:"24px",width:"300px",textAlign:"center",fontFamily:"system-ui, sans-serif"});let title=document.createElement("div");Object.assign(title.style,{fontSize:"17px",fontWeight:"600",marginBottom:"8px"}),title.textContent="支付确认";let desc=document.createElement("div");Object.assign(desc.style,{fontSize:"14px",color:"#666",marginBottom:"20px"}),desc.textContent=`模拟 ${api} 支付,请选择操作`;let btnRow=document.createElement("div");Object.assign(btnRow.style,{display:"flex",gap:"12px"});let btnBase=(text,bg,color,action)=>{let btn=document.createElement("button");return btn.textContent=text,btn.setAttribute("data-mearl-action",action),Object.assign(btn.style,{flex:"1",padding:"10px 0",border:"none",borderRadius:"8px",fontSize:"15px",fontWeight:"500",cursor:"pointer",background:bg,color}),btn},confirmBtn=btnBase("完成支付","#1677ff","#fff","payment-confirm"),cancelBtn=btnBase("取消支付","#f5f5f5","#333","payment-cancel"),cleanup=()=>{overlay.remove()};confirmBtn.addEventListener("click",()=>{cleanup(),log3("用户完成支付",api),succeed({ResultStatus:"9000",resultStatus:"9000"})}),cancelBtn.addEventListener("click",()=>{cleanup(),log3("用户取消支付",api),failed({ResultStatus:"6001",resultStatus:"6001"})}),btnRow.appendChild(cancelBtn),btnRow.appendChild(confirmBtn),card.appendChild(title),card.appendChild(desc),card.appendChild(btnRow),overlay.appendChild(card),(document.body??document.documentElement).appendChild(overlay)}function handleMessage(msg){if(msg.source==="mearl-content"&&msg.type==="APP_BRIDGE_MTOP_RESPONSE"){let pending=pendingMtop[msg.requestId];if(!pending)return!0;delete pendingMtop[msg.requestId];let result=msg.result;return result?.success?pending.succ?.(result.response):pending.fail?.(result?.error??"mtop delegate failed"),!0}if(msg.source==="mearl-content"&&msg.type==="APP_BRIDGE_USER_INFO_RESPONSE"){let requestId=msg.requestId,pending=pendingUserInfo[requestId];if(!pending)return!0;delete pendingUserInfo[requestId],clearTimeout(pending.timer);let result=msg.result,response=result?.success&&result.response&&typeof result.response=="object"?result.response:{};return pending.succ?.({...pending.fallback,...response}),!0}if(msg.source==="mearl-content"&&msg.type==="APP_BRIDGE_MTOP_STREAM_EVENT"){let requestId=msg.requestId,pending=pendingMtopStreams[requestId];if(!pending)return!0;let eventType=msg.eventType;return emitMtopStreamEvent(pending.sessionId,eventType,msg.data),(eventType==="onFinish"||eventType==="onError")&&delete pendingMtopStreams[requestId],!0}return!1}return{showAppToast,callMtop,callMtopStream,callUserInfo,openImagePicker,showPaymentDialog,handleMessage}}function installAppProfileBridgeProtocol(config2,environment,host){let{w,SRC,TAG,isTop,log:log3}=environment,{pageTransport,systemBars,requestOpen,requestClose,requestCloseAll,requestContainerData}=host,{showAppToast,callMtop,callMtopStream,callUserInfo,openImagePicker,showPaymentDialog}=pageTransport,{applyNavigationBarState,applyStatusBarState,syncSimulatedTitleBar}=systemBars,NOT_IMPLEMENTED_PAYLOAD=JSON.stringify({ret:["HY_FAILED"],msg:"not implemented"}),FPT_STORAGE_KEY=`__mearl_app_fpt__:${config2.profile}`,CALENDAR_STORAGE_KEY=`__mearl_app_calendar_events__:${config2.profile}`,unsupportedNativeInputNotified=!1,stopNetworkQualityMonitor=null,simulatedPageHidden=!1,simulatedVisibilityInstalled=!1,notificationListeners=new Map,megaListenerSeq=0,megaBroadcastListeners=new Map,megaLifeCycleListeners=new Set,megaPageCloseListeners=new Set,megaSystemBackListener=null,megaKVMutationVersion=0,MEGA_KV_TOTAL_SIZE=5*1024*1024,MEGA_KV_STORAGE_KEY=`__mearl_mega_kv__:${config2.profile}`;function readMegaKVStorage(){let storage=new Map;try{let parsed=JSON.parse(localStorage.getItem(MEGA_KV_STORAGE_KEY)??"{}");if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return storage;for(let[bizId,rawEntries]of Object.entries(parsed)){if(!rawEntries||typeof rawEntries!="object"||Array.isArray(rawEntries))continue;let entries=new Map;for(let[key,value]of Object.entries(rawEntries))typeof value=="string"&&entries.set(key,value);storage.set(bizId,entries)}}catch{}return storage}let megaKVStorage=readMegaKVStorage();function megaKVSnapshot(){let snapshot={};for(let[bizId,values]of megaKVStorage)snapshot[bizId]=Object.fromEntries(values);return snapshot}function persistMegaKVStorage(){try{localStorage.setItem(MEGA_KV_STORAGE_KEY,JSON.stringify(megaKVSnapshot()))}catch{}}function replaceMegaKVStorage(value){if(!(!value||typeof value!="object"||Array.isArray(value))){megaKVStorage.clear();for(let[bizId,rawEntries]of Object.entries(value)){if(!rawEntries||typeof rawEntries!="object"||Array.isArray(rawEntries))continue;let entries=new Map;for(let[key,entryValue]of Object.entries(rawEntries))typeof entryValue=="string"&&entries.set(key,entryValue);megaKVStorage.set(bizId,entries)}persistMegaKVStorage()}}function applyMegaKVMutation(payload){let operation=typeof payload.operation=="string"?payload.operation:"",bizId=typeof payload.bizId=="string"?payload.bizId:"",key=typeof payload.key=="string"?payload.key:"";if(bizId){if(operation==="set"&&key&&typeof payload.value=="string"){let entries=megaKVStorage.get(bizId)??new Map;entries.set(key,payload.value),megaKVStorage.set(bizId,entries)}else if(operation==="remove"&&key){let entries=megaKVStorage.get(bizId);entries?.delete(key),entries?.size===0&&megaKVStorage.delete(bizId)}else if(operation==="clear")megaKVStorage.delete(bizId);else return;megaKVMutationVersion+=1,persistMegaKVStorage()}}function emitMegaCallback(callback,value){callback&&setTimeout(()=>callback(value),0)}function megaBroadcastBizId(value){return typeof value=="string"&&value?value:"__MEGA_GLOBAL_MESSAGE__"}function dispatchMegaBroadcast(payload){let bizId=megaBroadcastBizId(payload.bizId),eventName=typeof payload.eventName=="string"?payload.eventName:"";if(eventName)for(let listener of Array.from(megaBroadcastListeners.values()))listener.bizId!==bizId||listener.eventName!==eventName||(listener.once&&megaBroadcastListeners.delete(listener.id),emitMegaCallback(listener.callback,{statusCode:1,type:"onEvent",data:{detail:payload.detail}}),listener.once&&emitMegaCallback(listener.callback,{statusCode:99,type:"finish"}))}let documentPrototype=typeof Document=="function"?Document.prototype:null,nativeHiddenDescriptor=documentPrototype?Object.getOwnPropertyDescriptor(documentPrototype,"hidden"):void 0,nativeVisibilityDescriptor=documentPrototype?Object.getOwnPropertyDescriptor(documentPrototype,"visibilityState"):void 0;function installSimulatedVisibilityState(){if(!simulatedVisibilityInstalled){simulatedVisibilityInstalled=!0;try{Object.defineProperty(document,"hidden",{configurable:!0,get:()=>simulatedPageHidden||!!(nativeHiddenDescriptor?.get?.call(document)??!1)}),Object.defineProperty(document,"visibilityState",{configurable:!0,get:()=>simulatedPageHidden?"hidden":nativeVisibilityDescriptor?.get?.call(document)??"visible"})}catch{}}}function dispatchPageTransitionEvent(type){try{let event=typeof PageTransitionEvent=="function"?new PageTransitionEvent(type,{persisted:!1}):new Event(type);window.dispatchEvent(event)}catch{}}function dispatchActiveEvents(){for(let name of config2.activeEvents)try{document.dispatchEvent(new Event(name))}catch{}}function handlePageVisibility(hidden){if(hidden===simulatedPageHidden)return;installSimulatedVisibilityState(),simulatedPageHidden=hidden;let lifeCycleType=hidden?"onPageDisappear":"onPageAppear";for(let callback of megaLifeCycleListeners)emitMegaCallback(callback,{statusCode:1,type:lifeCycleType,data:{pageId:location.href}});try{document.dispatchEvent(new Event("visibilitychange"))}catch{}if(hidden){try{window.dispatchEvent(new Event("blur"))}catch{}dispatchPageTransitionEvent("pagehide");return}dispatchPageTransitionEvent("pageshow");try{window.dispatchEvent(new Event("focus"))}catch{}dispatchActiveEvents()}function resolveWindowFunction(path23){let parts=path23.split(".").filter(Boolean),owner=w;for(let index=0;index<parts.length-1;index+=1){let next=owner[parts[index]];if(!next||typeof next!="object")return null;owner=next}let fn=owner[parts[parts.length-1]];return typeof fn=="function"?fn.bind(owner):null}function handleNativeBack(){let megaHandled=!1;for(let callback of megaPageCloseListeners)megaHandled=!0,emitMegaCallback(callback,{statusCode:1,type:"onClose",data:{}});if(megaSystemBackListener&&(megaHandled=!0,emitMegaCallback(megaSystemBackListener,{statusCode:1,type:"onSuccess",data:{}})),megaHandled)return!0;let nativeBack=config2.nativeBack;if(!nativeBack)return!1;if(nativeBack.handler){let handler=resolveWindowFunction(nativeBack.handler);if(!handler)return!1;try{return handler(),!0}catch{return!1}}let controlled=!1;if(nativeBack.controlFunction){let control=resolveWindowFunction(nativeBack.controlFunction);if(!control)return!1;try{controlled=control()===!0}catch{return!1}if(!controlled)return!1}if(!nativeBack.event)return controlled;try{let event=new Event(nativeBack.event,{cancelable:!0});return document.dispatchEvent(event),controlled||event.defaultPrevented}catch{return controlled}}function handleAppMessage(message){if(!message||typeof message!="object")return;let payload=message;if(payload.kind==="megaBroadcast"){dispatchMegaBroadcast(payload);return}if(payload.kind==="megaKVStorage"){applyMegaKVMutation(payload);return}if(payload.kind==="legacyBroadcast"&&typeof payload.instanceId=="string"){try{let event=new CustomEvent(`Broadcast.Message.${payload.instanceId}`,{detail:payload.message});Object.defineProperty(event,"param",{configurable:!0,value:payload.message}),document.dispatchEvent(event)}catch{}return}if(payload.kind==="notification"&&typeof payload.name=="string"){let listener=notificationListeners.get(payload.name);listener&&setTimeout(()=>listener(payload.data),0);return}if(!(payload.kind!=="message"||!config2.messageEvent))try{document.dispatchEvent(new CustomEvent(config2.messageEvent,{detail:{data:payload.data}}))}catch{}}function sendAppMessage(message){if(isTop){handleAppMessage(message);return}window.top?.postMessage({source:SRC,type:"appMessageToOpener",message},"*")}function applyRuntimeResponses(responses){let current=config2.actions.responses??{};for(let[api,response]of Object.entries(responses))!response||typeof response!="object"||Array.isArray(response)||(current[api]=response);config2.actions.responses=current}function parseFpt(value){let entries=[],normalized=value.trim();if(!normalized)return entries;let pattern=/([0-9A-Za-z._-]+)\(([0-9A-Za-z._-]+)\)/g,consumed="";for(let match of normalized.matchAll(pattern))consumed+=match[0],entries.push([match[1],match[2]]);return consumed===normalized?entries:[]}function setFptEntry(entries,key,value){entries.delete(key),entries.set(key,value)}function readInitialFptEntries(){let entries=new Map;try{for(let[key,value]of parseFpt(sessionStorage.getItem(FPT_STORAGE_KEY)??""))setFptEntry(entries,key,value)}catch{}try{let currentFpt=new URL(location.href).searchParams.get("fpt")??"";for(let[key,value]of parseFpt(currentFpt))setFptEntry(entries,key,value)}catch{}return entries}let fptEntries=readInitialFptEntries();function serializeFpt(entries){return Array.from(entries,([key,value])=>`${key}(${value})`).join("")}function persistFpt(){try{let value=serializeFpt(fptEntries);value?sessionStorage.setItem(FPT_STORAGE_KEY,value):sessionStorage.removeItem(FPT_STORAGE_KEY)}catch{}}function decorateUrlWithFpt(rawUrl){if(fptEntries.size===0)return rawUrl;try{let url2=new URL(rawUrl,location.href);if(url2.protocol!=="http:"&&url2.protocol!=="https:")return rawUrl;let merged=new Map(fptEntries);for(let[key,value]of parseFpt(url2.searchParams.get("fpt")??""))setFptEntry(merged,key,value);return url2.searchParams.set("fpt",serializeFpt(merged)),url2.href}catch{return rawUrl}}function classify(api){let a=config2.actions;return a.open.includes(api)?"open":a.close.includes(api)?"close":a.title.includes(api)?"title":a.navigationBar?.includes(api)?"navigationBar":a.statusBar?.includes(api)?"statusBar":a.systemInfo.includes(api)?"systemInfo":a.mtop.includes(api)?"mtop":a.kvGet?.includes(api)?"kvGet":a.kvSet?.includes(api)?"kvSet":a.kvDelete?.includes(api)?"kvDelete":a.pageContext?.includes(api)?"pageContext":a.responses&&Object.prototype.hasOwnProperty.call(a.responses,api)?"response":a.behaviors&&Object.prototype.hasOwnProperty.call(a.behaviors,api)?a.behaviors[api]:a.noop.includes(api)?"noop":"unknown"}function pickUrl(params){if(!params||typeof params!="object")return null;let p=params,candidates=[p.url,p.data?.url,p.param?.url,p.value?.params?.url];for(let c of candidates)if(typeof c=="string"&&c)return c;return null}function pickCloseData(params){if(params&&typeof params=="object"){let p=params;if("data"in p&&p.data!==void 0)return p.data;if(Object.keys(p).length>0)return p}}function decodeCookieValue2(raw){let value=raw;for(let i=0;i<2;i+=1)try{let decoded=decodeURIComponent(value);if(decoded===value)break;value=decoded}catch{break}return value.replace(/\\u([0-9a-f]{4})/gi,(_match,hex3)=>String.fromCharCode(Number.parseInt(hex3,16)))}function readCookie(name){let prefix=`${name}=`,pair=document.cookie.split(";").map(value=>value.trim()).find(value=>value.startsWith(prefix));return pair?decodeCookieValue2(pair.slice(prefix.length)):""}function readUserCookie(name){let pageUserCookie=w.userCookie;if(!pageUserCookie||typeof pageUserCookie!="object")return"";let value=pageUserCookie[name];return typeof value=="string"?decodeCookieValue2(value):""}function readFirstUserCookie(names){for(let name of names){let value=readCookie(name)||readUserCookie(name);if(value&&value!=="null")return value}return""}let cbSeq=0,callbacks={};function stashCallback(fn){if(typeof fn!="function")return 0;let id=++cbSeq;return callbacks[id]=fn,id}function extractQuery(url2,param){let q=url2.indexOf("?");if(q===-1)return null;for(let pair of url2.slice(q+1).split("&")){let eq=pair.indexOf("=");if(eq>0&&pair.slice(0,eq)===param)return pair.slice(eq+1)}return null}function resolveSchemeValue(raw,depth){if(depth>3)return null;let value=raw;try{value=decodeURIComponent(raw)}catch{}if(value.startsWith("{"))try{let found=pickUrl(JSON.parse(value));if(!found)return null;value=found}catch{return null}if(/^https?:/i.test(value))return value;if(/^[a-z][a-z0-9+.-]*:/i.test(value))return mapScheme(value,depth+1);let nestedUrl=extractQuery(value,"url");return nestedUrl?resolveSchemeValue(nestedUrl,depth+1):null}function mapScheme(url2,depth=0){if(depth>3)return null;let lower=url2.toLowerCase();for(let rule of config2.schemes){if(!lower.startsWith(rule.match))continue;if(rule.targetPath){let suffix=url2.slice(rule.match.length);if(suffix&&!suffix.startsWith("?")&&!suffix.startsWith("#"))continue;try{let source=new URL(url2),origin=location.origin;if(rule.targetHostPrefix){let hostname3=location.hostname.toLowerCase(),domainSuffix=hostname3==="wapa.taobao.com"||hostname3.endsWith(".wapa.taobao.com")?"wapa.taobao.com":hostname3==="m.taobao.com"||hostname3.endsWith(".m.taobao.com")?"m.taobao.com":"";domainSuffix&&(origin=`https://${rule.targetHostPrefix}.${domainSuffix}`)}let target=new URL(rule.targetPath,`${origin}/`);target.search=source.search,target.hash=source.hash;for(let[key,value]of Object.entries(rule.targetParams??{}))target.searchParams.has(key)||target.searchParams.set(key,value);return target.href}catch{return null}}if(!rule.param)continue;let raw=extractQuery(url2,rule.param);return raw?resolveSchemeValue(raw,depth):null}return null}function matchesImagePickerScheme(url2){let lower=url2.toLowerCase();return config2.imagePicker?.schemes.some(scheme=>lower.startsWith(scheme))===!0}function handleMaybeScheme(url2){if(typeof url2!="string"||!url2||!/^[a-z][a-z0-9+.-]*:/i.test(url2)||/^(https?|about|blob|data|javascript):/i.test(url2))return!1;let mapped=mapScheme(url2);return mapped?(log3("scheme 映射为 H5 open:",url2,"→",mapped),requestOpen(decorateUrlWithFpt(mapped),0,!1)):log3("外部 scheme 已拦截(真机表现为唤端):",url2),!0}function handleResume(msg){let{data,storageId,callbackId,final,gotoEvent}=msg;if(gotoEvent&&dispatchGotoEvent(data),callbackId&&callbacks[callbackId]){try{callbacks[callbackId]({backdata:data})}catch(e){console.error(TAG,"callbackCommand 执行失败",e)}final&&delete callbacks[callbackId]}if(data&&typeof data=="object"&&storageId)try{let d={...data};d.__$data=!0,d.__$storageId=String(storageId),localStorage.setItem("XPI_BACK_LISTENER_DATA_STORAGE",JSON.stringify(d))}catch{}simulatedPageHidden?handlePageVisibility(!1):dispatchActiveEvents()}function dispatchGotoEvent(data){if(data!==void 0)try{document.dispatchEvent(new CustomEvent("WV.GotoEvent",{detail:{data}}))}catch{}}function sendUserTrack(params){if(!params||typeof params!="object")return;let p=params,logkey=typeof p.logkey=="string"?p.logkey:"",gmkey=typeof p.gmkey=="string"?p.gmkey:typeof p.event=="string"?p.event:"",gokey=typeof p.gokey=="string"?p.gokey:"";if(!/^\/[0-9A-Za-z._/-]+$/.test(logkey)||!/^[0-9A-Za-z_-]+$/.test(gmkey))return;let pageWindow=w,aplus=pageWindow.goldlog??pageWindow.aplus;if(typeof aplus?.send!="function")return;let configuredHost=aplus.getMetaInfo?.("aplus-rhost-g"),host2=(typeof configuredHost=="string"?configuredHost:"gm.mmstat.com").replace(/^https?:\/\//i,"").replace(/^\/\//,"").split("/")[0];if(!(!host2||!/^[0-9A-Za-z.-]+$/.test(host2)))try{aplus.send(`//${host2}${logkey}`,`gmkey=${encodeURIComponent(gmkey)}&gokey=${gokey}&ts=${Date.now()}`,"GET")}catch{}}function readNetworkState(){let connection=navigator.connection;return navigator.onLine?connection?.type==="wifi"?"wifi":connection?.effectiveType??"unknown":"fail"}function networkTypeNumber(state){return{wifi:2,"slow-2g":3,"2g":3,"3g":4,"4g":5,"5g":6,fail:7}[state]??0}function calendarTimestamp(value){if(typeof value=="number"&&Number.isFinite(value))return value;if(typeof value!="string"||!value.trim())return null;let numeric=Number(value);if(Number.isFinite(numeric)&&numeric>0)return numeric;let parsed=Date.parse(value);return Number.isFinite(parsed)?parsed:null}function calendarEventFromParams(params){let p=params&&typeof params=="object"?params:{},stringValue=(...values)=>values.find(value=>typeof value=="string")??"";return{title:stringValue(p.calendar_title,p.title),startTime:calendarTimestamp(p.calendar_start_ms??p.start_time??p.calendar_start_datetime),endTime:calendarTimestamp(p.calendar_end_ms??p.end_time??p.calendar_end_datetime),url:stringValue(p.calendar_url,p.url),note:stringValue(p.calendar_note,p.note),location:stringValue(p.calendar_location,p.location)}}function readCalendarEvents(){try{let parsed=JSON.parse(localStorage.getItem(CALENDAR_STORAGE_KEY)??"[]");return Array.isArray(parsed)?parsed.filter(event=>event!==null&&typeof event=="object"&&typeof event.title=="string"):[]}catch{return[]}}function writeCalendarEvents(events){try{return localStorage.setItem(CALENDAR_STORAGE_KEY,JSON.stringify(events)),!0}catch{return!1}}function sameCalendarEvent(stored,candidate){return candidate.url?stored.url===candidate.url:!!candidate.title&&stored.title===candidate.title&&(candidate.startTime===null||stored.startTime===candidate.startTime)&&(candidate.endTime===null||stored.endTime===candidate.endTime)}function calendarEventResponse(event){return{title:event.title,start_time:event.startTime,end_time:event.endTime,url:event.url,note:event.note,location:event.location}}function dispatch(api,params,onSuccess,onFailure,callbackCommandFn){let succeed=value=>{onSuccess&&setTimeout(()=>onSuccess(value),0)},failed=reason=>{onFailure&&setTimeout(()=>onFailure(reason),0)},kind=classify(api),silent=config2.actions.silent?.includes(api)===!0;if(silent||log3("桥调用",api,`(${kind})`,params??""),kind==="open"||kind==="navigate"){let p=params&&typeof params=="object"?params:{},navigationData=p.data&&typeof p.data=="object"?p.data:void 0;if(kind==="navigate"&&navigationData?.type==="back"){isTop?requestCloseAll(navigationData.data,!0)||dispatchGotoEvent(navigationData.data):window.top?.postMessage({source:SRC,type:"closeAll",data:navigationData.data,gotoEvent:!0},"*"),succeed({});return}let url2=pickUrl(params);if(!url2){failed("missing url");return}if(matchesImagePickerScheme(url2)){openImagePicker(callbackCommandFn),succeed({});return}let wd=p.useWebdialog===!0||p.useWebdialog==="true"||p.useWebdialog===1||p.useWebdialog==="1";requestOpen(decorateUrlWithFpt(url2),stashCallback(callbackCommandFn),wd,p),succeed({});return}if(kind==="closeAll"){isTop?requestCloseAll(void 0):window.top?.postMessage({source:SRC,type:"closeAll"},"*"),succeed({});return}if(kind==="closeBackData"){let p=params&&typeof params=="object"?params:{};requestClose(Object.prototype.hasOwnProperty.call(p,"backdata")?p.backdata:pickCloseData(p)),succeed({});return}if(kind==="close"){requestClose(pickCloseData(params)),succeed({});return}if(kind==="postMessage"){let p=params&&typeof params=="object"?params:{};sendAppMessage({kind:"message",data:p.data??p}),succeed({});return}if(kind==="notifySubscribe"){let p=params&&typeof params=="object"?params:{};if(typeof p.name!="string"||!p.name){failed("missing notification name");return}onSuccess&¬ificationListeners.set(p.name,onSuccess);return}if(kind==="notifyUnsubscribe"){let p=params&&typeof params=="object"?params:{};typeof p.name=="string"&¬ificationListeners.delete(p.name),succeed({});return}if(kind==="notifyPost"){let p=params&&typeof params=="object"?params:{};if(typeof p.name!="string"||!p.name){failed("missing notification name");return}sendAppMessage({kind:"notification",name:p.name,data:p.data}),succeed({});return}if(kind==="sharedFileRead"||kind==="sharedFileWrite"||kind==="sharedDataGet"||kind==="sharedDataSet"){requestContainerData(kind,params&&typeof params=="object"?params:{},succeed,failed);return}if(kind==="legacyBroadcastCreate"||kind==="legacyBroadcastPost"||kind==="legacyBroadcastClose"){requestContainerData(kind,params&&typeof params=="object"?params:{},succeed,failed);return}if(kind==="title"){let title=params&&typeof params=="object"?params.title??params.name:void 0;if(typeof title=="string"&&title){systemBars.markStateExplicit();try{document.title=title,syncSimulatedTitleBar()}catch{}isTop||window.top?.postMessage({source:SRC,type:"title",title},"*")}succeed({});return}if(kind==="navigationBar"){applyNavigationBarState(api,params),succeed({});return}if(kind==="statusBar"){applyStatusBarState(params),succeed({});return}if(kind==="systemInfo"){let model=config2.globals.__DEVICE_MODEL__||"iPhone";succeed({language:config2.language,model,systemVersion:config2.systemVersion,statusBarHeight:config2.statusBarHeight,platform:config2.platform,brand:config2.platform==="iOS"?"Apple":"Android",client_version:config2.globals.__APP_VERSION__??"",client_type:config2.clientType});return}if(kind==="mtop"){callMtop(params??{},onSuccess,onFailure);return}if(kind==="mtopStream"){callMtopStream(params??{},succeed,failed);return}if(kind==="kvGet"||kind==="kvSet"||kind==="kvDelete"){let p=params&&typeof params=="object"?params:{},key=typeof p.key=="string"?p.key:"";if(!key){failed("missing key");return}try{let storageKey=`__mearl_app_kv__:${key}`;if(kind==="kvGet"){let stored=localStorage.getItem(storageKey);stored!==null?succeed(stored):failed(JSON.stringify({ret:["HY_FAILED"],msg:"key not found"}))}else if(kind==="kvSet"){let value=typeof p.value=="string"?p.value:p.value===void 0?"":JSON.stringify(p.value);localStorage.setItem(storageKey,value),succeed({})}else localStorage.removeItem(storageKey),succeed({})}catch{failed(JSON.stringify({ret:["HY_FAILED"],msg:"kv storage unavailable"}))}return}if(kind==="pageContext"){succeed({pageContext:void 0});return}if(kind==="memoryGet"||kind==="memorySet"||kind==="memoryDelete"){let p=params&&typeof params=="object"?params:{},key=typeof p.key=="string"?p.key:"";if(!key){failed({error_message:"missing key"});return}try{let storageKey=`__mearl_app_memory__:${key}`;if(kind==="memoryGet"){let value=sessionStorage.getItem(storageKey);succeed(value===null?{}:{value})}else if(kind==="memorySet"){let value=typeof p.value=="string"?p.value:p.value===void 0?"":JSON.stringify(p.value);sessionStorage.setItem(storageKey,value),succeed({key,success:!0})}else sessionStorage.removeItem(storageKey),succeed({key,success:!0})}catch{failed({error_message:"memory cache unavailable"})}return}if(kind==="availabilityMap"){let p=params&&typeof params=="object"?params:{},channels=Array.isArray(p.data)?p.data.filter(value=>typeof value=="string"):[];succeed({res:"success",data:Object.fromEntries(channels.map(channel=>[channel,!1]))});return}if(kind==="userInfo"){let userId=readFirstUserCookie(["unb"]),userName=readFirstUserCookie(["_w_tb_nick","_nk_","snk","tracknick"]);callUserInfo({...userId&&{userId},...userName&&{userName}},succeed);return}if(kind==="networkInfo"){let state=readNetworkState();if(api==="WVNetwork.getNetworkType"){succeed({type:{wifi:"WIFI","slow-2g":"2G","2g":"2G","3g":"3G","4g":"4G"}[state]??"UNKNOWN"});return}if(config2.profile==="alipay"||config2.profile==="koubei"){succeed({networkAvailable:state!=="fail",networkType:{wifi:"WIFI","slow-2g":"2G","2g":"2G","3g":"3G","4g":"4G",fail:"NOTREACHABLE"}[state]??"UNKNOWN"});return}let type=networkTypeNumber(state);succeed({type,state:state==="slow-2g"?"2g":state});return}if(kind==="networkQualityMonitor"){let p=params&&typeof params=="object"?params:{},action=typeof p.action=="string"?p.action:"";if(action==="add_notify_network_quality"){if(!stopNetworkQualityMonitor){let notify=()=>{try{document.dispatchEvent(new CustomEvent("WV.NETWORK_TYPE_CHANGED",{detail:{new_network_type:networkTypeNumber(readNetworkState())}}))}catch{}},connection=navigator.connection;window.addEventListener("online",notify),window.addEventListener("offline",notify),connection?.addEventListener?.("change",notify),stopNetworkQualityMonitor=()=>{window.removeEventListener("online",notify),window.removeEventListener("offline",notify),connection?.removeEventListener?.("change",notify)}}succeed({});return}if(action==="remove_notify_network_quality"){stopNetworkQualityMonitor?.(),stopNetworkQualityMonitor=null,succeed({});return}failed({error_message:"unsupported network quality monitor action"});return}if(kind==="beaconRequest"){let url2=pickUrl(params);if(!url2){failed({error_message:"missing url"});return}try{let resolved=new URL(url2,location.href);if(resolved.protocol!=="http:"&&resolved.protocol!=="https:"){failed({error_message:"unsupported request protocol"});return}let image=new Image;image.referrerPolicy="no-referrer-when-downgrade",image.src=resolved.href,succeed({})}catch{failed({error_message:"invalid url"})}return}if(kind==="calendar"){let p=params&&typeof params=="object"?params:{},events=readCalendarEvents();if(api==="store_calendar_event"){let event=calendarEventFromParams(p);if(!event.title||event.startTime===null){failed({error_message:"calendar title and start time are required"});return}let next=events.filter(stored=>!sameCalendarEvent(stored,event));if(next.push(event),!writeCalendarEvents(next)){failed({error_message:"calendar storage unavailable"});return}succeed({success:!0});return}if(api==="remove_calendar_event"){let candidate=calendarEventFromParams(p),next=events.filter(stored=>!sameCalendarEvent(stored,candidate));if(!writeCalendarEvents(next)){failed({error_message:"calendar storage unavailable"});return}succeed({success:!0,removed:events.length-next.length});return}if(api==="check_batch_calendar"){let batch=Array.isArray(p.batch)?p.batch:[];succeed({batch:batch.map(item=>{let candidate=calendarEventFromParams(item);return{...item&&typeof item=="object"?item:{},success:events.some(stored=>sameCalendarEvent(stored,candidate))}})});return}let urls=Array.isArray(p.urls)?p.urls.filter(value=>typeof value=="string"):typeof p.url=="string"?[p.url]:[],titles=Array.isArray(p.calendar_titles)?p.calendar_titles.filter(value=>typeof value=="string"):typeof p.calendar_title=="string"?[p.calendar_title]:[],matched=events.filter(event=>(urls.length===0||urls.includes(event.url))&&(titles.length===0||titles.includes(event.title)));succeed({events:matched.map(calendarEventResponse)});return}if(kind==="geolocation"){if(!navigator.geolocation){failed({errorCode:2,errorMsg:"geolocation unavailable"});return}let locate=()=>navigator.geolocation.getCurrentPosition(position=>{let{latitude,longitude,accuracy,altitude,altitudeAccuracy,heading,speed}=position.coords;succeed({latitude,longitude,accuracy,altitude,altitudeAccuracy,heading,speed,timestamp:position.timestamp})},error48=>failed({errorCode:error48.code,errorMsg:error48.message}),{enableHighAccuracy:!1,timeout:1e4,maximumAge:3e5});navigator.permissions?.query?navigator.permissions.query({name:"geolocation"}).then(status=>{status.state==="granted"?locate():failed({errorCode:1,errorMsg:"location permission not granted"})}).catch(locate):locate();return}if(kind==="permission"){let p=params&&typeof params=="object"?params:{},action=typeof p.action=="string"?p.action:"",permission=typeof p.permission=="string"?p.permission:"",permissionFailed=message=>failed({error_code:-1,error_message:message});if(permission==="album"||permission==="MODIFY_AUDIO_SETTINGS"){action==="check"||action==="request"?succeed({}):permissionFailed("unsupported permission action");return}let browserPermission=permission==="mic"?"microphone":permission==="camera"?"camera":permission==="lbs"?"geolocation":"";if(!browserPermission){permissionFailed("unsupported permission");return}if(action==="check"&&navigator.permissions?.query){navigator.permissions.query({name:browserPermission}).then(status=>{status.state==="granted"?succeed({}):permissionFailed("permission not granted")}).catch(()=>permissionFailed("permission check failed"));return}if(action==="request"&&(permission==="mic"||permission==="camera")){if(!navigator.mediaDevices?.getUserMedia){permissionFailed("media permission unavailable");return}navigator.mediaDevices.getUserMedia({audio:permission==="mic",video:permission==="camera"}).then(stream=>{for(let track of stream.getTracks())track.stop();succeed({})}).catch(()=>permissionFailed("permission denied"));return}if(action==="request"&&permission==="lbs"&&navigator.geolocation){navigator.geolocation.getCurrentPosition(()=>succeed({}),()=>permissionFailed("permission denied"),{timeout:1e4});return}permissionFailed("unsupported permission action");return}if(kind==="prefetch"){let p=params&&typeof params=="object"?params:{},url2=typeof p.url=="string"?p.url:"";if(!url2){failed({code:-1,errorMsg:"url is empty"});return}let resolvedUrl;try{resolvedUrl=new URL(url2,location.href).href}catch{failed({code:-1,errorMsg:"invalid url"});return}if(!Array.from(document.querySelectorAll('link[rel="prefetch"]')).some(link=>link.href===resolvedUrl)){let link=document.createElement("link");link.rel="prefetch",link.href=url2,(document.head??document.documentElement).appendChild(link)}succeed({});return}if(kind==="fptTrack"){let p=params&&typeof params=="object"?params:{},action=typeof p.action=="string"?p.action:"",actionParams=p.params&&typeof p.params=="object"?p.params:{},key=typeof actionParams.key=="string"?actionParams.key:"";if(action==="setFpt"){let value=typeof actionParams.value=="string"?actionParams.value:"";if(!key||!value||!/^[0-9A-Za-z._-]+$/.test(key)||!/^[0-9A-Za-z._-]+$/.test(value)||`${key}(${value})`.length>100){failed({error_message:"invalid fpt key or value"});return}setFptEntry(fptEntries,key,value),persistFpt()}else action==="deleteFpt"&&key&&(fptEntries.delete(key),persistFpt());succeed({});return}if(kind==="previewFile"){let p=params&&typeof params=="object"?params:{},fileUrl=typeof p.file_url=="string"?p.file_url:"",remoteUrl=typeof p.file_remote_url=="string"?p.file_remote_url:"",url2=(fileUrl.startsWith("http")?fileUrl:remoteUrl)||fileUrl||remoteUrl;url2?(requestOpen(url2,0,!1),succeed({})):failed({code:-1,errorMsg:"file_url is empty"});return}if(kind==="toast"){let error48=showAppToast(params);error48?failed({error_message:error48}):succeed({});return}if(kind==="unsupportedNativeInput"){let containerType="";try{containerType=new URL(location.href).searchParams.get("containerType")??""}catch{}!unsupportedNativeInputNotified&&(containerType==="h5_dx"||containerType==="flutter_h5")&&(unsupportedNativeInputNotified=!0,showAppToast({message:"当前页面使用原生输入框,请移除 URL 中的 containerType 参数以正常操作",milliseconds:4e3})),succeed({});return}if(kind==="payment"){log3("桥调用支付,等待用户确认",api,params),showPaymentDialog(api,params,succeed,failed);return}if(kind==="userTrack"){sendUserTrack(params),succeed({});return}if(kind==="response"){succeed(config2.actions.responses?.[api]);return}if(kind==="noop"){succeed({});return}silent||log3("未覆盖桥方法,回调 failure(页面库将走 H5 兜底):",api),failed(NOT_IMPLEMENTED_PAYLOAD)}let MEGA_SUPPORTED_APIS={stdPop:["showWeex2","showWeex","showH5","changeSize","close"],broadcast:["addEventListener","dispatchEvent","removeEventListener"],kvStorage:["setItem","getItem","removeItem","getAllKeys","clear","getCurrentInfo","getCurrentInfoAndKeys"],LifeCycle:["addPageLifeCycleListener","removePageLifeCycleListener"],Container:["interceptPageClose","disableInterceptPageClose"],navigator:["openURL","close","replace","setSystemBackBlockListener","removeSystemBackBlockListener"],NavBar:["setTitle"],Router:["popPage"]};function isMegaApiSupported(ability,api){return typeof ability=="string"&&typeof api=="string"&&MEGA_SUPPORTED_APIS[ability]?.includes(api)===!0}function megaParams(value){return value&&typeof value=="object"&&!Array.isArray(value)?value:{}}function megaError(callback,statusCode,message){emitMegaCallback(callback,{statusCode,type:"result",data:{errorMessage:typeof message=="string"?message:String(message??"")}})}function cloneMegaDetail(value){if(value===void 0)return{success:!0,value:void 0};try{return{success:!0,value:JSON.parse(JSON.stringify(value))}}catch{return{success:!1}}}function megaSuccess(data={}){return{statusCode:0,type:"result",data}}function megaFailure(message){return{statusCode:500,type:"result",data:{errorMessage:message}}}function megaKVParams(params){return{bizId:typeof params.bizID=="string"?params.bizID:typeof params.bizId=="string"?params.bizId:"",key:typeof params.key=="string"?params.key:"",value:typeof params.value=="string"?params.value:null}}function megaStringByteLength(value){try{return typeof TextEncoder=="function"?new TextEncoder().encode(value).length:value.length}catch{return value.length}}function megaKVUsedSize(entries){let size=0;for(let value of entries.values())size+=megaStringByteLength(value);return size}function reportMegaKVMutation(operation,bizId,key="",value,onSuccess,onFailure){requestContainerData("megaKVMutation",{operation,bizId,key,...value===void 0?{}:{value}},()=>onSuccess?.(),reason=>{log3("KVStorage 容器同步失败:",reason),onFailure?.(reason)})}function completeMegaKVMutation(operation,bizId,key,value,synchronous,callback){let result=megaSuccess();return reportMegaKVMutation(operation,bizId,key,value,synchronous?void 0:()=>emitMegaCallback(callback,result),synchronous?void 0:reason=>emitMegaCallback(callback,megaFailure(String(reason??"container sync failed")))),synchronous?result:null}function executeMegaKVStorage(api,params,synchronous,callback){let{bizId,key,value}=megaKVParams(params);if(!bizId)return megaFailure("missing bizID");let entries=megaKVStorage.get(bizId)??new Map;if(api==="setItem"){if(!key)return megaFailure("missing key");if(value===null||value==="")return megaFailure("missing value");let previousSize=megaStringByteLength(entries.get(key)??"");return megaKVUsedSize(entries)-previousSize+megaStringByteLength(value)>MEGA_KV_TOTAL_SIZE?megaFailure("KVStorage quota exceeded"):(entries.set(key,value),megaKVStorage.set(bizId,entries),megaKVMutationVersion+=1,persistMegaKVStorage(),completeMegaKVMutation("set",bizId,key,value,synchronous,callback))}if(api==="getItem"){if(!key)return megaFailure("missing key");let result=entries.get(key)??"";return megaSuccess(synchronous?{result}:result)}if(api==="removeItem")return key?(entries.delete(key),entries.size===0&&megaKVStorage.delete(bizId),megaKVMutationVersion+=1,persistMegaKVStorage(),completeMegaKVMutation("remove",bizId,key,void 0,synchronous,callback)):megaFailure("missing key");if(api==="getAllKeys"){let result=Array.from(entries.keys());return megaSuccess(synchronous?{result}:result)}if(api==="clear")return megaKVStorage.delete(bizId),megaKVMutationVersion+=1,persistMegaKVStorage(),completeMegaKVMutation("clear",bizId,"",void 0,synchronous,callback);if(api==="getCurrentInfo"||api==="getCurrentInfoAndKeys"){let data={totalSize:MEGA_KV_TOTAL_SIZE,freeSize:Math.max(MEGA_KV_TOTAL_SIZE-megaKVUsedSize(entries),0)};return api==="getCurrentInfoAndKeys"&&(data.keys=Array.from(entries.keys())),megaSuccess(data)}return{statusCode:405,type:"result",data:{}}}function handleMegaLifeCycle(api,callback){if(api==="addPageLifeCycleListener"){callback&&megaLifeCycleListeners.add(callback),emitMegaCallback(callback,megaSuccess());return}if(api==="removePageLifeCycleListener"){let listeners=Array.from(megaLifeCycleListeners);megaLifeCycleListeners.clear(),emitMegaCallback(callback,megaSuccess());for(let listener of listeners)emitMegaCallback(listener,{statusCode:99,type:"finish",data:{}});return}megaError(callback,405,`LifeCycle.${api} is not supported`)}function handleMegaContainer(api,callback){if(api==="interceptPageClose"){callback&&megaPageCloseListeners.add(callback),emitMegaCallback(callback,megaSuccess());return}if(api==="disableInterceptPageClose"){let listeners=Array.from(megaPageCloseListeners);megaPageCloseListeners.clear(),emitMegaCallback(callback,megaSuccess());for(let listener of listeners)emitMegaCallback(listener,{statusCode:99,type:"finish",data:{}});return}megaError(callback,405,`Container.${api} is not supported`)}function megaNavigationUrl(params){let rawUrl=pickUrl(params);if(!rawUrl)return null;if(!params.extQuery||typeof params.extQuery!="object"||Array.isArray(params.extQuery))return rawUrl;try{let target=new URL(rawUrl,location.href);for(let[key,value]of Object.entries(params.extQuery))value!=null&&target.searchParams.set(key,String(value));return target.href}catch{return rawUrl}}function handleMegaNavigator(api,params,callback){if(api==="openURL"||api==="replace"){let url2=megaNavigationUrl(params);if(!url2){megaError(callback,500,"missing url");return}let callbackId=api==="openURL"&&callback?stashCallback(value=>{let backdata=value&&typeof value=="object"?value.backdata:void 0;emitMegaCallback(callback,{statusCode:1,type:"onResult",data:{result:!0,...backdata===void 0?{}:{data:backdata}}}),emitMegaCallback(callback,{statusCode:99,type:"finish",data:{}})}):0;requestOpen(url2,callbackId,!1,{...params,...api==="replace"?{__mearlReplace:!0}:{}}),emitMegaCallback(callback,megaSuccess());return}if(api==="close"){emitMegaCallback(callback,megaSuccess()),requestClose(void 0);return}if(api==="setSystemBackBlockListener"){megaSystemBackListener&&megaSystemBackListener!==callback&&emitMegaCallback(megaSystemBackListener,{statusCode:99,type:"finish",data:{}}),megaSystemBackListener=callback??null,emitMegaCallback(callback,megaSuccess());return}if(api==="removeSystemBackBlockListener"){let listener=megaSystemBackListener;megaSystemBackListener=null,emitMegaCallback(callback,megaSuccess()),listener&&emitMegaCallback(listener,{statusCode:99,type:"finish",data:{}});return}megaError(callback,405,`navigator.${api} is not supported`)}function handleMegaNavBar(api,params,callback){if(api!=="setTitle"){megaError(callback,405,`NavBar.${api} is not supported`);return}applyNavigationBarState(api,params),emitMegaCallback(callback,megaSuccess())}function handleMegaRouter(api,callback){if(api!=="popPage"){megaError(callback,405,`Router.${api} is not supported`);return}emitMegaCallback(callback,megaSuccess()),requestClose(void 0)}function handleMegaStdPop(api,params,callback){if(api==="showH5"||api==="showWeex2"||api==="showWeex"){let url2=pickUrl(params),popId=typeof params.popId=="string"?params.popId.trim():"";if(!url2||!popId){megaError(callback,500,url2?"missing popId":"missing url");return}let callbackId=stashCallback(value=>{let result=value&&typeof value=="object"&&"backdata"in value?value.backdata:void 0;emitMegaCallback(callback,{statusCode:1,type:"onClose",data:result}),emitMegaCallback(callback,{statusCode:99,type:"finish"})});requestOpen(url2,callbackId,!0,{...params,__mearlMegaPopId:popId}),emitMegaCallback(callback,{statusCode:0,type:"result",data:{}});return}if(api==="close"){let popId=typeof params.popId=="string"?params.popId.trim():"";if(!popId){megaError(callback,500,"missing popId");return}let cloned=cloneMegaDetail(params.result);if(!cloned.success){megaError(callback,500,"result is not serializable");return}requestContainerData("megaPopClose",{popId,result:cloned.value},()=>emitMegaCallback(callback,{statusCode:0,type:"result",data:{}}),reason=>megaError(callback,500,reason));return}if(api==="changeSize"){let popId=typeof params.popId=="string"?params.popId.trim():"";if(!popId){megaError(callback,500,"missing popId");return}requestContainerData("megaPopResize",{...params,popId},()=>emitMegaCallback(callback,{statusCode:0,type:"result",data:{}}),reason=>megaError(callback,500,reason));return}megaError(callback,405,`stdPop.${api} is not supported`)}function handleMegaBroadcast(api,params,callback){let bizId=megaBroadcastBizId(params.bizId),eventName=typeof params.eventName=="string"?params.eventName.trim():"";if(!eventName){megaError(callback,500,"missing eventName");return}if(api==="addEventListener"){if(!callback)return;let id=`mearl-mega-listener-${++megaListenerSeq}`;megaBroadcastListeners.set(id,{id,bizId,eventName,once:params.once===!0,callback}),emitMegaCallback(callback,{statusCode:0,type:"result",data:{}}),emitMegaCallback(callback,{statusCode:1,type:"onAdd",data:{listenerId:id}});return}if(api==="dispatchEvent"){let detail=cloneMegaDetail(params.detail);if(!detail.success){megaError(callback,500,"detail is not serializable");return}requestContainerData("megaBroadcast",{message:{kind:"megaBroadcast",bizId,eventName,detail:detail.value}},()=>emitMegaCallback(callback,{statusCode:0,type:"result",data:{}}),reason=>megaError(callback,500,reason));return}if(api==="removeEventListener"){let listenerId=typeof params.listenerId=="string"?params.listenerId:"",removed=[];for(let listener of Array.from(megaBroadcastListeners.values()))listener.bizId!==bizId||listener.eventName!==eventName||listenerId&&listener.id!==listenerId||(megaBroadcastListeners.delete(listener.id),removed.push(listener));emitMegaCallback(callback,{statusCode:0,type:"result",data:{}});for(let listener of removed)emitMegaCallback(listener.callback,{statusCode:99,type:"finish"});return}megaError(callback,405,`broadcast.${api} is not supported`)}function makeMegaBridge(){return{asyncCall:(ability,api,rawParams,callback)=>{let params=megaParams(rawParams);if(ability==="ability"&&api==="available"){emitMegaCallback(callback,{statusCode:0,type:isMegaApiSupported(params.ability,params.api)?"YES":"NO",data:{}});return}if(ability==="ability"&&api==="batchFinishTrace"){emitMegaCallback(callback,{statusCode:0,type:"result",data:{}});return}if(!isMegaApiSupported(ability,api)){megaError(callback,405,`${ability}.${api} is not supported`);return}if(ability==="stdPop")handleMegaStdPop(api,params,callback);else if(ability==="broadcast")handleMegaBroadcast(api,params,callback);else if(ability==="kvStorage"){let result=executeMegaKVStorage(api,params,!1,callback);result&&emitMegaCallback(callback,result)}else ability==="LifeCycle"?handleMegaLifeCycle(api,callback):ability==="Container"?handleMegaContainer(api,callback):ability==="navigator"?handleMegaNavigator(api,params,callback):ability==="NavBar"?handleMegaNavBar(api,params,callback):handleMegaRouter(api,callback)},syncCall:(ability,api,rawParams)=>{let params=megaParams(rawParams);return ability==="ability"&&api==="available"?{statusCode:0,type:isMegaApiSupported(params.ability,params.api)?"YES":"NO",data:{}}:ability==="kvStorage"&&isMegaApiSupported(ability,api)?executeMegaKVStorage(api,params,!0)??megaFailure("container sync pending"):{statusCode:405,type:"result",data:{}}}}}function makeBridge(style){if(style==="mega")return makeMegaBridge();if(style==="easybikeNative"){let callNative=rawPayload=>{let payload;try{payload=typeof rawPayload=="string"?JSON.parse(rawPayload):rawPayload??{}}catch{return}let classMap=typeof payload.classMap=="string"?payload.classMap:"",method=typeof payload.method=="string"?payload.method:"",callbackId=typeof payload.callbackId=="string"||typeof payload.callbackId=="number"?String(payload.callbackId):"",params;try{params=typeof payload.params=="string"?payload.params?JSON.parse(payload.params):{}:payload.params??{}}catch{params={}}let complete=(code,data,msg="")=>{let callback=resolveWindowFunction("callBack");callbackId&&callback&&callback({callbackId,code,data,msg})};dispatch(`${classMap}.${method}`,params,value=>complete(0,value),error48=>complete(1,void 0,typeof error48=="string"?error48:String(error48??"")))};return{postMessage:callNative,callNative}}if(style==="windvane")return{isAvailable:!0,version:"8.7.0",call:(cls,method,params,succ,fail)=>dispatch(`${cls}.${method}`,params,succ,fail)};if(style==="fliggy"||style==="alipay"||style==="callback"){let bridge={call:(api,params,succ,fail)=>{typeof params=="function"&&(fail=succ,succ=params,params=void 0);let p=params&&typeof params=="object"?params:{},successFn=succ??(typeof p.success_callback=="function"?p.success_callback:void 0)??(typeof p.successCallback=="function"?p.successCallback:void 0),failureFn=fail??(typeof p.fail_callback=="function"?p.fail_callback:void 0)??(typeof p.failure_callback=="function"?p.failure_callback:void 0)??(typeof p.failCallback=="function"?p.failCallback:void 0)??(typeof p.failureCallback=="function"?p.failureCallback:void 0);dispatch(api,p,res=>successFn?.(res),err=>{failureFn?failureFn(err):successFn?.({error:err})},p.callbackCommand??p.callback_command)},pushBack:(prefixOrApi,apiOrParams,paramsOrSucc,succ)=>{let api=prefixOrApi,params=apiOrParams,success2=paramsOrSucc;typeof apiOrParams=="string"&&(api=apiOrParams,params=paramsOrSucc,success2=succ);let p=params??{},successFn=(typeof success2=="function"?success2:void 0)??(typeof p.successCallback=="function"?p.successCallback:void 0);return dispatch(api,p,res=>successFn?.(res),void 0,p.callbackCommand??p.callback_command),bridge},sendUriScheme:uri=>(handleMaybeScheme(uri),bridge)};if(style==="fliggy"){let normalizedAppName=(config2.globals.__APP_NAME__??"").toUpperCase(),os11=config2.clientType==="iphone"?"ios":"android",isAliApp=name=>normalizedAppName===name.toUpperCase();Object.assign(bridge,{version:"1.0.21",device:{os:os11,OS:config2.platform,type:os11,version:config2.systemVersion,model:config2.globals.__DEVICE_MODEL__??""},platform:os11,isAliApp,isTmall:isAliApp("TM"),isTaobao:isAliApp("TB"),isAlipay:isAliApp("AP"),isAlitrip:isAliApp("LX"),isKoubei:isAliApp("KB"),isElm:isAliApp("ELMC"),isGaode:isAliApp("amap"),isUC:/UCBrowser/i.test(config2.userAgent),isWeibo:/Weibo/i.test(config2.userAgent),isWeixin:/MicroMessenger/i.test(config2.userAgent),isWindVane:config2.bridges.some(item=>item.style==="windvane"),isAlipayClient:/AlipayClient/i.test(config2.userAgent)})}return bridge}if(style==="btrip")return{call:(api,params)=>dispatch(api,params??{},void 0,void 0)};if(style==="invoke")return{invoke:(api,params)=>{let p=params??{};dispatch(api,p,p.success,p.fail)}};if(style==="callHandler")return{callHandler:(api,params)=>dispatch(api,params??{},void 0,void 0)};if(style==="amap")return{ready:cb=>cb?.(),send:(msg,cb)=>{let m=msg??{};dispatch(typeof m.action=="string"?m.action:"",m,res=>cb?.(res),err=>cb?.({error:err}))}};if(style==="didi")return{openPage:params=>dispatch("openPage",params??{},void 0,void 0),closePage:params=>dispatch("closePage",params??{},void 0,void 0)};if(style==="wechatMiniProgram"){let invoke2=(api,params)=>{let p=params&&typeof params=="object"?params:{};dispatch(api,p,value=>{p.success?.(value),p.complete?.(value)},error48=>{p.fail?.(error48),p.complete?.(error48)})};return{navigateTo:params=>invoke2("navigateTo",params),redirectTo:params=>invoke2("redirectTo",params),switchTab:params=>invoke2("switchTab",params),reLaunch:params=>invoke2("reLaunch",params),navigateBack:params=>invoke2("navigateBack",params),postMessage:params=>invoke2("postMessage",params),getEnv:callback=>{callback&&setTimeout(()=>callback({miniprogram:!0}),0)}}}return{}}function setGlobal(path23,value){let parts=path23.split("."),obj=w;for(let i=0;i<parts.length-1;i++){let cur=obj[parts[i]];(!cur||typeof cur!="object")&&(obj[parts[i]]={}),obj=obj[parts[i]]}obj[parts[parts.length-1]]=value}if(config2.bridges.some(spec=>spec.style==="mega")){let hydrationVersion=megaKVMutationVersion;requestContainerData("megaKVSnapshot",{},value=>{let entries=value&&typeof value=="object"?value.entries:void 0;megaKVMutationVersion===hydrationVersion&&replaceMegaKVStorage(entries)},()=>{})}for(let spec of config2.bridges)try{setGlobal(spec.global,makeBridge(spec.style))}catch(e){console.error(TAG,"桥安装失败:",spec.global,e)}return{mapScheme,handleMaybeScheme,handleAppMessage,handleNativeBack,handleResume,handlePageVisibility,applyRuntimeResponses}}function installAppProfileContainerStack(config2,environment,links){let{SRC,TAG,simulateSystemBars,ROOT_FRAME_NAME,LAYER_FRAME_NAME,isTop,isRootFrame,isLayerFrame,isContainerFrame,usesRootContainer,log:log3}=environment,{pageTransport}=links,initialLayerTitleBarState=url2=>links.getSystemBars().initialLayerTitleBarState(url2),resolvedTitleBarState=layer=>links.getSystemBars().resolvedTitleBarState(layer),parseReportedTitleBarState=value=>links.getSystemBars().parseReportedTitleBarState(value),createSimulatedNavigationBarView=(placement,onBack)=>links.getSystemBars().createNavigationBarView(placement,onBack),destroySimulatedNavigationBarView=view=>links.getSystemBars().destroyNavigationBarView(view),syncLayerViewport=(layer,state)=>links.getSystemBars().syncLayerViewport(layer,state),syncActiveSystemBars=()=>links.getSystemBars().syncActiveSystemBars(),syncSimulatedTitleBar=()=>links.getSystemBars().syncSimulatedTitleBar(),rootContainerActive=!1,rootFrame=null,rootBusinessUrl=location.href,webViewEnvironmentRequestSeq=0,simulatedPageHidden=!1,runtimeResponses=null;function syncSimulatorStateToWindow(target){target&&(runtimeResponses&&target.postMessage({source:SRC,type:"runtimeResponses",profile:config2.profile,responses:runtimeResponses},"*"),simulatedPageHidden&&target.postMessage({source:SRC,type:"simulatorVisibility",hidden:!0},"*"))}function startPreparedWebViewNavigation(frame,target,canCommit,registerCleanup){let insets=config2.safeAreaInsets??{top:config2.statusBarHeight,right:0,bottom:0,left:0};if(!usesRootContainer||!Object.values(insets).some(value=>value>0)){canCommit()&&(frame.src=target);return}let requestId=++webViewEnvironmentRequestSeq,settled=!1,fallbackTimer=0,cleanup=()=>{settled||(settled=!0,clearTimeout(fallbackTimer),window.removeEventListener("message",handleResponse),registerCleanup?.(null))},commitNavigation=fallbackReason=>{cleanup(),fallbackReason&&console.warn(TAG,"WebView 环境准备未完成,降级提交导航",{target,requestId,reason:fallbackReason}),canCommit()&&(frame.src=target)},handleResponse=event=>{if(event.source!==window||event.data?.source!=="mearl-content"||event.data?.type!=="APP_BRIDGE_PREPARE_WEBVIEW_RESPONSE"||event.data?.requestId!==requestId)return;let result=event.data.result;result?.success===!0?commitNavigation():commitNavigation(String(result?.error??"unknown preparation failure"))};registerCleanup?.(cleanup),window.addEventListener("message",handleResponse),fallbackTimer=setTimeout(()=>commitNavigation("preparation timed out after 500ms"),500);try{window.postMessage({source:SRC,type:"prepareWebView",requestId},"*")}catch(error48){commitNavigation(error48 instanceof Error?error48.message:String(error48))}}function installRootContainer(){if(!usesRootContainer||!/^https?:$/i.test(location.protocol))return;let shellRoot,frame;try{for(let cookie of config2.rootContainer?.initialCookies??[]){if(!cookie.name)continue;let parts=[`${encodeURIComponent(cookie.name)}=${encodeURIComponent(cookie.value)}`,`Path=${cookie.path??"/"}`];cookie.domain&&parts.push(`Domain=${cookie.domain}`),document.cookie=parts.join("; ")}shellRoot=document.createElement("html");let shellHead=document.createElement("head"),charset=document.createElement("meta"),viewport=document.createElement("meta"),title=document.createElement("title"),shellBody=document.createElement("body");frame=document.createElement("iframe"),shellRoot.setAttribute("data-mearl-app-shell",""),shellBody.setAttribute("data-mearl-app-shell",""),charset.setAttribute("charset","utf-8"),viewport.name="viewport",viewport.content="width=device-width,initial-scale=1,viewport-fit=cover",shellHead.append(charset,viewport,title),shellRoot.append(shellHead,shellBody),shellRoot.style.cssText="width:100%;height:100%;margin:0;overflow:hidden;background:#fff;",shellBody.style.cssText="width:100%;height:100%;margin:0;overflow:hidden;background:#fff;",frame.name=ROOT_FRAME_NAME,frame.setAttribute("data-mearl-root-webview",config2.profile),frame.style.cssText="position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;border:0;display:block;background:#fff;z-index:0;opacity:1;",frame.addEventListener("load",()=>{let committedSrc=frame.getAttribute("src");!committedSrc||committedSrc==="about:blank"||(syncSimulatorStateToWindow(frame.contentWindow),requestAnimationFrame(()=>{rootFrame!==frame||!frame.isConnected||(frame.setAttribute("data-mearl-webview-ready",""),syncSimulatedTitleBar())}))}),shellBody.appendChild(frame);let currentRoot=document.documentElement;currentRoot?document.replaceChild(shellRoot,currentRoot):document.appendChild(shellRoot)}catch(error48){console.warn(TAG,"根 WebView 容器创建失败,保留当前页面",error48),rootFrame=null;return}rootFrame=frame,rootContainerActive=!0;try{typeof window.stop=="function"&&window.stop()}catch(error48){console.warn(TAG,"停止外层文档加载失败,继续启动根 WebView",error48)}try{startPreparedWebViewNavigation(frame,rootBusinessUrl,()=>rootFrame===frame&&frame.isConnected)}catch(error48){console.warn(TAG,"根 WebView 环境准备启动失败,直接提交业务导航",error48),rootFrame===frame&&frame.isConnected&&(frame.src=rootBusinessUrl)}}installRootContainer();function normalizeProxyPathPrefix(prefix){let withLeadingSlash=prefix.startsWith("/")?prefix:`/${prefix}`;return withLeadingSlash.endsWith("/")?withLeadingSlash:`${withLeadingSlash}/`}function matchesProxyTarget(hostname3,suffixes){return suffixes.some(suffix=>hostname3===suffix||hostname3.endsWith(`.${suffix}`))}function mapLayerFrameUrl(url2){let proxy=config2.layerUrlProxy;if(!proxy||!location.hostname.startsWith(proxy.sourceHostPrefix))return url2;try{let target=new URL(url2,location.href);if(!/^https?:$/.test(target.protocol))return url2;let prefix=normalizeProxyPathPrefix(proxy.pathPrefix);if(target.hostname===location.hostname){if(target.pathname.startsWith(prefix))return url2;let derivedHost=location.pathname.startsWith(prefix)?location.pathname.slice(prefix.length).split("/")[0]:proxy.defaultTargetHost;return!derivedHost||!matchesProxyTarget(derivedHost,proxy.targetHostSuffixes)?url2:`${location.origin}${prefix}${derivedHost}${target.pathname}${target.search}${target.hash}`}return matchesProxyTarget(target.hostname,proxy.targetHostSuffixes)?`${location.origin}${prefix}${target.host}${target.pathname}${target.search}${target.hash}`:url2}catch{return url2}}function restoreLayerBusinessUrl(url2){let proxy=config2.layerUrlProxy;if(!proxy)return url2;try{let current=new URL(url2,location.href),prefix=normalizeProxyPathPrefix(proxy.pathPrefix);if(current.origin!==location.origin||!current.pathname.startsWith(prefix))return url2;let rest=current.pathname.slice(prefix.length),slash=rest.indexOf("/"),host=slash===-1?rest:rest.slice(0,slash);if(!host)return url2;let hostname3=new URL(`${current.protocol}//${host}`).hostname;if(!matchesProxyTarget(hostname3,proxy.targetHostSuffixes))return url2;let pathname=slash===-1?"/":rest.slice(slash);return`${current.protocol}//${host}${pathname}${current.search}${current.hash}`}catch{return url2}}let ANIM_MS=config2.animationMs??300;function boolParam(value,fallback){return value===!0||value===1||value==="1"||value==="true"?!0:value===!1||value===0||value==="0"||value==="false"?!1:value===""?!0:fallback}function numberParam(value,fallback,min,max){let parsed=typeof value=="number"?value:Number(value);return Number.isFinite(parsed)?Math.min(Math.max(parsed,min),max):fallback}function resolveOverlayPresentation(url2,params,explicitWebdialog){let query=null;try{query=new URL(url2,location.href).searchParams}catch{}let records=[],addRecord=value=>{value&&typeof value=="object"&&!Array.isArray(value)&&records.push(value)};addRecord(params?.pageParams),addRecord(params?.page_params),addRecord(params?.popConfig),addRecord(params?.data),addRecord(params?.param),addRecord(params);let read=key=>{for(let record2 of records)if(Object.prototype.hasOwnProperty.call(record2,key))return record2[key];return query?.has(key)?query.get(key):void 0},protocol=config2.overlay;if(!explicitWebdialog&&(!protocol||!boolParam(read(protocol.enabledParam),!1)))return null;let configuredTopRatio=protocol?read(protocol.topRatioParam):void 0,configuredHeightRatio=protocol?.heightRatioParam?read(protocol.heightRatioParam):void 0,configuredMaxHeight=read("maxHeight")??configuredHeightRatio,defaultTopRatio=protocol?.defaultTopRatio??.2;return{topRatio:configuredTopRatio!==void 0?numberParam(configuredTopRatio,defaultTopRatio,0,1):configuredMaxHeight!==void 0?1-numberParam(configuredMaxHeight,1-defaultTopRatio,0,1):defaultTopRatio,widthRatio:numberParam(read("maxWidth"),1,0,1),radius:numberParam((protocol?read(protocol.radiusParam):void 0)??read("cornerRadius"),protocol?.defaultRadius??0,0,50),maskAlpha:numberParam(protocol?read(protocol.maskAlphaParam):void 0,protocol?.defaultMaskAlpha??.3,0,1),tapClose:boolParam((protocol?read(protocol.tapCloseParam):void 0)??read("tapEnable"),protocol?.defaultTapClose??!0)}}function requestsPopBeforeOpen(url2,params){if(params?.__mearlReplace===!0)return!0;let key=config2.popBeforeOpenParam;if(!key)return!1;let records=[params?.pageParams,params?.page_params,params?.data,params?.param,params];for(let value of records){if(!value||typeof value!="object"||Array.isArray(value))continue;let record2=value;if(Object.prototype.hasOwnProperty.call(record2,key))return boolParam(record2[key],!1)}try{let query=new URL(url2,location.href).searchParams;return query.has(key)&&boolParam(query.get(key),!1)}catch{return!1}}let layers=[],forwardStack=[],layerSeq=0,enteringLayerCount=0,closingLayerCount=0,explicitLayerTitleBarStates=new Map,rootScrollStyles=null,pendingClose=null,nativeBackRequestSeq=0,pendingNativeBack=null,containerDataRequestSeq=0,containerDataCallbacks=new Map,sharedFiles=new Map,sharedData=new Map,legacyBroadcastChannels=new Set,MEGA_KV_STORAGE_KEY=`__mearl_mega_kv__:${config2.profile}`;function readMegaKVStorage(){let storage=new Map;try{let parsed=JSON.parse(localStorage.getItem(MEGA_KV_STORAGE_KEY)??"{}");if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return storage;for(let[bizId,rawEntries]of Object.entries(parsed)){if(!rawEntries||typeof rawEntries!="object"||Array.isArray(rawEntries))continue;let entries=new Map;for(let[key,value]of Object.entries(rawEntries))typeof value=="string"&&entries.set(key,value);storage.set(bizId,entries)}}catch{}return storage}let megaKVStorage=readMegaKVStorage();function megaKVSnapshot(){let snapshot={};for(let[bizId,values]of megaKVStorage)snapshot[bizId]=Object.fromEntries(values);return snapshot}function persistMegaKVStorage(){try{localStorage.setItem(MEGA_KV_STORAGE_KEY,JSON.stringify(megaKVSnapshot()))}catch{}}let PENDING_CLOSE_TIMEOUT_MS=400,pendingRootHistoryDepth=null;function clearPendingClose(){pendingClose&&(clearTimeout(pendingClose.timer),pendingClose=null)}function clearPendingNativeBack(){pendingNativeBack&&(clearTimeout(pendingNativeBack.timer),pendingNativeBack=null)}function clearPendingRootHistoryDepth(){pendingRootHistoryDepth&&(clearTimeout(pendingRootHistoryDepth.timer),pendingRootHistoryDepth=null)}function armPendingClose(data,retries){clearPendingClose();let timer=setTimeout(()=>{pendingClose=null,log3("close 未等到 popstate,直接关栈顶兜底"),closeToDepth(Math.max(layers.length-1,0),data,!0)},PENDING_CLOSE_TIMEOUT_MS);pendingClose={data,retries,timer},history.back()}function parseStorageId(url2){try{return new URL(url2,location.href).searchParams.get("__storage_id")}catch{return null}}function titleBarStateCacheKey(url2){try{let parsed=new URL(url2,location.href);return parsed.hash="",parsed.href}catch{return url2}}function cacheExplicitTitleBarState(layer,state){explicitLayerTitleBarStates.set(titleBarStateCacheKey(layer.entryUrl),state),explicitLayerTitleBarStates.set(titleBarStateCacheKey(layer.url),state)}function readDepth(state){if(state&&typeof state=="object"){let d=state.__mearl_layer__;if(typeof d=="number")return d}return null}function mapUrlForSync(url2){let suffixes=config2.urlSyncHostSuffixes??[];try{let u=new URL(url2,location.href);if(!/^https?:$/.test(u.protocol)||!(suffixes.length===0||suffixes.some(s=>u.host===s||u.host.endsWith(`.${s}`))))return;let proxy=config2.layerUrlProxy;return proxy&&location.hostname.startsWith(proxy.sourceHostPrefix)&&matchesProxyTarget(u.hostname,proxy.targetHostSuffixes)?`${normalizeProxyPathPrefix(proxy.pathPrefix)}${u.host}${u.pathname}${u.search}${u.hash}`:u.pathname+u.search+u.hash}catch{return}}function createLayerEl(overlay,id){let el=document.createElement("div");el.setAttribute("data-mearl-layer",String(id)),el.style.cssText=`position:fixed;inset:0;z-index:${2147483e3+id%100*2};`;let frame=document.createElement("iframe");if(frame.name=LAYER_FRAME_NAME,frame.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-modals allow-downloads allow-popups"),frame.style.cssText="position:absolute;inset:0;width:100%;height:100%;border:0;display:block;background:#fff;z-index:0;opacity:1;",overlay){el.style.pointerEvents="none";let mask=document.createElement("div");mask.style.cssText=`position:absolute;inset:0;background:rgba(0,0,0,${overlay.maskAlpha});opacity:0;pointer-events:auto;`;let sheet=document.createElement("div"),width=overlay.widthRatio*100,left=(1-overlay.widthRatio)/2*100;return sheet.style.cssText=`position:absolute;left:${left}%;right:auto;bottom:0;width:${width}%;height:${(1-overlay.topRatio)*100}%;background:#fff;border-radius:${overlay.radius}px ${overlay.radius}px 0 0;overflow:hidden;pointer-events:auto;`,sheet.appendChild(frame),el.appendChild(mask),el.appendChild(sheet),{el,frame,animEl:sheet,mask}}return el.style.background="#fff",el.appendChild(frame),{el,frame,animEl:el,mask:null}}function setLayerInteractive(layer,interactive){layer.frame.style.pointerEvents=interactive?"":"none",layer.titleBarView&&(layer.titleBarView.root.style.pointerEvents=interactive?"":"none"),interactive?(layer.frame.removeAttribute("inert"),layer.frame.removeAttribute("aria-hidden"),layer.frame.removeAttribute("tabindex")):(layer.frame.setAttribute("inert",""),layer.frame.setAttribute("aria-hidden","true"),layer.frame.setAttribute("tabindex","-1"),layer.frame.blur()),layer.overlay?(layer.el.style.pointerEvents="none",layer.animEl.style.pointerEvents=interactive?"auto":"none",layer.mask&&(layer.mask.style.pointerEvents=interactive?"auto":"none")):layer.el.style.pointerEvents=interactive?"":"none"}function setRootFrameInteractive(interactive){rootFrame&&(rootFrame.style.pointerEvents=interactive?"":"none",interactive?(rootFrame.removeAttribute("inert"),rootFrame.removeAttribute("aria-hidden"),rootFrame.removeAttribute("tabindex")):(rootFrame.setAttribute("inert",""),rootFrame.setAttribute("aria-hidden","true"),rootFrame.setAttribute("tabindex","-1"),rootFrame.blur()))}function blockClosingLayerInteractions(layer){setLayerInteractive(layer,!1),layer.el.style.pointerEvents="auto"}function syncRootScrollLock(locked){let body=document.body;if(locked&&!rootScrollStyles){rootScrollStyles={html:document.documentElement.style.overflow,body:body?.style.overflow??null},document.documentElement.style.overflow="hidden",body&&(body.style.overflow="hidden");return}!locked&&rootScrollStyles&&(document.documentElement.style.overflow=rootScrollStyles.html,body&&rootScrollStyles.body!==null&&(body.style.overflow=rootScrollStyles.body),rootScrollStyles=null)}function syncLayerInteractivity(){let activeLayer=closingLayerCount===0&&enteringLayerCount===0?layers[layers.length-1]:void 0;for(let layer of layers)setLayerInteractive(layer,layer===activeLayer),!activeLayer&&layer===layers[layers.length-1]&&(layer.el.style.pointerEvents="auto");setRootFrameInteractive(layers.length===0&&enteringLayerCount===0&&closingLayerCount===0),syncRootScrollLock(layers.length>0||enteringLayerCount>0||closingLayerCount>0)}function finishLayerEntry(layer){layer.entering&&(layer.entering=!1,layer.enterTimer!==null&&clearTimeout(layer.enterTimer),layer.enterTimer=null,layer.enterTransitionEnd&&(layer.animEl.removeEventListener("transitionend",layer.enterTransitionEnd),layer.enterTransitionEnd=null),enteringLayerCount=Math.max(enteringLayerCount-1,0),syncLayerInteractivity())}function animateIn(layer){let t=layer.animEl;if(t.style.transform=layer.overlay?"translateY(100%)":"translateX(100%)",t.offsetWidth,t.style.transition=`transform ${ANIM_MS}ms ease`,t.style.transform="translate(0px, 0px)",layer.mask&&(layer.mask.style.transition=`opacity ${ANIM_MS}ms ease`,layer.mask.style.opacity="1"),ANIM_MS<=0){finishLayerEntry(layer);return}layer.enterTransitionEnd=event=>{event.target===t&&event.propertyName==="transform"&&finishLayerEntry(layer)},t.addEventListener("transitionend",layer.enterTransitionEnd),layer.enterTimer=setTimeout(()=>finishLayerEntry(layer),ANIM_MS+60)}function animateOut(layer,done){let t=layer.animEl;if(ANIM_MS<=0){t.style.transform=layer.overlay?"translateY(100%)":"translateX(100%)",layer.mask&&(layer.mask.style.opacity="0"),setTimeout(done,0);return}let settled=!1,fallbackTimer=0,finish=()=>{settled||(settled=!0,t.removeEventListener("transitionend",onTransitionEnd),clearTimeout(fallbackTimer),done())},onTransitionEnd=event=>{event.target===t&&event.propertyName==="transform"&&finish()};t.addEventListener("transitionend",onTransitionEnd),t.style.transition=`transform ${ANIM_MS}ms ease`,t.style.transform=layer.overlay?"translateY(100%)":"translateX(100%)",layer.mask&&(layer.mask.style.opacity="0"),fallbackTimer=setTimeout(finish,ANIM_MS+60)}function startLayerNavigation(layer,target){startPreparedWebViewNavigation(layer.frame,target,()=>!layer.closing&&layer.el.isConnected,cleanup=>{layer.navigationPreparationCleanup=cleanup})}function setPageVisibility(target,hidden){if(target===window){links.getBridgeProtocol().handlePageVisibility(hidden);return}try{target.postMessage({source:SRC,type:"simulatorVisibility",hidden},"*")}catch{}}function openLayer(url2,callbackId,overlay,openerWin,pushHistory,popId=null){clearPendingClose();let target=url2;if(!/^https?:/i.test(target)){let mapped=links.getBridgeProtocol().mapScheme(target);if(!mapped)return log3("open 失败,scheme 未映射:",url2),null;target=mapped}location.protocol==="https:"&&target.startsWith("http:")&&(target="https:"+target.slice(5));let presentation=overlay??resolveOverlayPresentation(target,void 0,!1);log3("open →",presentation?"(webdialog) ":"",target);let parts=createLayerEl(presentation,++layerSeq),restoredTitleBarState=explicitLayerTitleBarStates.get(titleBarStateCacheKey(target)),layer={id:layerSeq,win:parts.frame.contentWindow,frame:parts.frame,entryUrl:target,url:target,overlay:presentation,openerWin,callbackId,storageId:parseStorageId(target),popId,el:parts.el,animEl:parts.animEl,mask:parts.mask,entering:!0,enterTimer:null,enterTransitionEnd:null,closing:!1,navigationPreparationCleanup:null,titleBarState:restoredTitleBarState??initialLayerTitleBarState(target),titleBarStateExplicit:restoredTitleBarState!==void 0,titleBarStateReady:restoredTitleBarState!==void 0,titleBarView:null};if(popId&&layer.el.setAttribute("data-mearl-pop-id",popId),layer.mask&&presentation?.tapClose&&layer.mask.addEventListener("click",()=>requestOverlayClose(layer)),!presentation&&simulateSystemBars&&config2.titleBar&&(layer.titleBarView=createSimulatedNavigationBarView("layer",()=>requestNativeBack()),layer.titleBarView.root.setAttribute("data-mearl-layer-titlebar",String(layer.id)),parts.el.appendChild(layer.titleBarView.root)),layers.push(layer),setPageVisibility(openerWin,!0),enteringLayerCount+=1,syncLayerViewport(layer,layer.titleBarState),syncLayerInteractivity(),parts.frame.addEventListener("load",()=>{layer.win=parts.frame.contentWindow,parts.frame.name=LAYER_FRAME_NAME;let committedSrc=parts.frame.getAttribute("src");!committedSrc||committedSrc==="about:blank"||(syncSimulatorStateToWindow(parts.frame.contentWindow),requestAnimationFrame(()=>{layer.titleBarStateReady||layer.closing||!layer.el.isConnected||(layer.titleBarStateReady=!0,syncLayerViewport(layer,resolvedTitleBarState(layer)))}))}),(document.body??document.documentElement).appendChild(parts.el),layer.win=parts.frame.contentWindow,startLayerNavigation(layer,mapLayerFrameUrl(target)),animateIn(layer),pushHistory){forwardStack.length=0;try{history.pushState({__mearl_layer__:layers.length},"",mapUrlForSync(target))}catch{}}return layer}function replaceLayer(sourceLayer,url2,callbackId,overlay,popId=null){if(sourceLayer.closing||layers[layers.length-1]!==sourceLayer){openLayer(url2,callbackId,overlay,sourceLayer.win??window,!0,popId);return}let replacement=openLayer(url2,callbackId,overlay,sourceLayer.openerWin,!1,popId);if(!replacement)return;sourceLayer.navigationPreparationCleanup?.(),sourceLayer.navigationPreparationCleanup=null,sourceLayer.entering&&(sourceLayer.entering=!1,enteringLayerCount=Math.max(enteringLayerCount-1,0),sourceLayer.enterTimer!==null&&clearTimeout(sourceLayer.enterTimer),sourceLayer.enterTransitionEnd&&sourceLayer.animEl.removeEventListener("transitionend",sourceLayer.enterTransitionEnd));let sourceIndex=layers.indexOf(sourceLayer);sourceIndex>=0&&layers.splice(sourceIndex,1),destroySimulatedNavigationBarView(sourceLayer.titleBarView),sourceLayer.el.remove(),forwardStack.length=0,syncLayerInteractivity(),syncActiveSystemBars();try{history.replaceState({__mearl_layer__:layers.length},"",mapUrlForSync(replacement.url))}catch{}}function closeLayer(layer,data,final,gotoEvent=!1,resumeOpener=!0){if(layer.closing)return;layer.navigationPreparationCleanup?.(),layer.navigationPreparationCleanup=null,layer.entering&&(layer.entering=!1,enteringLayerCount=Math.max(enteringLayerCount-1,0),layer.enterTimer!==null&&clearTimeout(layer.enterTimer),layer.enterTimer=null,layer.enterTransitionEnd&&(layer.animEl.removeEventListener("transitionend",layer.enterTransitionEnd),layer.enterTransitionEnd=null)),layer.closing=!0;let idx=layers.indexOf(layer);idx>=0&&layers.splice(idx,1),closingLayerCount+=1,blockClosingLayerInteractions(layer),syncLayerInteractivity(),syncActiveSystemBars(),final?forwardStack.length=0:forwardStack.push({url:layer.url,overlay:layer.overlay,openerWin:layer.openerWin,callbackId:layer.callbackId,storageId:layer.storageId,popId:layer.popId}),log3("close ←",layer.url,data===void 0?"":data),animateOut(layer,()=>{if(destroySimulatedNavigationBarView(layer.titleBarView),layer.el.remove(),closingLayerCount=Math.max(closingLayerCount-1,0),syncLayerInteractivity(),syncActiveSystemBars(),!!resumeOpener)if(layer.openerWin===window)links.getBridgeProtocol().handleResume({data,storageId:layer.storageId,callbackId:layer.callbackId,final,gotoEvent});else try{layer.openerWin.postMessage({source:SRC,type:"resume",data,storageId:layer.storageId,callbackId:layer.callbackId,final,gotoEvent},"*")}catch{}})}function closeToDepth(depth,data,final){for(;layers.length>depth;){let revealsTarget=layers.length===depth+1;closeLayer(layers[layers.length-1],revealsTarget?data:void 0,final,!1,revealsTarget)}}function closeAllLayers(data,gotoEvent=!1){let depth=layers.length;for(;layers.length>0;){let isRootmostLayer=layers.length===1;closeLayer(layers[layers.length-1],isRootmostLayer?data:void 0,!0,isRootmostLayer&&gotoEvent,isRootmostLayer)}if(depth>0)try{history.go(-depth)}catch{}return depth>0}function requestOverlayClose(layer){if(!(layer.closing||layers[layers.length-1]!==layer)){for(let selector of config2.overlay?.tapCloseSelectors??[])try{let control=layer.frame.contentDocument?.querySelector(selector);if(typeof control?.click!="function")continue;control.click();return}catch{}requestCloseOnTop(void 0)}}function forwardToDepth(depth){for(;layers.length<depth&&forwardStack.length>0;){let entry=forwardStack.pop();openLayer(entry.url,entry.callbackId,entry.overlay,entry.openerWin,!1,entry.popId)}}function requestCloseOnTop(data){if(layers.length===0){history.back();return}if(rootContainerActive){clearPendingRootHistoryDepth(),closeLayer(layers[layers.length-1],data,!0);let depth=layers.length,timer=setTimeout(()=>{pendingRootHistoryDepth=null,console.warn(TAG,"WebView 已出栈,但浏览器历史未在预期时间内同步",{depth})},PENDING_CLOSE_TIMEOUT_MS);pendingRootHistoryDepth={depth,timer},history.back();return}armPendingClose(data,8)}function isActiveBusinessWindow(target){let topLayer=layers[layers.length-1];return topLayer?topLayer.frame.contentWindow===target:rootFrame?rootFrame.contentWindow===target:target===window}function finishNativeBack(requestId,target,handled){pendingNativeBack?.requestId!==requestId||pendingNativeBack.target!==target||(clearPendingNativeBack(),!handled&&isActiveBusinessWindow(target)&&requestCloseOnTop(void 0))}function requestNativeBack(){if(!isTop||pendingNativeBack)return;let target=layers[layers.length-1]?.frame.contentWindow??rootFrame?.contentWindow??window;if(!target||target===window){links.getBridgeProtocol().handleNativeBack()||requestCloseOnTop(void 0);return}let requestId=++nativeBackRequestSeq,timer=setTimeout(()=>finishNativeBack(requestId,target,!1),120);pendingNativeBack={requestId,target,timer};try{target.postMessage({source:SRC,type:"nativeBack",requestId},"*")}catch{finishNativeBack(requestId,target,!1)}}function layerForWindow(source){if(source)for(let layer of layers){if(layer.win===source)return layer;let currentWindow=layer.frame.contentWindow;if(currentWindow&¤tWindow===source)return layer.win=currentWindow,layer}}if(isTop){if(!rootContainerActive){let rawPushState=history.pushState.bind(history),rawReplaceState=history.replaceState.bind(history),withDepth=state=>state==null?{__mearl_layer__:layers.length}:typeof state=="object"&&!Array.isArray(state)?{...state,__mearl_layer__:layers.length}:state;try{history.pushState=function(...args){rawPushState(withDepth(args[0]),args[1],args[2])},history.replaceState=function(...args){rawReplaceState(withDepth(args[0]),args[1],args[2])}}catch{}}try{readDepth(history.state)===null&&history.replaceState({__mearl_layer__:0},"")}catch{}window.addEventListener("popstate",e=>{let depth=readDepth(e.state);if(rootContainerActive){if(pendingRootHistoryDepth){let expectedDepth=pendingRootHistoryDepth.depth;if(clearPendingRootHistoryDepth(),depth===expectedDepth)return;console.warn(TAG,"浏览器历史深度与 WebView 出栈事务不一致",{expectedDepth,actualDepth:depth})}if(depth===null)return;depth<layers.length?closeToDepth(depth,void 0,!1):depth>layers.length&&forwardToDepth(depth);return}if(pendingClose){if(depth!==null&&depth<layers.length){let{data}=pendingClose;clearPendingClose(),closeToDepth(depth,data,!0)}else if(pendingClose.retries>0)armPendingClose(pendingClose.data,pendingClose.retries-1);else{let{data}=pendingClose;clearPendingClose(),closeToDepth(layers.length-1,data,!0)}return}depth!==null&&(depth<layers.length?closeToDepth(depth,void 0,!1):depth>layers.length&&forwardToDepth(depth))})}function broadcastAppMessage(message){links.getBridgeProtocol().handleAppMessage(message);let targets=[rootFrame?.contentWindow??null,...layers.filter(layer=>!layer.closing).map(layer=>layer.frame.contentWindow)];for(let target of targets)if(!(!target||target===window))try{target.postMessage({source:SRC,type:"appMessage",message},"*")}catch{}}function closeMegaPop(popId,data){let index=layers.findIndex(layer=>layer.popId===popId&&!layer.closing);if(index<0)return!1;let closingDepth=layers.length-index;closeToDepth(index,data,!0);try{history.go(-closingDepth)}catch{}return!0}function resizeMegaPop(popId,params){let layer=layers.find(candidate=>candidate.popId===popId&&!candidate.closing);if(!layer?.overlay)return!1;if(params.maxHeight!==void 0){let maxHeight=numberParam(params.maxHeight,1-layer.overlay.topRatio,0,1);layer.overlay.topRatio=1-maxHeight,layer.animEl.style.height=`${maxHeight*100}%`}if(params.maxWidth!==void 0){let maxWidth=numberParam(params.maxWidth,1,0,1);layer.overlay.widthRatio=maxWidth,layer.animEl.style.width=`${maxWidth*100}%`,layer.animEl.style.left=`${(1-maxWidth)/2*100}%`,layer.animEl.style.right="auto"}return params.animated===!0&&(layer.animEl.style.transition="height 200ms ease, width 200ms ease, left 200ms ease"),!0}function executeContainerData(action,params){if(action==="sharedFileRead"||action==="sharedFileWrite"){let fileName=typeof params.fileName=="string"?params.fileName:"";if(!fileName)return{success:!1,value:"missing fileName"};if(action==="sharedFileRead")return{success:!0,value:{data:sharedFiles.get(fileName)??""}};let data=typeof params.data=="string"?params.data:String(params.data??"");return sharedFiles.set(fileName,data),{success:!0,value:{}}}if(action==="sharedDataGet"){let keys=Array.isArray(params.keys)?params.keys.filter(key=>typeof key=="string"):[],data={};for(let key of keys)sharedData.has(key)&&(data[key]=sharedData.get(key));return{success:!0,value:{data}}}if(action==="sharedDataSet"){if(!params.data||typeof params.data!="object"||Array.isArray(params.data))return{success:!1,value:"missing shared data"};for(let[key,value]of Object.entries(params.data))value==null?sharedData.delete(key):sharedData.set(key,value);return{success:!0,value:{}}}if(action==="megaBroadcast")return!params.message||typeof params.message!="object"||Array.isArray(params.message)?{success:!1,value:"missing broadcast message"}:(broadcastAppMessage(params.message),{success:!0,value:{}});if(action==="megaKVSnapshot")return{success:!0,value:{entries:megaKVSnapshot()}};if(action==="megaKVMutation"){let operation=typeof params.operation=="string"?params.operation:"",bizId=typeof params.bizId=="string"?params.bizId:"";if(!bizId)return{success:!1,value:"missing bizID"};let key=typeof params.key=="string"?params.key:"";if((operation==="set"||operation==="remove")&&!key)return{success:!1,value:"missing key"};if(operation==="set"){if(typeof params.value!="string")return{success:!1,value:"missing value"};let entries=megaKVStorage.get(bizId)??new Map;entries.set(key,params.value),megaKVStorage.set(bizId,entries)}else if(operation==="remove"){let entries=megaKVStorage.get(bizId);entries?.delete(key),entries?.size===0&&megaKVStorage.delete(bizId)}else if(operation==="clear")megaKVStorage.delete(bizId);else return{success:!1,value:"unsupported KVStorage operation"};return persistMegaKVStorage(),broadcastAppMessage({kind:"megaKVStorage",operation,bizId,key,value:params.value}),{success:!0,value:{}}}if(action==="legacyBroadcastCreate"){let instanceId=typeof params.instanceId=="string"?params.instanceId:"";return instanceId?(legacyBroadcastChannels.add(instanceId),{success:!0,value:{}}):{success:!1,value:"missing instanceId"}}if(action==="legacyBroadcastPost"){let instanceId=typeof params.instanceId=="string"?params.instanceId:"";return instanceId?legacyBroadcastChannels.has(instanceId)?(broadcastAppMessage({kind:"legacyBroadcast",instanceId,message:params.message}),{success:!0,value:{}}):{success:!1,value:"broadcast channel not found"}:{success:!1,value:"missing instanceId"}}if(action==="legacyBroadcastClose"){let instanceId=typeof params.instanceId=="string"?params.instanceId:"";return instanceId?(legacyBroadcastChannels.delete(instanceId),{success:!0,value:{}}):{success:!1,value:"missing instanceId"}}if(action==="megaPopClose"){let popId=typeof params.popId=="string"?params.popId:"";return popId?closeMegaPop(popId,params.result)?{success:!0,value:{}}:{success:!1,value:"popId not found"}:{success:!1,value:"missing popId"}}if(action==="megaPopResize"){let popId=typeof params.popId=="string"?params.popId:"";return popId?resizeMegaPop(popId,params)?{success:!0,value:{}}:{success:!1,value:"popId not found"}:{success:!1,value:"missing popId"}}return{success:!1,value:"unsupported container data action"}}function requestContainerData(action,params,onSuccess,onFailure){if(isTop){let result=executeContainerData(action,params);setTimeout(()=>result.success?onSuccess(result.value):onFailure(result.value),0);return}let requestId=++containerDataRequestSeq;containerDataCallbacks.set(requestId,{success:onSuccess,failure:onFailure});try{window.top?.postMessage({source:SRC,type:"containerDataRequest",requestId,action,params},"*")}catch(error48){containerDataCallbacks.delete(requestId),onFailure(error48 instanceof Error?error48.message:String(error48))}}function requestOpen(url2,callbackId,webdialog,params){let overlay=resolveOverlayPresentation(url2,params,webdialog),popBeforeOpen=requestsPopBeforeOpen(url2,params),popId=typeof params?.__mearlMegaPopId=="string"?params.__mearlMegaPopId:null;isTop?openLayer(url2,callbackId,overlay,window,!0,popId):window.top?.postMessage({source:SRC,type:"open",url:url2,callbackId,overlay,popBeforeOpen,popId},"*")}function requestClose(data){let payload;try{payload=data===void 0?void 0:JSON.parse(JSON.stringify(data))}catch{payload=void 0}isTop?requestCloseOnTop(payload):window.top?.postMessage({source:SRC,type:"close",data:payload},"*")}if(window.addEventListener("message",event=>{let msg=event.data;if(!(!msg||typeof msg!="object")){if(msg.source==="mearl-content"&&(msg.type==="APP_BRIDGE_SIMULATOR_VISIBILITY"||msg.type==="APP_BRIDGE_RUNTIME_RESPONSES")){if(!isTop||event.source!==window)return;if(msg.type==="APP_BRIDGE_SIMULATOR_VISIBILITY"&&typeof msg.hidden=="boolean"){simulatedPageHidden=msg.hidden,links.getBridgeProtocol().handlePageVisibility(msg.hidden);let lifecycleMessage={source:SRC,type:"simulatorVisibility",hidden:msg.hidden};rootFrame?.contentWindow?.postMessage(lifecycleMessage,"*");for(let layer of layers)layer.closing||layer.frame.contentWindow?.postMessage(lifecycleMessage,"*")}else if(msg.type==="APP_BRIDGE_RUNTIME_RESPONSES"&&msg.profile===config2.profile&&msg.responses&&typeof msg.responses=="object"&&!Array.isArray(msg.responses)){let responses=msg.responses;runtimeResponses={...runtimeResponses??{},...responses},links.getBridgeProtocol().applyRuntimeResponses(responses);let configMessage={source:SRC,type:"runtimeResponses",profile:config2.profile,responses};rootFrame?.contentWindow?.postMessage(configMessage,"*");for(let layer of layers)layer.closing||layer.frame.contentWindow?.postMessage(configMessage,"*")}return}if(msg.source===SRC){if(isTop){let sourceLayer=layerForWindow(event.source),sourceIsRoot=!!(rootFrame?.contentWindow&&rootFrame.contentWindow===event.source);if(!sourceLayer&&!sourceIsRoot)return;if(msg.type==="open"&&typeof msg.url=="string"){let rawOverlay=msg.overlay&&typeof msg.overlay=="object"?msg.overlay:void 0,overlay=rawOverlay?{topRatio:numberParam(rawOverlay.topRatio,.2,0,1),widthRatio:numberParam(rawOverlay.widthRatio,1,0,1),radius:numberParam(rawOverlay.radius,0,0,50),maskAlpha:numberParam(rawOverlay.maskAlpha,.3,0,1),tapClose:boolParam(rawOverlay.tapClose,!0)}:resolveOverlayPresentation(msg.url,void 0,!1),callbackId=typeof msg.callbackId=="number"?msg.callbackId:0,popId=typeof msg.popId=="string"&&msg.popId?msg.popId:null;msg.popBeforeOpen===!0&&sourceLayer?replaceLayer(sourceLayer,msg.url,callbackId,overlay,popId):openLayer(msg.url,callbackId,overlay,event.source??window,!0,popId)}else if(msg.type==="close")requestCloseOnTop(msg.data);else if(msg.type==="closeAll"){let gotoEvent=msg.gotoEvent===!0;if(gotoEvent&&sourceIsRoot&&layers.length===0&&msg.data!==void 0)try{event.source.postMessage({source:SRC,type:"resume",data:msg.data,storageId:null,callbackId:0,final:!0,gotoEvent:!0},"*")}catch{}else closeAllLayers(msg.data,gotoEvent)}else if(msg.type==="appMessageToOpener"&&sourceLayer){let target=sourceLayer.openerWin;if(target===window)links.getBridgeProtocol().handleAppMessage(msg.message);else try{target.postMessage({source:SRC,type:"appMessage",message:msg.message},"*")}catch{}}else if(msg.type==="containerDataRequest"&&typeof msg.requestId=="number"&&typeof msg.action=="string"&&msg.params&&typeof msg.params=="object"&&!Array.isArray(msg.params)&&event.source){let result=executeContainerData(msg.action,msg.params);try{event.source.postMessage({source:SRC,type:"containerDataResponse",requestId:msg.requestId,success:result.success,value:result.value},"*")}catch{}}else if(msg.type==="nativeBackResult"&&typeof msg.requestId=="number"&&typeof msg.handled=="boolean"&&event.source)finishNativeBack(msg.requestId,event.source,msg.handled);else if(msg.type==="urlChanged"&&typeof msg.url=="string"){let topLayer=layers[layers.length-1];if(sourceIsRoot&&!topLayer){rootBusinessUrl=msg.url;let mapped=mapUrlForSync(msg.url);if(mapped)try{history.replaceState({__mearl_layer__:0},"",mapped)}catch{}}else if(topLayer&&!topLayer.closing&&sourceLayer===topLayer){topLayer.url=msg.url,topLayer.titleBarStateExplicit&&topLayer.titleBarState&&cacheExplicitTitleBarState(topLayer,topLayer.titleBarState);let mapped=mapUrlForSync(msg.url);if(mapped)try{history.replaceState({__mearl_layer__:layers.length},"",mapped)}catch{}}}else if(msg.type==="title"&&typeof msg.title=="string"){let topLayer=layers[layers.length-1];if(sourceIsRoot&&!topLayer)try{document.title=msg.title,syncSimulatedTitleBar()}catch{}else if(topLayer&&sourceLayer===topLayer){document.title=msg.title;let state=resolvedTitleBarState(topLayer);topLayer.titleBarState={...state,title:msg.title},syncLayerViewport(topLayer,topLayer.titleBarState)}}else if(msg.type==="titleBarState"){let state=parseReportedTitleBarState(msg.state);if(state&&sourceIsRoot)links.getSystemBars().setPresentedRootTitleBarState(state);else if(state&&sourceLayer){let explicit=msg.explicit===!0;sourceLayer.titleBarStateReady=!0,explicit?(sourceLayer.titleBarState=state,sourceLayer.titleBarStateExplicit=!0,cacheExplicitTitleBarState(sourceLayer,state)):sourceLayer.titleBarStateExplicit||(sourceLayer.titleBarState=state);let resolvedState=sourceLayer.titleBarState??state;syncLayerViewport(sourceLayer,resolvedState)}}}else if(msg.type==="simulatorVisibility"&&typeof msg.hidden=="boolean"){if(event.source!==window.top)return;links.getBridgeProtocol().handlePageVisibility(msg.hidden)}else if(msg.type==="appMessage"){if(event.source!==window.top)return;links.getBridgeProtocol().handleAppMessage(msg.message)}else if(msg.type==="nativeBack"&&typeof msg.requestId=="number"){if(event.source!==window.top)return;let handled=links.getBridgeProtocol().handleNativeBack();window.top?.postMessage({source:SRC,type:"nativeBackResult",requestId:msg.requestId,handled},"*")}else if(msg.type==="containerDataResponse"&&typeof msg.requestId=="number"){if(event.source!==window.top)return;let callback=containerDataCallbacks.get(msg.requestId);if(!callback)return;containerDataCallbacks.delete(msg.requestId),msg.success===!0?callback.success(msg.value):callback.failure(msg.value)}else if(msg.type==="runtimeResponses"&&msg.profile===config2.profile&&msg.responses&&typeof msg.responses=="object"&&!Array.isArray(msg.responses)){if(event.source!==window.top)return;links.getBridgeProtocol().applyRuntimeResponses(msg.responses)}else if(msg.type==="resume"){if(event.source!==window.top)return;links.getBridgeProtocol().handleResume({data:msg.data,storageId:msg.storageId??null,callbackId:typeof msg.callbackId=="number"?msg.callbackId:0,final:msg.final===!0,gotoEvent:msg.gotoEvent===!0})}else event.source!==window.top&&window.top?.postMessage(msg,"*");return}pageTransport.handleMessage(msg)}}),!isTop&&isContainerFrame){let reportUrl=()=>{try{window.top?.postMessage({source:SRC,type:"urlChanged",url:restoreLayerBusinessUrl(location.href)},"*")}catch{}};try{let origPushState=history.pushState.bind(history),origReplaceState=history.replaceState.bind(history);history.pushState=function(...args){origPushState(...args),reportUrl()},history.replaceState=function(...args){origReplaceState(...args),reportUrl()},window.addEventListener("popstate",reportUrl),window.addEventListener("hashchange",reportUrl)}catch{}}if(isContainerFrame){let requestProxyLocationOpen=url2=>{if(links.getBridgeProtocol().handleMaybeScheme(url2))return!0;try{let current=new URL(restoreLayerBusinessUrl(location.href)),target=new URL(url2,current);return!/^https?:$/.test(target.protocol)||target.origin===current.origin&&target.pathname===current.pathname&&target.search===current.search?!1:(requestOpen(target.href,0,!1),!0)}catch{return!1}};Object.defineProperty(window,"__PROXY_LOCATION__",{value:{get href(){return location.href},set href(url2){requestProxyLocationOpen(url2)||(location.href=mapLayerFrameUrl(url2))},replace(url2){links.getBridgeProtocol().handleMaybeScheme(url2)||location.replace(mapLayerFrameUrl(url2))},assign(url2){requestProxyLocationOpen(url2)||location.assign(mapLayerFrameUrl(url2))}},writable:!1,configurable:!0})}if(isContainerFrame){document.addEventListener("click",event=>{let el=event.target;for(;el&&el.tagName!=="A";)el=el.parentElement;if(!el)return;let href=el.getAttribute("href");if(href){if(links.getBridgeProtocol().handleMaybeScheme(href)){event.preventDefault(),event.stopPropagation();return}/^https?:/i.test(href)&&el.getAttribute("target")==="_blank"&&(event.preventDefault(),event.stopPropagation(),requestOpen(href,0,!1))}},!0);let origOpen=window.open;window.open=function(url2,target,features){let urlStr=typeof url2=="string"?url2:url2 instanceof URL?url2.href:"";return links.getBridgeProtocol().handleMaybeScheme(urlStr)?null:/^https?:/i.test(urlStr)?(requestOpen(urlStr,0,!1),null):origOpen?origOpen.call(window,url2,target,features):null};try{let proto=Location.prototype,origAssign=proto.assign,origReplace=proto.replace;origAssign&&(proto.assign=function(url2){if(links.getBridgeProtocol().handleMaybeScheme(url2))return;let upgraded=location.protocol==="https:"&&url2.startsWith("http:")?"https:"+url2.slice(5):url2;origAssign.call(this,upgraded)}),origReplace&&(proto.replace=function(url2){if(links.getBridgeProtocol().handleMaybeScheme(url2))return;let upgraded=location.protocol==="https:"&&url2.startsWith("http:")?"https:"+url2.slice(5):url2;origReplace.call(this,upgraded)})}catch{}}return log3("容器环境已就绪",isTop?"(top)":isRootFrame?"(root)":isLayerFrame?"(layer)":"(iframe,仅桥)"),{getRootFrame:()=>rootFrame,getLayers:()=>layers,getClosingLayerCount:()=>closingLayerCount,requestOpen,requestClose,requestNativeBack,requestContainerData,closeAllLayers}}var APP_PROFILE_RUNTIME_FACTORIES={environment:installAppProfileEnvironment,containerStack:installAppProfileContainerStack,bridgeProtocol:installAppProfileBridgeProtocol,pageTransport:installAppProfilePageTransport,systemBars:installAppProfileSystemBars};function buildAppProfileRuntimeCallSource(configExpression){return`(${installAppProfileRuntime.toString()})(${configExpression},{environment:${installAppProfileEnvironment.toString()},pageTransport:${installAppProfilePageTransport.toString()},containerStack:${installAppProfileContainerStack.toString()},systemBars:${installAppProfileSystemBars.toString()},bridgeProtocol:${installAppProfileBridgeProtocol.toString()}})`}function installAppProfileRuntime(config2,factories=APP_PROFILE_RUNTIME_FACTORIES){let environment=factories.environment(config2);if(!environment)return;let pageTransport=factories.pageTransport(config2,environment),containerStack=factories.containerStack(config2,environment,{pageTransport,getSystemBars:()=>systemBars,getBridgeProtocol:()=>bridgeProtocol}),systemBars=factories.systemBars(config2,environment,{getRootFrame:containerStack.getRootFrame,getLayers:containerStack.getLayers,getClosingLayerCount:containerStack.getClosingLayerCount,requestClose:containerStack.requestClose,requestNativeBack:containerStack.requestNativeBack}),bridgeProtocol=factories.bridgeProtocol(config2,environment,{pageTransport,systemBars,requestOpen:containerStack.requestOpen,requestClose:containerStack.requestClose,requestCloseAll:containerStack.closeAllLayers,requestContainerData:containerStack.requestContainerData})}import https from"node:https";import http3 from"node:http";var TYPE_INTO_ELEMENT_SRC=typeIntoElement.toString(),CLICK_ELEMENT_VIA_JS_SRC=clickElementViaJS.toString(),GET_CLICK_COORDS_FROM_NODE_SRC=getClickCoordsFromNode.toString();function nodeFetch(urlStr,options={}){return new Promise((resolve3,reject)=>{let url2=new URL(urlStr),isHttps=url2.protocol==="https:",lib=isHttps?https:http3,{method="GET",headers={},body,timeoutMs=3e4}=options,req=lib.request({host:url2.hostname,port:url2.port||(isHttps?443:80),path:url2.pathname+url2.search,method,headers},res=>{let responseHeaders={};for(let[key,value]of Object.entries(res.headers))typeof value=="string"?responseHeaders[key]=value:Array.isArray(value)&&(responseHeaders[key]=value.join(", "));let chunks=[];res.on("data",chunk=>chunks.push(Buffer.from(chunk))),res.on("end",()=>{let bodyBuffer=Buffer.concat(chunks);resolve3({status:res.statusCode??0,statusText:res.statusMessage??"",headers:responseHeaders,body:bodyBuffer.toString("utf-8"),bodyBuffer})})});req.on("error",reject),req.setTimeout(timeoutMs,()=>{req.destroy(),reject(new Error(`Request timeout: ${urlStr}`))}),body&&req.write(body),req.end()})}async function getCookiesForUrl(session,targetUrl){let result=await session.client.sendCommand("Network.getCookies",{urls:[targetUrl]}),map2=new Map;for(let cookie of result.cookies??[])map2.set(cookie.name,cookie.value);return map2}function decodeTracknick(raw){if(!raw)return"";try{return decodeURIComponent(raw).replace(/\\u([0-9a-fA-F]{4})/g,(_match,hex3)=>String.fromCharCode(parseInt(hex3,16)))}catch{return raw}}function buildMultipartFormBody(fields){let boundary=`----mearl-${Date.now()}-${Math.random().toString(36).slice(2)}`,body=[...Object.entries(fields).map(([name,value])=>`--${boundary}\r
|
|
749
752
|
Content-Disposition: form-data; name="${name}"\r
|
|
750
753
|
\r
|
|
751
754
|
${value}\r
|
|
@@ -753,7 +756,29 @@ ${value}\r
|
|
|
753
756
|
`].join("");return{contentType:`multipart/form-data; boundary=${boundary}`,body}}async function waitForPageLoad(session,timeoutMs){return new Promise((resolve3,reject)=>{let settled=!1,removeLoadListener=()=>{},finish=error48=>{settled||(settled=!0,clearTimeout(timer),removeLoadListener(),error48?reject(error48):resolve3())},timer=setTimeout(()=>{finish(new Error(`Page load timeout after ${timeoutMs}ms`))},timeoutMs);removeLoadListener=session.client.on("Page.loadEventFired",()=>finish()),session.client.sendCommand("Runtime.evaluate",{expression:"document.readyState",returnByValue:!0}).then(result=>{result.result?.value==="complete"&&finish()}).catch(()=>{})})}async function getPageViewportSize(session){let result=await session.client.sendCommand("Runtime.evaluate",{expression:`({
|
|
754
757
|
width: window.visualViewport ? window.visualViewport.width : window.innerWidth,
|
|
755
758
|
height: window.visualViewport ? window.visualViewport.height : window.innerHeight
|
|
756
|
-
})`,returnByValue:!0}),width=result.result?.value?.width,height=result.result?.value?.height;return typeof width!="number"||typeof height!="number"||width<=0||height<=0?null:{width,height}}async function getCdpInputViewportSize(session){let metrics;try{metrics=await session.client.sendCommand("Page.getLayoutMetrics",{})}catch{return null}let viewport=metrics.cssVisualViewport??metrics.visualViewport??metrics.cssLayoutViewport??metrics.layoutViewport,width=viewport?.clientWidth,height=viewport?.clientHeight;return typeof width!="number"||typeof height!="number"||width<=0||height<=0?null:{width,height}}async function toCdpInputPoint(session,x,y){let[pageViewport,cdpViewport]=await Promise.all([getPageViewportSize(session),getCdpInputViewportSize(session)]);if(!pageViewport||!cdpViewport)return{x,y};let scaleX=cdpViewport.width/pageViewport.width,scaleY=cdpViewport.height/pageViewport.height;return!Number.isFinite(scaleX)||!Number.isFinite(scaleY)||scaleX<=0||scaleY<=0||Math.abs(scaleX-1)<.01&&Math.abs(scaleY-1)<.01?{x,y}:{x:x*scaleX,y:y*scaleY}}async function dispatchCdpClick(session,x,y,pointerType){let point=await toCdpInputPoint(session,x,y);if(pointerType==="touch"){await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchStart",touchPoints:[point]}),await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchEnd",touchPoints:[]});return}await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseMoved",x:point.x,y:point.y}),await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mousePressed",x:point.x,y:point.y,button:"left",buttons:1,clickCount:1}),await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseReleased",x:point.x,y:point.y,button:"left",buttons:0,clickCount:1})}async function dispatchCdpDrag(session,from,to,pointerType,durationMs){let[start,end]=await Promise.all([toCdpInputPoint(session,from.x,from.y),toCdpInputPoint(session,to.x,to.y)]),path23=buildPageDragPath(start,end,durationMs),waitForNextPoint=async()=>{path23.intervalMs<=0||await new Promise(resolve3=>setTimeout(resolve3,path23.intervalMs))};if(pointerType==="touch"){await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchStart",touchPoints:[start]});let primaryError2;try{for(let point of path23.points)await waitForNextPoint(),await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchMove",touchPoints:[point]})}catch(error48){throw primaryError2=error48,error48}finally{await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchEnd",touchPoints:[]}).catch(error48=>{if(primaryError2===void 0)throw error48})}return{steps:path23.points.length}}await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseMoved",x:start.x,y:start.y}),await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mousePressed",x:start.x,y:start.y,button:"left",buttons:1,clickCount:1});let primaryError;try{for(let point of path23.points)await waitForNextPoint(),await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseMoved",x:point.x,y:point.y,button:"left",buttons:1})}catch(error48){throw primaryError=error48,error48}finally{await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseReleased",x:end.x,y:end.y,button:"left",buttons:0,clickCount:1}).catch(error48=>{if(primaryError===void 0)throw error48})}return{steps:path23.points.length}}async function sendCdpInputCommand(session,method,params){try{await session.client.sendCommand(method,params,1e4)}catch(error48){if(error48 instanceof Error&&error48.message===`CDP command timeout: ${method}`){let eventType=typeof params.type=="string"?` (${params.type})`:"";throw new Error(`CDP ${method}${eventType} timed out after ${1e4}ms. The page may already have changed; verify its current state before retrying.`,{cause:error48})}throw error48}}async function resolveBackendNodeObjectId(session,backendNodeId){let objectId=(await session.client.sendCommand("DOM.resolveNode",{backendNodeId})).object?.objectId;if(!objectId)throw new Error(`Cannot resolve element for backendNodeId ${backendNodeId}`);return objectId}
|
|
759
|
+
})`,returnByValue:!0}),width=result.result?.value?.width,height=result.result?.value?.height;return typeof width!="number"||typeof height!="number"||width<=0||height<=0?null:{width,height}}async function getCdpInputViewportSize(session){let metrics;try{metrics=await session.client.sendCommand("Page.getLayoutMetrics",{})}catch{return null}let viewport=metrics.cssVisualViewport??metrics.visualViewport??metrics.cssLayoutViewport??metrics.layoutViewport,width=viewport?.clientWidth,height=viewport?.clientHeight;return typeof width!="number"||typeof height!="number"||width<=0||height<=0?null:{width,height}}async function toCdpInputPoint(session,x,y){let[pageViewport,cdpViewport]=await Promise.all([getPageViewportSize(session),getCdpInputViewportSize(session)]);if(!pageViewport||!cdpViewport)return{x,y};let scaleX=cdpViewport.width/pageViewport.width,scaleY=cdpViewport.height/pageViewport.height;return!Number.isFinite(scaleX)||!Number.isFinite(scaleY)||scaleX<=0||scaleY<=0||Math.abs(scaleX-1)<.01&&Math.abs(scaleY-1)<.01?{x,y}:{x:x*scaleX,y:y*scaleY}}async function dispatchCdpClick(session,x,y,pointerType){let point=await toCdpInputPoint(session,x,y);if(pointerType==="touch"){await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchStart",touchPoints:[point]}),await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchEnd",touchPoints:[]});return}await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseMoved",x:point.x,y:point.y}),await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mousePressed",x:point.x,y:point.y,button:"left",buttons:1,clickCount:1}),await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseReleased",x:point.x,y:point.y,button:"left",buttons:0,clickCount:1})}async function dispatchCdpDrag(session,from,to,pointerType,durationMs){let[start,end]=await Promise.all([toCdpInputPoint(session,from.x,from.y),toCdpInputPoint(session,to.x,to.y)]),path23=buildPageDragPath(start,end,durationMs),waitForNextPoint=async()=>{path23.intervalMs<=0||await new Promise(resolve3=>setTimeout(resolve3,path23.intervalMs))};if(pointerType==="touch"){await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchStart",touchPoints:[start]});let primaryError2;try{for(let point of path23.points)await waitForNextPoint(),await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchMove",touchPoints:[point]})}catch(error48){throw primaryError2=error48,error48}finally{await sendCdpInputCommand(session,"Input.dispatchTouchEvent",{type:"touchEnd",touchPoints:[]}).catch(error48=>{if(primaryError2===void 0)throw error48})}return{steps:path23.points.length}}await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseMoved",x:start.x,y:start.y}),await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mousePressed",x:start.x,y:start.y,button:"left",buttons:1,clickCount:1});let primaryError;try{for(let point of path23.points)await waitForNextPoint(),await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseMoved",x:point.x,y:point.y,button:"left",buttons:1})}catch(error48){throw primaryError=error48,error48}finally{await sendCdpInputCommand(session,"Input.dispatchMouseEvent",{type:"mouseReleased",x:end.x,y:end.y,button:"left",buttons:0,clickCount:1}).catch(error48=>{if(primaryError===void 0)throw error48})}return{steps:path23.points.length}}async function sendCdpInputCommand(session,method,params){try{await session.client.sendCommand(method,params,1e4)}catch(error48){if(error48 instanceof Error&&error48.message===`CDP command timeout: ${method}`){let eventType=typeof params.type=="string"?` (${params.type})`:"";throw new Error(`CDP ${method}${eventType} timed out after ${1e4}ms. The page may already have changed; verify its current state before retrying.`,{cause:error48})}throw error48}}async function resolveBackendNodeObjectId(session,backendNodeId){let objectId=(await session.client.sendCommand("DOM.resolveNode",{backendNodeId})).object?.objectId;if(!objectId)throw new Error(`Cannot resolve element for backendNodeId ${backendNodeId}`);return objectId}import{readFile}from"node:fs/promises";import{randomUUID}from"node:crypto";import{stat}from"node:fs/promises";import{basename,isAbsolute}from"node:path";async function resolveSendRequestFile(file2,index){if(!file2||typeof file2!="object")throw new Error(`files[${index}] must be an object`);let fieldName=assertSafeSendRequestMultipartValue(file2.fieldName,`files[${index}].fieldName`),hasPath=typeof file2.filePath=="string"&&file2.filePath.length>0,hasBase64=typeof file2.base64=="string";if(hasPath===hasBase64)throw new Error(`files[${index}] must provide exactly one of filePath or base64`);let filename,byteLength2,filePath,content;if(hasPath){if(filePath=file2.filePath,!isAbsolute(filePath))throw new Error(`files[${index}].filePath must be an absolute path`);let metadata;try{metadata=await stat(filePath)}catch(error48){throw new Error(`Unable to read files[${index}].filePath: ${error48 instanceof Error?error48.message:String(error48)}`,{cause:error48})}if(!metadata.isFile())throw new Error(`files[${index}].filePath is not a file`);filename=file2.filename||basename(filePath),byteLength2=metadata.size}else{if(filename=file2.filename||"",!filename)throw new Error(`files[${index}].filename is required when base64 is used`);let bytes=decodeSendRequestBase64Bytes(file2.base64,`files[${index}].base64`);content=Buffer.from(bytes),byteLength2=content.byteLength}let safeFilename=assertSafeSendRequestMultipartValue(filename,`files[${index}].filename`),contentType=typeof file2.contentType=="string"&&file2.contentType.trim()?assertSafeSendRequestMultipartValue(file2.contentType.trim(),`files[${index}].contentType`):inferSendRequestContentType(filename);return{descriptor:{fieldName,filename:safeFilename,contentType,byteLength:byteLength2},filePath,content}}async function resolveSendRequestFiles(files){assertSendRequestFileCount(files.length);let resolved=await Promise.all(files.map(resolveSendRequestFile));return assertSendRequestFileLimits(resolved.map(file2=>file2.descriptor.byteLength)),assertSendRequestBase64FileLimits(resolved.flatMap(file2=>file2.content?[file2.content.byteLength]:[])),resolved}var ALLOWED_METHODS=new Set(["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"]);function setHeader(headers,name,value){let existing=findSendRequestHeaderName(headers,name);existing&&existing!==name&&delete headers[existing],headers[name]=value}function removeHeader(headers,name){let existing=findSendRequestHeaderName(headers,name);existing&&delete headers[existing]}function escapeMultipartQuotedValue(value){return value.replace(/\\/g,"\\\\").replace(/"/g,"%22")}async function readMultipartFiles(files){let resolved=await resolveSendRequestFiles(files),contents=await Promise.all(resolved.map(async(file2,index)=>{if(file2.content)return file2.content;try{return await readFile(file2.filePath)}catch(error48){throw new Error(`Unable to read files[${index}].filePath: ${error48 instanceof Error?error48.message:String(error48)}`,{cause:error48})}}));return assertSendRequestFileLimits(contents.map(content=>content.byteLength)),resolved.map((file2,index)=>({fieldName:file2.descriptor.fieldName,filename:file2.descriptor.filename,contentType:file2.descriptor.contentType,content:contents[index]}))}async function buildMultipartBody(formData,files){if(formData!==void 0&&(formData===null||typeof formData!="object"||Array.isArray(formData)))throw new Error("formData must be an object");if(files!==void 0&&!Array.isArray(files))throw new Error("files must be an array");let resolvedFiles=await readMultipartFiles(files??[]),boundary=`----mearl-${randomUUID()}`,chunks=[];for(let[name,value]of Object.entries(formData??{})){if(!["string","number","boolean"].includes(typeof value))throw new Error(`formData.${name} must be a string, number, or boolean`);let safeName=escapeMultipartQuotedValue(assertSafeSendRequestMultipartValue(name,`formData field "${name}"`));chunks.push(Buffer.from(`--${boundary}\r
|
|
760
|
+
Content-Disposition: form-data; name="${safeName}"\r
|
|
761
|
+
\r
|
|
762
|
+
${String(value)}\r
|
|
763
|
+
`))}for(let file2 of resolvedFiles){let fieldName=escapeMultipartQuotedValue(file2.fieldName),filename=escapeMultipartQuotedValue(file2.filename);chunks.push(Buffer.from(`--${boundary}\r
|
|
764
|
+
Content-Disposition: form-data; name="${fieldName}"; filename="${filename}"\r
|
|
765
|
+
Content-Type: ${file2.contentType}\r
|
|
766
|
+
\r
|
|
767
|
+
`),file2.content,Buffer.from(`\r
|
|
768
|
+
`))}return chunks.push(Buffer.from(`--${boundary}--\r
|
|
769
|
+
`)),{contentType:`multipart/form-data; boundary=${boundary}`,body:Buffer.concat(chunks)}}function hasMultipartPayload(data){return data.formData!==void 0||data.files!==void 0}async function executeNodeSendRequest(data,cookieMap=new Map){let{url:url2,method="GET",headers={},params,body,formData,files,responseType="auto",timeout=3e4}=data;if(!url2||typeof url2!="string"||url2.trim()==="")throw new Error("Invalid url: url must be a non-empty string");let normalizedMethod=method.toUpperCase();if(!ALLOWED_METHODS.has(normalizedMethod))throw new Error(`Invalid method: ${method}. Allowed: ${[...ALLOWED_METHODS].join(", ")}`);if(!Number.isFinite(timeout)||timeout<=0)throw new Error("timeout must be a positive number");let targetUrl=new URL(url2);for(let[key,value]of Object.entries(params??{}))targetUrl.searchParams.set(key,String(value));let requestHeaders={Accept:"application/json, text/plain, */*","Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8","User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",...headers},resolvedSourceHeaders=getSendRequestSourceHeaders(targetUrl,headers);resolvedSourceHeaders.referer?setHeader(requestHeaders,"Referer",resolvedSourceHeaders.referer):removeHeader(requestHeaders,"Referer"),resolvedSourceHeaders.origin?setHeader(requestHeaders,"Origin",resolvedSourceHeaders.origin):removeHeader(requestHeaders,"Origin");let cookieHeader=[...cookieMap.entries()].map(([key,value])=>`${key}=${value}`).join("; ");cookieHeader&&setHeader(requestHeaders,"Cookie",cookieHeader);let xsrfToken=cookieMap.get("XSRF-TOKEN");xsrfToken&&!findSendRequestHeaderName(requestHeaders,"x-xsrf-token")&&setHeader(requestHeaders,"X-XSRF-TOKEN",xsrfToken);let requestBody;if(hasMultipartPayload(data)){if(body!=null)throw new Error("body cannot be combined with formData or files");if(normalizedMethod==="GET"||normalizedMethod==="HEAD")throw new Error(`${normalizedMethod} requests cannot use formData or files`);if(findSendRequestHeaderName(requestHeaders,"content-type"))throw new Error("Do not set Content-Type when using formData or files; Mearl sets the boundary");let multipart=await buildMultipartBody(formData,files);requestBody=multipart.body,setHeader(requestHeaders,"Content-Type",multipart.contentType),setHeader(requestHeaders,"Content-Length",String(multipart.body.byteLength))}else body!=null&&!["GET","HEAD"].includes(normalizedMethod)&&(typeof body=="string"?(requestBody=body,findSendRequestHeaderName(requestHeaders,"content-type")||setHeader(requestHeaders,"Content-Type","text/plain")):(requestBody=JSON.stringify(body),findSendRequestHeaderName(requestHeaders,"content-type")||setHeader(requestHeaders,"Content-Type","application/json")));let result=await nodeFetch(targetUrl.toString(),{method:normalizedMethod,headers:requestHeaders,body:requestBody,timeoutMs:timeout}),contentType=(result.headers["content-type"]??"").split(";")[0].trim().toLowerCase(),responseHeaders=Object.fromEntries(Object.entries(result.headers).filter(([name])=>name.toLowerCase()!=="set-cookie"&&name.toLowerCase()!=="set-cookie2")),responseBody,bodyType;if(responseType==="auto"&&isBinarySendRequestContentType(contentType))responseBody=result.bodyBuffer.toString("base64"),bodyType="base64";else{let trimmed=result.body.trimStart();if(responseType==="json"||responseType==="auto"&&contentType.includes("application/json")||responseType==="auto"&&(trimmed.startsWith("{")||trimmed.startsWith("[")))try{responseBody=JSON.parse(result.body),bodyType="json"}catch{if(responseType==="json")throw new Error("send_request expected a JSON response");responseBody=result.body,bodyType="text"}else responseBody=result.body,bodyType="text"}return{success:!0,status:result.status,statusText:result.statusText,headers:responseHeaders,body:responseBody,bodyType,attachedCookieCount:cookieMap.size}}async function cdpSendRequest(session,data){if(!data.url||typeof data.url!="string")throw new Error("Invalid url: url must be a non-empty string");let cookieMap=new Map;if(data.withCookies!==!1)try{cookieMap=await getCookiesForUrl(session,new URL(data.url).toString())}catch{}return executeNodeSendRequest(data,cookieMap)}async function prepareCdpMtopRequest(session,data,stream=!1){let resolved=resolveMtopRequest(data),cookieMap=await getCookiesForUrl(session,resolved.gatewayUrl.toString()),prepared=prepareSignedMtopRequest(resolved,cookieMap,stream);return{...prepared,requestHeaders:{...prepared.cookieHeader?{Cookie:prepared.cookieHeader}:{},...prepared.requestHeaders}}}async function cdpSendMtopRequest(session,data){let prepared=await prepareCdpMtopRequest(session,data),result=await nodeFetch(prepared.targetUrl.toString(),{method:prepared.normalizedMethod,headers:prepared.requestHeaders,body:prepared.body,timeoutMs:prepared.timeout});return{success:!0,response:parseMtopResponseText(result.body),requestData:prepared.requestData}}async function cdpSendMtopStreamRequest(session,data,callbacks){let prepared=await prepareCdpMtopRequest(session,data,!0),controller=new AbortController,timeoutId=setTimeout(()=>controller.abort(),prepared.timeout);try{await callbacks.onRequestPrepared?.({method:prepared.normalizedMethod,url:prepared.targetUrl.toString(),requestHeaders:Object.entries(prepared.requestHeaders).map(([name,value])=>({name,value}))});let response=await fetch(prepared.targetUrl,{method:prepared.normalizedMethod,headers:prepared.requestHeaders,body:prepared.body,signal:controller.signal}),responseHeaders=[];return response.headers.forEach((value,name)=>{name.toLowerCase()!=="set-cookie"&&responseHeaders.push({name,value})}),await callbacks.onResponse?.({status:response.status,statusText:response.statusText,responseHeaders}),{success:!0,response:await consumeMtopSseResponse(response,event=>callbacks.onReceive(event.data)),requestData:prepared.requestData}}catch(error48){throw error48 instanceof Error&&error48.name==="AbortError"?new Error(`send_mtop_stream timed out after ${prepared.timeout}ms: ${prepared.api}`,{cause:error48}):new Error(`send_mtop_stream failed: ${error48 instanceof Error?error48.message:String(error48)}`,{cause:error48})}finally{clearTimeout(timeoutId)}}async function cdpGetApiSchema(session,data){let{api,version:version2="1.0"}=data;if(!api||typeof api!="string")throw new Error("Invalid api: api must be a non-empty string");let targetUrl="https://ultramax.alibaba-inc.com/ultramax/api/query",payload=JSON.stringify({type:"RPC",rpcName:api,rpcVersion:version2}),cookieMap=await getCookiesForUrl(session,targetUrl),cookieHeader=buildCookieHeaderValue(cookieMap),result=await nodeFetch(targetUrl,{method:"POST",headers:{"Content-Type":"application/json",...cookieHeader?{Cookie:cookieHeader}:{}},body:payload,timeoutMs:15e3});if(result.status!==200)throw new Error(`Ultramax API returned status ${result.status}`);let responseBody;try{responseBody=JSON.parse(result.body)}catch{throw new Error(`Failed to parse Ultramax response: ${result.body.slice(0,200)}`)}return responseBody}registerActions([{name:"send_request",session:"page",handler:cdpSendRequest},{name:"send_mtop_request",session:"page",handler:cdpSendMtopRequest},{name:"get_api_schema",session:"page",handler:cdpGetApiSchema}]);var registries=new WeakMap;function getPageRefRegistry(session){let registry2=registries.get(session);if(!registry2){registry2=new BackendNodeRefRegistry,registries.set(session,registry2);let activeRegistry=registry2;session.client.on("Page.frameNavigated",params=>{params.frame?.parentId||activeRegistry.clearDocument()})}return registry2}function beginPageSnapshotRefs(session){return getPageRefRegistry(session).beginSnapshot()}function resolvePageRef(session,ref){return registries.get(session)?.resolve(ref)}function deletePageRef(session,ref){registries.get(session)?.delete(ref)}function clearPageRefsForNavigation(session){registries.get(session)?.clearDocument()}async function enrichCdpPageChangeSetWithRefs(session,observation){return enrichPageChangeSetWithRefs(observation,getPageRefRegistry(session),selectors=>resolveUniqueBackendNodeIds((method,params)=>session.client.sendCommand(method,params),selectors),(node,backendNodeId)=>({backendNodeId,role:node.role??"",name:node.name??""}))}var APP_PROFILE_BINDING="__mearlCdpAppProfileRelay",appProfileStates=new WeakMap;function serializeForSource(value){return JSON.stringify(value).replace(/[\u2028\u2029]/g,character=>character==="\u2028"?"\\u2028":"\\u2029")}function installCdpAppProfileRelay(bindingName){let browser=globalThis,target=globalThis;target.__mearlCdpAppProfileRelayInstalled__||(target.__mearlCdpAppProfileRelayInstalled__=!0,browser.addEventListener("message",event=>{if(event.source!==globalThis)return;let message=event.data;if(!message||message.source!=="mearl-app-bridge")return;let requestId=message.requestId;if(typeof requestId!="number")return;if(message.type==="prepareWebView"){browser.postMessage({source:"mearl-content",type:"APP_BRIDGE_PREPARE_WEBVIEW_RESPONSE",requestId,result:{success:!0}},"*");return}if(message.type!=="mtop"&&message.type!=="mtopStream"&&message.type!=="userInfo")return;let binding=target[bindingName];if(typeof binding=="function")try{binding(JSON.stringify({type:message.type,requestId,payload:message.payload}))}catch{}}))}function installEarlyAppProfileEnvironment(config2){let browser=globalThis,target=globalThis;for(let[key,value]of Object.entries(config2.globals))try{target[key]=value}catch{}let insets=config2.safeAreaInsets??{top:config2.statusBarHeight,right:0,bottom:0,left:0};target.__STATUS_BAR_HEIGHT__=config2.statusBarHeight,target.__SAFE_AREA_INSET_BOTTOM__=insets.bottom;for(let[key,value]of[["userAgent",config2.userAgent],["platform",config2.navigatorPlatform],["vendor","Apple Computer, Inc."],["appVersion",config2.userAgent.replace(/^Mozilla\//,"")],["maxTouchPoints",config2.maxTouchPoints]])try{Object.defineProperty(browser.navigator,key,{configurable:!0,get:()=>value})}catch{}}function installWhenDocumentElementExists(install){let browser=globalThis;if(browser.document.documentElement){install();return}let observer=new browser.MutationObserver(()=>{browser.document.documentElement&&(observer.disconnect(),install())});observer.observe(browser.document,{childList:!0})}function buildDocumentSource(config2){return`;(() => {const config=${serializeForSource(config2)};(${installCdpAppProfileRelay.toString()})(${JSON.stringify(APP_PROFILE_BINDING)});(${installEarlyAppProfileEnvironment.toString()})(config);(${installWhenDocumentElementExists.toString()})(() => {${buildAppProfileRuntimeCallSource("config")};});})();`}function appProfileEmulationCommands(config2,userAgent){return buildEnableEmulationCommands(config2).map(command=>command.method==="Emulation.setUserAgentOverride"?{...command,params:{userAgent,platform:config2.platform}}:command)}async function sendCommands(client2,commands){for(let{method,params,optional:optional2}of commands)await client2.sendCommand(method,params).catch(error48=>{if(!optional2)throw error48})}async function postRuntimeMessage(client2,executionContextId,message){await client2.sendCommand("Runtime.evaluate",{expression:`window.postMessage(${serializeForSource(message)}, '*')`,...typeof executionContextId=="number"?{contextId:executionContextId}:{}})}function listenForBridgeRequests(session,client2,state){return client2.on("Runtime.bindingCalled",params=>{if(params?.name!==APP_PROFILE_BINDING||appProfileStates.get(session)!==state)return;let request;try{request=JSON.parse(params.payload)}catch{return}if(typeof request.requestId!="number")return;let requestId=request.requestId,contextId=typeof params.executionContextId=="number"?params.executionContextId:void 0,reply=message=>postRuntimeMessage(client2,contextId,{requestId,source:"mearl-content",...message});(async()=>{if(request.type==="userInfo"){try{let result=await session.client.sendCommand("Network.getCookies",{urls:[session.url]}),response=resolveAppProfileUserInfo(session.url,(result.cookies??[]).map(cookie=>({name:cookie.name,value:cookie.value})));await reply({type:"APP_BRIDGE_USER_INFO_RESPONSE",result:{success:!0,response}})}catch(error48){await reply({type:"APP_BRIDGE_USER_INFO_RESPONSE",result:{success:!1,error:error48 instanceof Error?error48.message:String(error48)}})}return}let payload=request.payload??{},mtopPayload={...payload,...typeof payload.v=="string"&&payload.version===void 0?{version:payload.v}:{}},streamCapture;try{if(request.type==="mtopStream"){await cdpSendMtopStreamRequest(session,mtopPayload,{onRequestPrepared:metadata=>{streamCapture=recordCdpMtopStreamStart(session.buffers,{api:String(mtopPayload.api??""),url:metadata.url,method:metadata.method,requestHeaders:metadata.requestHeaders,requestData:mtopPayload.data??null})},onResponse:metadata=>{streamCapture&&recordCdpMtopStreamResponse(session.buffers,streamCapture,metadata)},onReceive:async data=>{streamCapture&&recordCdpMtopStreamChunk(session.buffers,streamCapture,data),await reply({type:"APP_BRIDGE_MTOP_STREAM_EVENT",eventType:"onReceive",data})}}),streamCapture&&recordCdpMtopStreamEnd(session.buffers,streamCapture),await reply({type:"APP_BRIDGE_MTOP_STREAM_EVENT",eventType:"onFinish",data:{}});return}let result=await cdpSendMtopRequest(session,mtopPayload);await reply({type:"APP_BRIDGE_MTOP_RESPONSE",result})}catch(error48){let message=error48 instanceof Error?error48.message:String(error48);request.type==="mtopStream"?(streamCapture&&recordCdpMtopStreamEnd(session.buffers,streamCapture,{error:message}),await reply({type:"APP_BRIDGE_MTOP_STREAM_EVENT",eventType:"onError",data:{ret:["HY_FAILED"],msg:message}})):await reply({type:"APP_BRIDGE_MTOP_RESPONSE",result:{success:!1,error:message}})}})().catch(()=>{})})}async function installChildTarget(session,state,params,source){let sessionId=params.sessionId;if(typeof sessionId!="string")return;let child=session.client.createChildSession(sessionId);try{if(params.targetInfo?.type!=="iframe"||appProfileStates.get(session)!==state)return;await child.sendCommand("Runtime.enable");let frameName=(await child.sendCommand("Runtime.evaluate",{expression:"window.name",returnByValue:!0})).result?.value;if(frameName!=="__mearl_root__"&&frameName!=="__mearl_layer__")return;state.emulation?await sendCommands(child,appProfileEmulationCommands(state.emulation,state.config.userAgent)):await child.sendCommand("Emulation.setUserAgentOverride",{userAgent:state.config.userAgent,platform:state.config.navigatorPlatform}),await child.sendCommand("Runtime.addBinding",{name:APP_PROFILE_BINDING}),state.disposeListeners.push(listenForBridgeRequests(session,child,state)),state.childClients.push(child),await child.sendCommand("Page.addScriptToEvaluateOnNewDocument",{source}).catch(()=>{}),await child.sendCommand("Runtime.evaluate",{expression:source})}finally{await child.sendCommand("Runtime.runIfWaitingForDebugger").catch(()=>{})}}async function disposeState(session,state,disableDeviceEmulation){appProfileStates.get(session)===state&&appProfileStates.delete(session);for(let dispose of state.disposeListeners.splice(0))dispose();await session.client.sendCommand("Target.setAutoAttach",{autoAttach:!1,waitForDebuggerOnStart:!1,flatten:!0}).catch(()=>{}),await session.client.sendCommand("Page.removeScriptToEvaluateOnNewDocument",{identifier:state.documentScriptIdentifier}).catch(()=>{}),await Promise.allSettled([session.client,...state.childClients].map(client2=>client2.sendCommand("Runtime.removeBinding",{name:APP_PROFILE_BINDING}))),disableDeviceEmulation&&(state.ownsDeviceEmulation||!state.independentDeviceEmulation?(await sendCommands(session.client,buildDisableEmulationCommands()),session.emulation=void 0):(await sendCommands(session.client,buildEnableEmulationCommands(state.independentDeviceEmulation)),session.emulation={mobile:state.independentDeviceEmulation.mobile,touch:state.independentDeviceEmulation.touch}))}function resolveCdpAppProfile(profile,options={}){let resolved=resolveAppProfile(profile,{os:options.os,appVersion:options.appVersion,deviceModel:options.deviceModel,simulateSystemBars:options.simulateSystemBars,bridgeConfig:options.bridgeConfig}),emulation=resolveEmulationConfig({preset:resolved.recommendedPreset,...options.emulation,enabled:!0});return{profile:resolved,emulation}}async function applyResolvedCdpAppProfile(session,resolved){let previous=appProfileStates.get(session);previous&&await disposeState(session,previous,!1);let source=buildDocumentSource(resolved.profile.injected);await sendCommands(session.client,appProfileEmulationCommands(resolved.emulation,resolved.profile.ua)),session.emulation={mobile:resolved.emulation.mobile,touch:resolved.emulation.touch},await session.client.sendCommand("Runtime.enable"),await session.client.sendCommand("Runtime.addBinding",{name:APP_PROFILE_BINDING});let script=await session.client.sendCommand("Page.addScriptToEvaluateOnNewDocument",{source});if(typeof script.identifier!="string"||!script.identifier)throw await sendCommands(session.client,buildDisableEmulationCommands()),session.emulation=void 0,new Error("Chrome did not return an app profile bootstrap script identifier");let state={config:resolved.profile.injected,documentScriptIdentifier:script.identifier,emulation:resolved.emulation,ownsDeviceEmulation:!0,disposeListeners:[],childClients:[]};appProfileStates.set(session,state),state.disposeListeners.push(listenForBridgeRequests(session,session.client,state)),state.disposeListeners.push(session.client.on("Target.attachedToTarget",params=>{installChildTarget(session,state,params,source).catch(()=>{})})),await session.client.sendCommand("Target.setAutoAttach",{autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0,filter:[{type:"iframe"},{exclude:!0}]})}function updateCdpAppProfileDeviceEmulation(session,emulation){let state=appProfileStates.get(session);if(state)return state.ownsDeviceEmulation=!1,state.emulation=emulation??void 0,state.independentDeviceEmulation=emulation??void 0,{userAgent:state.config.userAgent,platform:state.config.navigatorPlatform}}function isCdpAppProfileActive(session){return appProfileStates.has(session)}function hasLoadedRootWebView(frameTree){if(!frameTree)return!1;let frame=frameTree.frame;return frame?.name==="__mearl_root__"&&typeof frame.url=="string"&&/^https?:/i.test(frame.url)?!0:Array.isArray(frameTree.childFrames)?frameTree.childFrames.some(child=>hasLoadedRootWebView(child)):!1}async function waitForCdpAppProfileLoad(session,timeoutMs=15e3){let deadline=Date.now()+timeoutMs;for(;Date.now()<deadline;){let result=await session.client.sendCommand("Page.getFrameTree").catch(()=>null);if(hasLoadedRootWebView(result?.frameTree))return;await new Promise(resolve3=>setTimeout(resolve3,50))}throw new Error(`App profile root WebView load timeout after ${timeoutMs}ms`)}async function clearCdpAppProfile(session,reload=!0){let state=appProfileStates.get(session);if(!state)return{enabled:!1,reloaded:!1};await disposeState(session,state,!0);let reloaded=!1;return reload&&(clearPageRefsForNavigation(session),await session.client.sendCommand("Page.reload",{}),await waitForPageLoad(session,3e4),reloaded=!0),{enabled:!1,reloaded}}async function cdpSetAppProfile(session,data){if(typeof data?.enabled!="boolean")throw new Error('set_app_profile: "enabled" is required (true to enable, false to clear)');if(!data.enabled)return clearCdpAppProfile(session,data.reload!==!1);if(!data.profile||typeof data.profile!="string")throw new Error('set_app_profile: "profile" is required when enabled=true');let resolved=resolveCdpAppProfile(data.profile,data);await applyResolvedCdpAppProfile(session,resolved);let reloaded=!1;return data.reload!==!1&&(clearPageRefsForNavigation(session),await session.client.sendCommand("Page.reload",{}),await waitForCdpAppProfileLoad(session),reloaded=!0),{enabled:!0,profile:resolved.profile.profile,label:resolved.profile.label,userAgent:resolved.profile.ua,preset:resolved.emulation.presetName,os:resolved.profile.injected.platform==="Android"?"android":"ios",simulateSystemBars:resolved.profile.injected.simulateSystemBars!==!1,reloaded}}registerActions([{name:"set_app_profile",session:"page",handler:cdpSetAppProfile}]);async function releaseCdpControl(session){let pageSessions=session.listOpenPageSessions(),targetIds=new Set(pageSessions.map(pageSession=>pageSession.targetId)),affectedTabIds=session.listRegisteredTabIds(targetIds).sort((a,b)=>a-b),hadActiveControl=session.hasActiveConnections();try{await releaseCdpRecordings(pageSessions)}finally{await Promise.allSettled(pageSessions.flatMap(pageSession=>[clearCdpAppProfile(pageSession,!1),releaseControlledIndicator(pageSession)])),clearCdpMockState(),session.close()}return{released:!0,hadActiveControl,affectedTabIds}}var SAMPLE_PAGE_READINESS_SRC=samplePageReadinessInPage.toString(),DISPOSE_PAGE_READINESS_SRC=disposePageReadinessObserverInPage.toString();async function startCdpNavigationObserver(cdpSession2,pageSession,urlBefore,options={}){await ensureCdpDomain(pageSession.client,"Page"),options.trackNetwork&&await ensureCdpDomain(pageSession.client,"Network");let browserClient=null,baselineTargetIds=new Set;if(options.trackOpenedTabs)try{browserClient=await cdpSession2.getBrowserClient();let targets=await browserClient.sendCommand("Target.getTargets");for(let target of targets.targetInfos??[])baselineTargetIds.add(target.targetId)}catch{browserClient=null}let mainFrameId=(await pageSession.client.sendCommand("Page.getFrameTree")).frameTree?.frame?.id,tracker=createNavigationSettlementTracker({urlBefore,trackNetwork:options.trackNetwork,networkAvailable:options.trackNetwork===!0,networkIdleMs:options.networkIdleMs,contentReadyAfterMs:options.contentReadyAfterMs,sampleContent:async()=>(await pageSession.client.sendCommand("Runtime.evaluate",{expression:`(${SAMPLE_PAGE_READINESS_SRC})(${options.networkIdleMs??500})`,returnByValue:!0})).result?.value}),removeFrameNavigated=pageSession.client.on("Page.frameNavigated",params=>{params.frame?.parentId||mainFrameId&¶ms.frame?.id!==mainFrameId||tracker.markStarted(params.frame?.url)}),removeWithinDocument=pageSession.client.on("Page.navigatedWithinDocument",params=>{mainFrameId&¶ms.frameId!==mainFrameId||(tracker.markStarted(params.url),tracker.markDocumentComplete(params.url))}),removeLoad=pageSession.client.on("Page.loadEventFired",()=>{tracker.hasStarted()&&tracker.markDocumentComplete()}),removeRequestStarted=options.trackNetwork?pageSession.client.on("Network.requestWillBeSent",params=>{isPotentialNavigationRequest(params.type??"",params.request?.url??"")&&tracker.requestStarted(params.requestId)}):()=>{},onRequestFinished=params=>tracker.requestFinished(params.requestId),removeRequestFinished=options.trackNetwork?pageSession.client.on("Network.loadingFinished",onRequestFinished):()=>{},removeRequestFailed=options.trackNetwork?pageSession.client.on("Network.loadingFailed",onRequestFinished):()=>{};return{hasStarted:tracker.hasStarted,hasNetworkActivity:tracker.hasNetworkActivity,waitForStart:tracker.waitForStart,waitForNetworkIdle:tracker.waitForNetworkIdle,waitForResult:async timeoutMs=>{let result=await tracker.waitForResult(timeoutMs);try{let pageState=await pageSession.client.sendCommand("Runtime.evaluate",{expression:"({ title: document.title, url: location.href })",returnByValue:!0});return{...result,title:pageState.result?.value?.title??result.title,urlAfter:pageState.result?.value?.url??result.urlAfter}}catch{return result}},getOpenedTabs:async timeoutMs=>{if(!browserClient||options.sourceTabId===void 0)return[];let candidates=((await browserClient.sendCommand("Target.getTargets")).targetInfos??[]).filter(target=>target.type==="page"&&target.openerId===pageSession.targetId&&!baselineTargetIds.has(target.targetId));return(await Promise.all(candidates.map(async candidate=>{let tabId=await cdpSession2.ensureTargetRegistered(candidate.targetId),ready=!1;try{let openedPageSession=await cdpSession2.getPageSession(tabId);await ensureCdpDomain(openedPageSession.client,"Page"),await waitForPageLoad(openedPageSession,timeoutMs),ready=!0}catch{}let targetInfo=await browserClient.sendCommand("Target.getTargetInfo",{targetId:candidate.targetId}).then(result=>result.targetInfo).catch(()=>null);return targetInfo?{tabId,openerTabId:options.sourceTabId,url:targetInfo.url??candidate.url??"",title:targetInfo.title??candidate.title??"",ready,settledBy:ready?"load":"timeout"}:null}))).filter(tab=>tab!==null)},dispose:async()=>{removeFrameNavigated(),removeWithinDocument(),removeLoad(),removeRequestStarted(),removeRequestFinished(),removeRequestFailed(),tracker.dispose(),await pageSession.client.sendCommand("Runtime.evaluate",{expression:`(${DISPOSE_PAGE_READINESS_SRC})()`,returnByValue:!1}).catch(()=>{})}}}var INSTALL_PAGE_OBSERVER_SRC=installPageObserverInPage.toString(),DISPOSE_PAGE_OBSERVER_SRC=disposePageObserverInPage.toString(),PAGE_OBSERVER_GLOBAL="__MEARL_PAGE_OBSERVER__";function evaluationError(result){return result.exceptionDetails?result.exceptionDetails.exception?.description??result.exceptionDetails.text??"Page observation evaluation failed":null}async function startPageObservation(session){let result=await session.client.sendCommand("Runtime.evaluate",{expression:`(${INSTALL_PAGE_OBSERVER_SRC})()`,returnByValue:!0}),error48=evaluationError(result);if(error48)throw new Error(error48);let checkpoint=result.result?.value;if(!checkpoint||typeof checkpoint.version!="number")throw new Error("Page observer did not return a checkpoint");return checkpoint}async function finishPageObservation(session,checkpoint,options={}){let{quietMs,firstChangeTimeoutMs,timeoutMs}=resolvePageObservationWaitOptions(options),expression=`(() => {
|
|
770
|
+
const state = globalThis[${JSON.stringify(PAGE_OBSERVER_GLOBAL)}];
|
|
771
|
+
if (!state || typeof state.waitSince !== 'function') {
|
|
772
|
+
throw new Error('Page observer is unavailable after the action');
|
|
773
|
+
}
|
|
774
|
+
return state.waitSince(
|
|
775
|
+
${checkpoint.version},
|
|
776
|
+
${JSON.stringify(checkpoint.focus)},
|
|
777
|
+
${quietMs},
|
|
778
|
+
${firstChangeTimeoutMs},
|
|
779
|
+
${timeoutMs}
|
|
780
|
+
);
|
|
781
|
+
})()`,result=await session.client.sendCommand("Runtime.evaluate",{expression,returnByValue:!0,awaitPromise:!0},timeoutMs+2e3),error48=evaluationError(result);if(error48)throw new Error(error48);let changeSet=result.result?.value;if(!changeSet||changeSet.mode!=="delta")throw new Error("Page observer did not return a change set");return changeSet}async function disposePageObservation(session){await session.client.sendCommand("Runtime.evaluate",{expression:`(${DISPOSE_PAGE_OBSERVER_SRC})()`,returnByValue:!1}).catch(()=>{})}function filterRequests(buffers,opts){let pattern=opts.filter?compileTextPattern(opts.filter):void 0;return queryCapturedEntries(buffers.requests.filter(request=>Number.isSafeInteger(request.captureSequence)),buffers.capture,{after:opts.after,since:opts.since,limit:opts.count??10},request=>(!opts.source||opts.source==="all"||request.source===opts.source)&&(!pattern||matchesTextPattern(request.url,pattern)||matchesTextPattern(request.apiName,pattern)),buffers.capture.droppedRequestsThroughSequence,"requests")}async function cdpGetRequests(session,data){let opts={count:data.count??10,filter:data.filter,since:data.since,after:data.after,source:data.source,applyHiddenFilter:data.applyHiddenFilter!==!1},captured=filterRequests(session.buffers,opts),serializeOpts={includeBody:data.includeBody!==!1,includeHeaders:data.includeHeaders===!0,maxBodySize:data.maxBodySize??5e4,fields:data.fields,keysOnly:data.keysOnly===!0};return{meta:{count:captured.entries.length,totalMatched:captured.totalMatched,totalInBuffer:session.buffers.requests.length,filter:data.filter,since:data.since,after:data.after,nextCursor:captured.nextCursor,hasMore:captured.hasMore,gap:captured.gap,source:"cdp"},requests:captured.entries.map(r=>serializeRequest(r,serializeOpts))}}async function cdpGetLogs(session,data){let{level,since,after,limit=100,filter}=data,pattern=filter?compileTextPattern(filter):void 0,captured=queryCapturedEntries(session.buffers.logs,session.buffers.capture,{after,since,limit},log3=>(!level||level==="all"||log3.level===level)&&(!pattern||matchesTextPattern(log3.message,pattern)||log3.args.some(arg=>matchesTextPattern(arg,pattern))),session.buffers.capture.droppedLogsThroughSequence,"logs"),captureStatus=session.buffers.logs.length===0?"armed":"active";return{meta:{count:captured.entries.length,totalMatched:captured.totalMatched,totalInBuffer:session.buffers.logs.length,level:level||"all",since,after,filter,nextCursor:captured.nextCursor,hasMore:captured.hasMore,gap:captured.gap,captureStatus,...captureStatus==="armed"&&{hint:"Log capture is active, but this tab has no captured history yet. Reload the current tab or repeat the triggering action, then call get_logs again."},source:"cdp"},logs:captured.entries}}async function cdpCaptureCheckpoint(session,_data){return{tabId:session.tabId,cursor:captureCheckpoint(session.buffers.capture),timestampMs:Date.now(),captureStatus:session.buffers.capture.currentSequence===0?"armed":"active"}}async function collectCdpPageDiagnostics(session,after,diagnostics){let result={};if(diagnostics.logs){let options=diagnostics.logs===!0?{level:"error",limit:100}:{level:"error",limit:100,...diagnostics.logs};result.logs=await cdpGetLogs(session,{...options,after})}if(diagnostics.requests){let options=diagnostics.requests===!0?{source:"all",includeBody:!1,count:100}:{source:"all",includeBody:!1,count:100,...diagnostics.requests};result.requests=await cdpGetRequests(session,{...options,after})}if(diagnostics.events){let options=diagnostics.events===!0?{source:"all",limit:100}:{source:"all",limit:100,...diagnostics.events};result.events=await cdpGetEvents(session,{...options,after})}return result}async function cdpGetEvents(session,data){let{source="all",event_type,since,after,limit=20,filter,includeRaw=!1}=data,response=queryCapturedTrackingEvents(session.buffers.events,session.buffers.capture,{source,event_type,since,after,limit,filter},session.buffers.capture.droppedEventsThroughSequence),captureStatus=response.totalInBuffer===0?"armed":"active",hint=response.events.length===0&&captureStatus==="armed"?TRACKING_CAPTURE_ARMED_HINT:void 0;return{meta:{count:response.events.length,totalMatched:response.totalMatched,totalInBuffer:response.totalInBuffer,source,captureStatus,captureSource:"cdp",includeRaw,after,nextCursor:response.nextCursor,hasMore:response.hasMore,gap:response.gap,hint},events:response.events.map(event=>formatTrackingEvent(event,includeRaw))}}registerActions([{name:"tab_checkpoint",session:"page",handler:cdpCaptureCheckpoint},{name:"capture_checkpoint",session:"page",handler:cdpCaptureCheckpoint},{name:"get_requests",session:"page",handler:cdpGetRequests},{name:"get_logs",session:"page",handler:cdpGetLogs},{name:"get_events",session:"page",handler:cdpGetEvents}]);async function cdpRunActions(session,data,controlSource="local"){let{actions,tabId}=data;if(!Array.isArray(actions)||actions.length===0)throw new Error("actions must be a non-empty array");if(actions.length>50)throw new Error("actions array exceeds maximum of 50 steps");let results=[];for(let i=0;i<actions.length;i++){let step=actions[i],stepAction=String(step.action??"");if(!stepAction)return{results,completedSteps:results.length,totalSteps:actions.length,error:`Step ${i}: action must be a non-empty string`,failedStep:i};if(!isBrowserCommandAction(stepAction))return{results,completedSteps:results.length,totalSteps:actions.length,error:`Step ${i}: unsupported action "${stepAction}"`,failedStep:i};if(stepAction==="run_actions")return{results,completedSteps:results.length,totalSteps:actions.length,error:`Step ${i}: composite action "${stepAction}" is not allowed in run_actions`,failedStep:i};if(stepAction==="browser_release")return{results,completedSteps:results.length,totalSteps:actions.length,error:`Step ${i}: browser-level action "${stepAction}" is not allowed in run_actions`,failedStep:i};let mergedData={...step.data};tabId!==void 0&&mergedData.tabId===void 0&&(mergedData.tabId=tabId);try{let result=await dispatchCdpAction(session,stepAction,mergedData,controlSource);results.push({step:i,action:stepAction,success:!0,data:result})}catch(error48){let errorMessage2=error48 instanceof Error?error48.message:String(error48);return results.push({step:i,action:stepAction,success:!1,error:errorMessage2}),{results,completedSteps:i,totalSteps:actions.length,error:errorMessage2,failedStep:i}}}return{results,completedSteps:actions.length,totalSteps:actions.length}}async function cdpObservedPageAction(session,action,data,controlSource="local"){let{actionData,observe,diagnostics}=splitObservedActionPayload(action,data),{tabId}=actionData;if(typeof tabId!="number")throw new Error(`${action} requires a numeric tabId`);let pageSession=await session.getPageSession(tabId);if(await ensureControlledIndicator(pageSession,controlSource),observe===!1){if(!diagnostics)return dispatchCdpAction(session,action,actionData,controlSource);let cursor=captureCheckpoint(pageSession.buffers.capture),actionResult,actionFailure;try{actionResult=await dispatchCdpAction(session,action,actionData,controlSource)}catch(error48){actionFailure=describePageActionFailure(error48)}let result2={action:{name:action,success:actionFailure===void 0,...actionResult!==void 0?{data:actionResult}:{},...actionFailure||{}}};return actionFailure?.stage==="precondition"?result2:{...result2,diagnostics:await collectCdpPageDiagnostics(pageSession,cursor,diagnostics)}}let diagnosticsCursor,result=await runPageAct({action,actionData,observe},{startObservation:()=>startPageObservation(pageSession),finishObservation:(checkpoint,options)=>finishPageObservation(pageSession,checkpoint,options),startNavigationObserver:options=>startCdpNavigationObserver(session,pageSession,options.urlBefore,options),executeAction:(name,params)=>(diagnostics&&(diagnosticsCursor=captureCheckpoint(pageSession.buffers.capture)),dispatchCdpAction(session,name,{...params,tabId},controlSource)),finalizeObservation:observation=>observation.mode==="delta"?enrichCdpPageChangeSetWithRefs(pageSession,observation):Promise.resolve(observation),disposeObservation:()=>disposePageObservation(pageSession)});return!diagnostics||!diagnosticsCursor||result.action.stage==="precondition"?result:{...result,diagnostics:await collectCdpPageDiagnostics(pageSession,diagnosticsCursor,diagnostics)}}registerActions([{name:"run_actions",session:"browser",handler:cdpRunActions}]);import{randomUUID as randomUUID2}from"node:crypto";import{createReadStream}from"node:fs";var FILE_CHUNK_BYTES=256*1024,TRANSFER_ACTION_TIMEOUT_MS=15e3;async function sendFileChunks(transferId,fileIndex,file2,send){let chunkIndex=0,sendChunk=async chunk=>{await send("__send_request_file_chunk",{transferId,fileIndex,chunkIndex,base64:chunk.toString("base64")},TRANSFER_ACTION_TIMEOUT_MS),chunkIndex+=1};if(file2.filePath){for await(let chunk of createReadStream(file2.filePath,{highWaterMark:FILE_CHUNK_BYTES}))await sendChunk(Buffer.isBuffer(chunk)?chunk:Buffer.from(chunk));return}let content=file2.content;for(let offset=0;offset<content.byteLength;offset+=FILE_CHUNK_BYTES)await sendChunk(content.subarray(offset,offset+FILE_CHUNK_BYTES))}async function prepareFileTransfer(data,send){let files=await resolveSendRequestFiles(data.files??[]);if(files.length===0)throw new Error("files must contain at least one file");let transferId=randomUUID2();await send("__send_request_file_start",{transferId,files:files.map(file2=>file2.descriptor),url:data.url,withCookies:data.withCookies},TRANSFER_ACTION_TIMEOUT_MS);try{for(let index=0;index<files.length;index+=1)await sendFileChunks(transferId,index,files[index],send)}catch(error48){throw await send("__send_request_file_abort",{transferId},TRANSFER_ACTION_TIMEOUT_MS).catch(()=>{}),error48}let{files:_files,...request}=data;return{transferId,request}}async function abortFileTransfer(transferId,send){await send("__send_request_file_abort",{transferId},TRANSFER_ACTION_TIMEOUT_MS).catch(()=>{})}function hasSendRequestFiles(data){return!!data&&typeof data=="object"&&Array.isArray(data.files)&&data.files.length>0}function hasRunActionsSendRequestFiles(data){if(!data||typeof data!="object")return!1;let actions=data.actions;return Array.isArray(actions)&&actions.some(step=>step?.action==="send_request"&&hasSendRequestFiles(step.data))}async function sendRequestWithTransferredFiles(data,send){let prepared=await prepareFileTransfer(data,send);try{let requestTimeout=Number(data.timeout??3e4);return await send("__send_request_with_files",{...prepared.request,transferId:prepared.transferId},(Number.isFinite(requestTimeout)&&requestTimeout>0?requestTimeout:3e4)+5e3)}catch(error48){throw await abortFileTransfer(prepared.transferId,send),error48}}async function sendRunActionsWithTransferredFiles(data,send,resolveTimeoutMs){if(!Array.isArray(data.actions))throw new Error("actions must be an array");let preparedTransferIds=[];try{let actions=[];for(let index=0;index<data.actions.length;index+=1){let step=data.actions[index],action=String(step.action??"");if(action.startsWith("__"))throw new Error(`Step ${index}: internal action "${action}" is not available to clients`);if(action!=="send_request"||!hasSendRequestFiles(step.data)){actions.push(step);continue}let prepared=await prepareFileTransfer(step.data,send);preparedTransferIds.push(prepared.transferId),actions.push({action:"__send_request_with_files",data:{...prepared.request,transferId:prepared.transferId}})}let transformed={...data,actions};return await send("run_actions",transformed,resolveTimeoutMs(transformed))}finally{await Promise.all(preparedTransferIds.map(transferId=>abortFileTransfer(transferId,send)))}}import fs2 from"node:fs";import path2 from"node:path";import{spawn as spawn2,spawnSync}from"node:child_process";function isAlive(pid){if(!pid||pid<=0)return!1;try{return process.kill(pid,0),!0}catch(error48){return error48.code==="EPERM"}}import{join}from"node:path";import{homedir}from"node:os";import{createHash}from"node:crypto";var DAEMON_HOME=join(homedir(),".mearl");function hashKey(key){return createHash("sha256").update(key).digest("hex").slice(0,16)}function keyedDir(subdir){return join(DAEMON_HOME,subdir)}function keyedConfigFile(subdir,key){return join(keyedDir(subdir),`${hashKey(key)}.json`)}import{existsSync,mkdirSync,readFileSync,writeFileSync,renameSync,rmSync,readdirSync}from"node:fs";import{dirname,join as join2}from"node:path";function ensureDir(dir){existsSync(dir)||mkdirSync(dir,{recursive:!0,mode:448})}function writeRecord(file2,record2){ensureDir(dirname(file2));let tmp=`${file2}.${process.pid}.tmp`;try{writeFileSync(tmp,JSON.stringify(record2),{mode:384}),renameSync(tmp,file2)}catch(error48){try{rmSync(tmp,{force:!0})}catch{}throw error48}}function readRecord(file2){try{if(!existsSync(file2))return null;let parsed=JSON.parse(readFileSync(file2,"utf-8"));return parsed&&typeof parsed.pid=="number"?parsed:null}catch{return null}}function removeRecord(file2){try{rmSync(file2,{force:!0})}catch{}}function listRecordFiles(dir){try{return readdirSync(dir).filter(name=>name.endsWith(".json")).map(name=>join2(dir,name))}catch{return[]}}function readLiveRecords(dir){let out=[];for(let file2 of listRecordFiles(dir)){let rec=readRecord(file2);rec&&isAlive(rec.pid)?out.push(rec):removeRecord(file2)}return out}import{existsSync as existsSync2,statSync,renameSync as renameSync2,readFileSync as readFileSync2}from"node:fs";var DEFAULT_MAX_LOG_BYTES=5*1024*1024;import{spawn}from"node:child_process";import{openSync}from"node:fs";import{dirname as dirname2}from"node:path";var processes=new Map,CONNECTORS_SUBDIR="connectors",REGISTRY_DIR=keyedDir(CONNECTORS_SUBDIR),OFFICIAL_NPM_REGISTRY="https://registry.npmjs.org",STATUS_POLL_MS=5e3;function recordFileFor(serverUrl){return keyedConfigFile(CONNECTORS_SUBDIR,serverUrl)}var logFn=()=>{},isDaemon=!1,sendToExtensionFn=()=>{},nativeHostVersion="unknown",lastPushedKey="",statusWatcher=null;function initCloudConnector(deps){logFn=deps.log,isDaemon=deps.isDaemonMode,sendToExtensionFn=deps.sendToExtension,nativeHostVersion=deps.version,startStatusWatcher()}function liveRecords(){return readLiveRecords(REGISTRY_DIR)}function reconcile(){let live=new Map;for(let record2 of liveRecords())live.set(record2.serverUrl,{serverUrl:record2.serverUrl,pid:record2.pid,...record2.connectorId?{connectorId:record2.connectorId}:{},...record2.name?{name:record2.name}:{}});for(let[serverUrl,entry]of processes)isAlive(entry.pid)?live.has(serverUrl)||live.set(serverUrl,{serverUrl,pid:entry.pid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{}}):processes.delete(serverUrl);return Array.from(live.values())}function connectorsKey(connectors){return connectors.map(c=>`${c.serverUrl}@${c.pid}@${c.connectorId??""}@${c.name??""}`).sort().join("|")}function pushStatus(connectors){isDaemon||(lastPushedKey=connectorsKey(connectors),sendToExtensionFn({type:"cloud_connector_status_changed",data:{connectors}}))}function notifyStatusChanged(){pushStatus(reconcile())}function pushIfChanged(){let connectors=reconcile();return connectorsKey(connectors)!==lastPushedKey&&pushStatus(connectors),connectors}function startStatusWatcher(){isDaemon||statusWatcher||(statusWatcher=setInterval(()=>{try{pushIfChanged()}catch{}},STATUS_POLL_MS),statusWatcher.unref?.())}function registerConnector(serverUrl,pid,child){let record2=readRecord(recordFileFor(serverUrl)),entry={pid,serverUrl,...record2?.connectorId?{connectorId:record2.connectorId}:{},...record2?.name?{name:record2.name}:{},...child?{process:child}:{}};return processes.set(serverUrl,entry),notifyStatusChanged(),entry}function clearConnector(serverUrl,child){let entry=processes.get(serverUrl);child&&entry&&entry.process!==child||(processes.delete(serverUrl),removeRecord(recordFileFor(serverUrl)),notifyStatusChanged())}function findLiveConnector(serverUrl){let entry=processes.get(serverUrl);if(entry&&isAlive(entry.pid))return entry.pid;let record2=readRecord(recordFileFor(serverUrl));return record2&&isAlive(record2.pid)?record2.pid:(entry&&processes.delete(serverUrl),record2&&removeRecord(recordFileFor(serverUrl)),null)}function findBin(bin,env){let lookupCommand=process.platform==="win32"?"where":"which",result=spawnSync(lookupCommand,[bin],{encoding:"utf-8",env});return result.status===0&&result.stdout.split(/\r?\n/).find(Boolean)||null}function getBinVersion(binPath){try{let result=spawnSync(process.execPath,[binPath,"--version"],{encoding:"utf-8",timeout:5e3});return result.status===0?result.stdout.trim():null}catch{return null}}function makeDirectCommand(connectorPath){return process.platform!=="win32"?{command:process.execPath,argsPrefix:[connectorPath],displayName:`${process.execPath} ${connectorPath}`}:{command:connectorPath,argsPrefix:[],displayName:connectorPath}}function resolveCloudConnectorCommand(){let connectorBin=process.platform==="win32"?"mearl-cloud-connector.cmd":"mearl-cloud-connector",pathDelimiter=process.platform==="win32"?";":":",nodeDir=path2.dirname(process.execPath),enrichedPath=[nodeDir,process.env.PATH].filter(Boolean).join(pathDelimiter),enrichedEnv={...process.env,PATH:enrichedPath},connectorPath=findBin(connectorBin,enrichedEnv);if(connectorPath){let installedVersion=getBinVersion(connectorPath);if(installedVersion===nativeHostVersion)return logFn(`Cloud connector ${installedVersion} found at ${connectorPath}`),makeDirectCommand(connectorPath);logFn(`Cloud connector version mismatch: installed=${installedVersion}, expected=${nativeHostVersion}`)}let npmBin=process.platform==="win32"?"npm.cmd":"npm",npmPath=path2.join(nodeDir,npmBin),npmCommand=fs2.existsSync(npmPath)?npmPath:npmBin,targetPackage=`@mearl/cloud-connector@${nativeHostVersion}`;logFn(`Installing ${targetPackage} globally via ${npmCommand}...`);let install=spawnSync(npmCommand,["install","-g",targetPackage,"--prefer-offline",`--registry=${OFFICIAL_NPM_REGISTRY}`],{encoding:"utf-8",env:enrichedEnv,timeout:3e4});if(install.status===0){let newPath=findBin(connectorBin,enrichedEnv);if(newPath)return logFn(`Global install succeeded: ${newPath}`),makeDirectCommand(newPath)}logFn(`Global install failed (status=${install.status}), falling back to npx`),install.stderr&&logFn(install.stderr.trim());let npxBin=process.platform==="win32"?"npx.cmd":"npx",npxPath=path2.join(nodeDir,npxBin),npxCommand=fs2.existsSync(npxPath)?npxPath:npxBin;return{command:npxCommand,argsPrefix:[`@mearl/cloud-connector@${nativeHostVersion}`],displayName:`${npxCommand} @mearl/cloud-connector@${nativeHostVersion}`,env:enrichedEnv}}function startCloudConnector(serverUrl){return new Promise(resolve3=>{let existingPid=findLiveConnector(serverUrl);if(existingPid){logFn(`Reusing existing cloud connector for ${serverUrl} (pid=${existingPid})`);let entry=registerConnector(serverUrl,existingPid);resolve3({success:!0,pid:existingPid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{},reused:!0});return}let connectorCommand=resolveCloudConnectorCommand();logFn(`Starting cloud connector via ${connectorCommand.displayName}`);let child=spawn2(connectorCommand.command,[...connectorCommand.argsPrefix,serverUrl,"--fail-fast"],{detached:!0,env:connectorCommand.env,stdio:["ignore","pipe","pipe"],windowsHide:!0}),settled=!1,outputBuffer="",startupTimer=setTimeout(()=>{finish(!1,{error:"Cloud connector startup timeout"}),child.kill()},6e4),finish=(ok,result={})=>{if(!settled)if(settled=!0,clearTimeout(startupTimer),ok&&child.pid){let entry=registerConnector(serverUrl,child.pid,child);resolve3({success:!0,pid:child.pid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{}})}else resolve3({success:!1,error:result.error||"Failed to spawn cloud connector"})};child.once("error",error48=>{logFn(`Failed to spawn cloud connector: ${error48.message}`),finish(!1,{error:error48.message})});let handleOutput=chunk=>{let text=chunk.toString();outputBuffer=(outputBuffer+text).slice(-2e3),logFn(`[CloudConnector] ${text.trim()}`),text.includes("[CloudConnector] Connected to")&&finish(!0)};child.stdout?.on("data",handleOutput),child.stderr?.on("data",handleOutput),child.once("spawn",()=>{child.once("exit",(code,signal)=>{clearConnector(serverUrl,child),logFn(`Cloud connector exited for ${serverUrl}: code=${code??"null"} signal=${signal??"null"}`),settled||finish(!1,{error:outputBuffer.trim()||`Cloud connector exited before connected: code=${code??"null"} signal=${signal??"null"}`})}),child.unref()})})}function stopCloudConnector(serverUrl){let pid=processes.get(serverUrl)?.pid??readRecord(recordFileFor(serverUrl))?.pid;if(!pid)return{success:!1,error:"Cloud connector not found"};try{return isAlive(pid)&&process.kill(pid),clearConnector(serverUrl),logFn(`Stopped cloud connector for ${serverUrl} (pid=${pid})`),{success:!0}}catch(error48){let err=error48;return err.code==="ESRCH"?(clearConnector(serverUrl),{success:!0}):(logFn(`Failed to stop cloud connector: ${err.message}`),{success:!1,error:err.message})}}function listCloudConnectors(){return{connectors:pushIfChanged()}}var SCREENSHOT_HIDDEN_DISPLAY_PROPERTIES=["--mearl-side-panel-toggle-display","--mearl-device-cutout-display"],screenshotQueueTails=new WeakMap;async function runScreenshotExclusive(session,operation){let previous=screenshotQueueTails.get(session)??Promise.resolve(),unlock,tail=new Promise(resolve3=>{unlock=resolve3});screenshotQueueTails.set(session,tail),await previous;try{return await operation()}finally{unlock(),screenshotQueueTails.get(session)===tail&&screenshotQueueTails.delete(session)}}async function hideScreenshotArtifacts(session){return(await session.client.sendCommand("Runtime.evaluate",{expression:`
|
|
757
782
|
(() => {
|
|
758
783
|
const root = document.documentElement;
|
|
759
784
|
if (!root) return [];
|
|
@@ -819,29 +844,7 @@ ${value}\r
|
|
|
819
844
|
return null;
|
|
820
845
|
}
|
|
821
846
|
});
|
|
822
|
-
})()`,returnByValue:!0,awaitPromise:!0})).result?.value;if(!userInfo)throw new Error("Failed to parse user info from work.alibaba-inc.com");return{userId,detail:userInfo}}registerActions([{name:"page_screenshot",session:"page",handler:cdpPageScreenshot},{name:"page_selected_element",session:"page",handler:cdpPageSelectedElement},{name:"get_user_info",session:"page",handler:cdpGetUserInfo}]);import{readFile}from"node:fs/promises";import{randomUUID}from"node:crypto";import{stat}from"node:fs/promises";import{basename,isAbsolute}from"node:path";async function resolveSendRequestFile(file2,index){if(!file2||typeof file2!="object")throw new Error(`files[${index}] must be an object`);let fieldName=assertSafeSendRequestMultipartValue(file2.fieldName,`files[${index}].fieldName`),hasPath=typeof file2.filePath=="string"&&file2.filePath.length>0,hasBase64=typeof file2.base64=="string";if(hasPath===hasBase64)throw new Error(`files[${index}] must provide exactly one of filePath or base64`);let filename,byteLength2,filePath,content;if(hasPath){if(filePath=file2.filePath,!isAbsolute(filePath))throw new Error(`files[${index}].filePath must be an absolute path`);let metadata;try{metadata=await stat(filePath)}catch(error48){throw new Error(`Unable to read files[${index}].filePath: ${error48 instanceof Error?error48.message:String(error48)}`,{cause:error48})}if(!metadata.isFile())throw new Error(`files[${index}].filePath is not a file`);filename=file2.filename||basename(filePath),byteLength2=metadata.size}else{if(filename=file2.filename||"",!filename)throw new Error(`files[${index}].filename is required when base64 is used`);let bytes=decodeSendRequestBase64Bytes(file2.base64,`files[${index}].base64`);content=Buffer.from(bytes),byteLength2=content.byteLength}let safeFilename=assertSafeSendRequestMultipartValue(filename,`files[${index}].filename`),contentType=typeof file2.contentType=="string"&&file2.contentType.trim()?assertSafeSendRequestMultipartValue(file2.contentType.trim(),`files[${index}].contentType`):inferSendRequestContentType(filename);return{descriptor:{fieldName,filename:safeFilename,contentType,byteLength:byteLength2},filePath,content}}async function resolveSendRequestFiles(files){assertSendRequestFileCount(files.length);let resolved=await Promise.all(files.map(resolveSendRequestFile));return assertSendRequestFileLimits(resolved.map(file2=>file2.descriptor.byteLength)),assertSendRequestBase64FileLimits(resolved.flatMap(file2=>file2.content?[file2.content.byteLength]:[])),resolved}var ALLOWED_METHODS=new Set(["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"]);function setHeader(headers,name,value){let existing=findSendRequestHeaderName(headers,name);existing&&existing!==name&&delete headers[existing],headers[name]=value}function removeHeader(headers,name){let existing=findSendRequestHeaderName(headers,name);existing&&delete headers[existing]}function escapeMultipartQuotedValue(value){return value.replace(/\\/g,"\\\\").replace(/"/g,"%22")}async function readMultipartFiles(files){let resolved=await resolveSendRequestFiles(files),contents=await Promise.all(resolved.map(async(file2,index)=>{if(file2.content)return file2.content;try{return await readFile(file2.filePath)}catch(error48){throw new Error(`Unable to read files[${index}].filePath: ${error48 instanceof Error?error48.message:String(error48)}`,{cause:error48})}}));return assertSendRequestFileLimits(contents.map(content=>content.byteLength)),resolved.map((file2,index)=>({fieldName:file2.descriptor.fieldName,filename:file2.descriptor.filename,contentType:file2.descriptor.contentType,content:contents[index]}))}async function buildMultipartBody(formData,files){if(formData!==void 0&&(formData===null||typeof formData!="object"||Array.isArray(formData)))throw new Error("formData must be an object");if(files!==void 0&&!Array.isArray(files))throw new Error("files must be an array");let resolvedFiles=await readMultipartFiles(files??[]),boundary=`----mearl-${randomUUID()}`,chunks=[];for(let[name,value]of Object.entries(formData??{})){if(!["string","number","boolean"].includes(typeof value))throw new Error(`formData.${name} must be a string, number, or boolean`);let safeName=escapeMultipartQuotedValue(assertSafeSendRequestMultipartValue(name,`formData field "${name}"`));chunks.push(Buffer.from(`--${boundary}\r
|
|
823
|
-
Content-Disposition: form-data; name="${safeName}"\r
|
|
824
|
-
\r
|
|
825
|
-
${String(value)}\r
|
|
826
|
-
`))}for(let file2 of resolvedFiles){let fieldName=escapeMultipartQuotedValue(file2.fieldName),filename=escapeMultipartQuotedValue(file2.filename);chunks.push(Buffer.from(`--${boundary}\r
|
|
827
|
-
Content-Disposition: form-data; name="${fieldName}"; filename="${filename}"\r
|
|
828
|
-
Content-Type: ${file2.contentType}\r
|
|
829
|
-
\r
|
|
830
|
-
`),file2.content,Buffer.from(`\r
|
|
831
|
-
`))}return chunks.push(Buffer.from(`--${boundary}--\r
|
|
832
|
-
`)),{contentType:`multipart/form-data; boundary=${boundary}`,body:Buffer.concat(chunks)}}function hasMultipartPayload(data){return data.formData!==void 0||data.files!==void 0}async function executeNodeSendRequest(data,cookieMap=new Map){let{url:url2,method="GET",headers={},params,body,formData,files,responseType="auto",timeout=3e4}=data;if(!url2||typeof url2!="string"||url2.trim()==="")throw new Error("Invalid url: url must be a non-empty string");let normalizedMethod=method.toUpperCase();if(!ALLOWED_METHODS.has(normalizedMethod))throw new Error(`Invalid method: ${method}. Allowed: ${[...ALLOWED_METHODS].join(", ")}`);if(!Number.isFinite(timeout)||timeout<=0)throw new Error("timeout must be a positive number");let targetUrl=new URL(url2);for(let[key,value]of Object.entries(params??{}))targetUrl.searchParams.set(key,String(value));let requestHeaders={Accept:"application/json, text/plain, */*","Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8","User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",...headers},resolvedSourceHeaders=getSendRequestSourceHeaders(targetUrl,headers);resolvedSourceHeaders.referer?setHeader(requestHeaders,"Referer",resolvedSourceHeaders.referer):removeHeader(requestHeaders,"Referer"),resolvedSourceHeaders.origin?setHeader(requestHeaders,"Origin",resolvedSourceHeaders.origin):removeHeader(requestHeaders,"Origin");let cookieHeader=[...cookieMap.entries()].map(([key,value])=>`${key}=${value}`).join("; ");cookieHeader&&setHeader(requestHeaders,"Cookie",cookieHeader);let xsrfToken=cookieMap.get("XSRF-TOKEN");xsrfToken&&!findSendRequestHeaderName(requestHeaders,"x-xsrf-token")&&setHeader(requestHeaders,"X-XSRF-TOKEN",xsrfToken);let requestBody;if(hasMultipartPayload(data)){if(body!=null)throw new Error("body cannot be combined with formData or files");if(normalizedMethod==="GET"||normalizedMethod==="HEAD")throw new Error(`${normalizedMethod} requests cannot use formData or files`);if(findSendRequestHeaderName(requestHeaders,"content-type"))throw new Error("Do not set Content-Type when using formData or files; Mearl sets the boundary");let multipart=await buildMultipartBody(formData,files);requestBody=multipart.body,setHeader(requestHeaders,"Content-Type",multipart.contentType),setHeader(requestHeaders,"Content-Length",String(multipart.body.byteLength))}else body!=null&&!["GET","HEAD"].includes(normalizedMethod)&&(typeof body=="string"?(requestBody=body,findSendRequestHeaderName(requestHeaders,"content-type")||setHeader(requestHeaders,"Content-Type","text/plain")):(requestBody=JSON.stringify(body),findSendRequestHeaderName(requestHeaders,"content-type")||setHeader(requestHeaders,"Content-Type","application/json")));let result=await nodeFetch(targetUrl.toString(),{method:normalizedMethod,headers:requestHeaders,body:requestBody,timeoutMs:timeout}),contentType=(result.headers["content-type"]??"").split(";")[0].trim().toLowerCase(),responseHeaders=Object.fromEntries(Object.entries(result.headers).filter(([name])=>name.toLowerCase()!=="set-cookie"&&name.toLowerCase()!=="set-cookie2")),responseBody,bodyType;if(responseType==="auto"&&isBinarySendRequestContentType(contentType))responseBody=result.bodyBuffer.toString("base64"),bodyType="base64";else{let trimmed=result.body.trimStart();if(responseType==="json"||responseType==="auto"&&contentType.includes("application/json")||responseType==="auto"&&(trimmed.startsWith("{")||trimmed.startsWith("[")))try{responseBody=JSON.parse(result.body),bodyType="json"}catch{if(responseType==="json")throw new Error("send_request expected a JSON response");responseBody=result.body,bodyType="text"}else responseBody=result.body,bodyType="text"}return{success:!0,status:result.status,statusText:result.statusText,headers:responseHeaders,body:responseBody,bodyType,attachedCookieCount:cookieMap.size}}async function cdpSendRequest(session,data){if(!data.url||typeof data.url!="string")throw new Error("Invalid url: url must be a non-empty string");let cookieMap=new Map;if(data.withCookies!==!1)try{cookieMap=await getCookiesForUrl(session,new URL(data.url).toString())}catch{}return executeNodeSendRequest(data,cookieMap)}async function cdpSendMtopRequest(session,data){let{api,data:requestData={},version:version2="1.0",method="GET",appKey="12574478",env="online",timeout=1e4}=data;if(!api||typeof api!="string")throw new Error("Invalid api: api must be a non-empty string");let normalizedEnv=env.toLowerCase(),baseHost=MTOP_HOST_MAP[normalizedEnv];if(!baseHost)throw new Error(`Invalid env: "${env}". Supported values: ${Object.keys(MTOP_HOST_MAP).join(", ")}`);let isMopen=api.startsWith("mopen."),normalizedMethod=method.toUpperCase();if(normalizedMethod!=="GET"&&normalizedMethod!=="POST")throw new Error(`Invalid method: ${method}. mtop only supports GET or POST`);let gatewayUrl=new URL(`https://${baseHost}/h5/${api}/${version2}/`),cookieMap=await getCookiesForUrl(session,gatewayUrl.toString()),token=extractMtopToken(cookieMap,isMopen),timestamp=Date.now(),dataStr=JSON.stringify(requestData),sign=computeMtopSign({api,version:version2,timestamp,appKey,token,dataStr,isMopen}),targetUrl=new URL(gatewayUrl),queryParams={jsv:"2.7.2",appKey,t:timestamp.toString(),sign,api,v:version2,type:"originaljson",dataType:"json"};normalizedMethod==="GET"&&(queryParams.data=dataStr);for(let[key,value]of Object.entries(queryParams))targetUrl.searchParams.set(key,value);let cookieHeader=buildCookieHeaderValue(cookieMap),body,requestHeaders={Cookie:cookieHeader,Accept:"application/json"};normalizedMethod==="POST"&&(body=new URLSearchParams({data:dataStr}).toString(),requestHeaders["Content-Type"]="application/x-www-form-urlencoded");let result=await nodeFetch(targetUrl.toString(),{method:normalizedMethod,headers:requestHeaders,body,timeoutMs:timeout}),responseBody=result.body;try{responseBody=JSON.parse(result.body)}catch{let jsonpMatch=result.body.match(/^[^(]*\((.*)\)\s*;?\s*$/s);if(jsonpMatch)try{responseBody=JSON.parse(jsonpMatch[1])}catch{}}return{success:!0,response:responseBody,requestData}}async function cdpGetApiSchema(session,data){let{api,version:version2="1.0"}=data;if(!api||typeof api!="string")throw new Error("Invalid api: api must be a non-empty string");let targetUrl="https://ultramax.alibaba-inc.com/ultramax/api/query",payload=JSON.stringify({type:"RPC",rpcName:api,rpcVersion:version2}),cookieMap=await getCookiesForUrl(session,targetUrl),cookieHeader=buildCookieHeaderValue(cookieMap),result=await nodeFetch(targetUrl,{method:"POST",headers:{"Content-Type":"application/json",...cookieHeader?{Cookie:cookieHeader}:{}},body:payload,timeoutMs:15e3});if(result.status!==200)throw new Error(`Ultramax API returned status ${result.status}`);let responseBody;try{responseBody=JSON.parse(result.body)}catch{throw new Error(`Failed to parse Ultramax response: ${result.body.slice(0,200)}`)}return responseBody}registerActions([{name:"send_request",session:"page",handler:cdpSendRequest},{name:"send_mtop_request",session:"page",handler:cdpSendMtopRequest},{name:"get_api_schema",session:"page",handler:cdpGetApiSchema}]);var registries=new WeakMap;function getPageRefRegistry(session){let registry2=registries.get(session);if(!registry2){registry2=new BackendNodeRefRegistry,registries.set(session,registry2);let activeRegistry=registry2;session.client.on("Page.frameNavigated",params=>{params.frame?.parentId||activeRegistry.clearDocument()})}return registry2}function beginPageSnapshotRefs(session){return getPageRefRegistry(session).beginSnapshot()}function resolvePageRef(session,ref){return registries.get(session)?.resolve(ref)}function deletePageRef(session,ref){registries.get(session)?.delete(ref)}function clearPageRefsForNavigation(session){registries.get(session)?.clearDocument()}async function enrichCdpPageChangeSetWithRefs(session,observation){return enrichPageChangeSetWithRefs(observation,getPageRefRegistry(session),selectors=>resolveUniqueBackendNodeIds((method,params)=>session.client.sendCommand(method,params),selectors),(node,backendNodeId)=>({backendNodeId,role:node.role??"",name:node.name??""}))}var APP_PROFILE_BINDING="__mearlCdpAppProfileRelay",appProfileStates=new WeakMap;function serializeForSource(value){return JSON.stringify(value).replace(/[\u2028\u2029]/g,character=>character==="\u2028"?"\\u2028":"\\u2029")}function installCdpAppProfileRelay(bindingName){let browser=globalThis,target=globalThis;target.__mearlCdpAppProfileRelayInstalled__||(target.__mearlCdpAppProfileRelayInstalled__=!0,browser.addEventListener("message",event=>{if(event.source!==globalThis)return;let message=event.data;if(!message||message.source!=="mearl-app-bridge")return;let requestId=message.requestId;if(typeof requestId!="number")return;if(message.type==="prepareWebView"){browser.postMessage({source:"mearl-content",type:"APP_BRIDGE_PREPARE_WEBVIEW_RESPONSE",requestId,result:{success:!0}},"*");return}if(message.type!=="mtop"&&message.type!=="mtopStream"&&message.type!=="userInfo")return;let binding=target[bindingName];if(typeof binding=="function")try{binding(JSON.stringify({type:message.type,requestId,payload:message.payload}))}catch{}}))}function installEarlyAppProfileEnvironment(config2){let browser=globalThis,target=globalThis;for(let[key,value]of Object.entries(config2.globals))try{target[key]=value}catch{}let insets=config2.safeAreaInsets??{top:config2.statusBarHeight,right:0,bottom:0,left:0};target.__STATUS_BAR_HEIGHT__=config2.statusBarHeight,target.__SAFE_AREA_INSET_BOTTOM__=insets.bottom;for(let[key,value]of[["userAgent",config2.userAgent],["platform",config2.navigatorPlatform],["vendor","Apple Computer, Inc."],["appVersion",config2.userAgent.replace(/^Mozilla\//,"")],["maxTouchPoints",config2.maxTouchPoints]])try{Object.defineProperty(browser.navigator,key,{configurable:!0,get:()=>value})}catch{}}function installWhenDocumentElementExists(install){let browser=globalThis;if(browser.document.documentElement){install();return}let observer=new browser.MutationObserver(()=>{browser.document.documentElement&&(observer.disconnect(),install())});observer.observe(browser.document,{childList:!0})}function buildDocumentSource(config2){return`;(() => {const config=${serializeForSource(config2)};(${installCdpAppProfileRelay.toString()})(${JSON.stringify(APP_PROFILE_BINDING)});(${installEarlyAppProfileEnvironment.toString()})(config);(${installWhenDocumentElementExists.toString()})(() => {${buildAppProfileRuntimeCallSource("config")};});})();`}function appProfileEmulationCommands(config2,userAgent){return buildEnableEmulationCommands(config2).map(command=>command.method==="Emulation.setUserAgentOverride"?{...command,params:{userAgent,platform:config2.platform}}:command)}async function sendCommands(client2,commands){for(let{method,params,optional:optional2}of commands)await client2.sendCommand(method,params).catch(error48=>{if(!optional2)throw error48})}async function postRuntimeMessage(client2,executionContextId,message){await client2.sendCommand("Runtime.evaluate",{expression:`window.postMessage(${serializeForSource(message)}, '*')`,...typeof executionContextId=="number"?{contextId:executionContextId}:{}})}function listenForBridgeRequests(session,client2,state){return client2.on("Runtime.bindingCalled",params=>{if(params?.name!==APP_PROFILE_BINDING||appProfileStates.get(session)!==state)return;let request;try{request=JSON.parse(params.payload)}catch{return}if(typeof request.requestId!="number")return;let requestId=request.requestId,contextId=typeof params.executionContextId=="number"?params.executionContextId:void 0,reply=message=>postRuntimeMessage(client2,contextId,{requestId,source:"mearl-content",...message});(async()=>{if(request.type==="userInfo"){try{let response=await cdpGetUserInfo(session,{detail:!1});await reply({type:"APP_BRIDGE_USER_INFO_RESPONSE",result:{success:!0,response}})}catch(error48){await reply({type:"APP_BRIDGE_USER_INFO_RESPONSE",result:{success:!1,error:error48 instanceof Error?error48.message:String(error48)}})}return}let payload=request.payload??{},mtopPayload={...payload,...typeof payload.v=="string"&&payload.version===void 0?{version:payload.v}:{}};try{let result=await cdpSendMtopRequest(session,mtopPayload);request.type==="mtopStream"?(await reply({type:"APP_BRIDGE_MTOP_STREAM_EVENT",eventType:"onReceive",data:result.response}),await reply({type:"APP_BRIDGE_MTOP_STREAM_EVENT",eventType:"onFinish",data:{}})):await reply({type:"APP_BRIDGE_MTOP_RESPONSE",result})}catch(error48){let message=error48 instanceof Error?error48.message:String(error48);request.type==="mtopStream"?await reply({type:"APP_BRIDGE_MTOP_STREAM_EVENT",eventType:"onError",data:{ret:["HY_FAILED"],msg:message}}):await reply({type:"APP_BRIDGE_MTOP_RESPONSE",result:{success:!1,error:message}})}})().catch(()=>{})})}async function installChildTarget(session,state,params,source){let sessionId=params.sessionId;if(typeof sessionId!="string")return;let child=session.client.createChildSession(sessionId);try{if(params.targetInfo?.type!=="iframe"||appProfileStates.get(session)!==state)return;await child.sendCommand("Runtime.enable");let frameName=(await child.sendCommand("Runtime.evaluate",{expression:"window.name",returnByValue:!0})).result?.value;if(frameName!=="__mearl_root__"&&frameName!=="__mearl_layer__")return;state.emulation?await sendCommands(child,appProfileEmulationCommands(state.emulation,state.config.userAgent)):await child.sendCommand("Emulation.setUserAgentOverride",{userAgent:state.config.userAgent,platform:state.config.navigatorPlatform}),await child.sendCommand("Runtime.addBinding",{name:APP_PROFILE_BINDING}),state.disposeListeners.push(listenForBridgeRequests(session,child,state)),state.childClients.push(child),await child.sendCommand("Page.addScriptToEvaluateOnNewDocument",{source}).catch(()=>{}),await child.sendCommand("Runtime.evaluate",{expression:source})}finally{await child.sendCommand("Runtime.runIfWaitingForDebugger").catch(()=>{})}}async function disposeState(session,state,disableDeviceEmulation){appProfileStates.get(session)===state&&appProfileStates.delete(session);for(let dispose of state.disposeListeners.splice(0))dispose();await session.client.sendCommand("Target.setAutoAttach",{autoAttach:!1,waitForDebuggerOnStart:!1,flatten:!0}).catch(()=>{}),await session.client.sendCommand("Page.removeScriptToEvaluateOnNewDocument",{identifier:state.documentScriptIdentifier}).catch(()=>{}),await Promise.allSettled([session.client,...state.childClients].map(client2=>client2.sendCommand("Runtime.removeBinding",{name:APP_PROFILE_BINDING}))),disableDeviceEmulation&&(state.ownsDeviceEmulation||!state.independentDeviceEmulation?(await sendCommands(session.client,buildDisableEmulationCommands()),session.emulation=void 0):(await sendCommands(session.client,buildEnableEmulationCommands(state.independentDeviceEmulation)),session.emulation={mobile:state.independentDeviceEmulation.mobile,touch:state.independentDeviceEmulation.touch}))}function resolveCdpAppProfile(profile,options={}){let resolved=resolveAppProfile(profile,{os:options.os,appVersion:options.appVersion,deviceModel:options.deviceModel,simulateSystemBars:options.simulateSystemBars,bridgeConfig:options.bridgeConfig}),emulation=resolveEmulationConfig({preset:resolved.recommendedPreset,...options.emulation,enabled:!0});return{profile:resolved,emulation}}async function applyResolvedCdpAppProfile(session,resolved){let previous=appProfileStates.get(session);previous&&await disposeState(session,previous,!1);let source=buildDocumentSource(resolved.profile.injected);await sendCommands(session.client,appProfileEmulationCommands(resolved.emulation,resolved.profile.ua)),session.emulation={mobile:resolved.emulation.mobile,touch:resolved.emulation.touch},await session.client.sendCommand("Runtime.enable"),await session.client.sendCommand("Runtime.addBinding",{name:APP_PROFILE_BINDING});let script=await session.client.sendCommand("Page.addScriptToEvaluateOnNewDocument",{source});if(typeof script.identifier!="string"||!script.identifier)throw await sendCommands(session.client,buildDisableEmulationCommands()),session.emulation=void 0,new Error("Chrome did not return an app profile bootstrap script identifier");let state={config:resolved.profile.injected,documentScriptIdentifier:script.identifier,emulation:resolved.emulation,ownsDeviceEmulation:!0,disposeListeners:[],childClients:[]};appProfileStates.set(session,state),state.disposeListeners.push(listenForBridgeRequests(session,session.client,state)),state.disposeListeners.push(session.client.on("Target.attachedToTarget",params=>{installChildTarget(session,state,params,source).catch(()=>{})})),await session.client.sendCommand("Target.setAutoAttach",{autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0,filter:[{type:"iframe"},{exclude:!0}]})}function updateCdpAppProfileDeviceEmulation(session,emulation){let state=appProfileStates.get(session);if(state)return state.ownsDeviceEmulation=!1,state.emulation=emulation??void 0,state.independentDeviceEmulation=emulation??void 0,{userAgent:state.config.userAgent,platform:state.config.navigatorPlatform}}function isCdpAppProfileActive(session){return appProfileStates.has(session)}function hasLoadedRootWebView(frameTree){if(!frameTree)return!1;let frame=frameTree.frame;return frame?.name==="__mearl_root__"&&typeof frame.url=="string"&&/^https?:/i.test(frame.url)?!0:Array.isArray(frameTree.childFrames)?frameTree.childFrames.some(child=>hasLoadedRootWebView(child)):!1}async function waitForCdpAppProfileLoad(session,timeoutMs=15e3){let deadline=Date.now()+timeoutMs;for(;Date.now()<deadline;){let result=await session.client.sendCommand("Page.getFrameTree").catch(()=>null);if(hasLoadedRootWebView(result?.frameTree))return;await new Promise(resolve3=>setTimeout(resolve3,50))}throw new Error(`App profile root WebView load timeout after ${timeoutMs}ms`)}async function clearCdpAppProfile(session,reload=!0){let state=appProfileStates.get(session);if(!state)return{enabled:!1,reloaded:!1};await disposeState(session,state,!0);let reloaded=!1;return reload&&(clearPageRefsForNavigation(session),await session.client.sendCommand("Page.reload",{}),await waitForPageLoad(session,3e4),reloaded=!0),{enabled:!1,reloaded}}async function cdpSetAppProfile(session,data){if(typeof data?.enabled!="boolean")throw new Error('set_app_profile: "enabled" is required (true to enable, false to clear)');if(!data.enabled)return clearCdpAppProfile(session,data.reload!==!1);if(!data.profile||typeof data.profile!="string")throw new Error('set_app_profile: "profile" is required when enabled=true');let resolved=resolveCdpAppProfile(data.profile,data);await applyResolvedCdpAppProfile(session,resolved);let reloaded=!1;return data.reload!==!1&&(clearPageRefsForNavigation(session),await session.client.sendCommand("Page.reload",{}),await waitForCdpAppProfileLoad(session),reloaded=!0),{enabled:!0,profile:resolved.profile.profile,label:resolved.profile.label,userAgent:resolved.profile.ua,preset:resolved.emulation.presetName,os:resolved.profile.injected.platform==="Android"?"android":"ios",simulateSystemBars:resolved.profile.injected.simulateSystemBars!==!1,reloaded}}registerActions([{name:"set_app_profile",session:"page",handler:cdpSetAppProfile}]);async function releaseCdpControl(session){let pageSessions=session.listOpenPageSessions(),targetIds=new Set(pageSessions.map(pageSession=>pageSession.targetId)),affectedTabIds=session.listRegisteredTabIds(targetIds).sort((a,b)=>a-b),hadActiveControl=session.hasActiveConnections();try{await releaseCdpRecordings(pageSessions)}finally{await Promise.allSettled(pageSessions.flatMap(pageSession=>[clearCdpAppProfile(pageSession,!1),releaseControlledIndicator(pageSession)])),clearCdpMockState(),session.close()}return{released:!0,hadActiveControl,affectedTabIds}}var SAMPLE_PAGE_READINESS_SRC=samplePageReadinessInPage.toString(),DISPOSE_PAGE_READINESS_SRC=disposePageReadinessObserverInPage.toString();async function startCdpNavigationObserver(cdpSession2,pageSession,urlBefore,options={}){await ensureCdpDomain(pageSession.client,"Page"),options.trackNetwork&&await ensureCdpDomain(pageSession.client,"Network");let browserClient=null,baselineTargetIds=new Set;if(options.trackOpenedTabs)try{browserClient=await cdpSession2.getBrowserClient();let targets=await browserClient.sendCommand("Target.getTargets");for(let target of targets.targetInfos??[])baselineTargetIds.add(target.targetId)}catch{browserClient=null}let mainFrameId=(await pageSession.client.sendCommand("Page.getFrameTree")).frameTree?.frame?.id,tracker=createNavigationSettlementTracker({urlBefore,trackNetwork:options.trackNetwork,networkAvailable:options.trackNetwork===!0,networkIdleMs:options.networkIdleMs,contentReadyAfterMs:options.contentReadyAfterMs,sampleContent:async()=>(await pageSession.client.sendCommand("Runtime.evaluate",{expression:`(${SAMPLE_PAGE_READINESS_SRC})(${options.networkIdleMs??500})`,returnByValue:!0})).result?.value}),removeFrameNavigated=pageSession.client.on("Page.frameNavigated",params=>{params.frame?.parentId||mainFrameId&¶ms.frame?.id!==mainFrameId||tracker.markStarted(params.frame?.url)}),removeWithinDocument=pageSession.client.on("Page.navigatedWithinDocument",params=>{mainFrameId&¶ms.frameId!==mainFrameId||(tracker.markStarted(params.url),tracker.markDocumentComplete(params.url))}),removeLoad=pageSession.client.on("Page.loadEventFired",()=>{tracker.hasStarted()&&tracker.markDocumentComplete()}),removeRequestStarted=options.trackNetwork?pageSession.client.on("Network.requestWillBeSent",params=>{isPotentialNavigationRequest(params.type??"",params.request?.url??"")&&tracker.requestStarted(params.requestId)}):()=>{},onRequestFinished=params=>tracker.requestFinished(params.requestId),removeRequestFinished=options.trackNetwork?pageSession.client.on("Network.loadingFinished",onRequestFinished):()=>{},removeRequestFailed=options.trackNetwork?pageSession.client.on("Network.loadingFailed",onRequestFinished):()=>{};return{hasStarted:tracker.hasStarted,hasNetworkActivity:tracker.hasNetworkActivity,waitForStart:tracker.waitForStart,waitForNetworkIdle:tracker.waitForNetworkIdle,waitForResult:async timeoutMs=>{let result=await tracker.waitForResult(timeoutMs);try{let pageState=await pageSession.client.sendCommand("Runtime.evaluate",{expression:"({ title: document.title, url: location.href })",returnByValue:!0});return{...result,title:pageState.result?.value?.title??result.title,urlAfter:pageState.result?.value?.url??result.urlAfter}}catch{return result}},getOpenedTabs:async timeoutMs=>{if(!browserClient||options.sourceTabId===void 0)return[];let candidates=((await browserClient.sendCommand("Target.getTargets")).targetInfos??[]).filter(target=>target.type==="page"&&target.openerId===pageSession.targetId&&!baselineTargetIds.has(target.targetId));return(await Promise.all(candidates.map(async candidate=>{let tabId=await cdpSession2.ensureTargetRegistered(candidate.targetId),ready=!1;try{let openedPageSession=await cdpSession2.getPageSession(tabId);await ensureCdpDomain(openedPageSession.client,"Page"),await waitForPageLoad(openedPageSession,timeoutMs),ready=!0}catch{}let targetInfo=await browserClient.sendCommand("Target.getTargetInfo",{targetId:candidate.targetId}).then(result=>result.targetInfo).catch(()=>null);return targetInfo?{tabId,openerTabId:options.sourceTabId,url:targetInfo.url??candidate.url??"",title:targetInfo.title??candidate.title??"",ready,settledBy:ready?"load":"timeout"}:null}))).filter(tab=>tab!==null)},dispose:async()=>{removeFrameNavigated(),removeWithinDocument(),removeLoad(),removeRequestStarted(),removeRequestFinished(),removeRequestFailed(),tracker.dispose(),await pageSession.client.sendCommand("Runtime.evaluate",{expression:`(${DISPOSE_PAGE_READINESS_SRC})()`,returnByValue:!1}).catch(()=>{})}}}var INSTALL_PAGE_OBSERVER_SRC=installPageObserverInPage.toString(),DISPOSE_PAGE_OBSERVER_SRC=disposePageObserverInPage.toString(),PAGE_OBSERVER_GLOBAL="__MEARL_PAGE_OBSERVER__";function evaluationError(result){return result.exceptionDetails?result.exceptionDetails.exception?.description??result.exceptionDetails.text??"Page observation evaluation failed":null}async function startPageObservation(session){let result=await session.client.sendCommand("Runtime.evaluate",{expression:`(${INSTALL_PAGE_OBSERVER_SRC})()`,returnByValue:!0}),error48=evaluationError(result);if(error48)throw new Error(error48);let checkpoint=result.result?.value;if(!checkpoint||typeof checkpoint.version!="number")throw new Error("Page observer did not return a checkpoint");return checkpoint}async function finishPageObservation(session,checkpoint,options={}){let{quietMs,firstChangeTimeoutMs,timeoutMs}=resolvePageObservationWaitOptions(options),expression=`(() => {
|
|
833
|
-
const state = globalThis[${JSON.stringify(PAGE_OBSERVER_GLOBAL)}];
|
|
834
|
-
if (!state || typeof state.waitSince !== 'function') {
|
|
835
|
-
throw new Error('Page observer is unavailable after the action');
|
|
836
|
-
}
|
|
837
|
-
return state.waitSince(
|
|
838
|
-
${checkpoint.version},
|
|
839
|
-
${JSON.stringify(checkpoint.focus)},
|
|
840
|
-
${quietMs},
|
|
841
|
-
${firstChangeTimeoutMs},
|
|
842
|
-
${timeoutMs}
|
|
843
|
-
);
|
|
844
|
-
})()`,result=await session.client.sendCommand("Runtime.evaluate",{expression,returnByValue:!0,awaitPromise:!0},timeoutMs+2e3),error48=evaluationError(result);if(error48)throw new Error(error48);let changeSet=result.result?.value;if(!changeSet||changeSet.mode!=="delta")throw new Error("Page observer did not return a change set");return changeSet}async function disposePageObservation(session){await session.client.sendCommand("Runtime.evaluate",{expression:`(${DISPOSE_PAGE_OBSERVER_SRC})()`,returnByValue:!1}).catch(()=>{})}function filterRequests(buffers,opts){let pattern=opts.filter?compileTextPattern(opts.filter):void 0;return queryCapturedEntries(buffers.requests.filter(request=>Number.isSafeInteger(request.captureSequence)),buffers.capture,{after:opts.after,since:opts.since,limit:opts.count??10},request=>(!opts.source||opts.source==="all"||request.source===opts.source)&&(!pattern||matchesTextPattern(request.url,pattern)||matchesTextPattern(request.apiName,pattern)),buffers.capture.droppedRequestsThroughSequence,"requests")}async function cdpGetRequests(session,data){let opts={count:data.count??10,filter:data.filter,since:data.since,after:data.after,source:data.source,applyHiddenFilter:data.applyHiddenFilter!==!1},captured=filterRequests(session.buffers,opts),serializeOpts={includeBody:data.includeBody!==!1,includeHeaders:data.includeHeaders===!0,maxBodySize:data.maxBodySize??5e4,fields:data.fields,keysOnly:data.keysOnly===!0};return{meta:{count:captured.entries.length,totalMatched:captured.totalMatched,totalInBuffer:session.buffers.requests.length,filter:data.filter,since:data.since,after:data.after,nextCursor:captured.nextCursor,hasMore:captured.hasMore,gap:captured.gap,source:"cdp"},requests:captured.entries.map(r=>serializeRequest(r,serializeOpts))}}async function cdpGetLogs(session,data){let{level,since,after,limit=100,filter}=data,pattern=filter?compileTextPattern(filter):void 0,captured=queryCapturedEntries(session.buffers.logs,session.buffers.capture,{after,since,limit},log3=>(!level||level==="all"||log3.level===level)&&(!pattern||matchesTextPattern(log3.message,pattern)||log3.args.some(arg=>matchesTextPattern(arg,pattern))),session.buffers.capture.droppedLogsThroughSequence,"logs"),captureStatus=session.buffers.logs.length===0?"armed":"active";return{meta:{count:captured.entries.length,totalMatched:captured.totalMatched,totalInBuffer:session.buffers.logs.length,level:level||"all",since,after,filter,nextCursor:captured.nextCursor,hasMore:captured.hasMore,gap:captured.gap,captureStatus,...captureStatus==="armed"&&{hint:"Log capture is active, but this tab has no captured history yet. Reload the current tab or repeat the triggering action, then call get_logs again."},source:"cdp"},logs:captured.entries}}async function cdpCaptureCheckpoint(session,_data){return{tabId:session.tabId,cursor:captureCheckpoint(session.buffers.capture),timestampMs:Date.now(),captureStatus:session.buffers.capture.currentSequence===0?"armed":"active"}}async function collectCdpPageDiagnostics(session,after,diagnostics){let result={};if(diagnostics.logs){let options=diagnostics.logs===!0?{level:"error",limit:100}:{level:"error",limit:100,...diagnostics.logs};result.logs=await cdpGetLogs(session,{...options,after})}if(diagnostics.requests){let options=diagnostics.requests===!0?{source:"all",includeBody:!1,count:100}:{source:"all",includeBody:!1,count:100,...diagnostics.requests};result.requests=await cdpGetRequests(session,{...options,after})}if(diagnostics.events){let options=diagnostics.events===!0?{source:"all",limit:100}:{source:"all",limit:100,...diagnostics.events};result.events=await cdpGetEvents(session,{...options,after})}return result}async function cdpGetEvents(session,data){let{source="all",event_type,since,after,limit=20,filter,includeRaw=!1}=data,response=queryCapturedTrackingEvents(session.buffers.events,session.buffers.capture,{source,event_type,since,after,limit,filter},session.buffers.capture.droppedEventsThroughSequence),captureStatus=response.totalInBuffer===0?"armed":"active",hint=response.events.length===0&&captureStatus==="armed"?TRACKING_CAPTURE_ARMED_HINT:void 0;return{meta:{count:response.events.length,totalMatched:response.totalMatched,totalInBuffer:response.totalInBuffer,source,captureStatus,captureSource:"cdp",includeRaw,after,nextCursor:response.nextCursor,hasMore:response.hasMore,gap:response.gap,hint},events:response.events.map(event=>formatTrackingEvent(event,includeRaw))}}registerActions([{name:"tab_checkpoint",session:"page",handler:cdpCaptureCheckpoint},{name:"capture_checkpoint",session:"page",handler:cdpCaptureCheckpoint},{name:"get_requests",session:"page",handler:cdpGetRequests},{name:"get_logs",session:"page",handler:cdpGetLogs},{name:"get_events",session:"page",handler:cdpGetEvents}]);async function cdpRunActions(session,data,controlSource="local"){let{actions,tabId}=data;if(!Array.isArray(actions)||actions.length===0)throw new Error("actions must be a non-empty array");if(actions.length>50)throw new Error("actions array exceeds maximum of 50 steps");let results=[];for(let i=0;i<actions.length;i++){let step=actions[i],stepAction=String(step.action??"");if(!stepAction)return{results,completedSteps:results.length,totalSteps:actions.length,error:`Step ${i}: action must be a non-empty string`,failedStep:i};if(!isBrowserCommandAction(stepAction))return{results,completedSteps:results.length,totalSteps:actions.length,error:`Step ${i}: unsupported action "${stepAction}"`,failedStep:i};if(stepAction==="run_actions")return{results,completedSteps:results.length,totalSteps:actions.length,error:`Step ${i}: composite action "${stepAction}" is not allowed in run_actions`,failedStep:i};if(stepAction==="browser_release")return{results,completedSteps:results.length,totalSteps:actions.length,error:`Step ${i}: browser-level action "${stepAction}" is not allowed in run_actions`,failedStep:i};let mergedData={...step.data};tabId!==void 0&&mergedData.tabId===void 0&&(mergedData.tabId=tabId);try{let result=await dispatchCdpAction(session,stepAction,mergedData,controlSource);results.push({step:i,action:stepAction,success:!0,data:result})}catch(error48){let errorMessage2=error48 instanceof Error?error48.message:String(error48);return results.push({step:i,action:stepAction,success:!1,error:errorMessage2}),{results,completedSteps:i,totalSteps:actions.length,error:errorMessage2,failedStep:i}}}return{results,completedSteps:actions.length,totalSteps:actions.length}}async function cdpObservedPageAction(session,action,data,controlSource="local"){let{actionData,observe,diagnostics}=splitObservedActionPayload(action,data),{tabId}=actionData;if(typeof tabId!="number")throw new Error(`${action} requires a numeric tabId`);let pageSession=await session.getPageSession(tabId);if(await ensureControlledIndicator(pageSession,controlSource),observe===!1){if(!diagnostics)return dispatchCdpAction(session,action,actionData,controlSource);let cursor=captureCheckpoint(pageSession.buffers.capture),actionResult,actionFailure;try{actionResult=await dispatchCdpAction(session,action,actionData,controlSource)}catch(error48){actionFailure=describePageActionFailure(error48)}let result2={action:{name:action,success:actionFailure===void 0,...actionResult!==void 0?{data:actionResult}:{},...actionFailure||{}}};return actionFailure?.stage==="precondition"?result2:{...result2,diagnostics:await collectCdpPageDiagnostics(pageSession,cursor,diagnostics)}}let diagnosticsCursor,result=await runPageAct({action,actionData,observe},{startObservation:()=>startPageObservation(pageSession),finishObservation:(checkpoint,options)=>finishPageObservation(pageSession,checkpoint,options),startNavigationObserver:options=>startCdpNavigationObserver(session,pageSession,options.urlBefore,options),executeAction:(name,params)=>(diagnostics&&(diagnosticsCursor=captureCheckpoint(pageSession.buffers.capture)),dispatchCdpAction(session,name,{...params,tabId},controlSource)),finalizeObservation:observation=>observation.mode==="delta"?enrichCdpPageChangeSetWithRefs(pageSession,observation):Promise.resolve(observation),disposeObservation:()=>disposePageObservation(pageSession)});return!diagnostics||!diagnosticsCursor||result.action.stage==="precondition"?result:{...result,diagnostics:await collectCdpPageDiagnostics(pageSession,diagnosticsCursor,diagnostics)}}registerActions([{name:"run_actions",session:"browser",handler:cdpRunActions}]);import{randomUUID as randomUUID2}from"node:crypto";import{createReadStream}from"node:fs";var FILE_CHUNK_BYTES=256*1024,TRANSFER_ACTION_TIMEOUT_MS=15e3;async function sendFileChunks(transferId,fileIndex,file2,send){let chunkIndex=0,sendChunk=async chunk=>{await send("__send_request_file_chunk",{transferId,fileIndex,chunkIndex,base64:chunk.toString("base64")},TRANSFER_ACTION_TIMEOUT_MS),chunkIndex+=1};if(file2.filePath){for await(let chunk of createReadStream(file2.filePath,{highWaterMark:FILE_CHUNK_BYTES}))await sendChunk(Buffer.isBuffer(chunk)?chunk:Buffer.from(chunk));return}let content=file2.content;for(let offset=0;offset<content.byteLength;offset+=FILE_CHUNK_BYTES)await sendChunk(content.subarray(offset,offset+FILE_CHUNK_BYTES))}async function prepareFileTransfer(data,send){let files=await resolveSendRequestFiles(data.files??[]);if(files.length===0)throw new Error("files must contain at least one file");let transferId=randomUUID2();await send("__send_request_file_start",{transferId,files:files.map(file2=>file2.descriptor),url:data.url,withCookies:data.withCookies},TRANSFER_ACTION_TIMEOUT_MS);try{for(let index=0;index<files.length;index+=1)await sendFileChunks(transferId,index,files[index],send)}catch(error48){throw await send("__send_request_file_abort",{transferId},TRANSFER_ACTION_TIMEOUT_MS).catch(()=>{}),error48}let{files:_files,...request}=data;return{transferId,request}}async function abortFileTransfer(transferId,send){await send("__send_request_file_abort",{transferId},TRANSFER_ACTION_TIMEOUT_MS).catch(()=>{})}function hasSendRequestFiles(data){return!!data&&typeof data=="object"&&Array.isArray(data.files)&&data.files.length>0}function hasRunActionsSendRequestFiles(data){if(!data||typeof data!="object")return!1;let actions=data.actions;return Array.isArray(actions)&&actions.some(step=>step?.action==="send_request"&&hasSendRequestFiles(step.data))}async function sendRequestWithTransferredFiles(data,send){let prepared=await prepareFileTransfer(data,send);try{let requestTimeout=Number(data.timeout??3e4);return await send("__send_request_with_files",{...prepared.request,transferId:prepared.transferId},(Number.isFinite(requestTimeout)&&requestTimeout>0?requestTimeout:3e4)+5e3)}catch(error48){throw await abortFileTransfer(prepared.transferId,send),error48}}async function sendRunActionsWithTransferredFiles(data,send,resolveTimeoutMs){if(!Array.isArray(data.actions))throw new Error("actions must be an array");let preparedTransferIds=[];try{let actions=[];for(let index=0;index<data.actions.length;index+=1){let step=data.actions[index],action=String(step.action??"");if(action.startsWith("__"))throw new Error(`Step ${index}: internal action "${action}" is not available to clients`);if(action!=="send_request"||!hasSendRequestFiles(step.data)){actions.push(step);continue}let prepared=await prepareFileTransfer(step.data,send);preparedTransferIds.push(prepared.transferId),actions.push({action:"__send_request_with_files",data:{...prepared.request,transferId:prepared.transferId}})}let transformed={...data,actions};return await send("run_actions",transformed,resolveTimeoutMs(transformed))}finally{await Promise.all(preparedTransferIds.map(transferId=>abortFileTransfer(transferId,send)))}}import fs2 from"node:fs";import path2 from"node:path";import{spawn as spawn2,spawnSync}from"node:child_process";function isAlive(pid){if(!pid||pid<=0)return!1;try{return process.kill(pid,0),!0}catch(error48){return error48.code==="EPERM"}}import{join}from"node:path";import{homedir}from"node:os";import{createHash}from"node:crypto";var DAEMON_HOME=join(homedir(),".mearl");function hashKey(key){return createHash("sha256").update(key).digest("hex").slice(0,16)}function keyedDir(subdir){return join(DAEMON_HOME,subdir)}function keyedConfigFile(subdir,key){return join(keyedDir(subdir),`${hashKey(key)}.json`)}import{existsSync,mkdirSync,readFileSync,writeFileSync,renameSync,rmSync,readdirSync}from"node:fs";import{dirname,join as join2}from"node:path";function ensureDir(dir){existsSync(dir)||mkdirSync(dir,{recursive:!0,mode:448})}function writeRecord(file2,record2){ensureDir(dirname(file2));let tmp=`${file2}.${process.pid}.tmp`;try{writeFileSync(tmp,JSON.stringify(record2),{mode:384}),renameSync(tmp,file2)}catch(error48){try{rmSync(tmp,{force:!0})}catch{}throw error48}}function readRecord(file2){try{if(!existsSync(file2))return null;let parsed=JSON.parse(readFileSync(file2,"utf-8"));return parsed&&typeof parsed.pid=="number"?parsed:null}catch{return null}}function removeRecord(file2){try{rmSync(file2,{force:!0})}catch{}}function listRecordFiles(dir){try{return readdirSync(dir).filter(name=>name.endsWith(".json")).map(name=>join2(dir,name))}catch{return[]}}function readLiveRecords(dir){let out=[];for(let file2 of listRecordFiles(dir)){let rec=readRecord(file2);rec&&isAlive(rec.pid)?out.push(rec):removeRecord(file2)}return out}import{existsSync as existsSync2,statSync,renameSync as renameSync2,readFileSync as readFileSync2}from"node:fs";var DEFAULT_MAX_LOG_BYTES=5*1024*1024;import{spawn}from"node:child_process";import{openSync}from"node:fs";import{dirname as dirname2}from"node:path";var processes=new Map,CONNECTORS_SUBDIR="connectors",REGISTRY_DIR=keyedDir(CONNECTORS_SUBDIR),OFFICIAL_NPM_REGISTRY="https://registry.npmjs.org",STATUS_POLL_MS=5e3;function recordFileFor(serverUrl){return keyedConfigFile(CONNECTORS_SUBDIR,serverUrl)}var logFn=()=>{},isDaemon=!1,sendToExtensionFn=()=>{},nativeHostVersion="unknown",lastPushedKey="",statusWatcher=null;function initCloudConnector(deps){logFn=deps.log,isDaemon=deps.isDaemonMode,sendToExtensionFn=deps.sendToExtension,nativeHostVersion=deps.version,startStatusWatcher()}function liveRecords(){return readLiveRecords(REGISTRY_DIR)}function reconcile(){let live=new Map;for(let record2 of liveRecords())live.set(record2.serverUrl,{serverUrl:record2.serverUrl,pid:record2.pid,...record2.connectorId?{connectorId:record2.connectorId}:{},...record2.name?{name:record2.name}:{}});for(let[serverUrl,entry]of processes)isAlive(entry.pid)?live.has(serverUrl)||live.set(serverUrl,{serverUrl,pid:entry.pid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{}}):processes.delete(serverUrl);return Array.from(live.values())}function connectorsKey(connectors){return connectors.map(c=>`${c.serverUrl}@${c.pid}@${c.connectorId??""}@${c.name??""}`).sort().join("|")}function pushStatus(connectors){isDaemon||(lastPushedKey=connectorsKey(connectors),sendToExtensionFn({type:"cloud_connector_status_changed",data:{connectors}}))}function notifyStatusChanged(){pushStatus(reconcile())}function pushIfChanged(){let connectors=reconcile();return connectorsKey(connectors)!==lastPushedKey&&pushStatus(connectors),connectors}function startStatusWatcher(){isDaemon||statusWatcher||(statusWatcher=setInterval(()=>{try{pushIfChanged()}catch{}},STATUS_POLL_MS),statusWatcher.unref?.())}function registerConnector(serverUrl,pid,child){let record2=readRecord(recordFileFor(serverUrl)),entry={pid,serverUrl,...record2?.connectorId?{connectorId:record2.connectorId}:{},...record2?.name?{name:record2.name}:{},...child?{process:child}:{}};return processes.set(serverUrl,entry),notifyStatusChanged(),entry}function clearConnector(serverUrl,child){let entry=processes.get(serverUrl);child&&entry&&entry.process!==child||(processes.delete(serverUrl),removeRecord(recordFileFor(serverUrl)),notifyStatusChanged())}function findLiveConnector(serverUrl){let entry=processes.get(serverUrl);if(entry&&isAlive(entry.pid))return entry.pid;let record2=readRecord(recordFileFor(serverUrl));return record2&&isAlive(record2.pid)?record2.pid:(entry&&processes.delete(serverUrl),record2&&removeRecord(recordFileFor(serverUrl)),null)}function findBin(bin,env){let lookupCommand=process.platform==="win32"?"where":"which",result=spawnSync(lookupCommand,[bin],{encoding:"utf-8",env});return result.status===0&&result.stdout.split(/\r?\n/).find(Boolean)||null}function getBinVersion(binPath){try{let result=spawnSync(process.execPath,[binPath,"--version"],{encoding:"utf-8",timeout:5e3});return result.status===0?result.stdout.trim():null}catch{return null}}function makeDirectCommand(connectorPath){return process.platform!=="win32"?{command:process.execPath,argsPrefix:[connectorPath],displayName:`${process.execPath} ${connectorPath}`}:{command:connectorPath,argsPrefix:[],displayName:connectorPath}}function resolveCloudConnectorCommand(){let connectorBin=process.platform==="win32"?"mearl-cloud-connector.cmd":"mearl-cloud-connector",pathDelimiter=process.platform==="win32"?";":":",nodeDir=path2.dirname(process.execPath),enrichedPath=[nodeDir,process.env.PATH].filter(Boolean).join(pathDelimiter),enrichedEnv={...process.env,PATH:enrichedPath},connectorPath=findBin(connectorBin,enrichedEnv);if(connectorPath){let installedVersion=getBinVersion(connectorPath);if(installedVersion===nativeHostVersion)return logFn(`Cloud connector ${installedVersion} found at ${connectorPath}`),makeDirectCommand(connectorPath);logFn(`Cloud connector version mismatch: installed=${installedVersion}, expected=${nativeHostVersion}`)}let npmBin=process.platform==="win32"?"npm.cmd":"npm",npmPath=path2.join(nodeDir,npmBin),npmCommand=fs2.existsSync(npmPath)?npmPath:npmBin,targetPackage=`@mearl/cloud-connector@${nativeHostVersion}`;logFn(`Installing ${targetPackage} globally via ${npmCommand}...`);let install=spawnSync(npmCommand,["install","-g",targetPackage,"--prefer-offline",`--registry=${OFFICIAL_NPM_REGISTRY}`],{encoding:"utf-8",env:enrichedEnv,timeout:3e4});if(install.status===0){let newPath=findBin(connectorBin,enrichedEnv);if(newPath)return logFn(`Global install succeeded: ${newPath}`),makeDirectCommand(newPath)}logFn(`Global install failed (status=${install.status}), falling back to npx`),install.stderr&&logFn(install.stderr.trim());let npxBin=process.platform==="win32"?"npx.cmd":"npx",npxPath=path2.join(nodeDir,npxBin),npxCommand=fs2.existsSync(npxPath)?npxPath:npxBin;return{command:npxCommand,argsPrefix:[`@mearl/cloud-connector@${nativeHostVersion}`],displayName:`${npxCommand} @mearl/cloud-connector@${nativeHostVersion}`,env:enrichedEnv}}function startCloudConnector(serverUrl){return new Promise(resolve3=>{let existingPid=findLiveConnector(serverUrl);if(existingPid){logFn(`Reusing existing cloud connector for ${serverUrl} (pid=${existingPid})`);let entry=registerConnector(serverUrl,existingPid);resolve3({success:!0,pid:existingPid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{},reused:!0});return}let connectorCommand=resolveCloudConnectorCommand();logFn(`Starting cloud connector via ${connectorCommand.displayName}`);let child=spawn2(connectorCommand.command,[...connectorCommand.argsPrefix,serverUrl,"--fail-fast"],{detached:!0,env:connectorCommand.env,stdio:["ignore","pipe","pipe"],windowsHide:!0}),settled=!1,outputBuffer="",startupTimer=setTimeout(()=>{finish(!1,{error:"Cloud connector startup timeout"}),child.kill()},6e4),finish=(ok,result={})=>{if(!settled)if(settled=!0,clearTimeout(startupTimer),ok&&child.pid){let entry=registerConnector(serverUrl,child.pid,child);resolve3({success:!0,pid:child.pid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{}})}else resolve3({success:!1,error:result.error||"Failed to spawn cloud connector"})};child.once("error",error48=>{logFn(`Failed to spawn cloud connector: ${error48.message}`),finish(!1,{error:error48.message})});let handleOutput=chunk=>{let text=chunk.toString();outputBuffer=(outputBuffer+text).slice(-2e3),logFn(`[CloudConnector] ${text.trim()}`),text.includes("[CloudConnector] Connected to")&&finish(!0)};child.stdout?.on("data",handleOutput),child.stderr?.on("data",handleOutput),child.once("spawn",()=>{child.once("exit",(code,signal)=>{clearConnector(serverUrl,child),logFn(`Cloud connector exited for ${serverUrl}: code=${code??"null"} signal=${signal??"null"}`),settled||finish(!1,{error:outputBuffer.trim()||`Cloud connector exited before connected: code=${code??"null"} signal=${signal??"null"}`})}),child.unref()})})}function stopCloudConnector(serverUrl){let pid=processes.get(serverUrl)?.pid??readRecord(recordFileFor(serverUrl))?.pid;if(!pid)return{success:!1,error:"Cloud connector not found"};try{return isAlive(pid)&&process.kill(pid),clearConnector(serverUrl),logFn(`Stopped cloud connector for ${serverUrl} (pid=${pid})`),{success:!0}}catch(error48){let err=error48;return err.code==="ESRCH"?(clearConnector(serverUrl),{success:!0}):(logFn(`Failed to stop cloud connector: ${err.message}`),{success:!1,error:err.message})}}function listCloudConnectors(){return{connectors:pushIfChanged()}}var TDBANK_LOGIN_URL="https://tdbank.alibaba-inc.com",TdbankLoginRequiredError=class extends Error{},tdbankLoginAttempts=new WeakMap;async function cdpFetchTdbankRequest(session,path23,options={}){let url2=new URL(`https://tdbank.alibaba-inc.com${path23}`);for(let[key,value]of Object.entries(options.params??{}))value!=null&&url2.searchParams.set(key,String(value));let cookies=await getCookiesForUrl(session,url2.toString()),cookieHeader=buildCookieHeaderValue(cookies),headers={Accept:"application/json, text/plain, */*","Accept-Language":"en"};cookieHeader&&(headers.Cookie=cookieHeader);let method="GET",body;if(options.formBody){method="POST";let form=buildMultipartFormBody(options.formBody);headers["Content-Type"]=form.contentType,body=form.body}else options.body&&(method="POST",headers["Content-Type"]="application/json",body=JSON.stringify(options.body));let response=await nodeFetch(url2.toString(),{method,headers,body,timeoutMs:options.timeoutMs});if(response.status===401||response.status===403||response.status>=300&&response.status<400)throw new TdbankLoginRequiredError("未登录 TDBank,请先登录 tdbank.alibaba-inc.com");if(response.status<200||response.status>=300)throw new Error(`TDBank request failed (${response.status} ${response.statusText})`);let text=response.body;if(text.trimStart().startsWith("<"))throw new TdbankLoginRequiredError("未登录 TDBank,请先登录 tdbank.alibaba-inc.com");let payload;try{payload=JSON.parse(text)}catch{throw new Error("TDBank returned a non-JSON response")}if(payload?.success)return payload.data;throw new Error(payload?.message||`TDBank request failed (${payload?.code??"unknown"})`)}async function cdpGetTracknick(session){let cookies=await getCookiesForUrl(session,"https://www.taobao.com/");return decodeTracknick(cookies.get("tracknick")??"")}async function cdpWaitForTracknick(session,options={}){let{previous="",expected="",timeoutMs=1e4}=options,startedAt=Date.now(),latest="";for(;Date.now()-startedAt<timeoutMs;){if(latest=await cdpGetTracknick(session),expected&&latest===expected||!expected&&latest&&latest!==previous)return latest;await new Promise(resolve3=>setTimeout(resolve3,500))}return latest||await cdpGetTracknick(session)}async function cdpOpenAndCloseTarget(cdpSession2,url2){let browser=await cdpSession2.getBrowserClient(),{targetId}=await browser.sendCommand("Target.createTarget",{url:url2,background:!0});await new Promise(resolve3=>setTimeout(resolve3,3500)),await browser.sendCommand("Target.closeTarget",{targetId}).catch(()=>{})}async function refreshTdbankLogin(cdpSession2){let existing=tdbankLoginAttempts.get(cdpSession2);if(existing)return existing;let attempt=cdpOpenAndCloseTarget(cdpSession2,TDBANK_LOGIN_URL).finally(()=>{tdbankLoginAttempts.get(cdpSession2)===attempt&&tdbankLoginAttempts.delete(cdpSession2)});return tdbankLoginAttempts.set(cdpSession2,attempt),attempt}async function cdpFetchTdbank(cdpSession2,session,path23,options={}){try{return await cdpFetchTdbankRequest(session,path23,options)}catch(error48){if(!(error48 instanceof TdbankLoginRequiredError))throw error48}return await refreshTdbankLogin(cdpSession2),cdpFetchTdbankRequest(session,path23,options)}async function cdpFetchTdbankAccounts(cdpSession2,pageSession,pageIndex=1){let data=await cdpFetchTdbank(cdpSession2,pageSession,"/findPagedUsingAccountsByUser.do",{params:{_input_charset:"utf-8",pageIndex,searchKey:"",searchVal:""}});return{...data,accountList:Array.isArray(data?.accountList)?data.accountList:[]}}async function cdpSwitchTdbankAccount(cdpSession2,pageSession,account){let previousNickname=await cdpGetTracknick(pageSession),ssoUrl=await cdpFetchTdbank(cdpSession2,pageSession,"/accountSso.do",{params:{_input_charset:"utf-8"},formBody:{havanaId:String(account.havanaId),site:String(account.site)}});await cdpOpenAndCloseTarget(cdpSession2,String(ssoUrl));let nickname=await cdpWaitForTracknick(pageSession,{previous:account.loginId?previousNickname:"",expected:account.loginId});return{...account.id!==void 0?{accountId:String(account.id)}:{},nickname}}async function cdpCreateTdbankSsoUrl(cdpSession2,pageSession,account){return String(await cdpFetchTdbank(cdpSession2,pageSession,"/accountSso.do",{params:{_input_charset:"utf-8"},formBody:{havanaId:String(account.havanaId),site:String(account.site)}}))}async function cdpResolveTdbankAccount(cdpSession2,pageSession,data){if(data.accountId!==void 0){let account=(await cdpFetchTdbankAccounts(cdpSession2,pageSession,1)).accountList.find(account2=>String(account2.id)===String(data.accountId));if(!account)throw new Error(`TDBank account not found: ${data.accountId}`);if(account.site===void 0||account.site===null)throw new Error(`TDBank account ${data.accountId} has no site`);return account}if(data.havanaId!==void 0&&data.site!==void 0)return{id:data.havanaId,havanaId:data.havanaId,site:data.site};throw new Error("accountId or havanaId + site is required")}async function cdpBorrowAndResolveTdbankAccount(cdpSession2,pageSession,query){let searchResult=await cdpFetchTdbank(cdpSession2,pageSession,"/searchAccountByInputV2.do",{params:{_input_charset:"utf-8",loginId:query,site:0}});if(!Array.isArray(searchResult)||searchResult.length===0)throw new Error(`No TDBank account found for: ${query}`);let account=searchResult[0],{havanaId,accountBucId,site}=account;if(!havanaId||!accountBucId||site===void 0||site===null)throw new Error("TDBank search result is missing havanaId/accountBucId/site");try{await cdpFetchTdbank(cdpSession2,pageSession,"/quickApplyAccountV2.do",{params:{_input_charset:"utf-8",accountBucId,accreditType:7,havanaId,site}})}catch(error48){if(!(error48 instanceof Error?error48.message:String(error48)).includes("已经借用"))throw error48}return account}async function cdpPrepareTdbankSso(cdpSession2,data){let pageSession=await cdpSession2.getPageSession(typeof data?.tabId=="number"?data.tabId:void 0),query=String(data?.query??"").trim(),account=query?await cdpBorrowAndResolveTdbankAccount(cdpSession2,pageSession,query):await cdpResolveTdbankAccount(cdpSession2,pageSession,data),havanaId=account.havanaId??account.id;return{ssoUrl:await cdpCreateTdbankSsoUrl(cdpSession2,pageSession,{havanaId,site:account.site}),account:{accountId:account.id!==void 0?String(account.id):void 0,havanaId:String(havanaId),site:String(account.site),loginId:data.havanaId===void 0&&account.loginId?String(account.loginId):void 0}}}async function cdpConsumeTdbankSso(cdpSession2,ssoUrl,expectedLoginId){let browser=await cdpSession2.getBrowserClient(),{targetId}=await browser.sendCommand("Target.createTarget",{url:ssoUrl,background:!0});try{let tabId=await cdpSession2.registerTarget(targetId),pageSession=await cdpSession2.getPageSession(tabId),nickname=await cdpWaitForTracknick(pageSession,{expected:expectedLoginId,timeoutMs:15e3});if(!nickname)throw new Error("TDBank SSO completed without a tracknick cookie");if(expectedLoginId&&nickname!==expectedLoginId)throw new Error(`TDBank SSO account mismatch: expected ${expectedLoginId}, got ${nickname}`);return{nickname}}finally{await browser.sendCommand("Target.closeTarget",{targetId}).catch(()=>{})}}async function cdpTdbankAccount(cdpSession2,data){let pageSession=await cdpSession2.getPageSession(typeof data?.tabId=="number"?data.tabId:void 0),operation=data?.operation??"list";if(operation==="current"){let nickname=await cdpGetTracknick(pageSession),account=null;if(nickname)try{account=(await cdpFetchTdbankAccounts(cdpSession2,pageSession,1)).accountList.find(account2=>account2.loginId===nickname)??null}catch{account=null}return{nickname,account,source:"cdp"}}if(operation==="list")return{...await cdpFetchTdbankAccounts(cdpSession2,pageSession,data?.pageIndex??1),nickname:await cdpGetTracknick(pageSession),source:"cdp"};if(operation==="switch"){let account=await cdpResolveTdbankAccount(cdpSession2,pageSession,data);return cdpSwitchTdbankAccount(cdpSession2,pageSession,{id:account.id,havanaId:account.havanaId??account.id,site:account.site,loginId:account.loginId})}if(operation==="borrow"){let query=String(data?.query??"").trim();if(!query)throw new Error("query is required for TDBank borrow");let account=await cdpBorrowAndResolveTdbankAccount(cdpSession2,pageSession,query),{havanaId,site}=account,switchResult=await cdpSwitchTdbankAccount(cdpSession2,pageSession,{havanaId,site,loginId:account.loginId});return{account,switchResult}}throw new Error(`Unknown TDBank operation: ${operation}`)}registerActions([{name:"tdbank_account",session:"browser",handler:cdpTdbankAccount}]);function currentCapture(pageSession){return{tabId:pageSession.tabId,cursor:captureCheckpoint(pageSession.buffers.capture),timestampMs:Date.now(),captureStatus:pageSession.buffers.capture.currentSequence===0?"armed":"active"}}async function cdpTabOpen(session,data,controlSource="local"){let{url:url2,active=!1,emulation,reuse="never",match,appProfile}=data;if(!url2||typeof url2!="string")throw new Error("Invalid url: url must be a non-empty string");if(!["never","prefer","require"].includes(reuse))throw new Error('Invalid reuse: expected "never", "prefer", or "require"');if(data.os!==void 0&&data.os!=="ios"&&data.os!=="android")throw new Error('Invalid os: expected "ios" or "android"');if(data.os!==void 0&&!appProfile)throw new Error("tab_open os requires appProfile.");if(data.bridgeConfig!==void 0&&!appProfile)throw new Error("tab_open bridgeConfig requires appProfile.");let resolvedProfile=appProfile?resolveCdpAppProfile(appProfile,{os:data.os,simulateSystemBars:data.simulateSystemBars,bridgeConfig:data.bridgeConfig,emulation}):void 0,emulationConfig=resolvedProfile?.emulation??(emulation?resolveEmulationConfig({...emulation,enabled:!0}):void 0),browserClient=await session.getBrowserClient();if(reuse!=="never"){let pages=((await browserClient.sendCommand("Target.getTargets")).targetInfos??[]).filter(target=>target.type==="page"&&!target.url.startsWith("chrome-extension://")&&!target.url.startsWith("about:")&&!target.url.startsWith("chrome://")),existing=selectMatchingTab(pages,url2,match);if(existing){if(emulation||appProfile)throw new Error("tab_open cannot apply pre-navigation emulation or appProfile to a reused tab.");active&&await browserClient.sendCommand("Target.activateTarget",{targetId:existing.targetId});let tabId2=await session.ensureTargetRegistered(existing.targetId),pageSession2=await session.getPageSession(tabId2);await ensureControlledIndicator(pageSession2,controlSource);let capture2=currentCapture(pageSession2);return{tabId:tabId2,url:existing.url??url2,title:existing.title??"",opened:!1,reused:!0,capture:capture2}}if(reuse==="require")throw new Error('tab_open did not find a matching existing tab and reuse is "require".')}let targetId=(await browserClient.sendCommand("Target.createTarget",{url:"about:blank",background:!active})).targetId,tabId=await session.registerTarget(targetId),pageSession=await session.getPageSession(tabId);await ensureControlledIndicator(pageSession,controlSource);let capture=currentCapture(pageSession);if(resolvedProfile)await applyResolvedCdpAppProfile(pageSession,resolvedProfile);else if(emulationConfig){for(let{method,params,optional:optional2}of buildEnableEmulationCommands(emulationConfig))await pageSession.client.sendCommand(method,params).catch(error48=>{if(!optional2)throw error48});pageSession.emulation={mobile:emulationConfig.mobile,touch:emulationConfig.touch}}await pageSession.client.sendCommand("Page.navigate",{url:url2}),resolvedProfile?await waitForCdpAppProfileLoad(pageSession):await waitForPageLoad(pageSession,3e4);let targetInfo=await browserClient.sendCommand("Target.getTargetInfo",{targetId}).then(result2=>result2.targetInfo).catch(()=>null);return{tabId,url:targetInfo?.url??url2,title:targetInfo?.title??"",opened:!0,reused:!1,capture,...emulationConfig&&{emulation:{preset:emulationConfig.presetName,viewport:{width:emulationConfig.width,height:emulationConfig.height,deviceScaleFactor:emulationConfig.deviceScaleFactor},userAgent:emulationConfig.userAgent,mobile:emulationConfig.mobile,touch:emulationConfig.touch,orientation:emulationConfig.orientation}},...resolvedProfile&&{appProfile:{profile:resolvedProfile.profile.profile,label:resolvedProfile.profile.label,userAgent:resolvedProfile.profile.ua,os:resolvedProfile.profile.injected.platform==="Android"?"android":"ios",simulateSystemBars:resolvedProfile.profile.injected.simulateSystemBars!==!1}}}}async function cdpTabClose(session,data){let{tabId}=data;if(typeof tabId!="number")throw new Error("Invalid tabId: tabId must be a number");let browserClient=await session.getBrowserClient(),pageSession=await session.getPageSession(tabId);return await browserClient.sendCommand("Target.closeTarget",{targetId:pageSession.targetId}),{success:!0}}async function cdpTabList(session,_data){let pages=((await(await session.getBrowserClient()).sendCommand("Target.getTargets")).targetInfos??[]).filter(t=>t.type==="page"&&!t.url.startsWith("chrome-extension://")&&!t.url.startsWith("about:")&&!t.url.startsWith("chrome://")),tabs=await Promise.all(pages.map(async t=>{let tabId=await session.ensureTargetRegistered(t.targetId);return{id:tabId,tabId,url:t.url,title:t.title??"",active:!1}}));return{tabs,count:tabs.length}}registerActions([{name:"tab_open",session:"browser",handler:cdpTabOpen},{name:"tab_close",session:"browser",handler:cdpTabClose},{name:"tab_list",session:"browser",handler:cdpTabList}]);var GET_DRAG_COORDS_FROM_NODE_SRC=getDragCoordsFromNode.toString();function resolveSnapshotRef(session,ref){let entry=resolvePageRef(session,ref);if(!entry)throw new PageActionPreconditionError(`Ref ${ref} not found. Run page_snapshot first to get fresh refs.`);return entry}async function withSnapshotRef(session,ref,operation){let entry=resolveSnapshotRef(session,ref);try{return await operation(entry)}catch(error48){throw deletePageRef(session,ref),error48}}async function clickBySelectorJs(session,selector){let value=(await session.client.sendCommand("Runtime.evaluate",{expression:`(() => {
|
|
847
|
+
})()`,returnByValue:!0,awaitPromise:!0})).result?.value;if(!userInfo)throw new Error("Failed to parse user info from work.alibaba-inc.com");return{userId,detail:userInfo}}registerActions([{name:"page_screenshot",session:"page",handler:cdpPageScreenshot},{name:"page_selected_element",session:"page",handler:cdpPageSelectedElement},{name:"get_user_info",session:"page",handler:cdpGetUserInfo}]);var TDBANK_LOGIN_URL="https://tdbank.alibaba-inc.com",TdbankLoginRequiredError=class extends Error{},tdbankLoginAttempts=new WeakMap;async function cdpFetchTdbankRequest(session,path23,options={}){let url2=new URL(`https://tdbank.alibaba-inc.com${path23}`);for(let[key,value]of Object.entries(options.params??{}))value!=null&&url2.searchParams.set(key,String(value));let cookies=await getCookiesForUrl(session,url2.toString()),cookieHeader=buildCookieHeaderValue(cookies),headers={Accept:"application/json, text/plain, */*","Accept-Language":"en"};cookieHeader&&(headers.Cookie=cookieHeader);let method="GET",body;if(options.formBody){method="POST";let form=buildMultipartFormBody(options.formBody);headers["Content-Type"]=form.contentType,body=form.body}else options.body&&(method="POST",headers["Content-Type"]="application/json",body=JSON.stringify(options.body));let response=await nodeFetch(url2.toString(),{method,headers,body,timeoutMs:options.timeoutMs});if(response.status===401||response.status===403||response.status>=300&&response.status<400)throw new TdbankLoginRequiredError("未登录 TDBank,请先登录 tdbank.alibaba-inc.com");if(response.status<200||response.status>=300)throw new Error(`TDBank request failed (${response.status} ${response.statusText})`);let text=response.body;if(text.trimStart().startsWith("<"))throw new TdbankLoginRequiredError("未登录 TDBank,请先登录 tdbank.alibaba-inc.com");let payload;try{payload=JSON.parse(text)}catch{throw new Error("TDBank returned a non-JSON response")}if(payload?.success)return payload.data;throw new Error(payload?.message||`TDBank request failed (${payload?.code??"unknown"})`)}async function cdpGetTracknick(session){let cookies=await getCookiesForUrl(session,"https://www.taobao.com/");return decodeTracknick(cookies.get("tracknick")??"")}async function cdpWaitForTracknick(session,options={}){let{previous="",expected="",timeoutMs=1e4}=options,startedAt=Date.now(),latest="";for(;Date.now()-startedAt<timeoutMs;){if(latest=await cdpGetTracknick(session),expected&&latest===expected||!expected&&latest&&latest!==previous)return latest;await new Promise(resolve3=>setTimeout(resolve3,500))}return latest||await cdpGetTracknick(session)}async function cdpOpenAndCloseTarget(cdpSession2,url2){let browser=await cdpSession2.getBrowserClient(),{targetId}=await browser.sendCommand("Target.createTarget",{url:url2,background:!0});await new Promise(resolve3=>setTimeout(resolve3,3500)),await browser.sendCommand("Target.closeTarget",{targetId}).catch(()=>{})}async function refreshTdbankLogin(cdpSession2){let existing=tdbankLoginAttempts.get(cdpSession2);if(existing)return existing;let attempt=cdpOpenAndCloseTarget(cdpSession2,TDBANK_LOGIN_URL).finally(()=>{tdbankLoginAttempts.get(cdpSession2)===attempt&&tdbankLoginAttempts.delete(cdpSession2)});return tdbankLoginAttempts.set(cdpSession2,attempt),attempt}async function cdpFetchTdbank(cdpSession2,session,path23,options={}){try{return await cdpFetchTdbankRequest(session,path23,options)}catch(error48){if(!(error48 instanceof TdbankLoginRequiredError))throw error48}return await refreshTdbankLogin(cdpSession2),cdpFetchTdbankRequest(session,path23,options)}async function cdpFetchTdbankAccounts(cdpSession2,pageSession,pageIndex=1){let data=await cdpFetchTdbank(cdpSession2,pageSession,"/findPagedUsingAccountsByUser.do",{params:{_input_charset:"utf-8",pageIndex,searchKey:"",searchVal:""}});return{...data,accountList:Array.isArray(data?.accountList)?data.accountList:[]}}async function cdpSwitchTdbankAccount(cdpSession2,pageSession,account){let previousNickname=await cdpGetTracknick(pageSession),ssoUrl=await cdpFetchTdbank(cdpSession2,pageSession,"/accountSso.do",{params:{_input_charset:"utf-8"},formBody:{havanaId:String(account.havanaId),site:String(account.site)}});await cdpOpenAndCloseTarget(cdpSession2,String(ssoUrl));let nickname=await cdpWaitForTracknick(pageSession,{previous:account.loginId?previousNickname:"",expected:account.loginId});return{...account.id!==void 0?{accountId:String(account.id)}:{},nickname}}async function cdpCreateTdbankSsoUrl(cdpSession2,pageSession,account){return String(await cdpFetchTdbank(cdpSession2,pageSession,"/accountSso.do",{params:{_input_charset:"utf-8"},formBody:{havanaId:String(account.havanaId),site:String(account.site)}}))}async function cdpResolveTdbankAccount(cdpSession2,pageSession,data){if(data.accountId!==void 0){let account=(await cdpFetchTdbankAccounts(cdpSession2,pageSession,1)).accountList.find(account2=>String(account2.id)===String(data.accountId));if(!account)throw new Error(`TDBank account not found: ${data.accountId}`);if(account.site===void 0||account.site===null)throw new Error(`TDBank account ${data.accountId} has no site`);return account}if(data.havanaId!==void 0&&data.site!==void 0)return{id:data.havanaId,havanaId:data.havanaId,site:data.site};throw new Error("accountId or havanaId + site is required")}async function cdpBorrowAndResolveTdbankAccount(cdpSession2,pageSession,query){let searchResult=await cdpFetchTdbank(cdpSession2,pageSession,"/searchAccountByInputV2.do",{params:{_input_charset:"utf-8",loginId:query,site:0}});if(!Array.isArray(searchResult)||searchResult.length===0)throw new Error(`No TDBank account found for: ${query}`);let account=searchResult[0],{havanaId,accountBucId,site}=account;if(!havanaId||!accountBucId||site===void 0||site===null)throw new Error("TDBank search result is missing havanaId/accountBucId/site");try{await cdpFetchTdbank(cdpSession2,pageSession,"/quickApplyAccountV2.do",{params:{_input_charset:"utf-8",accountBucId,accreditType:7,havanaId,site}})}catch(error48){if(!(error48 instanceof Error?error48.message:String(error48)).includes("已经借用"))throw error48}return account}async function cdpPrepareTdbankSso(cdpSession2,data){let pageSession=await cdpSession2.getPageSession(typeof data?.tabId=="number"?data.tabId:void 0),query=String(data?.query??"").trim(),account=query?await cdpBorrowAndResolveTdbankAccount(cdpSession2,pageSession,query):await cdpResolveTdbankAccount(cdpSession2,pageSession,data),havanaId=account.havanaId??account.id;return{ssoUrl:await cdpCreateTdbankSsoUrl(cdpSession2,pageSession,{havanaId,site:account.site}),account:{accountId:account.id!==void 0?String(account.id):void 0,havanaId:String(havanaId),site:String(account.site),loginId:data.havanaId===void 0&&account.loginId?String(account.loginId):void 0}}}async function cdpConsumeTdbankSso(cdpSession2,ssoUrl,expectedLoginId){let browser=await cdpSession2.getBrowserClient(),{targetId}=await browser.sendCommand("Target.createTarget",{url:ssoUrl,background:!0});try{let tabId=await cdpSession2.registerTarget(targetId),pageSession=await cdpSession2.getPageSession(tabId),nickname=await cdpWaitForTracknick(pageSession,{expected:expectedLoginId,timeoutMs:15e3});if(!nickname)throw new Error("TDBank SSO completed without a tracknick cookie");if(expectedLoginId&&nickname!==expectedLoginId)throw new Error(`TDBank SSO account mismatch: expected ${expectedLoginId}, got ${nickname}`);return{nickname}}finally{await browser.sendCommand("Target.closeTarget",{targetId}).catch(()=>{})}}async function cdpTdbankAccount(cdpSession2,data){let pageSession=await cdpSession2.getPageSession(typeof data?.tabId=="number"?data.tabId:void 0),operation=data?.operation??"list";if(operation==="current"){let nickname=await cdpGetTracknick(pageSession),account=null;if(nickname)try{account=(await cdpFetchTdbankAccounts(cdpSession2,pageSession,1)).accountList.find(account2=>account2.loginId===nickname)??null}catch{account=null}return{nickname,account,source:"cdp"}}if(operation==="list")return{...await cdpFetchTdbankAccounts(cdpSession2,pageSession,data?.pageIndex??1),nickname:await cdpGetTracknick(pageSession),source:"cdp"};if(operation==="switch"){let account=await cdpResolveTdbankAccount(cdpSession2,pageSession,data);return cdpSwitchTdbankAccount(cdpSession2,pageSession,{id:account.id,havanaId:account.havanaId??account.id,site:account.site,loginId:account.loginId})}if(operation==="borrow"){let query=String(data?.query??"").trim();if(!query)throw new Error("query is required for TDBank borrow");let account=await cdpBorrowAndResolveTdbankAccount(cdpSession2,pageSession,query),{havanaId,site}=account,switchResult=await cdpSwitchTdbankAccount(cdpSession2,pageSession,{havanaId,site,loginId:account.loginId});return{account,switchResult}}throw new Error(`Unknown TDBank operation: ${operation}`)}registerActions([{name:"tdbank_account",session:"browser",handler:cdpTdbankAccount}]);function currentCapture(pageSession){return{tabId:pageSession.tabId,cursor:captureCheckpoint(pageSession.buffers.capture),timestampMs:Date.now(),captureStatus:pageSession.buffers.capture.currentSequence===0?"armed":"active"}}async function cdpTabOpen(session,data,controlSource="local"){let{url:url2,active=!1,emulation,reuse="never",match,appProfile}=data;if(!url2||typeof url2!="string")throw new Error("Invalid url: url must be a non-empty string");if(!["never","prefer","require"].includes(reuse))throw new Error('Invalid reuse: expected "never", "prefer", or "require"');if(data.os!==void 0&&data.os!=="ios"&&data.os!=="android")throw new Error('Invalid os: expected "ios" or "android"');if(data.os!==void 0&&!appProfile)throw new Error("tab_open os requires appProfile.");if(data.bridgeConfig!==void 0&&!appProfile)throw new Error("tab_open bridgeConfig requires appProfile.");let resolvedProfile=appProfile?resolveCdpAppProfile(appProfile,{os:data.os,simulateSystemBars:data.simulateSystemBars,bridgeConfig:data.bridgeConfig,emulation}):void 0,emulationConfig=resolvedProfile?.emulation??(emulation?resolveEmulationConfig({...emulation,enabled:!0}):void 0),browserClient=await session.getBrowserClient();if(reuse!=="never"){let pages=((await browserClient.sendCommand("Target.getTargets")).targetInfos??[]).filter(target=>target.type==="page"&&!target.url.startsWith("chrome-extension://")&&!target.url.startsWith("about:")&&!target.url.startsWith("chrome://")),existing=selectMatchingTab(pages,url2,match);if(existing){if(emulation||appProfile)throw new Error("tab_open cannot apply pre-navigation emulation or appProfile to a reused tab.");active&&await browserClient.sendCommand("Target.activateTarget",{targetId:existing.targetId});let tabId2=await session.ensureTargetRegistered(existing.targetId),pageSession2=await session.getPageSession(tabId2);await ensureControlledIndicator(pageSession2,controlSource);let capture2=currentCapture(pageSession2);return{tabId:tabId2,url:existing.url??url2,title:existing.title??"",opened:!1,reused:!0,capture:capture2}}if(reuse==="require")throw new Error('tab_open did not find a matching existing tab and reuse is "require".')}let targetId=(await browserClient.sendCommand("Target.createTarget",{url:"about:blank",background:!active})).targetId,tabId=await session.registerTarget(targetId),pageSession=await session.getPageSession(tabId);await ensureControlledIndicator(pageSession,controlSource);let capture=currentCapture(pageSession);if(resolvedProfile)await applyResolvedCdpAppProfile(pageSession,resolvedProfile);else if(emulationConfig){for(let{method,params,optional:optional2}of buildEnableEmulationCommands(emulationConfig))await pageSession.client.sendCommand(method,params).catch(error48=>{if(!optional2)throw error48});pageSession.emulation={mobile:emulationConfig.mobile,touch:emulationConfig.touch}}await pageSession.client.sendCommand("Page.navigate",{url:url2}),resolvedProfile?await waitForCdpAppProfileLoad(pageSession):await waitForPageLoad(pageSession,3e4);let targetInfo=await browserClient.sendCommand("Target.getTargetInfo",{targetId}).then(result2=>result2.targetInfo).catch(()=>null);return{tabId,url:targetInfo?.url??url2,title:targetInfo?.title??"",opened:!0,reused:!1,capture,...emulationConfig&&{emulation:{preset:emulationConfig.presetName,viewport:{width:emulationConfig.width,height:emulationConfig.height,deviceScaleFactor:emulationConfig.deviceScaleFactor},userAgent:emulationConfig.userAgent,mobile:emulationConfig.mobile,touch:emulationConfig.touch,orientation:emulationConfig.orientation}},...resolvedProfile&&{appProfile:{profile:resolvedProfile.profile.profile,label:resolvedProfile.profile.label,userAgent:resolvedProfile.profile.ua,os:resolvedProfile.profile.injected.platform==="Android"?"android":"ios",simulateSystemBars:resolvedProfile.profile.injected.simulateSystemBars!==!1}}}}async function cdpTabClose(session,data){let{tabId}=data;if(typeof tabId!="number")throw new Error("Invalid tabId: tabId must be a number");let browserClient=await session.getBrowserClient(),pageSession=await session.getPageSession(tabId);return await browserClient.sendCommand("Target.closeTarget",{targetId:pageSession.targetId}),{success:!0}}async function cdpTabList(session,_data){let pages=((await(await session.getBrowserClient()).sendCommand("Target.getTargets")).targetInfos??[]).filter(t=>t.type==="page"&&!t.url.startsWith("chrome-extension://")&&!t.url.startsWith("about:")&&!t.url.startsWith("chrome://")),tabs=await Promise.all(pages.map(async t=>{let tabId=await session.ensureTargetRegistered(t.targetId);return{id:tabId,tabId,url:t.url,title:t.title??"",active:!1}}));return{tabs,count:tabs.length}}registerActions([{name:"tab_open",session:"browser",handler:cdpTabOpen},{name:"tab_close",session:"browser",handler:cdpTabClose},{name:"tab_list",session:"browser",handler:cdpTabList}]);var GET_DRAG_COORDS_FROM_NODE_SRC=getDragCoordsFromNode.toString();function resolveSnapshotRef(session,ref){let entry=resolvePageRef(session,ref);if(!entry)throw new PageActionPreconditionError(`Ref ${ref} not found. Run page_snapshot first to get fresh refs.`);return entry}async function withSnapshotRef(session,ref,operation){let entry=resolveSnapshotRef(session,ref);try{return await operation(entry)}catch(error48){throw deletePageRef(session,ref),error48}}async function clickBySelectorJs(session,selector){let value=(await session.client.sendCommand("Runtime.evaluate",{expression:`(() => {
|
|
845
848
|
const sel = ${JSON.stringify(selector)};
|
|
846
849
|
const el = document.querySelector(sel);
|
|
847
850
|
if (!el) return { clicked: false, error: 'Element not found: ' + sel };
|
|
@@ -908,7 +911,7 @@ ${candidates}`)}let hit=hits[0],dispatchTarget;if(effectiveClickMode==="dom"||po
|
|
|
908
911
|
remaining -= 1;
|
|
909
912
|
}
|
|
910
913
|
return element;
|
|
911
|
-
}`,arguments:[{value:ancestorDepth}],returnByValue:!1});if(ancestorObjectId=ancestor.result?.objectId,!ancestorObjectId||ancestor.result?.subtype==="null")throw new Error("page_snapshot: cannot resolve an ancestor for rootRef");let ancestorBackendNodeId=(await session.client.sendCommand("DOM.describeNode",{objectId:ancestorObjectId})).node?.backendNodeId;if(ancestorBackendNodeId===void 0)throw new Error("page_snapshot: cannot resolve an ancestor for rootRef");return ancestorBackendNodeId}finally{ancestorObjectId&&await session.client.sendCommand("Runtime.releaseObject",{objectId:ancestorObjectId}).catch(()=>{}),await session.client.sendCommand("Runtime.releaseObject",{objectId}).catch(()=>{})}}async function getViewportBackendNodeIds(session){let[metrics,captured]=await Promise.all([session.client.sendCommand("Page.getLayoutMetrics",{}),session.client.sendCommand("DOMSnapshot.captureSnapshot",{computedStyles:[],includeDOMRects:!0,includePaintOrder:!1})]),viewport=resolveDOMSnapshotViewportBounds(metrics);if(!viewport)throw new Error("page_snapshot: viewport metrics are unavailable");let{left,top,width,height}=viewport,right=left+width,bottom=top+height,visible=new Set;for(let document2 of captured.documents??[]){let backendNodeIds=document2.nodes?.backendNodeId??[],nodeIndexes=document2.layout?.nodeIndex??[],bounds=document2.layout?.bounds??[];for(let index=0;index<nodeIndexes.length;index+=1){let box=bounds[index],backendNodeId=backendNodeIds[nodeIndexes[index]];if(!box||backendNodeId===void 0)continue;let[x,y,boxWidth,boxHeight]=box;boxWidth<=0||boxHeight<=0||x<right&&x+boxWidth>left&&y<bottom&&y+boxHeight>top&&visible.add(backendNodeId)}}return visible}async function cdpPageSnapshot(session,data){let mode=data?.mode??"full",rootSelector=data?.rootSelector,rootRef=data?.rootRef,ancestorDepth=data?.ancestorDepth??0,query=resolvePageSnapshotQuery(data?.query);if(!["full","interactive","viewport"].includes(mode))throw new Error("page_snapshot: mode must be one of full, interactive, viewport");if(rootSelector!==void 0&&(typeof rootSelector!="string"||!rootSelector.trim()))throw new Error("page_snapshot: rootSelector must be a non-empty CSS selector");if(rootRef!==void 0&&(typeof rootRef!="string"||!/^@e\d+$/.test(rootRef)))throw new Error('page_snapshot: rootRef must be a snapshot ref like "@e3"');if(rootSelector!==void 0&&rootRef!==void 0)throw new Error("page_snapshot: rootSelector and rootRef are mutually exclusive");if(!Number.isInteger(ancestorDepth)||ancestorDepth<0||ancestorDepth>20)throw new Error("page_snapshot: ancestorDepth must be an integer between 0 and 20");if(ancestorDepth>0&&rootRef===void 0)throw new Error("page_snapshot: ancestorDepth requires rootRef");let rootBackendNodeId;if(rootSelector)rootBackendNodeId=await resolveRootBackendNodeId(session,rootSelector);else if(rootRef){let entry=resolvePageRef(session,rootRef);if(!entry)throw new Error(`Ref ${rootRef} not found. Run page_snapshot first to get fresh refs.`);rootBackendNodeId=await resolveAncestorBackendNodeId(session,entry.backendNodeId,ancestorDepth)}let snapshotRefs=beginPageSnapshotRefs(session),[result,visibleBackendNodeIds]=await Promise.all([session.client.sendCommand(rootBackendNodeId===void 0?"Accessibility.getFullAXTree":"Accessibility.queryAXTree",rootBackendNodeId===void 0?{depth:data?.depth}:{backendNodeId:rootBackendNodeId}),mode==="viewport"||mode==="interactive"?getViewportBackendNodeIds(session):Promise.resolve(void 0)]),nodes=result.nodes??[];await reconcileAXCheckedStates(nodes,backendNodeId=>readDOMCheckedState2(session,backendNodeId));let nodeMap=new Map;for(let node of nodes)nodeMap.set(node.nodeId,node);let rootNode=nodes[0];if(!rootNode)return snapshotRefs.commit(new Set),{snapshot:"(empty page)",refs:{},elementCount:0,outputNodeCount:1,mode,...rootSelector?{rootSelector}:{},...rootRef?{rootRef,ancestorDepth}:{},...query?{query,matches:[],matchCount:0}:{}};let rawTree=buildSnapshotTree(nodeMap,rootNode.nodeId,snapshotRefs),viewportFilteredTree=mode==="interactive"?filterSnapshotTree(rawTree,"viewport",visibleBackendNodeIds):rawTree,effectiveMode=mode;mode==="interactive"&&!hasInteractiveSnapshotNode(viewportFilteredTree)&&(effectiveMode="viewport");let modeFilteredTree=mode==="interactive"?effectiveMode==="interactive"?filterSnapshotTree(viewportFilteredTree,"interactive"):viewportFilteredTree:filterSnapshotTree(rawTree,effectiveMode,visibleBackendNodeIds),queryResult=query?filterSnapshotTreeByQuery(modeFilteredTree,query):{tree:modeFilteredTree,matches:[]},limitedMatches=query?limitPageSnapshotQueryMatches(queryResult.matches):{matches:[],truncated:!1},tree=queryResult.tree,lines=[];tree&&formatSnapshotNode(tree,0,lines);let formatted=formatSnapshotWithLimits(lines.length>0?lines:[query?"(no matches)":"(empty page)"],{maxChars:data?.maxChars,maxNodes:data?.maxNodes}),refs={},outputRefKeys=new Set(Array.from(formatted.snapshot.matchAll(/(?:^|\n)\s*(@e\d+)\s/g),match=>match[1]));for(let match of limitedMatches.matches)match.ref&&outputRefKeys.add(match.ref);snapshotRefs.commit(outputRefKeys);let registry2=getPageRefRegistry(session);for(let ref of outputRefKeys){let entry=registry2.resolve(ref);entry&&(refs[ref.slice(1)]={backendNodeId:entry.backendNodeId})}return{snapshot:formatted.snapshot,refs,elementCount:countSnapshotNodes(tree),outputNodeCount:formatted.outputNodeCount,mode,...rootSelector?{rootSelector}:{},...rootRef?{rootRef,ancestorDepth}:{},...query?{query,matches:limitedMatches.matches,matchCount:queryResult.matches.length,...limitedMatches.truncated?{matchesTruncated:!0}:{}}:{},...effectiveMode!==mode?{fallbackMode:"viewport"}:{},...formatted.truncated?{truncated:!0}:{}}}async function cdpPageFrames(session,_data){let result=await session.client.sendCommand("Page.getFrameTree",{});function flattenFrameTree(tree){if(!tree)return[];let{frame,childFrames=[]}=tree;return[{frameId:frame.id,parentFrameId:frame.parentId??null,url:frame.url,name:frame.name??""},...childFrames.flatMap(flattenFrameTree)]}let frames=flattenFrameTree(result.frameTree);return{frames,count:frames.length}}registerActions([{name:"page_snapshot",session:"page",handler:cdpPageSnapshot},{name:"page_frames",session:"page",handler:cdpPageFrames}]);var MEARL_SERVICE_COOKIE_DOMAINS=["tdbank.alibaba-inc.com","ats2.alibaba-inc.com","g.alibaba-inc.com","login.alibaba-inc.com","token-hub.alibaba-inc.com","alibaba-inc.com"],MEARL_SERVICE_COOKIE_HOSTS=new Set(MEARL_SERVICE_COOKIE_DOMAINS);function normalizeCookieDomain2(input){let value=input.trim();if(!value)throw new Error("Cookie domain must be a non-empty string");let hostname3;try{hostname3=new URL(value.includes("://")?value:`https://${value}`).hostname}catch{throw new Error(`Invalid cookie domain: ${input}`)}if(hostname3=hostname3.toLowerCase().replace(/^\.+/,"").replace(/\.+$/,""),!hostname3)throw new Error(`Invalid cookie domain: ${input}`);return hostname3}function normalizeCookieDomains(inputs){if(!Array.isArray(inputs))throw new Error("copyCookieDomains must be an array of domains");return[...new Set(inputs.map(value=>normalizeCookieDomain2(String(value))))]}function isMearlServiceCookie(cookie){let domain2=normalizeCookieDomain2(cookie.domain);return MEARL_SERVICE_COOKIE_HOSTS.has(domain2)?!0:domain2.endsWith(".tdbank.alibaba-inc.com")||domain2.endsWith(".ats2.alibaba-inc.com")}function resolveCookieCopyPlan(input){return input==="mearl-services"?{domains:[...MEARL_SERVICE_COOKIE_DOMAINS],select:cookies=>cookies.filter(isMearlServiceCookie)}:{domains:input===void 0?[]:normalizeCookieDomains(input),select:cookies=>cookies}}function cookieMatchesDomain(cookieDomain,requestedDomain){let cookieHost=cookieDomain.toLowerCase().replace(/^\.+/,"");return cookieHost===requestedDomain||cookieHost.endsWith(`.${requestedDomain}`)||requestedDomain.endsWith(`.${cookieHost}`)}function toTransferableCookie(cookie){let result={name:String(cookie.name),value:String(cookie.value),domain:String(cookie.domain),path:String(cookie.path||"/"),secure:!!cookie.secure,httpOnly:!!cookie.httpOnly};return["Strict","Lax","None"].includes(cookie.sameSite)&&(result.sameSite=cookie.sameSite),typeof cookie.expires=="number"&&cookie.expires>0&&(result.expires=cookie.expires),["Low","Medium","High"].includes(cookie.priority)&&(result.priority=cookie.priority),typeof cookie.sameParty=="boolean"&&(result.sameParty=cookie.sameParty),["Unset","NonSecure","Secure"].includes(cookie.sourceScheme)&&(result.sourceScheme=cookie.sourceScheme),typeof cookie.sourcePort=="number"&&(result.sourcePort=cookie.sourcePort),cookie.partitionKey?.topLevelSite&&(result.partitionKey={topLevelSite:String(cookie.partitionKey.topLevelSite),...typeof cookie.partitionKey.hasCrossSiteAncestor=="boolean"?{hasCrossSiteAncestor:cookie.partitionKey.hasCrossSiteAncestor}:{}}),result}async function cdpExportCookies(session,domains){let requestedDomains=normalizeCookieDomains(domains);return((await(await session.getBrowserClient()).sendCommand("Storage.getCookies",{})).cookies??[]).filter(cookie=>requestedDomains.some(domain2=>cookieMatchesDomain(String(cookie.domain),domain2))).map(toTransferableCookie)}async function cdpImportCookies(session,cookies){if(cookies.length===0)return 0;let browser=await session.getBrowserClient();return cdpImportCookiesWithClient(browser,cookies)}async function cdpImportCookiesWithClient(browser,cookies){return cookies.length===0?0:(await browser.sendCommand("Storage.setCookies",{cookies}),cookies.length)}import{closeSync,existsSync as existsSync3,mkdtempSync,mkdirSync as mkdirSync2,openSync as openSync2,readFileSync as readFileSync3,renameSync as renameSync3,rmSync as rmSync2,writeFileSync as writeFileSync2}from"node:fs";import{spawn as spawn3,spawnSync as spawnSync2}from"node:child_process";import{randomUUID as randomUUID3}from"node:crypto";import{tmpdir}from"node:os";import{join as join3}from"node:path";var MANAGED_BROWSERS_SUBDIR="managed-browsers",MANAGED_BROWSER_LOCKS_SUBDIR="managed-browser-locks",MANAGED_PROFILES_SUBDIR="managed-profiles",LAUNCH_TIMEOUT_MS=15e3;function validateName(value){let name=typeof value=="string"?value.trim():"";if(!name)throw new Error("name is required");if(name.length>64)throw new Error("name must be at most 64 characters");if(/[/\\\0\r\n]/.test(name))throw new Error("name contains unsupported characters");return name}function managedBrowserId(name){return`managed:${name.toLocaleLowerCase("en-US")}`}function hasTdbankSelector(data){return data.accountId!==void 0||data.havanaId!==void 0||typeof data.query=="string"&&data.query.trim().length>0}function validateTdbankSelector(data){if(data.havanaId!==void 0&&data.site===void 0)throw new Error("site is required when havanaId is provided");if([data.accountId!==void 0,data.havanaId!==void 0,typeof data.query=="string"&&data.query.trim().length>0].filter(Boolean).length>1)throw new Error("Use only one of accountId, havanaId + site, or query")}function chromeExecutableCandidates(platform=process.platform){let envPath=process.env.MEARL_CHROME_PATH,candidates=envPath?[envPath]:[];if(platform==="darwin")return candidates.concat(["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary","/Applications/Chromium.app/Contents/MacOS/Chromium"]);if(platform==="win32"){let local=process.env.LOCALAPPDATA??"",programFiles=process.env.PROGRAMFILES??"",programFilesX86=process.env["PROGRAMFILES(X86)"]??"";return candidates.concat([join3(local,"Google","Chrome","Application","chrome.exe"),join3(programFiles,"Google","Chrome","Application","chrome.exe"),join3(programFilesX86,"Google","Chrome","Application","chrome.exe")])}return candidates.concat(["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser"])}function resolveChromeExecutable(explicitPath){if(explicitPath){if(!existsSync3(explicitPath))throw new Error(`Chrome executable not found: ${explicitPath}`);return explicitPath}let found=chromeExecutableCandidates().find(candidate=>candidate&&existsSync3(candidate));if(!found)throw new Error("Chrome executable not found. Set executablePath or MEARL_CHROME_PATH.");return found}function desktopChromeUserAgent(version2,platform=process.platform){if(!/^\d+(?:\.\d+){1,3}$/.test(version2))throw new Error(`Invalid Chrome version: ${version2}`);return`Mozilla/5.0 (${platform==="darwin"?"Macintosh; Intel Mac OS X 10_15_7":platform==="win32"?"Windows NT 10.0; Win64; x64":"X11; Linux x86_64"}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${version2} Safari/537.36`}function resolveChromeVersion(executablePath){let result=spawnSync2(executablePath,["--version"],{encoding:"utf8",windowsHide:!0}),version2=`${result.stdout??""} ${result.stderr??""}`.match(/\b(\d+(?:\.\d+){1,3})\b/)?.[1];if(!version2)throw new Error(`Could not determine Chrome version from: ${executablePath}`);return version2}function resolveUserAgentMode(value){if(value===void 0||value==="default")return"default";if(value==="desktop")return"desktop";throw new Error('userAgentMode must be "default" or "desktop"')}function buildManagedChromeArgs(options){return[`--user-data-dir=${options.userDataDir}`,"--remote-debugging-port=0","--no-first-run","--no-default-browser-check","--disable-background-networking",...options.headless?["--headless=new"]:[],...options.userAgent?[`--user-agent=${options.userAgent}`]:[],"about:blank"]}function browserSummary(record2,running){return{browserId:record2.browserId,name:record2.name,provider:"local",headless:record2.headless,persistent:record2.persistent,cdpPort:record2.cdpPort,createdAt:record2.createdAt,account:record2.account,copiedCookies:record2.copiedCookies,running}}function isManagedProcess(pid,commandMarker,platform=process.platform){if(!isAlive(pid))return!1;try{if(platform==="win32"){let escapedMarker=commandMarker.replace(/'/g,"''");return spawnSync2("powershell.exe",["-NoProfile","-NonInteractive","-Command",`$p = Get-CimInstance Win32_Process -Filter 'ProcessId = ${pid}'; if ($p.CommandLine -and $p.CommandLine.Contains('${escapedMarker}')) { exit 0 } else { exit 1 }`],{windowsHide:!0,stdio:"ignore"}).status===0}let result=spawnSync2("ps",["-p",String(pid),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return result.status===0&&result.stdout.includes(commandMarker)}catch{return!1}}function listRecords(){let records=[];for(let file2 of listRecordFiles(keyedDir(MANAGED_BROWSERS_SUBDIR))){let record2=readRecord(file2);if(!record2){removeRecord(file2);continue}let running=isManagedProcess(record2.pid,record2.userDataDir);if(!running&&(signalProcess(record2.hostPid,"SIGTERM",`--browser-id ${record2.browserId}`),removeRecord(keyedConfigFile("browsers",record2.browserId)),!record2.persistent)){removeRecord(file2),rmSync2(record2.userDataDir,{recursive:!0,force:!0});continue}records.push({record:record2,running})}return records}function listManagedBrowsers(){return listRecords().map(({record:record2,running})=>browserSummary(record2,running))}function findManagedRecord(selector){let normalized=selector.trim().toLowerCase();return listRecords().find(({record:record2})=>record2.browserId.toLowerCase()===normalized||record2.name.toLowerCase()===normalized)?.record??null}function hasManagedBrowser(selector){return findManagedRecord(selector)!==null}async function waitForActivePort(userDataDir){let deadline=Date.now()+LAUNCH_TIMEOUT_MS;for(;Date.now()<deadline;){let info=readDevToolsActivePort(userDataDir);if(info)return info.port;await new Promise(resolve3=>setTimeout(resolve3,100))}throw new Error(`Chrome did not expose a CDP port within ${LAUNCH_TIMEOUT_MS}ms`)}async function waitForBrowserRegistration(browserId,expectedPid){let file2=keyedConfigFile("browsers",browserId),deadline=Date.now()+LAUNCH_TIMEOUT_MS;for(;Date.now()<deadline;){if(readRecord(file2)?.pid===expectedPid&&isAlive(expectedPid))return;await new Promise(resolve3=>setTimeout(resolve3,100))}throw new Error(`Managed browser ${browserId} did not register within ${LAUNCH_TIMEOUT_MS}ms`)}function signalProcess(pid,signal,commandMarker){if(isManagedProcess(pid,commandMarker)){if(process.platform==="win32"){spawnSync2("taskkill",["/PID",String(pid),"/T","/F"],{windowsHide:!0,stdio:"ignore"});return}try{process.kill(pid,signal)}catch{}}}async function stopProcess(pid,commandMarker){signalProcess(pid,"SIGTERM",commandMarker);let deadline=Date.now()+3e3;for(;Date.now()<deadline&&isManagedProcess(pid,commandMarker);)await new Promise(resolve3=>setTimeout(resolve3,50));isManagedProcess(pid,commandMarker)&&signalProcess(pid,"SIGKILL",commandMarker)}function profileDirectory(browserId,persistent){if(!persistent)return mkdtempSync(join3(tmpdir(),"mearl-browser-"));let dir=join3(DAEMON_HOME,MANAGED_PROFILES_SUBDIR,hashKey(browserId));return mkdirSync2(dir,{recursive:!0}),dir}async function removeStoppedInstance(browserId){let file2=keyedConfigFile(MANAGED_BROWSERS_SUBDIR,browserId),record2=readRecord(file2);!record2||isManagedProcess(record2.pid,record2.userDataDir)||(await stopProcess(record2.hostPid,`--browser-id ${record2.browserId}`),removeRecord(file2),removeRecord(keyedConfigFile("browsers",record2.browserId)),record2.persistent||rmSync2(record2.userDataDir,{recursive:!0,force:!0}))}function acquireLaunchLock(browserId){let lockDir=keyedDir(MANAGED_BROWSER_LOCKS_SUBDIR),lockFile=keyedConfigFile(MANAGED_BROWSER_LOCKS_SUBDIR,browserId);mkdirSync2(lockDir,{recursive:!0});let token=`${process.pid}:${randomUUID3()}`,tryAcquire=()=>{try{return writeFileSync2(lockFile,token,{flag:"wx"}),!0}catch(error48){if(error48.code!=="EEXIST")throw error48;return!1}};if(!tryAcquire()){let observedToken="";try{observedToken=readFileSync3(lockFile,"utf-8")}catch{}let ownerPid=Number(observedToken.split(":",1)[0]);if(Number.isInteger(ownerPid)&&!isAlive(ownerPid)){let staleFile=`${lockFile}.${process.pid}.${randomUUID3()}.stale`;try{if(readFileSync3(lockFile,"utf-8")!==observedToken)throw new Error("Launch lock owner changed");if(renameSync3(lockFile,staleFile),readFileSync3(staleFile,"utf-8")===observedToken)rmSync2(staleFile,{force:!0});else try{renameSync3(staleFile,lockFile)}catch{}}catch{}}if(!tryAcquire())throw new Error(`Managed browser launch already in progress: ${browserId}`)}return()=>{try{readFileSync3(lockFile,"utf-8")===token&&rmSync2(lockFile,{force:!0})}catch{}}}async function launchManagedBrowser(input,deps){if(input.reuse!==void 0&&input.reuse!=="never"&&input.reuse!=="prefer"&&input.reuse!=="require")throw new Error('reuse must be "never", "prefer", or "require"');if(input.reuse==="prefer"||input.reuse==="require")throw new Error("reuse is currently supported only by the AgentBay browser provider");if(input.imageId!==void 0)throw new Error("imageId is only supported by the AgentBay browser provider");let name=validateName(input.name),browserId=managedBrowserId(name);validateTdbankSelector(input);let cookieCopy=resolveCookieCopyPlan(input.copyCookieDomains),copyCookieDomains=cookieCopy.domains,headless=input.headless!==!1,persistent=input.persistent===!0,executablePath=resolveChromeExecutable(input.executablePath),userAgent=resolveUserAgentMode(input.userAgentMode)==="desktop"?desktopChromeUserAgent(resolveChromeVersion(executablePath)):void 0,userDataDir=profileDirectory(browserId,persistent),logDir=keyedDir(MANAGED_BROWSERS_SUBDIR);mkdirSync2(logDir,{recursive:!0});let logPath=join3(logDir,`${hashKey(browserId)}.log`),logFd=openSync2(logPath,"a"),chromePid=0,hostPid=0,session=null,recordWritten=!1,releaseLock=null;try{if(releaseLock=acquireLaunchLock(browserId),await removeStoppedInstance(browserId),findManagedRecord(browserId))throw new Error(`Managed browser already running: ${browserId}`);let[ticket,exportedCookies]=await Promise.all([hasTdbankSelector(input)?deps.prepareTdbankSso(input):Promise.resolve(void 0),copyCookieDomains.length>0?deps.exportCookies(copyCookieDomains):Promise.resolve([])]),cookies=cookieCopy.select(exportedCookies),chromeArgs=buildManagedChromeArgs({userDataDir,headless,userAgent});rmSync2(join3(userDataDir,"DevToolsActivePort"),{force:!0});let chrome=spawn3(executablePath,chromeArgs,{detached:!0,stdio:["ignore","ignore",logFd],windowsHide:headless});if(await new Promise((resolve3,reject)=>{chrome.once("error",reject),chrome.once("spawn",resolve3)}),chromePid=chrome.pid??0,!chromePid)throw new Error("Chrome launched without a process id");chrome.unref();let cdpPort=await waitForActivePort(userDataDir);session=new CdpSession({port:cdpPort,userDataDir});let copiedCookieCount=await cdpImportCookies(session,cookies),account;if(ticket){let login=await cdpConsumeTdbankSso(session,ticket.ssoUrl,ticket.account.loginId);account={accountId:ticket.account.accountId,loginId:ticket.account.loginId,nickname:login.nickname}}input.url&&await(await session.getBrowserClient()).sendCommand("Target.createTarget",{url:input.url,background:headless}),session.close(),session=null;let host=spawn3(process.execPath,[deps.nativeHostScript,"--daemon","--cdp-port",String(cdpPort),"--cdp-user-data-dir",userDataDir,"--browser-id",browserId,"--browser-name",name],{detached:!0,stdio:"ignore",windowsHide:!0});if(await new Promise((resolve3,reject)=>{host.once("error",reject),host.once("spawn",resolve3)}),hostPid=host.pid??0,!hostPid)throw new Error("Native host launched without a process id");host.unref();let record2={pid:chromePid,hostPid,browserId,name,headless,persistent,userDataDir,executablePath,cdpPort,createdAt:new Date().toISOString(),account,...copyCookieDomains.length>0?{copiedCookies:{domains:copyCookieDomains,count:copiedCookieCount}}:{}};return writeRecord(keyedConfigFile(MANAGED_BROWSERS_SUBDIR,browserId),record2),recordWritten=!0,await waitForBrowserRegistration(browserId,hostPid),deps.log(`managed browser launched: ${browserId}, chrome=${chromePid}, host=${hostPid}`),{...browserSummary(record2,!0),created:!0,reused:!1}}catch(error48){throw session?.close(),hostPid&&await stopProcess(hostPid,`--browser-id ${browserId}`),chromePid&&await stopProcess(chromePid,userDataDir),recordWritten&&removeRecord(keyedConfigFile(MANAGED_BROWSERS_SUBDIR,browserId)),persistent||rmSync2(userDataDir,{recursive:!0,force:!0}),error48}finally{releaseLock?.(),closeSync(logFd)}}async function closeManagedBrowser(selector,options={}){let record2=findManagedRecord(selector);if(!record2)throw new Error(`Managed browser not found: ${selector}`);await stopProcess(record2.pid,record2.userDataDir);let closingOwnHost=record2.hostPid===process.pid;closingOwnHost||await stopProcess(record2.hostPid,`--browser-id ${record2.browserId}`),removeRecord(keyedConfigFile(MANAGED_BROWSERS_SUBDIR,record2.browserId)),removeRecord(keyedConfigFile("browsers",record2.browserId));let deleteProfile=options.deleteProfile===!0||!record2.persistent;return deleteProfile&&rmSync2(record2.userDataDir,{recursive:!0,force:!0}),closingOwnHost&&setTimeout(()=>process.kill(process.pid,"SIGTERM"),250).unref(),{browserId:record2.browserId,closed:!0,profileDeleted:deleteProfile}}import{existsSync as existsSync9,readFileSync as readFileSync7}from"node:fs";import{spawn as spawn5}from"node:child_process";import{homedir as homedir2}from"node:os";import{dirname as dirname6,join as join6,parse,resolve as resolve2}from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";function positiveIntegerMinutes(value,name,fallback){if(value===void 0||!value.trim())return fallback;let minutes=Number(value);if(!Number.isInteger(minutes)||minutes<=0)throw new Error(`${name} must be a positive integer in minutes`);return minutes}function resolveAgentBayLifecycleConfig(env=process.env){let idleReleaseTimeout=positiveIntegerMinutes(env.MEARL_AGENTBAY_IDLE_RELEASE_MINUTES,"MEARL_AGENTBAY_IDLE_RELEASE_MINUTES",30),maxRuntime=positiveIntegerMinutes(env.MEARL_AGENTBAY_MAX_RUNTIME_MINUTES,"MEARL_AGENTBAY_MAX_RUNTIME_MINUTES",120);if(idleReleaseTimeout<3)throw new Error("MEARL_AGENTBAY_IDLE_RELEASE_MINUTES must be at least 3");if(maxRuntime<idleReleaseTimeout)throw new Error("MEARL_AGENTBAY_MAX_RUNTIME_MINUTES must be greater than or equal to MEARL_AGENTBAY_IDLE_RELEASE_MINUTES");return{idleReleaseTimeout,maxRuntime}}var AgentBaySessionWatchdog=class{idleTimeoutMs;checkIntervalMs;now;keepAlive;close;log;activeRequests=0;lastActivityAt;timer=null;checking=!1;closing=!1;stopped=!1;constructor(options){if(!Number.isFinite(options.idleTimeoutMs)||options.idleTimeoutMs<=0)throw new Error("AgentBay idle timeout must be positive");if(this.idleTimeoutMs=options.idleTimeoutMs,this.checkIntervalMs=options.checkIntervalMs??6e4,!Number.isFinite(this.checkIntervalMs)||this.checkIntervalMs<=0)throw new Error("AgentBay lifecycle check interval must be positive");this.now=options.now??Date.now,this.keepAlive=options.keepAlive,this.close=options.close,this.log=options.log,this.lastActivityAt=this.now()}start(){this.timer||this.stopped||(this.timer=setInterval(()=>void this.checkNow(),this.checkIntervalMs),this.timer.unref())}stop(){this.stopped=!0,this.timer&&(clearInterval(this.timer),this.timer=null)}beginActivity(){return this.stopped||this.closing?!1:(this.activeRequests+=1,this.lastActivityAt=this.now(),!0)}endActivity(){this.activeRequests>0&&(this.activeRequests-=1),this.lastActivityAt=this.now()}async checkNow(){if(!(this.stopped||this.checking||this.closing)){this.checking=!0;try{let idleForMs=this.now()-this.lastActivityAt;if(this.activeRequests>0||idleForMs<this.idleTimeoutMs){try{await this.keepAlive()}catch(error48){this.log("AgentBay keepalive failed:",error48 instanceof Error?error48.message:String(error48))}return}this.closing=!0,this.log(`AgentBay browser reached the idle timeout after ${idleForMs}ms; closing`);try{await this.close()}catch(error48){this.closing=!1,this.log("AgentBay idle close failed:",error48 instanceof Error?error48.message:String(error48))}}finally{this.checking=!1}}}};var AGENTBAY_BROWSERS_SUBDIR="agentbay-browsers",DEFAULT_AGENTBAY_IMAGE_ID="imgc-0aae4rgl8kvagdv1j",sdkPromise=null;async function loadSdk(){return sdkPromise??=Promise.resolve().then(()=>(init_agentbay_sdk(),agentbay_sdk_exports)),sdkPromise}async function createClient(apiKey){let{AgentBay:AgentBay2}=await loadSdk();return new AgentBay2({apiKey})}function agentBayBrowserId(name){return`managed:agentbay:${name.toLocaleLowerCase("en-US")}`}function envValue(text,key){for(let line of text.split(/\r?\n/)){let match=/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)\s*$/.exec(line);if(!match||match[1]!==key)continue;let value=(match[2]??"").trim();return value.length>=2&&(value.startsWith('"')&&value.endsWith('"')||value.startsWith("'")&&value.endsWith("'"))?value=value.slice(1,-1):value=value.replace(/\s+#.*$/,"").trim(),value||void 0}}function envFilesUpward(start){let files=[],current=resolve2(start);for(;;){files.push(join6(current,".env"));let parent=dirname6(current);if(parent===current||current===parse(current).root)break;current=parent}return files}function resolveAgentBayApiKey(){let inherited=process.env.AGENTBAY_KEY?.trim()||process.env.AGENTBAY_API_KEY?.trim();if(inherited)return inherited;let moduleDir=dirname6(fileURLToPath2(import.meta.url)),candidates=[...process.env.MEARL_ENV_FILE?[resolve2(process.env.MEARL_ENV_FILE)]:[],...envFilesUpward(process.cwd()),...envFilesUpward(moduleDir),join6(homedir2(),".mearl",".env")];for(let file2 of new Set(candidates))if(existsSync9(file2))try{let text=readFileSync7(file2,"utf8"),value=envValue(text,"AGENTBAY_KEY")??envValue(text,"AGENTBAY_API_KEY");if(value)return value}catch{}throw new Error("AgentBay API key not found. Set AGENTBAY_KEY in the environment, project .env, or ~/.mearl/.env.")}function validateAgentBayInput(input){if(input.headless===!0)throw new Error("headless=true is not supported by the AgentBay browser provider");if(input.executablePath)throw new Error("executablePath is only supported by the local browser provider");if(input.accountId!==void 0||input.havanaId!==void 0||input.site!==void 0||typeof input.query=="string"&&input.query.trim())throw new Error("TDBank login parameters are only supported by the local browser provider")}function resolveReuseMode(value){if(value===void 0)return"never";if(value==="never"||value==="prefer"||value==="require")return value;throw new Error('reuse must be "never", "prefer", or "require"')}function validateReusableAgentBayConfiguration(input,record2){if(input.imageId!==void 0&&resolveAgentBayImageId(input.imageId)!==record2.imageId)throw new Error(`Cannot change imageId while reusing AgentBay browser: ${record2.browserId}`);if(input.persistent!==void 0&&input.persistent!==(record2.persistent===!0))throw new Error(`Cannot change persistent while reusing AgentBay browser: ${record2.browserId}`);if(input.userAgentMode!==void 0&&record2.userAgentMode!==void 0&&input.userAgentMode!==record2.userAgentMode)throw new Error(`Cannot change userAgentMode while reusing AgentBay browser: ${record2.browserId}`)}function resolveAgentBayImageId(value){if(value===void 0)return DEFAULT_AGENTBAY_IMAGE_ID;let imageId=typeof value=="string"?value.trim():"";if(!imageId||imageId.length>128||!/^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(imageId))throw new Error("imageId must be a valid AgentBay image alias or image ID");return imageId}function agentBayContextName(browserId){return`mearl-browser-${hashKey(browserId)}`}function normalizeDesktopUserAgent(value){let userAgent=typeof value=="string"?value.trim():"";if(!userAgent)throw new Error("Could not determine the control browser user agent");return userAgent.replace(/\bHeadlessChrome\//g,"Chrome/")}function normalizeAgentBayAccessUrl(value){let candidate=typeof value=="string"?value.trim():"";if(candidate)try{let url2=new URL(candidate);return url2.protocol==="https:"||url2.protocol==="http:"?url2.toString():void 0}catch{return}}function browserSummary2(record2,running){return{browserId:record2.browserId,name:record2.name,provider:"agentbay",headless:!1,persistent:record2.persistent===!0,agentbaySessionId:record2.sessionId,...record2.imageId?{agentbayImageId:record2.imageId}:{},...record2.contextId?{agentbayContextId:record2.contextId}:{},...record2.contextName?{agentbayContextName:record2.contextName}:{},createdAt:record2.createdAt,...record2.copiedCookies?{copiedCookies:record2.copiedCookies}:{},running}}function listRecords2(){let records=[];for(let file2 of listRecordFiles(keyedDir(AGENTBAY_BROWSERS_SUBDIR))){let stored=readRecord(file2);if(!stored){removeRecord(file2);continue}let{accessUrl:legacyAccessUrl,...record2}=stored;legacyAccessUrl!==void 0&&writeRecord(file2,record2);let running=isManagedProcess(record2.pid,`--browser-id ${record2.browserId}`);running||removeRecord(keyedConfigFile("browsers",record2.browserId)),records.push({record:record2,running})}return records}function findRecordWithStatus(selector){let normalized=selector.trim().toLowerCase();return listRecords2().find(({record:record2})=>record2.browserId.toLowerCase()===normalized||record2.name.toLowerCase()===normalized)??null}function findRecord(selector){return findRecordWithStatus(selector)?.record??null}function hasAgentBayBrowser(selector){return findRecord(selector)!==null}function listAgentBayBrowsers(){return listRecords2().map(({record:record2,running})=>browserSummary2(record2,running))}async function requireSession(sessionId,apiKey){let agentBay=await createClient(apiKey);return requireSessionFromClient(agentBay,sessionId)}async function requireSessionFromClient(agentBay,sessionId){let result=await agentBay.get(sessionId);if(!result.success||!result.session)throw new Error(result.errorMessage||`AgentBay session not found: ${sessionId}`);return result.session}async function getAgentBaySession(sessionId,dependencies={}){let apiKey=(dependencies.resolveApiKey??resolveAgentBayApiKey)(),agentBay=dependencies.createAgentBayClient?await dependencies.createAgentBayClient(apiKey):await createClient(apiKey);return requireSessionFromClient(agentBay,sessionId)}async function getAgentBayAccessUrl(sessionId,dependencies={}){let apiKey=(dependencies.resolveApiKey??resolveAgentBayApiKey)(),agentBay=dependencies.createAgentBayClient?await dependencies.createAgentBayClient(apiKey):await createClient(apiKey),session=await requireSessionFromClient(agentBay,sessionId);if(!session.info)throw new Error("The installed AgentBay SDK does not support live session information");let result=await session.info();if(result.success===!1)throw new Error(result.errorMessage||`AgentBay session info failed: ${sessionId}`);let data=result.data&&typeof result.data=="object"?result.data:null,accessUrl=normalizeAgentBayAccessUrl(data&&"resourceUrl"in data?data.resourceUrl:void 0);if(!accessUrl)throw new Error(`AgentBay session did not return a browser access URL: ${sessionId}`);return accessUrl}async function resolvePersistentContext(agentBay,browserId){if(!agentBay.context)throw new Error("The installed AgentBay SDK does not support persistent browser contexts");let name=agentBayContextName(browserId),result=await agentBay.context.get(name,!0);if(!result.success||!result.context?.id)throw new Error(result.errorMessage||`Failed to create AgentBay browser context: ${name}`);return{id:result.context.id,name:result.context.name||name}}async function resolveAgentBayEndpoint(sessionId){let apiKey=resolveAgentBayApiKey(),{AgentBay:AgentBay2,GetCdpLinkRequest:GetCdpLinkRequest2}=await loadSdk(),response=await new AgentBay2({apiKey}).client.getCdpLink(new GetCdpLinkRequest2({authorization:`Bearer ${apiKey}`,sessionId})),endpoint=response.body?.success?response.body.data?.url:void 0;if(!endpoint)throw new Error(response.body?.message||`Failed to get AgentBay CDP link: ${sessionId}`);let url2=new URL(endpoint);if(url2.protocol!=="ws:"&&url2.protocol!=="wss:")throw new Error(`AgentBay returned an unsupported CDP endpoint: ${url2.protocol}`);return url2.toString()}async function keepAgentBaySessionAlive(sessionId){let result=await(await requireSession(sessionId,resolveAgentBayApiKey())).keepAlive();if(result.success===!1)throw new Error(result.errorMessage||"AgentBay keepalive failed")}async function configureAgentBayBrowserSession(session,input,cookies,connectCdp=url2=>CdpClient.connect(url2)){let endpoint=await session.browser.getEndpointUrl(),cdp=await connectCdp(endpoint);try{await cdp.sendCommand("Browser.getVersion",{},1e4);let copiedCookieCount=await cdpImportCookiesWithClient(cdp,cookies);return input.url&&await cdp.sendCommand("Target.createTarget",{url:input.url,background:!1}),copiedCookieCount}finally{cdp.close()}}async function initializeAgentBayBrowserSession(session,input,cookies,options={}){if(!await session.browser.initializeAsync(options.userAgent?{userAgent:options.userAgent}:{}))throw new Error("AgentBay browser initialization failed");return configureAgentBayBrowserSession(session,input,cookies,options.connectCdp)}async function reuseAgentBayBrowserSession(session,input,cookies,options={}){return configureAgentBayBrowserSession(session,input,cookies,options.connectCdp)}async function launchAgentBayBrowser(input,deps){let name=validateName(input.name),browserId=agentBayBrowserId(name);validateAgentBayInput(input);let reuseMode=resolveReuseMode(input.reuse),imageId=resolveAgentBayImageId(input.imageId),persistent=input.persistent===!0,userAgentMode=resolveUserAgentMode(input.userAgentMode),cookieCopy=resolveCookieCopyPlan(input.copyCookieDomains),copyCookieDomains=cookieCopy.domains,apiKey=(deps.resolveApiKey??resolveAgentBayApiKey)(),lifecycle=resolveAgentBayLifecycleConfig(),releaseLock=acquireLaunchLock(browserId),persistBrowserRecord=deps.persistBrowserRecord??(record2=>writeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR,record2.browserId),record2)),findBrowserRecord=deps.findBrowserRecord??findRecordWithStatus,session=null,context,hostPid=0,recordWritten=!1;try{let existing=findBrowserRecord(browserId);if(existing){if(reuseMode==="never")throw new Error(`AgentBay browser already exists: ${browserId}`);if(!existing.running)throw new Error(`AgentBay browser is not running and cannot be reused: ${browserId}`);validateReusableAgentBayConfiguration(input,existing.record);let exportedCookies2=copyCookieDomains.length>0?await deps.exportCookies(copyCookieDomains):[],cookies2=cookieCopy.select(exportedCookies2),agentBay2=await(deps.createAgentBayClient??createClient)(apiKey),existingSession=await requireSessionFromClient(agentBay2,existing.record.sessionId),copiedCookieCount2=await reuseAgentBayBrowserSession(existingSession,input,cookies2,{connectCdp:deps.connectCdp}),record3={...existing.record,...copyCookieDomains.length>0?{copiedCookies:{domains:copyCookieDomains,count:copiedCookieCount2}}:{}};return copyCookieDomains.length>0&&persistBrowserRecord(record3),deps.log(`AgentBay browser reused: ${browserId}, host=${record3.pid}`),{...browserSummary2(record3,!0),created:!1,reused:!0}}if(reuseMode==="require")throw new Error(`AgentBay browser is not running and reuse=require: ${browserId}`);let[exportedCookies,userAgent]=await Promise.all([copyCookieDomains.length>0?deps.exportCookies(copyCookieDomains):Promise.resolve([]),userAgentMode==="desktop"?deps.getBrowserUserAgent().then(normalizeDesktopUserAgent):Promise.resolve(void 0)]),cookies=cookieCopy.select(exportedCookies),agentBay=await(deps.createAgentBayClient??createClient)(apiKey);context=persistent?await resolvePersistentContext(agentBay,browserId):void 0;let{LifecyclePolicy:LifecyclePolicy2}=await loadSdk(),created=await agentBay.create({imageId,framework:"mearl",lifecyclePolicy:new LifecyclePolicy2(lifecycle),...context?{browserContext:{contextId:context.id,autoUpload:!0,syncMode:"standard"}}:{}});if(!created.success||!created.session)throw new Error(created.errorMessage||"AgentBay session creation failed");session=created.session;let copiedCookieCount=await initializeAgentBayBrowserSession(session,input,cookies,{userAgent,connectCdp:deps.connectCdp}),host=spawn5(process.execPath,[deps.nativeHostScript,"--daemon","--agentbay-session-id",session.sessionId,"--browser-id",browserId,"--browser-name",name,"--agentbay-idle-release-minutes",String(lifecycle.idleReleaseTimeout)],{detached:!0,stdio:"ignore",windowsHide:!0});if(await new Promise((resolveSpawn,rejectSpawn)=>{host.once("error",rejectSpawn),host.once("spawn",resolveSpawn)}),hostPid=host.pid??0,!hostPid)throw new Error("AgentBay native host launched without a process id");host.unref();let record2={pid:hostPid,browserId,name,sessionId:session.sessionId,imageId,userAgentMode,persistent,...context?{contextId:context.id,contextName:context.name}:{},createdAt:new Date().toISOString(),...copyCookieDomains.length>0?{copiedCookies:{domains:copyCookieDomains,count:copiedCookieCount}}:{}};return persistBrowserRecord(record2),recordWritten=!0,await waitForBrowserRegistration(browserId,hostPid),deps.log(`AgentBay browser launched: ${browserId}, host=${hostPid}`),{...browserSummary2(record2,!0),created:!0,reused:!1}}catch(error48){if(hostPid&&await stopProcess(hostPid,`--browser-id ${browserId}`),recordWritten&&(removeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR,browserId)),removeRecord(keyedConfigFile("browsers",browserId))),session){let cleanupError;try{let deleted=await session.delete(!1);deleted.success||(cleanupError=new Error(deleted.errorMessage||"AgentBay session deletion failed"))}catch(deleteError){cleanupError=deleteError}if(cleanupError){let recoveryRecord={pid:hostPid,browserId,name,sessionId:session.sessionId,imageId,userAgentMode,persistent,...context?{contextId:context.id,contextName:context.name}:{},createdAt:new Date().toISOString()},recoverySaved=!1,recoveryError;try{persistBrowserRecord(recoveryRecord),recoverySaved=!0}catch(writeError){recoveryError=writeError}throw deps.log(`AgentBay launch cleanup failed for ${session.sessionId}:`,cleanupError instanceof Error?cleanupError.message:String(cleanupError)),recoveryError&&deps.log(`AgentBay recovery metadata could not be saved for ${session.sessionId}:`,recoveryError instanceof Error?recoveryError.message:String(recoveryError)),new AggregateError(recoveryError?[error48,cleanupError,recoveryError]:[error48,cleanupError],`${error48 instanceof Error?error48.message:String(error48)}; `+(recoverySaved?"AgentBay session cleanup failed and recovery metadata was retained for browser_close":`AgentBay session cleanup failed; session ${session.sessionId} may require manual deletion`),{cause:error48})}}throw error48}finally{releaseLock()}}function isMissingSessionError(error48){let message=error48 instanceof Error?error48.message:String(error48);return/not[ -]?found|does not exist|already deleted|invalid session/i.test(message)}async function releaseAgentBayBrowserResources(record2,agentBay,options={}){let deleteContext=record2.persistent===!0&&options.deleteProfile===!0,syncContext=record2.persistent===!0&&!deleteContext,contextSynced=!!record2.contextSyncedAt,session;try{session=await requireSessionFromClient(agentBay,record2.sessionId)}catch(error48){if(!isMissingSessionError(error48))throw error48}if(session){if(syncContext&&!contextSynced){if(!session.callMcpTool)throw new Error("The installed AgentBay SDK cannot stop the browser before context sync");let stopped=await session.callMcpTool("stopChrome",{},!1);if(stopped.success===!1)throw new Error(stopped.errorMessage||"AgentBay browser shutdown failed");if(!session.context)throw new Error("The installed AgentBay SDK cannot synchronize browser context state");let synced=await session.context.sync();if(!synced.success)throw new Error(synced.errorMessage||"AgentBay browser context sync failed");contextSynced=!0,record2.contextSyncedAt=new Date().toISOString(),options.persistRecord?.(record2)}try{let result=await session.delete(!1);if(!result.success)throw new Error(result.errorMessage||"AgentBay session deletion failed")}catch(error48){if(!isMissingSessionError(error48))throw error48}}if(deleteContext){if(!record2.contextId||!record2.contextName||!agentBay.context)throw new Error("AgentBay browser context metadata is unavailable for profile deletion");let result=await agentBay.context.delete({id:record2.contextId,name:record2.contextName});if(!result.success)throw new Error(result.errorMessage||"AgentBay context deletion failed")}return{sessionDeleted:!0,...syncContext?{contextSynced}:{},...deleteContext?{contextDeleted:!0}:{}}}async function closeAgentBayBrowser(selector,options={}){let record2=findRecord(selector);if(!record2)throw new Error(`AgentBay browser not found: ${selector}`);let agentBay=await createClient(resolveAgentBayApiKey()),releaseLock=acquireLaunchLock(record2.browserId);try{if(record2=findRecord(record2.browserId),!record2)throw new Error(`AgentBay browser not found: ${selector}`);let released=await releaseAgentBayBrowserResources(record2,agentBay,{...options,persistRecord:updatedRecord=>writeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR,updatedRecord.browserId),updatedRecord)}),closingOwnHost=record2.pid===process.pid;return closingOwnHost||await stopProcess(record2.pid,`--browser-id ${record2.browserId}`),removeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR,record2.browserId)),removeRecord(keyedConfigFile("browsers",record2.browserId)),closingOwnHost&&setTimeout(()=>process.kill(process.pid,"SIGTERM"),250).unref(),{browserId:record2.browserId,provider:"agentbay",closed:!0,...released,...record2.persistent===!0?{profileDeleted:options.deleteProfile===!0}:{profileDeleted:!0}}}finally{releaseLock()}}import{randomUUID as randomUUID5}from"node:crypto";import{basename as basename3,posix}from"node:path";var AGENTBAY_FILE_UPLOAD_WAIT_SECONDS=120;function pageUploadTargets(action,data){return action==="page_upload"?[{data}]:action!=="run_actions"||!Array.isArray(data?.actions)?[]:data.actions.flatMap((step,index)=>step?.action==="page_upload"?[{data:step.data,step:index}]:[])}function validateFilePaths(target){let filePaths=target.data?.filePaths;if(!Array.isArray(filePaths)||filePaths.length===0||filePaths.some(filePath=>typeof filePath!="string"||filePath.length===0)){let prefix=target.step===void 0?"":`Step ${target.step}: `;throw new Error(`${prefix}Invalid filePaths: must be a non-empty array of file path strings`)}return filePaths}function uploadError(result){return result.errorMessage??result.error_message??result.error??"unknown error"}async function stageAgentBayPageUploads(sessionId,action,data,dependencies={}){let targets=pageUploadTargets(action,data);if(targets.length===0)return data;let targetFilePaths=targets.map(target=>validateFilePaths(target)),fileSystem=(await(dependencies.getSession??getAgentBaySession)(sessionId)).fileSystem;if(!fileSystem)throw new Error("The installed AgentBay SDK does not support session file transfer");let contextPath=await fileSystem.getFileTransferContextPath();if(!contextPath)throw new Error(`AgentBay file transfer context is unavailable for session ${sessionId}`);let createTransferId=dependencies.createTransferId??randomUUID5,stagedPaths=await Promise.all(targetFilePaths.map(filePaths=>Promise.all(filePaths.map(async localPath=>{let remoteDirectory=posix.join(contextPath,createTransferId()),directoryResult=await fileSystem.createDirectory(remoteDirectory);if(directoryResult?.success===!1)throw new Error(`Failed to prepare AgentBay upload for ${basename3(localPath)}: ${uploadError(directoryResult)}`);let remotePath=posix.join(remoteDirectory,basename3(localPath)),result=await fileSystem.uploadFile(localPath,remotePath,{wait:!0,waitTimeout:AGENTBAY_FILE_UPLOAD_WAIT_SECONDS});if(result?.success!==!0)throw new Error(`Failed to upload ${basename3(localPath)} to AgentBay: ${uploadError(result)}`);return remotePath}))));if(action==="page_upload")return{...data,filePaths:stagedPaths[0]};let runActions=data,targetIndex=0;return{...runActions,actions:runActions.actions.map(step=>{if(step.action!=="page_upload")return step;let filePaths=stagedPaths[targetIndex++];return{...step,data:{...step.data,filePaths}}})}}var BROWSERS_SUBDIR="browsers",STALE_RECORD_TTL_MS=5*6e4,FOCUS_WRITE_THROTTLE_MS=1e3,identity=null,logFn2=()=>{};function initBrowserRegistry(deps){logFn2=deps.log}function recordFileFor2(browserId){return keyedConfigFile(BROWSERS_SUBDIR,browserId)}function ownsRecord(browserId){let existing=readRecord(recordFileFor2(browserId));return!existing||existing.pid===process.pid||!isAlive(existing.pid)}function persist(patch){if(!identity)return;let file2=recordFileFor2(identity.browserId);if(!ownsRecord(identity.browserId))return;let previous=readRecord(file2),record2={pid:process.pid,browserId:identity.browserId,socketPath:identity.socketPath,browserName:identity.browserName,nativeHostVersion:identity.nativeHostVersion,transport:identity.transport,startedAt:identity.startedAt,lastFocusedAt:previous?.lastFocusedAt,extensionVersion:previous?.extensionVersion,...patch,updatedAt:Date.now()};try{writeRecord(file2,record2)}catch(error48){logFn2("browser-registry: failed to write record:",String(error48))}}function registerBrowser(info){let startedAt=identity?.startedAt??new Date().toISOString();identity={browserId:info.browserId,socketPath:info.socketPath,browserName:info.browserName,nativeHostVersion:info.nativeHostVersion,transport:info.transport,startedAt};let previous=readRecord(recordFileFor2(info.browserId));persist({lastFocusedAt:previous?.lastFocusedAt??info.lastFocusedAt??Date.now(),extensionVersion:info.extensionVersion}),logFn2(`browser-registry: registered ${info.browserName} (${info.browserId})`)}var lastFocusWriteAt=0,focusFlushTimer=null;function writeFocusNow(){lastFocusWriteAt=Date.now(),persist({lastFocusedAt:lastFocusWriteAt})}function touchFocus(){if(!identity)return;let elapsed=Date.now()-lastFocusWriteAt;if(elapsed>=FOCUS_WRITE_THROTTLE_MS){writeFocusNow();return}focusFlushTimer||(focusFlushTimer=setTimeout(()=>{focusFlushTimer=null,writeFocusNow()},FOCUS_WRITE_THROTTLE_MS-elapsed),focusFlushTimer.unref())}function unregisterBrowser(){if(focusFlushTimer&&(clearTimeout(focusFlushTimer),focusFlushTimer=null),!identity)return;let file2=recordFileFor2(identity.browserId),existing=readRecord(file2);existing&&existing.pid!==process.pid||removeRecord(file2)}function pruneDeadBrowsers(){let now=Date.now();for(let file2 of listRecordFiles(keyedDir(BROWSERS_SUBDIR))){let rec=readRecord(file2);if(!rec){removeRecord(file2);continue}isAlive(rec.pid)||now-(rec.updatedAt??0)>STALE_RECORD_TTL_MS&&removeRecord(file2)}}function listRegisteredBrowsers(){let records=[];for(let file2 of listRecordFiles(keyedDir(BROWSERS_SUBDIR))){let record2=readRecord(file2);record2&&isAlive(record2.pid)&&records.push(record2)}return records.sort((a,b)=>(b.lastFocusedAt??0)-(a.lastFocusedAt??0)||(b.updatedAt??0)-(a.updatedAt??0))}function connectionFields(record2){return{extensionVersion:record2.extensionVersion,nativeHostVersion:record2.nativeHostVersion,transport:record2.transport}}function mergeBrowserInventory(connected,managed){let managedById=new Map(managed.map(browser=>[browser.browserId,browser])),browsers=connected.map(record2=>{let managedBrowser=managedById.get(record2.browserId);return managedBrowser?(managedById.delete(record2.browserId),{browserId:record2.browserId,name:managedBrowser.name,type:"managed",status:"connected",...connectionFields(record2),headless:managedBrowser.headless,persistent:managedBrowser.persistent,provider:managedBrowser.provider,..."cdpPort"in managedBrowser?{cdpPort:managedBrowser.cdpPort}:{},..."agentbaySessionId"in managedBrowser?{agentbaySessionId:managedBrowser.agentbaySessionId}:{},..."agentbayImageId"in managedBrowser&&managedBrowser.agentbayImageId?{agentbayImageId:managedBrowser.agentbayImageId}:{},..."agentbayContextId"in managedBrowser&&managedBrowser.agentbayContextId?{agentbayContextId:managedBrowser.agentbayContextId}:{},..."agentbayContextName"in managedBrowser&&managedBrowser.agentbayContextName?{agentbayContextName:managedBrowser.agentbayContextName}:{},createdAt:managedBrowser.createdAt,..."account"in managedBrowser?{account:managedBrowser.account}:{},..."copiedCookies"in managedBrowser?{copiedCookies:managedBrowser.copiedCookies}:{}}):{browserId:record2.browserId,name:record2.browserName,type:"regular",status:"connected",...connectionFields(record2)}}),disconnected=[...managedById.values()].sort((a,b)=>b.createdAt.localeCompare(a.createdAt)).map(browser=>({browserId:browser.browserId,name:browser.name,type:"managed",status:browser.running?"running_disconnected":"stopped",headless:browser.headless,persistent:browser.persistent,provider:browser.provider,..."cdpPort"in browser?{cdpPort:browser.cdpPort}:{},..."agentbaySessionId"in browser?{agentbaySessionId:browser.agentbaySessionId}:{},..."agentbayImageId"in browser&&browser.agentbayImageId?{agentbayImageId:browser.agentbayImageId}:{},..."agentbayContextId"in browser&&browser.agentbayContextId?{agentbayContextId:browser.agentbayContextId}:{},..."agentbayContextName"in browser&&browser.agentbayContextName?{agentbayContextName:browser.agentbayContextName}:{},createdAt:browser.createdAt,..."account"in browser?{account:browser.account}:{},..."copiedCookies"in browser?{copiedCookies:browser.copiedCookies}:{}}));return browsers.push(...disconnected),{count:browsers.length,connectedCount:connected.length,browsers}}function listBrowserInventory(){let managed=[...listManagedBrowsers(),...listAgentBayBrowsers()];return mergeBrowserInventory(listRegisteredBrowsers(),managed)}import fs5 from"node:fs";import path6 from"node:path";import os2 from"node:os";import{randomUUID as randomUUID6}from"node:crypto";var NATIVE_HOST_VERSION="2.9.1";var MEASUREMENT_ID="G-W84LJDZ6PH",API_SECRET="X233siI5RrGYLhlD0kBKEQ",ENDPOINT=`https://www.google-analytics.com/mp/collect?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`,CLIENT_ID_PATTERN=/^\d+\.\d+$/,BUILD_CHANNEL=NATIVE_HOST_VERSION==="unknown"?"development":"production",CONFIG_DIR=path6.join(os2.homedir(),".mearl"),CONFIG_FILE=path6.join(CONFIG_DIR,"config.json");function readConfig(){try{return JSON.parse(fs5.readFileSync(CONFIG_FILE,"utf-8"))}catch{return{}}}function writeConfig(config2){try{fs5.mkdirSync(CONFIG_DIR,{recursive:!0}),fs5.writeFileSync(CONFIG_FILE,JSON.stringify(config2,null,2))}catch{}}var clientId=null;function createClientId(seed=randomUUID6()){let first=2166136261,second=2246822519;for(let index=0;index<seed.length;index++){let code=seed.charCodeAt(index);first=Math.imul(first^code,16777619)>>>0,second=Math.imul(second^code,3266489917)>>>0}return`${first||1}.${second||1}`}function getClientId(){if(clientId)return clientId;let config2=readConfig();return config2.clientId&&CLIENT_ID_PATTERN.test(config2.clientId)?(clientId=config2.clientId,clientId):(clientId=createClientId(config2.clientId),writeConfig({...config2,clientId}),clientId)}function setAnalyticsClientId(value){return typeof value!="string"||!CLIENT_ID_PATTERN.test(value)?!1:(clientId=value,!0)}function classifyAnalyticsError(error48){let message=error48 instanceof Error?error48.message:String(error48);return/timed?\s*out|timeout/i.test(message)?"timeout":/permission|not authorized|access denied|forbidden/i.test(message)?"permission_denied":/not found|no matching|does not exist/i.test(message)?"not_found":/not connected|disconnected|unavailable|connection (?:failed|closed)/i.test(message)?"unavailable":/invalid|required|must be|unsupported/i.test(message)?"invalid_request":"execution_error"}function trackAction(action,params){let payload={client_id:getClientId(),events:[{name:"agent_action",params:{action,...params,mearl_version:NATIVE_HOST_VERSION,runtime:"native_host",build_channel:BUILD_CHANNEL}}]};fetch(ENDPOINT,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(payload),keepalive:!0}).catch(()=>{})}import{open}from"node:fs/promises";import path8 from"node:path";var TRUNCATED_MARKER=`
|
|
914
|
+
}`,arguments:[{value:ancestorDepth}],returnByValue:!1});if(ancestorObjectId=ancestor.result?.objectId,!ancestorObjectId||ancestor.result?.subtype==="null")throw new Error("page_snapshot: cannot resolve an ancestor for rootRef");let ancestorBackendNodeId=(await session.client.sendCommand("DOM.describeNode",{objectId:ancestorObjectId})).node?.backendNodeId;if(ancestorBackendNodeId===void 0)throw new Error("page_snapshot: cannot resolve an ancestor for rootRef");return ancestorBackendNodeId}finally{ancestorObjectId&&await session.client.sendCommand("Runtime.releaseObject",{objectId:ancestorObjectId}).catch(()=>{}),await session.client.sendCommand("Runtime.releaseObject",{objectId}).catch(()=>{})}}async function getViewportBackendNodeIds(session){let[metrics,captured]=await Promise.all([session.client.sendCommand("Page.getLayoutMetrics",{}),session.client.sendCommand("DOMSnapshot.captureSnapshot",{computedStyles:[],includeDOMRects:!0,includePaintOrder:!1})]),viewport=resolveDOMSnapshotViewportBounds(metrics);if(!viewport)throw new Error("page_snapshot: viewport metrics are unavailable");let{left,top,width,height}=viewport,right=left+width,bottom=top+height,visible=new Set;for(let document2 of captured.documents??[]){let backendNodeIds=document2.nodes?.backendNodeId??[],nodeIndexes=document2.layout?.nodeIndex??[],bounds=document2.layout?.bounds??[];for(let index=0;index<nodeIndexes.length;index+=1){let box=bounds[index],backendNodeId=backendNodeIds[nodeIndexes[index]];if(!box||backendNodeId===void 0)continue;let[x,y,boxWidth,boxHeight]=box;boxWidth<=0||boxHeight<=0||x<right&&x+boxWidth>left&&y<bottom&&y+boxHeight>top&&visible.add(backendNodeId)}}return visible}async function cdpPageSnapshot(session,data){let mode=data?.mode??"full",rootSelector=data?.rootSelector,rootRef=data?.rootRef,ancestorDepth=data?.ancestorDepth??0,query=resolvePageSnapshotQuery(data?.query);if(!["full","interactive","viewport"].includes(mode))throw new Error("page_snapshot: mode must be one of full, interactive, viewport");if(rootSelector!==void 0&&(typeof rootSelector!="string"||!rootSelector.trim()))throw new Error("page_snapshot: rootSelector must be a non-empty CSS selector");if(rootRef!==void 0&&(typeof rootRef!="string"||!/^@e\d+$/.test(rootRef)))throw new Error('page_snapshot: rootRef must be a snapshot ref like "@e3"');if(rootSelector!==void 0&&rootRef!==void 0)throw new Error("page_snapshot: rootSelector and rootRef are mutually exclusive");if(!Number.isInteger(ancestorDepth)||ancestorDepth<0||ancestorDepth>20)throw new Error("page_snapshot: ancestorDepth must be an integer between 0 and 20");if(ancestorDepth>0&&rootRef===void 0)throw new Error("page_snapshot: ancestorDepth requires rootRef");let rootBackendNodeId;if(rootSelector)rootBackendNodeId=await resolveRootBackendNodeId(session,rootSelector);else if(rootRef){let entry=resolvePageRef(session,rootRef);if(!entry)throw new Error(`Ref ${rootRef} not found. Run page_snapshot first to get fresh refs.`);rootBackendNodeId=await resolveAncestorBackendNodeId(session,entry.backendNodeId,ancestorDepth)}let snapshotRefs=beginPageSnapshotRefs(session),[result,visibleBackendNodeIds]=await Promise.all([session.client.sendCommand(rootBackendNodeId===void 0?"Accessibility.getFullAXTree":"Accessibility.queryAXTree",rootBackendNodeId===void 0?{depth:data?.depth}:{backendNodeId:rootBackendNodeId}),mode==="viewport"||mode==="interactive"?getViewportBackendNodeIds(session):Promise.resolve(void 0)]),nodes=result.nodes??[];await reconcileAXCheckedStates(nodes,backendNodeId=>readDOMCheckedState2(session,backendNodeId));let nodeMap=new Map;for(let node of nodes)nodeMap.set(node.nodeId,node);let rootNode=nodes[0];if(!rootNode)return snapshotRefs.commit(new Set),{snapshot:"(empty page)",refs:{},elementCount:0,outputNodeCount:1,mode,...rootSelector?{rootSelector}:{},...rootRef?{rootRef,ancestorDepth}:{},...query?{query,matches:[],matchCount:0}:{}};let rawTree=buildSnapshotTree(nodeMap,rootNode.nodeId,snapshotRefs),viewportFilteredTree=mode==="interactive"?filterSnapshotTree(rawTree,"viewport",visibleBackendNodeIds):rawTree,effectiveMode=mode;mode==="interactive"&&!hasInteractiveSnapshotNode(viewportFilteredTree)&&(effectiveMode="viewport");let modeFilteredTree=mode==="interactive"?effectiveMode==="interactive"?filterSnapshotTree(viewportFilteredTree,"interactive"):viewportFilteredTree:filterSnapshotTree(rawTree,effectiveMode,visibleBackendNodeIds),queryResult=query?filterSnapshotTreeByQuery(modeFilteredTree,query):{tree:modeFilteredTree,matches:[]},limitedMatches=query?limitPageSnapshotQueryMatches(queryResult.matches):{matches:[],truncated:!1},tree=queryResult.tree,lines=[];tree&&formatSnapshotNode(tree,0,lines);let formatted=formatSnapshotWithLimits(lines.length>0?lines:[query?"(no matches)":"(empty page)"],{maxChars:data?.maxChars,maxNodes:data?.maxNodes}),refs={},outputRefKeys=new Set(Array.from(formatted.snapshot.matchAll(/(?:^|\n)\s*(@e\d+)\s/g),match=>match[1]));for(let match of limitedMatches.matches)match.ref&&outputRefKeys.add(match.ref);snapshotRefs.commit(outputRefKeys);let registry2=getPageRefRegistry(session);for(let ref of outputRefKeys){let entry=registry2.resolve(ref);entry&&(refs[ref.slice(1)]={backendNodeId:entry.backendNodeId})}return{snapshot:formatted.snapshot,refs,elementCount:countSnapshotNodes(tree),outputNodeCount:formatted.outputNodeCount,mode,...rootSelector?{rootSelector}:{},...rootRef?{rootRef,ancestorDepth}:{},...query?{query,matches:limitedMatches.matches,matchCount:queryResult.matches.length,...limitedMatches.truncated?{matchesTruncated:!0}:{}}:{},...effectiveMode!==mode?{fallbackMode:"viewport"}:{},...formatted.truncated?{truncated:!0}:{}}}async function cdpPageFrames(session,_data){let result=await session.client.sendCommand("Page.getFrameTree",{});function flattenFrameTree(tree){if(!tree)return[];let{frame,childFrames=[]}=tree;return[{frameId:frame.id,parentFrameId:frame.parentId??null,url:frame.url,name:frame.name??""},...childFrames.flatMap(flattenFrameTree)]}let frames=flattenFrameTree(result.frameTree);return{frames,count:frames.length}}registerActions([{name:"page_snapshot",session:"page",handler:cdpPageSnapshot},{name:"page_frames",session:"page",handler:cdpPageFrames}]);var MEARL_SERVICE_COOKIE_DOMAINS=["tdbank.alibaba-inc.com","ats2.alibaba-inc.com","g.alibaba-inc.com","login.alibaba-inc.com","token-hub.alibaba-inc.com","alibaba-inc.com"],MEARL_SERVICE_COOKIE_HOSTS=new Set(MEARL_SERVICE_COOKIE_DOMAINS);function normalizeCookieDomain2(input){let value=input.trim();if(!value)throw new Error("Cookie domain must be a non-empty string");let hostname3;try{hostname3=new URL(value.includes("://")?value:`https://${value}`).hostname}catch{throw new Error(`Invalid cookie domain: ${input}`)}if(hostname3=hostname3.toLowerCase().replace(/^\.+/,"").replace(/\.+$/,""),!hostname3)throw new Error(`Invalid cookie domain: ${input}`);return hostname3}function normalizeCookieDomains(inputs){if(!Array.isArray(inputs))throw new Error("copyCookieDomains must be an array of domains");return[...new Set(inputs.map(value=>normalizeCookieDomain2(String(value))))]}function isMearlServiceCookie(cookie){let domain2=normalizeCookieDomain2(cookie.domain);return MEARL_SERVICE_COOKIE_HOSTS.has(domain2)?!0:domain2.endsWith(".tdbank.alibaba-inc.com")||domain2.endsWith(".ats2.alibaba-inc.com")}function resolveCookieCopyPlan(input){return input==="mearl-services"?{domains:[...MEARL_SERVICE_COOKIE_DOMAINS],select:cookies=>cookies.filter(isMearlServiceCookie)}:{domains:input===void 0?[]:normalizeCookieDomains(input),select:cookies=>cookies}}function cookieMatchesDomain(cookieDomain,requestedDomain){let cookieHost=cookieDomain.toLowerCase().replace(/^\.+/,"");return cookieHost===requestedDomain||cookieHost.endsWith(`.${requestedDomain}`)||requestedDomain.endsWith(`.${cookieHost}`)}function toTransferableCookie(cookie){let result={name:String(cookie.name),value:String(cookie.value),domain:String(cookie.domain),path:String(cookie.path||"/"),secure:!!cookie.secure,httpOnly:!!cookie.httpOnly};return["Strict","Lax","None"].includes(cookie.sameSite)&&(result.sameSite=cookie.sameSite),typeof cookie.expires=="number"&&cookie.expires>0&&(result.expires=cookie.expires),["Low","Medium","High"].includes(cookie.priority)&&(result.priority=cookie.priority),typeof cookie.sameParty=="boolean"&&(result.sameParty=cookie.sameParty),["Unset","NonSecure","Secure"].includes(cookie.sourceScheme)&&(result.sourceScheme=cookie.sourceScheme),typeof cookie.sourcePort=="number"&&(result.sourcePort=cookie.sourcePort),cookie.partitionKey?.topLevelSite&&(result.partitionKey={topLevelSite:String(cookie.partitionKey.topLevelSite),...typeof cookie.partitionKey.hasCrossSiteAncestor=="boolean"?{hasCrossSiteAncestor:cookie.partitionKey.hasCrossSiteAncestor}:{}}),result}async function cdpExportCookies(session,domains){let requestedDomains=normalizeCookieDomains(domains);return((await(await session.getBrowserClient()).sendCommand("Storage.getCookies",{})).cookies??[]).filter(cookie=>requestedDomains.some(domain2=>cookieMatchesDomain(String(cookie.domain),domain2))).map(toTransferableCookie)}async function cdpImportCookies(session,cookies){if(cookies.length===0)return 0;let browser=await session.getBrowserClient();return cdpImportCookiesWithClient(browser,cookies)}async function cdpImportCookiesWithClient(browser,cookies){return cookies.length===0?0:(await browser.sendCommand("Storage.setCookies",{cookies}),cookies.length)}import{closeSync,existsSync as existsSync3,mkdtempSync,mkdirSync as mkdirSync2,openSync as openSync2,readFileSync as readFileSync3,renameSync as renameSync3,rmSync as rmSync2,writeFileSync as writeFileSync2}from"node:fs";import{spawn as spawn3,spawnSync as spawnSync2}from"node:child_process";import{randomUUID as randomUUID3}from"node:crypto";import{tmpdir}from"node:os";import{join as join3}from"node:path";var MANAGED_BROWSERS_SUBDIR="managed-browsers",MANAGED_BROWSER_LOCKS_SUBDIR="managed-browser-locks",MANAGED_PROFILES_SUBDIR="managed-profiles",LAUNCH_TIMEOUT_MS=15e3;function validateName(value){let name=typeof value=="string"?value.trim():"";if(!name)throw new Error("name is required");if(name.length>64)throw new Error("name must be at most 64 characters");if(/[/\\\0\r\n]/.test(name))throw new Error("name contains unsupported characters");return name}function managedBrowserId(name){return`managed:${name.toLocaleLowerCase("en-US")}`}function hasTdbankSelector(data){return data.accountId!==void 0||data.havanaId!==void 0||typeof data.query=="string"&&data.query.trim().length>0}function validateTdbankSelector(data){if(data.havanaId!==void 0&&data.site===void 0)throw new Error("site is required when havanaId is provided");if([data.accountId!==void 0,data.havanaId!==void 0,typeof data.query=="string"&&data.query.trim().length>0].filter(Boolean).length>1)throw new Error("Use only one of accountId, havanaId + site, or query")}function chromeExecutableCandidates(platform=process.platform){let envPath=process.env.MEARL_CHROME_PATH,candidates=envPath?[envPath]:[];if(platform==="darwin")return candidates.concat(["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary","/Applications/Chromium.app/Contents/MacOS/Chromium"]);if(platform==="win32"){let local=process.env.LOCALAPPDATA??"",programFiles=process.env.PROGRAMFILES??"",programFilesX86=process.env["PROGRAMFILES(X86)"]??"";return candidates.concat([join3(local,"Google","Chrome","Application","chrome.exe"),join3(programFiles,"Google","Chrome","Application","chrome.exe"),join3(programFilesX86,"Google","Chrome","Application","chrome.exe")])}return candidates.concat(["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium","/usr/bin/chromium-browser"])}function resolveChromeExecutable(explicitPath){if(explicitPath){if(!existsSync3(explicitPath))throw new Error(`Chrome executable not found: ${explicitPath}`);return explicitPath}let found=chromeExecutableCandidates().find(candidate=>candidate&&existsSync3(candidate));if(!found)throw new Error("Chrome executable not found. Set executablePath or MEARL_CHROME_PATH.");return found}function desktopChromeUserAgent(version2,platform=process.platform){if(!/^\d+(?:\.\d+){1,3}$/.test(version2))throw new Error(`Invalid Chrome version: ${version2}`);return`Mozilla/5.0 (${platform==="darwin"?"Macintosh; Intel Mac OS X 10_15_7":platform==="win32"?"Windows NT 10.0; Win64; x64":"X11; Linux x86_64"}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${version2} Safari/537.36`}function resolveChromeVersion(executablePath){let result=spawnSync2(executablePath,["--version"],{encoding:"utf8",windowsHide:!0}),version2=`${result.stdout??""} ${result.stderr??""}`.match(/\b(\d+(?:\.\d+){1,3})\b/)?.[1];if(!version2)throw new Error(`Could not determine Chrome version from: ${executablePath}`);return version2}function resolveUserAgentMode(value){if(value===void 0||value==="default")return"default";if(value==="desktop")return"desktop";throw new Error('userAgentMode must be "default" or "desktop"')}function buildManagedChromeArgs(options){return[`--user-data-dir=${options.userDataDir}`,"--remote-debugging-port=0","--no-first-run","--no-default-browser-check","--disable-background-networking",...options.headless?["--headless=new"]:[],...options.userAgent?[`--user-agent=${options.userAgent}`]:[],"about:blank"]}function browserSummary(record2,running){return{browserId:record2.browserId,name:record2.name,provider:"local",headless:record2.headless,persistent:record2.persistent,cdpPort:record2.cdpPort,createdAt:record2.createdAt,account:record2.account,copiedCookies:record2.copiedCookies,running}}function isManagedProcess(pid,commandMarker,platform=process.platform){if(!isAlive(pid))return!1;try{if(platform==="win32"){let escapedMarker=commandMarker.replace(/'/g,"''");return spawnSync2("powershell.exe",["-NoProfile","-NonInteractive","-Command",`$p = Get-CimInstance Win32_Process -Filter 'ProcessId = ${pid}'; if ($p.CommandLine -and $p.CommandLine.Contains('${escapedMarker}')) { exit 0 } else { exit 1 }`],{windowsHide:!0,stdio:"ignore"}).status===0}let result=spawnSync2("ps",["-p",String(pid),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return result.status===0&&result.stdout.includes(commandMarker)}catch{return!1}}function listRecords(){let records=[];for(let file2 of listRecordFiles(keyedDir(MANAGED_BROWSERS_SUBDIR))){let record2=readRecord(file2);if(!record2){removeRecord(file2);continue}let running=isManagedProcess(record2.pid,record2.userDataDir);if(!running&&(signalProcess(record2.hostPid,"SIGTERM",`--browser-id ${record2.browserId}`),removeRecord(keyedConfigFile("browsers",record2.browserId)),!record2.persistent)){removeRecord(file2),rmSync2(record2.userDataDir,{recursive:!0,force:!0});continue}records.push({record:record2,running})}return records}function listManagedBrowsers(){return listRecords().map(({record:record2,running})=>browserSummary(record2,running))}function findManagedRecord(selector){let normalized=selector.trim().toLowerCase();return listRecords().find(({record:record2})=>record2.browserId.toLowerCase()===normalized||record2.name.toLowerCase()===normalized)?.record??null}function hasManagedBrowser(selector){return findManagedRecord(selector)!==null}async function waitForActivePort(userDataDir){let deadline=Date.now()+LAUNCH_TIMEOUT_MS;for(;Date.now()<deadline;){let info=readDevToolsActivePort(userDataDir);if(info)return info.port;await new Promise(resolve3=>setTimeout(resolve3,100))}throw new Error(`Chrome did not expose a CDP port within ${LAUNCH_TIMEOUT_MS}ms`)}async function waitForBrowserRegistration(browserId,expectedPid){let file2=keyedConfigFile("browsers",browserId),deadline=Date.now()+LAUNCH_TIMEOUT_MS;for(;Date.now()<deadline;){if(readRecord(file2)?.pid===expectedPid&&isAlive(expectedPid))return;await new Promise(resolve3=>setTimeout(resolve3,100))}throw new Error(`Managed browser ${browserId} did not register within ${LAUNCH_TIMEOUT_MS}ms`)}function signalProcess(pid,signal,commandMarker){if(isManagedProcess(pid,commandMarker)){if(process.platform==="win32"){spawnSync2("taskkill",["/PID",String(pid),"/T","/F"],{windowsHide:!0,stdio:"ignore"});return}try{process.kill(pid,signal)}catch{}}}async function stopProcess(pid,commandMarker){signalProcess(pid,"SIGTERM",commandMarker);let deadline=Date.now()+3e3;for(;Date.now()<deadline&&isManagedProcess(pid,commandMarker);)await new Promise(resolve3=>setTimeout(resolve3,50));isManagedProcess(pid,commandMarker)&&signalProcess(pid,"SIGKILL",commandMarker)}function profileDirectory(browserId,persistent){if(!persistent)return mkdtempSync(join3(tmpdir(),"mearl-browser-"));let dir=join3(DAEMON_HOME,MANAGED_PROFILES_SUBDIR,hashKey(browserId));return mkdirSync2(dir,{recursive:!0}),dir}async function removeStoppedInstance(browserId){let file2=keyedConfigFile(MANAGED_BROWSERS_SUBDIR,browserId),record2=readRecord(file2);!record2||isManagedProcess(record2.pid,record2.userDataDir)||(await stopProcess(record2.hostPid,`--browser-id ${record2.browserId}`),removeRecord(file2),removeRecord(keyedConfigFile("browsers",record2.browserId)),record2.persistent||rmSync2(record2.userDataDir,{recursive:!0,force:!0}))}function acquireLaunchLock(browserId){let lockDir=keyedDir(MANAGED_BROWSER_LOCKS_SUBDIR),lockFile=keyedConfigFile(MANAGED_BROWSER_LOCKS_SUBDIR,browserId);mkdirSync2(lockDir,{recursive:!0});let token=`${process.pid}:${randomUUID3()}`,tryAcquire=()=>{try{return writeFileSync2(lockFile,token,{flag:"wx"}),!0}catch(error48){if(error48.code!=="EEXIST")throw error48;return!1}};if(!tryAcquire()){let observedToken="";try{observedToken=readFileSync3(lockFile,"utf-8")}catch{}let ownerPid=Number(observedToken.split(":",1)[0]);if(Number.isInteger(ownerPid)&&!isAlive(ownerPid)){let staleFile=`${lockFile}.${process.pid}.${randomUUID3()}.stale`;try{if(readFileSync3(lockFile,"utf-8")!==observedToken)throw new Error("Launch lock owner changed");if(renameSync3(lockFile,staleFile),readFileSync3(staleFile,"utf-8")===observedToken)rmSync2(staleFile,{force:!0});else try{renameSync3(staleFile,lockFile)}catch{}}catch{}}if(!tryAcquire())throw new Error(`Managed browser launch already in progress: ${browserId}`)}return()=>{try{readFileSync3(lockFile,"utf-8")===token&&rmSync2(lockFile,{force:!0})}catch{}}}async function launchManagedBrowser(input,deps){if(input.reuse!==void 0&&input.reuse!=="never"&&input.reuse!=="prefer"&&input.reuse!=="require")throw new Error('reuse must be "never", "prefer", or "require"');if(input.reuse==="prefer"||input.reuse==="require")throw new Error("reuse is currently supported only by the AgentBay browser provider");if(input.imageId!==void 0)throw new Error("imageId is only supported by the AgentBay browser provider");let name=validateName(input.name),browserId=managedBrowserId(name);validateTdbankSelector(input);let cookieCopy=resolveCookieCopyPlan(input.copyCookieDomains),copyCookieDomains=cookieCopy.domains,headless=input.headless!==!1,persistent=input.persistent===!0,executablePath=resolveChromeExecutable(input.executablePath),userAgent=resolveUserAgentMode(input.userAgentMode)==="desktop"?desktopChromeUserAgent(resolveChromeVersion(executablePath)):void 0,userDataDir=profileDirectory(browserId,persistent),logDir=keyedDir(MANAGED_BROWSERS_SUBDIR);mkdirSync2(logDir,{recursive:!0});let logPath=join3(logDir,`${hashKey(browserId)}.log`),logFd=openSync2(logPath,"a"),chromePid=0,hostPid=0,session=null,recordWritten=!1,releaseLock=null;try{if(releaseLock=acquireLaunchLock(browserId),await removeStoppedInstance(browserId),findManagedRecord(browserId))throw new Error(`Managed browser already running: ${browserId}`);let[ticket,exportedCookies]=await Promise.all([hasTdbankSelector(input)?deps.prepareTdbankSso(input):Promise.resolve(void 0),copyCookieDomains.length>0?deps.exportCookies(copyCookieDomains):Promise.resolve([])]),cookies=cookieCopy.select(exportedCookies),chromeArgs=buildManagedChromeArgs({userDataDir,headless,userAgent});rmSync2(join3(userDataDir,"DevToolsActivePort"),{force:!0});let chrome=spawn3(executablePath,chromeArgs,{detached:!0,stdio:["ignore","ignore",logFd],windowsHide:headless});if(await new Promise((resolve3,reject)=>{chrome.once("error",reject),chrome.once("spawn",resolve3)}),chromePid=chrome.pid??0,!chromePid)throw new Error("Chrome launched without a process id");chrome.unref();let cdpPort=await waitForActivePort(userDataDir);session=new CdpSession({port:cdpPort,userDataDir});let copiedCookieCount=await cdpImportCookies(session,cookies),account;if(ticket){let login=await cdpConsumeTdbankSso(session,ticket.ssoUrl,ticket.account.loginId);account={accountId:ticket.account.accountId,loginId:ticket.account.loginId,nickname:login.nickname}}input.url&&await(await session.getBrowserClient()).sendCommand("Target.createTarget",{url:input.url,background:headless}),session.close(),session=null;let host=spawn3(process.execPath,[deps.nativeHostScript,"--daemon","--cdp-port",String(cdpPort),"--cdp-user-data-dir",userDataDir,"--browser-id",browserId,"--browser-name",name],{detached:!0,stdio:"ignore",windowsHide:!0});if(await new Promise((resolve3,reject)=>{host.once("error",reject),host.once("spawn",resolve3)}),hostPid=host.pid??0,!hostPid)throw new Error("Native host launched without a process id");host.unref();let record2={pid:chromePid,hostPid,browserId,name,headless,persistent,userDataDir,executablePath,cdpPort,createdAt:new Date().toISOString(),account,...copyCookieDomains.length>0?{copiedCookies:{domains:copyCookieDomains,count:copiedCookieCount}}:{}};return writeRecord(keyedConfigFile(MANAGED_BROWSERS_SUBDIR,browserId),record2),recordWritten=!0,await waitForBrowserRegistration(browserId,hostPid),deps.log(`managed browser launched: ${browserId}, chrome=${chromePid}, host=${hostPid}`),{...browserSummary(record2,!0),created:!0,reused:!1}}catch(error48){throw session?.close(),hostPid&&await stopProcess(hostPid,`--browser-id ${browserId}`),chromePid&&await stopProcess(chromePid,userDataDir),recordWritten&&removeRecord(keyedConfigFile(MANAGED_BROWSERS_SUBDIR,browserId)),persistent||rmSync2(userDataDir,{recursive:!0,force:!0}),error48}finally{releaseLock?.(),closeSync(logFd)}}async function closeManagedBrowser(selector,options={}){let record2=findManagedRecord(selector);if(!record2)throw new Error(`Managed browser not found: ${selector}`);await stopProcess(record2.pid,record2.userDataDir);let closingOwnHost=record2.hostPid===process.pid;closingOwnHost||await stopProcess(record2.hostPid,`--browser-id ${record2.browserId}`),removeRecord(keyedConfigFile(MANAGED_BROWSERS_SUBDIR,record2.browserId)),removeRecord(keyedConfigFile("browsers",record2.browserId));let deleteProfile=options.deleteProfile===!0||!record2.persistent;return deleteProfile&&rmSync2(record2.userDataDir,{recursive:!0,force:!0}),closingOwnHost&&setTimeout(()=>process.kill(process.pid,"SIGTERM"),250).unref(),{browserId:record2.browserId,closed:!0,profileDeleted:deleteProfile}}import{existsSync as existsSync9,readFileSync as readFileSync7}from"node:fs";import{spawn as spawn5}from"node:child_process";import{homedir as homedir2}from"node:os";import{dirname as dirname6,join as join6,parse,resolve as resolve2}from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";function positiveIntegerMinutes(value,name,fallback){if(value===void 0||!value.trim())return fallback;let minutes=Number(value);if(!Number.isInteger(minutes)||minutes<=0)throw new Error(`${name} must be a positive integer in minutes`);return minutes}function resolveAgentBayLifecycleConfig(env=process.env){let idleReleaseTimeout=positiveIntegerMinutes(env.MEARL_AGENTBAY_IDLE_RELEASE_MINUTES,"MEARL_AGENTBAY_IDLE_RELEASE_MINUTES",30),maxRuntime=positiveIntegerMinutes(env.MEARL_AGENTBAY_MAX_RUNTIME_MINUTES,"MEARL_AGENTBAY_MAX_RUNTIME_MINUTES",120);if(idleReleaseTimeout<3)throw new Error("MEARL_AGENTBAY_IDLE_RELEASE_MINUTES must be at least 3");if(maxRuntime<idleReleaseTimeout)throw new Error("MEARL_AGENTBAY_MAX_RUNTIME_MINUTES must be greater than or equal to MEARL_AGENTBAY_IDLE_RELEASE_MINUTES");return{idleReleaseTimeout,maxRuntime}}var AgentBaySessionWatchdog=class{idleTimeoutMs;checkIntervalMs;now;keepAlive;close;log;activeRequests=0;lastActivityAt;timer=null;checking=!1;closing=!1;stopped=!1;constructor(options){if(!Number.isFinite(options.idleTimeoutMs)||options.idleTimeoutMs<=0)throw new Error("AgentBay idle timeout must be positive");if(this.idleTimeoutMs=options.idleTimeoutMs,this.checkIntervalMs=options.checkIntervalMs??6e4,!Number.isFinite(this.checkIntervalMs)||this.checkIntervalMs<=0)throw new Error("AgentBay lifecycle check interval must be positive");this.now=options.now??Date.now,this.keepAlive=options.keepAlive,this.close=options.close,this.log=options.log,this.lastActivityAt=this.now()}start(){this.timer||this.stopped||(this.timer=setInterval(()=>void this.checkNow(),this.checkIntervalMs),this.timer.unref())}stop(){this.stopped=!0,this.timer&&(clearInterval(this.timer),this.timer=null)}beginActivity(){return this.stopped||this.closing?!1:(this.activeRequests+=1,this.lastActivityAt=this.now(),!0)}endActivity(){this.activeRequests>0&&(this.activeRequests-=1),this.lastActivityAt=this.now()}async checkNow(){if(!(this.stopped||this.checking||this.closing)){this.checking=!0;try{let idleForMs=this.now()-this.lastActivityAt;if(this.activeRequests>0||idleForMs<this.idleTimeoutMs){try{await this.keepAlive()}catch(error48){this.log("AgentBay keepalive failed:",error48 instanceof Error?error48.message:String(error48))}return}this.closing=!0,this.log(`AgentBay browser reached the idle timeout after ${idleForMs}ms; closing`);try{await this.close()}catch(error48){this.closing=!1,this.log("AgentBay idle close failed:",error48 instanceof Error?error48.message:String(error48))}}finally{this.checking=!1}}}};var AGENTBAY_BROWSERS_SUBDIR="agentbay-browsers",DEFAULT_AGENTBAY_IMAGE_ID="imgc-0aae4rgl8kvagdv1j",sdkPromise=null;async function loadSdk(){return sdkPromise??=Promise.resolve().then(()=>(init_agentbay_sdk(),agentbay_sdk_exports)),sdkPromise}async function createClient(apiKey){let{AgentBay:AgentBay2}=await loadSdk();return new AgentBay2({apiKey})}function agentBayBrowserId(name){return`managed:agentbay:${name.toLocaleLowerCase("en-US")}`}function envValue(text,key){for(let line of text.split(/\r?\n/)){let match=/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)\s*$/.exec(line);if(!match||match[1]!==key)continue;let value=(match[2]??"").trim();return value.length>=2&&(value.startsWith('"')&&value.endsWith('"')||value.startsWith("'")&&value.endsWith("'"))?value=value.slice(1,-1):value=value.replace(/\s+#.*$/,"").trim(),value||void 0}}function envFilesUpward(start){let files=[],current=resolve2(start);for(;;){files.push(join6(current,".env"));let parent=dirname6(current);if(parent===current||current===parse(current).root)break;current=parent}return files}function resolveAgentBayApiKey(){let inherited=process.env.AGENTBAY_KEY?.trim()||process.env.AGENTBAY_API_KEY?.trim();if(inherited)return inherited;let moduleDir=dirname6(fileURLToPath2(import.meta.url)),candidates=[...process.env.MEARL_ENV_FILE?[resolve2(process.env.MEARL_ENV_FILE)]:[],...envFilesUpward(process.cwd()),...envFilesUpward(moduleDir),join6(homedir2(),".mearl",".env")];for(let file2 of new Set(candidates))if(existsSync9(file2))try{let text=readFileSync7(file2,"utf8"),value=envValue(text,"AGENTBAY_KEY")??envValue(text,"AGENTBAY_API_KEY");if(value)return value}catch{}throw new Error("AgentBay API key not found. Set AGENTBAY_KEY in the environment, project .env, or ~/.mearl/.env.")}function validateAgentBayInput(input){if(input.headless===!0)throw new Error("headless=true is not supported by the AgentBay browser provider");if(input.executablePath)throw new Error("executablePath is only supported by the local browser provider");if(input.accountId!==void 0||input.havanaId!==void 0||input.site!==void 0||typeof input.query=="string"&&input.query.trim())throw new Error("TDBank login parameters are only supported by the local browser provider")}function resolveReuseMode(value){if(value===void 0)return"never";if(value==="never"||value==="prefer"||value==="require")return value;throw new Error('reuse must be "never", "prefer", or "require"')}function validateReusableAgentBayConfiguration(input,record2){if(input.imageId!==void 0&&resolveAgentBayImageId(input.imageId)!==record2.imageId)throw new Error(`Cannot change imageId while reusing AgentBay browser: ${record2.browserId}`);if(input.persistent!==void 0&&input.persistent!==(record2.persistent===!0))throw new Error(`Cannot change persistent while reusing AgentBay browser: ${record2.browserId}`);if(input.userAgentMode!==void 0&&record2.userAgentMode!==void 0&&input.userAgentMode!==record2.userAgentMode)throw new Error(`Cannot change userAgentMode while reusing AgentBay browser: ${record2.browserId}`)}function resolveAgentBayImageId(value){if(value===void 0)return DEFAULT_AGENTBAY_IMAGE_ID;let imageId=typeof value=="string"?value.trim():"";if(!imageId||imageId.length>128||!/^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(imageId))throw new Error("imageId must be a valid AgentBay image alias or image ID");return imageId}function agentBayContextName(browserId){return`mearl-browser-${hashKey(browserId)}`}function normalizeDesktopUserAgent(value){let userAgent=typeof value=="string"?value.trim():"";if(!userAgent)throw new Error("Could not determine the control browser user agent");return userAgent.replace(/\bHeadlessChrome\//g,"Chrome/")}function normalizeAgentBayAccessUrl(value){let candidate=typeof value=="string"?value.trim():"";if(candidate)try{let url2=new URL(candidate);return url2.protocol==="https:"||url2.protocol==="http:"?url2.toString():void 0}catch{return}}function browserSummary2(record2,running){return{browserId:record2.browserId,name:record2.name,provider:"agentbay",headless:!1,persistent:record2.persistent===!0,agentbaySessionId:record2.sessionId,...record2.imageId?{agentbayImageId:record2.imageId}:{},...record2.contextId?{agentbayContextId:record2.contextId}:{},...record2.contextName?{agentbayContextName:record2.contextName}:{},createdAt:record2.createdAt,...record2.copiedCookies?{copiedCookies:record2.copiedCookies}:{},running}}function listRecords2(){let records=[];for(let file2 of listRecordFiles(keyedDir(AGENTBAY_BROWSERS_SUBDIR))){let stored=readRecord(file2);if(!stored){removeRecord(file2);continue}let{accessUrl:legacyAccessUrl,...record2}=stored;legacyAccessUrl!==void 0&&writeRecord(file2,record2);let running=isManagedProcess(record2.pid,`--browser-id ${record2.browserId}`);running||removeRecord(keyedConfigFile("browsers",record2.browserId)),records.push({record:record2,running})}return records}function findRecordWithStatus(selector){let normalized=selector.trim().toLowerCase();return listRecords2().find(({record:record2})=>record2.browserId.toLowerCase()===normalized||record2.name.toLowerCase()===normalized)??null}function findRecord(selector){return findRecordWithStatus(selector)?.record??null}function hasAgentBayBrowser(selector){return findRecord(selector)!==null}function listAgentBayBrowsers(){return listRecords2().map(({record:record2,running})=>browserSummary2(record2,running))}async function requireSession(sessionId,apiKey){let agentBay=await createClient(apiKey);return requireSessionFromClient(agentBay,sessionId)}async function requireSessionFromClient(agentBay,sessionId){let result=await agentBay.get(sessionId);if(!result.success||!result.session)throw new Error(result.errorMessage||`AgentBay session not found: ${sessionId}`);return result.session}async function getAgentBaySession(sessionId,dependencies={}){let apiKey=(dependencies.resolveApiKey??resolveAgentBayApiKey)(),agentBay=dependencies.createAgentBayClient?await dependencies.createAgentBayClient(apiKey):await createClient(apiKey);return requireSessionFromClient(agentBay,sessionId)}async function getAgentBayAccessUrl(sessionId,dependencies={}){let apiKey=(dependencies.resolveApiKey??resolveAgentBayApiKey)(),agentBay=dependencies.createAgentBayClient?await dependencies.createAgentBayClient(apiKey):await createClient(apiKey),session=await requireSessionFromClient(agentBay,sessionId);if(!session.info)throw new Error("The installed AgentBay SDK does not support live session information");let result=await session.info();if(result.success===!1)throw new Error(result.errorMessage||`AgentBay session info failed: ${sessionId}`);let data=result.data&&typeof result.data=="object"?result.data:null,accessUrl=normalizeAgentBayAccessUrl(data&&"resourceUrl"in data?data.resourceUrl:void 0);if(!accessUrl)throw new Error(`AgentBay session did not return a browser access URL: ${sessionId}`);return accessUrl}async function resolvePersistentContext(agentBay,browserId){if(!agentBay.context)throw new Error("The installed AgentBay SDK does not support persistent browser contexts");let name=agentBayContextName(browserId),result=await agentBay.context.get(name,!0);if(!result.success||!result.context?.id)throw new Error(result.errorMessage||`Failed to create AgentBay browser context: ${name}`);return{id:result.context.id,name:result.context.name||name}}async function resolveAgentBayEndpoint(sessionId){let apiKey=resolveAgentBayApiKey(),{AgentBay:AgentBay2,GetCdpLinkRequest:GetCdpLinkRequest2}=await loadSdk(),response=await new AgentBay2({apiKey}).client.getCdpLink(new GetCdpLinkRequest2({authorization:`Bearer ${apiKey}`,sessionId})),endpoint=response.body?.success?response.body.data?.url:void 0;if(!endpoint)throw new Error(response.body?.message||`Failed to get AgentBay CDP link: ${sessionId}`);let url2=new URL(endpoint);if(url2.protocol!=="ws:"&&url2.protocol!=="wss:")throw new Error(`AgentBay returned an unsupported CDP endpoint: ${url2.protocol}`);return url2.toString()}async function keepAgentBaySessionAlive(sessionId){let result=await(await requireSession(sessionId,resolveAgentBayApiKey())).keepAlive();if(result.success===!1)throw new Error(result.errorMessage||"AgentBay keepalive failed")}async function configureAgentBayBrowserSession(session,input,cookies,connectCdp=url2=>CdpClient.connect(url2)){let endpoint=await session.browser.getEndpointUrl(),cdp=await connectCdp(endpoint);try{await cdp.sendCommand("Browser.getVersion",{},1e4);let copiedCookieCount=await cdpImportCookiesWithClient(cdp,cookies);return input.url&&await cdp.sendCommand("Target.createTarget",{url:input.url,background:!1}),copiedCookieCount}finally{cdp.close()}}async function initializeAgentBayBrowserSession(session,input,cookies,options={}){if(!await session.browser.initializeAsync(options.userAgent?{userAgent:options.userAgent}:{}))throw new Error("AgentBay browser initialization failed");return configureAgentBayBrowserSession(session,input,cookies,options.connectCdp)}async function reuseAgentBayBrowserSession(session,input,cookies,options={}){return configureAgentBayBrowserSession(session,input,cookies,options.connectCdp)}async function launchAgentBayBrowser(input,deps){let name=validateName(input.name),browserId=agentBayBrowserId(name);validateAgentBayInput(input);let reuseMode=resolveReuseMode(input.reuse),imageId=resolveAgentBayImageId(input.imageId),persistent=input.persistent===!0,userAgentMode=resolveUserAgentMode(input.userAgentMode),cookieCopy=resolveCookieCopyPlan(input.copyCookieDomains),copyCookieDomains=cookieCopy.domains,apiKey=(deps.resolveApiKey??resolveAgentBayApiKey)(),lifecycle=resolveAgentBayLifecycleConfig(),releaseLock=acquireLaunchLock(browserId),persistBrowserRecord=deps.persistBrowserRecord??(record2=>writeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR,record2.browserId),record2)),findBrowserRecord=deps.findBrowserRecord??findRecordWithStatus,session=null,context,hostPid=0,recordWritten=!1;try{let existing=findBrowserRecord(browserId);if(existing){if(reuseMode==="never")throw new Error(`AgentBay browser already exists: ${browserId}`);if(!existing.running)throw new Error(`AgentBay browser is not running and cannot be reused: ${browserId}`);validateReusableAgentBayConfiguration(input,existing.record);let exportedCookies2=copyCookieDomains.length>0?await deps.exportCookies(copyCookieDomains):[],cookies2=cookieCopy.select(exportedCookies2),agentBay2=await(deps.createAgentBayClient??createClient)(apiKey),existingSession=await requireSessionFromClient(agentBay2,existing.record.sessionId),copiedCookieCount2=await reuseAgentBayBrowserSession(existingSession,input,cookies2,{connectCdp:deps.connectCdp}),record3={...existing.record,...copyCookieDomains.length>0?{copiedCookies:{domains:copyCookieDomains,count:copiedCookieCount2}}:{}};return copyCookieDomains.length>0&&persistBrowserRecord(record3),deps.log(`AgentBay browser reused: ${browserId}, host=${record3.pid}`),{...browserSummary2(record3,!0),created:!1,reused:!0}}if(reuseMode==="require")throw new Error(`AgentBay browser is not running and reuse=require: ${browserId}`);let[exportedCookies,userAgent]=await Promise.all([copyCookieDomains.length>0?deps.exportCookies(copyCookieDomains):Promise.resolve([]),userAgentMode==="desktop"?deps.getBrowserUserAgent().then(normalizeDesktopUserAgent):Promise.resolve(void 0)]),cookies=cookieCopy.select(exportedCookies),agentBay=await(deps.createAgentBayClient??createClient)(apiKey);context=persistent?await resolvePersistentContext(agentBay,browserId):void 0;let{LifecyclePolicy:LifecyclePolicy2}=await loadSdk(),created=await agentBay.create({imageId,framework:"mearl",lifecyclePolicy:new LifecyclePolicy2(lifecycle),...context?{browserContext:{contextId:context.id,autoUpload:!0,syncMode:"standard"}}:{}});if(!created.success||!created.session)throw new Error(created.errorMessage||"AgentBay session creation failed");session=created.session;let copiedCookieCount=await initializeAgentBayBrowserSession(session,input,cookies,{userAgent,connectCdp:deps.connectCdp}),host=spawn5(process.execPath,[deps.nativeHostScript,"--daemon","--agentbay-session-id",session.sessionId,"--browser-id",browserId,"--browser-name",name,"--agentbay-idle-release-minutes",String(lifecycle.idleReleaseTimeout)],{detached:!0,stdio:"ignore",windowsHide:!0});if(await new Promise((resolveSpawn,rejectSpawn)=>{host.once("error",rejectSpawn),host.once("spawn",resolveSpawn)}),hostPid=host.pid??0,!hostPid)throw new Error("AgentBay native host launched without a process id");host.unref();let record2={pid:hostPid,browserId,name,sessionId:session.sessionId,imageId,userAgentMode,persistent,...context?{contextId:context.id,contextName:context.name}:{},createdAt:new Date().toISOString(),...copyCookieDomains.length>0?{copiedCookies:{domains:copyCookieDomains,count:copiedCookieCount}}:{}};return persistBrowserRecord(record2),recordWritten=!0,await waitForBrowserRegistration(browserId,hostPid),deps.log(`AgentBay browser launched: ${browserId}, host=${hostPid}`),{...browserSummary2(record2,!0),created:!0,reused:!1}}catch(error48){if(hostPid&&await stopProcess(hostPid,`--browser-id ${browserId}`),recordWritten&&(removeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR,browserId)),removeRecord(keyedConfigFile("browsers",browserId))),session){let cleanupError;try{let deleted=await session.delete(!1);deleted.success||(cleanupError=new Error(deleted.errorMessage||"AgentBay session deletion failed"))}catch(deleteError){cleanupError=deleteError}if(cleanupError){let recoveryRecord={pid:hostPid,browserId,name,sessionId:session.sessionId,imageId,userAgentMode,persistent,...context?{contextId:context.id,contextName:context.name}:{},createdAt:new Date().toISOString()},recoverySaved=!1,recoveryError;try{persistBrowserRecord(recoveryRecord),recoverySaved=!0}catch(writeError){recoveryError=writeError}throw deps.log(`AgentBay launch cleanup failed for ${session.sessionId}:`,cleanupError instanceof Error?cleanupError.message:String(cleanupError)),recoveryError&&deps.log(`AgentBay recovery metadata could not be saved for ${session.sessionId}:`,recoveryError instanceof Error?recoveryError.message:String(recoveryError)),new AggregateError(recoveryError?[error48,cleanupError,recoveryError]:[error48,cleanupError],`${error48 instanceof Error?error48.message:String(error48)}; `+(recoverySaved?"AgentBay session cleanup failed and recovery metadata was retained for browser_close":`AgentBay session cleanup failed; session ${session.sessionId} may require manual deletion`),{cause:error48})}}throw error48}finally{releaseLock()}}function isMissingSessionError(error48){let message=error48 instanceof Error?error48.message:String(error48);return/not[ -]?found|does not exist|already deleted|invalid session/i.test(message)}async function releaseAgentBayBrowserResources(record2,agentBay,options={}){let deleteContext=record2.persistent===!0&&options.deleteProfile===!0,syncContext=record2.persistent===!0&&!deleteContext,contextSynced=!!record2.contextSyncedAt,session;try{session=await requireSessionFromClient(agentBay,record2.sessionId)}catch(error48){if(!isMissingSessionError(error48))throw error48}if(session){if(syncContext&&!contextSynced){if(!session.callMcpTool)throw new Error("The installed AgentBay SDK cannot stop the browser before context sync");let stopped=await session.callMcpTool("stopChrome",{},!1);if(stopped.success===!1)throw new Error(stopped.errorMessage||"AgentBay browser shutdown failed");if(!session.context)throw new Error("The installed AgentBay SDK cannot synchronize browser context state");let synced=await session.context.sync();if(!synced.success)throw new Error(synced.errorMessage||"AgentBay browser context sync failed");contextSynced=!0,record2.contextSyncedAt=new Date().toISOString(),options.persistRecord?.(record2)}try{let result=await session.delete(!1);if(!result.success)throw new Error(result.errorMessage||"AgentBay session deletion failed")}catch(error48){if(!isMissingSessionError(error48))throw error48}}if(deleteContext){if(!record2.contextId||!record2.contextName||!agentBay.context)throw new Error("AgentBay browser context metadata is unavailable for profile deletion");let result=await agentBay.context.delete({id:record2.contextId,name:record2.contextName});if(!result.success)throw new Error(result.errorMessage||"AgentBay context deletion failed")}return{sessionDeleted:!0,...syncContext?{contextSynced}:{},...deleteContext?{contextDeleted:!0}:{}}}async function closeAgentBayBrowser(selector,options={}){let record2=findRecord(selector);if(!record2)throw new Error(`AgentBay browser not found: ${selector}`);let agentBay=await createClient(resolveAgentBayApiKey()),releaseLock=acquireLaunchLock(record2.browserId);try{if(record2=findRecord(record2.browserId),!record2)throw new Error(`AgentBay browser not found: ${selector}`);let released=await releaseAgentBayBrowserResources(record2,agentBay,{...options,persistRecord:updatedRecord=>writeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR,updatedRecord.browserId),updatedRecord)}),closingOwnHost=record2.pid===process.pid;return closingOwnHost||await stopProcess(record2.pid,`--browser-id ${record2.browserId}`),removeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR,record2.browserId)),removeRecord(keyedConfigFile("browsers",record2.browserId)),closingOwnHost&&setTimeout(()=>process.kill(process.pid,"SIGTERM"),250).unref(),{browserId:record2.browserId,provider:"agentbay",closed:!0,...released,...record2.persistent===!0?{profileDeleted:options.deleteProfile===!0}:{profileDeleted:!0}}}finally{releaseLock()}}import{randomUUID as randomUUID5}from"node:crypto";import{basename as basename3,posix}from"node:path";var AGENTBAY_FILE_UPLOAD_WAIT_SECONDS=120;function pageUploadTargets(action,data){return action==="page_upload"?[{data}]:action!=="run_actions"||!Array.isArray(data?.actions)?[]:data.actions.flatMap((step,index)=>step?.action==="page_upload"?[{data:step.data,step:index}]:[])}function validateFilePaths(target){let filePaths=target.data?.filePaths;if(!Array.isArray(filePaths)||filePaths.length===0||filePaths.some(filePath=>typeof filePath!="string"||filePath.length===0)){let prefix=target.step===void 0?"":`Step ${target.step}: `;throw new Error(`${prefix}Invalid filePaths: must be a non-empty array of file path strings`)}return filePaths}function uploadError(result){return result.errorMessage??result.error_message??result.error??"unknown error"}async function stageAgentBayPageUploads(sessionId,action,data,dependencies={}){let targets=pageUploadTargets(action,data);if(targets.length===0)return data;let targetFilePaths=targets.map(target=>validateFilePaths(target)),fileSystem=(await(dependencies.getSession??getAgentBaySession)(sessionId)).fileSystem;if(!fileSystem)throw new Error("The installed AgentBay SDK does not support session file transfer");let contextPath=await fileSystem.getFileTransferContextPath();if(!contextPath)throw new Error(`AgentBay file transfer context is unavailable for session ${sessionId}`);let createTransferId=dependencies.createTransferId??randomUUID5,stagedPaths=await Promise.all(targetFilePaths.map(filePaths=>Promise.all(filePaths.map(async localPath=>{let remoteDirectory=posix.join(contextPath,createTransferId()),directoryResult=await fileSystem.createDirectory(remoteDirectory);if(directoryResult?.success===!1)throw new Error(`Failed to prepare AgentBay upload for ${basename3(localPath)}: ${uploadError(directoryResult)}`);let remotePath=posix.join(remoteDirectory,basename3(localPath)),result=await fileSystem.uploadFile(localPath,remotePath,{wait:!0,waitTimeout:AGENTBAY_FILE_UPLOAD_WAIT_SECONDS});if(result?.success!==!0)throw new Error(`Failed to upload ${basename3(localPath)} to AgentBay: ${uploadError(result)}`);return remotePath}))));if(action==="page_upload")return{...data,filePaths:stagedPaths[0]};let runActions=data,targetIndex=0;return{...runActions,actions:runActions.actions.map(step=>{if(step.action!=="page_upload")return step;let filePaths=stagedPaths[targetIndex++];return{...step,data:{...step.data,filePaths}}})}}var BROWSERS_SUBDIR="browsers",STALE_RECORD_TTL_MS=5*6e4,FOCUS_WRITE_THROTTLE_MS=1e3,identity=null,logFn2=()=>{};function initBrowserRegistry(deps){logFn2=deps.log}function recordFileFor2(browserId){return keyedConfigFile(BROWSERS_SUBDIR,browserId)}function ownsRecord(browserId){let existing=readRecord(recordFileFor2(browserId));return!existing||existing.pid===process.pid||!isAlive(existing.pid)}function persist(patch){if(!identity)return;let file2=recordFileFor2(identity.browserId);if(!ownsRecord(identity.browserId))return;let previous=readRecord(file2),record2={pid:process.pid,browserId:identity.browserId,socketPath:identity.socketPath,browserName:identity.browserName,nativeHostVersion:identity.nativeHostVersion,transport:identity.transport,startedAt:identity.startedAt,lastFocusedAt:previous?.lastFocusedAt,extensionVersion:previous?.extensionVersion,...patch,updatedAt:Date.now()};try{writeRecord(file2,record2)}catch(error48){logFn2("browser-registry: failed to write record:",String(error48))}}function registerBrowser(info){let startedAt=identity?.startedAt??new Date().toISOString();identity={browserId:info.browserId,socketPath:info.socketPath,browserName:info.browserName,nativeHostVersion:info.nativeHostVersion,transport:info.transport,startedAt};let previous=readRecord(recordFileFor2(info.browserId));persist({lastFocusedAt:previous?.lastFocusedAt??info.lastFocusedAt??Date.now(),extensionVersion:info.extensionVersion}),logFn2(`browser-registry: registered ${info.browserName} (${info.browserId})`)}var lastFocusWriteAt=0,focusFlushTimer=null;function writeFocusNow(){lastFocusWriteAt=Date.now(),persist({lastFocusedAt:lastFocusWriteAt})}function touchFocus(){if(!identity)return;let elapsed=Date.now()-lastFocusWriteAt;if(elapsed>=FOCUS_WRITE_THROTTLE_MS){writeFocusNow();return}focusFlushTimer||(focusFlushTimer=setTimeout(()=>{focusFlushTimer=null,writeFocusNow()},FOCUS_WRITE_THROTTLE_MS-elapsed),focusFlushTimer.unref())}function unregisterBrowser(){if(focusFlushTimer&&(clearTimeout(focusFlushTimer),focusFlushTimer=null),!identity)return;let file2=recordFileFor2(identity.browserId),existing=readRecord(file2);existing&&existing.pid!==process.pid||removeRecord(file2)}function pruneDeadBrowsers(){let now=Date.now();for(let file2 of listRecordFiles(keyedDir(BROWSERS_SUBDIR))){let rec=readRecord(file2);if(!rec){removeRecord(file2);continue}isAlive(rec.pid)||now-(rec.updatedAt??0)>STALE_RECORD_TTL_MS&&removeRecord(file2)}}function listRegisteredBrowsers(){let records=[];for(let file2 of listRecordFiles(keyedDir(BROWSERS_SUBDIR))){let record2=readRecord(file2);record2&&isAlive(record2.pid)&&records.push(record2)}return records.sort((a,b)=>(b.lastFocusedAt??0)-(a.lastFocusedAt??0)||(b.updatedAt??0)-(a.updatedAt??0))}function connectionFields(record2){return{extensionVersion:record2.extensionVersion,nativeHostVersion:record2.nativeHostVersion,transport:record2.transport}}function mergeBrowserInventory(connected,managed){let managedById=new Map(managed.map(browser=>[browser.browserId,browser])),browsers=connected.map(record2=>{let managedBrowser=managedById.get(record2.browserId);return managedBrowser?(managedById.delete(record2.browserId),{browserId:record2.browserId,name:managedBrowser.name,type:"managed",status:"connected",...connectionFields(record2),headless:managedBrowser.headless,persistent:managedBrowser.persistent,provider:managedBrowser.provider,..."cdpPort"in managedBrowser?{cdpPort:managedBrowser.cdpPort}:{},..."agentbaySessionId"in managedBrowser?{agentbaySessionId:managedBrowser.agentbaySessionId}:{},..."agentbayImageId"in managedBrowser&&managedBrowser.agentbayImageId?{agentbayImageId:managedBrowser.agentbayImageId}:{},..."agentbayContextId"in managedBrowser&&managedBrowser.agentbayContextId?{agentbayContextId:managedBrowser.agentbayContextId}:{},..."agentbayContextName"in managedBrowser&&managedBrowser.agentbayContextName?{agentbayContextName:managedBrowser.agentbayContextName}:{},createdAt:managedBrowser.createdAt,..."account"in managedBrowser?{account:managedBrowser.account}:{},..."copiedCookies"in managedBrowser?{copiedCookies:managedBrowser.copiedCookies}:{}}):{browserId:record2.browserId,name:record2.browserName,type:"regular",status:"connected",...connectionFields(record2)}}),disconnected=[...managedById.values()].sort((a,b)=>b.createdAt.localeCompare(a.createdAt)).map(browser=>({browserId:browser.browserId,name:browser.name,type:"managed",status:browser.running?"running_disconnected":"stopped",headless:browser.headless,persistent:browser.persistent,provider:browser.provider,..."cdpPort"in browser?{cdpPort:browser.cdpPort}:{},..."agentbaySessionId"in browser?{agentbaySessionId:browser.agentbaySessionId}:{},..."agentbayImageId"in browser&&browser.agentbayImageId?{agentbayImageId:browser.agentbayImageId}:{},..."agentbayContextId"in browser&&browser.agentbayContextId?{agentbayContextId:browser.agentbayContextId}:{},..."agentbayContextName"in browser&&browser.agentbayContextName?{agentbayContextName:browser.agentbayContextName}:{},createdAt:browser.createdAt,..."account"in browser?{account:browser.account}:{},..."copiedCookies"in browser?{copiedCookies:browser.copiedCookies}:{}}));return browsers.push(...disconnected),{count:browsers.length,connectedCount:connected.length,browsers}}function listBrowserInventory(){let managed=[...listManagedBrowsers(),...listAgentBayBrowsers()];return mergeBrowserInventory(listRegisteredBrowsers(),managed)}import fs5 from"node:fs";import path6 from"node:path";import os2 from"node:os";import{randomUUID as randomUUID6}from"node:crypto";var NATIVE_HOST_VERSION="2.9.3";var MEASUREMENT_ID="G-W84LJDZ6PH",API_SECRET="X233siI5RrGYLhlD0kBKEQ",ENDPOINT=`https://www.google-analytics.com/mp/collect?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`,CLIENT_ID_PATTERN=/^\d+\.\d+$/,BUILD_CHANNEL=NATIVE_HOST_VERSION==="unknown"?"development":"production",CONFIG_DIR=path6.join(os2.homedir(),".mearl"),CONFIG_FILE=path6.join(CONFIG_DIR,"config.json");function readConfig(){try{return JSON.parse(fs5.readFileSync(CONFIG_FILE,"utf-8"))}catch{return{}}}function writeConfig(config2){try{fs5.mkdirSync(CONFIG_DIR,{recursive:!0}),fs5.writeFileSync(CONFIG_FILE,JSON.stringify(config2,null,2))}catch{}}var clientId=null;function createClientId(seed=randomUUID6()){let first=2166136261,second=2246822519;for(let index=0;index<seed.length;index++){let code=seed.charCodeAt(index);first=Math.imul(first^code,16777619)>>>0,second=Math.imul(second^code,3266489917)>>>0}return`${first||1}.${second||1}`}function getClientId(){if(clientId)return clientId;let config2=readConfig();return config2.clientId&&CLIENT_ID_PATTERN.test(config2.clientId)?(clientId=config2.clientId,clientId):(clientId=createClientId(config2.clientId),writeConfig({...config2,clientId}),clientId)}function setAnalyticsClientId(value){return typeof value!="string"||!CLIENT_ID_PATTERN.test(value)?!1:(clientId=value,!0)}function classifyAnalyticsError(error48){let message=error48 instanceof Error?error48.message:String(error48);return/timed?\s*out|timeout/i.test(message)?"timeout":/permission|not authorized|access denied|forbidden/i.test(message)?"permission_denied":/not found|no matching|does not exist/i.test(message)?"not_found":/not connected|disconnected|unavailable|connection (?:failed|closed)/i.test(message)?"unavailable":/invalid|required|must be|unsupported/i.test(message)?"invalid_request":"execution_error"}function trackAction(action,params){let payload={client_id:getClientId(),events:[{name:"agent_action",params:{action,...params,mearl_version:NATIVE_HOST_VERSION,runtime:"native_host",build_channel:BUILD_CHANNEL}}]};fetch(ENDPOINT,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(payload),keepalive:!0}).catch(()=>{})}import{open}from"node:fs/promises";import path8 from"node:path";var TRUNCATED_MARKER=`
|
|
912
915
|
… [middle truncated for Native Messaging] …
|
|
913
916
|
`;function truncateUtf82(value,maxBytes){if(Buffer.byteLength(value,"utf8")<=maxBytes)return value;let markerBytes=Buffer.byteLength(TRUNCATED_MARKER,"utf8");if(maxBytes<=markerBytes)return"";let source=Buffer.from(value,"utf8"),contentBytes=maxBytes-markerBytes,headBytes=Math.ceil(contentBytes/2),tailBytes=Math.floor(contentBytes/2);do{let truncated=`${source.subarray(0,headBytes).toString("utf8")}${TRUNCATED_MARKER}${source.subarray(source.length-tailBytes).toString("utf8")}`;if(Buffer.byteLength(truncated,"utf8")<=maxBytes)return truncated;headBytes>=tailBytes?headBytes-=1:tailBytes-=1}while(headBytes>0&&tailBytes>0);return""}function sanitizeValue(value,budget,depth){if(value===null||typeof value=="boolean"||typeof value=="number")return value;if(typeof value=="string"){let available=Math.max(0,budget.remaining),next2=truncateUtf82(value,available),bytes=Buffer.byteLength(next2,"utf8");return budget.remaining=Math.max(0,budget.remaining-bytes),next2!==value&&(budget.truncated=!0),next2}if(typeof value>"u")return null;if(typeof value!="object")return String(value);if(depth>=12||budget.remaining<=0)return budget.truncated=!0,{__transportTruncated:!0};if(budget.seen.has(value))return budget.truncated=!0,"[Circular]";if(budget.seen.add(value),Array.isArray(value)){let next2=value.slice(0,160).map(entry=>sanitizeValue(entry,budget,depth+1));return value.length>160&&(budget.truncated=!0,next2.push({__transportTruncated:!0,originalLength:value.length})),next2}let entries=Object.entries(value),next={};for(let[index,[key,entry]]of entries.entries()){if(index>=160||budget.remaining<=0){budget.truncated=!0;break}budget.remaining=Math.max(0,budget.remaining-Buffer.byteLength(key,"utf8")),next[key]=sanitizeValue(entry,budget,depth+1)}return budget.truncated&&(next.__transportTruncated=!0),next}function sanitizeAgentChatEvent(event){let budget={remaining:409600,truncated:!1,seen:new WeakSet},next={...event,params:sanitizeValue(event.params,budget,0)},bytes=Buffer.byteLength(JSON.stringify(next),"utf8");return bytes<=524288?next:{...event,params:{__transportTruncated:!0,originalBytes:bytes,message:"Agent event exceeded the Native Messaging transport limit."}}}import fs6 from"node:fs";import path7 from"node:path";import{execFile}from"node:child_process";function selectedPath(stdout){return stdout.replace(/[\r\n]+$/,"")||null}var runDirectoryPickerCommand=(command,args)=>new Promise((resolve3,reject)=>{execFile(command,args,{encoding:"utf8",windowsHide:!0},(error48,stdout)=>{if(!error48){resolve3(selectedPath(stdout));return}if(error48.code===1){resolve3(null);return}reject(error48)})});function isMissingCommand(error48){return error48 instanceof Error&&error48.code==="ENOENT"}async function pickWorkspaceDirectory(platform=process.platform,run=runDirectoryPickerCommand){let directory;if(platform==="darwin")directory=await run("osascript",["-e",'POSIX path of (choose folder with prompt "Select a workspace for Agent Chat")']);else if(platform==="win32"){let script=["Add-Type -AssemblyName System.Windows.Forms;","$dialog = New-Object System.Windows.Forms.FolderBrowserDialog;","$dialog.Description = 'Select a workspace for Agent Chat';","if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {","[Console]::OutputEncoding = [System.Text.Encoding]::UTF8;","Write-Output $dialog.SelectedPath;","}"].join(" ");directory=await run("powershell.exe",["-NoProfile","-STA","-Command",script])}else if(platform==="linux")try{directory=await run("zenity",["--file-selection","--directory","--title=Select a workspace for Agent Chat"])}catch(error48){if(!isMissingCommand(error48))throw error48;try{directory=await run("kdialog",["--getexistingdirectory",".","--title","Select a workspace for Agent Chat"])}catch(fallbackError){throw isMissingCommand(fallbackError)?new Error("Install zenity or kdialog to select an Agent Chat workspace",{cause:fallbackError}):fallbackError}}else throw new Error(`Directory selection is not supported on ${platform}`);return directory?resolveWorkspaceDirectory(directory):null}function resolveWorkspaceDirectory(directory){if(typeof directory!="string"||!directory)throw new Error("Workspace directory is required");if(!path7.isAbsolute(directory))throw new Error("Workspace directory must be an absolute path");let resolved;try{resolved=fs6.realpathSync.native(directory)}catch(error48){throw new Error(`Workspace directory does not exist: ${directory}`,{cause:error48})}if(!fs6.statSync(resolved).isDirectory())throw new Error(`Workspace path is not a directory: ${directory}`);return resolved}var MAX_REPLAY_EVENTS=1e3,MAX_REPLAY_BYTES=2048*1024,MAX_REPLAY_PAGE_BYTES=524288,MAX_SKILL_FILE_BYTES=1024*1024,SUPPORTED_IMAGE_MIME_TYPES=new Set(AGENT_CHAT_SUPPORTED_IMAGE_MIME_TYPES),REPLAY_SNAPSHOT_METHODS=new Set(["thread/settings/updated"]);function createAgentDeveloperInstructions({cwd,tabId,initialPageUrl,initialPageTitle}){return[...cwd?[createAgentDirectoryContextInstructions(cwd)]:[],...tabId!==void 0?[createBrowserAgentDeveloperInstructions(tabId,{...initialPageUrl?{url:initialPageUrl}:{},...initialPageTitle?{title:initialPageTitle}:{}})]:[]].join(`
|
|
914
917
|
|