@mearl/native-host 2.20.0 → 2.20.1

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.
Files changed (2) hide show
  1. package/dist/index.js +39 -31
  2. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -79,7 +79,7 @@ ${SOURCE_BADGES[source]}
79
79
  <circle cx="104" cy="104" r="21" fill="#16A34A" stroke="#FFFFFF" stroke-width="6"/>
80
80
  `,remote:`
81
81
  <circle cx="104" cy="104" r="21" fill="#FF7A00" stroke="#FFFFFF" stroke-width="6"/>
82
- `}}});function getJsonpCallback(url2){try{let searchParams=new URL(url2).searchParams,callback=searchParams.get("callback")??searchParams.get("jsonp");return callback&&JSONP_CALLBACK_RE.test(callback)?callback:null}catch{return null}}function serializeMockResponse(requestUrl,responseData){let callback=getJsonpCallback(requestUrl);if(!callback)return{body:typeof responseData=="string"?responseData:JSON.stringify(responseData)??"null",isJsonp:!1};let json2=JSON.stringify(responseData)??"null";if(typeof responseData=="string")try{JSON.parse(responseData),json2=responseData}catch{}return{body:`${callback}(${json2});`,isJsonp:!0}}function prepareMockResponseHeaders(headers,isJsonp){let stripped=(headers??[]).filter(header=>!["content-encoding","content-length"].includes(header.name.toLowerCase()));if(!isJsonp)return stripped;let index=stripped.findIndex(header=>header.name.toLowerCase()==="content-type");if(index===-1)return[...stripped,{name:"content-type",value:JSONP_CONTENT_TYPE}];let result=[...stripped];return result[index]={...result[index],value:JSONP_CONTENT_TYPE},result}var JSONP_CALLBACK_RE,JSONP_CONTENT_TYPE,init_mockResponse=__esm({"../browser-core/dist/mockResponse.js"(){"use strict";JSONP_CALLBACK_RE=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/,JSONP_CONTENT_TYPE="application/javascript; charset=utf-8"}});var init_dist=__esm({"../browser-core/dist/index.js"(){"use strict";init_types();init_tdbankLogin();init_mtopSigner();init_mtopRequest();init_mtopStreamCapture();init_appProfileUserInfo();init_eventParsers();init_eventFilters();init_requestSerializer();init_boundedRequestBuffer();init_proxyPermissions();init_domTyping();init_domSelectors();init_domScrolling();init_domInspection();init_domSnapshot();init_deviceEmulation();init_axTextMatch();init_domClicking();init_pageDragging();init_pagePressing();init_axSnapshot();init_pageObserver();init_navigationTracker();init_pageAct();init_backendNodeRefs();init_pageEffectRefs();init_pageWait();init_pageNavigation();init_tabMatching();init_agentChat();init_agentSkills();init_agentServiceProtocol();init_toolbox();init_browserActionProtocol();init_runActions();init_sendRequestFiles();init_sendRequestHeaders();init_cookie();init_controlledFavicon();init_capture();init_sseParser();init_mockResponse()}});import{randomUUID}from"node:crypto";var BROWSER_QUEUE,ControlSessionRegistry,init_control_session=__esm({"src/control-session.ts"(){"use strict";init_dist();BROWSER_QUEUE=-1,ControlSessionRegistry=class{constructor(browserId){this.browserId=browserId}sessions=new Map;owners=new Map;queues=new Map;pending=new Map;browserReleasing=!1;resuming=new Set;create(transport){if(this.browserReleasing)throw new Error("BROWSER_CONTROL_RELEASING");let record2={sessionId:`cs_${randomUUID()}`,browserId:this.browserId(),transport,status:"active",tabs:[],generation:1};return this.sessions.set(record2.sessionId,record2),this.info(record2.sessionId)}info(id){let record2=this.require(id);return{...record2,tabs:record2.tabs.map(tab=>({...tab}))}}list(){return[...this.sessions.values()].filter(record2=>record2.status!=="released").map(record2=>this.info(record2.sessionId))}require(id){let record2=this.sessions.get(id);if(!record2||record2.browserId!==this.browserId())throw new Error("CONTROL_SESSION_NOT_FOUND");return record2}assertActive(id,generation){let record2=this.require(id);if(record2.status!=="active"||generation!==void 0&&generation!==record2.generation)throw new Error(`CONTROL_SESSION_PAUSED: ${record2.status}; inspect the page after the user returns control`);return record2}claim(id,tabId,source){let record2=this.require(id),owner=this.owners.get(tabId);if(owner&&owner!==id)throw new Error("TAB_CONTROLLED_BY_SESSION");record2.tabs.some(tab=>tab.tabId===tabId)||record2.tabs.push({tabId,source}),this.owners.set(tabId,id)}blockedTabs(id){return[...this.owners].filter(([,owner])=>owner!==id).map(([tab])=>tab)}assertBrowserRelease(){if(this.list().length)throw new Error("ACTIVE_CONTROL_SESSIONS: release the owning session first")}async releaseBrowser(operation){if(this.assertBrowserRelease(),this.browserReleasing)throw new Error("BROWSER_CONTROL_RELEASING");this.browserReleasing=!0;try{return await Promise.all([...this.queues.values()]),await operation()}finally{this.browserReleasing=!1}}async run(id,action,data,operation,transport="extension"){if(this.browserReleasing)throw new Error("BROWSER_CONTROL_RELEASING");let generation=id?this.assertActive(id).generation:void 0,tabs=new Set;typeof data.tabId=="number"&&tabs.add(data.tabId);for(let tab of data.tabIds??[])typeof tab=="number"&&tabs.add(tab);typeof data.openerTabId=="number"&&tabs.add(data.openerTabId);let steps=action==="run_actions"?data.actions:[{action,data}];if(action==="run_actions"){validateActionBatch(data);for(let step of data.actions??[]){typeof step.data?.tabId=="number"&&tabs.add(step.data.tabId);for(let tab of step.data?.tabIds??[])typeof tab=="number"&&tabs.add(tab);typeof step.data?.openerTabId=="number"&&tabs.add(step.data.openerTabId)}}let opensPage=steps.some(step=>step.action==="tab_open"),sharedResources=steps.some(step=>["set_rule","set_cookie","send_request","send_mtop_request"].includes(step.action)||step.action==="set_app_profile"&&transport!=="cdp"&&step.data?.mtopEnv!==void 0),assertSharedResources=()=>{if(action==="run_actions"&&!id&&this.list().length&&steps.some(step=>["tab_open","browser_close"].includes(step.action)))throw new Error("ACTIVE_CONTROL_SESSIONS: open pages outside run_actions while sessions are active");if(sharedResources&&this.list().some(record2=>record2.sessionId!==id))throw new Error("BROWSER_RESOURCE_CONFLICT: use an isolated browser for shared settings or requests");if(data.closeExisting&&!id&&this.list().length)throw new Error("ACTIVE_CONTROL_SESSIONS")};assertSharedResources();for(let tab of tabs){if(tab<0)continue;let owner=this.owners.get(tab);if(owner&&owner!==id)throw new Error("TAB_CONTROLLED_BY_SESSION")}let unlock,tail=new Promise(resolve9=>{unlock=resolve9}),predecessors=[...tabs].map(tab=>this.queues.get(tab)).filter(Boolean);this.queues.has(BROWSER_QUEUE)&&predecessors.push(this.queues.get(BROWSER_QUEUE)),(sharedResources||action==="page_download"||opensPage)&&(predecessors.push(...this.queues.values()),tabs.add(BROWSER_QUEUE));for(let tab of tabs)this.queues.set(tab,tail);let promise2=(async()=>{try{await Promise.all(predecessors),id&&this.assertActive(id,generation),assertSharedResources();for(let tab of tabs){let owner=this.owners.get(tab);if(owner&&owner!==id)throw new Error("TAB_CONTROLLED_BY_SESSION");id&&tab>=0&&this.claim(id,tab,"attached")}return await operation()}finally{unlock();for(let tab of tabs)this.queues.get(tab)===tail&&this.queues.delete(tab)}})();if(id){let pending=this.pending.get(id)??new Set;pending.add(promise2),this.pending.set(id,pending);try{return await promise2}finally{pending.delete(promise2),pending.size||this.pending.delete(id)}}return promise2}async waitForIdle(id){await Promise.allSettled([...this.pending.get(id)??[]])}assertStep(id,generation){this.assertActive(id,generation)}recordResult(id,action,result,data){action==="tab_open"&&typeof result?.tabId=="number"&&this.claim(id,result.tabId,result.opened===!0?"created":"attached");for(let tab of result?.observation?.openedTabs??[])typeof tab.tabId=="number"&&this.claim(id,tab.tabId,"created");let target=this.require(id).tabs.find(tab=>tab.tabId===(result?.tabId??data?.tabId));if(target&&typeof result?.title=="string"&&(target.title=result.title),target&&typeof result?.url=="string"&&(target.url=result.url),action==="tab_close"&&typeof data?.tabId=="number"&&(this.owners.delete(data.tabId),this.require(id).tabs=this.require(id).tabs.filter(tab=>tab.tabId!==data.tabId)),action==="tab_close")for(let tab of this.require(id).tabs)(result?.closedTabIds??[]).includes(tab.tabId)&&this.owners.delete(tab.tabId)}handoff(id,reason){let record2=this.assertActive(id);return record2.status="user",record2.generation+=1,record2.reason=reason,this.info(id)}async resume(id,cleanup=async()=>{}){let record2=this.require(id);if(record2.status!=="user")throw new Error("Session is not waiting for the user");if(this.resuming.has(id))throw new Error("CONTROL_SESSION_RESUMING");this.resuming.add(id);try{return await this.waitForIdle(id),await cleanup(),record2.status="active",record2.reason=void 0,record2.generation+=1,this.info(id)}finally{this.resuming.delete(id)}}async release(id,params,cleanup){let record2=this.require(id);if(this.resuming.has(id))throw new Error("CONTROL_SESSION_RESUMING");if(record2.status==="released")return this.info(id);if(record2.status==="releasing")throw new Error("CONTROL_SESSION_RELEASING");let previous=record2.status;record2.status="releasing",record2.generation+=1,await Promise.allSettled([...this.pending.get(id)??[]]);let tabs=record2.tabs.map(tab=>tab.tabId),keep=new Set(params.keepTabIds??[]),close=params.closeCreatedTabs?record2.tabs.filter(tab=>tab.source==="created"&&!keep.has(tab.tabId)).map(tab=>tab.tabId):[];try{await cleanup(tabs,close);for(let tab of tabs)this.owners.get(tab)===id&&this.owners.delete(tab);record2.status="released";let released=[...this.sessions.values()].filter(session=>session.status==="released"&&session.sessionId!==id);for(let old of released.slice(0,Math.max(0,released.length-99)))this.sessions.delete(old.sessionId)}catch(error48){throw record2.status=previous,error48}return this.info(id)}}}});import{rmSync}from"node:fs";import{randomUUID as randomUUID2}from"node:crypto";import{mkdir,open,rm,stat,writeFile}from"node:fs/promises";import path from"node:path";import os from"node:os";var MAX_BYTES,ARTIFACT_CHUNK_BYTES,BrowserArtifactStore,init_browser_artifacts=__esm({"src/browser-artifacts.ts"(){"use strict";MAX_BYTES=256*1024*1024,ARTIFACT_CHUNK_BYTES=256*1024,BrowserArtifactStore=class{constructor(root=path.join(os.tmpdir(),`mearl-artifacts-${process.pid}-${randomUUID2()}`)){this.root=root}files=new Map;directory;sweeper;async create(filename,sessionId){if(typeof filename!="string"||!filename||[".",".."].includes(filename)||/[\\/]/.test(filename)||filename.length>255)throw new Error("Invalid artifact filename");this.sweeper||(this.sweeper=setInterval(()=>{for(let[id,file3]of this.files)!file3.sessionId&&!file3.writing&&Date.now()-file3.accessedAt>3600*1e3&&this.remove(id).catch(()=>{})},6e4),this.sweeper.unref()),await mkdir(this.root,{recursive:!0,mode:448}),this.directory=this.root;let artifactId=randomUUID2(),directory=path.join(this.root,artifactId);await mkdir(directory,{mode:448});let file2={artifactId,filename,bytes:0,location:"browser",path:path.join(directory,filename),sessionId,ready:!1,accessedAt:Date.now()};return await writeFile(file2.path,"",{mode:384}),this.files.set(artifactId,file2),this.info(file2)}async importFile(filename,sourcePath,sessionId){let source=await open(sourcePath,"r"),id;try{let metadata=await source.stat();if(!metadata.isFile()||metadata.size>MAX_BYTES)throw new Error("Download is unavailable or exceeds 256 MiB");id=(await this.create(filename,sessionId)).artifactId;let file2=this.require(id,sessionId),target=await open(file2.path,"w"),copied=0;try{for await(let chunk of source.createReadStream({autoClose:!1})){if(copied+=chunk.length,copied>MAX_BYTES)throw new Error("Download exceeds 256 MiB");let written=0;for(;written<chunk.length;){let result=await target.write(chunk,written,chunk.length-written);if(!result.bytesWritten)throw new Error("Download import made no progress");written+=result.bytesWritten}}}finally{await target.close()}if(copied!==metadata.size)throw new Error("Download changed during import");return file2.bytes=(await stat(file2.path)).size,file2.ready=!0,this.info(file2)}catch(error48){throw id&&await this.remove(id,sessionId),error48}finally{await source.close()}}require(id,sessionId){let file2=this.files.get(id);if(!file2||file2.sessionId!==void 0&&file2.sessionId!==sessionId)throw new Error("ARTIFACT_NOT_FOUND");return file2.accessedAt=Date.now(),file2}info(file2){return{artifactId:file2.artifactId,filename:file2.filename,bytes:file2.bytes,location:"browser"}}async write(id,offset,base643,sessionId){let file2=this.require(id,sessionId);if(file2.ready||file2.writing||offset!==file2.bytes)throw new Error("Invalid artifact write offset or completed transfer");if(typeof base643!="string"||base643.length>Math.ceil(ARTIFACT_CHUNK_BYTES/3)*4||base643.length%4!==0||!/^[A-Za-z0-9+/]*={0,2}$/.test(base643))throw new Error("Invalid artifact chunk");let chunk=Buffer.from(base643,"base64");if(chunk.toString("base64")!==base643)throw new Error("Invalid artifact chunk");if(file2.bytes+chunk.length>MAX_BYTES)throw new Error("Artifact exceeds 256 MiB");file2.writing=!0;try{let handle=await open(file2.path,"r+");try{let written=0;for(;written<chunk.length;){let result=await handle.write(chunk,written,chunk.length-written,offset+written);if(!result.bytesWritten)throw new Error("Artifact write made no progress");written+=result.bytesWritten}}finally{await handle.close()}return file2.bytes+=chunk.length,this.info(file2)}finally{file2.writing=!1}}complete(id,bytes,sessionId){let file2=this.require(id,sessionId);if(file2.writing||bytes!==file2.bytes)throw new Error("Artifact size mismatch");return file2.ready=!0,this.info(file2)}resolve(id,sessionId){let file2=this.require(id,sessionId);if(!file2.ready)throw new Error("Artifact is not ready");return file2.path}async read(id,offset,sessionId){let file2=this.require(id,sessionId);if(!file2.ready||!Number.isSafeInteger(offset)||offset<0||offset>file2.bytes)throw new Error("Invalid artifact read");let handle=await open(file2.path,"r");try{let buffer=Buffer.alloc(Math.min(ARTIFACT_CHUNK_BYTES,file2.bytes-offset)),result=await handle.read(buffer,0,buffer.length,offset);return{base64:buffer.subarray(0,result.bytesRead).toString("base64"),bytes:result.bytesRead,totalBytes:file2.bytes}}finally{await handle.close()}}async remove(id,sessionId){let file2=this.require(id,sessionId);await rm(path.dirname(file2.path),{recursive:!0,force:!0}),this.files.delete(id)}async release(sessionId,keep=[]){let retain=new Set(keep);for(let[id,file2]of this.files)file2.sessionId===sessionId&&(retain.has(id)?(file2.sessionId=void 0,file2.accessedAt=Date.now()):await this.remove(id,sessionId))}disposeSync(){this.sweeper&&clearInterval(this.sweeper),this.directory&&rmSync(this.directory,{recursive:!0,force:!0}),this.files.clear()}async dispose(){this.sweeper&&clearInterval(this.sweeper),this.directory&&await rm(this.directory,{recursive:!0,force:!0}),this.files.clear()}}}});var ControlSessionManager,init_control_session_manager=__esm({"src/control-session-manager.ts"(){"use strict";init_dist();init_control_session();init_browser_artifacts();ControlSessionManager=class{constructor(dependencies){this.dependencies=dependencies;this.registry=new ControlSessionRegistry(dependencies.browserId)}registry;artifacts=new BrowserArtifactStore;async closeTabs(tabs,transport,sessionId){for(let tabId of tabs)try{let result=await this.dependencies.invoke("tab_close",{tabId},transport);this.registry.recordResult(sessionId,"tab_close",result,{tabId})}catch(error48){let current=await this.dependencies.invoke("tab_list",{},transport);if(!Array.isArray(current.tabs)||current.tabs.some(tab=>(tab.tabId??tab.id)===tabId))throw error48;this.registry.recordResult(sessionId,"tab_close",{},{tabId})}}async userControl(id,operation){if(operation==="release")return await this.invoke("browser_release",{},id),this.registry.info(id);let current=this.registry.info(id),info=operation==="resume"?await this.registry.resume(id,()=>this.dependencies.cleanup(current.tabs.map(tab=>tab.tabId),current.transport,!0)):this.registry.handoff(id);return this.dependencies.notify(),info}async invoke(action,data,sessionId,requestedTransport,origin="local"){if(data&&(Object.keys(data).some(key=>key.startsWith("__mearl"))||(data.actions??[]).some(step=>Object.keys(step.data??{}).some(key=>key.startsWith("__mearl")))))throw new Error("Internal session fields are reserved");validateRequiredActionTabId(action,data);let created=sessionId==="new";if(sessionId==="new"){if(!["tab_open","page_snapshot","page_screenshot"].includes(action))throw new Error("A new session requires tab_open, page_snapshot or page_screenshot");sessionId=this.registry.create(requestedTransport??this.dependencies.transport()).sessionId}let info=sessionId?this.registry.info(sessionId):void 0,transport=info?.transport??requestedTransport??this.dependencies.transport();if(requestedTransport&&transport!==requestedTransport)throw new Error("A session cannot change transport");if(action==="browser_control"){if(!sessionId||!["handoff","resume"].includes(data.operation))throw new Error("browser_control requires --session and handoff/resume");if(data.operation==="resume")return{session:await this.userControl(sessionId,"resume")};if(data.tabId!==void 0&&!info.tabs.some(tab=>tab.tabId===data.tabId))throw new Error("TAB_NOT_IN_CONTROL_SESSION");let session=this.registry.handoff(sessionId,data.reason);return this.dependencies.notify(),{session}}if(action==="browser_release"&&sessionId){let params=data,session=await this.registry.release(sessionId,params,async(tabs,close)=>{await this.dependencies.cleanup(tabs,transport,params.preserveEnvironment!==!1),await this.closeTabs(close,transport,sessionId),await this.artifacts.release(sessionId,params.keepArtifactIds)});return this.dependencies.notify(),{released:!0,hadActiveControl:!0,transports:[transport],affectedTabIds:info.tabs.map(tab=>tab.tabId),session}}if((action==="browser_release"||action==="browser_close")&&this.registry.assertBrowserRelease(),(action==="browser_release"||action==="browser_close")&&!sessionId)return this.registry.releaseBrowser(()=>this.dependencies.invoke(action,data,transport));let invokeStep=async(name,payload,batch=!1)=>{if(name==="tab_open"&&(sessionId&&payload.closeExisting&&(await this.closeTabs(this.registry.info(sessionId).tabs.filter(tab=>tab.source==="created").map(tab=>tab.tabId),transport,sessionId),payload={...payload,closeExisting:!1}),payload={...payload,__mearlBlockedTabIds:this.registry.blockedTabs(sessionId)}),name==="page_upload"&&payload.files){if(payload.filePaths)throw new Error("Use files or filePaths, not both");payload={...payload,filePaths:payload.files.map(file2=>this.artifacts.resolve(file2.artifactId,sessionId))},delete payload.files}if(batch){if(transport==="provider"){let result4=await this.dependencies.invoke(name,{...payload,__mearlControlSource:origin},transport);return sessionId&&this.registry.recordResult(sessionId,name,result4,payload),result4?.action?.success===!1?{...result4.action,success:!1}:result4?.success===!1?{...result4,success:!1}:{success:!0,data:result4}}let result3=await this.dependencies.invoke("run_actions",{tabId:payload.tabId,actions:[{action:name,data:payload}],__mearlControlSource:origin},transport),outcome=result3.results?.[0]??{success:!1,error:result3.error??"Batch step returned no result",stage:result3.stage,attempt:result3.attempt};return sessionId&&outcome.success&&this.registry.recordResult(sessionId,name,outcome.data,payload),outcome}let result2=await this.dependencies.invoke(name,{...payload,__mearlControlSource:origin},transport);return sessionId&&this.registry.recordResult(sessionId,name,result2,payload),result2},result;try{result=await this.registry.run(sessionId,action,data,async()=>{if(transport==="extension"&&this.dependencies.transport()!=="extension")throw new Error("CONTROL_SESSION_TRANSPORT_UNAVAILABLE: extension is disconnected");if(action.startsWith("__artifact_")){let store=this.artifacts;switch(action){case"__artifact_init":return{artifact:await store.create(data.filename,sessionId),browserId:this.dependencies.browserId()};case"__artifact_write":return store.write(data.artifactId,data.offset,data.base64,sessionId);case"__artifact_complete":return store.complete(data.artifactId,data.bytes,sessionId);case"__artifact_read":return store.read(data.artifactId,data.offset,sessionId);case"__artifact_remove":return await store.remove(data.artifactId,sessionId),{removed:!0};default:throw new Error("Unknown artifact operation")}}if(action==="page_download"){let downloaded=await this.dependencies.download(data,transport,origin);try{return sessionId&&this.registry.recordResult(sessionId,"page_click",downloaded.action,data),{download:{...await this.artifacts.importFile(downloaded.filename,downloaded.filePath,sessionId),browserId:this.dependencies.browserId()},action:downloaded.action}}finally{if(downloaded.owned){let{rm:rm4,rmdir:rmdir2}=await import("node:fs/promises");await rm4(downloaded.filePath,{force:!0}),downloaded.directory&&await rmdir2(downloaded.directory).catch(()=>{})}}}return action==="run_actions"&&sessionId?runActionBatch(data,(name,payload)=>invokeStep(name,payload,!0),{beforeStep:()=>this.registry.assertStep(sessionId,info.generation)}):invokeStep(action,data)},transport)}catch(error48){throw created&&sessionId&&await this.registry.release(sessionId,{},async()=>{await this.artifacts.release(sessionId)}),this.dependencies.notify(),error48}if(sessionId&&action==="tab_list"&&Array.isArray(result.tabs)){let blocked=new Set(this.registry.blockedTabs(sessionId));result={...result,tabs:result.tabs.filter(tab=>!blocked.has(tab.tabId??tab.id))},result.count=result.tabs.length}return sessionId?(this.dependencies.notify(),{...result,session:this.registry.info(sessionId)}):result}}}});function isAlive(pid){if(!pid||pid<=0)return!1;try{return process.kill(pid,0),!0}catch(error48){return error48.code==="EPERM"}}var init_process=__esm({"../daemon-core/dist/process.js"(){"use strict"}});import{join}from"node:path";import{homedir}from"node:os";import{createHash}from"node:crypto";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`)}var DAEMON_HOME,init_paths=__esm({"../daemon-core/dist/paths.js"(){"use strict";DAEMON_HOME=join(homedir(),".mearl")}});import{closeSync,existsSync,linkSync,openSync,statSync,mkdirSync,readFileSync,writeFileSync,renameSync,rmSync as rmSync2,readdirSync}from"node:fs";import{dirname,join as join2}from"node:path";import{randomUUID as randomUUID3}from"node:crypto";function ensureDir(dir){existsSync(dir)||mkdirSync(dir,{recursive:!0,mode:448})}function pauseForLock(){Atomics.wait(lockWaitBuffer,0,0,LOCK_WAIT_MS)}function readRecordUnlocked(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 removeRecordUnlocked(file2){rmSync2(file2,{force:!0})}function writeRecordUnlocked(file2,record2){let tmp=`${file2}.${process.pid}.${randomUUID3()}.tmp`;try{writeFileSync(tmp,JSON.stringify(record2),{mode:384}),renameSync(tmp,file2)}catch(error48){try{rmSync2(tmp,{force:!0})}catch{}throw error48}}function removeStaleLock(lockDir){let ownerFile=join2(lockDir,"owner.json"),owner=readRecordUnlocked(ownerFile);if(owner){if(isAlive(owner.pid))return!1}else try{if(Date.now()-statSync(lockDir).mtimeMs<OWNER_WRITE_GRACE_MS)return!1}catch{return!0}try{return rmSync2(lockDir,{recursive:!0,force:!0}),!0}catch{return!1}}function withRecordLock(file2,operation){ensureDir(dirname(file2));let lockDir=`${file2}.registry.lock`,ownerFile=join2(lockDir,"owner.json"),token=randomUUID3(),deadline=Date.now()+LOCK_TIMEOUT_MS;for(;;){try{mkdirSync(lockDir,{mode:448})}catch(error48){if(error48.code!=="EEXIST")throw error48;if(!removeStaleLock(lockDir)){if(Date.now()>=deadline)throw new Error(`Timed out waiting for registry lock: ${file2}`,{cause:error48});pauseForLock()}continue}let ownerFd=null;try{ownerFd=openSync(ownerFile,"wx",384),writeFileSync(ownerFd,JSON.stringify({pid:process.pid,token}))}catch(error48){if(ownerFd!==null&&closeSync(ownerFd),ownerFd=null,error48.code==="EEXIST"){if(Date.now()>=deadline)throw new Error(`Timed out acquiring registry lock: ${file2}`,{cause:error48});pauseForLock();continue}throw error48}finally{ownerFd!==null&&closeSync(ownerFd)}try{return operation()}finally{readRecordUnlocked(ownerFile)?.token===token&&rmSync2(lockDir,{recursive:!0,force:!0})}}}function writeRecord(file2,record2){withRecordLock(file2,()=>writeRecordUnlocked(file2,record2))}function claimRecord(file2,record2){return withRecordLock(file2,()=>{let candidate=`${file2}.${process.pid}.${randomUUID3()}.claim`;try{return writeFileSync(candidate,JSON.stringify(record2),{mode:384}),linkSync(candidate,file2),!0}catch(error48){if(error48.code==="EEXIST")return!1;throw error48}finally{rmSync2(candidate,{force:!0})}})}function readRecord(file2){return readRecordUnlocked(file2)}function removeRecord(file2){try{withRecordLock(file2,()=>removeRecordUnlocked(file2))}catch{}}function removeRecordIfPid(file2,pid){try{return withRecordLock(file2,()=>readRecordUnlocked(file2)?.pid!==pid?!1:(removeRecordUnlocked(file2),!0))}catch{return!1}}function writeRecordIfPid(file2,pid,record2){return withRecordLock(file2,()=>readRecordUnlocked(file2)?.pid!==pid?!1:(writeRecordUnlocked(file2,record2),!0))}function removeInvalidRecord(file2){try{return withRecordLock(file2,()=>!existsSync(file2)||readRecordUnlocked(file2)?!1:(removeRecordUnlocked(file2),!0))}catch{return!1}}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):rec?removeRecordIfPid(file2,rec.pid):removeInvalidRecord(file2)}return out}var LOCK_WAIT_MS,LOCK_TIMEOUT_MS,OWNER_WRITE_GRACE_MS,lockWaitBuffer,init_registry=__esm({"../daemon-core/dist/registry.js"(){"use strict";init_process();LOCK_WAIT_MS=10,LOCK_TIMEOUT_MS=5e3,OWNER_WRITE_GRACE_MS=1e3,lockWaitBuffer=new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))}});import{existsSync as existsSync2,statSync as statSync2,renameSync as renameSync2,readFileSync as readFileSync2}from"node:fs";function rotateLogIfNeeded(logFile,maxBytes=DEFAULT_MAX_LOG_BYTES){try{if(!existsSync2(logFile)||statSync2(logFile).size<maxBytes)return;renameSync2(logFile,`${logFile}.1`)}catch{}}var DEFAULT_MAX_LOG_BYTES,init_log=__esm({"../daemon-core/dist/log.js"(){"use strict";DEFAULT_MAX_LOG_BYTES=5*1024*1024}});import{spawn}from"node:child_process";import{closeSync as closeSync2,openSync as openSync2}from"node:fs";import{dirname as dirname2}from"node:path";var init_daemon=__esm({"../daemon-core/dist/daemon.js"(){"use strict";init_process();init_registry();init_log()}});var init_dist2=__esm({"../daemon-core/dist/index.js"(){"use strict";init_process();init_paths();init_registry();init_log();init_daemon()}});var init_types2=__esm({"../provider/dist/types.js"(){"use strict"}});function isProviderAction(value){return typeof value=="string"&&providerActionSet.has(value)}var PROVIDER_ACTIONS,providerActionSet,init_generated_provider_actions=__esm({"../provider/dist/generated-provider-actions.js"(){"use strict";PROVIDER_ACTIONS=["tab_checkpoint","capture_checkpoint","get_requests","get_logs","get_events","set_mock","get_mocks","set_rule","get_rules","send_request","send_mtop_request","browser_release","page_screenshot","tab_open","tab_close","tab_list","tab_group","page_click","page_drag","page_type","page_scroll","page_hover","page_eval","page_inspect","page_snapshot","page_press","page_wait","page_navigate","page_upload","page_frames","set_device_emulation","set_app_profile","set_timezone","get_cookie","set_cookie","request_domain_permission","run_actions","page_download"],providerActionSet=new Set(PROVIDER_ACTIONS)}});function isJsonValue(value,depth=0){return depth>32?!1:value===null||["string","boolean"].includes(typeof value)?!0:typeof value=="number"?Number.isFinite(value):Array.isArray(value)?value.every(item=>isJsonValue(item,depth+1)):typeof value=="object"&&Object.values(value).every(item=>isJsonValue(item,depth+1))}function isOptionalString(value){return value===void 0||typeof value=="string"}function isOptionalFiniteNumber(value){return value===void 0||typeof value=="number"&&Number.isFinite(value)}function isOptionalCount(value){return value===void 0||Number.isInteger(value)&&Number(value)>=0}function isProviderInputSchema(value,depth=0){if(!value||typeof value!="object"||Array.isArray(value)||depth>32)return!1;let schema=value;if(!isOptionalString(schema.title)||!isOptionalString(schema.description)||schema.component!==void 0&&!["cookie-sync","switch"].includes(String(schema.component))||schema.default!==void 0&&!isJsonValue(schema.default)||schema.formDefault!==void 0&&!isJsonValue(schema.formDefault)||schema.formHidden!==void 0&&typeof schema.formHidden!="boolean"||schema.formWidth!==void 0&&!["half","full"].includes(String(schema.formWidth))||schema.formHideOptional!==void 0&&typeof schema.formHideOptional!="boolean"||schema.formVisibleWhen!==void 0&&(!schema.formVisibleWhen||typeof schema.formVisibleWhen!="object"||Array.isArray(schema.formVisibleWhen)||typeof schema.formVisibleWhen.field!="string"||!schema.formVisibleWhen.field||typeof schema.formVisibleWhen.empty!="boolean"))return!1;if(schema.type==="string"){let validPattern=!0;if(schema.pattern!==void 0)try{new RegExp(String(schema.pattern))}catch{validPattern=!1}if(!((schema.enum===void 0||Array.isArray(schema.enum)&&schema.enum.every(item=>typeof item=="string"))&&(schema.secret===void 0||typeof schema.secret=="boolean")&&isOptionalCount(schema.minLength)&&isOptionalCount(schema.maxLength)&&(schema.minLength===void 0||schema.maxLength===void 0||Number(schema.minLength)<=Number(schema.maxLength))&&isOptionalString(schema.pattern)&&validPattern&&isOptionalString(schema.placeholder)))return!1}else if(schema.type==="number"){if(!((schema.integer===void 0||typeof schema.integer=="boolean")&&isOptionalFiniteNumber(schema.minimum)&&isOptionalFiniteNumber(schema.maximum)&&(schema.minimum===void 0||schema.maximum===void 0||Number(schema.minimum)<=Number(schema.maximum))))return!1}else if(schema.type!=="boolean")if(schema.type==="array"){if(!isProviderInputSchema(schema.items,depth+1)||!isOptionalCount(schema.minItems)||!isOptionalCount(schema.maxItems)||schema.minItems!==void 0&&schema.maxItems!==void 0&&Number(schema.minItems)>Number(schema.maxItems))return!1}else{if(schema.type!=="object"||!schema.properties||typeof schema.properties!="object"||Array.isArray(schema.properties)||schema.additionalProperties!==void 0&&typeof schema.additionalProperties!="boolean")return!1;let properties=schema.properties;if(!Object.values(properties).every(item=>isProviderInputSchema(item,depth+1))||Object.values(properties).some(item=>{let condition=item.formVisibleWhen;return condition!==void 0&&!(String(condition.field)in properties)})||schema.not!==void 0&&(!isProviderInputSchema(schema.not,depth+1)||schema.not.type!=="object")||schema.oneOf!==void 0&&(!Array.isArray(schema.oneOf)||schema.oneOf.length===0||schema.oneOf.some(branch=>!isProviderInputSchema(branch,depth+1)||branch.type!=="object"))||schema.required!==void 0&&(!Array.isArray(schema.required)||schema.required.some(item=>typeof item!="string"||!(item in properties))||new Set(schema.required).size!==schema.required.length))return!1}if(schema.component==="cookie-sync"&&schema.type!=="object"||schema.component==="switch"&&schema.type!=="boolean")return!1;if(schema.default!==void 0)try{validateSchemaValue(value,schema.default,"default")}catch{return!1}if(schema.formDefault!==void 0)try{validateSchemaValue(value,schema.formDefault,"formDefault")}catch{return!1}return!0}function fail(path25,message){throw new Error(`${path25} ${message}`)}function validateSchemaValue(schema,value,path25){if(schema.type==="string"){typeof value!="string"&&fail(path25,"must be a string"),schema.enum&&!schema.enum.includes(value)&&fail(path25,"has an unsupported value"),schema.minLength!==void 0&&value.length<schema.minLength&&fail(path25,`must contain at least ${schema.minLength} characters`),schema.maxLength!==void 0&&value.length>schema.maxLength&&fail(path25,`must contain at most ${schema.maxLength} characters`),schema.pattern!==void 0&&!new RegExp(schema.pattern).test(value)&&fail(path25,"has an invalid format");return}if(schema.type==="number"){(typeof value!="number"||!Number.isFinite(value))&&fail(path25,"must be a number"),schema.integer&&!Number.isInteger(value)&&fail(path25,"must be an integer"),schema.minimum!==void 0&&value<schema.minimum&&fail(path25,`must be at least ${schema.minimum}`),schema.maximum!==void 0&&value>schema.maximum&&fail(path25,`must be at most ${schema.maximum}`);return}if(schema.type==="boolean"){typeof value!="boolean"&&fail(path25,"must be a boolean");return}if(schema.type==="array"){Array.isArray(value)||fail(path25,"must be an array"),schema.minItems!==void 0&&value.length<schema.minItems&&fail(path25,`must contain at least ${schema.minItems} items`),schema.maxItems!==void 0&&value.length>schema.maxItems&&fail(path25,`must contain at most ${schema.maxItems} items`),value.forEach((item,index)=>validateSchemaValue(schema.items,item,`${path25}[${index}]`));return}validateObject(schema,value,path25)}function validateObject(schema,value,path25){(!value||typeof value!="object"||Array.isArray(value))&&fail(path25,"must be an object");let input2=value;for(let key of schema.required??[])input2[key]===void 0&&fail(`${path25}.${key}`,"is required");if(schema.not){let matches=!1;try{validateObject(schema.not,input2,path25),matches=!0}catch{}matches&&fail(path25,"matches a forbidden field combination")}if(schema.oneOf&&schema.oneOf.filter(branch=>{try{return validateObject(branch,input2,path25),!0}catch{return!1}}).length!==1&&fail(path25,"must match exactly one launch form"),schema.additionalProperties!==!0)for(let key of Object.keys(input2))schema.properties[key]||fail(`${path25}.${key}`,"is not supported");for(let[key,item]of Object.entries(input2)){let property=schema.properties[key];property&&validateSchemaValue(property,item,`${path25}.${key}`)}}function validateProviderInput(schema,value){validateObject(schema,value,"options")}function validateProviderBrowser(browser){if(!browser||typeof browser!="object")throw new Error("Provider returned no browser");if(typeof browser.browserId!="string"||!browser.browserId.trim())throw new Error("Provider browserId is required");if(typeof browser.name!="string"||!browser.name.trim())throw new Error(`Provider browser ${browser.browserId} needs a name`);if(!["connected","pairing","running_disconnected","stopped"].includes(browser.status))throw new Error(`Provider browser ${browser.browserId} has an invalid status`);if(!["ephemeral","persistent"].includes(browser.persistence))throw new Error(`Provider browser ${browser.browserId} has invalid persistence`);if(browser.ownership!==void 0&&!["owned","attached"].includes(browser.ownership))throw new Error(`Provider browser ${browser.browserId} has invalid ownership`);if(!browser.control||!["provider","host","none"].includes(browser.control.kind))throw new Error(`Provider browser ${browser.browserId} has invalid control`);if(!Array.isArray(browser.operations)||new Set(browser.operations).size!==browser.operations.length||browser.operations.some(operation=>!LIFECYCLE_OPERATIONS.has(operation)))throw new Error(`Provider browser ${browser.browserId} has invalid lifecycle operations`);if(browser.status==="pairing"){if(browser.pairing?.kind!=="qr"||typeof browser.pairing.url!="string"||!browser.pairing.url.trim())throw new Error(`Pairing browser ${browser.browserId} needs a pairing URL`)}else if(browser.pairing)throw new Error(`Pairing metadata requires a pairing state: ${browser.browserId}`);if(browser.pairing&&(!isOptionalString(browser.pairing.code)||!isOptionalString(browser.pairing.label)))throw new Error(`Provider browser ${browser.browserId} has invalid pairing metadata`);if(browser.lastFocusedAt!==void 0&&(!Number.isFinite(browser.lastFocusedAt)||browser.lastFocusedAt<0))throw new Error(`Provider browser ${browser.browserId} has an invalid lastFocusedAt`);if(browser.status==="stopped"&&browser.control.kind!=="none")throw new Error(`Stopped Provider browser ${browser.browserId} cannot expose live control`);if(browser.status==="connected"&&browser.control.kind==="none")throw new Error(`Connected Provider browser ${browser.browserId} must expose control`);let capabilities=browser.control.kind==="provider"||browser.control.kind==="host"?browser.control.capabilities:void 0;if(browser.control.kind==="provider"||capabilities){if(!Array.isArray(capabilities?.actions))throw new Error(`Provider browser ${browser.browserId} needs action capabilities`);if(capabilities.actions.some(action=>!isProviderAction(action))||new Set(capabilities.actions).size!==capabilities.actions.length)throw new Error(`Provider browser ${browser.browserId} has invalid action capabilities`);if(!["native","reconstructed","none"].includes(capabilities.screenshot))throw new Error(`Provider browser ${browser.browserId} has invalid screenshot capabilities`);if(capabilities.actions.includes("page_screenshot")===(capabilities.screenshot==="none"))throw new Error(`Provider browser ${browser.browserId} has inconsistent screenshot capabilities`)}if(browser.control.kind==="host"&&(!["extension","cdp"].includes(browser.control.transport)||typeof browser.control.browserId!="string"||!browser.control.browserId.trim()))throw new Error(`Provider browser ${browser.browserId} has invalid host control`);if(browser.references!==void 0&&(!Array.isArray(browser.references)||browser.references.some(reference=>!reference||typeof reference.kind!="string"||!reference.kind.trim()||typeof reference.id!="string"||!reference.id.trim()||!isOptionalString(reference.label))||new Set(browser.references.map(reference=>`${reference.kind}:${reference.id}`)).size!==browser.references.length))throw new Error(`Provider browser ${browser.browserId} has invalid references`);if(browser.details!==void 0&&(!browser.details||typeof browser.details!="object"||Array.isArray(browser.details)||!isJsonValue(browser.details)))throw new Error(`Provider browser ${browser.browserId} has invalid details`);if(browser.details){let details=browser.details,strings=value=>Array.isArray(value)&&value.every(item=>typeof item=="string");if(details.headless!==void 0&&typeof details.headless!="boolean"||details.createdAt!==void 0&&(typeof details.createdAt!="string"||!Number.isFinite(Date.parse(details.createdAt)))||details.cdpPort!==void 0&&(!Number.isInteger(details.cdpPort)||details.cdpPort<1||details.cdpPort>65535)||details.copiedCookies!==void 0&&(!details.copiedCookies||!strings(details.copiedCookies.domains)||!Number.isInteger(details.copiedCookies.count)||details.copiedCookies.count<0))throw new Error(`Provider browser ${browser.browserId} has invalid common details`)}}function validateDefinition(definition){let{providerId,name,version:version2,protocolVersion}=definition.descriptor;if(!providerId?.trim())throw new Error("providerId is required");if(!name?.trim())throw new Error("provider name is required");if(!version2?.trim())throw new Error("provider version is required");if(protocolVersion!==void 0&&protocolVersion!==2)throw new Error(`Unsupported provider protocol ${protocolVersion}; expected ${2}`);if(!definition.browserType.name?.trim())throw new Error("provider browser type name is required");if(!isProviderInputSchema(definition.browserType.inputSchema)||definition.browserType.inputSchema.type!=="object")throw new Error("Provider input schema is invalid");if(definition.browserType.documentationUrl!==void 0&&(typeof definition.browserType.documentationUrl!="string"||!/^https?:\/\//.test(definition.browserType.documentationUrl)))throw new Error("Provider documentation URL must use HTTP(S)");let configuration=definition.browserType.configuration;if(configuration&&(!isProviderInputSchema(configuration.inputSchema)||configuration.inputSchema.type!=="object"))throw new Error("Provider configuration schema is invalid")}function createProviderRuntime(definition){validateDefinition(definition);let publishedBrowsers=[],validateRuntimeBrowser=browser=>{validateProviderBrowser(browser);let implementations={start:definition.start,detach:definition.detach,access:definition.getAccess,syncCookies:definition.syncCookies};for(let[operation,implementation]of Object.entries(implementations))if(browser.operations.includes(operation)&&!implementation)throw new Error(`Provider browser ${browser.browserId} advertises ${operation} without implementing it`)},listBrowsers=async(context={})=>{let browsers=definition.listBrowsers?await definition.listBrowsers(context):publishedBrowsers,seen=new Set;for(let browser of browsers){if(validateRuntimeBrowser(browser),seen.has(browser.browserId))throw new Error(`Duplicate provider browserId: ${browser.browserId}`);seen.add(browser.browserId)}return browsers},requireBrowser=async(browserId,operation,context)=>{let browser=(await listBrowsers(context)).find(item=>item.browserId===browserId);if(!browser)throw new Error(`Provider browser not found: ${browserId}`);if(!browser.operations.includes(operation))throw new Error(`Provider browser ${browserId} does not support ${operation}`);return browser};return{definition,listBrowsers,updateBrowsers(browsers){if(browsers.forEach(validateRuntimeBrowser),new Set(browsers.map(browser=>browser.browserId)).size!==browsers.length)throw new Error("Provider browser ids must be unique");publishedBrowsers=[...browsers]},async launch(options,context={}){validateProviderInput(definition.browserType.inputSchema,options);let browser=await definition.launch(options,context);return validateRuntimeBrowser(browser),browser},async start(request,context={}){if(await requireBrowser(request.browserId,"start",context),!definition.start)throw new Error("Provider does not implement start");let browser=await definition.start(request,context);return validateRuntimeBrowser(browser),browser},async close(request,context={}){return await requireBrowser(request.browserId,request.deleteData?"deleteData":"close",context),definition.close(request,context)},async detach(request,context={}){if(await requireBrowser(request.browserId,"detach",context),!definition.detach)throw new Error("Provider does not implement detach");return definition.detach(request,context)},async syncCookies(request,context={}){if(await requireBrowser(request.browserId,"syncCookies",context),!definition.syncCookies)throw new Error("Provider does not implement cookie sync");if(!request.scope||typeof request.scope!="object"||Array.isArray(request.scope)||!isJsonValue(request.scope))throw new Error("Cookie sync scope must be a JSON object");return definition.syncCookies(request,context)},async getAccess(request,context={}){if(await requireBrowser(request.browserId,"access",context),!definition.getAccess)throw new Error("Provider does not expose browser access");let access=await definition.getAccess(request,context);if(!access||typeof access.kind!="string"||!access.kind.trim()||typeof access.url!="string")throw new Error("Provider returned an invalid browser access result");let url2=new URL(access.url);if(!["http:","https:"].includes(url2.protocol)||access.sensitive!==!0)throw new Error("Provider returned an invalid browser access result");return{...access,url:url2.toString()}},async configure(options,context={}){let configuration=definition.browserType.configuration;if(!configuration||!definition.configure)throw new Error("Provider does not support configuration");return validateProviderInput(configuration.inputSchema,options),definition.configure(options,context)},async invokeAction(actionContext){let browser=(await listBrowsers({controlSource:actionContext.controlSource})).find(item=>item.browserId===actionContext.browserId);if(!browser)throw new Error(`Provider browser not found: ${actionContext.browserId}`);if(browser.status!=="connected")throw new Error(`Provider browser ${actionContext.browserId} is not connected`);if(browser.control.kind!=="provider")throw new Error(`Provider browser ${actionContext.browserId} uses host control`);if(!browser.control.capabilities.actions.includes(actionContext.action))throw new Error(`Provider browser ${actionContext.browserId} does not support ${actionContext.action}`);if(!definition.handleAction)throw new Error("Provider does not implement browser actions");return definition.handleAction(actionContext)}}}var LIFECYCLE_OPERATIONS,init_provider_runtime=__esm({"../provider/dist/provider-runtime.js"(){"use strict";init_types2();init_generated_provider_actions();LIFECYCLE_OPERATIONS=new Set(["start","close","detach","deleteData","access","syncCookies"])}});import{existsSync as existsSync3,readFileSync as readFileSync3,renameSync as renameSync3,rmSync as rmSync3,statSync as statSync3,writeFileSync as writeFileSync2}from"node:fs";import{randomUUID as randomUUID4}from"node:crypto";import{isAbsolute,join as join3,relative,resolve,sep}from"node:path";function providerBrowserKey(providerId,browserId){let redundantPrefix=`managed:${providerId}:`,scopedBrowserId=browserId.toLowerCase().startsWith(redundantPrefix.toLowerCase())?browserId.slice(redundantPrefix.length):browserId,encodedBrowserId=encodeURIComponent(scopedBrowserId).replace(/%3A/gi,":");return`provider:${encodeURIComponent(providerId)}:${encodedBrowserId}`}function installedProviderFile(providerId){return keyedConfigFile(INSTALLED_PROVIDERS_SUBDIR,providerId)}function liveProviderFile(providerId){return keyedConfigFile(LIVE_PROVIDERS_SUBDIR,providerId)}function startingProviderFile(providerId){return keyedConfigFile(STARTING_PROVIDERS_SUBDIR,providerId)}function claimProviderStart(providerId,token,pid=process.pid){let file2=startingProviderFile(providerId),existing=readRecord(file2);return existing&&isAlive(existing.pid)?existing.token===token:(existing?removeRecordIfPid(file2,existing.pid):removeInvalidRecord(file2),claimRecord(file2,{pid,providerId,token,startedAt:new Date().toISOString()}))}function readProviderStart(providerId){let record2=readRecord(startingProviderFile(providerId));return record2&&isAlive(record2.pid)?record2:null}function transferProviderStart(providerId,token,pid){let file2=startingProviderFile(providerId),record2=readRecord(file2);return!record2||record2.token!==token?!1:writeRecordIfPid(file2,record2.pid,{...record2,pid})}function releaseProviderStart(providerId,token){let file2=startingProviderFile(providerId),record2=readRecord(file2);return record2?.token===token?removeRecordIfPid(file2,record2.pid):!1}function writeManifest(file2,manifest){ensureDir(keyedDir(INSTALLED_PROVIDERS_SUBDIR));let temporary=`${file2}.${process.pid}.${randomUUID4()}.tmp`;try{writeFileSync2(temporary,JSON.stringify(manifest),{mode:384}),renameSync3(temporary,file2)}catch(error48){throw rmSync3(temporary,{force:!0}),error48}}function validateInstalledProviderManifest(manifest){if(!manifest||typeof manifest.providerId!="string"||!manifest.providerId.trim()||typeof manifest.name!="string"||!manifest.name.trim()||typeof manifest.version!="string"||!manifest.version.trim())return"manifest is incomplete";if(manifest.protocolVersion!==2)return`protocol ${manifest.protocolVersion} is unsupported`;if(RESERVED_PROVIDER_IDS.has(manifest.providerId))return`providerId ${manifest.providerId} is reserved for a built-in Provider`;if(!isProviderBrowserType(manifest.browserType))return"browserType is invalid";if(typeof manifest.packageName!="string"||!manifest.packageName.trim())return"packageName is required";if(typeof manifest.packageRoot!="string"||!isAbsolute(manifest.packageRoot))return"packageRoot must be an absolute path";if(typeof manifest.entryPath!="string"||!isAbsolute(manifest.entryPath))return"entryPath must be an absolute path";let entryRelative=relative(manifest.packageRoot,manifest.entryPath);return entryRelative===""||isAbsolute(entryRelative)||entryRelative===".."||entryRelative.startsWith(`..${sep}`)?"entryPath must be a file inside packageRoot":isFile(manifest.entryPath)?null:"entryPath does not exist or is not a file"}function installProvider(manifest){let invalid=validateInstalledProviderManifest(manifest);if(invalid)throw new Error(`Invalid provider manifest: ${invalid}`);writeManifest(installedProviderFile(manifest.providerId),manifest)}function packageFile(packageRoot){return join3(packageRoot,"package.json")}function isFile(filePath){try{return statSync3(filePath).isFile()}catch{return!1}}function isProviderBrowserType(value){if(!value||typeof value!="object")return!1;let browserType=value;return typeof browserType.name!="string"||!browserType.name.trim()||browserType.documentationUrl!==void 0&&(typeof browserType.documentationUrl!="string"||!/^https?:\/\//.test(browserType.documentationUrl))||browserType.help!==void 0&&(!Array.isArray(browserType.help)||browserType.help.some(item=>typeof item!="string"||!item.trim()))||!isProviderObjectSchema(browserType.inputSchema)?!1:browserType.configuration===void 0||!!browserType.configuration&&typeof browserType.configuration=="object"&&isProviderObjectSchema(browserType.configuration.inputSchema)}function isProviderObjectSchema(value){return isProviderInputSchema(value)&&value.type==="object"}function registerProviderPackage(packageRoot){if(!isAbsolute(packageRoot))throw new Error("Provider packageRoot must be an absolute path");let packageJson;try{packageJson=JSON.parse(readFileSync3(packageFile(packageRoot),"utf8"))}catch(error48){throw new Error(`Unable to read Provider package metadata from ${packageRoot}`,{cause:error48})}let metadata=packageJson.mearl?.provider;if(typeof packageJson.name!="string"||!packageJson.name.trim()||typeof packageJson.version!="string"||!packageJson.version.trim()||typeof metadata?.providerId!="string"||!metadata.providerId.trim()||typeof metadata.name!="string"||!metadata.name.trim()||metadata.protocolVersion!==2||typeof metadata.entry!="string"||!metadata.entry.trim()||!isProviderBrowserType(metadata.browserType))throw new Error(`Invalid mearl.provider metadata in ${packageFile(packageRoot)}`);if(isAbsolute(metadata.entry))throw new Error(`Provider entry must be relative to ${packageFile(packageRoot)}`);let normalizedRoot=resolve(packageRoot),entryPath=resolve(normalizedRoot,metadata.entry),entryRelative=relative(normalizedRoot,entryPath);if(isAbsolute(entryRelative)||entryRelative===".."||entryRelative.startsWith(`..${sep}`)||!isFile(entryPath))throw new Error(`Provider entry must be an existing file inside ${normalizedRoot}`);let installed=listInstalledProviders(),idConflict=installed.find(provider=>provider.providerId===metadata.providerId&&provider.packageName!==packageJson.name);if(idConflict)throw new Error(`Provider id ${metadata.providerId} is already registered by ${idConflict.packageName}`);let packageConflict=installed.find(provider=>provider.packageName===packageJson.name&&provider.providerId!==metadata.providerId);if(packageConflict)throw new Error(`Package ${packageJson.name} is already registered as Provider ${packageConflict.providerId}`);let manifest={providerId:metadata.providerId,name:metadata.name,version:packageJson.version,protocolVersion:metadata.protocolVersion,browserType:metadata.browserType,packageName:packageJson.name,packageRoot:normalizedRoot,entryPath};return installProvider(manifest),manifest}function listInstalledProviders(){let manifests=[];for(let file2 of listRecordFiles(keyedDir(INSTALLED_PROVIDERS_SUBDIR)))try{let parsed=JSON.parse(readFileSync3(file2,"utf8"));parsed&&typeof parsed.providerId=="string"&&typeof parsed.packageName=="string"&&manifests.push(parsed)}catch{}return manifests.sort((a,b)=>a.providerId.localeCompare(b.providerId))}function readLiveProvider(providerId){let record2=readRecord(liveProviderFile(providerId));return record2&&isAlive(record2.pid)?record2:null}function listLiveProviders(){return readLiveRecords(keyedDir(LIVE_PROVIDERS_SUBDIR))}var INSTALLED_PROVIDERS_SUBDIR,LIVE_PROVIDERS_SUBDIR,STARTING_PROVIDERS_SUBDIR,PROVIDER_START_TOKEN_ENV,RESERVED_PROVIDER_IDS,init_registry2=__esm({"../provider/dist/registry.js"(){"use strict";init_dist2();init_types2();init_provider_runtime();INSTALLED_PROVIDERS_SUBDIR="providers/installed",LIVE_PROVIDERS_SUBDIR="providers/live",STARTING_PROVIDERS_SUBDIR="providers/starting",PROVIDER_START_TOKEN_ENV="MEARL_PROVIDER_START_TOKEN",RESERVED_PROVIDER_IDS=new Set(["local"])}});import{StringDecoder}from"node:string_decoder";var Utf8LineBuffer,init_socketLines=__esm({"src/socketLines.ts"(){"use strict";Utf8LineBuffer=class{constructor(maxBufferBytes){this.maxBufferBytes=maxBufferBytes}buffer="";decoder=new StringDecoder("utf8");push(chunk){if(this.buffer+=this.decoder.write(chunk),Buffer.byteLength(this.buffer,"utf8")>this.maxBufferBytes)return this.buffer="",{lines:[],overflow:!0};let lines=[],newlineIndex;for(;(newlineIndex=this.buffer.indexOf(`
82
+ `}}});function getJsonpCallback(url2){try{let searchParams=new URL(url2).searchParams,callback=searchParams.get("callback")??searchParams.get("jsonp");return callback&&JSONP_CALLBACK_RE.test(callback)?callback:null}catch{return null}}function serializeMockResponse(requestUrl,responseData){let callback=getJsonpCallback(requestUrl);if(!callback)return{body:typeof responseData=="string"?responseData:JSON.stringify(responseData)??"null",isJsonp:!1};let json2=JSON.stringify(responseData)??"null";if(typeof responseData=="string")try{JSON.parse(responseData),json2=responseData}catch{}return{body:`${callback}(${json2});`,isJsonp:!0}}function prepareMockResponseHeaders(headers,isJsonp){let stripped=(headers??[]).filter(header=>!["content-encoding","content-length"].includes(header.name.toLowerCase()));if(!isJsonp)return stripped;let index=stripped.findIndex(header=>header.name.toLowerCase()==="content-type");if(index===-1)return[...stripped,{name:"content-type",value:JSONP_CONTENT_TYPE}];let result=[...stripped];return result[index]={...result[index],value:JSONP_CONTENT_TYPE},result}var JSONP_CALLBACK_RE,JSONP_CONTENT_TYPE,init_mockResponse=__esm({"../browser-core/dist/mockResponse.js"(){"use strict";JSONP_CALLBACK_RE=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/,JSONP_CONTENT_TYPE="application/javascript; charset=utf-8"}});var init_dist=__esm({"../browser-core/dist/index.js"(){"use strict";init_types();init_tdbankLogin();init_mtopSigner();init_mtopRequest();init_mtopStreamCapture();init_appProfileUserInfo();init_eventParsers();init_eventFilters();init_requestSerializer();init_boundedRequestBuffer();init_proxyPermissions();init_domTyping();init_domSelectors();init_domScrolling();init_domInspection();init_domSnapshot();init_deviceEmulation();init_axTextMatch();init_domClicking();init_pageDragging();init_pagePressing();init_axSnapshot();init_pageObserver();init_navigationTracker();init_pageAct();init_backendNodeRefs();init_pageEffectRefs();init_pageWait();init_pageNavigation();init_tabMatching();init_agentChat();init_agentSkills();init_agentServiceProtocol();init_toolbox();init_browserActionProtocol();init_runActions();init_sendRequestFiles();init_sendRequestHeaders();init_cookie();init_controlledFavicon();init_capture();init_sseParser();init_mockResponse()}});import{randomUUID}from"node:crypto";var BROWSER_QUEUE,ControlSessionRegistry,init_control_session=__esm({"src/control-session.ts"(){"use strict";init_dist();BROWSER_QUEUE=-1,ControlSessionRegistry=class{constructor(browserId){this.browserId=browserId}sessions=new Map;owners=new Map;queues=new Map;pending=new Map;browserReleasing=!1;resuming=new Set;create(transport){if(this.browserReleasing)throw new Error("BROWSER_CONTROL_RELEASING");let record2={sessionId:`cs_${randomUUID()}`,browserId:this.browserId(),transport,status:"active",tabs:[],generation:1};return this.sessions.set(record2.sessionId,record2),this.info(record2.sessionId)}info(id){let record2=this.require(id);return{...record2,tabs:record2.tabs.map(tab=>({...tab}))}}list(){return[...this.sessions.values()].filter(record2=>record2.status!=="released").map(record2=>this.info(record2.sessionId))}require(id){let record2=this.sessions.get(id);if(!record2||record2.browserId!==this.browserId())throw new Error("CONTROL_SESSION_NOT_FOUND");return record2}assertActive(id,generation){let record2=this.require(id);if(record2.status!=="active"||generation!==void 0&&generation!==record2.generation)throw new Error(`CONTROL_SESSION_PAUSED: ${record2.status}; inspect the page after the user returns control`);return record2}claim(id,tabId,source){let record2=this.require(id),owner=this.owners.get(tabId);if(owner&&owner!==id)throw new Error("TAB_CONTROLLED_BY_SESSION");record2.tabs.some(tab=>tab.tabId===tabId)||record2.tabs.push({tabId,source}),this.owners.set(tabId,id)}blockedTabs(id){return[...this.owners].filter(([,owner])=>owner!==id).map(([tab])=>tab)}assertBrowserRelease(){if(this.list().length)throw new Error("ACTIVE_CONTROL_SESSIONS: release the owning session first")}async releaseBrowser(operation){if(this.assertBrowserRelease(),this.browserReleasing)throw new Error("BROWSER_CONTROL_RELEASING");this.browserReleasing=!0;try{return await Promise.all([...this.queues.values()]),await operation()}finally{this.browserReleasing=!1}}async run(id,action,data,operation,transport="extension"){if(this.browserReleasing)throw new Error("BROWSER_CONTROL_RELEASING");let generation=id?this.assertActive(id).generation:void 0,tabs=new Set;typeof data.tabId=="number"&&tabs.add(data.tabId);for(let tab of data.tabIds??[])typeof tab=="number"&&tabs.add(tab);typeof data.openerTabId=="number"&&tabs.add(data.openerTabId);let steps=action==="run_actions"?data.actions:[{action,data}];if(action==="run_actions"){validateActionBatch(data);for(let step of data.actions??[]){typeof step.data?.tabId=="number"&&tabs.add(step.data.tabId);for(let tab of step.data?.tabIds??[])typeof tab=="number"&&tabs.add(tab);typeof step.data?.openerTabId=="number"&&tabs.add(step.data.openerTabId)}}let opensPage=steps.some(step=>step.action==="tab_open"),sharedResources=steps.some(step=>["set_rule","set_cookie","send_request","send_mtop_request"].includes(step.action)||step.action==="set_app_profile"&&transport!=="cdp"&&step.data?.mtopEnv!==void 0),assertSharedResources=()=>{if(action==="run_actions"&&!id&&this.list().length&&steps.some(step=>["tab_open","browser_close"].includes(step.action)))throw new Error("ACTIVE_CONTROL_SESSIONS: open pages outside run_actions while sessions are active");if(sharedResources&&this.list().some(record2=>record2.sessionId!==id))throw new Error("BROWSER_RESOURCE_CONFLICT: use an isolated browser for shared settings or requests");if(data.closeExisting&&!id&&this.list().length)throw new Error("ACTIVE_CONTROL_SESSIONS")};assertSharedResources();for(let tab of tabs){if(tab<0)continue;let owner=this.owners.get(tab);if(owner&&owner!==id)throw new Error("TAB_CONTROLLED_BY_SESSION")}let unlock,tail=new Promise(resolve9=>{unlock=resolve9}),predecessors=[...tabs].map(tab=>this.queues.get(tab)).filter(Boolean);this.queues.has(BROWSER_QUEUE)&&predecessors.push(this.queues.get(BROWSER_QUEUE)),(sharedResources||action==="page_download"||opensPage)&&(predecessors.push(...this.queues.values()),tabs.add(BROWSER_QUEUE));for(let tab of tabs)this.queues.set(tab,tail);let promise2=(async()=>{try{await Promise.all(predecessors),id&&this.assertActive(id,generation),assertSharedResources();for(let tab of tabs){let owner=this.owners.get(tab);if(owner&&owner!==id)throw new Error("TAB_CONTROLLED_BY_SESSION");id&&tab>=0&&this.claim(id,tab,"attached")}return await operation()}finally{unlock();for(let tab of tabs)this.queues.get(tab)===tail&&this.queues.delete(tab)}})();if(id){let pending=this.pending.get(id)??new Set;pending.add(promise2),this.pending.set(id,pending);try{return await promise2}finally{pending.delete(promise2),pending.size||this.pending.delete(id)}}return promise2}async waitForIdle(id){await Promise.allSettled([...this.pending.get(id)??[]])}assertStep(id,generation){this.assertActive(id,generation)}recordResult(id,action,result,data){action==="tab_open"&&typeof result?.tabId=="number"&&this.claim(id,result.tabId,result.opened===!0?"created":"attached");for(let tab of result?.observation?.openedTabs??[])typeof tab.tabId=="number"&&this.claim(id,tab.tabId,"created");let target=this.require(id).tabs.find(tab=>tab.tabId===(result?.tabId??data?.tabId));if(target&&typeof result?.title=="string"&&(target.title=result.title),target&&typeof result?.url=="string"&&(target.url=result.url),action==="tab_close"&&typeof data?.tabId=="number"&&(this.owners.delete(data.tabId),this.require(id).tabs=this.require(id).tabs.filter(tab=>tab.tabId!==data.tabId)),action==="tab_close")for(let tab of this.require(id).tabs)(result?.closedTabIds??[]).includes(tab.tabId)&&this.owners.delete(tab.tabId)}handoff(id,reason){let record2=this.assertActive(id);return record2.status="user",record2.generation+=1,record2.reason=reason,this.info(id)}async resume(id,cleanup=async()=>{}){let record2=this.require(id);if(record2.status!=="user")throw new Error("Session is not waiting for the user");if(this.resuming.has(id))throw new Error("CONTROL_SESSION_RESUMING");this.resuming.add(id);try{return await this.waitForIdle(id),await cleanup(),record2.status="active",record2.reason=void 0,record2.generation+=1,this.info(id)}finally{this.resuming.delete(id)}}async release(id,params,cleanup){let record2=this.require(id);if(this.resuming.has(id))throw new Error("CONTROL_SESSION_RESUMING");if(record2.status==="released")return this.info(id);if(record2.status==="releasing")throw new Error("CONTROL_SESSION_RELEASING");let previous=record2.status;record2.status="releasing",record2.generation+=1,await Promise.allSettled([...this.pending.get(id)??[]]);let tabs=record2.tabs.map(tab=>tab.tabId),keep=new Set(params.keepTabIds??[]),close=params.closeCreatedTabs?record2.tabs.filter(tab=>tab.source==="created"&&!keep.has(tab.tabId)).map(tab=>tab.tabId):[];try{await cleanup(tabs,close);for(let tab of tabs)this.owners.get(tab)===id&&this.owners.delete(tab);record2.status="released";let released=[...this.sessions.values()].filter(session=>session.status==="released"&&session.sessionId!==id);for(let old of released.slice(0,Math.max(0,released.length-99)))this.sessions.delete(old.sessionId)}catch(error48){throw record2.status=previous,error48}return this.info(id)}}}});import{rmSync}from"node:fs";import{randomUUID as randomUUID2}from"node:crypto";import{mkdir,open,rm,stat,writeFile}from"node:fs/promises";import path from"node:path";import os from"node:os";var MAX_BYTES,ARTIFACT_CHUNK_BYTES,BrowserArtifactStore,init_browser_artifacts=__esm({"src/browser-artifacts.ts"(){"use strict";MAX_BYTES=256*1024*1024,ARTIFACT_CHUNK_BYTES=256*1024,BrowserArtifactStore=class{constructor(root=path.join(os.tmpdir(),`mearl-artifacts-${process.pid}-${randomUUID2()}`)){this.root=root}files=new Map;directory;sweeper;async create(filename,sessionId){if(typeof filename!="string"||!filename||[".",".."].includes(filename)||/[\\/]/.test(filename)||filename.length>255)throw new Error("Invalid artifact filename");this.sweeper||(this.sweeper=setInterval(()=>{for(let[id,file3]of this.files)!file3.sessionId&&!file3.writing&&Date.now()-file3.accessedAt>3600*1e3&&this.remove(id).catch(()=>{})},6e4),this.sweeper.unref()),await mkdir(this.root,{recursive:!0,mode:448}),this.directory=this.root;let artifactId=randomUUID2(),directory=path.join(this.root,artifactId);await mkdir(directory,{mode:448});let file2={artifactId,filename,bytes:0,location:"browser",path:path.join(directory,filename),sessionId,ready:!1,accessedAt:Date.now()};return await writeFile(file2.path,"",{mode:384}),this.files.set(artifactId,file2),this.info(file2)}async importFile(filename,sourcePath,sessionId){let source=await open(sourcePath,"r"),id;try{let metadata=await source.stat();if(!metadata.isFile()||metadata.size>MAX_BYTES)throw new Error("Download is unavailable or exceeds 256 MiB");id=(await this.create(filename,sessionId)).artifactId;let file2=this.require(id,sessionId),target=await open(file2.path,"w"),copied=0;try{for await(let chunk of source.createReadStream({autoClose:!1})){if(copied+=chunk.length,copied>MAX_BYTES)throw new Error("Download exceeds 256 MiB");let written=0;for(;written<chunk.length;){let result=await target.write(chunk,written,chunk.length-written);if(!result.bytesWritten)throw new Error("Download import made no progress");written+=result.bytesWritten}}}finally{await target.close()}if(copied!==metadata.size)throw new Error("Download changed during import");return file2.bytes=(await stat(file2.path)).size,file2.ready=!0,this.info(file2)}catch(error48){throw id&&await this.remove(id,sessionId),error48}finally{await source.close()}}require(id,sessionId){let file2=this.files.get(id);if(!file2||file2.sessionId!==void 0&&file2.sessionId!==sessionId)throw new Error("ARTIFACT_NOT_FOUND");return file2.accessedAt=Date.now(),file2}info(file2){return{artifactId:file2.artifactId,filename:file2.filename,bytes:file2.bytes,location:"browser"}}async write(id,offset,base643,sessionId){let file2=this.require(id,sessionId);if(file2.ready||file2.writing||offset!==file2.bytes)throw new Error("Invalid artifact write offset or completed transfer");if(typeof base643!="string"||base643.length>Math.ceil(ARTIFACT_CHUNK_BYTES/3)*4||base643.length%4!==0||!/^[A-Za-z0-9+/]*={0,2}$/.test(base643))throw new Error("Invalid artifact chunk");let chunk=Buffer.from(base643,"base64");if(chunk.toString("base64")!==base643)throw new Error("Invalid artifact chunk");if(file2.bytes+chunk.length>MAX_BYTES)throw new Error("Artifact exceeds 256 MiB");file2.writing=!0;try{let handle=await open(file2.path,"r+");try{let written=0;for(;written<chunk.length;){let result=await handle.write(chunk,written,chunk.length-written,offset+written);if(!result.bytesWritten)throw new Error("Artifact write made no progress");written+=result.bytesWritten}}finally{await handle.close()}return file2.bytes+=chunk.length,this.info(file2)}finally{file2.writing=!1}}complete(id,bytes,sessionId){let file2=this.require(id,sessionId);if(file2.writing||bytes!==file2.bytes)throw new Error("Artifact size mismatch");return file2.ready=!0,this.info(file2)}resolve(id,sessionId){let file2=this.require(id,sessionId);if(!file2.ready)throw new Error("Artifact is not ready");return file2.path}async read(id,offset,sessionId){let file2=this.require(id,sessionId);if(!file2.ready||!Number.isSafeInteger(offset)||offset<0||offset>file2.bytes)throw new Error("Invalid artifact read");let handle=await open(file2.path,"r");try{let buffer=Buffer.alloc(Math.min(ARTIFACT_CHUNK_BYTES,file2.bytes-offset)),result=await handle.read(buffer,0,buffer.length,offset);return{base64:buffer.subarray(0,result.bytesRead).toString("base64"),bytes:result.bytesRead,totalBytes:file2.bytes}}finally{await handle.close()}}async remove(id,sessionId){let file2=this.require(id,sessionId);await rm(path.dirname(file2.path),{recursive:!0,force:!0}),this.files.delete(id)}async release(sessionId,keep=[]){let retain=new Set(keep);for(let[id,file2]of this.files)file2.sessionId===sessionId&&(retain.has(id)?(file2.sessionId=void 0,file2.accessedAt=Date.now()):await this.remove(id,sessionId))}disposeSync(){this.sweeper&&clearInterval(this.sweeper),this.directory&&rmSync(this.directory,{recursive:!0,force:!0}),this.files.clear()}async dispose(){this.sweeper&&clearInterval(this.sweeper),this.directory&&await rm(this.directory,{recursive:!0,force:!0}),this.files.clear()}}}});var ControlSessionManager,init_control_session_manager=__esm({"src/control-session-manager.ts"(){"use strict";init_dist();init_control_session();init_browser_artifacts();ControlSessionManager=class{constructor(dependencies){this.dependencies=dependencies;this.registry=new ControlSessionRegistry(dependencies.browserId)}registry;artifacts=new BrowserArtifactStore;async closeTabs(tabs,transport,sessionId){for(let tabId of tabs)try{let result=await this.dependencies.invoke("tab_close",{tabId},transport);this.registry.recordResult(sessionId,"tab_close",result,{tabId})}catch(error48){let current=await this.dependencies.invoke("tab_list",{},transport);if(!Array.isArray(current.tabs)||current.tabs.some(tab=>(tab.tabId??tab.id)===tabId))throw error48;this.registry.recordResult(sessionId,"tab_close",{},{tabId})}}async userControl(id,operation){if(operation==="release")return await this.invoke("browser_release",{},id),this.registry.info(id);let current=this.registry.info(id),info=operation==="resume"?await this.registry.resume(id,()=>this.dependencies.cleanup(current.tabs.map(tab=>tab.tabId),current.transport,!0)):this.registry.handoff(id);return this.dependencies.notify(),info}async invoke(action,data,sessionId,requestedTransport,origin="local"){if(data&&(Object.keys(data).some(key=>key.startsWith("__mearl"))||(data.actions??[]).some(step=>Object.keys(step.data??{}).some(key=>key.startsWith("__mearl")))))throw new Error("Internal session fields are reserved");validateRequiredActionTabId(action,data);let created=sessionId==="new";if(sessionId==="new"){if(!["tab_open","page_snapshot","page_screenshot"].includes(action))throw new Error("A new session requires tab_open, page_snapshot or page_screenshot");sessionId=this.registry.create(requestedTransport??this.dependencies.transport()).sessionId}let info=sessionId?this.registry.info(sessionId):void 0,transport=info?.transport??requestedTransport??this.dependencies.transport();if(requestedTransport&&transport!==requestedTransport)throw new Error("A session cannot change transport");if(action==="browser_control"){if(!sessionId||!["handoff","resume"].includes(data.operation))throw new Error("browser_control requires --session and handoff/resume");if(data.operation==="resume")return{session:await this.userControl(sessionId,"resume")};if(data.tabId!==void 0&&!info.tabs.some(tab=>tab.tabId===data.tabId))throw new Error("TAB_NOT_IN_CONTROL_SESSION");let session=this.registry.handoff(sessionId,data.reason);return this.dependencies.notify(),{session}}if(action==="browser_release"&&sessionId){let params=data,session=await this.registry.release(sessionId,params,async(tabs,close)=>{await this.dependencies.cleanup(tabs,transport,params.preserveEnvironment!==!1),await this.closeTabs(close,transport,sessionId),await this.artifacts.release(sessionId,params.keepArtifactIds)});return this.dependencies.notify(),{released:!0,hadActiveControl:!0,transports:[transport],affectedTabIds:info.tabs.map(tab=>tab.tabId),session}}if((action==="browser_release"||action==="browser_close")&&this.registry.assertBrowserRelease(),(action==="browser_release"||action==="browser_close")&&!sessionId)return this.registry.releaseBrowser(()=>this.dependencies.invoke(action,data,transport));let invokeStep=async(name,payload,batch=!1)=>{if(name==="tab_open"&&(sessionId&&payload.closeExisting&&(await this.closeTabs(this.registry.info(sessionId).tabs.filter(tab=>tab.source==="created").map(tab=>tab.tabId),transport,sessionId),payload={...payload,closeExisting:!1}),payload={...payload,__mearlBlockedTabIds:this.registry.blockedTabs(sessionId)}),name==="page_upload"&&payload.files){if(payload.filePaths)throw new Error("Use files or filePaths, not both");payload={...payload,filePaths:payload.files.map(file2=>this.artifacts.resolve(file2.artifactId,sessionId))},delete payload.files}if(batch){if(transport==="provider"){let result4=await this.dependencies.invoke(name,{...payload,__mearlControlSource:origin},transport);return sessionId&&this.registry.recordResult(sessionId,name,result4,payload),result4?.action?.success===!1?{...result4.action,success:!1}:result4?.success===!1?{...result4,success:!1}:{success:!0,data:result4}}let result3=await this.dependencies.invoke("run_actions",{tabId:payload.tabId,actions:[{action:name,data:payload}],__mearlControlSource:origin},transport),outcome=result3.results?.[0]??{success:!1,error:result3.error??"Batch step returned no result",stage:result3.stage,attempt:result3.attempt};return sessionId&&outcome.success&&this.registry.recordResult(sessionId,name,outcome.data,payload),outcome}let result2=await this.dependencies.invoke(name,{...payload,__mearlControlSource:origin},transport);return sessionId&&this.registry.recordResult(sessionId,name,result2,payload),result2},result;try{result=await this.registry.run(sessionId,action,data,async()=>{if(transport==="extension"&&this.dependencies.transport()!=="extension")throw new Error("CONTROL_SESSION_TRANSPORT_UNAVAILABLE: extension is disconnected");if(action.startsWith("__artifact_")){let store=this.artifacts;switch(action){case"__artifact_init":return{artifact:await store.create(data.filename,sessionId),browserId:this.dependencies.browserId()};case"__artifact_write":return store.write(data.artifactId,data.offset,data.base64,sessionId);case"__artifact_complete":return store.complete(data.artifactId,data.bytes,sessionId);case"__artifact_read":return store.read(data.artifactId,data.offset,sessionId);case"__artifact_remove":return await store.remove(data.artifactId,sessionId),{removed:!0};default:throw new Error("Unknown artifact operation")}}if(action==="page_download"){let downloaded=await this.dependencies.download(data,transport,origin);try{return sessionId&&this.registry.recordResult(sessionId,"page_click",downloaded.action,data),{download:{...await this.artifacts.importFile(downloaded.filename,downloaded.filePath,sessionId),browserId:this.dependencies.browserId()},action:downloaded.action}}finally{if(downloaded.owned){let{rm:rm4,rmdir:rmdir2}=await import("node:fs/promises");await rm4(downloaded.filePath,{force:!0}),downloaded.directory&&await rmdir2(downloaded.directory).catch(()=>{})}}}return action==="run_actions"&&sessionId?runActionBatch(data,(name,payload)=>invokeStep(name,payload,!0),{beforeStep:()=>this.registry.assertStep(sessionId,info.generation)}):invokeStep(action,data)},transport)}catch(error48){throw created&&sessionId&&await this.registry.release(sessionId,{},async()=>{await this.artifacts.release(sessionId)}),this.dependencies.notify(),error48}if(sessionId&&action==="tab_list"&&Array.isArray(result.tabs)){let blocked=new Set(this.registry.blockedTabs(sessionId));result={...result,tabs:result.tabs.filter(tab=>!blocked.has(tab.tabId??tab.id))},result.count=result.tabs.length}return sessionId?(this.dependencies.notify(),{...result,session:this.registry.info(sessionId)}):result}}}});function isAlive(pid){if(!pid||pid<=0)return!1;try{return process.kill(pid,0),!0}catch(error48){return error48.code==="EPERM"}}var init_process=__esm({"../daemon-core/dist/process.js"(){"use strict"}});import{join}from"node:path";import{homedir}from"node:os";import{createHash}from"node:crypto";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`)}var DAEMON_HOME,init_paths=__esm({"../daemon-core/dist/paths.js"(){"use strict";DAEMON_HOME=join(homedir(),".mearl")}});import{closeSync,existsSync,linkSync,openSync,statSync,mkdirSync,readFileSync,writeFileSync,renameSync,rmSync as rmSync2,readdirSync}from"node:fs";import{dirname,join as join2}from"node:path";import{randomUUID as randomUUID3}from"node:crypto";function ensureDir(dir){existsSync(dir)||mkdirSync(dir,{recursive:!0,mode:448})}function pauseForLock(){Atomics.wait(lockWaitBuffer,0,0,LOCK_WAIT_MS)}function readRecordUnlocked(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 removeRecordUnlocked(file2){rmSync2(file2,{force:!0})}function writeRecordUnlocked(file2,record2){let tmp=`${file2}.${process.pid}.${randomUUID3()}.tmp`;try{writeFileSync(tmp,JSON.stringify(record2),{mode:384}),renameSync(tmp,file2)}catch(error48){try{rmSync2(tmp,{force:!0})}catch{}throw error48}}function removeStaleLock(lockDir){let ownerFile=join2(lockDir,"owner.json"),owner=readRecordUnlocked(ownerFile);if(owner){if(isAlive(owner.pid))return!1}else try{if(Date.now()-statSync(lockDir).mtimeMs<OWNER_WRITE_GRACE_MS)return!1}catch{return!0}try{return rmSync2(lockDir,{recursive:!0,force:!0}),!0}catch{return!1}}function withRecordLock(file2,operation){ensureDir(dirname(file2));let lockDir=`${file2}.registry.lock`,ownerFile=join2(lockDir,"owner.json"),token=randomUUID3(),deadline=Date.now()+LOCK_TIMEOUT_MS;for(;;){try{mkdirSync(lockDir,{mode:448})}catch(error48){if(error48.code!=="EEXIST")throw error48;if(!removeStaleLock(lockDir)){if(Date.now()>=deadline)throw new Error(`Timed out waiting for registry lock: ${file2}`,{cause:error48});pauseForLock()}continue}let ownerFd=null;try{ownerFd=openSync(ownerFile,"wx",384),writeFileSync(ownerFd,JSON.stringify({pid:process.pid,token}))}catch(error48){if(ownerFd!==null&&closeSync(ownerFd),ownerFd=null,error48.code==="EEXIST"){if(Date.now()>=deadline)throw new Error(`Timed out acquiring registry lock: ${file2}`,{cause:error48});pauseForLock();continue}throw error48}finally{ownerFd!==null&&closeSync(ownerFd)}try{return operation()}finally{readRecordUnlocked(ownerFile)?.token===token&&rmSync2(lockDir,{recursive:!0,force:!0})}}}function writeRecord(file2,record2){withRecordLock(file2,()=>writeRecordUnlocked(file2,record2))}function claimRecord(file2,record2){return withRecordLock(file2,()=>{let candidate=`${file2}.${process.pid}.${randomUUID3()}.claim`;try{return writeFileSync(candidate,JSON.stringify(record2),{mode:384}),linkSync(candidate,file2),!0}catch(error48){if(error48.code==="EEXIST")return!1;throw error48}finally{rmSync2(candidate,{force:!0})}})}function readRecord(file2){return readRecordUnlocked(file2)}function removeRecord(file2){try{withRecordLock(file2,()=>removeRecordUnlocked(file2))}catch{}}function removeRecordIfPid(file2,pid){try{return withRecordLock(file2,()=>readRecordUnlocked(file2)?.pid!==pid?!1:(removeRecordUnlocked(file2),!0))}catch{return!1}}function writeRecordIfPid(file2,pid,record2){return withRecordLock(file2,()=>readRecordUnlocked(file2)?.pid!==pid?!1:(writeRecordUnlocked(file2,record2),!0))}function removeInvalidRecord(file2){try{return withRecordLock(file2,()=>!existsSync(file2)||readRecordUnlocked(file2)?!1:(removeRecordUnlocked(file2),!0))}catch{return!1}}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):rec?removeRecordIfPid(file2,rec.pid):removeInvalidRecord(file2)}return out}var LOCK_WAIT_MS,LOCK_TIMEOUT_MS,OWNER_WRITE_GRACE_MS,lockWaitBuffer,init_registry=__esm({"../daemon-core/dist/registry.js"(){"use strict";init_process();LOCK_WAIT_MS=10,LOCK_TIMEOUT_MS=5e3,OWNER_WRITE_GRACE_MS=1e3,lockWaitBuffer=new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))}});import{existsSync as existsSync2,statSync as statSync2,renameSync as renameSync2,readFileSync as readFileSync2}from"node:fs";function rotateLogIfNeeded(logFile,maxBytes=DEFAULT_MAX_LOG_BYTES){try{if(!existsSync2(logFile)||statSync2(logFile).size<maxBytes)return;renameSync2(logFile,`${logFile}.1`)}catch{}}var DEFAULT_MAX_LOG_BYTES,init_log=__esm({"../daemon-core/dist/log.js"(){"use strict";DEFAULT_MAX_LOG_BYTES=5*1024*1024}});import{spawn}from"node:child_process";import{closeSync as closeSync2,openSync as openSync2}from"node:fs";import{dirname as dirname2}from"node:path";var init_daemon=__esm({"../daemon-core/dist/daemon.js"(){"use strict";init_process();init_registry();init_log()}});var init_dist2=__esm({"../daemon-core/dist/index.js"(){"use strict";init_process();init_paths();init_registry();init_log();init_daemon()}});var init_types2=__esm({"../provider/dist/types.js"(){"use strict"}});function isProviderAction(value){return typeof value=="string"&&providerActionSet.has(value)}var PROVIDER_ACTIONS,providerActionSet,init_generated_provider_actions=__esm({"../provider/dist/generated-provider-actions.js"(){"use strict";PROVIDER_ACTIONS=["tab_checkpoint","capture_checkpoint","get_requests","get_logs","get_events","set_mock","get_mocks","set_rule","get_rules","send_request","send_mtop_request","browser_release","page_screenshot","tab_open","tab_close","tab_list","tab_group","page_click","page_drag","page_type","page_scroll","page_hover","page_eval","page_inspect","page_snapshot","page_press","page_wait","page_navigate","page_upload","page_frames","set_device_emulation","set_app_profile","set_timezone","get_cookie","set_cookie","request_domain_permission","run_actions","page_download"],providerActionSet=new Set(PROVIDER_ACTIONS)}});function isJsonValue(value,depth=0){return depth>32?!1:value===null||["string","boolean"].includes(typeof value)?!0:typeof value=="number"?Number.isFinite(value):Array.isArray(value)?value.every(item=>isJsonValue(item,depth+1)):typeof value=="object"&&Object.values(value).every(item=>isJsonValue(item,depth+1))}function isOptionalString(value){return value===void 0||typeof value=="string"}function isOptionalFiniteNumber(value){return value===void 0||typeof value=="number"&&Number.isFinite(value)}function isOptionalCount(value){return value===void 0||Number.isInteger(value)&&Number(value)>=0}function isProviderInputSchema(value,depth=0){if(!value||typeof value!="object"||Array.isArray(value)||depth>32)return!1;let schema=value;if(!isOptionalString(schema.title)||!isOptionalString(schema.description)||schema.component!==void 0&&!["cookie-sync","switch"].includes(String(schema.component))||schema.default!==void 0&&!isJsonValue(schema.default)||schema.formDefault!==void 0&&!isJsonValue(schema.formDefault)||schema.formHidden!==void 0&&typeof schema.formHidden!="boolean"||schema.formWidth!==void 0&&!["half","full"].includes(String(schema.formWidth))||schema.formHideOptional!==void 0&&typeof schema.formHideOptional!="boolean"||schema.formVisibleWhen!==void 0&&(!schema.formVisibleWhen||typeof schema.formVisibleWhen!="object"||Array.isArray(schema.formVisibleWhen)||typeof schema.formVisibleWhen.field!="string"||!schema.formVisibleWhen.field||typeof schema.formVisibleWhen.empty!="boolean"))return!1;if(schema.type==="string"){let validPattern=!0;if(schema.pattern!==void 0)try{new RegExp(String(schema.pattern))}catch{validPattern=!1}if(!((schema.enum===void 0||Array.isArray(schema.enum)&&schema.enum.every(item=>typeof item=="string"))&&(schema.secret===void 0||typeof schema.secret=="boolean")&&isOptionalCount(schema.minLength)&&isOptionalCount(schema.maxLength)&&(schema.minLength===void 0||schema.maxLength===void 0||Number(schema.minLength)<=Number(schema.maxLength))&&isOptionalString(schema.pattern)&&validPattern&&isOptionalString(schema.placeholder)&&(schema.options===void 0||Array.isArray(schema.options)&&schema.options.every(option=>option&&typeof option=="object"&&!Array.isArray(option)&&typeof option.value=="string"&&typeof option.label=="string"&&isOptionalString(option.description)&&(option.disabled===void 0||typeof option.disabled=="boolean")&&(schema.enum===void 0||schema.enum.includes(option.value)))&&new Set(schema.options.map(option=>option.value)).size===schema.options.length)))return!1}else if(schema.type==="number"){if(!((schema.integer===void 0||typeof schema.integer=="boolean")&&isOptionalFiniteNumber(schema.minimum)&&isOptionalFiniteNumber(schema.maximum)&&(schema.minimum===void 0||schema.maximum===void 0||Number(schema.minimum)<=Number(schema.maximum))))return!1}else if(schema.type!=="boolean")if(schema.type==="array"){if(!isProviderInputSchema(schema.items,depth+1)||!isOptionalCount(schema.minItems)||!isOptionalCount(schema.maxItems)||schema.minItems!==void 0&&schema.maxItems!==void 0&&Number(schema.minItems)>Number(schema.maxItems))return!1}else{if(schema.type!=="object"||!schema.properties||typeof schema.properties!="object"||Array.isArray(schema.properties)||schema.additionalProperties!==void 0&&typeof schema.additionalProperties!="boolean")return!1;let properties=schema.properties;if(!Object.values(properties).every(item=>isProviderInputSchema(item,depth+1))||Object.values(properties).some(item=>{let condition=item.formVisibleWhen;return condition!==void 0&&!(String(condition.field)in properties)})||schema.not!==void 0&&(!isProviderInputSchema(schema.not,depth+1)||schema.not.type!=="object")||schema.oneOf!==void 0&&(!Array.isArray(schema.oneOf)||schema.oneOf.length===0||schema.oneOf.some(branch=>!isProviderInputSchema(branch,depth+1)||branch.type!=="object"))||schema.required!==void 0&&(!Array.isArray(schema.required)||schema.required.some(item=>typeof item!="string"||!(item in properties))||new Set(schema.required).size!==schema.required.length))return!1}if(schema.component==="cookie-sync"&&schema.type!=="object"||schema.component==="switch"&&schema.type!=="boolean")return!1;if(schema.default!==void 0)try{validateSchemaValue(value,schema.default,"default")}catch{return!1}if(schema.formDefault!==void 0)try{validateSchemaValue(value,schema.formDefault,"formDefault")}catch{return!1}return!0}function fail(path25,message){throw new Error(`${path25} ${message}`)}function validateSchemaValue(schema,value,path25){if(schema.type==="string"){typeof value!="string"&&fail(path25,"must be a string"),schema.enum&&!schema.enum.includes(value)&&fail(path25,"has an unsupported value"),schema.minLength!==void 0&&value.length<schema.minLength&&fail(path25,`must contain at least ${schema.minLength} characters`),schema.maxLength!==void 0&&value.length>schema.maxLength&&fail(path25,`must contain at most ${schema.maxLength} characters`),schema.pattern!==void 0&&!new RegExp(schema.pattern).test(value)&&fail(path25,"has an invalid format");return}if(schema.type==="number"){(typeof value!="number"||!Number.isFinite(value))&&fail(path25,"must be a number"),schema.integer&&!Number.isInteger(value)&&fail(path25,"must be an integer"),schema.minimum!==void 0&&value<schema.minimum&&fail(path25,`must be at least ${schema.minimum}`),schema.maximum!==void 0&&value>schema.maximum&&fail(path25,`must be at most ${schema.maximum}`);return}if(schema.type==="boolean"){typeof value!="boolean"&&fail(path25,"must be a boolean");return}if(schema.type==="array"){Array.isArray(value)||fail(path25,"must be an array"),schema.minItems!==void 0&&value.length<schema.minItems&&fail(path25,`must contain at least ${schema.minItems} items`),schema.maxItems!==void 0&&value.length>schema.maxItems&&fail(path25,`must contain at most ${schema.maxItems} items`),value.forEach((item,index)=>validateSchemaValue(schema.items,item,`${path25}[${index}]`));return}validateObject(schema,value,path25)}function validateObject(schema,value,path25){(!value||typeof value!="object"||Array.isArray(value))&&fail(path25,"must be an object");let input2=value;for(let key of schema.required??[])input2[key]===void 0&&fail(`${path25}.${key}`,"is required");if(schema.not){let matches=!1;try{validateObject(schema.not,input2,path25),matches=!0}catch{}matches&&fail(path25,"matches a forbidden field combination")}if(schema.oneOf&&schema.oneOf.filter(branch=>{try{return validateObject(branch,input2,path25),!0}catch{return!1}}).length!==1&&fail(path25,"must match exactly one launch form"),schema.additionalProperties!==!0)for(let key of Object.keys(input2))schema.properties[key]||fail(`${path25}.${key}`,"is not supported");for(let[key,item]of Object.entries(input2)){let property=schema.properties[key];property&&validateSchemaValue(property,item,`${path25}.${key}`)}}function validateProviderInput(schema,value){validateObject(schema,value,"options")}function validateProviderBrowser(browser){if(!browser||typeof browser!="object")throw new Error("Provider returned no browser");if(typeof browser.browserId!="string"||!browser.browserId.trim())throw new Error("Provider browserId is required");if(typeof browser.name!="string"||!browser.name.trim())throw new Error(`Provider browser ${browser.browserId} needs a name`);if(!["connected","pairing","running_disconnected","stopped"].includes(browser.status))throw new Error(`Provider browser ${browser.browserId} has an invalid status`);if(!["ephemeral","persistent"].includes(browser.persistence))throw new Error(`Provider browser ${browser.browserId} has invalid persistence`);if(browser.ownership!==void 0&&!["owned","attached"].includes(browser.ownership))throw new Error(`Provider browser ${browser.browserId} has invalid ownership`);if(!browser.control||!["provider","host","none"].includes(browser.control.kind))throw new Error(`Provider browser ${browser.browserId} has invalid control`);if(!Array.isArray(browser.operations)||new Set(browser.operations).size!==browser.operations.length||browser.operations.some(operation=>!LIFECYCLE_OPERATIONS.has(operation)))throw new Error(`Provider browser ${browser.browserId} has invalid lifecycle operations`);if(browser.status==="pairing"){if(browser.pairing?.kind!=="qr"||typeof browser.pairing.url!="string"||!browser.pairing.url.trim())throw new Error(`Pairing browser ${browser.browserId} needs a pairing URL`)}else if(browser.pairing)throw new Error(`Pairing metadata requires a pairing state: ${browser.browserId}`);if(browser.pairing&&(!isOptionalString(browser.pairing.code)||!isOptionalString(browser.pairing.label)))throw new Error(`Provider browser ${browser.browserId} has invalid pairing metadata`);if(browser.lastFocusedAt!==void 0&&(!Number.isFinite(browser.lastFocusedAt)||browser.lastFocusedAt<0))throw new Error(`Provider browser ${browser.browserId} has an invalid lastFocusedAt`);if(browser.status==="stopped"&&browser.control.kind!=="none")throw new Error(`Stopped Provider browser ${browser.browserId} cannot expose live control`);if(browser.status==="connected"&&browser.control.kind==="none")throw new Error(`Connected Provider browser ${browser.browserId} must expose control`);let capabilities=browser.control.kind==="provider"||browser.control.kind==="host"?browser.control.capabilities:void 0;if(browser.control.kind==="provider"||capabilities){if(!Array.isArray(capabilities?.actions))throw new Error(`Provider browser ${browser.browserId} needs action capabilities`);if(capabilities.actions.some(action=>!isProviderAction(action))||new Set(capabilities.actions).size!==capabilities.actions.length)throw new Error(`Provider browser ${browser.browserId} has invalid action capabilities`);if(!["native","reconstructed","none"].includes(capabilities.screenshot))throw new Error(`Provider browser ${browser.browserId} has invalid screenshot capabilities`);if(capabilities.actions.includes("page_screenshot")===(capabilities.screenshot==="none"))throw new Error(`Provider browser ${browser.browserId} has inconsistent screenshot capabilities`)}if(browser.control.kind==="host"&&(!["extension","cdp"].includes(browser.control.transport)||typeof browser.control.browserId!="string"||!browser.control.browserId.trim()))throw new Error(`Provider browser ${browser.browserId} has invalid host control`);if(browser.references!==void 0&&(!Array.isArray(browser.references)||browser.references.some(reference=>!reference||typeof reference.kind!="string"||!reference.kind.trim()||typeof reference.id!="string"||!reference.id.trim()||!isOptionalString(reference.label))||new Set(browser.references.map(reference=>`${reference.kind}:${reference.id}`)).size!==browser.references.length))throw new Error(`Provider browser ${browser.browserId} has invalid references`);if(browser.details!==void 0&&(!browser.details||typeof browser.details!="object"||Array.isArray(browser.details)||!isJsonValue(browser.details)))throw new Error(`Provider browser ${browser.browserId} has invalid details`);if(browser.details){let details=browser.details,strings=value=>Array.isArray(value)&&value.every(item=>typeof item=="string");if(details.headless!==void 0&&typeof details.headless!="boolean"||details.createdAt!==void 0&&(typeof details.createdAt!="string"||!Number.isFinite(Date.parse(details.createdAt)))||details.cdpPort!==void 0&&(!Number.isInteger(details.cdpPort)||details.cdpPort<1||details.cdpPort>65535)||details.copiedCookies!==void 0&&(!details.copiedCookies||!strings(details.copiedCookies.domains)||!Number.isInteger(details.copiedCookies.count)||details.copiedCookies.count<0))throw new Error(`Provider browser ${browser.browserId} has invalid common details`)}}function validateDefinition(definition){let{providerId,name,version:version2,protocolVersion}=definition.descriptor;if(!providerId?.trim())throw new Error("providerId is required");if(!name?.trim())throw new Error("provider name is required");if(!version2?.trim())throw new Error("provider version is required");if(protocolVersion!==void 0&&protocolVersion!==2)throw new Error(`Unsupported provider protocol ${protocolVersion}; expected ${2}`);if(!definition.browserType.name?.trim())throw new Error("provider browser type name is required");if(!isProviderInputSchema(definition.browserType.inputSchema)||definition.browserType.inputSchema.type!=="object")throw new Error("Provider input schema is invalid");if(definition.browserType.documentationUrl!==void 0&&(typeof definition.browserType.documentationUrl!="string"||!/^https?:\/\//.test(definition.browserType.documentationUrl)))throw new Error("Provider documentation URL must use HTTP(S)");if(definition.browserType.dynamicLaunchForm!==void 0&&typeof definition.browserType.dynamicLaunchForm!="boolean")throw new Error("Provider dynamic launch form declaration is invalid");if(definition.browserType.dynamicLaunchForm&&!definition.getLaunchForm)throw new Error("Provider does not implement getLaunchForm");definition.browserType.launchForm!==void 0&&validateProviderLaunchForm(definition.browserType.launchForm);let configuration=definition.browserType.configuration;if(configuration&&(!isProviderInputSchema(configuration.inputSchema)||configuration.inputSchema.type!=="object"))throw new Error("Provider configuration schema is invalid")}function validateProviderLaunchForm(form){if(!form||!isProviderInputSchema(form.inputSchema)||form.inputSchema.type!=="object"||!isOptionalString(form.variant)||!isOptionalString(form.message)||form.blocked!==void 0&&typeof form.blocked!="boolean"||form.values!==void 0&&(!form.values||typeof form.values!="object"||Array.isArray(form.values)||!isJsonValue(form.values))||form.dynamicFields!==void 0&&(!Array.isArray(form.dynamicFields)||form.dynamicFields.some(field=>typeof field!="string"||!(field in form.inputSchema.properties)))||form.refreshOn!==void 0&&(!Array.isArray(form.refreshOn)||form.refreshOn.some(field=>typeof field!="string"||!(field in form.inputSchema.properties)))||form.variants!==void 0&&(!Array.isArray(form.variants)||!form.variants.length||form.variants.some(variant=>!variant||typeof variant.id!="string"||!variant.id||typeof variant.title!="string"||!isOptionalString(variant.description))||new Set(form.variants.map(variant=>variant.id)).size!==form.variants.length||!form.variants.some(variant=>variant.id===form.variant)))throw new Error("Provider returned an invalid launch form");for(let variant of form.variants??[])validateProviderLaunchForm({inputSchema:variant.inputSchema===void 0?form.inputSchema:variant.inputSchema,values:variant.values===void 0?form.values:variant.values,refreshOn:variant.refreshOn===void 0?form.refreshOn:variant.refreshOn,dynamicFields:variant.dynamicFields===void 0?form.dynamicFields:variant.dynamicFields})}function createProviderRuntime(definition){validateDefinition(definition);let publishedBrowsers=[],validateRuntimeBrowser=browser=>{validateProviderBrowser(browser);let implementations={start:definition.start,detach:definition.detach,access:definition.getAccess,syncCookies:definition.syncCookies};for(let[operation,implementation]of Object.entries(implementations))if(browser.operations.includes(operation)&&!implementation)throw new Error(`Provider browser ${browser.browserId} advertises ${operation} without implementing it`)},listBrowsers=async(context={})=>{let browsers=definition.listBrowsers?await definition.listBrowsers(context):publishedBrowsers,seen=new Set;for(let browser of browsers){if(validateRuntimeBrowser(browser),seen.has(browser.browserId))throw new Error(`Duplicate provider browserId: ${browser.browserId}`);seen.add(browser.browserId)}return browsers},requireBrowser=async(browserId,operation,context)=>{let browser=(await listBrowsers(context)).find(item=>item.browserId===browserId);if(!browser)throw new Error(`Provider browser not found: ${browserId}`);if(!browser.operations.includes(operation))throw new Error(`Provider browser ${browserId} does not support ${operation}`);return browser};return{definition,listBrowsers,updateBrowsers(browsers){if(browsers.forEach(validateRuntimeBrowser),new Set(browsers.map(browser=>browser.browserId)).size!==browsers.length)throw new Error("Provider browser ids must be unique");publishedBrowsers=[...browsers]},async getLaunchForm(request,context={}){if(!definition.browserType.dynamicLaunchForm||!definition.getLaunchForm)throw new Error("Provider does not support dynamic launch forms");if(!request||!isOptionalString(request.variant)||!request.values||typeof request.values!="object"||Array.isArray(request.values)||!isJsonValue(request.values))throw new Error("Invalid launch form request");let form=await definition.getLaunchForm(request,context);validateProviderLaunchForm(form);for(let[key,value]of Object.entries(form.values??{})){let schema=definition.browserType.inputSchema.properties[key];if(!schema)throw new Error(`Launch form returned an unknown parameter: ${key}`);validateSchemaValue(schema,value,key)}return form},async launch(options,context={}){validateProviderInput(definition.browserType.inputSchema,options);let browser=await definition.launch(options,context);return validateRuntimeBrowser(browser),browser},async start(request,context={}){if(await requireBrowser(request.browserId,"start",context),!definition.start)throw new Error("Provider does not implement start");let browser=await definition.start(request,context);return validateRuntimeBrowser(browser),browser},async close(request,context={}){return await requireBrowser(request.browserId,request.deleteData?"deleteData":"close",context),definition.close(request,context)},async detach(request,context={}){if(await requireBrowser(request.browserId,"detach",context),!definition.detach)throw new Error("Provider does not implement detach");return definition.detach(request,context)},async syncCookies(request,context={}){if(await requireBrowser(request.browserId,"syncCookies",context),!definition.syncCookies)throw new Error("Provider does not implement cookie sync");if(!request.scope||typeof request.scope!="object"||Array.isArray(request.scope)||!isJsonValue(request.scope))throw new Error("Cookie sync scope must be a JSON object");return definition.syncCookies(request,context)},async getAccess(request,context={}){if(await requireBrowser(request.browserId,"access",context),!definition.getAccess)throw new Error("Provider does not expose browser access");let access=await definition.getAccess(request,context);if(!access||typeof access.kind!="string"||!access.kind.trim()||typeof access.url!="string")throw new Error("Provider returned an invalid browser access result");let url2=new URL(access.url);if(!["http:","https:"].includes(url2.protocol)||access.sensitive!==!0)throw new Error("Provider returned an invalid browser access result");return{...access,url:url2.toString()}},async configure(options,context={}){let configuration=definition.browserType.configuration;if(!configuration||!definition.configure)throw new Error("Provider does not support configuration");return validateProviderInput(configuration.inputSchema,options),definition.configure(options,context)},async invokeAction(actionContext){let browser=(await listBrowsers({controlSource:actionContext.controlSource})).find(item=>item.browserId===actionContext.browserId);if(!browser)throw new Error(`Provider browser not found: ${actionContext.browserId}`);if(browser.status!=="connected")throw new Error(`Provider browser ${actionContext.browserId} is not connected`);if(browser.control.kind!=="provider")throw new Error(`Provider browser ${actionContext.browserId} uses host control`);if(!browser.control.capabilities.actions.includes(actionContext.action))throw new Error(`Provider browser ${actionContext.browserId} does not support ${actionContext.action}`);if(!definition.handleAction)throw new Error("Provider does not implement browser actions");return definition.handleAction(actionContext)}}}var LIFECYCLE_OPERATIONS,init_provider_runtime=__esm({"../provider/dist/provider-runtime.js"(){"use strict";init_types2();init_generated_provider_actions();LIFECYCLE_OPERATIONS=new Set(["start","close","detach","deleteData","access","syncCookies"])}});import{existsSync as existsSync3,readFileSync as readFileSync3,renameSync as renameSync3,rmSync as rmSync3,statSync as statSync3,writeFileSync as writeFileSync2}from"node:fs";import{randomUUID as randomUUID4}from"node:crypto";import{isAbsolute,join as join3,relative,resolve,sep}from"node:path";function providerBrowserKey(providerId,browserId){let redundantPrefix=`managed:${providerId}:`,scopedBrowserId=browserId.toLowerCase().startsWith(redundantPrefix.toLowerCase())?browserId.slice(redundantPrefix.length):browserId,encodedBrowserId=encodeURIComponent(scopedBrowserId).replace(/%3A/gi,":");return`provider:${encodeURIComponent(providerId)}:${encodedBrowserId}`}function installedProviderFile(providerId){return keyedConfigFile(INSTALLED_PROVIDERS_SUBDIR,providerId)}function liveProviderFile(providerId){return keyedConfigFile(LIVE_PROVIDERS_SUBDIR,providerId)}function startingProviderFile(providerId){return keyedConfigFile(STARTING_PROVIDERS_SUBDIR,providerId)}function claimProviderStart(providerId,token,pid=process.pid){let file2=startingProviderFile(providerId),existing=readRecord(file2);return existing&&isAlive(existing.pid)?existing.token===token:(existing?removeRecordIfPid(file2,existing.pid):removeInvalidRecord(file2),claimRecord(file2,{pid,providerId,token,startedAt:new Date().toISOString()}))}function readProviderStart(providerId){let record2=readRecord(startingProviderFile(providerId));return record2&&isAlive(record2.pid)?record2:null}function transferProviderStart(providerId,token,pid){let file2=startingProviderFile(providerId),record2=readRecord(file2);return!record2||record2.token!==token?!1:writeRecordIfPid(file2,record2.pid,{...record2,pid})}function releaseProviderStart(providerId,token){let file2=startingProviderFile(providerId),record2=readRecord(file2);return record2?.token===token?removeRecordIfPid(file2,record2.pid):!1}function writeManifest(file2,manifest){ensureDir(keyedDir(INSTALLED_PROVIDERS_SUBDIR));let temporary=`${file2}.${process.pid}.${randomUUID4()}.tmp`;try{writeFileSync2(temporary,JSON.stringify(manifest),{mode:384}),renameSync3(temporary,file2)}catch(error48){throw rmSync3(temporary,{force:!0}),error48}}function validateInstalledProviderManifest(manifest){if(!manifest||typeof manifest.providerId!="string"||!manifest.providerId.trim()||typeof manifest.name!="string"||!manifest.name.trim()||typeof manifest.version!="string"||!manifest.version.trim())return"manifest is incomplete";if(manifest.protocolVersion!==2)return`protocol ${manifest.protocolVersion} is unsupported`;if(RESERVED_PROVIDER_IDS.has(manifest.providerId))return`providerId ${manifest.providerId} is reserved for a built-in Provider`;if(!isProviderBrowserType(manifest.browserType))return"browserType is invalid";if(typeof manifest.packageName!="string"||!manifest.packageName.trim())return"packageName is required";if(typeof manifest.packageRoot!="string"||!isAbsolute(manifest.packageRoot))return"packageRoot must be an absolute path";if(typeof manifest.entryPath!="string"||!isAbsolute(manifest.entryPath))return"entryPath must be an absolute path";let entryRelative=relative(manifest.packageRoot,manifest.entryPath);return entryRelative===""||isAbsolute(entryRelative)||entryRelative===".."||entryRelative.startsWith(`..${sep}`)?"entryPath must be a file inside packageRoot":isFile(manifest.entryPath)?null:"entryPath does not exist or is not a file"}function installProvider(manifest){let invalid=validateInstalledProviderManifest(manifest);if(invalid)throw new Error(`Invalid provider manifest: ${invalid}`);writeManifest(installedProviderFile(manifest.providerId),manifest)}function packageFile(packageRoot){return join3(packageRoot,"package.json")}function isFile(filePath){try{return statSync3(filePath).isFile()}catch{return!1}}function isProviderBrowserType(value){if(!value||typeof value!="object")return!1;let browserType=value;if(typeof browserType.name!="string"||!browserType.name.trim()||browserType.documentationUrl!==void 0&&(typeof browserType.documentationUrl!="string"||!/^https?:\/\//.test(browserType.documentationUrl))||browserType.help!==void 0&&(!Array.isArray(browserType.help)||browserType.help.some(item=>typeof item!="string"||!item.trim()))||!isProviderObjectSchema(browserType.inputSchema)||browserType.dynamicLaunchForm!==void 0&&typeof browserType.dynamicLaunchForm!="boolean")return!1;if(browserType.launchForm!==void 0)try{validateProviderLaunchForm(browserType.launchForm)}catch{return!1}return browserType.configuration===void 0||!!browserType.configuration&&typeof browserType.configuration=="object"&&isProviderObjectSchema(browserType.configuration.inputSchema)}function isProviderObjectSchema(value){return isProviderInputSchema(value)&&value.type==="object"}function registerProviderPackage(packageRoot){if(!isAbsolute(packageRoot))throw new Error("Provider packageRoot must be an absolute path");let packageJson;try{packageJson=JSON.parse(readFileSync3(packageFile(packageRoot),"utf8"))}catch(error48){throw new Error(`Unable to read Provider package metadata from ${packageRoot}`,{cause:error48})}let metadata=packageJson.mearl?.provider;if(typeof packageJson.name!="string"||!packageJson.name.trim()||typeof packageJson.version!="string"||!packageJson.version.trim()||typeof metadata?.providerId!="string"||!metadata.providerId.trim()||typeof metadata.name!="string"||!metadata.name.trim()||metadata.protocolVersion!==2||typeof metadata.entry!="string"||!metadata.entry.trim()||!isProviderBrowserType(metadata.browserType))throw new Error(`Invalid mearl.provider metadata in ${packageFile(packageRoot)}`);if(isAbsolute(metadata.entry))throw new Error(`Provider entry must be relative to ${packageFile(packageRoot)}`);let normalizedRoot=resolve(packageRoot),entryPath=resolve(normalizedRoot,metadata.entry),entryRelative=relative(normalizedRoot,entryPath);if(isAbsolute(entryRelative)||entryRelative===".."||entryRelative.startsWith(`..${sep}`)||!isFile(entryPath))throw new Error(`Provider entry must be an existing file inside ${normalizedRoot}`);let installed=listInstalledProviders(),idConflict=installed.find(provider=>provider.providerId===metadata.providerId&&provider.packageName!==packageJson.name);if(idConflict)throw new Error(`Provider id ${metadata.providerId} is already registered by ${idConflict.packageName}`);let packageConflict=installed.find(provider=>provider.packageName===packageJson.name&&provider.providerId!==metadata.providerId);if(packageConflict)throw new Error(`Package ${packageJson.name} is already registered as Provider ${packageConflict.providerId}`);let manifest={providerId:metadata.providerId,name:metadata.name,version:packageJson.version,protocolVersion:metadata.protocolVersion,browserType:metadata.browserType,packageName:packageJson.name,packageRoot:normalizedRoot,entryPath};return installProvider(manifest),manifest}function listInstalledProviders(){let manifests=[];for(let file2 of listRecordFiles(keyedDir(INSTALLED_PROVIDERS_SUBDIR)))try{let parsed=JSON.parse(readFileSync3(file2,"utf8"));parsed&&typeof parsed.providerId=="string"&&typeof parsed.packageName=="string"&&manifests.push(parsed)}catch{}return manifests.sort((a,b)=>a.providerId.localeCompare(b.providerId))}function readLiveProvider(providerId){let record2=readRecord(liveProviderFile(providerId));return record2&&isAlive(record2.pid)?record2:null}function listLiveProviders(){return readLiveRecords(keyedDir(LIVE_PROVIDERS_SUBDIR))}var INSTALLED_PROVIDERS_SUBDIR,LIVE_PROVIDERS_SUBDIR,STARTING_PROVIDERS_SUBDIR,PROVIDER_START_TOKEN_ENV,RESERVED_PROVIDER_IDS,init_registry2=__esm({"../provider/dist/registry.js"(){"use strict";init_dist2();init_types2();init_provider_runtime();INSTALLED_PROVIDERS_SUBDIR="providers/installed",LIVE_PROVIDERS_SUBDIR="providers/live",STARTING_PROVIDERS_SUBDIR="providers/starting",PROVIDER_START_TOKEN_ENV="MEARL_PROVIDER_START_TOKEN",RESERVED_PROVIDER_IDS=new Set(["local"])}});import{StringDecoder}from"node:string_decoder";var Utf8LineBuffer,init_socketLines=__esm({"src/socketLines.ts"(){"use strict";Utf8LineBuffer=class{constructor(maxBufferBytes){this.maxBufferBytes=maxBufferBytes}buffer="";decoder=new StringDecoder("utf8");push(chunk){if(this.buffer+=this.decoder.write(chunk),Buffer.byteLength(this.buffer,"utf8")>this.maxBufferBytes)return this.buffer="",{lines:[],overflow:!0};let lines=[],newlineIndex;for(;(newlineIndex=this.buffer.indexOf(`
83
83
  `))!==-1;)lines.push(this.buffer.slice(0,newlineIndex)),this.buffer=this.buffer.slice(newlineIndex+1);return{lines,overflow:!1}}}}});import{spawn as spawn3}from"node:child_process";import{randomUUID as randomUUID7}from"node:crypto";import{tmpdir}from"node:os";import{join as join5}from"node:path";function providerControlHostFile(){return keyedConfigFile("control","providers")}function providerControlSocketPath(pid){return process.platform==="win32"?`\\\\.\\pipe\\mearl-provider-control-${pid}`:join5(tmpdir(),`mearl-provider-control-${pid}.sock`)}function readProviderControlHost(){let record2=readRecord(providerControlHostFile());return record2?.ready&&typeof record2.socketPath=="string"&&isAlive(record2.pid)?record2:null}function ensureProviderControlHost(timeoutMs=1e4){if(startup)return startup;let pending=(async()=>{let file2=providerControlHostFile(),deadline=Date.now()+timeoutMs;for(;Date.now()<deadline;){let ready=readProviderControlHost();if(ready)return ready;let previous=readRecord(file2);if(!previous||!isAlive(previous.pid)){previous?removeRecordIfPid(file2,previous.pid):removeInvalidRecord(file2);let token=randomUUID7();if(claimRecord(file2,{pid:process.pid,socketPath:"",token,ready:!1}))try{let entry=process.env.MEARL_NATIVE_HOST_ENTRY,child=spawn3(entry?process.execPath:"mearl-native-host",[...entry?[entry]:[],"--provider-control",token],{detached:!0,stdio:"ignore",windowsHide:!0});if(await new Promise((resolve9,reject)=>{child.once("error",reject),child.once("spawn",resolve9)}),child.unref(),!child.pid)throw new Error("Provider control host did not report its pid");writeRecordIfPid(file2,process.pid,{pid:child.pid,socketPath:providerControlSocketPath(child.pid),token,ready:!1})}catch(error48){throw removeRecordIfPid(file2,process.pid),error48}}await new Promise(resolve9=>setTimeout(resolve9,50))}throw new Error("Provider control host startup timed out")})();return startup=pending,pending.finally(()=>{startup===pending&&(startup=void 0)}).catch(()=>{}),pending}var startup,init_control_host=__esm({"../provider/dist/control-host.js"(){"use strict";init_dist2()}});var init_host=__esm({"../provider/dist/host.js"(){"use strict";init_registry2();init_control_host()}});var BROWSER_DEVICE_PRESET_NAMES,APP_PROFILE_NAMES,TAB_ID_REQUIRED_ACTIONS2,TAB_ID_REQUIRED_ACTION_SET2,PAGE_ACT_ACTIONS2,EXTENSION_BROWSER_ACTIONS2,BROWSER_CAPABILITY_ACTIONS2,init_generated_browser_action_protocol=__esm({"../client/dist/generated-browser-action-protocol.js"(){"use strict";BROWSER_DEVICE_PRESET_NAMES=["iphone-duo-folded","iphone-duo-unfolded","iphone-17-pro","iphone-17e","pixel-11","ipad-mini-a17-pro","galaxy-s26","pura-x-max","iphone-15-pro","iphone-se","pixel-8","ipad-mini","galaxy-s23"],APP_PROFILE_NAMES=["fliggy","taobao","wechat","tmall","alipay","koubei","taobao-tj","taobao-live","xianyu","etao","eleme","damai","btrip","amap","qianwen","lingyou","didi","easybike"],TAB_ID_REQUIRED_ACTIONS2=["tab_checkpoint","capture_checkpoint","get_requests","get_logs","get_events","set_mock","get_mocks","page_screenshot","tab_close","page_click","page_drag","page_type","page_scroll","page_hover","page_eval","page_inspect","page_snapshot","page_press","page_wait","page_navigate","page_upload","page_download","page_frames","set_device_emulation","set_app_profile","set_timezone","run_actions"],TAB_ID_REQUIRED_ACTION_SET2=new Set(TAB_ID_REQUIRED_ACTIONS2),PAGE_ACT_ACTIONS2=["page_click","page_drag","page_type","page_hover","page_scroll","page_press","page_upload","page_eval"],EXTENSION_BROWSER_ACTIONS2={tab_checkpoint:!0,capture_checkpoint:!0,get_requests:!0,get_logs:!0,get_events:!0,set_mock:!0,get_mocks:!0,set_rule:!0,get_rules:!0,send_request:!0,send_mtop_request:!0,browser_release:!0,page_screenshot:!0,tab_open:!0,tab_close:!0,tab_list:!0,tab_group:!0,page_click:!0,page_drag:!0,page_type:!0,page_scroll:!0,page_hover:!0,page_eval:!0,page_inspect:!0,page_snapshot:!0,page_press:!0,page_wait:!0,page_navigate:!0,page_upload:!0,page_frames:!0,set_device_emulation:!0,set_app_profile:!0,set_timezone:!0,get_cookie:!0,set_cookie:!0,request_domain_permission:!0,run_actions:!0},BROWSER_CAPABILITY_ACTIONS2={...EXTENSION_BROWSER_ACTIONS2,page_download:!0}}});var require_ms=__commonJS({"../../node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js"(exports,module){var s=1e3,m=s*60,h=m*60,d=h*24,w=d*7,y=d*365.25;module.exports=function(val,options){options=options||{};var type=typeof val;if(type==="string"&&val.length>0)return parse3(val);if(type==="number"&&isFinite(val))return options.long?fmtLong(val):fmtShort(val);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(val))};function parse3(str){if(str=String(str),!(str.length>100)){var match=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);if(match){var n=parseFloat(match[1]),type=(match[2]||"ms").toLowerCase();switch(type){case"years":case"year":case"yrs":case"yr":case"y":return n*y;case"weeks":case"week":case"w":return n*w;case"days":case"day":case"d":return n*d;case"hours":case"hour":case"hrs":case"hr":case"h":return n*h;case"minutes":case"minute":case"mins":case"min":case"m":return n*m;case"seconds":case"second":case"secs":case"sec":case"s":return n*s;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return n;default:return}}}}function fmtShort(ms){var msAbs=Math.abs(ms);return msAbs>=d?Math.round(ms/d)+"d":msAbs>=h?Math.round(ms/h)+"h":msAbs>=m?Math.round(ms/m)+"m":msAbs>=s?Math.round(ms/s)+"s":ms+"ms"}function fmtLong(ms){var msAbs=Math.abs(ms);return msAbs>=d?plural(ms,msAbs,d,"day"):msAbs>=h?plural(ms,msAbs,h,"hour"):msAbs>=m?plural(ms,msAbs,m,"minute"):msAbs>=s?plural(ms,msAbs,s,"second"):ms+" ms"}function plural(ms,msAbs,n,name){var isPlural=msAbs>=n*1.5;return Math.round(ms/n)+" "+name+(isPlural?"s":"")}}});var require_common=__commonJS({"../../node_modules/.pnpm/debug@4.4.3_supports-color@5.5.0/node_modules/debug/src/common.js"(exports,module){function setup(env){createDebug.debug=createDebug,createDebug.default=createDebug,createDebug.coerce=coerce,createDebug.disable=disable,createDebug.enable=enable,createDebug.enabled=enabled,createDebug.humanize=require_ms(),createDebug.destroy=destroy,Object.keys(env).forEach(key=>{createDebug[key]=env[key]}),createDebug.names=[],createDebug.skips=[],createDebug.formatters={};function selectColor(namespace){let hash2=0;for(let i=0;i<namespace.length;i++)hash2=(hash2<<5)-hash2+namespace.charCodeAt(i),hash2|=0;return createDebug.colors[Math.abs(hash2)%createDebug.colors.length]}createDebug.selectColor=selectColor;function createDebug(namespace){let prevTime,enableOverride=null,namespacesCache,enabledCache;function debug(...args){if(!debug.enabled)return;let self=debug,curr=Number(new Date),ms=curr-(prevTime||curr);self.diff=ms,self.prev=prevTime,self.curr=curr,prevTime=curr,args[0]=createDebug.coerce(args[0]),typeof args[0]!="string"&&args.unshift("%O");let index=0;args[0]=args[0].replace(/%([a-zA-Z%])/g,(match,format)=>{if(match==="%%")return"%";index++;let formatter=createDebug.formatters[format];if(typeof formatter=="function"){let val=args[index];match=formatter.call(self,val),args.splice(index,1),index--}return match}),createDebug.formatArgs.call(self,args),(self.log||createDebug.log).apply(self,args)}return debug.namespace=namespace,debug.useColors=createDebug.useColors(),debug.color=createDebug.selectColor(namespace),debug.extend=extend2,debug.destroy=createDebug.destroy,Object.defineProperty(debug,"enabled",{enumerable:!0,configurable:!1,get:()=>enableOverride!==null?enableOverride:(namespacesCache!==createDebug.namespaces&&(namespacesCache=createDebug.namespaces,enabledCache=createDebug.enabled(namespace)),enabledCache),set:v=>{enableOverride=v}}),typeof createDebug.init=="function"&&createDebug.init(debug),debug}function extend2(namespace,delimiter){let newDebug=createDebug(this.namespace+(typeof delimiter>"u"?":":delimiter)+namespace);return newDebug.log=this.log,newDebug}function enable(namespaces){createDebug.save(namespaces),createDebug.namespaces=namespaces,createDebug.names=[],createDebug.skips=[];let split=(typeof namespaces=="string"?namespaces:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let ns of split)ns[0]==="-"?createDebug.skips.push(ns.slice(1)):createDebug.names.push(ns)}function matchesTemplate(search,template){let searchIndex=0,templateIndex=0,starIndex=-1,matchIndex=0;for(;searchIndex<search.length;)if(templateIndex<template.length&&(template[templateIndex]===search[searchIndex]||template[templateIndex]==="*"))template[templateIndex]==="*"?(starIndex=templateIndex,matchIndex=searchIndex,templateIndex++):(searchIndex++,templateIndex++);else if(starIndex!==-1)templateIndex=starIndex+1,matchIndex++,searchIndex=matchIndex;else return!1;for(;templateIndex<template.length&&template[templateIndex]==="*";)templateIndex++;return templateIndex===template.length}function disable(){let namespaces=[...createDebug.names,...createDebug.skips.map(namespace=>"-"+namespace)].join(",");return createDebug.enable(""),namespaces}function enabled(name){for(let skip of createDebug.skips)if(matchesTemplate(name,skip))return!1;for(let ns of createDebug.names)if(matchesTemplate(name,ns))return!0;return!1}function coerce(val){return val instanceof Error?val.stack||val.message:val}function destroy(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return createDebug.enable(createDebug.load()),createDebug}module.exports=setup}});var require_browser=__commonJS({"../../node_modules/.pnpm/debug@4.4.3_supports-color@5.5.0/node_modules/debug/src/browser.js"(exports,module){exports.formatArgs=formatArgs;exports.save=save;exports.load=load;exports.useColors=useColors;exports.storage=localstorage();exports.destroy=(()=>{let warned=!1;return()=>{warned||(warned=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})();exports.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function useColors(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let m;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&(m=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(m[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function formatArgs(args){if(args[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+args[0]+(this.useColors?"%c ":" ")+"+"+module.exports.humanize(this.diff),!this.useColors)return;let c="color: "+this.color;args.splice(1,0,c,"color: inherit");let index=0,lastC=0;args[0].replace(/%[a-zA-Z%]/g,match=>{match!=="%%"&&(index++,match==="%c"&&(lastC=index))}),args.splice(lastC,0,c)}exports.log=console.debug||console.log||(()=>{});function save(namespaces){try{namespaces?exports.storage.setItem("debug",namespaces):exports.storage.removeItem("debug")}catch{}}function load(){let r;try{r=exports.storage.getItem("debug")||exports.storage.getItem("DEBUG")}catch{}return!r&&typeof process<"u"&&"env"in process&&(r=process.env.DEBUG),r}function localstorage(){try{return localStorage}catch{}}module.exports=require_common()(exports);var{formatters}=module.exports;formatters.j=function(v){try{return JSON.stringify(v)}catch(error48){return"[UnexpectedJSONParseError]: "+error48.message}}}});var require_has_flag=__commonJS({"../../node_modules/.pnpm/has-flag@3.0.0/node_modules/has-flag/index.js"(exports,module){"use strict";module.exports=(flag,argv)=>{argv=argv||process.argv;let prefix=flag.startsWith("-")?"":flag.length===1?"-":"--",pos=argv.indexOf(prefix+flag),terminatorPos=argv.indexOf("--");return pos!==-1&&(terminatorPos===-1?!0:pos<terminatorPos)}}});var require_supports_color=__commonJS({"../../node_modules/.pnpm/supports-color@5.5.0/node_modules/supports-color/index.js"(exports,module){"use strict";var os13=__require("os"),hasFlag=require_has_flag(),env=process.env,forceColor;hasFlag("no-color")||hasFlag("no-colors")||hasFlag("color=false")?forceColor=!1:(hasFlag("color")||hasFlag("colors")||hasFlag("color=true")||hasFlag("color=always"))&&(forceColor=!0);"FORCE_COLOR"in env&&(forceColor=env.FORCE_COLOR.length===0||parseInt(env.FORCE_COLOR,10)!==0);function translateLevel(level){return level===0?!1:{level,hasBasic:!0,has256:level>=2,has16m:level>=3}}function supportsColor(stream){if(forceColor===!1)return 0;if(hasFlag("color=16m")||hasFlag("color=full")||hasFlag("color=truecolor"))return 3;if(hasFlag("color=256"))return 2;if(stream&&!stream.isTTY&&forceColor!==!0)return 0;let min=forceColor?1:0;if(process.platform==="win32"){let osRelease=os13.release().split(".");return Number(process.versions.node.split(".")[0])>=8&&Number(osRelease[0])>=10&&Number(osRelease[2])>=10586?Number(osRelease[2])>=14931?3:2:1}if("CI"in env)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some(sign=>sign in env)||env.CI_NAME==="codeship"?1:min;if("TEAMCITY_VERSION"in env)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION)?1:0;if(env.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in env){let version2=parseInt((env.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(env.TERM_PROGRAM){case"iTerm.app":return version2>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(env.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)||"COLORTERM"in env?1:(env.TERM==="dumb",min)}function getSupportLevel(stream){let level=supportsColor(stream);return translateLevel(level)}module.exports={supportsColor:getSupportLevel,stdout:getSupportLevel(process.stdout),stderr:getSupportLevel(process.stderr)}}});var require_node=__commonJS({"../../node_modules/.pnpm/debug@4.4.3_supports-color@5.5.0/node_modules/debug/src/node.js"(exports,module){var tty=__require("tty"),util=__require("util");exports.init=init;exports.log=log2;exports.formatArgs=formatArgs;exports.save=save;exports.load=load;exports.useColors=useColors;exports.destroy=util.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");exports.colors=[6,2,3,4,5,1];try{let supportsColor=require_supports_color();supportsColor&&(supportsColor.stderr||supportsColor).level>=2&&(exports.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch{}exports.inspectOpts=Object.keys(process.env).filter(key=>/^debug_/i.test(key)).reduce((obj,key)=>{let prop=key.substring(6).toLowerCase().replace(/_([a-z])/g,(_,k)=>k.toUpperCase()),val=process.env[key];return/^(yes|on|true|enabled)$/i.test(val)?val=!0:/^(no|off|false|disabled)$/i.test(val)?val=!1:val==="null"?val=null:val=Number(val),obj[prop]=val,obj},{});function useColors(){return"colors"in exports.inspectOpts?!!exports.inspectOpts.colors:tty.isatty(process.stderr.fd)}function formatArgs(args){let{namespace:name,useColors:useColors2}=this;if(useColors2){let c=this.color,colorCode="\x1B[3"+(c<8?c:"8;5;"+c),prefix=` ${colorCode};1m${name} \x1B[0m`;args[0]=prefix+args[0].split(`
84
84
  `).join(`
85
85
  `+prefix),args.push(colorCode+"m+"+module.exports.humanize(this.diff)+"\x1B[0m")}else args[0]=getDate()+name+" "+args[0]}function getDate(){return exports.inspectOpts.hideDate?"":new Date().toISOString()+" "}function log2(...args){return process.stderr.write(util.formatWithOptions(exports.inspectOpts,...args)+`
@@ -134,7 +134,7 @@ Expecting one of '${allowedValues.join("', '")}'`);let helpEvent=`${position}Hel
134
134
  modalRestoreFrame = null;
135
135
  if (document.querySelector?.('dialog:modal')) return;
136
136
  const positions = [];
137
- for (const { presentation } of inlineAgentPanels.values()) {
137
+ for (const { presentation } of anchoredAgentPanels.values()) {
138
138
  if (!presentation.element.isConnected) continue;
139
139
  const rect = presentation.element.getBoundingClientRect();
140
140
  if (![rect.top, rect.left, rect.width, rect.height].every(Number.isFinite)) continue;
@@ -291,36 +291,41 @@ Expecting one of '${allowedValues.join("', '")}'`);let helpEvent=`${position}Hel
291
291
  return context === undefined ? null : context.trim();
292
292
  };
293
293
 
294
- const inlineAgentPanels = new Map();
294
+ const anchoredAgentPanels = new Map();
295
295
 
296
- const stopInlineAgentPanelTracking = key => {
296
+ const stopAgentAnchorTracking = key => {
297
297
  if (key) {
298
- inlineAgentPanels.get(key)?.cleanup();
299
- inlineAgentPanels.delete(key);
298
+ anchoredAgentPanels.get(key)?.cleanup();
299
+ anchoredAgentPanels.delete(key);
300
300
  return;
301
301
  }
302
- for (const tracked of inlineAgentPanels.values()) tracked.cleanup();
303
- inlineAgentPanels.clear();
302
+ for (const tracked of anchoredAgentPanels.values()) tracked.cleanup();
303
+ anchoredAgentPanels.clear();
304
304
  };
305
305
 
306
- const inlineAgentPanelAnchor = (options, key) => {
306
+ const agentPanelAnchor = (options, key, layout) => {
307
307
  const anchor = options.anchor;
308
308
  if (!(anchor instanceof Element)) {
309
- throw new Error('Inline Agent panel anchor must be an element');
309
+ throw new Error('Agent panel anchor must be an element');
310
310
  }
311
311
  const rect = anchor.getBoundingClientRect();
312
312
  if (![rect.top, rect.left, rect.width, rect.height].every(Number.isFinite)) {
313
- throw new Error('Inline Agent panel anchor returned invalid bounds');
313
+ throw new Error('Agent panel anchor returned invalid bounds');
314
314
  }
315
315
  return {
316
316
  element: anchor,
317
317
  key,
318
+ layout,
318
319
  bounds: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },
319
320
  };
320
321
  };
321
322
 
322
- const trackInlineAgentPanel = presentation => {
323
- stopInlineAgentPanelTracking(presentation.key);
323
+ const trackAgentAnchor = presentation => {
324
+ if (presentation.layout === 'workspace' || [...anchoredAgentPanels.values()].some(item => item.presentation.layout === 'workspace')) {
325
+ stopAgentAnchorTracking();
326
+ } else {
327
+ stopAgentAnchorTracking(presentation.key);
328
+ }
324
329
  let frame = null;
325
330
  const update = () => {
326
331
  frame = null;
@@ -366,7 +371,7 @@ Expecting one of '${allowedValues.join("', '")}'`);let helpEvent=`${position}Hel
366
371
  window.removeEventListener('resize', schedule);
367
372
  document.removeEventListener('scroll', schedule, true);
368
373
  };
369
- inlineAgentPanels.set(presentation.key, { presentation, cleanup });
374
+ anchoredAgentPanels.set(presentation.key, { presentation, cleanup });
370
375
  };
371
376
 
372
377
  const scrollInlineAgentPage = (presentation, deltaX, deltaY) => {
@@ -396,8 +401,11 @@ Expecting one of '${allowedValues.join("', '")}'`);let helpEvent=`${position}Hel
396
401
  };
397
402
 
398
403
  const agentPanelPresentation = (options, layout, key) => {
399
- if (layout !== 'inline') return null;
400
- return inlineAgentPanelAnchor(options, key);
404
+ if (layout === 'inline') return agentPanelAnchor(options, key, layout);
405
+ if (layout === 'workspace' && options.anchor !== undefined) {
406
+ return agentPanelAnchor(options, key || 'toolbox-workspace', layout);
407
+ }
408
+ return null;
401
409
  };
402
410
 
403
411
  const setAgentPanelVisible = async (visible, options = {}) => {
@@ -417,16 +425,16 @@ Expecting one of '${allowedValues.join("', '")}'`);let helpEvent=`${position}Hel
417
425
  });
418
426
  if (presentation) {
419
427
  await ready;
420
- trackInlineAgentPanel(presentation);
428
+ trackAgentAnchor(presentation);
421
429
  } else if (!visible && key) {
422
- stopInlineAgentPanelTracking(key);
430
+ stopAgentAnchorTracking(key);
423
431
  } else {
424
- stopInlineAgentPanelTracking();
432
+ stopAgentAnchorTracking();
425
433
  }
426
434
  try {
427
435
  await request;
428
436
  } catch (error) {
429
- if (presentation) stopInlineAgentPanelTracking(presentation.key);
437
+ if (presentation) stopAgentAnchorTracking(presentation.key);
430
438
  throw error;
431
439
  }
432
440
  };
@@ -494,14 +502,14 @@ Expecting one of '${allowedValues.join("', '")}'`);let helpEvent=`${position}Hel
494
502
  });
495
503
  if (presentation) {
496
504
  await ready;
497
- trackInlineAgentPanel(presentation);
505
+ trackAgentAnchor(presentation);
498
506
  } else {
499
- stopInlineAgentPanelTracking();
507
+ stopAgentAnchorTracking();
500
508
  }
501
509
  try {
502
510
  await request;
503
511
  } catch (error) {
504
- if (presentation) stopInlineAgentPanelTracking(presentation.key);
512
+ if (presentation) stopAgentAnchorTracking(presentation.key);
505
513
  throw error;
506
514
  }
507
515
  };
@@ -565,14 +573,14 @@ Expecting one of '${allowedValues.join("', '")}'`);let helpEvent=`${position}Hel
565
573
  if (
566
574
  response?.type === 'agent-panel-wheel' &&
567
575
  typeof response.key === 'string' &&
568
- inlineAgentPanels.has(response.key) &&
576
+ anchoredAgentPanels.has(response.key) &&
569
577
  typeof response.deltaX === 'number' &&
570
578
  Number.isFinite(response.deltaX) &&
571
579
  typeof response.deltaY === 'number' &&
572
580
  Number.isFinite(response.deltaY)
573
581
  ) {
574
582
  scrollInlineAgentPage(
575
- inlineAgentPanels.get(response.key).presentation,
583
+ anchoredAgentPanels.get(response.key).presentation,
576
584
  response.deltaX,
577
585
  response.deltaY,
578
586
  );
@@ -892,7 +900,7 @@ except BaseException as error:
892
900
  `)}async function refreshRegisteredPlugin(name,includePage=!1){let key=`${pluginDirectory()}/${name}`,pending=registrationRefreshes.get(key);if(pending)return await pending,refreshRegisteredPlugin(name,includePage);let registration=findPluginRegistration(name);if(!registration)return;let entryChanged=pluginRegistrationNeedsRefresh(registration);if(!entryChanged&&(!includePage||!pluginRegistrationNeedsRefresh(registration,!0)))return registration;let refresh=(async()=>{let entryVersion=pluginFileVersion(registration.entry),loaded=entryChanged?await loadPlugin(registration.entry,{options:{},invoke:async()=>{throw new Error("注册时不能执行浏览器操作")},progress:()=>{throw new Error("注册时不能报告执行进度")}},name):registration,current=findPluginRegistration(name);if(JSON.stringify(current)!==JSON.stringify(registration))return current;if(pluginFileVersion(registration.entry)!==entryVersion)throw new PluginError("PLUGIN_SOURCE_CHANGED",`插件更新进行中,请重新打开工具: ${name}`);return registerPlugin(name,registration.entry,loaded.description,{toolbox:loaded.toolbox,...registration.managedBy?{managedBy:registration.managedBy}:{}}),findPluginRegistration(name)})();registrationRefreshes.set(key,refresh);try{return await refresh}finally{registrationRefreshes.delete(key)}}async function loadPlugin(entry,context,pluginName){let entryVersion;try{entryVersion=pluginFileVersion(entry)}catch{throw new PluginError("PLUGIN_ENTRY_MISSING",missingPluginEntryMessage(entry,pluginName))}let commands=new Map,executing=!1,registering=!0,name,description,toolbox,app=Object.freeze({options:Object.freeze({...context.options}),command(signature,handler,description2="",examples=[]){if(!registering)throw new Error("命令只能在入口注册阶段声明");let[name2,...args]=signature.trim().split(/\s+/);if(!/^[a-z][a-z0-9-]*$/.test(name2)||commands.has(name2)||typeof handler!="function"||!Array.isArray(examples)||examples.some(example=>typeof example!="string"||!example.trim()))throw new Error(`无效或重复的命令: ${signature}`);let command=new Command(name2).description(description2);for(let argument of args){if(!/^(?:<[a-zA-Z][\w-]*(?:\.\.\.)?>|\[[a-zA-Z][\w-]*(?:\.\.\.)?\])$/.test(argument))throw new Error(`无效的位置参数: ${argument}`);command.argument(argument)}let names=command.registeredArguments.map(argument=>argument.name());if(new Set(names).size!==names.length)throw new Error(`参数名称重复: ${signature}`);commands.set(name2,{command,signature,handler,examples:[...examples]})},invoke(action,payload={},options={}){if(!executing)throw new Error("app.invoke 只能在命令执行期间调用");return context.invoke(action,payload,options)},progress(progress){if(!executing)throw new Error("app.progress 只能在命令执行期间调用");context.progress(normalizePluginProgress(progress))}});try{if(extname2(entry).toLowerCase()===".py"){let descriptor=await describePythonPlugin(entry,app.options);name=descriptor.name,description=descriptor.description,toolbox=normalizePluginToolboxContribution(descriptor.toolbox);for(let command of descriptor.commands){let commandName=command.signature.trim().split(/\s+/)[0];app.command(command.signature,input2=>runPythonPluginCommand(entry,commandName,input2,app),command.description)}}else{let moduleUrl=pathToFileURL(entry);moduleUrl.searchParams.set("mearl-version",entryVersion);let module=await import(moduleUrl.href);if(module.name!==void 0&&typeof module.name!="string")throw new Error("入口的 name 导出必须为字符串");if(name=module.name,module.description!==void 0&&typeof module.description!="string")throw new Error("入口的 description 导出必须为字符串");if(description=module.description,toolbox=normalizePluginToolboxContribution(module.toolbox),typeof module.default!="function")throw new Error("入口必须默认导出 register(app) 函数");await module.default(app)}if(commands.size===0)throw new Error("入口未注册任何命令");let toolboxCommands=toolbox?.page.commands??[];for(let command of toolboxCommands)if(!commands.has(command))throw new Error(`toolbox 命令未注册: ${command}`)}catch(error48){throw new PluginError("PLUGIN_LOAD_FAILED",`${entry}: ${error48 instanceof Error?error48.message:String(error48)}`)}finally{registering=!1}let find=name2=>{let command=commands.get(name2);if(!command)throw new PluginError("PLUGIN_COMMAND_NOT_FOUND",`未知子命令: ${name2}`);return command};return{name,description,toolbox,version:readPluginVersion(entry),commandHelp(namespace){return[...commands.values()].map(({command,signature})=>` ${namespace} ${signature} ${command.description()}`).join(`
893
901
  `)},help(namespace,name2){let selected=name2?[find(name2)]:[...commands.values()],examples=selected.flatMap(({examples:examples2})=>examples2);return["用法:",...selected.map(({command,signature})=>` ${namespace} ${signature} ${command.description()}`),...examples.length?["","示例:",...examples.map(example=>` ${namespace} ${example}`)]:[]].join(`
894
902
  `)},async run(positionals,payload,namedInput={}){if(payload!==void 0&&positionals.length>0)throw new PluginError("PLUGIN_INVALID_INPUT","位置参数调用与 --payload 调用不能混用");if(payload!==void 0&&Object.keys(namedInput).length>0)throw new PluginError("PLUGIN_INVALID_INPUT","插件业务选项与 --payload 调用不能混用");if(payload!==void 0&&(!isObject2(payload)||typeof payload.command!="string"||!isObject2(payload.input)))throw new PluginError("PLUGIN_INVALID_INPUT",'--payload 必须为 {"command":"...","input":{...}}');let envelope=payload,{command,handler}=find(envelope?.command??positionals[0]??""),positionalInput=envelope?{...envelope.input}:Object.fromEntries(command.registeredArguments.map((argument,index)=>[argument.name(),argument.variadic?positionals.slice(index+1):positionals[index+1]]).filter(([,value])=>value!==void 0));for(let name2 of Object.keys(namedInput))if(Object.hasOwn(positionalInput,name2))throw new PluginError("PLUGIN_INVALID_INPUT",`参数不能重复传入: ${name2}`);let input2={...positionalInput,...namedInput};if(!envelope&&!command.registeredArguments.some(argument=>argument.variadic)&&positionals.length-1>command.registeredArguments.length)throw new PluginError("PLUGIN_INVALID_INPUT","位置参数过多");for(let argument of command.registeredArguments){let value=Object.hasOwn(input2,argument.name())?input2[argument.name()]:void 0;if(argument.required&&(value==null||value===""||Array.isArray(value)&&value.length===0))throw new PluginError("PLUGIN_INVALID_INPUT",`缺少必填参数: ${argument.name()}`);if(argument.variadic&&value!==void 0&&!Array.isArray(value))throw new PluginError("PLUGIN_INVALID_INPUT",`${argument.name()} 必须为数组`)}executing=!0;try{return await handler(input2)}finally{executing=!1}}}}async function loadRegisteredPluginWithState(name,context,options={},state={stack:[]}){if(state.stack.includes(name))throw new PluginError("PLUGIN_INVOCATION_CYCLE",`插件调用形成循环: ${[...state.stack,name].join(" -> ")}`);let registration=findPluginRegistration(name);if(!registration&&findOfficialPlugin(name)&&(await(context.ensurePlugin??ensureOfficialPluginRegistered)(name,options.onProgress?message=>options.onProgress?.(message):void 0),registration=findPluginRegistration(name)),!registration)throw new PluginError("PLUGIN_NOT_REGISTERED",`插件未注册: ${name}`);let{onProgress,...invokeOptions}=options,childState={stack:[...state.stack,name]};return loadPlugin(registration.entry,{options:invokeOptions,progress:onProgress??(()=>{}),async invoke(action,payload,overrides){let nestedOptions={...invokeOptions,...overrides};if(COMMAND_MAP.has(action)||action==="connector_list"){let result2=await context.invoke(action,payload,nestedOptions);if(result2?.action?.success===!1)throw new Error(result2.action.error||`${action} failed`);return result2}let pluginInvocation=isPluginInvocation(payload);if(findPluginRegistration(action)||findOfficialPlugin(action)||pluginInvocation){if(!pluginInvocation)throw new PluginError("PLUGIN_INVALID_INPUT",`调用插件 ${action} 需要 {"command":"...","input":{...}}`);return invokeRegisteredPluginWithState(action,payload,context,{...nestedOptions,...onProgress?{onProgress}:{}},childState)}let result=await context.invoke(action,payload,nestedOptions);if(result?.action?.success===!1)throw new Error(result.action.error||`${action} failed`);return result}},name)}async function invokeRegisteredPluginWithState(name,invocation2,context,options={},state={stack:[]}){return(await loadRegisteredPluginWithState(name,context,options,state)).run([],invocation2)}function invokeRegisteredPlugin(name,invocation2,context,options={}){return invokeRegisteredPluginWithState(name,invocation2,context,options)}var registrationRefreshes,init_plugin=__esm({"../client/dist/plugin.js"(){"use strict";init_commander();init_commands();init_officialPluginCatalog();init_officialPluginInstaller();init_pluginRegistry();init_pluginSource();init_pythonPlugin();init_pluginRegistry();init_officialPluginCatalog();registrationRefreshes=new Map}});import fs10 from"node:fs";import os8 from"node:os";import path12 from"node:path";import{execFileSync}from"node:child_process";function resolveNativeHostDirectory(options={}){let env=options.env??process.env,home=(options.homedir??os8.homedir)();switch(options.platform??process.platform){case"darwin":return path12.join(home,"Library/Application Support/Google/Chrome/NativeMessagingHosts");case"linux":return path12.join(home,".config/google-chrome/NativeMessagingHosts");case"win32":return path12.join(env.PROGRAMDATA||"C:\\ProgramData","Google\\Chrome\\NativeMessagingHosts");default:throw new Error(`Unsupported platform: ${String(options.platform??process.platform)}`)}}function unregisterWindowsNativeHost(hostName){let registryKey=`HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;try{execFileSync("reg",["delete",registryKey,"/f"],{stdio:"pipe"})}catch{}}function uninstallNativeHostArtifacts(options={},dependencies={}){let{mode="both",silent=!1}=options;if(mode==="both")return["skills","mcp"].map(integrationMode=>uninstallNativeHostArtifacts({...options,mode:integrationMode},dependencies)).every(Boolean);let writeLine=dependencies.writeLine??(line=>console.error(line)),log2=line=>{silent||writeLine(line)};try{let existsSync11=dependencies.existsSync??fs10.existsSync,platform=dependencies.platform??process.platform,hostDir=dependencies.hostDir??resolveNativeHostDirectory({env:dependencies.env,homedir:dependencies.homedir,platform}),unlinkSync=dependencies.unlinkSync??fs10.unlinkSync,unregister=dependencies.unregisterWindowsNativeHost??unregisterWindowsNativeHost,hostName=MEARL_NATIVE_HOST_NAMES[mode],launcherExtension=platform==="win32"?"cmd":"sh",artifacts=[path12.join(hostDir,`${hostName}.json`),path12.join(hostDir,`${hostName}-launcher.${launcherExtension}`)];for(let artifact of artifacts)existsSync11(artifact)&&(unlinkSync(artifact),log2(`✅ Removed: ${artifact}`));return platform==="win32"&&unregister(hostName),!0}catch(error48){return log2(`❌ Uninstall failed: ${error48 instanceof Error?error48.message:String(error48)}`),!1}}var MEARL_NATIVE_HOST_NAMES,init_nativeHost=__esm({"../setup/dist/nativeHost.js"(){"use strict";MEARL_NATIVE_HOST_NAMES={skills:"com.alibaba.mearl.skills",mcp:"com.alibaba.mearl.mcp"}}});function initBrowserRegistry(deps){logFn=deps.log}function recordFileFor(browserId){return keyedConfigFile(BROWSERS_SUBDIR,browserId)}function persist(patch){if(!identity)return!1;let file2=recordFileFor(identity.browserId),previous=readRecord(file2);if(previous&&previous.pid!==process.pid&&isAlive(previous.pid))return!1;let 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{return previous?.pid===process.pid?writeRecordIfPid(file2,process.pid,record2):previous&&!removeRecordIfPid(file2,previous.pid)?!1:claimRecord(file2,record2)}catch(error48){return logFn("browser-registry: failed to write record:",String(error48)),!1}}async function retireUnreachableBrowserRecord(browserId,canConnect){let file2=recordFileFor(browserId),existing=readRecord(file2);return!existing||existing.pid===process.pid||!isAlive(existing.pid)||await canConnect(existing.socketPath)?!1:removeRecordIfPid(file2,existing.pid)}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(recordFileFor(info.browserId)),registered=persist({lastFocusedAt:info.preserveFocus===!1?info.lastFocusedAt??0:previous?.lastFocusedAt??info.lastFocusedAt??Date.now(),extensionVersion:info.extensionVersion});return logFn(`browser-registry: ${registered?"registered":"registration skipped"} ${info.browserName} (${info.browserId})`),registered}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=recordFileFor(identity.browserId);removeRecordIfPid(file2,process.pid)}function pruneDeadBrowsers(){let now=Date.now();for(let file2 of listRecordFiles(keyedDir(BROWSERS_SUBDIR))){let rec=readRecord(file2);if(!rec){removeInvalidRecord(file2);continue}isAlive(rec.pid)||now-(rec.updatedAt??0)>STALE_RECORD_TTL_MS&&removeRecordIfPid(file2,rec.pid)}}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))}var BROWSERS_SUBDIR,STALE_RECORD_TTL_MS,FOCUS_WRITE_THROTTLE_MS,identity,logFn,lastFocusWriteAt,focusFlushTimer,init_browser_registry=__esm({"src/browser-registry.ts"(){"use strict";init_dist2();BROWSERS_SUBDIR="browsers",STALE_RECORD_TTL_MS=5*6e4,FOCUS_WRITE_THROTTLE_MS=1e3,identity=null,logFn=()=>{};lastFocusWriteAt=0,focusFlushTimer=null}});import net3 from"node:net";function requestBrowserSocket(socketPath,action,data,version2,timeoutMs=6e4,browserId,host,routing){let id=`browser_manager_${Date.now()}_${Math.random().toString(36).slice(2,10)}`;return new Promise((resolve9,reject)=>{let client2=net3.createConnection(socketPath),lines=new Utf8LineBuffer(MAX_RESPONSE_BUFFER_SIZE),settled=!1,finish=(error48,result)=>{settled||(settled=!0,clearTimeout(timer),client2.removeAllListeners(),client2.destroy(),error48?reject(error48):resolve9(result))},timer=setTimeout(()=>finish(new Error(`Browser request timeout after ${timeoutMs}ms`)),timeoutMs);client2.on("connect",()=>{client2.write(`${JSON.stringify({id,action,data,version:version2,controlSource:routing?.controlSource??"local",...routing?.providerTarget?{providerTarget:routing.providerTarget}:{},...browserId?{browserId}:{},...host?{host}:{}})}
895
- `)}),client2.on("data",chunk=>{let result=lines.push(chunk);if(result.overflow){finish(new Error("Browser response exceeded the supported size"));return}for(let line of result.lines){let response;try{response=JSON.parse(line)}catch{continue}if(response.id===id){response.success?finish(void 0,response.data):finish(new Error(response.error||"Browser request failed"));return}}}),client2.on("error",error48=>finish(error48)),client2.on("end",()=>finish(new Error("Browser connection closed before responding"))),client2.on("close",()=>finish(new Error("Browser connection closed before responding")))})}var MAX_RESPONSE_BUFFER_SIZE,init_browser_socket_request=__esm({"src/browser-socket-request.ts"(){"use strict";init_socketLines();MAX_RESPONSE_BUFFER_SIZE=64*1024*1024}});var NATIVE_HOST_VERSION,init_version=__esm({"src/version.ts"(){"use strict";NATIVE_HOST_VERSION="2.20.0"}});import{isAbsolute as isAbsolute6}from"node:path";function identity2(browser){return`${browser.pid}:${browser.startedAt}:${browser.socketPath}`}var ProviderControlService,init_provider_control=__esm({"src/provider-control.ts"(){"use strict";init_dist();init_control_session_manager();ProviderControlService=class{constructor(dependencies){this.dependencies=dependencies}controls=new Map;retired=new Set;retire(manager){let cleanup=Promise.all(manager.registry.list().map(session=>manager.registry.waitForIdle(session.sessionId))).then(()=>manager.artifacts.dispose());this.retired.add(cleanup),cleanup.finally(()=>this.retired.delete(cleanup)).catch(()=>{})}reap(){let browsers=this.dependencies.browsers();for(let[browserId,control]of this.controls){let browser=browsers.find(item=>item.browserId===browserId);(!browser||identity2(browser)!==control.identity)&&(this.controls.delete(browserId),this.retire(control.manager))}}browser(browserId){let browser=this.dependencies.browsers().find(item=>item.browserId===browserId);if(browser?.transport!=="provider"||!browser.providerBrowserId)throw new Error("CONTROL_SESSION_NOT_FOUND: Provider browser is unavailable");return browser}list(){return this.reap(),[...this.controls.values()].flatMap(control=>control.manager.registry.list())}async userControl(sessionId,operation){this.reap();for(let[browserId,control]of this.controls){try{control.manager.registry.info(sessionId)}catch{continue}if(identity2(this.browser(browserId))!==control.identity)throw new Error("CONTROL_SESSION_NOT_FOUND");return control.manager.userControl(sessionId,operation)}throw new Error("CONTROL_SESSION_NOT_FOUND")}getControl(browser){let previous=this.controls.get(browser.browserId);if(previous?.identity===identity2(browser))return previous;previous&&this.retire(previous.manager);let control={identity:identity2(browser),manager:new ControlSessionManager({browserId:()=>browser.browserId,transport:()=>"provider",invoke:async(action,payload)=>{let current=this.browser(browser.browserId);if(identity2(current)!==control.identity)throw new Error("CONTROL_SESSION_NOT_FOUND");let{__mearlControlSource:origin="local",__mearlBlockedTabIds:blocked,...data}=payload;if(action==="tab_open"&&blocked?.length&&data.reuse!=="never"){let result=await this.request(current,"tab_list",{},origin);if(!Array.isArray(result.tabs))throw new Error("Provider did not return its current pages");if(findMatchingTabs(result.tabs,data.url,data.match).some(tab=>blocked.includes(tab.tabId??tab.id)))throw new Error("TAB_CONTROLLED_BY_SESSION")}return this.request(current,action,data,origin)},cleanup:async(tabs,_transport,preserveEnvironment)=>{preserveEnvironment||await this.clearEnvironment(browser.browserId,tabs)},download:async(data,_transport,origin)=>{let current=this.browser(browser.browserId);if(identity2(current)!==control.identity)throw new Error("CONTROL_SESSION_NOT_FOUND");let result=await this.request(current,"page_download",data,origin);if(!result||typeof result.filename!="string"||!result.filename||typeof result.filePath!="string"||!isAbsolute6(result.filePath)||!Object.hasOwn(result,"action")||result.owned!==void 0&&typeof result.owned!="boolean")throw new Error("Provider page_download must return a completed file with filename, absolute filePath and action");return{filename:result.filename,filePath:result.filePath,action:result.action,owned:result.owned===!0}},notify:this.dependencies.notify})};return this.controls.set(browser.browserId,control),control}async request(browser,action,data,origin,host){let lifecycle=action==="browser_close"?data.deleteProfile===!0?"deleteData":"close":action==="browser_release"?"detach":action==="get_browser_access_url"?"access":action==="browser_manager_start"?"start":action==="browser_manager_sync_cookies"?"syncCookies":void 0;if(lifecycle&&!browser.operations?.includes(lifecycle))throw new Error(`Provider browser does not support ${lifecycle}`);if(!lifecycle&&action!=="get_versions"){if(browser.status!=="connected")throw new Error("Provider browser is not connected");if(!browser.capabilities?.actions.some(capability=>capability===action))throw new Error(`Provider browser does not support ${action}`)}return this.dependencies.request(browser,action,data,origin,host)}async clearEnvironment(browserId,tabs){let browser=this.browser(browserId),actions=new Set(browser.capabilities?.actions??[]);if(actions.has("set_mock")&&!actions.has("get_mocks"))throw new Error("Provider cannot enumerate Mock state for cleanup");let clear=async(action,data)=>{let result=await this.request(browser,action,data,"local");if(result?.success===!1||result?.action?.success===!1)throw new Error(result.error??result.action?.error??"Provider environment cleanup failed")};for(let tabId of tabs){if(actions.has("set_mock")){let result=await this.request(browser,"get_mocks",{tabId},"local");if(!Array.isArray(result.mocks))throw new Error("Provider did not return its Mock state");let names=new Set(result.mocks.map(mock=>mock.apiName));for(let apiName of names)await clear("set_mock",{tabId,apiName,enabled:!1})}for(let[action,data]of[["set_app_profile",{tabId,enabled:!1,mtopEnv:"default"}],["set_device_emulation",{tabId,enabled:!1}],["set_timezone",{tabId,timezone:""}]])actions.has(action)&&await clear(action,data)}}async invoke(browserId,action,data={},sessionId,origin="local",host){this.reap();let browser=this.browser(browserId),{manager}=this.getControl(browser);return action==="get_versions"||action==="get_browser_access_url"?this.request(browser,action,data,origin):action==="browser_manager_start"||action==="browser_manager_sync_cookies"?manager.registry.releaseBrowser(()=>this.request(browser,action,data,origin,host)):manager.invoke(action,data,sessionId,void 0,origin)}async dispose(){await Promise.all([...this.retired,...[...this.controls.values()].map(async({manager})=>{await Promise.all(manager.registry.list().map(session=>manager.registry.waitForIdle(session.sessionId))),await manager.artifacts.dispose()})])}}}});var provider_control_host_exports={};__export(provider_control_host_exports,{runProviderControlHost:()=>runProviderControlHost});import net4 from"node:net";import{chmodSync as chmodSync2,rmSync as rmSync8}from"node:fs";import{randomUUID as randomUUID16}from"node:crypto";async function runProviderControlHost(token){let file2=providerControlHostFile(),owner=readRecord(file2);if(!owner||owner.token!==token)throw new Error("Provider control host startup ownership was lost");let socketPath=providerControlSocketPath(process.pid);if(!writeRecordIfPid(file2,owner.pid,{pid:process.pid,socketPath,token,ready:!1}))throw new Error("Provider control host startup ownership was lost");let connections=new Set,service=new ProviderControlService({browsers:listRegisteredBrowsers,request:(browser,action,data,origin,host)=>requestBrowserSocket(browser.socketPath,action,data,NATIVE_HOST_VERSION,12e4,browser.providerBrowserId,host,{controlSource:origin}),notify:()=>{for(let browser of listRegisteredBrowsers())browser.transport==="extension"&&requestBrowserSocket(browser.socketPath,"provider_control_sessions_changed",{},NATIVE_HOST_VERSION,5e3).catch(()=>{})}}),server=net4.createServer(socket=>{connections.add(socket),socket.on("error",()=>{}),socket.once("close",()=>connections.delete(socket));let lines=new Utf8LineBuffer(16*1024*1024);socket.on("data",chunk=>{let result=lines.push(chunk);if(result.overflow)return socket.destroy();for(let line of result.lines)handle(line,socket)})});async function handle(line,socket){let id="";try{let request=JSON.parse(line);id=typeof request.id=="string"?request.id:randomUUID16();let data=request.data??{},result;if(request.action==="control_sessions_list")result={sessions:service.list()};else if(request.action==="control_session_update"){if(!["handoff","resume","release"].includes(data.operation))throw new Error("Invalid control operation");result={session:await service.userControl(data.sessionId,data.operation)}}else{if(typeof request.providerTarget!="string"||typeof request.action!="string")throw new Error("Provider browser and action are required");if(!data||typeof data!="object"||Array.isArray(data))throw new Error("Invalid action payload");if(request.transport&&request.transport!=="provider")throw new Error("A session cannot change transport");result=await service.invoke(request.providerTarget,request.action,data,request.controlSessionId,request.controlSource??"local",request.host)}socket.destroyed||socket.write(JSON.stringify({id,success:!0,data:result})+`
903
+ `)}),client2.on("data",chunk=>{let result=lines.push(chunk);if(result.overflow){finish(new Error("Browser response exceeded the supported size"));return}for(let line of result.lines){let response;try{response=JSON.parse(line)}catch{continue}if(response.id===id){response.success?finish(void 0,response.data):finish(new Error(response.error||"Browser request failed"));return}}}),client2.on("error",error48=>finish(error48)),client2.on("end",()=>finish(new Error("Browser connection closed before responding"))),client2.on("close",()=>finish(new Error("Browser connection closed before responding")))})}var MAX_RESPONSE_BUFFER_SIZE,init_browser_socket_request=__esm({"src/browser-socket-request.ts"(){"use strict";init_socketLines();MAX_RESPONSE_BUFFER_SIZE=64*1024*1024}});var NATIVE_HOST_VERSION,init_version=__esm({"src/version.ts"(){"use strict";NATIVE_HOST_VERSION="2.20.1"}});import{isAbsolute as isAbsolute6}from"node:path";function identity2(browser){return`${browser.pid}:${browser.startedAt}:${browser.socketPath}`}var ProviderControlService,init_provider_control=__esm({"src/provider-control.ts"(){"use strict";init_dist();init_control_session_manager();ProviderControlService=class{constructor(dependencies){this.dependencies=dependencies}controls=new Map;retired=new Set;retire(manager){let cleanup=Promise.all(manager.registry.list().map(session=>manager.registry.waitForIdle(session.sessionId))).then(()=>manager.artifacts.dispose());this.retired.add(cleanup),cleanup.finally(()=>this.retired.delete(cleanup)).catch(()=>{})}reap(){let browsers=this.dependencies.browsers();for(let[browserId,control]of this.controls){let browser=browsers.find(item=>item.browserId===browserId);(!browser||identity2(browser)!==control.identity)&&(this.controls.delete(browserId),this.retire(control.manager))}}browser(browserId){let browser=this.dependencies.browsers().find(item=>item.browserId===browserId);if(browser?.transport!=="provider"||!browser.providerBrowserId)throw new Error("CONTROL_SESSION_NOT_FOUND: Provider browser is unavailable");return browser}list(){return this.reap(),[...this.controls.values()].flatMap(control=>control.manager.registry.list())}async userControl(sessionId,operation){this.reap();for(let[browserId,control]of this.controls){try{control.manager.registry.info(sessionId)}catch{continue}if(identity2(this.browser(browserId))!==control.identity)throw new Error("CONTROL_SESSION_NOT_FOUND");return control.manager.userControl(sessionId,operation)}throw new Error("CONTROL_SESSION_NOT_FOUND")}getControl(browser){let previous=this.controls.get(browser.browserId);if(previous?.identity===identity2(browser))return previous;previous&&this.retire(previous.manager);let control={identity:identity2(browser),manager:new ControlSessionManager({browserId:()=>browser.browserId,transport:()=>"provider",invoke:async(action,payload)=>{let current=this.browser(browser.browserId);if(identity2(current)!==control.identity)throw new Error("CONTROL_SESSION_NOT_FOUND");let{__mearlControlSource:origin="local",__mearlBlockedTabIds:blocked,...data}=payload;if(action==="tab_open"&&blocked?.length&&data.reuse!=="never"){let result=await this.request(current,"tab_list",{},origin);if(!Array.isArray(result.tabs))throw new Error("Provider did not return its current pages");if(findMatchingTabs(result.tabs,data.url,data.match).some(tab=>blocked.includes(tab.tabId??tab.id)))throw new Error("TAB_CONTROLLED_BY_SESSION")}return this.request(current,action,data,origin)},cleanup:async(tabs,_transport,preserveEnvironment)=>{preserveEnvironment||await this.clearEnvironment(browser.browserId,tabs)},download:async(data,_transport,origin)=>{let current=this.browser(browser.browserId);if(identity2(current)!==control.identity)throw new Error("CONTROL_SESSION_NOT_FOUND");let result=await this.request(current,"page_download",data,origin);if(!result||typeof result.filename!="string"||!result.filename||typeof result.filePath!="string"||!isAbsolute6(result.filePath)||!Object.hasOwn(result,"action")||result.owned!==void 0&&typeof result.owned!="boolean")throw new Error("Provider page_download must return a completed file with filename, absolute filePath and action");return{filename:result.filename,filePath:result.filePath,action:result.action,owned:result.owned===!0}},notify:this.dependencies.notify})};return this.controls.set(browser.browserId,control),control}async request(browser,action,data,origin,host){let lifecycle=action==="browser_close"?data.deleteProfile===!0?"deleteData":"close":action==="browser_release"?"detach":action==="get_browser_access_url"?"access":action==="browser_manager_start"?"start":action==="browser_manager_sync_cookies"?"syncCookies":void 0;if(lifecycle&&!browser.operations?.includes(lifecycle))throw new Error(`Provider browser does not support ${lifecycle}`);if(!lifecycle&&action!=="get_versions"){if(browser.status!=="connected")throw new Error("Provider browser is not connected");if(!browser.capabilities?.actions.some(capability=>capability===action))throw new Error(`Provider browser does not support ${action}`)}return this.dependencies.request(browser,action,data,origin,host)}async clearEnvironment(browserId,tabs){let browser=this.browser(browserId),actions=new Set(browser.capabilities?.actions??[]);if(actions.has("set_mock")&&!actions.has("get_mocks"))throw new Error("Provider cannot enumerate Mock state for cleanup");let clear=async(action,data)=>{let result=await this.request(browser,action,data,"local");if(result?.success===!1||result?.action?.success===!1)throw new Error(result.error??result.action?.error??"Provider environment cleanup failed")};for(let tabId of tabs){if(actions.has("set_mock")){let result=await this.request(browser,"get_mocks",{tabId},"local");if(!Array.isArray(result.mocks))throw new Error("Provider did not return its Mock state");let names=new Set(result.mocks.map(mock=>mock.apiName));for(let apiName of names)await clear("set_mock",{tabId,apiName,enabled:!1})}for(let[action,data]of[["set_app_profile",{tabId,enabled:!1,mtopEnv:"default"}],["set_device_emulation",{tabId,enabled:!1}],["set_timezone",{tabId,timezone:""}]])actions.has(action)&&await clear(action,data)}}async invoke(browserId,action,data={},sessionId,origin="local",host){this.reap();let browser=this.browser(browserId),{manager}=this.getControl(browser);return action==="get_versions"||action==="get_browser_access_url"?this.request(browser,action,data,origin):action==="browser_manager_start"||action==="browser_manager_sync_cookies"?manager.registry.releaseBrowser(()=>this.request(browser,action,data,origin,host)):manager.invoke(action,data,sessionId,void 0,origin)}async dispose(){await Promise.all([...this.retired,...[...this.controls.values()].map(async({manager})=>{await Promise.all(manager.registry.list().map(session=>manager.registry.waitForIdle(session.sessionId))),await manager.artifacts.dispose()})])}}}});var provider_control_host_exports={};__export(provider_control_host_exports,{runProviderControlHost:()=>runProviderControlHost});import net4 from"node:net";import{chmodSync as chmodSync2,rmSync as rmSync8}from"node:fs";import{randomUUID as randomUUID16}from"node:crypto";async function runProviderControlHost(token){let file2=providerControlHostFile(),owner=readRecord(file2);if(!owner||owner.token!==token)throw new Error("Provider control host startup ownership was lost");let socketPath=providerControlSocketPath(process.pid);if(!writeRecordIfPid(file2,owner.pid,{pid:process.pid,socketPath,token,ready:!1}))throw new Error("Provider control host startup ownership was lost");let connections=new Set,service=new ProviderControlService({browsers:listRegisteredBrowsers,request:(browser,action,data,origin,host)=>requestBrowserSocket(browser.socketPath,action,data,NATIVE_HOST_VERSION,12e4,browser.providerBrowserId,host,{controlSource:origin}),notify:()=>{for(let browser of listRegisteredBrowsers())browser.transport==="extension"&&requestBrowserSocket(browser.socketPath,"provider_control_sessions_changed",{},NATIVE_HOST_VERSION,5e3).catch(()=>{})}}),server=net4.createServer(socket=>{connections.add(socket),socket.on("error",()=>{}),socket.once("close",()=>connections.delete(socket));let lines=new Utf8LineBuffer(16*1024*1024);socket.on("data",chunk=>{let result=lines.push(chunk);if(result.overflow)return socket.destroy();for(let line of result.lines)handle(line,socket)})});async function handle(line,socket){let id="";try{let request=JSON.parse(line);id=typeof request.id=="string"?request.id:randomUUID16();let data=request.data??{},result;if(request.action==="control_sessions_list")result={sessions:service.list()};else if(request.action==="control_session_update"){if(!["handoff","resume","release"].includes(data.operation))throw new Error("Invalid control operation");result={session:await service.userControl(data.sessionId,data.operation)}}else{if(typeof request.providerTarget!="string"||typeof request.action!="string")throw new Error("Provider browser and action are required");if(!data||typeof data!="object"||Array.isArray(data))throw new Error("Invalid action payload");if(request.transport&&request.transport!=="provider")throw new Error("A session cannot change transport");result=await service.invoke(request.providerTarget,request.action,data,request.controlSessionId,request.controlSource??"local",request.host)}socket.destroyed||socket.write(JSON.stringify({id,success:!0,data:result})+`
896
904
  `)}catch(error48){socket.destroyed||socket.write(JSON.stringify({id,success:!1,error:error48 instanceof Error?error48.message:String(error48)})+`
897
905
  `)}}try{if(await new Promise((resolve9,reject)=>{server.once("error",reject),server.listen(socketPath,()=>{server.removeListener("error",reject),resolve9()})}),process.platform!=="win32"&&chmodSync2(socketPath,384),!writeRecordIfPid(file2,process.pid,{pid:process.pid,socketPath,token,ready:!0}))throw new Error("Provider control host startup ownership was lost");await new Promise(resolve9=>{let stop=()=>{removeRecordIfPid(file2,process.pid);for(let socket of connections)socket.destroy();server.close(()=>resolve9())};process.once("SIGTERM",stop),process.once("SIGINT",stop)})}finally{removeRecordIfPid(file2,process.pid);for(let socket of connections)socket.destroy();server.close(),process.platform!=="win32"&&rmSync8(socketPath,{force:!0}),await service.dispose()}}var init_provider_control_host=__esm({"src/provider-control-host.ts"(){"use strict";init_dist2();init_host();init_browser_registry();init_browser_socket_request();init_provider_control();init_socketLines();init_version()}});var install_exports={};__export(install_exports,{installNativeHost:()=>installNativeHost,parseNativeHostInstallArgs:()=>parseNativeHostInstallArgs,resolveHostDir:()=>resolveHostDir,runCli:()=>runCli,uninstallNativeHost:()=>uninstallNativeHost});import fs20 from"node:fs";import path23 from"node:path";import{execFileSync as execFileSync2}from"node:child_process";import{createRequire as createRequire4}from"node:module";import{fileURLToPath as fileURLToPath2}from"node:url";function resolveHostDir(){return resolveNativeHostDirectory()}function resolveNativeHostPath(){let siblingPath=path23.join(__dirname,"index.js");if(fs20.existsSync(siblingPath))return siblingPath;try{return createRequire4(import.meta.url).resolve("@mearl/native-host/runtime")}catch{throw new Error("Cannot locate native-host runtime entry point. Ensure @mearl/native-host is installed correctly.")}}function registerWindowsNativeHost(hostName,manifestPath){let regKey=`HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;execFileSync2("reg",["add",regKey,"/ve","/t","REG_SZ","/d",manifestPath,"/f"],{stdio:"pipe"})}function createLauncherScript(hostDir,hostPath,hostName){let nodePath=path23.resolve(process.execPath);if(process.platform==="win32"){let launcherPath2=path23.join(hostDir,`${hostName}-launcher.cmd`),content2=`@echo off\r
898
906
  "${nodePath}" "${hostPath}" %*\r
@@ -1517,7 +1525,7 @@ Content-Type: ${file2.contentType}\r
1517
1525
  `),file2.content,Buffer.from(`\r
1518
1526
  `))}return chunks.push(Buffer.from(`--${boundary}--\r
1519
1527
  `)),{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}),contentType2=(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(contentType2))responseBody=result.bodyBuffer.toString("base64"),bodyType="base64";else{let trimmed=result.body.trimStart();if(responseType==="json"||responseType==="auto"&&contentType2.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)}}registerActions([{name:"send_request",session:"page",handler:cdpSendRequest},{name:"send_mtop_request",session:"page",handler:cdpSendMtopRequest}]);var MTOP_GATEWAY_FAMILIES=[{prod:"h5api.m.taobao.com",pre:"h5api.wapa.taobao.com"},{prod:"h5api.m.alibaba-inc.com",pre:"h5api.wapa.alibaba-inc.com"}],environments=new WeakMap;function rewriteMtopGatewayUrl(url2,target){try{let parsed=new URL(url2),family=MTOP_GATEWAY_FAMILIES.find(item=>Object.values(item).includes(parsed.hostname));return!family||parsed.hostname===family[target]?url2:(parsed.hostname=family[target],parsed.toString())}catch{return url2}}function isMtopGatewayUrl(url2){try{let host=new URL(url2).hostname;return MTOP_GATEWAY_FAMILIES.some(family=>Object.values(family).includes(host))}catch{return!1}}function hasOriginHeader(request){return Object.keys(request.headers??{}).some(name=>name.toLowerCase()==="origin")}async function handleMtopEnvironmentRequest({session,params,isResponseStage}){let target=environments.get(session);if(!target)return!1;let request=params.request??{},url2=typeof request.url=="string"?request.url:"";if(!isMtopGatewayUrl(url2))return!1;if(!isResponseStage){let rewrittenUrl=rewriteMtopGatewayUrl(url2,target);return rewrittenUrl===url2?!1:(await session.client.sendCommand("Fetch.continueRequest",{requestId:params.requestId,url:rewrittenUrl}),!0)}if(params.responseStatusCode==null||!hasOriginHeader(request))return!1;let responseHeaders=ensureCorsHeaders([...params.responseHeaders??[]],request);return await session.client.sendCommand("Fetch.continueResponse",{requestId:params.requestId,responseCode:params.responseStatusCode,...typeof params.responseStatusText=="string"&&{responsePhrase:params.responseStatusText},responseHeaders}),!0}async function setCdpMtopEnvironment(session,target){if(target!=="default"&&target!=="prod"&&target!=="pre")throw new Error('set_app_profile: "mtopEnv" must be "default", "prod", or "pre"');if(target==="default"){environments.delete(session),await unregisterCdpFetchPauseHandler(session,"mtop-environment");return}environments.set(session,target);try{await registerCdpFetchPauseHandler(session,"mtop-environment",50,handleMtopEnvironmentRequest)}catch(error48){throw environments.delete(session),error48}}function clearCdpMtopEnvironmentState(sessions){if(!sessions){environments=new WeakMap;return}for(let session of sessions)environments.delete(session)}import{randomUUID as randomUUID10}from"node:crypto";var QrCodeDataType=(QrCodeDataType2=>(QrCodeDataType2[QrCodeDataType2.Border=-1]="Border",QrCodeDataType2[QrCodeDataType2.Data=0]="Data",QrCodeDataType2[QrCodeDataType2.Function=1]="Function",QrCodeDataType2[QrCodeDataType2.Position=2]="Position",QrCodeDataType2[QrCodeDataType2.Timing=3]="Timing",QrCodeDataType2[QrCodeDataType2.Alignment=4]="Alignment",QrCodeDataType2))(QrCodeDataType||{}),__defProp2=Object.defineProperty,__defNormalProp=(obj,key,value)=>key in obj?__defProp2(obj,key,{enumerable:!0,configurable:!0,writable:!0,value}):obj[key]=value,__publicField=(obj,key,value)=>(__defNormalProp(obj,typeof key!="symbol"?key+"":key,value),value),LOW=[0,1],MEDIUM=[1,0],QUARTILE=[2,3],HIGH=[3,2],EccMap={L:LOW,M:MEDIUM,Q:QUARTILE,H:HIGH},NUMERIC_REGEX=/^[0-9]*$/,ALPHANUMERIC_REGEX=/^[A-Z0-9 $%*+.\/:-]*$/,ALPHANUMERIC_CHARSET="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",MIN_VERSION=1,MAX_VERSION=40,PENALTY_N1=3,PENALTY_N2=3,PENALTY_N3=40,PENALTY_N4=10,ECC_CODEWORDS_PER_BLOCK=[[-1,7,10,15,20,26,18,20,24,30,18,20,24,26,30,22,24,28,30,28,28,28,28,30,30,26,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,10,16,26,18,24,16,18,22,22,26,30,22,22,24,24,28,28,26,26,26,26,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28],[-1,13,22,18,26,18,24,18,22,20,24,28,26,24,20,30,24,28,28,26,30,28,30,30,30,30,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,17,28,22,16,22,28,26,26,24,28,24,28,22,24,24,30,28,28,26,28,30,24,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30]],NUM_ERROR_CORRECTION_BLOCKS=[[-1,1,1,1,1,1,2,2,2,2,4,4,4,4,4,6,6,6,6,7,8,8,9,9,10,12,12,12,13,14,15,16,17,18,19,19,20,21,22,24,25],[-1,1,1,1,2,2,4,4,4,5,5,5,8,9,9,10,10,11,13,14,16,17,17,18,20,21,23,25,26,28,29,31,33,35,37,38,40,43,45,47,49],[-1,1,1,2,2,4,4,6,6,8,8,8,10,12,16,12,17,16,18,21,20,23,23,25,27,29,34,34,35,38,40,43,45,48,51,53,56,59,62,65,68],[-1,1,1,2,4,4,4,5,6,8,8,11,11,16,16,18,16,19,21,25,25,25,34,30,32,35,37,40,42,45,48,51,54,57,60,63,66,70,74,77,81]],QrCode=class{constructor(version2,ecc,dataCodewords,msk){if(this.version=version2,this.ecc=ecc,__publicField(this,"size"),__publicField(this,"mask"),__publicField(this,"modules",[]),__publicField(this,"types",[]),version2<MIN_VERSION||version2>MAX_VERSION)throw new RangeError("Version value out of range");if(msk<-1||msk>7)throw new RangeError("Mask value out of range");this.size=version2*4+17;let row=Array.from({length:this.size},()=>!1);for(let i=0;i<this.size;i++)this.modules.push(row.slice()),this.types.push(row.map(()=>0));this.drawFunctionPatterns();let allCodewords=this.addEccAndInterleave(dataCodewords);if(this.drawCodewords(allCodewords),msk===-1){let minPenalty=1e9;for(let i=0;i<8;i++){this.applyMask(i),this.drawFormatBits(i);let penalty=this.getPenaltyScore();penalty<minPenalty&&(msk=i,minPenalty=penalty),this.applyMask(i)}}this.mask=msk,this.applyMask(msk),this.drawFormatBits(msk)}getModule(x,y){return x>=0&&x<this.size&&y>=0&&y<this.size&&this.modules[y][x]}drawFunctionPatterns(){for(let i=0;i<this.size;i++)this.setFunctionModule(6,i,i%2===0,QrCodeDataType.Timing),this.setFunctionModule(i,6,i%2===0,QrCodeDataType.Timing);this.drawFinderPattern(3,3),this.drawFinderPattern(this.size-4,3),this.drawFinderPattern(3,this.size-4);let alignPatPos=this.getAlignmentPatternPositions(),numAlign=alignPatPos.length;for(let i=0;i<numAlign;i++)for(let j=0;j<numAlign;j++)i===0&&j===0||i===0&&j===numAlign-1||i===numAlign-1&&j===0||this.drawAlignmentPattern(alignPatPos[i],alignPatPos[j]);this.drawFormatBits(0),this.drawVersion()}drawFormatBits(mask){let data=this.ecc[1]<<3|mask,rem=data;for(let i=0;i<10;i++)rem=rem<<1^(rem>>>9)*1335;let bits=(data<<10|rem)^21522;for(let i=0;i<=5;i++)this.setFunctionModule(8,i,getBit(bits,i));this.setFunctionModule(8,7,getBit(bits,6)),this.setFunctionModule(8,8,getBit(bits,7)),this.setFunctionModule(7,8,getBit(bits,8));for(let i=9;i<15;i++)this.setFunctionModule(14-i,8,getBit(bits,i));for(let i=0;i<8;i++)this.setFunctionModule(this.size-1-i,8,getBit(bits,i));for(let i=8;i<15;i++)this.setFunctionModule(8,this.size-15+i,getBit(bits,i));this.setFunctionModule(8,this.size-8,!0)}drawVersion(){if(this.version<7)return;let rem=this.version;for(let i=0;i<12;i++)rem=rem<<1^(rem>>>11)*7973;let bits=this.version<<12|rem;for(let i=0;i<18;i++){let color=getBit(bits,i),a=this.size-11+i%3,b=Math.floor(i/3);this.setFunctionModule(a,b,color),this.setFunctionModule(b,a,color)}}drawFinderPattern(x,y){for(let dy=-4;dy<=4;dy++)for(let dx=-4;dx<=4;dx++){let dist=Math.max(Math.abs(dx),Math.abs(dy)),xx=x+dx,yy=y+dy;xx>=0&&xx<this.size&&yy>=0&&yy<this.size&&this.setFunctionModule(xx,yy,dist!==2&&dist!==4,QrCodeDataType.Position)}}drawAlignmentPattern(x,y){for(let dy=-2;dy<=2;dy++)for(let dx=-2;dx<=2;dx++)this.setFunctionModule(x+dx,y+dy,Math.max(Math.abs(dx),Math.abs(dy))!==1,QrCodeDataType.Alignment)}setFunctionModule(x,y,isDark,type=QrCodeDataType.Function){this.modules[y][x]=isDark,this.types[y][x]=type}addEccAndInterleave(data){let ver=this.version,ecl=this.ecc;if(data.length!==getNumDataCodewords(ver,ecl))throw new RangeError("Invalid argument");let numBlocks=NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver],blockEccLen=ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver],rawCodewords=Math.floor(getNumRawDataModules(ver)/8),numShortBlocks=numBlocks-rawCodewords%numBlocks,shortBlockLen=Math.floor(rawCodewords/numBlocks),blocks=[],rsDiv=reedSolomonComputeDivisor(blockEccLen);for(let i=0,k=0;i<numBlocks;i++){let dat=data.slice(k,k+shortBlockLen-blockEccLen+(i<numShortBlocks?0:1));k+=dat.length;let ecc=reedSolomonComputeRemainder(dat,rsDiv);i<numShortBlocks&&dat.push(0),blocks.push(dat.concat(ecc))}let result=[];for(let i=0;i<blocks[0].length;i++)blocks.forEach((block,j)=>{(i!==shortBlockLen-blockEccLen||j>=numShortBlocks)&&result.push(block[i])});return result}drawCodewords(data){if(data.length!==Math.floor(getNumRawDataModules(this.version)/8))throw new RangeError("Invalid argument");let i=0;for(let right=this.size-1;right>=1;right-=2){right===6&&(right=5);for(let vert=0;vert<this.size;vert++)for(let j=0;j<2;j++){let x=right-j,y=(right+1&2)===0?this.size-1-vert:vert;!this.types[y][x]&&i<data.length*8&&(this.modules[y][x]=getBit(data[i>>>3],7-(i&7)),i++)}}}applyMask(mask){if(mask<0||mask>7)throw new RangeError("Mask value out of range");for(let y=0;y<this.size;y++)for(let x=0;x<this.size;x++){let invert;switch(mask){case 0:invert=(x+y)%2===0;break;case 1:invert=y%2===0;break;case 2:invert=x%3===0;break;case 3:invert=(x+y)%3===0;break;case 4:invert=(Math.floor(x/3)+Math.floor(y/2))%2===0;break;case 5:invert=x*y%2+x*y%3===0;break;case 6:invert=(x*y%2+x*y%3)%2===0;break;case 7:invert=((x+y)%2+x*y%3)%2===0;break;default:throw new Error("Unreachable")}!this.types[y][x]&&invert&&(this.modules[y][x]=!this.modules[y][x])}}getPenaltyScore(){let result=0;for(let y=0;y<this.size;y++){let runColor=!1,runX=0,runHistory=[0,0,0,0,0,0,0];for(let x=0;x<this.size;x++)this.modules[y][x]===runColor?(runX++,runX===5?result+=PENALTY_N1:runX>5&&result++):(this.finderPenaltyAddHistory(runX,runHistory),runColor||(result+=this.finderPenaltyCountPatterns(runHistory)*PENALTY_N3),runColor=this.modules[y][x],runX=1);result+=this.finderPenaltyTerminateAndCount(runColor,runX,runHistory)*PENALTY_N3}for(let x=0;x<this.size;x++){let runColor=!1,runY=0,runHistory=[0,0,0,0,0,0,0];for(let y=0;y<this.size;y++)this.modules[y][x]===runColor?(runY++,runY===5?result+=PENALTY_N1:runY>5&&result++):(this.finderPenaltyAddHistory(runY,runHistory),runColor||(result+=this.finderPenaltyCountPatterns(runHistory)*PENALTY_N3),runColor=this.modules[y][x],runY=1);result+=this.finderPenaltyTerminateAndCount(runColor,runY,runHistory)*PENALTY_N3}for(let y=0;y<this.size-1;y++)for(let x=0;x<this.size-1;x++){let color=this.modules[y][x];color===this.modules[y][x+1]&&color===this.modules[y+1][x]&&color===this.modules[y+1][x+1]&&(result+=PENALTY_N2)}let dark=0;for(let row of this.modules)dark=row.reduce((sum,color)=>sum+(color?1:0),dark);let total=this.size*this.size,k=Math.ceil(Math.abs(dark*20-total*10)/total)-1;return result+=k*PENALTY_N4,result}getAlignmentPatternPositions(){if(this.version===1)return[];{let numAlign=Math.floor(this.version/7)+2,step=this.version===32?26:Math.ceil((this.version*4+4)/(numAlign*2-2))*2,result=[6];for(let pos=this.size-7;result.length<numAlign;pos-=step)result.splice(1,0,pos);return result}}finderPenaltyCountPatterns(runHistory){let n=runHistory[1],core=n>0&&runHistory[2]===n&&runHistory[3]===n*3&&runHistory[4]===n&&runHistory[5]===n;return(core&&runHistory[0]>=n*4&&runHistory[6]>=n?1:0)+(core&&runHistory[6]>=n*4&&runHistory[0]>=n?1:0)}finderPenaltyTerminateAndCount(currentRunColor,currentRunLength,runHistory){return currentRunColor&&(this.finderPenaltyAddHistory(currentRunLength,runHistory),currentRunLength=0),currentRunLength+=this.size,this.finderPenaltyAddHistory(currentRunLength,runHistory),this.finderPenaltyCountPatterns(runHistory)}finderPenaltyAddHistory(currentRunLength,runHistory){runHistory[0]===0&&(currentRunLength+=this.size),runHistory.pop(),runHistory.unshift(currentRunLength)}};function appendBits(val,len,bb){if(len<0||len>31||val>>>len)throw new RangeError("Value out of range");for(let i=len-1;i>=0;i--)bb.push(val>>>i&1)}function getBit(x,i){return(x>>>i&1)!==0}var QrSegment=class{constructor(mode,numChars,bitData){if(this.mode=mode,this.numChars=numChars,this.bitData=bitData,numChars<0)throw new RangeError("Invalid argument");this.bitData=bitData.slice()}getData(){return this.bitData.slice()}},MODE_NUMERIC=[1,10,12,14],MODE_ALPHANUMERIC=[2,9,11,13],MODE_BYTE=[4,8,16,16];function numCharCountBits(mode,ver){return mode[Math.floor((ver+7)/17)+1]}function makeBytes(data){let bb=[];for(let b of data)appendBits(b,8,bb);return new QrSegment(MODE_BYTE,data.length,bb)}function makeNumeric(digits){if(!isNumeric(digits))throw new RangeError("String contains non-numeric characters");let bb=[];for(let i=0;i<digits.length;){let n=Math.min(digits.length-i,3);appendBits(Number.parseInt(digits.substring(i,i+n),10),n*3+1,bb),i+=n}return new QrSegment(MODE_NUMERIC,digits.length,bb)}function makeAlphanumeric(text){if(!isAlphanumeric(text))throw new RangeError("String contains unencodable characters in alphanumeric mode");let bb=[],i;for(i=0;i+2<=text.length;i+=2){let temp=ALPHANUMERIC_CHARSET.indexOf(text.charAt(i))*45;temp+=ALPHANUMERIC_CHARSET.indexOf(text.charAt(i+1)),appendBits(temp,11,bb)}return i<text.length&&appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)),6,bb),new QrSegment(MODE_ALPHANUMERIC,text.length,bb)}function makeSegments(text){return text===""?[]:isNumeric(text)?[makeNumeric(text)]:isAlphanumeric(text)?[makeAlphanumeric(text)]:[makeBytes(toUtf8ByteArray(text))]}function isNumeric(text){return NUMERIC_REGEX.test(text)}function isAlphanumeric(text){return ALPHANUMERIC_REGEX.test(text)}function getTotalBits(segs,version2){let result=0;for(let seg of segs){let ccbits=numCharCountBits(seg.mode,version2);if(seg.numChars>=1<<ccbits)return Number.POSITIVE_INFINITY;result+=4+ccbits+seg.bitData.length}return result}function toUtf8ByteArray(str){str=encodeURI(str);let result=[];for(let i=0;i<str.length;i++)str.charAt(i)!=="%"?result.push(str.charCodeAt(i)):(result.push(Number.parseInt(str.substring(i+1,i+3),16)),i+=2);return result}function getNumRawDataModules(ver){if(ver<MIN_VERSION||ver>MAX_VERSION)throw new RangeError("Version number out of range");let result=(16*ver+128)*ver+64;if(ver>=2){let numAlign=Math.floor(ver/7)+2;result-=(25*numAlign-10)*numAlign-55,ver>=7&&(result-=36)}return result}function getNumDataCodewords(ver,ecl){return Math.floor(getNumRawDataModules(ver)/8)-ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver]*NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver]}function reedSolomonComputeDivisor(degree){if(degree<1||degree>255)throw new RangeError("Degree out of range");let result=[];for(let i=0;i<degree-1;i++)result.push(0);result.push(1);let root=1;for(let i=0;i<degree;i++){for(let j=0;j<result.length;j++)result[j]=reedSolomonMultiply(result[j],root),j+1<result.length&&(result[j]^=result[j+1]);root=reedSolomonMultiply(root,2)}return result}function reedSolomonComputeRemainder(data,divisor){let result=divisor.map(_=>0);for(let b of data){let factor=b^result.shift();result.push(0),divisor.forEach((coef,i)=>result[i]^=reedSolomonMultiply(coef,factor))}return result}function reedSolomonMultiply(x,y){if(x>>>8||y>>>8)throw new RangeError("Byte out of range");let z2=0;for(let i=7;i>=0;i--)z2=z2<<1^(z2>>>7)*285,z2^=(y>>>i&1)*x;return z2}function encodeSegments(segs,ecl,minVersion=1,maxVersion=40,mask=-1,boostEcl=!0){if(!(MIN_VERSION<=minVersion&&minVersion<=maxVersion&&maxVersion<=MAX_VERSION)||mask<-1||mask>7)throw new RangeError("Invalid value");let version2,dataUsedBits;for(version2=minVersion;;version2++){let dataCapacityBits2=getNumDataCodewords(version2,ecl)*8,usedBits=getTotalBits(segs,version2);if(usedBits<=dataCapacityBits2){dataUsedBits=usedBits;break}if(version2>=maxVersion)throw new RangeError("Data too long")}for(let newEcl of[MEDIUM,QUARTILE,HIGH])boostEcl&&dataUsedBits<=getNumDataCodewords(version2,newEcl)*8&&(ecl=newEcl);let bb=[];for(let seg of segs){appendBits(seg.mode[0],4,bb),appendBits(seg.numChars,numCharCountBits(seg.mode,version2),bb);for(let b of seg.getData())bb.push(b)}let dataCapacityBits=getNumDataCodewords(version2,ecl)*8;appendBits(0,Math.min(4,dataCapacityBits-bb.length),bb),appendBits(0,(8-bb.length%8)%8,bb);for(let padByte=236;bb.length<dataCapacityBits;padByte^=253)appendBits(padByte,8,bb);let dataCodewords=Array.from({length:Math.ceil(bb.length/8)},()=>0);return bb.forEach((b,i)=>dataCodewords[i>>>3]|=b<<7-(i&7)),new QrCode(version2,ecl,dataCodewords,mask)}function encode(data,options){let{ecc="L",boostEcc=!1,minVersion=1,maxVersion=40,maskPattern=-1,border=1}=options||{},segment=typeof data=="string"?makeSegments(data):Array.isArray(data)?[makeBytes(data)]:void 0;if(!segment)throw new Error(`uqr only supports encoding string and binary data, but got: ${typeof data}`);let qr=encodeSegments(segment,EccMap[ecc],minVersion,maxVersion,maskPattern,boostEcc),result=addBorder({version:qr.version,maskPattern:qr.mask,size:qr.size,data:qr.modules,types:qr.types},border);return options?.invert&&(result.data=result.data.map(row=>row.map(mod=>!mod))),options?.onEncoded?.(result),result}function addBorder(input2,border=1){if(!border)return input2;let{size}=input2,newSize=size+border*2;input2.size=newSize,input2.data.forEach(row=>{for(let i=0;i<border;i++)row.unshift(!1),row.push(!1)});for(let i=0;i<border;i++)input2.data.unshift(Array.from({length:newSize},_=>!1)),input2.data.push(Array.from({length:newSize},_=>!1));let b=QrCodeDataType.Border;input2.types.forEach(row=>{for(let i=0;i<border;i++)row.unshift(b),row.push(b)});for(let i=0;i<border;i++)input2.types.unshift(Array.from({length:newSize},_=>b)),input2.types.push(Array.from({length:newSize},_=>b));return input2}function renderSVG(data,options={}){let result=encode(data,options),{pixelSize=10,whiteColor="white",blackColor="black"}=options,height=result.size*pixelSize,width=result.size*pixelSize,svg=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}">`,pathes=[];for(let row=0;row<result.size;row++)for(let col=0;col<result.size;col++){let x=col*pixelSize,y=row*pixelSize;result.data[row][col]&&pathes.push(`M${x},${y}h${pixelSize}v${pixelSize}h-${pixelSize}z`)}return svg+=`<rect fill="${whiteColor}" width="${width}" height="${height}"/>`,svg+=`<path fill="${blackColor}" d="${pathes.join("")}"/>`,svg+="</svg>",svg}init_host();import fs3 from"node:fs";import path5 from"node:path";import fs2 from"node:fs";import path4 from"node:path";import{spawn as spawn4}from"node:child_process";var MAX_CAPTURE_LENGTH=1e6;function isExecutable(filePath,platform=process.platform){try{return fs2.accessSync(filePath,platform==="win32"?fs2.constants.F_OK:fs2.constants.X_OK),!0}catch{return!1}}function executableNames(name,platform=process.platform){return platform==="win32"?[`${name}.cmd`,`${name}.exe`,name]:[name]}function versionManagerExecutableCandidates(home,names,options={}){let env=options.env??process.env,platform=options.platform??process.platform,readdirSync4=options.readdirSync??fs2.readdirSync,fnmDefaultRoot=env.XDG_DATA_HOME?path4.join(env.XDG_DATA_HOME,"fnm"):platform==="darwin"?path4.join(home,"Library","Application Support","fnm"):platform==="win32"&&env.APPDATA?path4.join(env.APPDATA,"fnm"):path4.join(home,".local","share","fnm");return[path4.join(env.NVM_DIR||path4.join(home,".nvm"),"versions","node"),path4.join(env.FNM_DIR||fnmDefaultRoot,"node-versions"),path4.join(home,".fnm","node-versions")].filter((root,index,all)=>all.indexOf(root)===index).flatMap(root=>{try{return readdirSync4(root,{withFileTypes:!0}).filter(entry=>entry.isDirectory()).sort((left,right)=>right.name.localeCompare(left.name,void 0,{numeric:!0})).flatMap(entry=>names.flatMap(name=>[path4.join(root,entry.name,"bin",name),path4.join(root,entry.name,"installation","bin",name)]))}catch{return[]}})}function resolveSpawnCommand(executable,args,platform=process.platform,commandInterpreter=process.env.ComSpec){return platform==="win32"&&/\.(?:cmd|bat)$/i.test(executable)?{command:commandInterpreter||"cmd.exe",args:["/d","/s","/c",executable,...args]}:{command:executable,args}}function prependCommandPath(command,env=process.env){return path4.isAbsolute(command)?prependPathDirectory(path4.dirname(command),env):env}function prependNodePath(env=process.env,nodeExecutable=process.execPath){return prependPathDirectory(path4.dirname(nodeExecutable),env)}function prependPathDirectory(directory,env=process.env){let pathKey=Object.keys(env).find(key=>key.toLowerCase()==="path")||"PATH",entries=(env[pathKey]||"").split(path4.delimiter).filter(Boolean);return entries.includes(directory)?env:{...env,[pathKey]:[directory,...entries].join(path4.delimiter)}}function findExecutable(name,options={}){let env=options.env??process.env,platform=options.platform??process.platform,existsSync11=options.existsSync??(candidate=>isExecutable(candidate,platform)),pathKey=Object.keys(env).find(key=>key.toLowerCase()==="path")||"PATH",directories=[...options.extraDirectories??[],...(env[pathKey]??"").split(path4.delimiter).filter(Boolean)];for(let directory of directories)for(let executableName of executableNames(name,platform)){let candidate=path4.join(directory,executableName);if(existsSync11(candidate))return candidate}return null}var runCommand=(command,args,options={})=>new Promise((resolve9,reject)=>{let capture=options.capture===!0||options.tee===!0,launch=resolveSpawnCommand(command,args),child=spawn4(launch.command,launch.args,{cwd:options.cwd,env:options.env,stdio:capture?[options.tee?"inherit":"ignore","pipe","pipe"]:"inherit",windowsHide:!0}),stdout="",stderr="",settled=!1,append=(current,chunk)=>options.tee?(current+chunk).slice(-MAX_CAPTURE_LENGTH):current.length>=MAX_CAPTURE_LENGTH?current:(current+chunk).slice(0,MAX_CAPTURE_LENGTH),finish=(error48,code=1)=>{settled||(settled=!0,timer&&clearTimeout(timer),error48?reject(error48):resolve9({code,stdout,stderr}))},timer=options.timeoutMs===void 0?void 0:setTimeout(()=>{child.kill("SIGTERM"),finish(new Error(`Command timed out after ${options.timeoutMs}ms`))},options.timeoutMs);capture&&(child.stdout?.setEncoding("utf8").on("data",chunk=>{stdout=append(stdout,chunk),options.tee&&process.stdout.write(chunk)}),child.stderr?.setEncoding("utf8").on("data",chunk=>{stderr=append(stderr,chunk),options.tee&&process.stderr.write(chunk)})),child.once("error",error48=>finish(error48)),child.once("close",code=>finish(void 0,code??1))});function normalizePath(filePath){return filePath.replaceAll("\\","/").replace(/\/+$/,"")}function firstExisting(candidates,existsSync11){return candidates.find(candidate=>existsSync11(candidate))}function fallbackCommand(name,platform){return platform!=="win32"?name:name==="bun"||name==="volta"?`${name}.exe`:`${name}.cmd`}function resolvePackageManagerInstallation(packageRoot,packageName,options={}){let env=options.env??process.env,platform=options.platform??process.platform,existsSync11=options.existsSync??(candidate=>isExecutable(candidate,platform)),processExecPath=options.processExecPath??process.execPath,normalizedRoot=normalizePath(path5.resolve(packageRoot)),lowerRoot=normalizedRoot.toLowerCase(),lowerPackageName=packageName.toLowerCase(),pnpmGlobalRoot=/\/global\/\d+\/(?:\.pnpm\/.*\/)?node_modules\//.exec(lowerRoot);if(pnpmGlobalRoot&&lowerRoot.endsWith(`/node_modules/${lowerPackageName}`)){let pnpmHome=normalizedRoot.slice(0,pnpmGlobalRoot.index);return{manager:"pnpm",command:firstExisting([...executableNames("pnpm",platform).map(name=>path5.join(pnpmHome,name)),...executableNames("pnpm",platform).map(name=>path5.join(path5.dirname(processExecPath),name))],existsSync11)??fallbackCommand("pnpm",platform),binDirectory:pnpmHome}}let bunMarker=`/.bun/install/global/node_modules/${lowerPackageName}`;if(lowerRoot.endsWith(bunMarker)){let bunHome=normalizedRoot.slice(0,lowerRoot.indexOf("/.bun/"));return{manager:"bun",command:firstExisting(executableNames("bun",platform).map(name=>path5.join(bunHome,".bun","bin",name)),existsSync11)??fallbackCommand("bun",platform),binDirectory:path5.join(bunHome,".bun","bin")}}if((lowerRoot.includes("/.config/yarn/global/node_modules/")||lowerRoot.includes("/.yarn/global/node_modules/")||lowerRoot.includes("/yarn/global/node_modules/")||lowerRoot.includes("/yarn/data/global/node_modules/"))&&lowerRoot.endsWith(`/node_modules/${lowerPackageName}`)){let layout=[{marker:"/.config/yarn/global/",binSegments:[".yarn","bin"]},{marker:"/.yarn/global/",binSegments:[".yarn","bin"]},{marker:"/yarn/data/global/",binSegments:["yarn","bin"]},{marker:"/yarn/global/",binSegments:["yarn","bin"]}].find(candidate=>lowerRoot.includes(candidate.marker)),prefix=normalizedRoot.slice(0,lowerRoot.indexOf(layout.marker)),binDirectory=path5.join(prefix,...layout.binSegments);return{manager:"yarn",command:firstExisting([...executableNames("yarn",platform).map(name=>path5.join(binDirectory,name)),...executableNames("yarn",platform).map(name=>path5.join(path5.dirname(processExecPath),name))],existsSync11)??findExecutable("yarn",{env,existsSync:existsSync11,platform})??fallbackCommand("yarn",platform),binDirectory}}if(lowerRoot.includes("/.volta/tools/image/packages/")&&lowerRoot.endsWith(`/lib/node_modules/${lowerPackageName}`)){let voltaHome=normalizedRoot.slice(0,lowerRoot.indexOf("/.volta/"));return{manager:"volta",command:firstExisting(executableNames("volta",platform).map(name=>path5.join(voltaHome,".volta","bin",name)),existsSync11)??fallbackCommand("volta",platform),binDirectory:path5.join(voltaHome,".volta","bin")}}let npmMarker=`/lib/node_modules/${lowerPackageName}`;if(lowerRoot.endsWith(npmMarker)){let prefix=normalizedRoot.slice(0,lowerRoot.length-npmMarker.length);return{manager:"npm",command:firstExisting([...executableNames("npm",platform).map(name=>path5.join(prefix,"bin",name)),...executableNames("npm",platform).map(name=>path5.join(path5.dirname(processExecPath),name))],existsSync11)??fallbackCommand("npm",platform),binDirectory:path5.join(prefix,"bin")}}if(platform==="win32"&&env.APPDATA){let npmRoot=normalizePath(path5.join(env.APPDATA,"npm","node_modules",packageName));if(lowerRoot===npmRoot.toLowerCase()){let binDirectory=path5.join(env.APPDATA,"npm");return{manager:"npm",command:firstExisting([...executableNames("npm",platform).map(name=>path5.join(binDirectory,name)),...executableNames("npm",platform).map(name=>path5.join(path5.dirname(processExecPath),name))],existsSync11)??fallbackCommand("npm",platform),binDirectory}}}return null}function buildGlobalPackageCommand(installation,operation,packages,targetSelector="latest"){let targets=operation==="uninstall"?packages:packages.map(packageName=>`${packageName}@${targetSelector}`),args;switch(installation.manager){case"npm":args=operation==="uninstall"?["uninstall","-g",...targets]:["install","-g",...targets];break;case"pnpm":args=operation==="uninstall"?["remove","-g",...targets]:["add","-g",...targets];break;case"yarn":args=operation==="uninstall"?["global","remove",...targets]:["global","add",...targets];break;case"bun":args=operation==="uninstall"?["remove","-g",...targets]:["add","-g",...targets];break;case"volta":args=operation==="uninstall"?["uninstall",...targets]:["install",...targets];break}return{manager:installation.manager,command:installation.command,args}}function resolveInvokingPackageManager(options={}){let env=options.env??process.env,existsSync11=options.existsSync??fs3.existsSync,platform=options.platform??process.platform,processExecPath=options.processExecPath??process.execPath,userAgent=(env.npm_config_user_agent??"").toLowerCase(),manager=userAgent.startsWith("pnpm/")?"pnpm":userAgent.startsWith("yarn/")?"yarn":userAgent.startsWith("bun/")?"bun":"npm",sibling=firstExisting(executableNames(manager,platform).map(name=>path5.join(path5.dirname(processExecPath),name)),existsSync11);return{manager,command:sibling??fallbackCommand(manager,platform)}}import fs7 from"node:fs";import os6 from"node:os";import path9 from"node:path";import{createHash as createHash2,randomUUID as randomUUID8}from"node:crypto";import{open as open2,mkdir as mkdir2,rename,rm as rm3,stat as stat3}from"node:fs/promises";import path6 from"node:path";var CHUNK_BYTES=256*1024;import WebSocket2 from"ws";init_generated_browser_action_protocol();var OBSERVED_PAGE_ACTIONS=new Set(PAGE_ACT_ACTIONS2);init_generated_browser_action_protocol();import net from"node:net";import fs6 from"node:fs";import os5 from"node:os";import path8 from"node:path";import{createRequire}from"node:module";init_host();import fs4 from"node:fs";import fs5 from"node:fs";import os4 from"node:os";import path7 from"node:path";var BROWSERS_DIR=path7.join(os4.homedir(),".mearl","browsers");var require2=createRequire(import.meta.url),CLIENT_VERSION=require2("../package.json").version,MAX_SOCKET_BUFFER_SIZE=64*1024*1024,SOCKET_PATH=process.platform==="win32"?"\\\\.\\pipe\\mearl-agent":path8.join(os5.tmpdir(),"mearl-agent.sock");var SESSION_OPTION=Symbol("control-session");import{existsSync as existsSync5,readFileSync as readFileSync4}from"node:fs";import{homedir as homedir2}from"node:os";import{join as join6}from"node:path";var MEARL_CONFIG_DIR=join6(homedir2(),".mearl");var import_extract_zip=__toESM(require_extract_zip(),1);import WebSocket3 from"ws";var RELEASE_VERSION_PATTERN=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-beta\.(0|[1-9]\d*))?$/,RELEASE_LINE_PATTERN=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.x$/;function parseComponent(value){let component=Number(value);return Number.isSafeInteger(component)&&component<=65535?component:null}function parseMearlReleaseVersion(value){if(typeof value!="string"||value.length>64)return null;let match=RELEASE_VERSION_PATTERN.exec(value);if(!match)return null;let major=parseComponent(match[1]),minor=parseComponent(match[2]),patch=parseComponent(match[3]),beta=match[4]===void 0?void 0:parseComponent(match[4]);return major===null||minor===null||patch===null||beta===null?null:{raw:value,major,minor,patch,channel:beta===void 0?"stable":"beta",...beta===void 0?{}:{beta}}}function isMearlReleaseVersion(value){return parseMearlReleaseVersion(value)!==null}function parseMearlReleaseLine(value){if(typeof value!="string"||value.length>64)return null;let match=RELEASE_LINE_PATTERN.exec(value);if(!match)return null;let major=parseComponent(match[1]),minor=parseComponent(match[2]);return major===null||minor===null?null:{raw:value,major,minor}}function mearlReleaseLineForVersion(version2){let parsed=parseMearlReleaseVersion(version2);if(!parsed)throw new Error("A valid Mearl release version is required");return`${parsed.major}.${parsed.minor}.x`}function isMearlReleaseVersionInLine(version2,releaseLine){let parsedVersion=parseMearlReleaseVersion(version2),parsedLine=parseMearlReleaseLine(releaseLine);return parsedVersion!==null&&parsedLine!==null&&parsedVersion.major===parsedLine.major&&parsedVersion.minor===parsedLine.minor}function compareMearlReleaseLines(leftVersion,rightVersion){let left=parseMearlReleaseVersion(leftVersion),right=parseMearlReleaseVersion(rightVersion);if(!left||!right)throw new Error("Mearl release-line comparison requires valid release versions");for(let key of["major","minor"]){if(left[key]<right[key])return-1;if(left[key]>right[key])return 1}return 0}function compareMearlReleaseVersions(leftVersion,rightVersion){let left=parseMearlReleaseVersion(leftVersion),right=parseMearlReleaseVersion(rightVersion);if(!left||!right)throw new Error("Mearl release comparison requires valid release versions");for(let key of["major","minor","patch"]){if(left[key]<right[key])return-1;if(left[key]>right[key])return 1}if(left.channel!==right.channel)return left.channel==="stable"?1:-1;let leftBeta=left.beta??0,rightBeta=right.beta??0;return leftBeta<rightBeta?-1:leftBeta>rightBeta?1:0}var MEARL_EXTENSION_DOWNLOAD_PAGE="https://mearl.alibaba-inc.com/",MEARL_EXTENSION_REMOTE_CONFIG_URL=`${MEARL_EXTENSION_DOWNLOAD_PAGE}config.json`;var MEARL_EXTENSION_ID="aoehhjnofngknnjefamjbplchbolghkm",MEARL_EXTENSION_SETUP_MARKER=".mearl-setup.json";var MAX_ARCHIVE_BYTES=64*1024*1024,SHA256_PATTERN=/^[a-f\d]{64}$/i;function extensionArchiveUrl(version2){if(!isMearlReleaseVersion(version2))throw new Error(`Invalid Mearl browser extension version: ${version2}`);return new URL(`mearl-chrome-v${version2}.zip`,MEARL_EXTENSION_DOWNLOAD_PAGE).toString()}function validateExtensionRelease(release){if(!isMearlReleaseVersion(release.version))throw new Error("Remote extension config has an invalid latestVersion");let expectedArchiveUrl=extensionArchiveUrl(release.version),archiveUrl;try{archiveUrl=new URL(release.archiveUrl).toString()}catch{throw new Error("Remote extension config has an invalid downloadUrl")}if(archiveUrl!==expectedArchiveUrl)throw new Error("Remote extension downloadUrl does not match latestVersion");if(release.sha256!==void 0&&!SHA256_PATTERN.test(release.sha256))throw new Error("Remote extension config has an invalid downloadSha256");return{archiveUrl,...release.sha256?{sha256:release.sha256.toLowerCase()}:{},version:release.version}}async function fetchBrowserExtensionRelease(fetchImpl=fetch){let response=await fetchImpl(MEARL_EXTENSION_REMOTE_CONFIG_URL,{cache:"no-store"});if(!response.ok)throw new Error(`Extension config returned HTTP ${response.status}`);let config2=await response.json();return validateExtensionRelease({archiveUrl:typeof config2.downloadUrl=="string"?config2.downloadUrl:"",...typeof config2.downloadSha256=="string"?{sha256:config2.downloadSha256}:{},version:typeof config2.latestVersion=="string"?config2.latestVersion:""})}function sameExtensionPath(left,right){let normalizedLeft=path9.normalize(path9.resolve(left)),normalizedRight=path9.normalize(path9.resolve(right));return process.platform==="win32"?normalizedLeft.toLowerCase()===normalizedRight.toLowerCase():normalizedLeft===normalizedRight}function setupMarkerPath(directory){return path9.join(directory,MEARL_EXTENSION_SETUP_MARKER)}function hasSetupMarker(targetDirectory){try{let marker=JSON.parse(fs7.readFileSync(setupMarkerPath(targetDirectory),"utf8"));return marker.schemaVersion===1&&marker.extensionId===MEARL_EXTENSION_ID&&typeof marker.path=="string"&&sameExtensionPath(marker.path,targetDirectory)}catch{return!1}}async function writeSetupMarker(directory,targetDirectory){let marker={extensionId:MEARL_EXTENSION_ID,path:path9.resolve(targetDirectory),schemaVersion:1};await fs7.promises.writeFile(setupMarkerPath(directory),`${JSON.stringify(marker,null,2)}
1520
- `,{mode:384})}async function replaceDirectory(stagingDirectory,targetDirectory){let backupDirectory=`${targetDirectory}.backup-${randomUUID8()}`,targetExists=fs7.existsSync(targetDirectory);try{targetExists&&await fs7.promises.rename(targetDirectory,backupDirectory),await fs7.promises.rename(stagingDirectory,targetDirectory)}catch(error48){throw!fs7.existsSync(targetDirectory)&&fs7.existsSync(backupDirectory)&&await fs7.promises.rename(backupDirectory,targetDirectory),error48}targetExists&&await fs7.promises.rm(backupDirectory,{force:!0,recursive:!0})}function readExtensionManifest(directory){let manifestPath=path9.join(directory,"manifest.json"),parsed;try{parsed=JSON.parse(fs7.readFileSync(manifestPath,"utf8"))}catch(error48){throw new Error(`Downloaded extension has no valid manifest.json: ${error48 instanceof Error?error48.message:error48}`,{cause:error48})}if(parsed.manifest_version!==3||typeof parsed.name!="string"||typeof parsed.key!="string"||parsed.key.length===0)throw new Error("Downloaded archive is not a valid Manifest V3 extension");if(!isMearlReleaseVersion(parsed.version))throw new Error("Downloaded extension manifest has an invalid version");return parsed}async function downloadAndReplaceExtension(releaseInput,targetDirectory,fetchImpl,extractArchive){let release=validateExtensionRelease(releaseInput),parentDirectory=path9.dirname(targetDirectory),stagingDirectory=`${targetDirectory}.staging-${randomUUID8()}`,archivePath=path9.join(parentDirectory,`.mearl-extension-${randomUUID8()}.zip`);await fs7.promises.mkdir(parentDirectory,{recursive:!0});try{let response=await fetchImpl(release.archiveUrl,{redirect:"follow"});if(!response.ok)throw new Error(`Extension archive returned HTTP ${response.status}: ${release.archiveUrl}`);if(Number(response.headers.get("content-length")??0)>MAX_ARCHIVE_BYTES)throw new Error(`Extension archive exceeds ${MAX_ARCHIVE_BYTES} bytes`);let archive=Buffer.from(await response.arrayBuffer());if(archive.length===0||archive.length>MAX_ARCHIVE_BYTES)throw new Error("Extension archive is empty or too large");if(release.sha256&&createHash2("sha256").update(archive).digest("hex")!==release.sha256)throw new Error("Extension archive SHA256 does not match remote config");await fs7.promises.writeFile(archivePath,archive,{mode:384}),await fs7.promises.mkdir(stagingDirectory,{recursive:!0}),await extractArchive(archivePath,stagingDirectory);let manifest=readExtensionManifest(stagingDirectory);if(manifest.version!==release.version)throw new Error(`Extension archive version ${String(manifest.version)} does not match ${release.version}`);return await writeSetupMarker(stagingDirectory,targetDirectory),await replaceDirectory(stagingDirectory,targetDirectory),release}finally{await fs7.promises.rm(archivePath,{force:!0}),await fs7.promises.rm(stagingDirectory,{force:!0,recursive:!0})}}async function updateSetupManagedBrowserExtensionFiles(options,dependencies={}){let targetDirectory=path9.resolve(options.targetDirectory);if(!hasSetupMarker(targetDirectory))throw new Error("The running extension is not managed by Mearl setup");let fetchImpl=dependencies.fetch??fetch,extractArchive=dependencies.extractArchive??((archivePath,destination)=>(0,import_extract_zip.default)(archivePath,{dir:destination}));return{...await downloadAndReplaceExtension(options.release,targetDirectory,fetchImpl,extractArchive),path:targetDirectory}}init_plugin();init_host();import fs11 from"node:fs";import path13 from"node:path";import{createInterface as createInterface2}from"node:readline/promises";import{stdin as input,stdout as output}from"node:process";import fs9 from"node:fs";import os7 from"node:os";import path11 from"node:path";import{spawn as spawn7}from"node:child_process";var COMMAND_TIMEOUT_MS=12e4,MAX_OUTPUT_LENGTH=1e6,ANSI_ESCAPE_PATTERN=new RegExp(String.raw`\u001B\[[0-?]*[ -/]*[@-~]`,"g");function existingExecutable(candidates,existsSync11){return candidates.find(candidate=>candidate&&existsSync11(candidate))??null}function stripAnsi(value){return value.replace(ANSI_ESCAPE_PATTERN,"")}function resolveAliSkillsExecutable(options={}){let env=options.env??process.env,home=(options.homedir??os7.homedir)(),platform=options.platform??process.platform,existsSync11=options.existsSync??(candidate=>isExecutable(candidate,platform)),processExecPath=options.processExecPath??process.execPath,readdirSync4=options.readdirSync??fs9.readdirSync,names=executableNames("ali-skills",platform),pathKey=Object.keys(env).find(key=>key.toLowerCase()==="path")||"PATH",pathCandidates=(env[pathKey]||"").split(path11.delimiter).filter(Boolean).flatMap(directory=>names.map(name=>path11.join(directory,name))),candidates=[env.MEARL_ALI_SKILLS_PATH,...names.map(name=>path11.join(path11.dirname(processExecPath),name)),...names.map(name=>path11.join(home,".local","bin",name)),...names.map(name=>path11.join(home,".npm-global","bin",name)),...names.map(name=>path11.join(home,".volta","bin",name)),...names.map(name=>path11.join(home,".local","share","pnpm",name)),...names.map(name=>path11.join(home,"Library","pnpm",name)),...versionManagerExecutableCandidates(home,names,{env,platform,readdirSync:readdirSync4}),...platform==="win32"?[]:["/opt/homebrew/bin/ali-skills","/usr/local/bin/ali-skills","/usr/bin/ali-skills"],...pathCandidates];return existingExecutable(candidates,existsSync11)}var runAliSkillsCli=(executable,args,cwd)=>new Promise((resolve9,reject)=>{let launch=resolveSpawnCommand(executable,args),child=spawn7(launch.command,launch.args,{cwd,env:prependNodePath(prependCommandPath(executable)),stdio:["ignore","pipe","pipe"],windowsHide:!0}),stdout="",stderr="",settled=!1,append=(current,chunk)=>current.length>=MAX_OUTPUT_LENGTH?current:(current+chunk.toString("utf8")).slice(0,MAX_OUTPUT_LENGTH),finish=error48=>{settled||(settled=!0,clearTimeout(timer),error48?reject(error48):resolve9({stdout,stderr}))},timer=setTimeout(()=>{child.kill("SIGTERM"),finish(new Error(`Ali Skills command timed out after ${COMMAND_TIMEOUT_MS/1e3}s`))},COMMAND_TIMEOUT_MS);child.stdout.on("data",chunk=>stdout=append(stdout,chunk)),child.stderr.on("data",chunk=>stderr=append(stderr,chunk)),child.once("error",error48=>finish(error48)),child.once("exit",code=>{if(code===0){finish();return}let detail=stripAnsi(stderr||stdout).trim();finish(new Error(detail||`Ali Skills command exited with code ${String(code)}`))})});function resolveAliSkillsInvocation(options={}){let env=options.env??process.env,executable=resolveAliSkillsExecutable(options);if(executable)return{command:executable,argsPrefix:[],env:prependNodePath(prependCommandPath(executable,env))};let processExecPath=options.processExecPath??process.execPath,npx=findExecutable("npx",{env,existsSync:options.existsSync,platform:options.platform,extraDirectories:[path11.dirname(processExecPath)]});return npx?{command:npx,argsPrefix:["-y","ali-skills"],env:prependNodePath(prependCommandPath(npx,env),processExecPath)}:null}init_nativeHost();init_plugin();import{dirname as dirname6}from"node:path";var ALIBABA_NPM_REGISTRY="https://registry.anpm.alibaba-inc.com/";function packageRegistryEnvironment(packageName,env){return packageName.startsWith("@ali/")?{...env,npm_config_registry:ALIBABA_NPM_REGISTRY}:env}init_plugin();import{existsSync as existsSync7,mkdirSync as mkdirSync5,readdirSync as readdirSync3,readlinkSync,realpathSync as realpathSync2,rmdirSync,statSync as statSync7}from"node:fs";import{homedir as homedir4}from"node:os";import{basename as basename3,dirname as dirname5,isAbsolute as isAbsolute5,join as join11,relative as relative3,resolve as resolve5,sep as sep3}from"node:path";import{existsSync as existsSync6,readFileSync as readFileSync8}from"node:fs";import{createRequire as createRequire3}from"node:module";import{join as join10}from"node:path";var require4=createRequire3(import.meta.url),PLUGIN_RUNTIME_VERSION=require4("../package.json").version;function globalAliSkill(entry){let globalSkillsDirectory=join11(homedir4(),".agents","skills"),relativeEntry=relative3(globalSkillsDirectory,resolve5(entry));if(!isAbsolute5(relativeEntry)&&relativeEntry!==".."&&!relativeEntry.startsWith(`..${sep3}`)){let[name,...entrySegments]=relativeEntry.split(sep3);if(name&&entrySegments.length>0)return{directory:join11(globalSkillsDirectory,name),name}}let sourceDirectory=dirname5(dirname5(resolve5(entry)));if(basename3(dirname5(entry))==="scripts")try{let source=existsSync7(sourceDirectory)?realpathSync2(sourceDirectory):sourceDirectory;for(let name of readdirSync3(globalSkillsDirectory)){let directory=join11(globalSkillsDirectory,name),target;try{target=resolve5(globalSkillsDirectory,readlinkSync(directory))}catch{continue}if(target===sourceDirectory||existsSync7(target)&&realpathSync2(target)===source)return{directory,name}}}catch{}}function projectAliSkill(entry,managedBy){if(managedBy!=="ali-skills")return;let absolute=resolve5(entry),marker=`${sep3}.agents${sep3}skills${sep3}`,markerIndex=absolute.lastIndexOf(marker);if(markerIndex<=0)return;let cwd=absolute.slice(0,markerIndex);if(resolve5(cwd)===resolve5(homedir4()))return;let[name,scripts,filename,...remaining]=absolute.slice(markerIndex+marker.length).split(sep3);if(!(!name||scripts!=="scripts"||!["main.mjs","main.py"].includes(filename)||remaining.length>0))return{directory:join11(cwd,".agents","skills",name),name,cwd}}async function uninstallPlugin(name,runner=runCommand){assertPluginName(name);let entry=findPluginEntry(name);if(!entry)return{removed:!1,unregisteredNames:[]};let entryMissing=!existsSync7(entry),managedSkill=projectAliSkill(entry,findPluginRegistration(name)?.managedBy)??globalAliSkill(entry);if(!managedSkill)return unregisterPlugin(name),{...entryMissing?{entryMissing:!0}:{},removed:!0,unregisteredNames:[name]};let invocation2=resolveAliSkillsInvocation();if(!invocation2)throw new Error("未找到 ali-skills 或 npx,插件注册已保留。");let{directory:skillDirectory,name:skillName}=managedSkill,unregisteredNames=listPluginNames().filter(pluginName=>{try{let candidate=findPluginEntry(pluginName);return candidate?(projectAliSkill(candidate,"ali-skills")??globalAliSkill(candidate))?.directory===skillDirectory:!1}catch{return!1}}),placeholderCreated=!1;if(!existsSync7(skillDirectory)){mkdirSync5(dirname5(skillDirectory),{recursive:!0,mode:448});try{mkdirSync5(skillDirectory,{mode:448}),placeholderCreated=!0}catch(error48){if(error48.code!=="EEXIST")throw error48}}let removed;try{removed=await runner(invocation2.command,[...invocation2.argsPrefix,"remove",skillName,...managedSkill.cwd?[]:["--global"],"--yes"],{env:invocation2.env,tee:!0,...managedSkill.cwd?{cwd:managedSkill.cwd}:{}})}catch(error48){throw new Error(`ali-skills remove ${skillName} 执行失败:${error48 instanceof Error?error48.message:String(error48)};插件注册已保留。`,{cause:error48})}finally{if(placeholderCreated)try{rmdirSync(skillDirectory)}catch{}}if(removed.code!==0)throw new Error(`ali-skills remove ${skillName} 失败(exit ${removed.code});插件注册已保留。`);for(let pluginName of unregisteredNames)unregisterPlugin(pluginName);return{...entryMissing?{entryMissing:!0}:{},removed:!0,skillName,unregisteredNames}}var ALIBABA_INTERNAL_PLUGIN_NAMES=listOfficialPluginNames("alibaba");init_host();import{existsSync as existsSync8}from"node:fs";import{join as join12,resolve as resolve6}from"node:path";function parseProviderPackageSpec(value){let nameMatch=value.trim().match(/^(@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)(?:@(.+))?$/i);if(!nameMatch||!nameMatch[1]||/\s/.test(nameMatch[2]??""))throw new Error(`Provider install requires an npm package name, received: ${value}`);return{packageName:nameMatch[1],target:nameMatch[2]||"latest"}}function providerManager(env,dependencies,resolvedManager){return resolvedManager??(dependencies.resolveInvokingManager??(childEnv=>resolveInvokingPackageManager({env:childEnv})))(env)}function outputPath(output2){return output2.split(/\r?\n/).map(line=>line.trim()).filter(Boolean).at(-1)??null}async function resolveGlobalProviderPackageRoot(installation,packageName,runner,env){let args,toNodeModules;switch(installation.manager){case"npm":case"pnpm":args=["root","-g"],toNodeModules=value=>value;break;case"yarn":args=["global","dir"],toNodeModules=value=>join12(value,"node_modules");break;case"bun":args=["pm","bin","-g"],toNodeModules=value=>resolve6(value,"..","install","global","node_modules");break;case"volta":throw new Error("Volta cannot manage a Provider package without a binary; use npm or pnpm")}let result=await runner(installation.command,args,{capture:!0,env:prependCommandPath(installation.command,env)}),root=outputPath(result.stdout);if(result.code!==0||!root)throw new Error(`${installation.manager} global package root lookup failed`);return join12(toNodeModules(root),...packageName.split("/"))}async function runPackageCommand(installation,operation,packageName,target,runner,env){let command=buildGlobalPackageCommand(installation,operation,[packageName],target),commandEnv=operation==="uninstall"?env:packageRegistryEnvironment(packageName,env),result=await runner(command.command,command.args,{env:prependCommandPath(command.command,commandEnv),tee:!0});if(result.code!==0)throw new Error(`${packageName} ${operation} failed (exit ${result.code})`)}async function installProviderPackage(packageSpec,dependencies={}){let{packageName,target}=parseProviderPackageSpec(packageSpec),env=process.env,runner=dependencies.runCommand??runCommand,installation=providerManager(env,dependencies);await runPackageCommand(installation,"install",packageName,target,runner,env);let packageRoot=await(dependencies.resolvePackageRoot??resolveGlobalProviderPackageRoot)(installation,packageName,runner,env);if(!(dependencies.existsSync??existsSync8)(join12(packageRoot,"package.json")))throw new Error(`${packageName} was installed but its package root was not found: ${packageRoot}`);return{manifest:(dependencies.registerPackage??registerProviderPackage)(packageRoot),manager:installation.manager}}init_nativeHost();init_types2();init_generated_provider_actions();init_registry2();init_provider_runtime();import net2 from"node:net";init_dist2();init_generated_provider_actions();init_provider_runtime();init_registry2();init_types2();import{chmodSync,rmSync as rmSync6}from"node:fs";import{dirname as dirname7}from"node:path";var MAX_REQUEST_BYTES=16*1024*1024;init_host();init_browser_registry();init_browser_socket_request();init_version();function listExternalBrowserProviders(){return listInstalledProviders().map(provider=>({provider:{id:provider.providerId,name:provider.name,builtin:!1,version:provider.version,protocolVersion:provider.protocolVersion},browserType:provider.browserType}))}async function requireLiveProvider(providerId){let warnings=await ensureInstalledProvidersRunning(),live=readLiveProvider(providerId);if(!live){let warning=warnings.find(item=>item.startsWith(`provider ${providerId}:`));throw new Error(warning??`Provider did not start: ${providerId}`)}return{socketPath:live.socketPath}}async function launchProviderBrowser(input2){let providerId=input2.provider.trim();if(!listInstalledProviders().find(item=>item.providerId===providerId))throw new Error(`Provider is not registered: ${providerId}`);let live=await requireLiveProvider(providerId),result=await(input2.host?requestBrowserSocket(live.socketPath,"browser_launch",input2.providerOptions,NATIVE_HOST_VERSION,6e4,void 0,input2.host):requestBrowserSocket(live.socketPath,"browser_launch",input2.providerOptions,NATIVE_HOST_VERSION));return validateProviderBrowser(result),{...result,browserId:providerBrowserKey(providerId,result.browserId)}}function findProviderBrowser(selector){let normalized=selector.toLowerCase(),exact=listRegisteredBrowsers().filter(browser=>browser.transport==="provider").filter(browser=>browser.browserId.toLowerCase()===normalized||browser.providerBrowserId?.toLowerCase()===normalized||browser.browserName.toLowerCase()===normalized);if(exact.length>1)throw new Error(`Provider browser selector is ambiguous: ${selector}`);return exact[0]??null}function requireProviderBrowser(browser){if(browser.transport!=="provider"||!browser.providerBrowserId)throw new Error(`Browser is not managed by an external Provider: ${browser.browserId}`);return browser.providerBrowserId}function requestControlledProvider(browser,action,data,host){return requireProviderBrowser(browser),ensureProviderControlHost().then(controlHost=>requestBrowserSocket(controlHost.socketPath,action,data,NATIVE_HOST_VERSION,12e4,void 0,host,{providerTarget:browser.browserId}))}async function listProviderControlSessions(){let host=readProviderControlHost();return host?(await requestBrowserSocket(host.socketPath,"control_sessions_list",{},NATIVE_HOST_VERSION)).sessions??[]:[]}async function updateProviderControlSession(sessionId,operation){let host=readProviderControlHost();if(!host)throw new Error("CONTROL_SESSION_NOT_FOUND");return(await requestBrowserSocket(host.socketPath,"control_session_update",{sessionId,operation},NATIVE_HOST_VERSION)).session}function closeProviderBrowser(browser,options={}){return requestControlledProvider(browser,"browser_close",{deleteProfile:options.deleteProfile===!0})}function detachProviderBrowser(browser){return requestControlledProvider(browser,"browser_release",{})}async function accessProviderBrowser(browser){return(await requestBrowserSocket(browser.socketPath,"get_browser_access_url",{},NATIVE_HOST_VERSION,6e4,requireProviderBrowser(browser))).browserAccess}async function startProviderBrowser(browser){let result=await requestControlledProvider(browser,"browser_manager_start",{});return validateProviderBrowser(result),{...result,browserId:browser.browserId}}function syncProviderBrowserCookies(browser,scope,host){return requestControlledProvider(browser,"browser_manager_sync_cookies",{scope},host)}async function configureProvider(providerId,options){if(!listInstalledProviders().find(item=>item.providerId===providerId)?.browserType.configuration)throw new Error(`Provider does not support configuration: ${providerId}`);let live=await requireLiveProvider(providerId);return requestBrowserSocket(live.socketPath,"browser_provider_configure",options,NATIVE_HOST_VERSION)}init_browser_socket_request();init_version();var AUTH_TIMEOUT_MS=12e4,POLL_INTERVAL_MS=750,BROW_BROWSER_PREFIX="provider:brow:",BROW_PACKAGE="@ali/mearl-provider-brow",browInstallation=null,runInstallerCommand=(command,args,options)=>runCommand(command,args,{...options,capture:!0,tee:!1,timeoutMs:options?.tee?18e4:3e4});async function ensureBrowInstalled(onProgress){listInstalledProviders().some(provider=>provider.providerId==="brow")||(onProgress?.("installing"),browInstallation??=installProviderPackage(BROW_PACKAGE,{runCommand:runInstallerCommand}).then(({manifest})=>{if(manifest.providerId!=="brow")throw new Error("Brow installer registered an unexpected Provider")}).finally(()=>{browInstallation=null}),await browInstallation)}function validateAlipayAuthCodeParams(value){let params=value&&typeof value=="object"?value:{},appId=typeof params.appId=="string"?params.appId.trim():"",scopeNicks=params.scopeNicks;if(!/^\d{10,32}$/.test(appId))throw new Error("getAuthCode requires a valid appId");if(!Array.isArray(scopeNicks)||scopeNicks.length<1||scopeNicks.length>8||!scopeNicks.every(scope=>typeof scope=="string"&&/^[a-zA-Z0-9_]{1,64}$/.test(scope)))throw new Error("getAuthCode requires valid scopeNicks");return{appId,scopeNicks,showErrorTip:params.showErrorTip===!0}}async function startAlipayAuthCode(value,onProgress){validateAlipayAuthCodeParams(value),await ensureBrowInstalled(onProgress);let browser=await launchProviderBrowser({provider:"brow",providerOptions:{}});try{if(browser.pairing?.kind!=="qr"||!browser.pairing.url)throw new Error("Brow did not return a pairing QR URL");return{browserId:browser.browserId,qrSvg:renderSVG(browser.pairing.url,{pixelSize:1,border:2})}}catch(error48){throw await closeAlipayAuthCode(browser.browserId).catch(()=>{}),error48}}async function closeAlipayAuthCode(browserId){let prefix=BROW_BROWSER_PREFIX;if(!browserId.startsWith(prefix))return;let browser=findProviderBrowser(browserId);if(browser)try{await closeProviderBrowser(browser);return}catch{}let live=readLiveProvider("brow");live&&await requestBrowserSocket(live.socketPath,"browser_close",{},NATIVE_HOST_VERSION,15e3,browserId.slice(prefix.length))}async function evaluate(browserId,tabId,expression){let browser=findProviderBrowser(browserId);if(!browser?.providerBrowserId)throw new Error("Brow pairing has ended");return(await requestBrowserSocket(browser.socketPath,"page_eval",{tabId,expression},NATIVE_HOST_VERSION,15e3,browser.providerBrowserId))?.result}async function waitAlipayAuthCode(browserId,value,onProgress){if(!browserId.startsWith(BROW_BROWSER_PREFIX))throw new Error("Invalid Brow pairing");let params=validateAlipayAuthCodeParams(value),deadline=Date.now()+AUTH_TIMEOUT_MS,probeKey=`__mearlAuthCode_${randomUUID10().replaceAll("-","")}`,started=!1,tabId=0,connected=!1;for(;Date.now()<deadline;){let browser=findProviderBrowser(browserId);if(browser?.providerBrowserId)try{if(!tabId){let tabs=(await requestBrowserSocket(browser.socketPath,"tab_list",{},NATIVE_HOST_VERSION,15e3,browser.providerBrowserId))?.tabs;tabId=(tabs?.find(item=>item.active&&typeof item.tabId=="number"&&/^https?:\/\//.test(item.url??""))??tabs?.find(item=>typeof item.tabId=="number"&&/^https?:\/\//.test(item.url??"")))?.tabId??0}if(tabId&&!connected&&(connected=!0,onProgress?.("connected")),tabId&&!started){let expression=`(() => {
1528
+ `,{mode:384})}async function replaceDirectory(stagingDirectory,targetDirectory){let backupDirectory=`${targetDirectory}.backup-${randomUUID8()}`,targetExists=fs7.existsSync(targetDirectory);try{targetExists&&await fs7.promises.rename(targetDirectory,backupDirectory),await fs7.promises.rename(stagingDirectory,targetDirectory)}catch(error48){throw!fs7.existsSync(targetDirectory)&&fs7.existsSync(backupDirectory)&&await fs7.promises.rename(backupDirectory,targetDirectory),error48}targetExists&&await fs7.promises.rm(backupDirectory,{force:!0,recursive:!0})}function readExtensionManifest(directory){let manifestPath=path9.join(directory,"manifest.json"),parsed;try{parsed=JSON.parse(fs7.readFileSync(manifestPath,"utf8"))}catch(error48){throw new Error(`Downloaded extension has no valid manifest.json: ${error48 instanceof Error?error48.message:error48}`,{cause:error48})}if(parsed.manifest_version!==3||typeof parsed.name!="string"||typeof parsed.key!="string"||parsed.key.length===0)throw new Error("Downloaded archive is not a valid Manifest V3 extension");if(!isMearlReleaseVersion(parsed.version))throw new Error("Downloaded extension manifest has an invalid version");return parsed}async function downloadAndReplaceExtension(releaseInput,targetDirectory,fetchImpl,extractArchive){let release=validateExtensionRelease(releaseInput),parentDirectory=path9.dirname(targetDirectory),stagingDirectory=`${targetDirectory}.staging-${randomUUID8()}`,archivePath=path9.join(parentDirectory,`.mearl-extension-${randomUUID8()}.zip`);await fs7.promises.mkdir(parentDirectory,{recursive:!0});try{let response=await fetchImpl(release.archiveUrl,{redirect:"follow"});if(!response.ok)throw new Error(`Extension archive returned HTTP ${response.status}: ${release.archiveUrl}`);if(Number(response.headers.get("content-length")??0)>MAX_ARCHIVE_BYTES)throw new Error(`Extension archive exceeds ${MAX_ARCHIVE_BYTES} bytes`);let archive=Buffer.from(await response.arrayBuffer());if(archive.length===0||archive.length>MAX_ARCHIVE_BYTES)throw new Error("Extension archive is empty or too large");if(release.sha256&&createHash2("sha256").update(archive).digest("hex")!==release.sha256)throw new Error("Extension archive SHA256 does not match remote config");await fs7.promises.writeFile(archivePath,archive,{mode:384}),await fs7.promises.mkdir(stagingDirectory,{recursive:!0}),await extractArchive(archivePath,stagingDirectory);let manifest=readExtensionManifest(stagingDirectory);if(manifest.version!==release.version)throw new Error(`Extension archive version ${String(manifest.version)} does not match ${release.version}`);return await writeSetupMarker(stagingDirectory,targetDirectory),await replaceDirectory(stagingDirectory,targetDirectory),release}finally{await fs7.promises.rm(archivePath,{force:!0}),await fs7.promises.rm(stagingDirectory,{force:!0,recursive:!0})}}async function updateSetupManagedBrowserExtensionFiles(options,dependencies={}){let targetDirectory=path9.resolve(options.targetDirectory);if(!hasSetupMarker(targetDirectory))throw new Error("The running extension is not managed by Mearl setup");let fetchImpl=dependencies.fetch??fetch,extractArchive=dependencies.extractArchive??((archivePath,destination)=>(0,import_extract_zip.default)(archivePath,{dir:destination}));return{...await downloadAndReplaceExtension(options.release,targetDirectory,fetchImpl,extractArchive),path:targetDirectory}}init_plugin();init_host();import fs11 from"node:fs";import path13 from"node:path";import{createInterface as createInterface2}from"node:readline/promises";import{stdin as input,stdout as output}from"node:process";import fs9 from"node:fs";import os7 from"node:os";import path11 from"node:path";import{spawn as spawn7}from"node:child_process";var COMMAND_TIMEOUT_MS=12e4,MAX_OUTPUT_LENGTH=1e6,ANSI_ESCAPE_PATTERN=new RegExp(String.raw`\u001B\[[0-?]*[ -/]*[@-~]`,"g");function existingExecutable(candidates,existsSync11){return candidates.find(candidate=>candidate&&existsSync11(candidate))??null}function stripAnsi(value){return value.replace(ANSI_ESCAPE_PATTERN,"")}function resolveAliSkillsExecutable(options={}){let env=options.env??process.env,home=(options.homedir??os7.homedir)(),platform=options.platform??process.platform,existsSync11=options.existsSync??(candidate=>isExecutable(candidate,platform)),processExecPath=options.processExecPath??process.execPath,readdirSync4=options.readdirSync??fs9.readdirSync,names=executableNames("ali-skills",platform),pathKey=Object.keys(env).find(key=>key.toLowerCase()==="path")||"PATH",pathCandidates=(env[pathKey]||"").split(path11.delimiter).filter(Boolean).flatMap(directory=>names.map(name=>path11.join(directory,name))),candidates=[env.MEARL_ALI_SKILLS_PATH,...names.map(name=>path11.join(path11.dirname(processExecPath),name)),...names.map(name=>path11.join(home,".local","bin",name)),...names.map(name=>path11.join(home,".npm-global","bin",name)),...names.map(name=>path11.join(home,".volta","bin",name)),...names.map(name=>path11.join(home,".local","share","pnpm",name)),...names.map(name=>path11.join(home,"Library","pnpm",name)),...versionManagerExecutableCandidates(home,names,{env,platform,readdirSync:readdirSync4}),...platform==="win32"?[]:["/opt/homebrew/bin/ali-skills","/usr/local/bin/ali-skills","/usr/bin/ali-skills"],...pathCandidates];return existingExecutable(candidates,existsSync11)}var runAliSkillsCli=(executable,args,cwd)=>new Promise((resolve9,reject)=>{let launch=resolveSpawnCommand(executable,args),child=spawn7(launch.command,launch.args,{cwd,env:prependNodePath(prependCommandPath(executable)),stdio:["ignore","pipe","pipe"],windowsHide:!0}),stdout="",stderr="",settled=!1,append=(current,chunk)=>current.length>=MAX_OUTPUT_LENGTH?current:(current+chunk.toString("utf8")).slice(0,MAX_OUTPUT_LENGTH),finish=error48=>{settled||(settled=!0,clearTimeout(timer),error48?reject(error48):resolve9({stdout,stderr}))},timer=setTimeout(()=>{child.kill("SIGTERM"),finish(new Error(`Ali Skills command timed out after ${COMMAND_TIMEOUT_MS/1e3}s`))},COMMAND_TIMEOUT_MS);child.stdout.on("data",chunk=>stdout=append(stdout,chunk)),child.stderr.on("data",chunk=>stderr=append(stderr,chunk)),child.once("error",error48=>finish(error48)),child.once("exit",code=>{if(code===0){finish();return}let detail=stripAnsi(stderr||stdout).trim();finish(new Error(detail||`Ali Skills command exited with code ${String(code)}`))})});function resolveAliSkillsInvocation(options={}){let env=options.env??process.env,executable=resolveAliSkillsExecutable(options);if(executable)return{command:executable,argsPrefix:[],env:prependNodePath(prependCommandPath(executable,env))};let processExecPath=options.processExecPath??process.execPath,npx=findExecutable("npx",{env,existsSync:options.existsSync,platform:options.platform,extraDirectories:[path11.dirname(processExecPath)]});return npx?{command:npx,argsPrefix:["-y","ali-skills"],env:prependNodePath(prependCommandPath(npx,env),processExecPath)}:null}init_nativeHost();init_plugin();import{dirname as dirname6}from"node:path";var OFFICIAL_NPM_REGISTRY="https://registry.npmjs.org/",ALIBABA_NPM_REGISTRY="https://registry.anpm.alibaba-inc.com/";function packageRegistryEnvironment(packageName,env){let scope=packageName.split("/")[0],registry2=scope==="@mearl"?OFFICIAL_NPM_REGISTRY:scope==="@ali"?ALIBABA_NPM_REGISTRY:void 0;return registry2?{...env,npm_config_registry:registry2,NPM_CONFIG_REGISTRY:registry2,BUN_CONFIG_REGISTRY:registry2,[`npm_config_${scope}:registry`]:registry2}:env}init_plugin();import{existsSync as existsSync7,mkdirSync as mkdirSync5,readdirSync as readdirSync3,readlinkSync,realpathSync as realpathSync2,rmdirSync,statSync as statSync7}from"node:fs";import{homedir as homedir4}from"node:os";import{basename as basename3,dirname as dirname5,isAbsolute as isAbsolute5,join as join11,relative as relative3,resolve as resolve5,sep as sep3}from"node:path";import{existsSync as existsSync6,readFileSync as readFileSync8}from"node:fs";import{createRequire as createRequire3}from"node:module";import{join as join10}from"node:path";var require4=createRequire3(import.meta.url),PLUGIN_RUNTIME_VERSION=require4("../package.json").version;function globalAliSkill(entry){let globalSkillsDirectory=join11(homedir4(),".agents","skills"),relativeEntry=relative3(globalSkillsDirectory,resolve5(entry));if(!isAbsolute5(relativeEntry)&&relativeEntry!==".."&&!relativeEntry.startsWith(`..${sep3}`)){let[name,...entrySegments]=relativeEntry.split(sep3);if(name&&entrySegments.length>0)return{directory:join11(globalSkillsDirectory,name),name}}let sourceDirectory=dirname5(dirname5(resolve5(entry)));if(basename3(dirname5(entry))==="scripts")try{let source=existsSync7(sourceDirectory)?realpathSync2(sourceDirectory):sourceDirectory;for(let name of readdirSync3(globalSkillsDirectory)){let directory=join11(globalSkillsDirectory,name),target;try{target=resolve5(globalSkillsDirectory,readlinkSync(directory))}catch{continue}if(target===sourceDirectory||existsSync7(target)&&realpathSync2(target)===source)return{directory,name}}}catch{}}function projectAliSkill(entry,managedBy){if(managedBy!=="ali-skills")return;let absolute=resolve5(entry),marker=`${sep3}.agents${sep3}skills${sep3}`,markerIndex=absolute.lastIndexOf(marker);if(markerIndex<=0)return;let cwd=absolute.slice(0,markerIndex);if(resolve5(cwd)===resolve5(homedir4()))return;let[name,scripts,filename,...remaining]=absolute.slice(markerIndex+marker.length).split(sep3);if(!(!name||scripts!=="scripts"||!["main.mjs","main.py"].includes(filename)||remaining.length>0))return{directory:join11(cwd,".agents","skills",name),name,cwd}}async function uninstallPlugin(name,runner=runCommand){assertPluginName(name);let entry=findPluginEntry(name);if(!entry)return{removed:!1,unregisteredNames:[]};let entryMissing=!existsSync7(entry),managedSkill=projectAliSkill(entry,findPluginRegistration(name)?.managedBy)??globalAliSkill(entry);if(!managedSkill)return unregisterPlugin(name),{...entryMissing?{entryMissing:!0}:{},removed:!0,unregisteredNames:[name]};let invocation2=resolveAliSkillsInvocation();if(!invocation2)throw new Error("未找到 ali-skills 或 npx,插件注册已保留。");let{directory:skillDirectory,name:skillName}=managedSkill,unregisteredNames=listPluginNames().filter(pluginName=>{try{let candidate=findPluginEntry(pluginName);return candidate?(projectAliSkill(candidate,"ali-skills")??globalAliSkill(candidate))?.directory===skillDirectory:!1}catch{return!1}}),placeholderCreated=!1;if(!existsSync7(skillDirectory)){mkdirSync5(dirname5(skillDirectory),{recursive:!0,mode:448});try{mkdirSync5(skillDirectory,{mode:448}),placeholderCreated=!0}catch(error48){if(error48.code!=="EEXIST")throw error48}}let removed;try{removed=await runner(invocation2.command,[...invocation2.argsPrefix,"remove",skillName,...managedSkill.cwd?[]:["--global"],"--yes"],{env:invocation2.env,tee:!0,...managedSkill.cwd?{cwd:managedSkill.cwd}:{}})}catch(error48){throw new Error(`ali-skills remove ${skillName} 执行失败:${error48 instanceof Error?error48.message:String(error48)};插件注册已保留。`,{cause:error48})}finally{if(placeholderCreated)try{rmdirSync(skillDirectory)}catch{}}if(removed.code!==0)throw new Error(`ali-skills remove ${skillName} 失败(exit ${removed.code});插件注册已保留。`);for(let pluginName of unregisteredNames)unregisterPlugin(pluginName);return{...entryMissing?{entryMissing:!0}:{},removed:!0,skillName,unregisteredNames}}var ALIBABA_INTERNAL_PLUGIN_NAMES=listOfficialPluginNames("alibaba");init_host();import{existsSync as existsSync8}from"node:fs";import{join as join12,resolve as resolve6}from"node:path";function parseProviderPackageSpec(value){let nameMatch=value.trim().match(/^(@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)(?:@(.+))?$/i);if(!nameMatch||!nameMatch[1]||/\s/.test(nameMatch[2]??""))throw new Error(`Provider install requires an npm package name, received: ${value}`);return{packageName:nameMatch[1],target:nameMatch[2]||"latest"}}function providerManager(env,dependencies,resolvedManager){return resolvedManager??(dependencies.resolveInvokingManager??(childEnv=>resolveInvokingPackageManager({env:childEnv})))(env)}function outputPath(output2){return output2.split(/\r?\n/).map(line=>line.trim()).filter(Boolean).at(-1)??null}async function resolveGlobalProviderPackageRoot(installation,packageName,runner,env){let args,toNodeModules;switch(installation.manager){case"npm":case"pnpm":args=["root","-g"],toNodeModules=value=>value;break;case"yarn":args=["global","dir"],toNodeModules=value=>join12(value,"node_modules");break;case"bun":args=["pm","bin","-g"],toNodeModules=value=>resolve6(value,"..","install","global","node_modules");break;case"volta":throw new Error("Volta cannot manage a Provider package without a binary; use npm or pnpm")}let result=await runner(installation.command,args,{capture:!0,env:prependCommandPath(installation.command,env)}),root=outputPath(result.stdout);if(result.code!==0||!root)throw new Error(`${installation.manager} global package root lookup failed`);return join12(toNodeModules(root),...packageName.split("/"))}async function runPackageCommand(installation,operation,packageName,target,runner,env){let command=buildGlobalPackageCommand(installation,operation,[packageName],target),commandEnv=operation==="uninstall"?env:packageRegistryEnvironment(packageName,env),result=await runner(command.command,command.args,{env:prependCommandPath(command.command,commandEnv),tee:!0});if(result.code!==0)throw new Error(`${packageName} ${operation} failed (exit ${result.code})`)}async function installProviderPackage(packageSpec,dependencies={}){let{packageName,target}=parseProviderPackageSpec(packageSpec),env=process.env,runner=dependencies.runCommand??runCommand,installation=providerManager(env,dependencies);await runPackageCommand(installation,"install",packageName,target,runner,env);let packageRoot=await(dependencies.resolvePackageRoot??resolveGlobalProviderPackageRoot)(installation,packageName,runner,env);if(!(dependencies.existsSync??existsSync8)(join12(packageRoot,"package.json")))throw new Error(`${packageName} was installed but its package root was not found: ${packageRoot}`);return{manifest:(dependencies.registerPackage??registerProviderPackage)(packageRoot),manager:installation.manager}}init_nativeHost();init_types2();init_generated_provider_actions();init_registry2();init_provider_runtime();import net2 from"node:net";init_dist2();init_generated_provider_actions();init_provider_runtime();init_registry2();init_types2();import{chmodSync,rmSync as rmSync6}from"node:fs";import{dirname as dirname7}from"node:path";var MAX_REQUEST_BYTES=16*1024*1024;init_host();init_browser_registry();init_browser_socket_request();init_version();function listExternalBrowserProviders(){return listInstalledProviders().map(provider=>({provider:{id:provider.providerId,name:provider.name,builtin:!1,version:provider.version,protocolVersion:provider.protocolVersion},browserType:provider.browserType}))}async function getProviderLaunchForm(providerId,request){if(!listInstalledProviders().find(item=>item.providerId===providerId)?.browserType.dynamicLaunchForm)throw new Error(`Provider does not support dynamic launch forms: ${providerId}`);let live=await requireLiveProvider(providerId),form=await requestBrowserSocket(live.socketPath,"browser_provider_launch_form",{...request},NATIVE_HOST_VERSION,12e4);return validateProviderLaunchForm(form),form}async function requireLiveProvider(providerId){let warnings=await ensureInstalledProvidersRunning(),live=readLiveProvider(providerId);if(!live){let warning=warnings.find(item=>item.startsWith(`provider ${providerId}:`));throw new Error(warning??`Provider did not start: ${providerId}`)}return{socketPath:live.socketPath}}async function launchProviderBrowser(input2){let providerId=input2.provider.trim();if(!listInstalledProviders().find(item=>item.providerId===providerId))throw new Error(`Provider is not registered: ${providerId}`);let live=await requireLiveProvider(providerId),result=await(input2.host?requestBrowserSocket(live.socketPath,"browser_launch",input2.providerOptions,NATIVE_HOST_VERSION,6e4,void 0,input2.host):requestBrowserSocket(live.socketPath,"browser_launch",input2.providerOptions,NATIVE_HOST_VERSION));return validateProviderBrowser(result),{...result,browserId:providerBrowserKey(providerId,result.browserId)}}function findProviderBrowser(selector){let normalized=selector.toLowerCase(),exact=listRegisteredBrowsers().filter(browser=>browser.transport==="provider").filter(browser=>browser.browserId.toLowerCase()===normalized||browser.providerBrowserId?.toLowerCase()===normalized||browser.browserName.toLowerCase()===normalized);if(exact.length>1)throw new Error(`Provider browser selector is ambiguous: ${selector}`);return exact[0]??null}function requireProviderBrowser(browser){if(browser.transport!=="provider"||!browser.providerBrowserId)throw new Error(`Browser is not managed by an external Provider: ${browser.browserId}`);return browser.providerBrowserId}function requestControlledProvider(browser,action,data,host){return requireProviderBrowser(browser),ensureProviderControlHost().then(controlHost=>requestBrowserSocket(controlHost.socketPath,action,data,NATIVE_HOST_VERSION,12e4,void 0,host,{providerTarget:browser.browserId}))}async function listProviderControlSessions(){let host=readProviderControlHost();return host?(await requestBrowserSocket(host.socketPath,"control_sessions_list",{},NATIVE_HOST_VERSION)).sessions??[]:[]}async function updateProviderControlSession(sessionId,operation){let host=readProviderControlHost();if(!host)throw new Error("CONTROL_SESSION_NOT_FOUND");return(await requestBrowserSocket(host.socketPath,"control_session_update",{sessionId,operation},NATIVE_HOST_VERSION)).session}function closeProviderBrowser(browser,options={}){return requestControlledProvider(browser,"browser_close",{deleteProfile:options.deleteProfile===!0})}function detachProviderBrowser(browser){return requestControlledProvider(browser,"browser_release",{})}async function accessProviderBrowser(browser){return(await requestBrowserSocket(browser.socketPath,"get_browser_access_url",{},NATIVE_HOST_VERSION,6e4,requireProviderBrowser(browser))).browserAccess}async function startProviderBrowser(browser){let result=await requestControlledProvider(browser,"browser_manager_start",{});return validateProviderBrowser(result),{...result,browserId:browser.browserId}}function syncProviderBrowserCookies(browser,scope,host){return requestControlledProvider(browser,"browser_manager_sync_cookies",{scope},host)}async function configureProvider(providerId,options){if(!listInstalledProviders().find(item=>item.providerId===providerId)?.browserType.configuration)throw new Error(`Provider does not support configuration: ${providerId}`);let live=await requireLiveProvider(providerId);return requestBrowserSocket(live.socketPath,"browser_provider_configure",options,NATIVE_HOST_VERSION)}init_browser_socket_request();init_version();var AUTH_TIMEOUT_MS=12e4,POLL_INTERVAL_MS=750,BROW_BROWSER_PREFIX="provider:brow:",BROW_PACKAGE="@ali/mearl-provider-brow",browInstallation=null,runInstallerCommand=(command,args,options)=>runCommand(command,args,{...options,capture:!0,tee:!1,timeoutMs:options?.tee?18e4:3e4});async function ensureBrowInstalled(onProgress){listInstalledProviders().some(provider=>provider.providerId==="brow")||(onProgress?.("installing"),browInstallation??=installProviderPackage(BROW_PACKAGE,{runCommand:runInstallerCommand}).then(({manifest})=>{if(manifest.providerId!=="brow")throw new Error("Brow installer registered an unexpected Provider")}).finally(()=>{browInstallation=null}),await browInstallation)}function validateAlipayAuthCodeParams(value){let params=value&&typeof value=="object"?value:{},appId=typeof params.appId=="string"?params.appId.trim():"",scopeNicks=params.scopeNicks;if(!/^\d{10,32}$/.test(appId))throw new Error("getAuthCode requires a valid appId");if(!Array.isArray(scopeNicks)||scopeNicks.length<1||scopeNicks.length>8||!scopeNicks.every(scope=>typeof scope=="string"&&/^[a-zA-Z0-9_]{1,64}$/.test(scope)))throw new Error("getAuthCode requires valid scopeNicks");return{appId,scopeNicks,showErrorTip:params.showErrorTip===!0}}async function startAlipayAuthCode(value,onProgress){validateAlipayAuthCodeParams(value),await ensureBrowInstalled(onProgress);let browser=await launchProviderBrowser({provider:"brow",providerOptions:{}});try{if(browser.pairing?.kind!=="qr"||!browser.pairing.url)throw new Error("Brow did not return a pairing QR URL");return{browserId:browser.browserId,qrSvg:renderSVG(browser.pairing.url,{pixelSize:1,border:2})}}catch(error48){throw await closeAlipayAuthCode(browser.browserId).catch(()=>{}),error48}}async function closeAlipayAuthCode(browserId){let prefix=BROW_BROWSER_PREFIX;if(!browserId.startsWith(prefix))return;let browser=findProviderBrowser(browserId);if(browser)try{await closeProviderBrowser(browser);return}catch{}let live=readLiveProvider("brow");live&&await requestBrowserSocket(live.socketPath,"browser_close",{},NATIVE_HOST_VERSION,15e3,browserId.slice(prefix.length))}async function evaluate(browserId,tabId,expression){let browser=findProviderBrowser(browserId);if(!browser?.providerBrowserId)throw new Error("Brow pairing has ended");return(await requestBrowserSocket(browser.socketPath,"page_eval",{tabId,expression},NATIVE_HOST_VERSION,15e3,browser.providerBrowserId))?.result}async function waitAlipayAuthCode(browserId,value,onProgress){if(!browserId.startsWith(BROW_BROWSER_PREFIX))throw new Error("Invalid Brow pairing");let params=validateAlipayAuthCodeParams(value),deadline=Date.now()+AUTH_TIMEOUT_MS,probeKey=`__mearlAuthCode_${randomUUID10().replaceAll("-","")}`,started=!1,tabId=0,connected=!1;for(;Date.now()<deadline;){let browser=findProviderBrowser(browserId);if(browser?.providerBrowserId)try{if(!tabId){let tabs=(await requestBrowserSocket(browser.socketPath,"tab_list",{},NATIVE_HOST_VERSION,15e3,browser.providerBrowserId))?.tabs;tabId=(tabs?.find(item=>item.active&&typeof item.tabId=="number"&&/^https?:\/\//.test(item.url??""))??tabs?.find(item=>typeof item.tabId=="number"&&/^https?:\/\//.test(item.url??"")))?.tabId??0}if(tabId&&!connected&&(connected=!0,onProgress?.("connected")),tabId&&!started){let expression=`(() => {
1521
1529
  if (!/AliApp\\(AP\\//.test(navigator.userAgent) ||
1522
1530
  typeof window.AlipayJSBridge?.call !== 'function') return 'not-ready';
1523
1531
  const key = ${JSON.stringify(probeKey)};
@@ -1544,7 +1552,7 @@ Content-Type: ${file2.contentType}\r
1544
1552
  ${firstChangeTimeoutMs},
1545
1553
  ${timeoutMs}
1546
1554
  );
1547
- })()`,result=await sendCdpDeviceShellPageCommand(session,"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 sendCdpDeviceShellPageCommand(session,"Runtime.evaluate",{expression:`(${DISPOSE_PAGE_OBSERVER_SRC})()`,returnByValue:!1}).catch(()=>{})}init_dist();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},log2=>(!level||level==="all"||log2.level===level)&&(!pattern||matchesTextPattern(log2.message,pattern)||log2.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,tabId:session.tabId,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,tabId:session.tabId,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,tabId:session.tabId,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"){return runActionBatch(data,async(action,payload)=>({success:!0,data:await dispatchCdpAction(session,action,payload,controlSource)}))}async function cdpObservedPageAction(session,action,data,controlSource="local"){let{actionData,observe,diagnostics}=splitObservedActionPayload(action,data),{tabId}=actionData,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 randomUUID11}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=randomUUID11();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)))}}init_dist2();import fs12 from"node:fs";import path14 from"node:path";import{spawn as spawn8,spawnSync}from"node:child_process";var processes=new Map,CONNECTORS_SUBDIR="connectors",REGISTRY_DIR=keyedDir(CONNECTORS_SUBDIR),OFFICIAL_NPM_REGISTRY="https://registry.npmjs.org",STATUS_POLL_MS=5e3;function recordFileFor2(serverUrl){return keyedConfigFile(CONNECTORS_SUBDIR,serverUrl)}var logFn2=()=>{},isDaemon=!1,sendToExtensionFn=()=>{},nativeHostVersion="unknown",lastPushedKey="",statusWatcher=null;function initCloudConnector(deps){logFn2=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(recordFileFor2(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,expected){let entry=processes.get(serverUrl);entry&&entry.pid!==expected.pid||expected.child&&entry?.process&&entry.process!==expected.child||(processes.delete(serverUrl),removeRecordIfPid(recordFileFor2(serverUrl),expected.pid),notifyStatusChanged())}function findLiveConnector(serverUrl){let entry=processes.get(serverUrl);if(entry&&isAlive(entry.pid))return entry.pid;let record2=readRecord(recordFileFor2(serverUrl));return record2&&isAlive(record2.pid)?record2.pid:(entry&&processes.delete(serverUrl),record2&&removeRecordIfPid(recordFileFor2(serverUrl),record2.pid),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=path14.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 logFn2(`Cloud connector ${installedVersion} found at ${connectorPath}`),makeDirectCommand(connectorPath);logFn2(`Cloud connector version mismatch: installed=${installedVersion}, expected=${nativeHostVersion}`)}let npmBin=process.platform==="win32"?"npm.cmd":"npm",npmPath=path14.join(nodeDir,npmBin),npmCommand=fs12.existsSync(npmPath)?npmPath:npmBin,targetPackage=`@mearl/cloud-connector@${nativeHostVersion}`;logFn2(`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 logFn2(`Global install succeeded: ${newPath}`),makeDirectCommand(newPath)}logFn2(`Global install failed (status=${install.status}), falling back to npx`),install.stderr&&logFn2(install.stderr.trim());let npxBin=process.platform==="win32"?"npx.cmd":"npx",npxPath=path14.join(nodeDir,npxBin),npxCommand=fs12.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(resolve9=>{let existingPid=findLiveConnector(serverUrl);if(existingPid){logFn2(`Reusing existing cloud connector for ${serverUrl} (pid=${existingPid})`);let entry=registerConnector(serverUrl,existingPid);resolve9({success:!0,pid:existingPid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{},reused:!0});return}let connectorCommand=resolveCloudConnectorCommand();logFn2(`Starting cloud connector via ${connectorCommand.displayName}`);let child=spawn8(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);resolve9({success:!0,pid:child.pid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{}})}else resolve9({success:!1,error:result.error||"Failed to spawn cloud connector"})};child.once("error",error48=>{logFn2(`Failed to spawn cloud connector: ${error48.message}`),finish(!1,{error:error48.message})});let handleOutput=chunk=>{let text=chunk.toString();outputBuffer=(outputBuffer+text).slice(-2e3),logFn2(`[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)=>{child.pid&&clearConnector(serverUrl,{pid:child.pid,child}),logFn2(`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(recordFileFor2(serverUrl))?.pid;if(!pid)return{success:!1,error:"Cloud connector not found"};try{return isAlive(pid)&&process.kill(pid),clearConnector(serverUrl,{pid}),logFn2(`Stopped cloud connector for ${serverUrl} (pid=${pid})`),{success:!0}}catch(error48){let err=error48;return err.code==="ESRCH"?(clearConnector(serverUrl,{pid}),{success:!0}):(logFn2(`Failed to stop cloud connector: ${err.message}`),{success:!1,error:err.message})}}function listCloudConnectors(){return{connectors:pushIfChanged()}}init_dist();async function activateCdpTarget(browserClient,targetId){let windowRestored=!1,windowState;try{let windowInfo=await browserClient.sendCommand("Browser.getWindowForTarget",{targetId});windowState=windowInfo?.bounds?.windowState,typeof windowInfo?.windowId=="number"&&windowState==="minimized"&&(await browserClient.sendCommand("Browser.setWindowBounds",{windowId:windowInfo.windowId,bounds:{windowState:"normal"}}),windowRestored=!0,windowState="normal")}catch{}return await browserClient.sendCommand("Target.activateTarget",{targetId}),{requested:!0,tabActive:!0,...windowRestored?{windowRestored}:{},...windowState?{windowState}:{}}}async function readCdpVisibilityState(pageSession){try{let result=await pageSession.client.sendCommand("Runtime.evaluate",{expression:"document.visibilityState",returnByValue:!0});return typeof result.result?.value=="string"?result.result.value:void 0}catch{return}}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,devicePreset:emulation?.preset,orientation:emulation?.orientation,bridgeConfig:data.bridgeConfig}):void 0,emulationConfig=emulation?resolveEmulationConfig({...emulation,enabled:!0}):void 0,splitScreen=emulation?.deviceShell===!0&&emulation?.splitScreen===!0&&emulationConfig?.orientation==="landscape"&&!!resolvedProfile,browserClient=await session.getBrowserClient();if(reuse!=="never"){let pages=((await browserClient.sendCommand("Target.getTargets")).targetInfos??[]).filter(target=>target.type==="page"&&isImplicitlySelectablePageUrl(target.url)),blocked=new Set(data.__mearlBlockedTabIds??[]),available=[];for(let page of pages){let tabId2=await session.ensureTargetRegistered(page.targetId);blocked.has(tabId2)||available.push(page)}let existing=selectMatchingTab(available,url2,match);if(existing){if(emulation||appProfile)throw new Error("tab_open cannot apply pre-navigation emulation or appProfile to a reused tab.");let activation2=active?await activateCdpTarget(browserClient,existing.targetId):void 0,tabId2=await session.ensureTargetRegistered(existing.targetId),pageSession2=await session.getPageSession(tabId2);if(activation2){let visibilityState=await readCdpVisibilityState(pageSession2);visibilityState&&(activation2.visibilityState=visibilityState)}await ensureControlledIndicator(pageSession2,controlSource);let capture2=currentCapture(pageSession2);return{tabId:tabId2,url:existing.url??url2,title:existing.title??"",opened:!1,reused:!0,capture:capture2,...activation2?{activation:activation2}:{}}}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,activation=active?await activateCdpTarget(browserClient,targetId):void 0,tabId=await session.registerTarget(targetId),pageSession=await session.getPageSession(tabId);await ensureControlledIndicator(pageSession,controlSource);let capture=currentCapture(pageSession);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,config:emulationConfig,deviceShell:emulation?.deviceShell===!0,splitScreen},emulation?.deviceShell&&await applyCdpDeviceShell(pageSession,emulationConfig,{rootContainerManagedByApp:splitScreen})}resolvedProfile&&await applyResolvedCdpAppProfile(pageSession,resolvedProfile),await pageSession.client.sendCommand("Page.navigate",{url:url2}),emulation?.deviceShell?await waitForCdpDeviceShellLoad(pageSession):resolvedProfile?await waitForCdpAppProfileLoad(pageSession):await waitForPageLoad(pageSession,3e4);let targetInfo=await browserClient.sendCommand("Target.getTargetInfo",{targetId}).then(result2=>result2.targetInfo).catch(()=>null),openedUrl=targetInfo?.url??url2;if(activation){let visibilityState=await readCdpVisibilityState(pageSession);visibilityState&&(activation.visibilityState=visibilityState)}return{tabId,url:openedUrl,title:targetInfo?.title??"",opened:!0,reused:!1,capture,...activation?{activation}:{},...!isImplicitlySelectablePageUrl(openedUrl)&&{note:"This URL is excluded from implicit CDP target selection. Pass this tabId to subsequent page actions."},...emulationConfig&&{emulation:{preset:emulationConfig.presetName,viewport:{width:emulationConfig.width,height:emulationConfig.height,deviceScaleFactor:emulationConfig.deviceScaleFactor,scale:emulationConfig.scale??1},userAgent:emulationConfig.userAgent,mobile:emulationConfig.mobile,touch:emulationConfig.touch,orientation:emulationConfig.orientation,deviceShell:emulation?.deviceShell===!0,splitScreen}},...resolvedProfile&&{appProfile:{profile:resolvedProfile.profile.profile,label:resolvedProfile.profile.label,userAgent:resolvedProfile.profile.ua,os:resolvedProfile.profile.injected.platform==="Android"?"android":"ios"}}}}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"&&isImplicitlySelectablePageUrl(t.url)),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}]);init_dist();init_dist();async function withCdpFrameTarget(session,targetId,callback){let{sessionId}=await session.client.sendCommand("Target.attachToTarget",{targetId,flatten:!0});try{return await callback(session.client.createChildSession(sessionId))}finally{await session.client.sendCommand("Target.detachFromTarget",{sessionId}).catch(()=>{})}}async function readCdpFrameEntries(session,requestedFrameId){let{frameTree}=await session.client.sendCommand("Page.getFrameTree",{}),mainFrameId=frameTree?.frame?.id,entries=new Map,append=(tree,targetId,parentFrameId)=>{if(!tree)return;let{frame,childFrames=[]}=tree;entries.set(frame.id,{targetId,frame:{frameId:frame.id,parentFrameId:frame.parentId??parentFrameId??null,url:frame.url,name:frame.name??"",isMainFrame:frame.id===mainFrameId}});for(let child of childFrames)append(child,targetId,frame.id)};if(append(frameTree,session.targetId),requestedFrameId&&entries.has(requestedFrameId))return[...entries.values()];let{targetInfos=[]}=await session.client.sendCommand("Target.getTargets"),pending=targetInfos.filter(target=>target.type==="iframe"),pageTargets=new Set([session.targetId]),expanded=!0;for(;expanded;){expanded=!1;for(let index=pending.length-1;index>=0;index-=1){let target=pending[index];if(!(target.parentId&&pageTargets.has(target.parentId))&&!(target.parentFrameId&&entries.has(target.parentFrameId)))continue;pending.splice(index,1);let tree=await withCdpFrameTarget(session,target.targetId,child=>child.sendCommand("Page.getFrameTree",{}));if(append(tree.frameTree,target.targetId,target.parentFrameId),pageTargets.add(target.targetId),expanded=!0,requestedFrameId&&entries.has(requestedFrameId))return[...entries.values()]}}return[...entries.values()]}async function evaluateCdpFrame(session,frameId,params){if(typeof frameId!="string"||!frameId.trim())throw new PageActionPreconditionError("page_eval: frameId must be a non-empty string");let entry=(await readCdpFrameEntries(session,frameId)).find(candidate=>candidate.frame.frameId===frameId);if(!entry)throw new PageActionPreconditionError(`page_eval: frameId "${frameId}" is not present in the current page. Run page_frames to get current frame IDs.`);return withCdpFrameTarget(session,entry.targetId,child=>evaluateFrameContext(child,frameId,params))}async function evaluateFrameContext(child,frameId,params){let contextId,notifyContext=()=>{},disposers=[child.on("Runtime.executionContextCreated",({context})=>{context?.auxData?.frameId===frameId&&context.auxData.isDefault===!0&&typeof context.id=="number"&&(contextId=context.id,notifyContext())}),child.on("Runtime.executionContextsCleared",()=>{contextId=void 0}),child.on("Runtime.executionContextDestroyed",({executionContextId})=>{executionContextId===contextId&&(contextId=void 0)})];try{if(await child.sendCommand("Runtime.enable"),contextId===void 0&&await new Promise(resolve9=>{let timer=setTimeout(resolve9,3e3);notifyContext=()=>{clearTimeout(timer),resolve9()}}),contextId===void 0)throw new PageActionPreconditionError(`page_eval: main-world execution context for frame "${frameId}" is unavailable. Run page_frames to verify the frame is still present.`);return await child.sendCommand("Runtime.evaluate",{...params,contextId})}finally{for(let dispose of disposers)dispose()}}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 sendCdpDeviceShellPageCommand(session,"Runtime.evaluate",{expression:`(() => {
1555
+ })()`,result=await sendCdpDeviceShellPageCommand(session,"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 sendCdpDeviceShellPageCommand(session,"Runtime.evaluate",{expression:`(${DISPOSE_PAGE_OBSERVER_SRC})()`,returnByValue:!1}).catch(()=>{})}init_dist();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},log2=>(!level||level==="all"||log2.level===level)&&(!pattern||matchesTextPattern(log2.message,pattern)||log2.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,tabId:session.tabId,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,tabId:session.tabId,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,tabId:session.tabId,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"){return runActionBatch(data,async(action,payload)=>({success:!0,data:await dispatchCdpAction(session,action,payload,controlSource)}))}async function cdpObservedPageAction(session,action,data,controlSource="local"){let{actionData,observe,diagnostics}=splitObservedActionPayload(action,data),{tabId}=actionData,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 randomUUID11}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=randomUUID11();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 fs12 from"node:fs";import path14 from"node:path";import{spawn as spawn8,spawnSync}from"node:child_process";init_dist2();var processes=new Map,CONNECTORS_SUBDIR="connectors",REGISTRY_DIR=keyedDir(CONNECTORS_SUBDIR),STATUS_POLL_MS=5e3;function recordFileFor2(serverUrl){return keyedConfigFile(CONNECTORS_SUBDIR,serverUrl)}var logFn2=()=>{},isDaemon=!1,sendToExtensionFn=()=>{},nativeHostVersion="unknown",lastPushedKey="",statusWatcher=null;function initCloudConnector(deps){logFn2=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(recordFileFor2(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,expected){let entry=processes.get(serverUrl);entry&&entry.pid!==expected.pid||expected.child&&entry?.process&&entry.process!==expected.child||(processes.delete(serverUrl),removeRecordIfPid(recordFileFor2(serverUrl),expected.pid),notifyStatusChanged())}function findLiveConnector(serverUrl){let entry=processes.get(serverUrl);if(entry&&isAlive(entry.pid))return entry.pid;let record2=readRecord(recordFileFor2(serverUrl));return record2&&isAlive(record2.pid)?record2.pid:(entry&&processes.delete(serverUrl),record2&&removeRecordIfPid(recordFileFor2(serverUrl),record2.pid),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=path14.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 logFn2(`Cloud connector ${installedVersion} found at ${connectorPath}`),makeDirectCommand(connectorPath);logFn2(`Cloud connector version mismatch: installed=${installedVersion}, expected=${nativeHostVersion}`)}let npmBin=process.platform==="win32"?"npm.cmd":"npm",npmPath=path14.join(nodeDir,npmBin),npmCommand=fs12.existsSync(npmPath)?npmPath:npmBin,targetPackage=`@mearl/cloud-connector@${nativeHostVersion}`,installEnv=packageRegistryEnvironment("@mearl/cloud-connector",enrichedEnv);logFn2(`Installing ${targetPackage} globally via ${npmCommand}...`);let install=spawnSync(npmCommand,["install","-g",targetPackage,"--prefer-offline"],{encoding:"utf-8",env:installEnv,timeout:3e4});if(install.status===0){let newPath=findBin(connectorBin,enrichedEnv);if(newPath)return logFn2(`Global install succeeded: ${newPath}`),makeDirectCommand(newPath)}logFn2(`Global install failed (status=${install.status}), falling back to npx`),install.stderr&&logFn2(install.stderr.trim());let npxBin=process.platform==="win32"?"npx.cmd":"npx",npxPath=path14.join(nodeDir,npxBin),npxCommand=fs12.existsSync(npxPath)?npxPath:npxBin;return{command:npxCommand,argsPrefix:[`@mearl/cloud-connector@${nativeHostVersion}`],displayName:`${npxCommand} @mearl/cloud-connector@${nativeHostVersion}`,env:installEnv}}function startCloudConnector(serverUrl){return new Promise(resolve9=>{let existingPid=findLiveConnector(serverUrl);if(existingPid){logFn2(`Reusing existing cloud connector for ${serverUrl} (pid=${existingPid})`);let entry=registerConnector(serverUrl,existingPid);resolve9({success:!0,pid:existingPid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{},reused:!0});return}let connectorCommand=resolveCloudConnectorCommand();logFn2(`Starting cloud connector via ${connectorCommand.displayName}`);let child=spawn8(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);resolve9({success:!0,pid:child.pid,...entry.connectorId?{connectorId:entry.connectorId}:{},...entry.name?{name:entry.name}:{}})}else resolve9({success:!1,error:result.error||"Failed to spawn cloud connector"})};child.once("error",error48=>{logFn2(`Failed to spawn cloud connector: ${error48.message}`),finish(!1,{error:error48.message})});let handleOutput=chunk=>{let text=chunk.toString();outputBuffer=(outputBuffer+text).slice(-2e3),logFn2(`[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)=>{child.pid&&clearConnector(serverUrl,{pid:child.pid,child}),logFn2(`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(recordFileFor2(serverUrl))?.pid;if(!pid)return{success:!1,error:"Cloud connector not found"};try{return isAlive(pid)&&process.kill(pid),clearConnector(serverUrl,{pid}),logFn2(`Stopped cloud connector for ${serverUrl} (pid=${pid})`),{success:!0}}catch(error48){let err=error48;return err.code==="ESRCH"?(clearConnector(serverUrl,{pid}),{success:!0}):(logFn2(`Failed to stop cloud connector: ${err.message}`),{success:!1,error:err.message})}}function listCloudConnectors(){return{connectors:pushIfChanged()}}init_dist();async function activateCdpTarget(browserClient,targetId){let windowRestored=!1,windowState;try{let windowInfo=await browserClient.sendCommand("Browser.getWindowForTarget",{targetId});windowState=windowInfo?.bounds?.windowState,typeof windowInfo?.windowId=="number"&&windowState==="minimized"&&(await browserClient.sendCommand("Browser.setWindowBounds",{windowId:windowInfo.windowId,bounds:{windowState:"normal"}}),windowRestored=!0,windowState="normal")}catch{}return await browserClient.sendCommand("Target.activateTarget",{targetId}),{requested:!0,tabActive:!0,...windowRestored?{windowRestored}:{},...windowState?{windowState}:{}}}async function readCdpVisibilityState(pageSession){try{let result=await pageSession.client.sendCommand("Runtime.evaluate",{expression:"document.visibilityState",returnByValue:!0});return typeof result.result?.value=="string"?result.result.value:void 0}catch{return}}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,devicePreset:emulation?.preset,orientation:emulation?.orientation,bridgeConfig:data.bridgeConfig}):void 0,emulationConfig=emulation?resolveEmulationConfig({...emulation,enabled:!0}):void 0,splitScreen=emulation?.deviceShell===!0&&emulation?.splitScreen===!0&&emulationConfig?.orientation==="landscape"&&!!resolvedProfile,browserClient=await session.getBrowserClient();if(reuse!=="never"){let pages=((await browserClient.sendCommand("Target.getTargets")).targetInfos??[]).filter(target=>target.type==="page"&&isImplicitlySelectablePageUrl(target.url)),blocked=new Set(data.__mearlBlockedTabIds??[]),available=[];for(let page of pages){let tabId2=await session.ensureTargetRegistered(page.targetId);blocked.has(tabId2)||available.push(page)}let existing=selectMatchingTab(available,url2,match);if(existing){if(emulation||appProfile)throw new Error("tab_open cannot apply pre-navigation emulation or appProfile to a reused tab.");let activation2=active?await activateCdpTarget(browserClient,existing.targetId):void 0,tabId2=await session.ensureTargetRegistered(existing.targetId),pageSession2=await session.getPageSession(tabId2);if(activation2){let visibilityState=await readCdpVisibilityState(pageSession2);visibilityState&&(activation2.visibilityState=visibilityState)}await ensureControlledIndicator(pageSession2,controlSource);let capture2=currentCapture(pageSession2);return{tabId:tabId2,url:existing.url??url2,title:existing.title??"",opened:!1,reused:!0,capture:capture2,...activation2?{activation:activation2}:{}}}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,activation=active?await activateCdpTarget(browserClient,targetId):void 0,tabId=await session.registerTarget(targetId),pageSession=await session.getPageSession(tabId);await ensureControlledIndicator(pageSession,controlSource);let capture=currentCapture(pageSession);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,config:emulationConfig,deviceShell:emulation?.deviceShell===!0,splitScreen},emulation?.deviceShell&&await applyCdpDeviceShell(pageSession,emulationConfig,{rootContainerManagedByApp:splitScreen})}resolvedProfile&&await applyResolvedCdpAppProfile(pageSession,resolvedProfile),await pageSession.client.sendCommand("Page.navigate",{url:url2}),emulation?.deviceShell?await waitForCdpDeviceShellLoad(pageSession):resolvedProfile?await waitForCdpAppProfileLoad(pageSession):await waitForPageLoad(pageSession,3e4);let targetInfo=await browserClient.sendCommand("Target.getTargetInfo",{targetId}).then(result2=>result2.targetInfo).catch(()=>null),openedUrl=targetInfo?.url??url2;if(activation){let visibilityState=await readCdpVisibilityState(pageSession);visibilityState&&(activation.visibilityState=visibilityState)}return{tabId,url:openedUrl,title:targetInfo?.title??"",opened:!0,reused:!1,capture,...activation?{activation}:{},...!isImplicitlySelectablePageUrl(openedUrl)&&{note:"This URL is excluded from implicit CDP target selection. Pass this tabId to subsequent page actions."},...emulationConfig&&{emulation:{preset:emulationConfig.presetName,viewport:{width:emulationConfig.width,height:emulationConfig.height,deviceScaleFactor:emulationConfig.deviceScaleFactor,scale:emulationConfig.scale??1},userAgent:emulationConfig.userAgent,mobile:emulationConfig.mobile,touch:emulationConfig.touch,orientation:emulationConfig.orientation,deviceShell:emulation?.deviceShell===!0,splitScreen}},...resolvedProfile&&{appProfile:{profile:resolvedProfile.profile.profile,label:resolvedProfile.profile.label,userAgent:resolvedProfile.profile.ua,os:resolvedProfile.profile.injected.platform==="Android"?"android":"ios"}}}}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"&&isImplicitlySelectablePageUrl(t.url)),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}]);init_dist();init_dist();async function withCdpFrameTarget(session,targetId,callback){let{sessionId}=await session.client.sendCommand("Target.attachToTarget",{targetId,flatten:!0});try{return await callback(session.client.createChildSession(sessionId))}finally{await session.client.sendCommand("Target.detachFromTarget",{sessionId}).catch(()=>{})}}async function readCdpFrameEntries(session,requestedFrameId){let{frameTree}=await session.client.sendCommand("Page.getFrameTree",{}),mainFrameId=frameTree?.frame?.id,entries=new Map,append=(tree,targetId,parentFrameId)=>{if(!tree)return;let{frame,childFrames=[]}=tree;entries.set(frame.id,{targetId,frame:{frameId:frame.id,parentFrameId:frame.parentId??parentFrameId??null,url:frame.url,name:frame.name??"",isMainFrame:frame.id===mainFrameId}});for(let child of childFrames)append(child,targetId,frame.id)};if(append(frameTree,session.targetId),requestedFrameId&&entries.has(requestedFrameId))return[...entries.values()];let{targetInfos=[]}=await session.client.sendCommand("Target.getTargets"),pending=targetInfos.filter(target=>target.type==="iframe"),pageTargets=new Set([session.targetId]),expanded=!0;for(;expanded;){expanded=!1;for(let index=pending.length-1;index>=0;index-=1){let target=pending[index];if(!(target.parentId&&pageTargets.has(target.parentId))&&!(target.parentFrameId&&entries.has(target.parentFrameId)))continue;pending.splice(index,1);let tree=await withCdpFrameTarget(session,target.targetId,child=>child.sendCommand("Page.getFrameTree",{}));if(append(tree.frameTree,target.targetId,target.parentFrameId),pageTargets.add(target.targetId),expanded=!0,requestedFrameId&&entries.has(requestedFrameId))return[...entries.values()]}}return[...entries.values()]}async function evaluateCdpFrame(session,frameId,params){if(typeof frameId!="string"||!frameId.trim())throw new PageActionPreconditionError("page_eval: frameId must be a non-empty string");let entry=(await readCdpFrameEntries(session,frameId)).find(candidate=>candidate.frame.frameId===frameId);if(!entry)throw new PageActionPreconditionError(`page_eval: frameId "${frameId}" is not present in the current page. Run page_frames to get current frame IDs.`);return withCdpFrameTarget(session,entry.targetId,child=>evaluateFrameContext(child,frameId,params))}async function evaluateFrameContext(child,frameId,params){let contextId,notifyContext=()=>{},disposers=[child.on("Runtime.executionContextCreated",({context})=>{context?.auxData?.frameId===frameId&&context.auxData.isDefault===!0&&typeof context.id=="number"&&(contextId=context.id,notifyContext())}),child.on("Runtime.executionContextsCleared",()=>{contextId=void 0}),child.on("Runtime.executionContextDestroyed",({executionContextId})=>{executionContextId===contextId&&(contextId=void 0)})];try{if(await child.sendCommand("Runtime.enable"),contextId===void 0&&await new Promise(resolve9=>{let timer=setTimeout(resolve9,3e3);notifyContext=()=>{clearTimeout(timer),resolve9()}}),contextId===void 0)throw new PageActionPreconditionError(`page_eval: main-world execution context for frame "${frameId}" is unavailable. Run page_frames to verify the frame is still present.`);return await child.sendCommand("Runtime.evaluate",{...params,contextId})}finally{for(let dispose of disposers)dispose()}}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 sendCdpDeviceShellPageCommand(session,"Runtime.evaluate",{expression:`(() => {
1548
1556
  const sel = ${JSON.stringify(selector)};
1549
1557
  const el = document.querySelector(sel);
1550
1558
  if (!el) return { clicked: false, error: 'Element not found: ' + sel };
@@ -1676,10 +1684,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
1676
1684
  User request:
1677
1685
  ${message}`:message,promptContent=[...prompt?[{type:"text",text:prompt}]:[],...images.map(image=>({type:"image",data:image.data,mimeType:image.mimeType}))];return session.instructionsSent=!0,this.emit({providerSessionId,kind:"notification",method:"turn/started",params:{turn:{id:turnId,status:"inProgress"}}}),this.runPrompt(providerSessionId,session,turn,promptContent),{turnId}}async interrupt(providerSessionId,_turnId){await this.ensureStarted(),await this.getContext().notify(methods.agent.session.cancel,{sessionId:providerSessionId}),this.cancelPermissions(providerSessionId)}async closeSession(providerSessionId){this.sessions.get(providerSessionId)?.activeTurn&&this.context&&await this.context.notify(methods.agent.session.cancel,{sessionId:providerSessionId}).catch(()=>{}),this.cancelPermissions(providerSessionId),this.sessions.delete(providerSessionId)}respondToRequest(requestId,result){let pending=this.pendingPermissions.get(requestId);if(!pending)throw new Error(`Unknown Qoder permission request: ${String(requestId)}`);if(!isPermissionResponse(result))throw new Error("Invalid Qoder permission response");this.pendingPermissions.delete(requestId),pending.resolve(result),this.emit({providerSessionId:pending.providerSessionId,kind:"notification",method:"serverRequest/resolved",params:{requestId}})}dispose(){for(let pending of this.pendingPermissions.values())pending.resolve({outcome:{outcome:"cancelled"}});this.pendingPermissions.clear(),this.historyCaptures.clear(),this.sessions.clear();let connection=this.connection,child=this.process;this.process=null,this.connection=null,this.context=null,this.initializeResponse=null,this.startPromise=null,this.executableResolver.reset(),connection?.close(new Error("Qoder provider disposed")),child&&!child.killed&&child.kill("SIGTERM")}async ensureStarted(){if(!(this.process&&!this.process.killed&&this.context)){if(this.startPromise)return this.startPromise;this.startPromise=this.start();try{await this.startPromise}catch(error48){throw this.startPromise=null,error48}}}async start(){let resolution=await this.resolveExecutable();if(resolution.executable===null)throw new Error(resolution.error);let{executable}=resolution,launch=resolveSpawnCommand(executable,["--acp"]),child=spawn11(launch.command,launch.args,{stdio:["pipe","pipe","pipe"],windowsHide:!0,env:prependNodePath()});this.process=child,child.stderr.on("data",chunk=>{let message=chunk.toString("utf8").trim();message&&this.log("[Qoder]",message)}),child.once("error",error48=>this.handleExit(child,error48)),child.once("exit",(code,signal)=>{this.handleExit(child,new Error(`Qoder ACP exited (code=${String(code)}, signal=${String(signal)})`))});let stream=ndJsonStream(Writable.toWeb(child.stdin),Readable.toWeb(child.stdout)),connection=client({name:"mearl"}).onRequest(methods.client.session.requestPermission,context=>this.handlePermissionRequest(context.requestId,context.params)).onNotification(methods.client.session.update,context=>{this.handleSessionUpdate(context.params)}).connect(stream);this.connection=connection,this.context=connection.agent;try{this.initializeResponse=await this.withTimeout(connection.agent.request(methods.agent.initialize,{protocolVersion:PROTOCOL_VERSION,clientCapabilities:{},clientInfo:{name:"mearl",title:"Mearl",version:this.clientVersion}}),"Qoder ACP initialization")}catch(error48){throw this.process=null,this.connection=null,this.context=null,this.executableResolver.reset(),connection.close(error48),child.killed||child.kill("SIGTERM"),new Error(`Qoder ACP failed to initialize. Start "qodercli", enter "/login", and try again: ${errorMessage(error48)}`,{cause:error48})}}async runPrompt(providerSessionId,session,turn,prompt){try{let response=await this.getContext().request(methods.agent.session.prompt,{sessionId:providerSessionId,prompt});turn.reasoningStarted&&this.emit({providerSessionId,kind:"notification",method:"item/completed",params:{turnId:turn.id,item:{id:turn.reasoningItemId,type:"reasoning",summary:turn.reasoningText?[turn.reasoningText]:[]}}}),turn.assistantText&&this.emit({providerSessionId,kind:"notification",method:"item/completed",params:{turnId:turn.id,item:{id:turn.assistantItemId,type:"agentMessage",text:turn.assistantText}}}),response.usage&&this.emit({providerSessionId,kind:"notification",method:"thread/tokenUsage/updated",params:{turnId:turn.id,usage:response.usage}}),this.emit({providerSessionId,kind:"notification",method:"turn/completed",params:{turn:{id:turn.id,status:response.stopReason==="cancelled"?"cancelled":"completed",stopReason:response.stopReason}}})}catch(error48){this.emit({providerSessionId,kind:"error",method:"chat/error",params:{turnId:turn.id,message:errorMessage(error48)}}),this.emit({providerSessionId,kind:"notification",method:"turn/completed",params:{turn:{id:turn.id,status:"failed"}}})}finally{session.activeTurn===turn&&delete session.activeTurn}}handleSessionUpdate(notification){let historyCapture=this.historyCaptures.get(notification.sessionId);if(historyCapture){captureHistoryUpdate(historyCapture,notification.update);return}let session=this.sessions.get(notification.sessionId),update=notification.update;if(update.sessionUpdate==="config_option_update"){let model=qoderModelInfo(update.configOptions);session&&(model?session.model=model:delete session.model),this.emit({providerSessionId:notification.sessionId,kind:"notification",method:"session/model/updated",params:{model:model??null}}),this.emit({providerSessionId:notification.sessionId,kind:"notification",method:"qoder/sessionUpdate",params:notification});return}let turn=session?.activeTurn;if(!turn){this.emit({providerSessionId:notification.sessionId,kind:"notification",method:"qoder/sessionUpdate",params:notification});return}switch(update.sessionUpdate){case"agent_message_chunk":{let delta=contentText(update.content);if(!delta)return;turn.assistantText+=delta,this.emit({providerSessionId:notification.sessionId,kind:"notification",method:"item/agentMessage/delta",params:{turnId:turn.id,itemId:turn.assistantItemId,delta}});return}case"agent_thought_chunk":{let delta=contentText(update.content);if(!delta)return;turn.reasoningStarted||(turn.reasoningStarted=!0,this.emit({providerSessionId:notification.sessionId,kind:"notification",method:"item/started",params:{turnId:turn.id,item:{id:turn.reasoningItemId,type:"reasoning",summary:[]}}})),turn.reasoningText+=delta,this.emit({providerSessionId:notification.sessionId,kind:"notification",method:"item/reasoning/summaryTextDelta",params:{turnId:turn.id,itemId:turn.reasoningItemId,delta}});return}case"tool_call":turn.toolTitles.set(update.toolCallId,update.title),this.emitToolUpdate(notification.sessionId,turn,update,update.title);return;case"tool_call_update":{let title=update.title||turn.toolTitles.get(update.toolCallId)||update.toolCallId;turn.toolTitles.set(update.toolCallId,title),this.emitToolUpdate(notification.sessionId,turn,update,title);return}case"plan":{let text=planText(update.entries);this.emit({providerSessionId:notification.sessionId,kind:"notification",method:"item/completed",params:{turnId:turn.id,item:{id:turn.planItemId,type:"plan",text}}});return}case"usage_update":this.emit({providerSessionId:notification.sessionId,kind:"notification",method:"thread/tokenUsage/updated",params:{turnId:turn.id,usage:update}});return;default:this.emit({providerSessionId:notification.sessionId,kind:"notification",method:"qoder/sessionUpdate",params:{turnId:turn.id,update}})}}emitToolUpdate(providerSessionId,turn,update,title){let completed=update.status==="completed"||update.status==="failed";this.emit({providerSessionId,kind:"notification",method:completed?"item/completed":"item/started",params:{turnId:turn.id,item:{id:update.toolCallId,type:"dynamicToolCall",namespace:"qoder",tool:title,status:update.status||(completed?"completed":"inProgress"),kind:update.kind,rawInput:update.rawInput,rawOutput:update.rawOutput,content:update.content,locations:update.locations}}})}handlePermissionRequest(requestId,request){return requestId===null?Promise.resolve({outcome:{outcome:"cancelled"}}):new Promise(resolve9=>{this.pendingPermissions.set(requestId,{providerSessionId:request.sessionId,resolve:resolve9}),this.emit({providerSessionId:request.sessionId,kind:"request",method:"qoder/requestPermission",params:request,requestId})})}cancelPermissions(providerSessionId){for(let[requestId,pending]of this.pendingPermissions)pending.providerSessionId===providerSessionId&&(this.pendingPermissions.delete(requestId),pending.resolve({outcome:{outcome:"cancelled"}}))}handleExit(child,error48){if(this.process===child){this.process=null,this.connection?.close(error48),this.connection=null,this.context=null,this.initializeResponse=null,this.startPromise=null,this.executableResolver.reset();for(let providerSessionId of this.sessions.keys())this.cancelPermissions(providerSessionId),this.emit({providerSessionId,kind:"error",method:"provider/exited",params:{message:error48.message}})}}getContext(){if(!this.context)throw new Error("Qoder ACP is not running");return this.context}assertImageInputSupported(){if(!this.initializeResponse?.agentCapabilities?.promptCapabilities?.image)throw new Error("This Qoder CLI version does not support image prompts")}withTimeout(promise2,operation){return new Promise((resolve9,reject)=>{let timer=setTimeout(()=>reject(new Error(`${operation} timed out`)),REQUEST_TIMEOUT_MS2);promise2.then(result=>{clearTimeout(timer),resolve9(result)},error48=>{clearTimeout(timer),reject(error48)})})}probeExecutable(executable){return probeAgentExecutable(executable,{args:["--version"],timeoutMs:PROBE_TIMEOUT_MS2,timeoutError:"Timed out while checking Qoder CLI availability.",startError:error48=>`Failed to start Qoder CLI: ${error48.message}`,exitError:code=>`Qoder CLI check exited with code ${String(code)}`})}runSkillsList(executable,cwd){return new Promise((resolve9,reject)=>{let launch=resolveSpawnCommand(executable,["skill","list","--all"]),child=spawn11(launch.command,launch.args,{cwd,stdio:["ignore","pipe","pipe"],windowsHide:!0,env:prependNodePath()}),stdout="",stderr="",settled=!1,finish=error48=>{settled||(settled=!0,clearTimeout(timer),error48?reject(error48):resolve9(stdout))},timer=setTimeout(()=>{child.kill("SIGTERM"),finish(new Error("Timed out while listing Qoder skills."))},REQUEST_TIMEOUT_MS2);child.stdout.on("data",chunk=>{stdout.length<1e6&&(stdout+=chunk.toString("utf8"))}),child.stderr.on("data",chunk=>{stderr.length<1e4&&(stderr+=chunk.toString("utf8"))}),child.once("error",error48=>finish(error48)),child.once("exit",code=>{code===0?finish():finish(new Error(stderr.trim()||`Qoder skill list exited with code ${String(code)}`))})})}resolveExecutable(){return this.executableResolver.resolve()}resolveExecutableCandidates(){return executableFileCandidates(qoderExecutableCandidatePaths())}emit(event){for(let listener of this.listeners)listener(event)}};import{existsSync as existsSync9,realpathSync as realpathSync3}from"node:fs";import{homedir as homedir6}from"node:os";import{dirname as dirname9,join as join13,resolve as resolve8}from"node:path";init_plugin();var NPX_EXECUTABLE=process.platform==="win32"?"npx.cmd":"npx",NPX_ARGS_PREFIX=["-y","ali-skills"],SKILL_PLUGIN_MANAGER="ali-skills",registrationContext={options:{},invoke:async()=>{throw new Error("注册时不能执行浏览器操作")},progress:()=>{throw new Error("注册时不能报告执行进度")}};function installedSkillDirectory(name,scope,cwd){return join13(scope==="global"?homedir6():cwd,".agents","skills",name)}function canonicalDirectory(directory){try{return realpathSync3(directory)}catch{return resolve8(directory)}}function registeredNamesForSkill(directory){let installedDirectory=resolve8(directory);return listPluginNames().filter(name=>{let entry=findPluginRegistration(name)?.entry;return entry!==void 0&&resolve8(dirname9(dirname9(entry)))===installedDirectory})}async function registerInstalledSkillPlugin(directory,skillName){if(!existsSync9(join13(directory,"SKILL.md")))throw new Error(`Skill 安装完成但找不到安装目录: ${directory}`);let entry=findPluginDirectoryEntry(directory);if(!entry)return;let plugin=await loadPlugin(entry,registrationContext),name=plugin.name||skillName,existing=findPluginRegistration(name),existingDirectory=existing&&dirname9(dirname9(existing.entry));if(existing&&existingDirectory&&(existing.managedBy===SKILL_PLUGIN_MANAGER?resolve8(existingDirectory)!==resolve8(directory):canonicalDirectory(existingDirectory)!==canonicalDirectory(directory)))throw new Error(`插件 ${name} 已由其他 Skill 注册,无法自动覆盖`);return registerPlugin(name,entry,plugin.description,{managedBy:SKILL_PLUGIN_MANAGER,...plugin.toolbox?{toolbox:plugin.toolbox}:{}}),name}var runSkillCli=runAliSkillsCli;function validateProvider(value){if(value!=="codex"&&value!=="qoder")throw new Error("Skill provider must be codex or qoder");return value}function validateScope(value){if(value!=="project"&&value!=="global")throw new Error("Skill scope must be project or global");return value}function validateArgument(value,label){if(typeof value!="string"||!value.trim()||/[\0\r\n]/.test(value))throw new Error(`${label} is invalid`);return value.trim()}function validateSkillName(value){let name=validateArgument(value,"Skill name");if(name==="."||name===".."||name.includes("/")||name.includes("\\"))throw new Error("Skill name is invalid");return name}function scopeCwd(scope,cwd){if(scope!=="global")return resolveWorkspaceDirectory(cwd)}function parseSkillUpdates(stdout,scope){let clean=stripAnsi(stdout),updates=[],pattern=/^\s*↑\s+([^\s(]+)(?:\s+\(([^)]+)\))?/gm;for(let match of clean.matchAll(pattern))match[1]&&updates.push({name:match[1],...match[2]?{source:match[2]}:{},scope});return updates}var AgentSkillManager=class{run;constructor(options={}){this.run=options.run??runSkillCli}async install(data){let{providerId,scope,cwd}=this.mutationContext(data),source=validateArgument(data.source,"Skill source"),name=validateSkillName(data.name),args=["add",source,"--skill",name,"--agent",providerId,scope==="global"?"--global":"--project","--full-depth","--install-mode","symlink","--yes"],output2=await this.run(NPX_EXECUTABLE,[...NPX_ARGS_PREFIX,...args],cwd);return await registerInstalledSkillPlugin(installedSkillDirectory(name,scope,cwd),name),{ok:!0,output:stripAnsi(output2.stdout||output2.stderr).trim()}}async checkUpdates(data){validateProvider(data.providerId);let commands=[this.run(NPX_EXECUTABLE,[...NPX_ARGS_PREFIX,"check","--global"]).then(output2=>parseSkillUpdates(`${output2.stdout}
1678
1686
  ${output2.stderr}`,"global"))];if(data.cwd!==void 0&&data.cwd!==null&&data.cwd!==""){let cwd=resolveWorkspaceDirectory(data.cwd);commands.push(this.run(NPX_EXECUTABLE,[...NPX_ARGS_PREFIX,"check"],cwd).then(output2=>parseSkillUpdates(`${output2.stdout}
1679
- ${output2.stderr}`,"project")))}return{updates:(await Promise.all(commands)).flat()}}async update(data){let{scope,cwd}=this.mutationContext(data),name=validateSkillName(data.name),args=["update",name,...scope==="global"?["--global"]:[],"--yes"],directory=installedSkillDirectory(name,scope,cwd),registeredNames=registeredNamesForSkill(directory),output2=await this.run(NPX_EXECUTABLE,[...NPX_ARGS_PREFIX,...args],cwd);if(findPluginDirectoryEntry(directory)){let registeredName=await registerInstalledSkillPlugin(directory,name);for(let pluginName of registeredNames)pluginName!==registeredName&&findPluginRegistration(pluginName)?.managedBy===SKILL_PLUGIN_MANAGER&&unregisterPlugin(pluginName)}else for(let pluginName of registeredNames)unregisterPlugin(pluginName);return{ok:!0,output:stripAnsi(output2.stdout||output2.stderr).trim()}}async uninstall(data){let{providerId,scope,cwd}=this.mutationContext(data),name=validateSkillName(data.name),args=["remove",name,"--agent",providerId,...scope==="global"?["--global"]:[],"--yes"],directory=installedSkillDirectory(name,scope,cwd),registeredNames=registeredNamesForSkill(directory),output2=await this.run(NPX_EXECUTABLE,[...NPX_ARGS_PREFIX,...args],cwd);if(!existsSync9(directory))for(let pluginName of registeredNames)unregisterPlugin(pluginName);return{ok:!0,output:stripAnsi(output2.stdout||output2.stderr).trim()}}mutationContext(data){let providerId=validateProvider(data.providerId),scope=validateScope(data.scope),cwd=scopeCwd(scope,data.cwd);return{providerId,scope,...cwd?{cwd}:{}}}};init_browser_registry();init_dist();var INTERNAL_EXTENSION_ACTIONS=new Set(["__export_cookies","__capture_download","__control_cleanup","control_sessions_list","control_session_update","__send_request_file_start","__send_request_file_chunk","__send_request_file_abort","__send_request_with_files","browser_provider_list","browser_provider_configure","browser_manager_start","browser_manager_sync_cookies","toolbox_tools_list","toolbox_tool_open","toolbox_plugin_refresh","toolbox_plugin_uninstall","toolbox_tool_page_chunk","toolbox_tool_invoke","toolbox_tool_start","toolbox_tool_operation","toolbox_tool_operations"]);function isInternalExtensionAction(action){return typeof action=="string"&&INTERNAL_EXTENSION_ACTIONS.has(action)}function createExtensionRequestMessage(id,action,data,trustedInternal=!1,controlSource="local"){return{id,action,data,controlSource:toControlSourceWireValue(controlSource),...trustedInternal?{trustedInternal:!0}:{}}}init_version();init_dist2();import fs18 from"node:fs";import path21 from"node:path";import{fileURLToPath}from"node:url";var NATIVE_HOST_UPDATE_TIMEOUT_MS=5*6e4,UPDATE_LOCK_PATH=path21.join(DAEMON_HOME,"native-host-update.lock"),UPDATE_LOCK_POLL_MS=500,INVALID_UPDATE_LOCK_GRACE_MS=1e4,NativeHostUpdateFailure=class extends Error{constructor(updateError,message){super(message);this.updateError=updateError;this.name="NativeHostUpdateFailure"}};function wait(delayMs){return new Promise(resolve9=>setTimeout(resolve9,delayMs))}function readLockState(lockPath){try{let stat4=fs18.lstatSync(lockPath);if(!stat4.isFile()||stat4.isSymbolicLink()||stat4.size>4096)return{modifiedAt:stat4.mtimeMs,owner:null};try{let value=JSON.parse(fs18.readFileSync(lockPath,"utf8")),owner=Number.isInteger(value.pid)&&value.pid>0&&typeof value.startedAt=="number"&&Number.isFinite(value.startedAt)&&value.startedAt>0?{pid:value.pid,startedAt:value.startedAt}:null;return{modifiedAt:stat4.mtimeMs,owner}}catch{return{modifiedAt:stat4.mtimeMs,owner:null}}}catch{return null}}async function withNativeHostUpdateLock(lockPath,targetVersion,operation){fs18.mkdirSync(path21.dirname(lockPath),{recursive:!0,mode:448});let startedAt=Date.now(),owner=`${JSON.stringify({pid:process.pid,startedAt,targetVersion})}
1687
+ ${output2.stderr}`,"project")))}return{updates:(await Promise.all(commands)).flat()}}async update(data){let{scope,cwd}=this.mutationContext(data),name=validateSkillName(data.name),args=["update",name,...scope==="global"?["--global"]:[],"--yes"],directory=installedSkillDirectory(name,scope,cwd),registeredNames=registeredNamesForSkill(directory),output2=await this.run(NPX_EXECUTABLE,[...NPX_ARGS_PREFIX,...args],cwd);if(findPluginDirectoryEntry(directory)){let registeredName=await registerInstalledSkillPlugin(directory,name);for(let pluginName of registeredNames)pluginName!==registeredName&&findPluginRegistration(pluginName)?.managedBy===SKILL_PLUGIN_MANAGER&&unregisterPlugin(pluginName)}else for(let pluginName of registeredNames)unregisterPlugin(pluginName);return{ok:!0,output:stripAnsi(output2.stdout||output2.stderr).trim()}}async uninstall(data){let{providerId,scope,cwd}=this.mutationContext(data),name=validateSkillName(data.name),args=["remove",name,"--agent",providerId,...scope==="global"?["--global"]:[],"--yes"],directory=installedSkillDirectory(name,scope,cwd),registeredNames=registeredNamesForSkill(directory),output2=await this.run(NPX_EXECUTABLE,[...NPX_ARGS_PREFIX,...args],cwd);if(!existsSync9(directory))for(let pluginName of registeredNames)unregisterPlugin(pluginName);return{ok:!0,output:stripAnsi(output2.stdout||output2.stderr).trim()}}mutationContext(data){let providerId=validateProvider(data.providerId),scope=validateScope(data.scope),cwd=scopeCwd(scope,data.cwd);return{providerId,scope,...cwd?{cwd}:{}}}};init_browser_registry();init_dist();var INTERNAL_EXTENSION_ACTIONS=new Set(["__export_cookies","__capture_download","__control_cleanup","control_sessions_list","control_session_update","__send_request_file_start","__send_request_file_chunk","__send_request_file_abort","__send_request_with_files","browser_provider_list","browser_provider_configure","browser_provider_launch_form","browser_manager_start","browser_manager_sync_cookies","toolbox_tools_list","toolbox_tool_open","toolbox_plugin_refresh","toolbox_plugin_uninstall","toolbox_tool_page_chunk","toolbox_tool_invoke","toolbox_tool_start","toolbox_tool_operation","toolbox_tool_operations"]);function isInternalExtensionAction(action){return typeof action=="string"&&INTERNAL_EXTENSION_ACTIONS.has(action)}function createExtensionRequestMessage(id,action,data,trustedInternal=!1,controlSource="local"){return{id,action,data,controlSource:toControlSourceWireValue(controlSource),...trustedInternal?{trustedInternal:!0}:{}}}init_version();init_dist2();import fs18 from"node:fs";import path21 from"node:path";import{fileURLToPath}from"node:url";var NATIVE_HOST_UPDATE_TIMEOUT_MS=5*6e4,UPDATE_LOCK_PATH=path21.join(DAEMON_HOME,"native-host-update.lock"),UPDATE_LOCK_POLL_MS=500,INVALID_UPDATE_LOCK_GRACE_MS=1e4,NativeHostUpdateFailure=class extends Error{constructor(updateError,message){super(message);this.updateError=updateError;this.name="NativeHostUpdateFailure"}};function wait(delayMs){return new Promise(resolve9=>setTimeout(resolve9,delayMs))}function readLockState(lockPath){try{let stat4=fs18.lstatSync(lockPath);if(!stat4.isFile()||stat4.isSymbolicLink()||stat4.size>4096)return{modifiedAt:stat4.mtimeMs,owner:null};try{let value=JSON.parse(fs18.readFileSync(lockPath,"utf8")),owner=Number.isInteger(value.pid)&&value.pid>0&&typeof value.startedAt=="number"&&Number.isFinite(value.startedAt)&&value.startedAt>0?{pid:value.pid,startedAt:value.startedAt}:null;return{modifiedAt:stat4.mtimeMs,owner}}catch{return{modifiedAt:stat4.mtimeMs,owner:null}}}catch{return null}}async function withNativeHostUpdateLock(lockPath,targetVersion,operation){fs18.mkdirSync(path21.dirname(lockPath),{recursive:!0,mode:448});let startedAt=Date.now(),owner=`${JSON.stringify({pid:process.pid,startedAt,targetVersion})}
1680
1688
  `;for(;;)try{let handle=fs18.openSync(lockPath,"wx",384);try{fs18.writeFileSync(handle,owner,"utf8")}finally{fs18.closeSync(handle)}break}catch(error48){if(!(error48 instanceof Error)||!("code"in error48)||error48.code!=="EEXIST")throw error48;let existing=readLockState(lockPath),staleAfter=existing?.owner?NATIVE_HOST_UPDATE_TIMEOUT_MS:INVALID_UPDATE_LOCK_GRACE_MS,referenceTime=existing?.owner?.startedAt??existing?.modifiedAt,expired=referenceTime!==void 0&&Date.now()-referenceTime>staleAfter,ownerAlive=existing?.owner?isAlive(existing.owner.pid):!1;if(expired&&!ownerAlive)try{fs18.unlinkSync(lockPath);continue}catch{}if(Date.now()-startedAt>NATIVE_HOST_UPDATE_TIMEOUT_MS+1e4)throw new NativeHostUpdateFailure("lock-timeout","Another Mearl Native Host update did not finish in time");await wait(UPDATE_LOCK_POLL_MS)}try{return await operation()}finally{try{fs18.readFileSync(lockPath,"utf8")===owner&&fs18.unlinkSync(lockPath)}catch{}}}function classifyUpdateFailure(output2){return/\b(?:E404|ETARGET)\b|no matching version found|404\s+not found|package.+not found/i.test(output2)?"package-unavailable":/\b(?:EAI_AGAIN|ECONNREFUSED|ECONNRESET|ENETUNREACH|ENOTFOUND|ERR_SOCKET_TIMEOUT)\b|fetch failed|network request/i.test(output2)?"network":"setup-failed"}function nativeHostUpdateCommand(targetVersion){if(!isMearlReleaseVersion(targetVersion))throw new Error("The Native Host update target must be a valid Mearl release");let releaseLine=mearlReleaseLineForVersion(targetVersion);return{args:["--yes",`@mearl/setup@${releaseLine}`,"update","--local","--yes","--target-line",releaseLine,"--skip-skill"]}}function currentNativeHostPackageRoot(entryPath){let current=path21.dirname(entryPath);for(let depth=0;depth<12;depth+=1){try{if(JSON.parse(fs18.readFileSync(path21.join(current,"package.json"),"utf8")).name==="@mearl/native-host")return current}catch{}let parent=path21.dirname(current);if(parent===current)break;current=parent}return null}function currentPackageManagerInstallation(environment,nodePath,platform){let packageRoot=currentNativeHostPackageRoot(fileURLToPath(import.meta.url));return packageRoot?resolvePackageManagerInstallation(packageRoot,"@mearl/native-host",{env:environment,platform,processExecPath:nodePath}):null}async function installedLocalPackagesMatch(targetReleaseLine,environment,runner){let installedVersions=[];for(let executableName of["mearl-native-host","mearl"]){let executable=findExecutable(executableName,{env:environment});if(!executable)return!1;try{let result=await runner(executable,["--version"],{capture:!0,env:environment,timeoutMs:5e3}),installedVersion=result.stdout.trim();if(result.code!==0||!isMearlReleaseVersionInLine(installedVersion,targetReleaseLine))return!1;installedVersions.push(installedVersion)}catch{return!1}}return new Set(installedVersions).size===1}async function runNativeHostUpdate(targetVersion,options={}){let command=nativeHostUpdateCommand(targetVersion),targetReleaseLine=mearlReleaseLineForVersion(targetVersion),environment=options.environment??process.env,platform=options.platform??process.platform,nodePath=options.nodePath??process.execPath,currentInstallation=currentPackageManagerInstallation(environment,nodePath,platform),managerCommand=options.packageManagerCommand===void 0?currentInstallation?.command??null:options.packageManagerCommand,packageBinDirectory=options.packageBinDirectory===void 0?currentInstallation?.binDirectory??null:options.packageBinDirectory,childEnvironment=prependNodePath(environment,nodePath);managerCommand&&(childEnvironment=prependCommandPath(managerCommand,childEnvironment)),packageBinDirectory&&(childEnvironment=prependPathDirectory(packageBinDirectory,childEnvironment));let packageRunner=options.packageRunner??findExecutable("npx",{env:childEnvironment,extraDirectories:[path21.dirname(nodePath)],platform});if(!packageRunner)throw new NativeHostUpdateFailure("package-unavailable","The package runner is unavailable");let runner=options.runner??runCommand,areTargetsInstalled=options.areTargetsInstalled??((version2,env)=>installedLocalPackagesMatch(version2,env,runner));await(options.withUpdateLock??((version2,operation)=>withNativeHostUpdateLock(options.updateLockPath??UPDATE_LOCK_PATH,version2,operation)))(targetVersion,async()=>{let result;try{result=await runner(packageRunner,command.args,{capture:!0,env:childEnvironment,timeoutMs:options.timeoutMs??NATIVE_HOST_UPDATE_TIMEOUT_MS})}catch(error48){let message=error48 instanceof Error?error48.message:String(error48),classified=classifyUpdateFailure(message);throw new NativeHostUpdateFailure(/timed out/i.test(message)?"timeout":classified==="setup-failed"?"unknown":classified,"The Native Host update process did not complete")}if(result.code!==0)throw new NativeHostUpdateFailure(classifyUpdateFailure(`${result.stderr.slice(0,8192)}
1681
1689
  ${result.stdout.slice(0,8192)}`),"The Mearl setup release line did not complete successfully");if(!await areTargetsInstalled(targetReleaseLine,childEnvironment))throw new NativeHostUpdateFailure("verification-failed","The installed Native Host and client do not match the Extension release line")})}var NativeHostUpdateCoordinator=class{constructor(options){this.options=options}#automaticAttempted=!1;#operation=null;evaluate(extensionVersion2,checkForUpdates){if(checkForUpdates!==!0||this.#automaticAttempted||this.#operation)return;if(!isMearlReleaseVersion(extensionVersion2)||!isMearlReleaseVersion(this.options.hostVersion)){this.options.log("Skipped Native Host update check because a release version was invalid");return}let targetVersion=extensionVersion2;if(compareMearlReleaseLines(this.options.hostVersion,targetVersion)>=0)return;this.#automaticAttempted=!0;let operation=this.options.runUpdate(targetVersion).then(()=>this.options.requestRestart()).catch(error48=>{let category=error48 instanceof NativeHostUpdateFailure?error48.updateError:"unknown";this.options.log(`Native Host automatic update failed (${category})`)}).finally(()=>{this.#operation===operation&&(this.#operation=null)});this.#operation=operation}};init_dist2();import fs19 from"node:fs";import path22 from"node:path";import{randomUUID as randomUUID14}from"node:crypto";var EXTENSION_UPDATE_LOCK_PATH=path22.join(DAEMON_HOME,"extension-update.lock"),EXTENSION_UPDATE_LOCK_STALE_MS=10*6e4,INVALID_UPDATE_LOCK_GRACE_MS2=1e4;function readUpdateLock(lockPath){try{let stat4=fs19.lstatSync(lockPath);if(!stat4.isFile()||stat4.isSymbolicLink()||stat4.size>4096)return{modifiedAt:stat4.mtimeMs,owner:null};try{let value=JSON.parse(fs19.readFileSync(lockPath,"utf8")),owner=typeof value.id=="string"&&Number.isInteger(value.pid)&&(value.pid??0)>0&&typeof value.startedAt=="number"?value:null;return{modifiedAt:stat4.mtimeMs,owner}}catch{return{modifiedAt:stat4.mtimeMs,owner:null}}}catch{return null}}async function withExtensionUpdateLock(operation,dependencies){let lockPath=dependencies.lockPath??EXTENSION_UPDATE_LOCK_PATH,now=dependencies.now??Date.now,isProcessAlive=dependencies.isProcessAlive??isAlive;fs19.mkdirSync(path22.dirname(lockPath),{recursive:!0,mode:448});let owner={id:randomUUID14(),pid:process.pid,startedAt:now()},serializedOwner=`${JSON.stringify(owner)}
1682
- `;for(let attempt=0;attempt<2;attempt+=1)try{fs19.writeFileSync(lockPath,serializedOwner,{encoding:"utf8",flag:"wx",mode:384});break}catch(error48){if(!(error48 instanceof Error)||!("code"in error48)||error48.code!=="EEXIST")throw error48;let state=readUpdateLock(lockPath);if(!(state===null||(state.owner?now()-state.owner.startedAt>EXTENSION_UPDATE_LOCK_STALE_MS&&!isProcessAlive(state.owner.pid):now()-state.modifiedAt>INVALID_UPDATE_LOCK_GRACE_MS2))||attempt>0)throw new Error("Another extension update is already running",{cause:error48});try{fs19.unlinkSync(lockPath)}catch(unlinkError){throw new Error("Another extension update is already running",{cause:unlinkError})}}try{return await operation()}finally{try{fs19.readFileSync(lockPath,"utf8")===serializedOwner&&fs19.unlinkSync(lockPath)}catch{}}}async function updateSetupManagedExtension(request,dependencies={}){if(!isMearlReleaseVersion(request.currentVersion))throw new Error("The running extension reported an invalid version");if(!request.setupManagedPath||!path22.isAbsolute(request.setupManagedPath))throw new Error("A setup-managed extension path is required");let release=await(dependencies.fetchRelease??fetchBrowserExtensionRelease)(),changelogUrl=`https://mearl.alibaba-inc.com/changelog.html#v${release.version}`;return compareMearlReleaseVersions(release.version,request.currentVersion)<=0?{changelogUrl,updated:!1,version:request.currentVersion}:withExtensionUpdateLock(async()=>(await(dependencies.updateFiles??updateSetupManagedBrowserExtensionFiles)({release,targetDirectory:request.setupManagedPath}),{changelogUrl,updated:!0,version:release.version}),dependencies)}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){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==="--discover-cdp"){options.discoverCdp=!0;continue}if(argument==="--skip-browser-registration"){options.skipBrowserRegistration=!0;continue}if(argument==="--browser-headless"){options.browserHeadless=!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 stringOptions=[["--cdp-user-data-dir","cdpUserDataDir"],["--cdp-endpoint-file","cdpEndpointFile"],["--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{browserHeadless:options.browserHeadless??!1,browserId:options.browserId??"cdp",browserName:options.browserName??"CDP",...options.cdpEndpointFile?{cdpEndpointFile:options.cdpEndpointFile}:{},cdpPort:options.cdpPort??9222,...options.cdpUserDataDir?{cdpUserDataDir:options.cdpUserDataDir}:{},daemon:options.daemon===!0,discoverCdp:options.discoverCdp===!0,help:options.help===!0,skipBrowserRegistration:options.skipBrowserRegistration===!0,version:options.version===!0}}var OPEN_SANDBOX_PORT_PLACEHOLDER="{port}",AONE_PORT_MAPPING_URL="http://127.0.0.1:58596/api/port-mapping";function normalizeBrowserAccessUrl(value){if(typeof value!="string"||!value.trim())return null;let input2=/^[a-z][a-z\d+.-]*:\/\//i.test(value.trim())?value.trim():`https://${value.trim()}`;try{let parsed=new URL(input2);return parsed.protocol==="ws:"&&(parsed.protocol="http:"),parsed.protocol==="wss:"&&(parsed.protocol="https:"),!["http:","https:"].includes(parsed.protocol)||!parsed.hostname?null:parsed.toString()}catch{return null}}function resolveSandboxBrowserAccessCapability(env=process.env){return env.OPENSANDBOX_ID?.trim()?{kind:"sandbox-novnc",environment:"opensandbox",port:6080}:env.AONE_SANDBOX_ID?.trim()?{kind:"sandbox-novnc",environment:"aone",port:6080}:null}function resolveOpenSandboxBrowserAccessUrl(port,env=process.env){if(!env.OPENSANDBOX_ID?.trim())return null;let template=env.AONE_SANDBOX_ENDPOINT_TEMPLATE?.trim();return template?.includes(OPEN_SANDBOX_PORT_PLACEHOLDER)?normalizeBrowserAccessUrl(template.replaceAll(OPEN_SANDBOX_PORT_PLACEHOLDER,String(port))):null}async function resolveAoneBrowserAccessUrl(port,dependencies){let response=await(dependencies.fetch??globalThis.fetch)(`${AONE_PORT_MAPPING_URL}?port=${port}`,{signal:AbortSignal.timeout(5e3)});if(!response.ok)throw new Error(`AONE Sandbox port mapping failed with HTTP ${response.status}`);let payload=await response.json(),url2=payload.success?normalizeBrowserAccessUrl(payload.url):null;if(!url2)throw new Error(`AONE Sandbox did not return a browser access URL for port ${port}`);return url2}async function resolveSandboxBrowserAccess(dependencies={}){let env=dependencies.env??process.env,capability=resolveSandboxBrowserAccessCapability(env);if(!capability)throw new Error("The selected browser is not running in a supported sandbox");if(capability.environment==="opensandbox"){let url3=resolveOpenSandboxBrowserAccessUrl(capability.port,env);if(url3)return{...capability,url:url3};if(!env.AONE_SANDBOX_ID?.trim())throw new Error("OpenSandbox browser access is unavailable because AONE_SANDBOX_ENDPOINT_TEMPLATE is missing or invalid")}let url2=await resolveAoneBrowserAccessUrl(capability.port,dependencies);return{...capability,environment:"aone",url:url2}}init_dist2();import{closeSync as closeSync6,existsSync as existsSync10,mkdtempSync,mkdirSync as mkdirSync6,openSync as openSync6,readFileSync as readFileSync9,renameSync as renameSync5,rmSync as rmSync7,writeFileSync as writeFileSync5}from"node:fs";import{spawn as spawn12,spawnSync as spawnSync2}from"node:child_process";import{randomUUID as randomUUID15}from"node:crypto";import{tmpdir as tmpdir2}from"node:os";import{join as join14}from"node:path";function stoppedPersistentBrowserRecord(record2,deleteProfile){if(deleteProfile||record2.persistent!==!0)return null;let stopped={...record2,pid:0};return"hostPid"in stopped?{...stopped,hostPid:0}:stopped}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 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([join14(local,"Google","Chrome","Application","chrome.exe"),join14(programFiles,"Google","Chrome","Application","chrome.exe"),join14(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(!existsSync10(explicitPath))throw new Error(`Chrome executable not found: ${explicitPath}`);return explicitPath}let found=chromeExecutableCandidates().find(candidate=>candidate&&existsSync10(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,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),rmSync7(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}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(resolve9=>setTimeout(resolve9,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(resolve9=>setTimeout(resolve9,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(resolve9=>setTimeout(resolve9,50));isManagedProcess(pid,commandMarker)&&signalProcess(pid,"SIGKILL",commandMarker)}function profileDirectory(browserId,persistent){if(!persistent)return mkdtempSync(join14(tmpdir2(),"mearl-browser-"));let dir=join14(DAEMON_HOME,MANAGED_PROFILES_SUBDIR,hashKey(browserId));return mkdirSync6(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||rmSync7(record2.userDataDir,{recursive:!0,force:!0}))}function acquireLaunchLock(browserId){let lockDir=keyedDir(MANAGED_BROWSER_LOCKS_SUBDIR),lockFile=keyedConfigFile(MANAGED_BROWSER_LOCKS_SUBDIR,browserId);mkdirSync6(lockDir,{recursive:!0});let token=`${process.pid}:${randomUUID15()}`,tryAcquire=()=>{try{return writeFileSync5(lockFile,token,{flag:"wx"}),!0}catch(error48){if(error48.code!=="EEXIST")throw error48;return!1}};if(!tryAcquire()){let observedToken="";try{observedToken=readFileSync9(lockFile,"utf-8")}catch{}let ownerPid=Number(observedToken.split(":",1)[0]);if(Number.isInteger(ownerPid)&&!isAlive(ownerPid)){let staleFile=`${lockFile}.${process.pid}.${randomUUID15()}.stale`;try{if(readFileSync9(lockFile,"utf-8")!==observedToken)throw new Error("Launch lock owner changed");if(renameSync5(lockFile,staleFile),readFileSync9(staleFile,"utf-8")===observedToken)rmSync7(staleFile,{force:!0});else try{renameSync5(staleFile,lockFile)}catch{}}catch{}}if(!tryAcquire())throw new Error(`Managed browser launch already in progress: ${browserId}`)}return()=>{try{readFileSync9(lockFile,"utf-8")===token&&rmSync7(lockFile,{force:!0})}catch{}}}async function launchManagedBrowser(input2,deps){let name=validateName(input2.name),browserId=managedBrowserId(name),cookieCopy=resolveCookieCopyPlan(input2.copyCookieDomains),copyCookieDomains=cookieCopy.domains,headless=input2.headless!==!1,persistent=input2.persistent===!0,executablePath=resolveChromeExecutable(input2.executablePath),userAgent=resolveUserAgentMode(input2.userAgentMode)==="desktop"?desktopChromeUserAgent(resolveChromeVersion(executablePath)):void 0,userDataDir=profileDirectory(browserId,persistent),logDir=keyedDir(MANAGED_BROWSERS_SUBDIR);mkdirSync6(logDir,{recursive:!0});let logPath=join14(logDir,`${hashKey(browserId)}.log`),logFd=openSync6(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 exportedCookies=copyCookieDomains.length>0?await deps.exportCookies(copyCookieDomains):[],cookies=cookieCopy.select(exportedCookies),chromeArgs=buildManagedChromeArgs({userDataDir,headless,userAgent});rmSync7(join14(userDataDir,"DevToolsActivePort"),{force:!0});let chrome=spawn12(executablePath,chromeArgs,{detached:!0,stdio:["ignore","ignore",logFd],windowsHide:headless});if(await new Promise((resolve9,reject)=>{chrome.once("error",reject),chrome.once("spawn",resolve9)}),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);input2.url&&await(await session.getBrowserClient()).sendCommand("Target.createTarget",{url:input2.url,background:headless}),session.close(),session=null;let host=spawn12(process.execPath,[deps.nativeHostScript,"--daemon","--cdp-port",String(cdpPort),"--cdp-user-data-dir",userDataDir,"--browser-id",browserId,"--browser-name",name,...headless?["--browser-headless"]:[]],{detached:!0,stdio:"ignore",windowsHide:!0});if(await new Promise((resolve9,reject)=>{host.once("error",reject),host.once("spawn",resolve9)}),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(),...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||rmSync7(userDataDir,{recursive:!0,force:!0}),error48}finally{releaseLock?.(),closeSync6(logFd)}}async function closeManagedBrowser(selector,options={}){let record2=findManagedRecord(selector);if(!record2)throw new Error(`Managed browser not found: ${selector}`);let recordFile=keyedConfigFile(MANAGED_BROWSERS_SUBDIR,record2.browserId);await stopProcess(record2.pid,record2.userDataDir);let closingOwnHost=record2.hostPid===process.pid;closingOwnHost||await stopProcess(record2.hostPid,`--browser-id ${record2.browserId}`),removeRecord(keyedConfigFile("browsers",record2.browserId));let deleteProfile=options.deleteProfile===!0||!record2.persistent,stoppedRecord=stoppedPersistentBrowserRecord(record2,deleteProfile);return stoppedRecord?writeRecord(recordFile,stoppedRecord):(removeRecord(recordFile),rmSync7(record2.userDataDir,{recursive:!0,force:!0})),closingOwnHost&&setTimeout(()=>process.kill(process.pid,"SIGTERM"),250).unref(),{browserId:record2.browserId,closed:!0,profileDeleted:deleteProfile}}init_browser_registry();init_version();var commonLaunchProperties={name:{type:"string",minLength:1},persistent:{type:"boolean",default:!0},copyCookieDomains:{type:"object",component:"cookie-sync",properties:{presets:{type:"array",items:{type:"string",enum:["mearl-services"]}},domains:{type:"array",items:{type:"string",minLength:1}}}}};function connectedBrowserIds(){return new Set(listRegisteredBrowsers().filter(browser=>browser.status===void 0||browser.status==="connected").map(browser=>browser.browserId))}function commonDetails(browser){return{headless:browser.headless,createdAt:browser.createdAt,...browser.copiedCookies?{copiedCookies:{domains:browser.copiedCookies.domains,count:browser.copiedCookies.count}}:{}}}function localBrowser(browser,connected){let stopped=!browser.running;return{browserId:browser.browserId,name:browser.name,status:stopped?"stopped":connected.has(browser.browserId)?"connected":"running_disconnected",control:stopped?{kind:"none"}:{kind:"host",transport:"cdp",browserId:browser.browserId},ownership:"owned",persistence:browser.persistent?"persistent":"ephemeral",operations:stopped?["start","deleteData"]:["close","deleteData"],references:[{kind:"profile",id:browser.browserId,label:"Profile"}],details:{...commonDetails(browser),cdpPort:browser.cdpPort}}}function localDefinition(deps){return{descriptor:{providerId:"local",name:"Local Chrome",version:NATIVE_HOST_VERSION,protocolVersion:2,builtin:!0},browserType:{name:"本地浏览器",inputSchema:{type:"object",required:["name"],additionalProperties:!0,properties:{...commonLaunchProperties,headless:{type:"boolean",default:!0}}}},listBrowsers:()=>{let connected=connectedBrowserIds();return listManagedBrowsers().map(browser=>localBrowser(browser,connected))},launch:async options=>{let summary=await launchManagedBrowser(options,{nativeHostScript:deps.nativeHostScript,exportCookies:deps.exportCookies,log:deps.log});return localBrowser(summary,connectedBrowserIds())},start:async({browserId})=>{let summary=listManagedBrowsers().find(browser=>browser.browserId===browserId);if(!summary)throw new Error(`Local browser not found: ${browserId}`);let launched=await launchManagedBrowser({name:summary.name,persistent:summary.persistent,headless:summary.headless},{nativeHostScript:deps.nativeHostScript,exportCookies:deps.exportCookies,log:deps.log});return localBrowser(launched,connectedBrowserIds())},close:({browserId,deleteData})=>closeManagedBrowser(browserId,{deleteProfile:deleteData})}}function createBuiltinBrowserProviders(deps){return[createProviderRuntime(localDefinition(deps))]}var BrowserProviderCoordinator=class{constructor(runtimes,hostServices){this.runtimes=runtimes;this.hostServices=hostServices}async hostContext(options){if(!this.hostServices)return;let result={};if(options.copyCookieDomains!==void 0){let plan=resolveCookieCopyPlan(options.copyCookieDomains);result.cookies=plan.select(await this.hostServices.exportCookies(plan.domains))}return options.userAgentMode==="desktop"&&(result.userAgent=await this.hostServices.getBrowserUserAgent()),Object.keys(result).length>0?result:void 0}definitions(){return{providers:[...this.runtimes.map(runtime=>{let descriptor=runtime.definition.descriptor;return{provider:providerIdentity(descriptor),browserType:runtime.definition.browserType}}),...listExternalBrowserProviders()]}}get providerRuntimes(){return this.runtimes}async launch(input2){let providerId=input2.provider?.trim()||"local",runtime=this.runtimes.find(item=>item.definition.descriptor.providerId===providerId),builtinOptions={...input2};if(delete builtinOptions.provider,delete builtinOptions.providerOptions,input2.providerOptions&&Object.keys(builtinOptions).length>0)throw new Error("Use either providerOptions or flat launch options, not both");if(runtime){let descriptor=runtime.definition.descriptor,options={...input2.providerOptions??builtinOptions};return Array.isArray(options.copyCookieDomains)&&(options.copyCookieDomains={domains:options.copyCookieDomains}),options.copyCookieDomains==="mearl-services"&&(options.copyCookieDomains={presets:["mearl-services"]}),providerBrowserInfo({provider:providerIdentity(descriptor),browser:await runtime.launch(options)})}let external=listExternalBrowserProviders().find(provider=>provider.provider.id===providerId);if(!external)throw new Error(`Provider is not registered: ${providerId}`);if(Object.keys(builtinOptions).length>0)throw new Error("External Provider launch options must be supplied in providerOptions");let host=await this.hostContext(input2.providerOptions??{});return providerBrowserInfo({provider:external.provider,browser:await launchProviderBrowser({provider:providerId,providerOptions:input2.providerOptions??{},...host?{host}:{}})})}async close(selector,deleteProfile=!1){let match=await this.requireOne(selector);return"external"in match?closeProviderBrowser(match.external,{deleteProfile}):match.runtime.close({browserId:match.browser.browserId,deleteData:deleteProfile})}async start(selector){let match=await this.requireOne(selector);if("external"in match){if(!match.external.provider)throw new Error("Provider identity is missing");return providerBrowserInfo({provider:match.external.provider,browser:await startProviderBrowser(match.external)})}let descriptor=match.runtime.definition.descriptor;return providerBrowserInfo({provider:providerIdentity(descriptor),browser:await match.runtime.start({browserId:match.browser.browserId})})}async syncCookies(selector,scope){let match=await this.requireOne(selector);if("external"in match){let host=await this.hostContext({copyCookieDomains:scope});return host?syncProviderBrowserCookies(match.external,scope,host):syncProviderBrowserCookies(match.external,scope)}return match.runtime.syncCookies({browserId:match.browser.browserId,scope})}async access(selector){let match=await this.requireOne(selector);return{browserAccess:"runtime"in match?await match.runtime.getAccess({browserId:match.browser.browserId}):await accessProviderBrowser(match.external)}}async detach(selector){let match=await this.requireOne(selector);return"runtime"in match?match.runtime.detach({browserId:match.browser.browserId}):detachProviderBrowser(match.external)}async configure(providerId,options){let runtime=this.runtimes.find(item=>item.definition.descriptor.providerId===providerId);return runtime?runtime.configure(options):configureProvider(providerId,options)}async findRuntimeBrowsers(selector){let normalized=selector.trim().toLowerCase();return(await Promise.all(this.runtimes.map(async runtime=>(await runtime.listBrowsers()).map(browser=>({runtime,browser}))))).flat().filter(entry=>entry.browser.browserId.toLowerCase()===normalized||entry.browser.name.toLowerCase()===normalized)}async requireOne(selector){let matches=await this.findRuntimeBrowsers(selector),external=findProviderBrowser(selector);if(matches.length+ +!!external>1)throw new Error(`Browser name is ambiguous: ${selector}. Use the full browserId from browser_list.`);if(matches[0])return matches[0];if(external)return{external};throw new Error(`Provider browser not found: ${selector}`)}};process.env.MEARL_NATIVE_HOST_ENTRY??=fileURLToPath3(import.meta.url);var cliArgs=process.argv.slice(2),cliArg=cliArgs[0];if(cliArg==="--provider-control"){let{runProviderControlHost:runProviderControlHost2}=await Promise.resolve().then(()=>(init_provider_control_host(),provider_control_host_exports));await runProviderControlHost2(cliArgs[1]??""),process.exit(0)}if(cliArg==="--init"||cliArg==="--uninstall"||cliArg==="init"||cliArg==="uninstall"){let{runCli:runCli2}=await Promise.resolve().then(()=>(init_install(),install_exports));process.exit(await runCli2(cliArgs))}function printCliHelp(){console.error(`mearl-native-host v${NATIVE_HOST_VERSION}
1690
+ `;for(let attempt=0;attempt<2;attempt+=1)try{fs19.writeFileSync(lockPath,serializedOwner,{encoding:"utf8",flag:"wx",mode:384});break}catch(error48){if(!(error48 instanceof Error)||!("code"in error48)||error48.code!=="EEXIST")throw error48;let state=readUpdateLock(lockPath);if(!(state===null||(state.owner?now()-state.owner.startedAt>EXTENSION_UPDATE_LOCK_STALE_MS&&!isProcessAlive(state.owner.pid):now()-state.modifiedAt>INVALID_UPDATE_LOCK_GRACE_MS2))||attempt>0)throw new Error("Another extension update is already running",{cause:error48});try{fs19.unlinkSync(lockPath)}catch(unlinkError){throw new Error("Another extension update is already running",{cause:unlinkError})}}try{return await operation()}finally{try{fs19.readFileSync(lockPath,"utf8")===serializedOwner&&fs19.unlinkSync(lockPath)}catch{}}}async function updateSetupManagedExtension(request,dependencies={}){if(!isMearlReleaseVersion(request.currentVersion))throw new Error("The running extension reported an invalid version");if(!request.setupManagedPath||!path22.isAbsolute(request.setupManagedPath))throw new Error("A setup-managed extension path is required");let release=await(dependencies.fetchRelease??fetchBrowserExtensionRelease)(),changelogUrl=`https://mearl.alibaba-inc.com/changelog.html#v${release.version}`;return compareMearlReleaseVersions(release.version,request.currentVersion)<=0?{changelogUrl,updated:!1,version:request.currentVersion}:withExtensionUpdateLock(async()=>(await(dependencies.updateFiles??updateSetupManagedBrowserExtensionFiles)({release,targetDirectory:request.setupManagedPath}),{changelogUrl,updated:!0,version:release.version}),dependencies)}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){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==="--discover-cdp"){options.discoverCdp=!0;continue}if(argument==="--skip-browser-registration"){options.skipBrowserRegistration=!0;continue}if(argument==="--browser-headless"){options.browserHeadless=!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 stringOptions=[["--cdp-user-data-dir","cdpUserDataDir"],["--cdp-endpoint-file","cdpEndpointFile"],["--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{browserHeadless:options.browserHeadless??!1,browserId:options.browserId??"cdp",browserName:options.browserName??"CDP",...options.cdpEndpointFile?{cdpEndpointFile:options.cdpEndpointFile}:{},cdpPort:options.cdpPort??9222,...options.cdpUserDataDir?{cdpUserDataDir:options.cdpUserDataDir}:{},daemon:options.daemon===!0,discoverCdp:options.discoverCdp===!0,help:options.help===!0,skipBrowserRegistration:options.skipBrowserRegistration===!0,version:options.version===!0}}var OPEN_SANDBOX_PORT_PLACEHOLDER="{port}",AONE_PORT_MAPPING_URL="http://127.0.0.1:58596/api/port-mapping";function normalizeBrowserAccessUrl(value){if(typeof value!="string"||!value.trim())return null;let input2=/^[a-z][a-z\d+.-]*:\/\//i.test(value.trim())?value.trim():`https://${value.trim()}`;try{let parsed=new URL(input2);return parsed.protocol==="ws:"&&(parsed.protocol="http:"),parsed.protocol==="wss:"&&(parsed.protocol="https:"),!["http:","https:"].includes(parsed.protocol)||!parsed.hostname?null:parsed.toString()}catch{return null}}function resolveSandboxBrowserAccessCapability(env=process.env){return env.OPENSANDBOX_ID?.trim()?{kind:"sandbox-novnc",environment:"opensandbox",port:6080}:env.AONE_SANDBOX_ID?.trim()?{kind:"sandbox-novnc",environment:"aone",port:6080}:null}function resolveOpenSandboxBrowserAccessUrl(port,env=process.env){if(!env.OPENSANDBOX_ID?.trim())return null;let template=env.AONE_SANDBOX_ENDPOINT_TEMPLATE?.trim();return template?.includes(OPEN_SANDBOX_PORT_PLACEHOLDER)?normalizeBrowserAccessUrl(template.replaceAll(OPEN_SANDBOX_PORT_PLACEHOLDER,String(port))):null}async function resolveAoneBrowserAccessUrl(port,dependencies){let response=await(dependencies.fetch??globalThis.fetch)(`${AONE_PORT_MAPPING_URL}?port=${port}`,{signal:AbortSignal.timeout(5e3)});if(!response.ok)throw new Error(`AONE Sandbox port mapping failed with HTTP ${response.status}`);let payload=await response.json(),url2=payload.success?normalizeBrowserAccessUrl(payload.url):null;if(!url2)throw new Error(`AONE Sandbox did not return a browser access URL for port ${port}`);return url2}async function resolveSandboxBrowserAccess(dependencies={}){let env=dependencies.env??process.env,capability=resolveSandboxBrowserAccessCapability(env);if(!capability)throw new Error("The selected browser is not running in a supported sandbox");if(capability.environment==="opensandbox"){let url3=resolveOpenSandboxBrowserAccessUrl(capability.port,env);if(url3)return{...capability,url:url3};if(!env.AONE_SANDBOX_ID?.trim())throw new Error("OpenSandbox browser access is unavailable because AONE_SANDBOX_ENDPOINT_TEMPLATE is missing or invalid")}let url2=await resolveAoneBrowserAccessUrl(capability.port,dependencies);return{...capability,environment:"aone",url:url2}}init_dist2();import{closeSync as closeSync6,existsSync as existsSync10,mkdtempSync,mkdirSync as mkdirSync6,openSync as openSync6,readFileSync as readFileSync9,renameSync as renameSync5,rmSync as rmSync7,writeFileSync as writeFileSync5}from"node:fs";import{spawn as spawn12,spawnSync as spawnSync2}from"node:child_process";import{randomUUID as randomUUID15}from"node:crypto";import{tmpdir as tmpdir2}from"node:os";import{join as join14}from"node:path";function stoppedPersistentBrowserRecord(record2,deleteProfile){if(deleteProfile||record2.persistent!==!0)return null;let stopped={...record2,pid:0};return"hostPid"in stopped?{...stopped,hostPid:0}:stopped}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 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([join14(local,"Google","Chrome","Application","chrome.exe"),join14(programFiles,"Google","Chrome","Application","chrome.exe"),join14(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(!existsSync10(explicitPath))throw new Error(`Chrome executable not found: ${explicitPath}`);return explicitPath}let found=chromeExecutableCandidates().find(candidate=>candidate&&existsSync10(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,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),rmSync7(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}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(resolve9=>setTimeout(resolve9,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(resolve9=>setTimeout(resolve9,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(resolve9=>setTimeout(resolve9,50));isManagedProcess(pid,commandMarker)&&signalProcess(pid,"SIGKILL",commandMarker)}function profileDirectory(browserId,persistent){if(!persistent)return mkdtempSync(join14(tmpdir2(),"mearl-browser-"));let dir=join14(DAEMON_HOME,MANAGED_PROFILES_SUBDIR,hashKey(browserId));return mkdirSync6(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||rmSync7(record2.userDataDir,{recursive:!0,force:!0}))}function acquireLaunchLock(browserId){let lockDir=keyedDir(MANAGED_BROWSER_LOCKS_SUBDIR),lockFile=keyedConfigFile(MANAGED_BROWSER_LOCKS_SUBDIR,browserId);mkdirSync6(lockDir,{recursive:!0});let token=`${process.pid}:${randomUUID15()}`,tryAcquire=()=>{try{return writeFileSync5(lockFile,token,{flag:"wx"}),!0}catch(error48){if(error48.code!=="EEXIST")throw error48;return!1}};if(!tryAcquire()){let observedToken="";try{observedToken=readFileSync9(lockFile,"utf-8")}catch{}let ownerPid=Number(observedToken.split(":",1)[0]);if(Number.isInteger(ownerPid)&&!isAlive(ownerPid)){let staleFile=`${lockFile}.${process.pid}.${randomUUID15()}.stale`;try{if(readFileSync9(lockFile,"utf-8")!==observedToken)throw new Error("Launch lock owner changed");if(renameSync5(lockFile,staleFile),readFileSync9(staleFile,"utf-8")===observedToken)rmSync7(staleFile,{force:!0});else try{renameSync5(staleFile,lockFile)}catch{}}catch{}}if(!tryAcquire())throw new Error(`Managed browser launch already in progress: ${browserId}`)}return()=>{try{readFileSync9(lockFile,"utf-8")===token&&rmSync7(lockFile,{force:!0})}catch{}}}async function launchManagedBrowser(input2,deps){let name=validateName(input2.name),browserId=managedBrowserId(name),cookieCopy=resolveCookieCopyPlan(input2.copyCookieDomains),copyCookieDomains=cookieCopy.domains,headless=input2.headless!==!1,persistent=input2.persistent===!0,executablePath=resolveChromeExecutable(input2.executablePath),userAgent=resolveUserAgentMode(input2.userAgentMode)==="desktop"?desktopChromeUserAgent(resolveChromeVersion(executablePath)):void 0,userDataDir=profileDirectory(browserId,persistent),logDir=keyedDir(MANAGED_BROWSERS_SUBDIR);mkdirSync6(logDir,{recursive:!0});let logPath=join14(logDir,`${hashKey(browserId)}.log`),logFd=openSync6(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 exportedCookies=copyCookieDomains.length>0?await deps.exportCookies(copyCookieDomains):[],cookies=cookieCopy.select(exportedCookies),chromeArgs=buildManagedChromeArgs({userDataDir,headless,userAgent});rmSync7(join14(userDataDir,"DevToolsActivePort"),{force:!0});let chrome=spawn12(executablePath,chromeArgs,{detached:!0,stdio:["ignore","ignore",logFd],windowsHide:headless});if(await new Promise((resolve9,reject)=>{chrome.once("error",reject),chrome.once("spawn",resolve9)}),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);input2.url&&await(await session.getBrowserClient()).sendCommand("Target.createTarget",{url:input2.url,background:headless}),session.close(),session=null;let host=spawn12(process.execPath,[deps.nativeHostScript,"--daemon","--cdp-port",String(cdpPort),"--cdp-user-data-dir",userDataDir,"--browser-id",browserId,"--browser-name",name,...headless?["--browser-headless"]:[]],{detached:!0,stdio:"ignore",windowsHide:!0});if(await new Promise((resolve9,reject)=>{host.once("error",reject),host.once("spawn",resolve9)}),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(),...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||rmSync7(userDataDir,{recursive:!0,force:!0}),error48}finally{releaseLock?.(),closeSync6(logFd)}}async function closeManagedBrowser(selector,options={}){let record2=findManagedRecord(selector);if(!record2)throw new Error(`Managed browser not found: ${selector}`);let recordFile=keyedConfigFile(MANAGED_BROWSERS_SUBDIR,record2.browserId);await stopProcess(record2.pid,record2.userDataDir);let closingOwnHost=record2.hostPid===process.pid;closingOwnHost||await stopProcess(record2.hostPid,`--browser-id ${record2.browserId}`),removeRecord(keyedConfigFile("browsers",record2.browserId));let deleteProfile=options.deleteProfile===!0||!record2.persistent,stoppedRecord=stoppedPersistentBrowserRecord(record2,deleteProfile);return stoppedRecord?writeRecord(recordFile,stoppedRecord):(removeRecord(recordFile),rmSync7(record2.userDataDir,{recursive:!0,force:!0})),closingOwnHost&&setTimeout(()=>process.kill(process.pid,"SIGTERM"),250).unref(),{browserId:record2.browserId,closed:!0,profileDeleted:deleteProfile}}init_browser_registry();init_version();var commonLaunchProperties={name:{type:"string",minLength:1},persistent:{type:"boolean",default:!0},copyCookieDomains:{type:"object",component:"cookie-sync",properties:{presets:{type:"array",items:{type:"string",enum:["mearl-services"]}},domains:{type:"array",items:{type:"string",minLength:1}}}}};function connectedBrowserIds(){return new Set(listRegisteredBrowsers().filter(browser=>browser.status===void 0||browser.status==="connected").map(browser=>browser.browserId))}function commonDetails(browser){return{headless:browser.headless,createdAt:browser.createdAt,...browser.copiedCookies?{copiedCookies:{domains:browser.copiedCookies.domains,count:browser.copiedCookies.count}}:{}}}function localBrowser(browser,connected){let stopped=!browser.running;return{browserId:browser.browserId,name:browser.name,status:stopped?"stopped":connected.has(browser.browserId)?"connected":"running_disconnected",control:stopped?{kind:"none"}:{kind:"host",transport:"cdp",browserId:browser.browserId},ownership:"owned",persistence:browser.persistent?"persistent":"ephemeral",operations:stopped?["start","deleteData"]:["close","deleteData"],references:[{kind:"profile",id:browser.browserId,label:"Profile"}],details:{...commonDetails(browser),cdpPort:browser.cdpPort}}}function localDefinition(deps){return{descriptor:{providerId:"local",name:"Local Chrome",version:NATIVE_HOST_VERSION,protocolVersion:2,builtin:!0},browserType:{name:"本地浏览器",inputSchema:{type:"object",required:["name"],additionalProperties:!0,properties:{...commonLaunchProperties,headless:{type:"boolean",default:!0}}}},listBrowsers:()=>{let connected=connectedBrowserIds();return listManagedBrowsers().map(browser=>localBrowser(browser,connected))},launch:async options=>{let summary=await launchManagedBrowser(options,{nativeHostScript:deps.nativeHostScript,exportCookies:deps.exportCookies,log:deps.log});return localBrowser(summary,connectedBrowserIds())},start:async({browserId})=>{let summary=listManagedBrowsers().find(browser=>browser.browserId===browserId);if(!summary)throw new Error(`Local browser not found: ${browserId}`);let launched=await launchManagedBrowser({name:summary.name,persistent:summary.persistent,headless:summary.headless},{nativeHostScript:deps.nativeHostScript,exportCookies:deps.exportCookies,log:deps.log});return localBrowser(launched,connectedBrowserIds())},close:({browserId,deleteData})=>closeManagedBrowser(browserId,{deleteProfile:deleteData})}}function createBuiltinBrowserProviders(deps){return[createProviderRuntime(localDefinition(deps))]}var BrowserProviderCoordinator=class{constructor(runtimes,hostServices){this.runtimes=runtimes;this.hostServices=hostServices}async hostContext(options){if(!this.hostServices)return;let result={};if(options.copyCookieDomains!==void 0){let plan=resolveCookieCopyPlan(options.copyCookieDomains);result.cookies=plan.select(await this.hostServices.exportCookies(plan.domains))}return options.userAgentMode==="desktop"&&(result.userAgent=await this.hostServices.getBrowserUserAgent()),Object.keys(result).length>0?result:void 0}definitions(){return{providers:[...this.runtimes.map(runtime=>{let descriptor=runtime.definition.descriptor;return{provider:providerIdentity(descriptor),browserType:runtime.definition.browserType}}),...listExternalBrowserProviders()]}}get providerRuntimes(){return this.runtimes}async launch(input2){let providerId=input2.provider?.trim()||"local",runtime=this.runtimes.find(item=>item.definition.descriptor.providerId===providerId),builtinOptions={...input2};if(delete builtinOptions.provider,delete builtinOptions.providerOptions,input2.providerOptions&&Object.keys(builtinOptions).length>0)throw new Error("Use either providerOptions or flat launch options, not both");if(runtime){let descriptor=runtime.definition.descriptor,options={...input2.providerOptions??builtinOptions};return Array.isArray(options.copyCookieDomains)&&(options.copyCookieDomains={domains:options.copyCookieDomains}),options.copyCookieDomains==="mearl-services"&&(options.copyCookieDomains={presets:["mearl-services"]}),providerBrowserInfo({provider:providerIdentity(descriptor),browser:await runtime.launch(options)})}let external=listExternalBrowserProviders().find(provider=>provider.provider.id===providerId);if(!external)throw new Error(`Provider is not registered: ${providerId}`);if(Object.keys(builtinOptions).length>0)throw new Error("External Provider launch options must be supplied in providerOptions");let host=await this.hostContext(input2.providerOptions??{});return providerBrowserInfo({provider:external.provider,browser:await launchProviderBrowser({provider:providerId,providerOptions:input2.providerOptions??{},...host?{host}:{}})})}async close(selector,deleteProfile=!1){let match=await this.requireOne(selector);return"external"in match?closeProviderBrowser(match.external,{deleteProfile}):match.runtime.close({browserId:match.browser.browserId,deleteData:deleteProfile})}async start(selector){let match=await this.requireOne(selector);if("external"in match){if(!match.external.provider)throw new Error("Provider identity is missing");return providerBrowserInfo({provider:match.external.provider,browser:await startProviderBrowser(match.external)})}let descriptor=match.runtime.definition.descriptor;return providerBrowserInfo({provider:providerIdentity(descriptor),browser:await match.runtime.start({browserId:match.browser.browserId})})}async syncCookies(selector,scope){let match=await this.requireOne(selector);if("external"in match){let host=await this.hostContext({copyCookieDomains:scope});return host?syncProviderBrowserCookies(match.external,scope,host):syncProviderBrowserCookies(match.external,scope)}return match.runtime.syncCookies({browserId:match.browser.browserId,scope})}async access(selector){let match=await this.requireOne(selector);return{browserAccess:"runtime"in match?await match.runtime.getAccess({browserId:match.browser.browserId}):await accessProviderBrowser(match.external)}}async detach(selector){let match=await this.requireOne(selector);return"runtime"in match?match.runtime.detach({browserId:match.browser.browserId}):detachProviderBrowser(match.external)}async configure(providerId,options){let runtime=this.runtimes.find(item=>item.definition.descriptor.providerId===providerId);return runtime?runtime.configure(options):configureProvider(providerId,options)}async getLaunchForm(providerId,request){let runtime=this.runtimes.find(item=>item.definition.descriptor.providerId===providerId);return runtime?runtime.getLaunchForm(request):getProviderLaunchForm(providerId,request)}async findRuntimeBrowsers(selector){let normalized=selector.trim().toLowerCase();return(await Promise.all(this.runtimes.map(async runtime=>(await runtime.listBrowsers()).map(browser=>({runtime,browser}))))).flat().filter(entry=>entry.browser.browserId.toLowerCase()===normalized||entry.browser.name.toLowerCase()===normalized)}async requireOne(selector){let matches=await this.findRuntimeBrowsers(selector),external=findProviderBrowser(selector);if(matches.length+ +!!external>1)throw new Error(`Browser name is ambiguous: ${selector}. Use the full browserId from browser_list.`);if(matches[0])return matches[0];if(external)return{external};throw new Error(`Provider browser not found: ${selector}`)}};process.env.MEARL_NATIVE_HOST_ENTRY??=fileURLToPath3(import.meta.url);var cliArgs=process.argv.slice(2),cliArg=cliArgs[0];if(cliArg==="--provider-control"){let{runProviderControlHost:runProviderControlHost2}=await Promise.resolve().then(()=>(init_provider_control_host(),provider_control_host_exports));await runProviderControlHost2(cliArgs[1]??""),process.exit(0)}if(cliArg==="--init"||cliArg==="--uninstall"||cliArg==="init"||cliArg==="uninstall"){let{runCli:runCli2}=await Promise.resolve().then(()=>(init_install(),install_exports));process.exit(await runCli2(cliArgs))}function printCliHelp(){console.error(`mearl-native-host v${NATIVE_HOST_VERSION}
1683
1691
 
1684
1692
  Usage:
1685
1693
  mearl-native-host [runtime-options]
@@ -1726,7 +1734,7 @@ Examples:
1726
1734
  mearl-native-host --version`)}!cliArg&&process.stdin.isTTY&&(printCliHelp(),process.exit(0));var runtimeArgs={browserId:"cdp",browserHeadless:!1,browserName:"CDP",cdpPort:9222,daemon:!1,discoverCdp:!1,help:!1,skipBrowserRegistration:!1,version:!1};if(cliArgs.length>0)try{runtimeArgs=await parseNativeHostRuntimeArgs(cliArgs)}catch(error48){console.error(`Error: ${error48 instanceof Error?error48.message:String(error48)}`),printCliHelp(),process.exit(2)}runtimeArgs.version&&(console.log(NATIVE_HOST_VERSION),process.exit(0));runtimeArgs.help&&(printCliHelp(),process.exit(0));var isDaemonMode=runtimeArgs.daemon,discoverCdp=runtimeArgs.discoverCdp,skipBrowserRegistration=runtimeArgs.skipBrowserRegistration,CDP_ENDPOINT_FILE=runtimeArgs.cdpEndpointFile,CDP_PORT=runtimeArgs.cdpPort,CDP_USER_DATA_DIR=runtimeArgs.cdpUserDataDir,BROWSER_HEADLESS=runtimeArgs.browserHeadless,CDP_BROWSER_ID=runtimeArgs.browserId,CDP_BROWSER_NAME=runtimeArgs.browserName,CDP_ENDPOINT_SOURCE=cliArgs.some(argument=>["--cdp-port","--cdp-user-data-dir","--cdp-endpoint-file"].some(option=>argument===option||argument.startsWith(`${option}=`)))?"command-line":"built-in default";function describeCdpEndpoint(){return CDP_ENDPOINT_FILE?`endpoint-file (source=${CDP_ENDPOINT_SOURCE})`:`127.0.0.1:${CDP_PORT} (source=${CDP_ENDPOINT_SOURCE})`}function oneLineError(value){return value.replace(/[\r\n]+/g," ").trim().slice(0,500)}function socketPathFor(suffix){return process.platform==="win32"?`\\\\.\\pipe\\mearl-agent${suffix}`:path24.join(os12.tmpdir(),`mearl-agent${suffix}.sock`)}function canConnectInstanceSocket(socketPath){return new Promise(resolve9=>{let socket=net5.createConnection(socketPath),settled=!1,timer=setTimeout(()=>finish(!0),300);timer.unref();let finish=reachable=>{settled||(settled=!0,clearTimeout(timer),socket.destroy(),resolve9(reachable))};socket.once("connect",()=>finish(!0)),socket.once("error",error48=>finish(error48.code!=="ENOENT"&&error48.code!=="ECONNREFUSED"))})}var LEGACY_SOCKET_PATH=socketPathFor(""),INSTANCE_SOCKET_PATH=socketPathFor(`-${process.pid}`),LOG_FILE=path24.join(os12.tmpdir(),"mearl-native-host.log"),DEFAULT_TIMEOUT_MS=15e3,INVENTORY_IDLE_EXIT_MS=1e3,DISCOVERY_REQUEST_IDLE_EXIT_MS=5e3,MAX_SOCKET_BUFFER_SIZE2=64*1024*1024,extensionVersion=null,versionWarningEmitted=!1,cdpPermissionNoticeLogged=!1,EXTENSION_INSTALL_URL="https://chromewebstore.google.com/detail/mearl/aoehhjnofngknnjefamjbplchbolghkm";function majorMinor(version2){let parts=version2.split(".");return parts.length>=2?`${parts[0]}.${parts[1]}`:version2}function extractChromeVersion(input2){let match=/Chrome\/([\d.]+)/.exec(input2);return match?match[1].split(".").slice(0,3).join("."):null}async function fetchCdpBrowserVersion(){if(CDP_ENDPOINT_FILE)try{return(await(await getCdpSession().getBrowserClient()).sendCommand("Browser.getVersion",{},5e3)).product??null}catch{return null}let port=readDevToolsActivePort(CDP_USER_DATA_DIR)?.port??CDP_PORT;return new Promise(resolve9=>{let req=http4.get(`http://localhost:${port}/json/version`,res=>{let data="";res.on("data",chunk=>data+=chunk),res.on("end",()=>{try{let info=JSON.parse(data);resolve9(info.Browser??null)}catch{resolve9(null)}})});req.on("error",()=>resolve9(null)),req.setTimeout(2e3,()=>{req.destroy(),resolve9(null)})})}async function getCurrentBrowserUserAgent(){if(extensionVersion!==null)try{let result=await sendRequestToExtension("get_browser_info",{},3e3,!0);if(result.userAgent?.trim())return result.userAgent}catch{}try{let result=await(await getCdpSession().getBrowserClient()).sendCommand("Browser.getVersion",{},5e3);if(result.userAgent?.trim())return result.userAgent}catch{}throw new Error("Could not determine the control browser user agent for userAgentMode=desktop")}function currentBrowserSupportsSandboxAccess(){return!BROWSER_HEADLESS}function resolveBrowserAccessCapability(){return currentBrowserSupportsSandboxAccess()?resolveSandboxBrowserAccessCapability():null}async function resolveBrowserAccess(){if(!resolveBrowserAccessCapability())throw new Error("The selected browser does not expose a browser access URL");return resolveSandboxBrowserAccess()}async function collectVersions(includeInstallationInfo=!1){let browserAccess=resolveBrowserAccessCapability(),info={nativeHost:NATIVE_HOST_VERSION,extension:extensionVersion,browser:null,...browserAccess?{browserAccess}:{}};if(extensionVersion!==null)try{let browserInfo=await sendRequestToExtension("get_browser_info",{},3e3,!0);browserInfo?.userAgent&&(info.browser=extractChromeVersion(browserInfo.userAgent)),browserInfo?.extensionVersion&&(info.extension=browserInfo.extensionVersion),includeInstallationInfo&&(browserInfo?.extensionId&&(info.extensionId=browserInfo.extensionId),(typeof browserInfo?.setupManagedPath=="string"||browserInfo?.setupManagedPath===null)&&(info.setupManagedPath=browserInfo.setupManagedPath))}catch{}if(!info.browser){let cdpBrowser=await fetchCdpBrowserVersion();cdpBrowser&&(info.browser=extractChromeVersion(cdpBrowser))}return info}function buildVersionWarning(clientVersion){let versions=[clientVersion?{name:"client",version:clientVersion}:null,{name:"native-host",version:NATIVE_HOST_VERSION},extensionVersion?{name:"extension",version:extensionVersion}:null].filter(Boolean);return new Set(versions.map(v=>majorMinor(v.version))).size<=1?null:["⚠️ Mearl version mismatch detected:",versions.map(v=>` - ${v.name}: ${v.version}`).join(`
1727
1735
  `),"","This may cause unexpected behavior. To update:"," npx @mearl/setup update --local",` Browser extension: ${EXTENSION_INSTALL_URL}`].join(`
1728
1736
  `)}var pendingRequests=new Map,nativeMessageBuffer=Buffer.alloc(0),socketServer=null,legacyServer=null,inventoryExitTimer=null,cdpRegistrationTimer=null,cdpBrowserPublished=!1;function cancelInventoryExit(){inventoryExitTimer&&(clearTimeout(inventoryExitTimer),inventoryExitTimer=null)}function scheduleInventoryExit(delayMs=INVENTORY_IDLE_EXIT_MS){cancelInventoryExit(),inventoryExitTimer=setTimeout(()=>cleanupAndExit(0),delayMs),inventoryExitTimer.unref()}var cdpSession=null,cdpAutoReconnectEnabled=!0;function getCdpSession(){return cdpAutoReconnectEnabled=!0,cdpSession||(cdpSession=CDP_ENDPOINT_FILE?new CdpSession({endpointResolver:async()=>{let endpoint=fs21.readFileSync(CDP_ENDPOINT_FILE,"utf8").trim(),url2=new URL(endpoint);if(url2.protocol!=="ws:"&&url2.protocol!=="wss:")throw new Error(`Unsupported CDP WebSocket protocol: ${url2.protocol}`);return url2.toString()}}):new CdpSession({port:CDP_PORT,userDataDir:CDP_USER_DATA_DIR})),cdpSession}var controlBrowserId=isDaemonMode?CDP_BROWSER_ID:"default",controlSessionManager;function getControlSessionManager(){return controlSessionManager??=new ControlSessionManager({browserId:()=>controlBrowserId,transport:()=>extensionVersion!==null?"extension":"cdp",invoke:async(action,data,transport)=>{let{__mearlControlSource:origin,...payload}=data;return(await dispatchHostRequest({action,data:payload,controlSource:origin??"local",transport},!0)).data},cleanup:async(tabs,transport,preserveEnvironment)=>{if(transport==="extension"){let result=await sendRequestToExtension("__control_cleanup",{tabIds:tabs,preserveEnvironment},3e4,!0);if(result.released===!1)throw new Error("Session cleanup failed: "+JSON.stringify(result.failures))}else for(let tabId of tabs){if(!cdpSession?.listRegisteredTabIds().includes(tabId))continue;let page=await cdpSession.getPageSession(tabId);clearPageRefsForNavigation(page),await releaseControlledIndicator(page),preserveEnvironment||(clearCdpPageMocks(page),await dispatchCdpAction(getCdpSession(),"set_app_profile",{tabId,enabled:!1,mtopEnv:"default"},"local"),await dispatchCdpAction(getCdpSession(),"set_device_emulation",{tabId,enabled:!1},"local"),await dispatchCdpAction(getCdpSession(),"set_timezone",{tabId,timezone:""},"local"))}},download:async(data,transport,origin)=>transport==="extension"?sendRequestToExtension("__capture_download",data,Number(data.timeout??3e4)+1e4,!0,normalizeControlSource(origin)):captureCdpDownload(getCdpSession(),data,CDP_BROWSER_ID.startsWith("managed:"),()=>handleViaCdp("page_click",{...data.trigger,tabId:data.tabId},3e4,normalizeControlSource(origin))),notify:()=>{extensionVersion!==null&&sendToExtension({type:"control_sessions_changed"})}})}function log(...args){let msg=`[${new Date().toISOString()}] [NativeHost] ${args.join(" ")}
1729
- `;try{fs21.appendFileSync(LOG_FILE,msg)}catch{}}function sendToExtension(message){let json2=JSON.stringify(message),length=Buffer.byteLength(json2,"utf-8"),header=Buffer.alloc(4);header.writeUInt32LE(length,0),process.stdout.write(header),process.stdout.write(json2)}var nativeHostUpdateCoordinator=new NativeHostUpdateCoordinator({hostVersion:NATIVE_HOST_VERSION,log,runUpdate:targetVersion=>runNativeHostUpdate(targetVersion),requestRestart:()=>{restartAfterUpdate()}}),agentChatManager=null,agentSkillManager=new AgentSkillManager;function getAgentChatManager(){return agentChatManager||(agentChatManager=new AgentChatManager([new CodexAgentProvider(log,NATIVE_HOST_VERSION,INSTANCE_SOCKET_PATH),new QoderAgentProvider(log,NATIVE_HOST_VERSION)],event=>{sendToExtension({type:"agent_chat_event",data:event})})),agentChatManager}var agentServiceHandlers={agent_chat_pick_directory:async()=>({path:await pickWorkspaceDirectory()}),agent_chat_status:()=>getAgentChatManager().getStatus(),agent_chat_prepare:async data=>(await getAgentChatManager().prepare(data),{ok:!0}),agent_chat_list_sessions:data=>getAgentChatManager().listSessions(data),agent_chat_start:data=>getAgentChatManager().startSession(data),agent_chat_send:data=>getAgentChatManager().sendMessage(data),agent_chat_run:data=>getAgentChatManager().runTask(data),agent_chat_interrupt:async data=>(await getAgentChatManager().interrupt(data),{ok:!0}),agent_chat_close:async data=>(await getAgentChatManager().closeSession(data),{ok:!0}),agent_chat_events:data=>getAgentChatManager().getEvents(data),agent_chat_refresh:data=>getAgentChatManager().refreshSession(data),agent_chat_open_app:async data=>(await getAgentChatManager().openSession(data),{ok:!0}),agent_chat_open_workspace:async data=>(await getAgentChatManager().openWorkspace(data),{ok:!0}),agent_chat_respond:data=>(getAgentChatManager().respondToRequest(data),{ok:!0}),agent_skills_installed:async data=>({skills:await getAgentChatManager().listSkills(data)}),agent_skills_read:data=>getAgentChatManager().readSkill(data),agent_skills_install:data=>agentSkillManager.install(data),agent_skills_check_updates:data=>agentSkillManager.checkUpdates(data),agent_skills_update:data=>agentSkillManager.update(data),agent_skills_uninstall:data=>agentSkillManager.uninstall(data)};function dispatchAgentServiceAction(action,request){let handler=agentServiceHandlers[action];return Promise.resolve(handler(request))}var browserProviderCoordinator=null;function getBrowserProviderCoordinator(){if(browserProviderCoordinator)return browserProviderCoordinator;let runtimes=createBuiltinBrowserProviders({nativeHostScript:fileURLToPath3(import.meta.url),exportCookies:async domains=>extensionVersion!==null?(await sendRequestToExtension("__export_cookies",{domains},2e4,!0)).cookies??[]:cdpExportCookies(getCdpSession(),domains),log});return browserProviderCoordinator=new BrowserProviderCoordinator(runtimes,{exportCookies:async domains=>extensionVersion!==null?(await sendRequestToExtension("__export_cookies",{domains},2e4,!0)).cookies??[]:cdpExportCookies(getCdpSession(),domains),getBrowserUserAgent:getCurrentBrowserUserAgent}),browserProviderCoordinator}async function launchBrowser(data){return getBrowserProviderCoordinator().launch(data)}async function closeBrowser(data){let selector=String(data?.browser??data?.browserId??data?.name??"").trim();if(!selector)throw new Error("browser is required");return getBrowserProviderCoordinator().close(selector,data?.deleteProfile===!0)}async function getManagedBrowserAccess(data){let selector=String(data?.browser??data?.browserId??"").trim();if(!selector)throw new Error("browser is required");return(await getBrowserProviderCoordinator().access(selector)).browserAccess}function appendWarnings(result,warnings){let merged=[...new Set([...result.warnings??[],...warnings])];return{...result,...merged.length>0?{warnings:merged}:{}}}async function handleExtensionControlMessage(message){let{id,action,data={}}=message;if(action==="control_sessions_list"){sendToExtension({id,success:!0,data:{sessions:[...getControlSessionManager().registry.list(),...await listProviderControlSessions()]}});return}if(action==="control_session_update"){if(!["handoff","resume","release"].includes(data.operation))throw new Error("Invalid control operation");let session;try{getControlSessionManager().registry.info(data.sessionId),session=await getControlSessionManager().userControl(data.sessionId,data.operation)}catch(error48){if(!(error48 instanceof Error)||!error48.message.startsWith("CONTROL_SESSION_NOT_FOUND"))throw error48;session=await updateProviderControlSession(data.sessionId,data.operation)}sendToExtension({id,success:!0,data:{session}});return}if(action==="alipay_auth_code_start"){let pairing=await startAlipayAuthCode(data.params,phase=>{try{sendToExtension({id,type:"progress",data:{phase}})}catch{}});sendToExtension({id,success:!0,data:pairing});return}if(action==="alipay_auth_code_wait"){let browserId=String(data.browserId??"");try{let response=await waitAlipayAuthCode(browserId,data.params,phase=>{try{sendToExtension({id,type:"progress",data:{phase}})}catch{}});sendToExtension({id,success:!0,data:response})}finally{await closeAlipayAuthCode(browserId).catch(()=>{})}return}if(action==="alipay_auth_code_close"){await closeAlipayAuthCode(String(data.browserId??"")),sendToExtension({id,success:!0,data:{}});return}if(isAgentServiceAction(action)){let result=await dispatchAgentServiceAction(action,data);sendToExtension({id,success:!0,data:result});return}if(isToolboxServiceAction(action)){let context={invoke:(pluginAction,payload={})=>pluginAction==="agent_chat_run"?getAgentChatManager().runTask(payload):sendRequestToExtension(pluginAction,payload,toTimeoutMs(pluginAction,payload),!1,"local")},result=action==="toolbox_tools_list"?await listToolboxPluginTools():action==="toolbox_plugin_refresh"?await refreshToolboxPlugin(data?.id):action==="toolbox_plugin_uninstall"?await uninstallToolboxPlugin(data?.id):action==="toolbox_tool_open"?await openToolboxPluginTool(data?.id,context):action==="toolbox_tool_page_chunk"?readToolboxPluginPageChunk(data?.id,data?.hash,data?.index):action==="toolbox_tool_start"?startToolboxPluginTool(data?.id,data?.command,data?.input,context):action==="toolbox_tool_operation"?getToolboxPluginOperation(data?.id,data?.operationId):action==="toolbox_tool_operations"?listToolboxPluginOperations(data?.id):await invokeToolboxPluginTool(data?.id,data?.command,data?.input,context);sendToExtension({id,success:!0,data:result});return}if(action==="browser_list"){let providerWarnings=await ensureInstalledProvidersRunning(),inventory=await listBrowserInventory(getBrowserProviderCoordinator().providerRuntimes);sendToExtension({id,success:!0,data:appendWarnings(inventory,providerWarnings)});return}if(action==="browser_provider_list"){sendToExtension({id,success:!0,data:getBrowserProviderCoordinator().definitions()});return}if(action==="browser_launch"){let result=await launchBrowser(data);sendToExtension({id,success:!0,data:result});return}if(action==="browser_close"){let result=await closeBrowser(data);sendToExtension({id,success:!0,data:result});return}if(action==="browser_manager_release"){let selector=String(data?.browser??data?.browserId??"").trim();if(!selector)throw new Error("browser is required");let result=await getBrowserProviderCoordinator().detach(selector);sendToExtension({id,success:!0,data:result});return}if(action==="browser_manager_start"||action==="browser_manager_sync_cookies"){let selector=String(data?.browser??"").trim();if(!selector)throw new Error("browser is required");let coordinator=getBrowserProviderCoordinator(),result=action==="browser_manager_start"?await coordinator.start(selector):await coordinator.syncCookies(selector,data?.scope);sendToExtension({id,success:!0,data:result});return}if(action==="get_browser_access_url"){let browserAccess=await getManagedBrowserAccess(data);sendToExtension({id,success:!0,data:{browserAccess}});return}if(action==="browser_provider_configure"){if(typeof data?.provider!="string"||!data.provider.trim())throw new Error("provider is required");let result=await getBrowserProviderCoordinator().configure(data.provider,data.options);sendToExtension({id,success:!0,data:result});return}if(action==="start_cloud_connector"){let serverUrl=data?.serverUrl;if(!serverUrl||typeof serverUrl!="string"){sendToExtension({id,success:!1,error:"serverUrl is required"});return}let result=await startCloudConnector(serverUrl);sendToExtension({id,success:result.success,data:result,error:result.error});return}if(action==="stop_cloud_connector"){let serverUrl=data?.serverUrl;if(!serverUrl||typeof serverUrl!="string"){sendToExtension({id,success:!1,error:"serverUrl is required"});return}let result=stopCloudConnector(serverUrl);sendToExtension({id,success:result.success,data:result,error:result.error});return}if(action==="list_cloud_connectors"){sendToExtension({id,success:!0,data:listCloudConnectors()});return}if(action==="update_setup_extension"){let result=await updateSetupManagedExtension({currentVersion:data?.currentVersion,setupManagedPath:data?.setupManagedPath});sendToExtension({id,success:!0,data:result});return}sendToExtension({id,success:!1,error:`Unknown extension action: ${action}`})}function handleExtensionMessage(message){if(message&&message.type==="ping"){message.version&&(extensionVersion=message.version,log(`Extension version: ${extensionVersion}, Native Host version: ${NATIVE_HOST_VERSION}`)),setAnalyticsClientId(message.analyticsClientId),controlBrowserId=typeof message.browserId=="string"?message.browserId:"default",registerBrowser({browserId:typeof message.browserId=="string"?message.browserId:"default",socketPath:INSTANCE_SOCKET_PATH,browserName:typeof message.browserName=="string"?message.browserName:"Browser",nativeHostVersion:NATIVE_HOST_VERSION,transport:"extension",extensionVersion:extensionVersion??void 0}),sendToExtension({type:"pong",timestamp:Date.now(),version:NATIVE_HOST_VERSION}),nativeHostUpdateCoordinator.evaluate(message.version,message.checkForUpdates);return}if(message&&message.type==="browser_focus"){touchFocus();return}if(!message||typeof message!="object"||!message.id)return;let pending=pendingRequests.get(message.id);if(!pending){message.action&&handleExtensionControlMessage(message).catch(error48=>{sendToExtension({id:message.id,success:!1,error:error48 instanceof Error?error48.message:String(error48)})});return}clearTimeout(pending.timer),pendingRequests.delete(message.id),message.success?pending.resolve(message.data):pending.reject(new Error(message.error||"Unknown error from extension"))}function processNativeMessages(){for(;nativeMessageBuffer.length>=4;){let length=nativeMessageBuffer.readUInt32LE(0);if(nativeMessageBuffer.length<4+length)return;let jsonBytes=nativeMessageBuffer.subarray(4,4+length);nativeMessageBuffer=nativeMessageBuffer.subarray(4+length);try{let message=JSON.parse(jsonBytes.toString("utf-8"));handleExtensionMessage(message)}catch(error48){log("Failed to parse extension message:",String(error48))}}}function setupNativeMessageInput(){process.stdin.on("readable",()=>{let chunk;for(;(chunk=process.stdin.read())!==null;)nativeMessageBuffer=Buffer.concat([nativeMessageBuffer,chunk]),processNativeMessages()}),process.stdin.on("end",()=>{log("Extension disconnected (stdin end)"),cleanupAndExit(0)}),process.stdin.on("error",error48=>{log("stdin error:",String(error48)),cleanupAndExit(1)})}function sendRequestToExtension(action,data,timeoutMs,trustedInternal=!1,controlSource="local"){let id=`${Date.now()}_${Math.random().toString(36).slice(2,10)}`;return new Promise((resolve9,reject)=>{let timer=setTimeout(()=>{pendingRequests.delete(id),reject(new Error(`Request timeout after ${timeoutMs}ms`))},timeoutMs);pendingRequests.set(id,{resolve:resolve9,reject,timer}),sendToExtension(createExtensionRequestMessage(id,action,data,trustedInternal,controlSource))})}function toTimeoutMs(action,data){if(action==="send_request"||action==="__send_request_with_files")return Number(data&&data.timeout?data.timeout:3e4)+5e3;if(action==="send_mtop_request")return Number(data&&data.timeout?data.timeout:1e4)+5e3;if(action==="page_wait")return Number(data?.time??data?.timeout??1e4)+5e3;if(action==="tab_open")return 4e4;if(action==="run_actions"){let timeoutMs=(Array.isArray(data?.actions)?data.actions:[{}]).reduce((total,step)=>{let stepAction=String(step?.action??"");return!stepAction||stepAction==="run_actions"?total+DEFAULT_TIMEOUT_MS:total+toTimeoutMs(stepAction,step?.data??{})},0);return Math.max(DEFAULT_TIMEOUT_MS,timeoutMs)}if(shouldObservePageAction(action,data)){let observationMs=Math.min(Math.max(Number(data?.observe?.timeoutMs??3e3),500),3e4),navigationGraceMs=Math.min(Math.max(Number(data?.observe?.navigationGraceMs??1e3),0),5e3),navigationTimeoutMs=Math.min(Math.max(Number(data?.observe?.navigationTimeoutMs??15e3),1e3),3e4);return Math.max(DEFAULT_TIMEOUT_MS,observationMs+navigationGraceMs+4e3+navigationTimeoutMs+5e3)}return DEFAULT_TIMEOUT_MS}async function dispatchHostRequest(request,managed=!1){let{action,data={}}=request,controlSource=normalizeControlSource(request.controlSource);if(action==="provider_control_sessions_changed")return sendToExtension({type:"control_sessions_changed"}),{data:{refreshed:!0}};if(!managed&&(isBrowserCommandAction(action)||typeof action=="string"&&action.startsWith("__artifact_")))return{data:await getControlSessionManager().invoke(action,data,request.controlSessionId,request.transport,controlSource)};if(action==="start_cloud_connector"){if(!data.serverUrl||typeof data.serverUrl!="string")throw new Error("serverUrl is required");let result=await startCloudConnector(data.serverUrl);if(!result.success)throw new Error(result.error??"Cloud connector failed to start");return{data:result}}if(action==="stop_cloud_connector"){if(!data.serverUrl||typeof data.serverUrl!="string")throw new Error("serverUrl is required");let result=stopCloudConnector(data.serverUrl);if(!result.success)throw new Error(result.error??"Cloud connector failed to stop");return{data:result}}if(action==="list_cloud_connectors")return{data:listCloudConnectors()};if(action==="get_versions")return{data:await collectVersions(controlSource==="local")};if(action==="get_browser_access_url")return{data:{browserAccess:data.browser?await getManagedBrowserAccess(data):await resolveBrowserAccess()}};if(isInternalExtensionAction(action))throw new Error("Internal action is not available to clients");if(action==="agent_chat_run")return{data:await getAgentChatManager().runTask(data)};if(action==="browser_list"){discoverCdp&&cancelInventoryExit();let providerWarnings=await ensureInstalledProvidersRunning(),shouldDiscover=isDaemonMode&&!skipBrowserRegistration;discoverCdp&&CDP_BROWSER_ID==="cdp"&&await retireUnreachableBrowserRecord(CDP_BROWSER_ID,canConnectInstanceSocket);let discoveryProbeError,discovered=shouldDiscover?await ensureDiscoverableCdpBrowser({isPublished:()=>cdpBrowserPublished,isAvailable:async()=>{let probe=await getCdpSession().probeAvailability();return discoveryProbeError=probe.error?oneLineError(probe.error):void 0,log(`CDP discovery probe ${describeCdpEndpoint()} -> ${probe.available?"ok":`fail (${discoveryProbeError||"unknown error"})`}`),probe.available},publish:publishDaemonBrowser,monitor:monitorConnectedDaemonBrowser}):!1,inventory=await listBrowserInventory(getBrowserProviderCoordinator().providerRuntimes),registeredCdpAvailable=inventory.browsers.some(browser=>browser.browserId===CDP_BROWSER_ID&&browser.transport==="cdp"&&browser.status==="connected"),discoveryWarnings=shouldDiscover&&!discovered&&!registeredCdpAvailable?[`CDP discovery probe ${describeCdpEndpoint()} failed: ${discoveryProbeError||"unknown error"}`]:[],inventoryData=appendWarnings(inventory,[...providerWarnings,...discoveryWarnings]),closeConnection=skipBrowserRegistration||discoverCdp&&!discovered;return closeConnection&&scheduleInventoryExit(),{data:inventoryData,closeConnection}}if(action==="browser_close")return{data:await closeBrowser(data)};if(action==="browser_launch")return{data:await launchBrowser(data)};if(action==="browser_release"){let startedAt2=Date.now(),affectedTabIds=new Set,transports=[],failures=[],released=!0,hadActiveControl=!1;try{let releaseErrors=[];if(extensionVersion!==null)try{let result=await sendRequestToExtension(action,data,toTimeoutMs(action,data));released=released&&result?.released!==!1,hadActiveControl=hadActiveControl||result?.hadActiveControl===!0,result?.hadActiveControl&&transports.push("extension");for(let tabId of result?.affectedTabIds??[])affectedTabIds.add(tabId);Array.isArray(result?.failures)&&failures.push(...result.failures)}catch(error48){releaseErrors.push(`extension: ${error48 instanceof Error?error48.message:String(error48)}`)}if(cdpSession){let session=cdpSession;cdpSession=null;try{let result=await releaseCdpControl(session);released=released&&result.released,hadActiveControl=hadActiveControl||result.hadActiveControl,result.hadActiveControl&&transports.push("cdp");for(let tabId of result.affectedTabIds)affectedTabIds.add(tabId)}catch(error48){session.close(),releaseErrors.push(`cdp: ${error48 instanceof Error?error48.message:String(error48)}`)}}if(cdpAutoReconnectEnabled=!1,releaseErrors.length>0)throw new Error(`Failed to fully release browser control (${releaseErrors.join("; ")})`);return trackAction(action,{success:released,transport:transports.join("+")||"none",duration_ms:Date.now()-startedAt2,extension_version:extensionVersion??"not_connected"}),{data:{released,hadActiveControl,transports,affectedTabIds:[...affectedTabIds].sort((a,b)=>a-b),...failures.length?{failures}:{}}}}catch(error48){throw trackAction(action,{success:!1,transport:transports.join("+")||(extensionVersion!==null?"extension":"cdp"),duration_ms:Date.now()-startedAt2,error_code:classifyAnalyticsError(error48),extension_version:extensionVersion??"not_connected"}),error48}}if(!isExtensionBrowserAction(action)&&(typeof action!="string"||!action.startsWith("__")))throw new Error(`Unsupported action: ${String(action)}`);if(request.transport==="extension"&&extensionVersion===null)throw new Error("CONTROL_SESSION_TRANSPORT_UNAVAILABLE: extension is disconnected");let useExtension=request.transport!=="cdp"&&extensionVersion!==null,transport=useExtension?"extension":"cdp",startedAt=Date.now();try{validateRequiredActionTabId(action,data);let result;return useExtension?action==="send_request"&&hasSendRequestFiles(data)?result=await sendRequestWithTransferredFiles(data,(internalAction,payload,timeoutMs)=>sendRequestToExtension(internalAction,payload,timeoutMs,!0,controlSource)):action==="run_actions"&&hasRunActionsSendRequestFiles(data)?result=await sendRunActionsWithTransferredFiles(data,(internalAction,payload,timeoutMs)=>sendRequestToExtension(internalAction,payload,timeoutMs,!0,controlSource),transformed=>toTimeoutMs("run_actions",transformed)):result=await sendRequestToExtension(action,data,toTimeoutMs(action,data),!1,controlSource):(cdpPermissionNoticeLogged||(cdpPermissionNoticeLogged=!0,log("CDP mode: domain permission checks are not enforced — all actions run without domain authorization")),result=await handleViaCdp(action,data,toTimeoutMs(action,data),controlSource)),trackAction(action,{success:!0,transport,duration_ms:Date.now()-startedAt,extension_version:extensionVersion??"not_connected"}),{data:result}}catch(error48){throw trackAction(action,{success:!1,transport,duration_ms:Date.now()-startedAt,error_code:classifyAnalyticsError(error48),extension_version:extensionVersion??"not_connected"}),error48}}async function handleSocketRequest(socket,line){let request;try{request=JSON.parse(line)}catch{socket.write(JSON.stringify({id:"",success:!1,error:`Invalid JSON request: ${line}`})+`
1737
+ `;try{fs21.appendFileSync(LOG_FILE,msg)}catch{}}function sendToExtension(message){let json2=JSON.stringify(message),length=Buffer.byteLength(json2,"utf-8"),header=Buffer.alloc(4);header.writeUInt32LE(length,0),process.stdout.write(header),process.stdout.write(json2)}var nativeHostUpdateCoordinator=new NativeHostUpdateCoordinator({hostVersion:NATIVE_HOST_VERSION,log,runUpdate:targetVersion=>runNativeHostUpdate(targetVersion),requestRestart:()=>{restartAfterUpdate()}}),agentChatManager=null,agentSkillManager=new AgentSkillManager;function getAgentChatManager(){return agentChatManager||(agentChatManager=new AgentChatManager([new CodexAgentProvider(log,NATIVE_HOST_VERSION,INSTANCE_SOCKET_PATH),new QoderAgentProvider(log,NATIVE_HOST_VERSION)],event=>{sendToExtension({type:"agent_chat_event",data:event})})),agentChatManager}var agentServiceHandlers={agent_chat_pick_directory:async()=>({path:await pickWorkspaceDirectory()}),agent_chat_status:()=>getAgentChatManager().getStatus(),agent_chat_prepare:async data=>(await getAgentChatManager().prepare(data),{ok:!0}),agent_chat_list_sessions:data=>getAgentChatManager().listSessions(data),agent_chat_start:data=>getAgentChatManager().startSession(data),agent_chat_send:data=>getAgentChatManager().sendMessage(data),agent_chat_run:data=>getAgentChatManager().runTask(data),agent_chat_interrupt:async data=>(await getAgentChatManager().interrupt(data),{ok:!0}),agent_chat_close:async data=>(await getAgentChatManager().closeSession(data),{ok:!0}),agent_chat_events:data=>getAgentChatManager().getEvents(data),agent_chat_refresh:data=>getAgentChatManager().refreshSession(data),agent_chat_open_app:async data=>(await getAgentChatManager().openSession(data),{ok:!0}),agent_chat_open_workspace:async data=>(await getAgentChatManager().openWorkspace(data),{ok:!0}),agent_chat_respond:data=>(getAgentChatManager().respondToRequest(data),{ok:!0}),agent_skills_installed:async data=>({skills:await getAgentChatManager().listSkills(data)}),agent_skills_read:data=>getAgentChatManager().readSkill(data),agent_skills_install:data=>agentSkillManager.install(data),agent_skills_check_updates:data=>agentSkillManager.checkUpdates(data),agent_skills_update:data=>agentSkillManager.update(data),agent_skills_uninstall:data=>agentSkillManager.uninstall(data)};function dispatchAgentServiceAction(action,request){let handler=agentServiceHandlers[action];return Promise.resolve(handler(request))}var browserProviderCoordinator=null;function getBrowserProviderCoordinator(){if(browserProviderCoordinator)return browserProviderCoordinator;let runtimes=createBuiltinBrowserProviders({nativeHostScript:fileURLToPath3(import.meta.url),exportCookies:async domains=>extensionVersion!==null?(await sendRequestToExtension("__export_cookies",{domains},2e4,!0)).cookies??[]:cdpExportCookies(getCdpSession(),domains),log});return browserProviderCoordinator=new BrowserProviderCoordinator(runtimes,{exportCookies:async domains=>extensionVersion!==null?(await sendRequestToExtension("__export_cookies",{domains},2e4,!0)).cookies??[]:cdpExportCookies(getCdpSession(),domains),getBrowserUserAgent:getCurrentBrowserUserAgent}),browserProviderCoordinator}async function launchBrowser(data){return getBrowserProviderCoordinator().launch(data)}async function closeBrowser(data){let selector=String(data?.browser??data?.browserId??data?.name??"").trim();if(!selector)throw new Error("browser is required");return getBrowserProviderCoordinator().close(selector,data?.deleteProfile===!0)}async function getManagedBrowserAccess(data){let selector=String(data?.browser??data?.browserId??"").trim();if(!selector)throw new Error("browser is required");return(await getBrowserProviderCoordinator().access(selector)).browserAccess}function appendWarnings(result,warnings){let merged=[...new Set([...result.warnings??[],...warnings])];return{...result,...merged.length>0?{warnings:merged}:{}}}async function handleExtensionControlMessage(message){let{id,action,data={}}=message;if(action==="control_sessions_list"){sendToExtension({id,success:!0,data:{sessions:[...getControlSessionManager().registry.list(),...await listProviderControlSessions()]}});return}if(action==="control_session_update"){if(!["handoff","resume","release"].includes(data.operation))throw new Error("Invalid control operation");let session;try{getControlSessionManager().registry.info(data.sessionId),session=await getControlSessionManager().userControl(data.sessionId,data.operation)}catch(error48){if(!(error48 instanceof Error)||!error48.message.startsWith("CONTROL_SESSION_NOT_FOUND"))throw error48;session=await updateProviderControlSession(data.sessionId,data.operation)}sendToExtension({id,success:!0,data:{session}});return}if(action==="alipay_auth_code_start"){let pairing=await startAlipayAuthCode(data.params,phase=>{try{sendToExtension({id,type:"progress",data:{phase}})}catch{}});sendToExtension({id,success:!0,data:pairing});return}if(action==="alipay_auth_code_wait"){let browserId=String(data.browserId??"");try{let response=await waitAlipayAuthCode(browserId,data.params,phase=>{try{sendToExtension({id,type:"progress",data:{phase}})}catch{}});sendToExtension({id,success:!0,data:response})}finally{await closeAlipayAuthCode(browserId).catch(()=>{})}return}if(action==="alipay_auth_code_close"){await closeAlipayAuthCode(String(data.browserId??"")),sendToExtension({id,success:!0,data:{}});return}if(isAgentServiceAction(action)){let result=await dispatchAgentServiceAction(action,data);sendToExtension({id,success:!0,data:result});return}if(isToolboxServiceAction(action)){let context={invoke:(pluginAction,payload={})=>pluginAction==="agent_chat_run"?getAgentChatManager().runTask(payload):sendRequestToExtension(pluginAction,payload,toTimeoutMs(pluginAction,payload),!1,"local")},result=action==="toolbox_tools_list"?await listToolboxPluginTools():action==="toolbox_plugin_refresh"?await refreshToolboxPlugin(data?.id):action==="toolbox_plugin_uninstall"?await uninstallToolboxPlugin(data?.id):action==="toolbox_tool_open"?await openToolboxPluginTool(data?.id,context):action==="toolbox_tool_page_chunk"?readToolboxPluginPageChunk(data?.id,data?.hash,data?.index):action==="toolbox_tool_start"?startToolboxPluginTool(data?.id,data?.command,data?.input,context):action==="toolbox_tool_operation"?getToolboxPluginOperation(data?.id,data?.operationId):action==="toolbox_tool_operations"?listToolboxPluginOperations(data?.id):await invokeToolboxPluginTool(data?.id,data?.command,data?.input,context);sendToExtension({id,success:!0,data:result});return}if(action==="browser_list"){let providerWarnings=await ensureInstalledProvidersRunning(),inventory=await listBrowserInventory(getBrowserProviderCoordinator().providerRuntimes);sendToExtension({id,success:!0,data:appendWarnings(inventory,providerWarnings)});return}if(action==="browser_provider_list"){sendToExtension({id,success:!0,data:getBrowserProviderCoordinator().definitions()});return}if(action==="browser_provider_launch_form"){if(typeof data?.provider!="string"||!data.provider.trim())throw new Error("provider is required");let result=await getBrowserProviderCoordinator().getLaunchForm(data.provider,{variant:data.variant,values:data.values??{}});sendToExtension({id,success:!0,data:result});return}if(action==="browser_launch"){let result=await launchBrowser(data);sendToExtension({id,success:!0,data:result});return}if(action==="browser_close"){let result=await closeBrowser(data);sendToExtension({id,success:!0,data:result});return}if(action==="browser_manager_release"){let selector=String(data?.browser??data?.browserId??"").trim();if(!selector)throw new Error("browser is required");let result=await getBrowserProviderCoordinator().detach(selector);sendToExtension({id,success:!0,data:result});return}if(action==="browser_manager_start"||action==="browser_manager_sync_cookies"){let selector=String(data?.browser??"").trim();if(!selector)throw new Error("browser is required");let coordinator=getBrowserProviderCoordinator(),result=action==="browser_manager_start"?await coordinator.start(selector):await coordinator.syncCookies(selector,data?.scope);sendToExtension({id,success:!0,data:result});return}if(action==="get_browser_access_url"){let browserAccess=await getManagedBrowserAccess(data);sendToExtension({id,success:!0,data:{browserAccess}});return}if(action==="browser_provider_configure"){if(typeof data?.provider!="string"||!data.provider.trim())throw new Error("provider is required");let result=await getBrowserProviderCoordinator().configure(data.provider,data.options);sendToExtension({id,success:!0,data:result});return}if(action==="start_cloud_connector"){let serverUrl=data?.serverUrl;if(!serverUrl||typeof serverUrl!="string"){sendToExtension({id,success:!1,error:"serverUrl is required"});return}let result=await startCloudConnector(serverUrl);sendToExtension({id,success:result.success,data:result,error:result.error});return}if(action==="stop_cloud_connector"){let serverUrl=data?.serverUrl;if(!serverUrl||typeof serverUrl!="string"){sendToExtension({id,success:!1,error:"serverUrl is required"});return}let result=stopCloudConnector(serverUrl);sendToExtension({id,success:result.success,data:result,error:result.error});return}if(action==="list_cloud_connectors"){sendToExtension({id,success:!0,data:listCloudConnectors()});return}if(action==="update_setup_extension"){let result=await updateSetupManagedExtension({currentVersion:data?.currentVersion,setupManagedPath:data?.setupManagedPath});sendToExtension({id,success:!0,data:result});return}sendToExtension({id,success:!1,error:`Unknown extension action: ${action}`})}function handleExtensionMessage(message){if(message&&message.type==="ping"){message.version&&(extensionVersion=message.version,log(`Extension version: ${extensionVersion}, Native Host version: ${NATIVE_HOST_VERSION}`)),setAnalyticsClientId(message.analyticsClientId),controlBrowserId=typeof message.browserId=="string"?message.browserId:"default",registerBrowser({browserId:typeof message.browserId=="string"?message.browserId:"default",socketPath:INSTANCE_SOCKET_PATH,browserName:typeof message.browserName=="string"?message.browserName:"Browser",nativeHostVersion:NATIVE_HOST_VERSION,transport:"extension",extensionVersion:extensionVersion??void 0}),sendToExtension({type:"pong",timestamp:Date.now(),version:NATIVE_HOST_VERSION}),nativeHostUpdateCoordinator.evaluate(message.version,message.checkForUpdates);return}if(message&&message.type==="browser_focus"){touchFocus();return}if(!message||typeof message!="object"||!message.id)return;let pending=pendingRequests.get(message.id);if(!pending){message.action&&handleExtensionControlMessage(message).catch(error48=>{sendToExtension({id:message.id,success:!1,error:error48 instanceof Error?error48.message:String(error48)})});return}clearTimeout(pending.timer),pendingRequests.delete(message.id),message.success?pending.resolve(message.data):pending.reject(new Error(message.error||"Unknown error from extension"))}function processNativeMessages(){for(;nativeMessageBuffer.length>=4;){let length=nativeMessageBuffer.readUInt32LE(0);if(nativeMessageBuffer.length<4+length)return;let jsonBytes=nativeMessageBuffer.subarray(4,4+length);nativeMessageBuffer=nativeMessageBuffer.subarray(4+length);try{let message=JSON.parse(jsonBytes.toString("utf-8"));handleExtensionMessage(message)}catch(error48){log("Failed to parse extension message:",String(error48))}}}function setupNativeMessageInput(){process.stdin.on("readable",()=>{let chunk;for(;(chunk=process.stdin.read())!==null;)nativeMessageBuffer=Buffer.concat([nativeMessageBuffer,chunk]),processNativeMessages()}),process.stdin.on("end",()=>{log("Extension disconnected (stdin end)"),cleanupAndExit(0)}),process.stdin.on("error",error48=>{log("stdin error:",String(error48)),cleanupAndExit(1)})}function sendRequestToExtension(action,data,timeoutMs,trustedInternal=!1,controlSource="local"){let id=`${Date.now()}_${Math.random().toString(36).slice(2,10)}`;return new Promise((resolve9,reject)=>{let timer=setTimeout(()=>{pendingRequests.delete(id),reject(new Error(`Request timeout after ${timeoutMs}ms`))},timeoutMs);pendingRequests.set(id,{resolve:resolve9,reject,timer}),sendToExtension(createExtensionRequestMessage(id,action,data,trustedInternal,controlSource))})}function toTimeoutMs(action,data){if(action==="send_request"||action==="__send_request_with_files")return Number(data&&data.timeout?data.timeout:3e4)+5e3;if(action==="send_mtop_request")return Number(data&&data.timeout?data.timeout:1e4)+5e3;if(action==="page_wait")return Number(data?.time??data?.timeout??1e4)+5e3;if(action==="tab_open")return 4e4;if(action==="run_actions"){let timeoutMs=(Array.isArray(data?.actions)?data.actions:[{}]).reduce((total,step)=>{let stepAction=String(step?.action??"");return!stepAction||stepAction==="run_actions"?total+DEFAULT_TIMEOUT_MS:total+toTimeoutMs(stepAction,step?.data??{})},0);return Math.max(DEFAULT_TIMEOUT_MS,timeoutMs)}if(shouldObservePageAction(action,data)){let observationMs=Math.min(Math.max(Number(data?.observe?.timeoutMs??3e3),500),3e4),navigationGraceMs=Math.min(Math.max(Number(data?.observe?.navigationGraceMs??1e3),0),5e3),navigationTimeoutMs=Math.min(Math.max(Number(data?.observe?.navigationTimeoutMs??15e3),1e3),3e4);return Math.max(DEFAULT_TIMEOUT_MS,observationMs+navigationGraceMs+4e3+navigationTimeoutMs+5e3)}return DEFAULT_TIMEOUT_MS}async function dispatchHostRequest(request,managed=!1){let{action,data={}}=request,controlSource=normalizeControlSource(request.controlSource);if(action==="provider_control_sessions_changed")return sendToExtension({type:"control_sessions_changed"}),{data:{refreshed:!0}};if(!managed&&(isBrowserCommandAction(action)||typeof action=="string"&&action.startsWith("__artifact_")))return{data:await getControlSessionManager().invoke(action,data,request.controlSessionId,request.transport,controlSource)};if(action==="start_cloud_connector"){if(!data.serverUrl||typeof data.serverUrl!="string")throw new Error("serverUrl is required");let result=await startCloudConnector(data.serverUrl);if(!result.success)throw new Error(result.error??"Cloud connector failed to start");return{data:result}}if(action==="stop_cloud_connector"){if(!data.serverUrl||typeof data.serverUrl!="string")throw new Error("serverUrl is required");let result=stopCloudConnector(data.serverUrl);if(!result.success)throw new Error(result.error??"Cloud connector failed to stop");return{data:result}}if(action==="list_cloud_connectors")return{data:listCloudConnectors()};if(action==="get_versions")return{data:await collectVersions(controlSource==="local")};if(action==="get_browser_access_url")return{data:{browserAccess:data.browser?await getManagedBrowserAccess(data):await resolveBrowserAccess()}};if(isInternalExtensionAction(action))throw new Error("Internal action is not available to clients");if(action==="agent_chat_run")return{data:await getAgentChatManager().runTask(data)};if(action==="browser_list"){discoverCdp&&cancelInventoryExit();let providerWarnings=await ensureInstalledProvidersRunning(),shouldDiscover=isDaemonMode&&!skipBrowserRegistration;discoverCdp&&CDP_BROWSER_ID==="cdp"&&await retireUnreachableBrowserRecord(CDP_BROWSER_ID,canConnectInstanceSocket);let discoveryProbeError,discovered=shouldDiscover?await ensureDiscoverableCdpBrowser({isPublished:()=>cdpBrowserPublished,isAvailable:async()=>{let probe=await getCdpSession().probeAvailability();return discoveryProbeError=probe.error?oneLineError(probe.error):void 0,log(`CDP discovery probe ${describeCdpEndpoint()} -> ${probe.available?"ok":`fail (${discoveryProbeError||"unknown error"})`}`),probe.available},publish:publishDaemonBrowser,monitor:monitorConnectedDaemonBrowser}):!1,inventory=await listBrowserInventory(getBrowserProviderCoordinator().providerRuntimes),registeredCdpAvailable=inventory.browsers.some(browser=>browser.browserId===CDP_BROWSER_ID&&browser.transport==="cdp"&&browser.status==="connected"),discoveryWarnings=shouldDiscover&&!discovered&&!registeredCdpAvailable?[`CDP discovery probe ${describeCdpEndpoint()} failed: ${discoveryProbeError||"unknown error"}`]:[],inventoryData=appendWarnings(inventory,[...providerWarnings,...discoveryWarnings]),closeConnection=skipBrowserRegistration||discoverCdp&&!discovered;return closeConnection&&scheduleInventoryExit(),{data:inventoryData,closeConnection}}if(action==="browser_close")return{data:await closeBrowser(data)};if(action==="browser_launch")return{data:await launchBrowser(data)};if(action==="browser_release"){let startedAt2=Date.now(),affectedTabIds=new Set,transports=[],failures=[],released=!0,hadActiveControl=!1;try{let releaseErrors=[];if(extensionVersion!==null)try{let result=await sendRequestToExtension(action,data,toTimeoutMs(action,data));released=released&&result?.released!==!1,hadActiveControl=hadActiveControl||result?.hadActiveControl===!0,result?.hadActiveControl&&transports.push("extension");for(let tabId of result?.affectedTabIds??[])affectedTabIds.add(tabId);Array.isArray(result?.failures)&&failures.push(...result.failures)}catch(error48){releaseErrors.push(`extension: ${error48 instanceof Error?error48.message:String(error48)}`)}if(cdpSession){let session=cdpSession;cdpSession=null;try{let result=await releaseCdpControl(session);released=released&&result.released,hadActiveControl=hadActiveControl||result.hadActiveControl,result.hadActiveControl&&transports.push("cdp");for(let tabId of result.affectedTabIds)affectedTabIds.add(tabId)}catch(error48){session.close(),releaseErrors.push(`cdp: ${error48 instanceof Error?error48.message:String(error48)}`)}}if(cdpAutoReconnectEnabled=!1,releaseErrors.length>0)throw new Error(`Failed to fully release browser control (${releaseErrors.join("; ")})`);return trackAction(action,{success:released,transport:transports.join("+")||"none",duration_ms:Date.now()-startedAt2,extension_version:extensionVersion??"not_connected"}),{data:{released,hadActiveControl,transports,affectedTabIds:[...affectedTabIds].sort((a,b)=>a-b),...failures.length?{failures}:{}}}}catch(error48){throw trackAction(action,{success:!1,transport:transports.join("+")||(extensionVersion!==null?"extension":"cdp"),duration_ms:Date.now()-startedAt2,error_code:classifyAnalyticsError(error48),extension_version:extensionVersion??"not_connected"}),error48}}if(!isExtensionBrowserAction(action)&&(typeof action!="string"||!action.startsWith("__")))throw new Error(`Unsupported action: ${String(action)}`);if(request.transport==="extension"&&extensionVersion===null)throw new Error("CONTROL_SESSION_TRANSPORT_UNAVAILABLE: extension is disconnected");let useExtension=request.transport!=="cdp"&&extensionVersion!==null,transport=useExtension?"extension":"cdp",startedAt=Date.now();try{validateRequiredActionTabId(action,data);let result;return useExtension?action==="send_request"&&hasSendRequestFiles(data)?result=await sendRequestWithTransferredFiles(data,(internalAction,payload,timeoutMs)=>sendRequestToExtension(internalAction,payload,timeoutMs,!0,controlSource)):action==="run_actions"&&hasRunActionsSendRequestFiles(data)?result=await sendRunActionsWithTransferredFiles(data,(internalAction,payload,timeoutMs)=>sendRequestToExtension(internalAction,payload,timeoutMs,!0,controlSource),transformed=>toTimeoutMs("run_actions",transformed)):result=await sendRequestToExtension(action,data,toTimeoutMs(action,data),!1,controlSource):(cdpPermissionNoticeLogged||(cdpPermissionNoticeLogged=!0,log("CDP mode: domain permission checks are not enforced — all actions run without domain authorization")),result=await handleViaCdp(action,data,toTimeoutMs(action,data),controlSource)),trackAction(action,{success:!0,transport,duration_ms:Date.now()-startedAt,extension_version:extensionVersion??"not_connected"}),{data:result}}catch(error48){throw trackAction(action,{success:!1,transport,duration_ms:Date.now()-startedAt,error_code:classifyAnalyticsError(error48),extension_version:extensionVersion??"not_connected"}),error48}}async function handleSocketRequest(socket,line){let request;try{request=JSON.parse(line)}catch{socket.write(JSON.stringify({id:"",success:!1,error:`Invalid JSON request: ${line}`})+`
1730
1738
  `);return}let id=request.id??"";try{let result=await dispatchHostRequest(request),response={id,success:!0,data:result.data};if(!versionWarningEmitted){let warning=buildVersionWarning(request.version);warning&&(versionWarningEmitted=!0,response.versionWarning=warning)}let encoded=JSON.stringify(response)+`
1731
1739
  `;result.closeConnection?socket.end(encoded):socket.write(encoded)}catch(error48){socket.write(JSON.stringify({id,success:!1,error:error48 instanceof Error?error48.message:String(error48)})+`
1732
1740
  `)}}async function handleSocketLine(socket,line){await handleSocketRequest(socket,line)}async function handleViaCdp(action,data,_timeoutMs,controlSource){if(!getRegisteredActionNames().includes(action))throw new Error(`Action "${action}" is not supported in CDP mode`);if(!await getCdpSession().isAvailable())throw CDP_ENDPOINT_FILE?new Error("The remote CDP endpoint is not available"):new Error(`Chrome DevTools remote debugging is not available on port ${CDP_PORT}. Enable it via chrome://inspect/#remote-debugging (Chrome 145+) or install the Mearl extension.`);return isDaemonMode&&!skipBrowserRegistration&&(publishDaemonBrowser(),shouldReconnectDaemonBrowser()||monitorConnectedDaemonBrowser()),shouldObservePageAction(action,data)?cdpObservedPageAction(getCdpSession(),action,data,controlSource):dispatchCdpAction(getCdpSession(),action,data,controlSource)}function onSocketConnection(socket){let lineBuffer=new Utf8LineBuffer(MAX_SOCKET_BUFFER_SIZE2);socket.on("data",chunk=>{let result=lineBuffer.push(chunk);if(result.overflow){log(`socket request exceeded ${MAX_SOCKET_BUFFER_SIZE2} bytes; closing connection`),socket.destroy();return}for(let line of result.lines)line.trim()&&handleSocketLine(socket,line)}),socket.on("error",error48=>{log("socket error:",String(error48))})}function isPathAlive(socketPath){return new Promise(resolve9=>{if(process.platform!=="win32"&&!fs21.existsSync(socketPath)){resolve9(!1);return}let client2=net5.createConnection(socketPath),done=alive=>{client2.removeAllListeners(),client2.destroy(),resolve9(alive)},timer=setTimeout(()=>done(!1),500);client2.on("connect",()=>{clearTimeout(timer),done(!0)}),client2.on("error",()=>{clearTimeout(timer),done(!1)})})}function listenOn(socketPath){return new Promise((resolve9,reject)=>{if(process.platform!=="win32"&&fs21.existsSync(socketPath))try{fs21.unlinkSync(socketPath)}catch{}let server=net5.createServer(onSocketConnection);server.once("error",reject),server.listen(socketPath,()=>{if(process.platform!=="win32")try{fs21.chmodSync(socketPath,384)}catch(error48){server.close();try{fs21.unlinkSync(socketPath)}catch{}reject(error48);return}server.removeListener("error",reject),server.on("error",error48=>log("socket server error:",String(error48))),log(`listening on ${socketPath}`),resolve9(server)})})}async function tryBindLegacySocket(){if(await isPathAlive(LEGACY_SOCKET_PATH)){log("legacy socket already owned by a live host, skipping");return}try{legacyServer=await listenOn(LEGACY_SOCKET_PATH)}catch(error48){log("legacy socket bind failed (raced):",String(error48)),legacyServer=null}}function releaseLegacySocket(){if(!legacyServer)return;let server=legacyServer;legacyServer=null;try{server.close()}catch{}if(process.platform!=="win32")try{fs21.existsSync(LEGACY_SOCKET_PATH)&&fs21.unlinkSync(LEGACY_SOCKET_PATH)}catch{}}async function startSocketServer(){socketServer=await listenOn(INSTANCE_SOCKET_PATH),skipBrowserRegistration||await tryBindLegacySocket()}function cleanupInstanceSocketFile(){if(process.platform!=="win32")try{fs21.existsSync(INSTANCE_SOCKET_PATH)&&fs21.unlinkSync(INSTANCE_SOCKET_PATH)}catch(error48){log("cleanup socket file failed:",String(error48))}}function cleanupAndExit(code){controlSessionManager?.artifacts.disposeSync(),cancelInventoryExit(),cdpRegistrationTimer&&(clearInterval(cdpRegistrationTimer),cdpRegistrationTimer=null),cdpSession?.close(),agentChatManager?.dispose(),agentChatManager=null,unregisterBrowser(),cdpBrowserPublished=!1,releaseLegacySocket();let finish=()=>{cleanupInstanceSocketFile(),process.exit(code)};if(socketServer){socketServer.close(finish),socketServer=null;return}finish()}function restartAfterUpdate(){setTimeout(()=>process.exit(0),2e3).unref(),cleanupAndExit(0)}function publishDaemonBrowser(){if(cancelInventoryExit(),cdpBrowserPublished)return!0;let registered=registerBrowser({browserId:CDP_BROWSER_ID,socketPath:INSTANCE_SOCKET_PATH,browserName:CDP_BROWSER_NAME,nativeHostVersion:NATIVE_HOST_VERSION,transport:"cdp",lastFocusedAt:discoverCdp?-1:CDP_BROWSER_ID.startsWith("managed:")?0:void 0,preserveFocus:!discoverCdp});return cdpBrowserPublished=registered,registered}function unpublishDaemonBrowser(){cdpBrowserPublished&&(unregisterBrowser(),cdpBrowserPublished=!1)}function shouldReconnectDaemonBrowser(){return!!CDP_ENDPOINT_FILE||CDP_BROWSER_ID.startsWith("managed:")}function monitorConnectedDaemonBrowser(){cdpRegistrationTimer||(cdpRegistrationTimer=setInterval(()=>{getCdpSession().hasActiveConnections()||(unpublishDaemonBrowser(),cdpRegistrationTimer&&clearInterval(cdpRegistrationTimer),cdpRegistrationTimer=null,discoverCdp&&scheduleInventoryExit())},2e3),cdpRegistrationTimer.unref())}async function monitorReconnectableDaemonBrowser(){let checking=!1,refresh=async()=>{if(!checking&&cdpAutoReconnectEnabled){checking=!0;try{await getCdpSession().isAvailable()?publishDaemonBrowser():unpublishDaemonBrowser()}finally{checking=!1}}};await refresh(),cdpRegistrationTimer=setInterval(()=>{refresh()},2e3),cdpRegistrationTimer.unref()}async function main(){initBrowserRegistry({log}),pruneDeadBrowsers(),initCloudConnector({log,isDaemonMode,sendToExtension,version:NATIVE_HOST_VERSION}),isDaemonMode?log(`running in ${skipBrowserRegistration?"browser inventory":discoverCdp?"CDP discovery":"CDP"} daemon mode, pid=${process.pid}, version=${NATIVE_HOST_VERSION}, cdp=${describeCdpEndpoint()}`):setupNativeMessageInput(),discoverCdp&&scheduleInventoryExit(DISCOVERY_REQUEST_IDLE_EXIT_MS),await startSocketServer(),isDaemonMode&&!skipBrowserRegistration&&shouldReconnectDaemonBrowser()&&await monitorReconnectableDaemonBrowser(),process.on("SIGINT",()=>cleanupAndExit(0)),process.on("SIGTERM",()=>cleanupAndExit(0)),process.on("uncaughtException",error48=>{log("uncaughtException:",String(error48)),cleanupAndExit(1)}),process.on("unhandledRejection",error48=>{log("unhandledRejection:",String(error48)),cleanupAndExit(1)})}main().catch(error48=>{log("main() failed:",String(error48)),process.exit(1)});