surf-cli 2.19.0 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,25 +1,54 @@
1
- var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r},n=class extends Error{code;details;constructor(e,t,n){super(t),this.name=`CDPControllerError`,this.code=e,this.details=n}},r={alt:1,ctrl:2,control:2,meta:4,cmd:4,command:4,win:4,windows:4,shift:8},i={enter:{key:`Enter`,code:`Enter`,keyCode:13,text:`\r`},tab:{key:`Tab`,code:`Tab`,keyCode:9},escape:{key:`Escape`,code:`Escape`,keyCode:27},backspace:{key:`Backspace`,code:`Backspace`,keyCode:8},delete:{key:`Delete`,code:`Delete`,keyCode:46},arrowup:{key:`ArrowUp`,code:`ArrowUp`,keyCode:38},arrowdown:{key:`ArrowDown`,code:`ArrowDown`,keyCode:40},arrowleft:{key:`ArrowLeft`,code:`ArrowLeft`,keyCode:37},arrowright:{key:`ArrowRight`,code:`ArrowRight`,keyCode:39},home:{key:`Home`,code:`Home`,keyCode:36},end:{key:`End`,code:`End`,keyCode:35},pageup:{key:`PageUp`,code:`PageUp`,keyCode:33},pagedown:{key:`PageDown`,code:`PageDown`,keyCode:34},space:{key:` `,code:`Space`,keyCode:32,text:` `},f1:{key:`F1`,code:`F1`,keyCode:112},f2:{key:`F2`,code:`F2`,keyCode:113},f3:{key:`F3`,code:`F3`,keyCode:114},f4:{key:`F4`,code:`F4`,keyCode:115},f5:{key:`F5`,code:`F5`,keyCode:116},f6:{key:`F6`,code:`F6`,keyCode:117},f7:{key:`F7`,code:`F7`,keyCode:118},f8:{key:`F8`,code:`F8`,keyCode:119},f9:{key:`F9`,code:`F9`,keyCode:120},f10:{key:`F10`,code:`F10`,keyCode:121},f11:{key:`F11`,code:`F11`,keyCode:122},f12:{key:`F12`,code:`F12`,keyCode:123}},a=class e{targets=new Map;consoleMessages=new Map;networkRequests=new Map;networkEntries=new Map;consoleCallbacks=new Map;networkCallbacks=new Map;networkRequestStartTimes=new Map;pendingDialogs=new Map;detachReasons=new Map;networkEntrySeq=0;networkBodyBytes=new Map;networkCapture=new Map;networkEventQueue=new Map;static debuggerListenerRegistered=!1;static DEFAULT_PER_BODY_BYTES=65536;static DEFAULT_TOTAL_BODY_BYTES=2097152;static STATIC_ASSET_TYPES=new Set([`image/png`,`image/jpeg`,`image/gif`,`image/webp`,`image/svg+xml`,`image/x-icon`,`font/woff`,`font/woff2`,`font/ttf`,`font/otf`,`application/font-woff`,`application/font-woff2`,`text/css`,`application/javascript`,`text/javascript`,`application/x-javascript`]);static BINARY_TYPES=new Set([`image/png`,`image/jpeg`,`image/gif`,`image/webp`,`image/x-icon`,`font/woff`,`font/woff2`,`font/ttf`,`font/otf`,`application/font-woff`,`application/font-woff2`,`application/octet-stream`,`application/pdf`,`application/zip`,`audio/mpeg`,`audio/wav`,`audio/ogg`,`video/mp4`,`video/webm`,`video/ogg`]);async attach(e){if(this.targets.has(e))return;let t={tabId:e};try{await chrome.debugger.attach(t,`1.3`)}catch(t){let r=t instanceof Error?t.message:String(t);throw/already attached/i.test(r)?new n(`debugger_busy`,`Another debugger already controls tab ${e}. Close DevTools or the competing debugger and retry.`,{tabId:e}):r.includes(`Cannot access`)||r.includes(`Cannot attach`)?new n(`restricted_target`,`Cannot control this page. Chrome restricts automation on chrome://, extensions, and web store pages.`,{tabId:e}):new n(`debugger_attach_failed`,`Failed to attach debugger: ${r}`,{tabId:e})}this.targets.set(e,t),this.detachReasons.delete(e),this.setupEventListener(),this.consoleMessages.set(e,[]),this.networkRequests.set(e,[]);try{await this.send(e,`Page.enable`)}catch{}}async detach(e){let t=this.targets.get(e);if(t){try{await chrome.debugger.detach(t)}catch(e){console.warn(`[CDPController] Error detaching:`,e)}this.targets.delete(e),this.consoleMessages.delete(e),this.networkRequests.delete(e),this.networkEntries.delete(e),this.networkBodyBytes.delete(e),this.networkCapture.delete(e),this.consoleCallbacks.delete(e),this.networkCallbacks.delete(e),this.pendingDialogs.delete(e),this.clearRequestStartTimes(e),this.detachReasons.delete(e)}}async detachAll(){for(let e of this.targets.keys())await this.detach(e)}setupEventListener(){e.debuggerListenerRegistered||(e.debuggerListenerRegistered=!0,chrome.debugger.onEvent.addListener((e,t,n)=>{let r=e.tabId;!r||!this.targets.has(r)||this.enqueueCDPEvent(r,t,n)}),chrome.debugger.onDetach.addListener((e,t)=>{let n=e.tabId;n&&this.targets.has(n)&&(this.detachReasons.set(n,t||`unknown`),this.targets.delete(n),this.consoleMessages.delete(n),this.networkRequests.delete(n),this.networkEntries.delete(n),this.networkBodyBytes.delete(n),this.networkCapture.delete(n),this.consoleCallbacks.delete(n),this.networkCallbacks.delete(n),this.pendingDialogs.delete(n),this.clearRequestStartTimes(n))}))}requestStartKey(e,t){return`${e}:${t}`}clearRequestStartTimes(e){let t=`${e}:`;for(let e of this.networkRequestStartTimes.keys())e.startsWith(t)&&this.networkRequestStartTimes.delete(e)}enqueueCDPEvent(e,t,n){let r=(this.networkEventQueue.get(e)||Promise.resolve()).catch(()=>void 0).then(()=>this.handleCDPEvent(e,t,n)).catch(()=>void 0);this.networkEventQueue.set(e,r),r.finally(()=>{this.networkEventQueue.get(e)===r&&this.networkEventQueue.delete(e)})}async drainNetworkEvents(e){await this.networkEventQueue.get(e)}async handleCDPEvent(e,t,n){switch(t){case`Runtime.consoleAPICalled`:this.handleRuntimeConsole(e,n);break;case`Runtime.exceptionThrown`:this.handleRuntimeException(e,n);break;case`Network.requestWillBeSent`:this.handleNetworkRequest(e,n);break;case`Network.responseReceived`:this.handleNetworkResponse(e,n);break;case`Network.loadingFailed`:this.handleNetworkFailed(e,n);break;case`Network.loadingFinished`:await this.handleLoadingFinished(e,n);break;case`Page.javascriptDialogOpening`:this.handleDialogOpening(e,n);break;case`Page.javascriptDialogClosed`:this.pendingDialogs.delete(e)}}handleRuntimeConsole(e,t){let n=this.consoleMessages.get(e)||[],r=(t.args||[]).map(e=>e.value===void 0?e.description?e.description:``:String(e.value)).join(` `),i=t.stackTrace?.callFrames?.[0],a={type:t.type||`log`,text:r,timestamp:t.timestamp||Date.now(),url:i?.url,line:i?.lineNumber};n.push(a),n.length>1e3&&n.shift(),this.consoleMessages.set(e,n);let o=this.consoleCallbacks.get(e);if(o)for(let e of o.values())e(a)}handleRuntimeException(e,t){let n=this.consoleMessages.get(e)||[],r=t.exceptionDetails;if(!r)return;let i={type:`exception`,text:r.exception?.description||r.text||`Unknown exception`,timestamp:r.timestamp||Date.now(),url:r.url,line:r.lineNumber};n.push(i),n.length>1e3&&n.shift(),this.consoleMessages.set(e,n);let a=this.consoleCallbacks.get(e);if(a)for(let e of a.values())e(i)}handleNetworkRequest(e,t){let n=this.networkRequests.get(e)||[],r=t.request;if(!r)return;let i=t.timestamp?t.timestamp*1e3:Date.now();this.networkRequestStartTimes.set(this.requestStartKey(e,t.requestId),i);let a={};if(r.headers)for(let[e,t]of Object.entries(r.headers))a[e]=String(t);n.push({requestId:t.requestId,url:r.url,method:r.method,type:t.type,timestamp:i,requestHeaders:a,requestBody:r.postData}),n.length>500&&n.shift(),this.networkRequests.set(e,n),this.networkEntries.has(e)||this.networkEntries.set(e,new Map);let o=this.networkEntries.get(e),s=`r_${i}_${++this.networkEntrySeq}`,c={};if(r.headers)for(let[e,t]of Object.entries(r.headers))c[e]=String(t);let l=r.postData,u=l?l.length:void 0,d={id:s,ts:i,method:r.method,url:r.url,origin:this.extractOrigin(r.url),requestHeaders:c,requestBody:l,requestBodySize:u,tabId:e,tabUrl:t.documentURL,type:t.type,flags:[],bodyCapture:{mode:this.networkCapture.get(e)?.mode||`none`,complete:!1,reason:`pending`},_requestId:t.requestId,_responseReceived:!1,_loadingFinished:!1};if(o.size>500){let e=o.keys().next().value;e&&o.delete(e)}o.set(t.requestId,d)}handleNetworkResponse(e,t){let n=(this.networkRequests.get(e)||[]).find(e=>e.requestId===t.requestId);if(n){if(n.status=t.response?.status,n.mimeType=t.response?.mimeType,t.response?.headers){let e={};for(let[n,r]of Object.entries(t.response.headers))e[n]=String(r);n.responseHeaders=e}let r=this.networkCallbacks.get(e);if(r){let i=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),a=Date.now(),o=i?Math.round(a-i):void 0;for(let e of r.values())e({method:n.method,url:n.url,status:n.status,duration:o,timestamp:a})}}let r=this.networkEntries.get(e)?.get(t.requestId);if(r&&t.response){let n=t.response,i=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),a=t.timestamp?t.timestamp*1e3:Date.now();i&&(r.ttfb=Math.round(a-i)),r.status=n.status,r.statusText=n.statusText,r.mimeType=n.mimeType;let o={};if(n.headers)for(let[e,t]of Object.entries(n.headers))o[e]=String(t);r.responseHeaders=o,this.isBinaryType(n.mimeType)&&r.flags.push(`binary`),(n.mimeType?.includes(`protobuf`)||n.mimeType?.includes(`x-protobuf`)||n.mimeType?.includes(`application/grpc`))&&r.flags.push(`protobuf`),r._responseReceived=!0}}handleNetworkFailed(e,t){let n=(this.networkRequests.get(e)||[]).find(e=>e.requestId===t.requestId);if(n&&!n.status){n.status=0;let r=this.networkCallbacks.get(e);if(r){let i=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),a=Date.now(),o=i?Math.round(a-i):void 0;this.networkRequestStartTimes.delete(this.requestStartKey(e,t.requestId));for(let e of r.values())e({method:n.method,url:n.url,status:0,duration:o,timestamp:a})}}let r=this.networkEntries.get(e)?.get(t.requestId);if(r){let n=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),i=t.timestamp?t.timestamp*1e3:Date.now();n&&(r.duration=Math.round(i-n)),this.networkRequestStartTimes.delete(this.requestStartKey(e,t.requestId)),r.status=0,r.flags.push(`failed`),r._loadingFinished=!0}}handleDialogOpening(e,t){this.pendingDialogs.set(e,{type:t.type,message:t.message,defaultPrompt:t.defaultPrompt,timestamp:Date.now()})}async handleLoadingFinished(e,t){let n=(this.networkRequests.get(e)||[]).find(e=>e.requestId===t.requestId);if(n){let r=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),i=t.timestamp?t.timestamp*1e3:Date.now();r&&(n.duration=Math.round(i-r))}let r=this.networkEntries.get(e)?.get(t.requestId);if(!r)return;let i=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),a=t.timestamp?t.timestamp*1e3:Date.now();i&&(r.duration=Math.round(a-i)),this.networkRequestStartTimes.delete(this.requestStartKey(e,t.requestId)),r.responseBodySize=t.encodedDataLength,r._loadingFinished=!0;let o=this.networkCapture.get(e)||{mode:`none`,perBodyBytes:0,totalBytes:0},s=Math.max(0,Number(t.encodedDataLength)||0),c=null;if(o.mode===`none`?c=`disabled`:o.mode===`text`&&(this.isStaticAsset(r.mimeType)||this.isBinaryType(r.mimeType))?c=`content-mode`:s>o.perBodyBytes?c=`per-body-cap`:(this.networkBodyBytes.get(e)||0)+s>o.totalBytes&&(c=`session-cap`),c){r.bodyCapture={mode:o.mode,complete:!1,reason:c},c.endsWith(`cap`)&&r.flags.push(`truncated`);return}try{let i=await this.send(e,`Network.getResponseBody`,{requestId:t.requestId}),a=typeof i.body==`string`?i.body:``,s=i.base64Encoded?Math.ceil(a.length*.75):new TextEncoder().encode(a).byteLength;if(s>o.perBodyBytes||(this.networkBodyBytes.get(e)||0)+s>o.totalBytes){r.flags.push(`truncated`),r.bodyCapture={mode:o.mode,complete:!1,reason:s>o.perBodyBytes?`per-body-cap`:`session-cap`};return}if(i.base64Encoded&&o.mode===`all`)r.responseBody=a,r.responseBodyEncoding=`base64`;else if(i.base64Encoded)try{r.responseBody=atob(a)}catch{r.bodyCapture={mode:o.mode,complete:!1,reason:`decode-failed`};return}else r.responseBody=a;this.networkBodyBytes.set(e,(this.networkBodyBytes.get(e)||0)+s),r.bodyCapture={mode:o.mode,complete:!0,capturedBytes:s},n&&(n.responseBody=r.responseBody)}catch{r.bodyCapture={mode:o.mode,complete:!1,reason:`unavailable`}}}extractOrigin(e){try{return new URL(e).origin}catch{return``}}isStaticAsset(t){return t?e.STATIC_ASSET_TYPES.has(t):!1}isBinaryType(t){return t?e.BINARY_TYPES.has(t):!1}async enableConsoleTracking(e){await this.ensureAttached(e);try{await this.send(e,`Runtime.enable`)}catch{}}async enableNetworkTracking(t,n={}){await this.ensureAttached(t);let r=n.bodyMode||`text`,i=n.perBodyBytes??e.DEFAULT_PER_BODY_BYTES,a=n.totalBytes??e.DEFAULT_TOTAL_BODY_BYTES;if(!Number.isInteger(i)||i<0||!Number.isInteger(a)||a<0)throw Error(`network body caps must be non-negative integers`);this.networkCapture.set(t,{mode:r,perBodyBytes:i,totalBytes:a}),this.networkBodyBytes.has(t)||this.networkBodyBytes.set(t,0);try{await this.send(t,`Network.enable`,{maxPostDataSize:65536})}catch{}}async disableNetworkTracking(e){if(await this.drainNetworkEvents(e),this.networkCapture.delete(e),this.networkBodyBytes.delete(e),!this.networkCallbacks.get(e)?.size)try{await this.send(e,`Network.disable`)}catch{}}async handleDialog(e,t,n){try{return await this.send(e,`Page.handleJavaScriptDialog`,{accept:t,promptText:n}),this.pendingDialogs.delete(e),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}getDialogInfo(e){return this.pendingDialogs.get(e)||null}async emulateNetwork(e,t){await this.ensureAttached(e);let n={offline:{offline:!0,latency:0,downloadThroughput:0,uploadThroughput:0},"slow-3g":{offline:!1,latency:2e3,downloadThroughput:5e4,uploadThroughput:5e4},"fast-3g":{offline:!1,latency:562.5,downloadThroughput:18e4,uploadThroughput:84375},"4g":{offline:!1,latency:100,downloadThroughput:4e6,uploadThroughput:3e6},reset:{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}},r=n[t.toLowerCase().replace(/\s+/g,`-`)];if(!r)return{success:!1,error:`Unknown preset: ${t}. Available: ${Object.keys(n).join(`, `)}`};try{return await this.send(e,`Network.enable`),await this.send(e,`Network.emulateNetworkConditions`,r),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateCPU(e,t){if(await this.ensureAttached(e),t<1)return{success:!1,error:`CPU throttling rate must be >= 1 (1 = no throttle, 4 = 4x slower)`};try{return await this.send(e,`Emulation.setCPUThrottlingRate`,{rate:t}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateGeolocation(e,t,n,r){await this.ensureAttached(e);try{return await this.send(e,`Emulation.setGeolocationOverride`,{latitude:t,longitude:n,accuracy:r||100}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async clearGeolocation(e){await this.ensureAttached(e);try{return await this.send(e,`Emulation.clearGeolocationOverride`),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateDevice(e,t){await this.ensureAttached(e);try{return await this.send(e,`Emulation.setDeviceMetricsOverride`,{width:t.width,height:t.height,deviceScaleFactor:t.deviceScaleFactor,mobile:t.mobile}),t.userAgent&&await this.send(e,`Emulation.setUserAgentOverride`,{userAgent:t.userAgent}),t.touch&&await this.send(e,`Emulation.setTouchEmulationEnabled`,{enabled:!0,maxTouchPoints:5}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async clearDeviceEmulation(e){await this.ensureAttached(e);try{return await this.send(e,`Emulation.clearDeviceMetricsOverride`),await this.send(e,`Emulation.setUserAgentOverride`,{userAgent:``}),await this.send(e,`Emulation.setTouchEmulationEnabled`,{enabled:!1}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateViewport(e,t){await this.ensureAttached(e);try{let n=await this.getViewportSize(e);return await this.send(e,`Emulation.setDeviceMetricsOverride`,{width:t.width||n.width,height:t.height||n.height,deviceScaleFactor:t.deviceScaleFactor||1,mobile:t.mobile||!1}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateTouch(e,t){await this.ensureAttached(e);try{return await this.send(e,`Emulation.setTouchEmulationEnabled`,{enabled:t,maxTouchPoints:t?5:0}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async startPerformanceTrace(e,t){await this.ensureAttached(e);try{return await this.send(e,`Performance.enable`),await this.send(e,`Tracing.start`,{categories:t?.join(`,`)||`devtools.timeline,v8.execute,disabled-by-default-devtools.timeline`,transferMode:`ReturnAsStream`}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async stopPerformanceTrace(e){await this.ensureAttached(e);try{await this.send(e,`Performance.enable`);let t=await this.send(e,`Performance.getMetrics`);await this.send(e,`Tracing.end`),await this.send(e,`Performance.disable`);let n={};for(let e of t.metrics||[])n[e.name]=e.value;return{success:!0,metrics:n}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async getPerformanceMetrics(e){await this.ensureAttached(e);try{await this.send(e,`Performance.enable`);let t=await this.send(e,`Performance.getMetrics`);await this.send(e,`Performance.disable`);let n={};for(let e of t.metrics||[])n[e.name]=e.value;return{success:!0,metrics:n}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async setFileInputBySelector(e,t,n){await this.ensureAttached(e);try{await this.send(e,`DOM.enable`);let r=await this.send(e,`DOM.getDocument`),i=await this.send(e,`DOM.querySelector`,{nodeId:r.root.nodeId,selector:t});return i.nodeId?(await this.send(e,`DOM.setFileInputFiles`,{nodeId:i.nodeId,files:n}),{success:!0}):{success:!1,error:`Could not find element by selector`}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async waitForLoad(e,t=3e4){await this.ensureAttached(e);let n=Date.now();try{for(;Date.now()-n<t;){let t=(await this.send(e,`Runtime.evaluate`,{expression:`document.readyState`,returnByValue:!0})).result?.value;if(t===`complete`)return{success:!0,readyState:t};await new Promise(e=>setTimeout(e,100))}return{success:!1,error:`Timeout waiting for page load (${t}ms)`}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async getFrames(e){await this.ensureAttached(e);try{await this.send(e,`Page.enable`);let t=await this.send(e,`Page.getFrameTree`),n=[],r=(e,t)=>{if(n.push({frameId:e.frame.id,url:e.frame.url,name:e.frame.name||``,parentId:t}),e.childFrames)for(let t of e.childFrames)r(t,e.frame.id)};return r(t.frameTree),{success:!0,frames:n}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async evaluateInFrame(e,t,n){await this.ensureAttached(e);try{let r=await this.send(e,`Page.createIsolatedWorld`,{frameId:t,worldName:`surf-isolated`}),i=`JSON.stringify((function() { ${n} })())`,a=await this.send(e,`Runtime.evaluate`,{expression:i,contextId:r.executionContextId,returnByValue:!0,awaitPromise:!0});if(a.exceptionDetails)return{success:!1,error:a.exceptionDetails.text||a.exceptionDetails.exception?.description||`Evaluation failed`};try{return{success:!0,result:JSON.parse(a.result?.value)}}catch{return{success:!0,result:a.result?.value}}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}getConsoleMessages(e,t){let n=this.consoleMessages.get(e)||[];if(t?.onlyErrors&&(n=n.filter(e=>e.type===`error`||e.type===`exception`)),t?.pattern)try{let e=new RegExp(t.pattern,`i`);n=n.filter(t=>e.test(t.text))}catch{n=n.filter(e=>e.text.includes(t.pattern))}return t?.limit&&(n=n.slice(-t.limit)),[...n]}clearConsoleMessages(e){this.consoleMessages.set(e,[])}getNetworkRequests(e,t){let n=this.networkRequests.get(e)||[];return t?.urlPattern&&(n=n.filter(e=>e.url.includes(t.urlPattern))),t?.limit&&(n=n.slice(-t.limit)),[...n]}clearNetworkRequests(e){this.networkRequests.set(e,[]),this.networkEntries.set(e,new Map),this.networkBodyBytes.set(e,0)}getNetworkEntries(e,t){let n=this.networkEntries.get(e),r=[];return r=n&&n.size>0?Array.from(n.values()):(this.networkRequests.get(e)||[]).map((t,n)=>({id:`r_${t.timestamp}_${n}`,ts:t.timestamp,method:t.method,url:t.url,origin:this.extractOrigin(t.url),requestHeaders:{},tabId:e,type:t.type,status:t.status,flags:[],bodyCapture:{mode:`none`,complete:!1,reason:`legacy`},_requestId:t.requestId,_responseReceived:!0,_loadingFinished:!0})),t?.includeStatic||(r=r.filter(e=>!this.isStaticAsset(e.mimeType))),t?.urlPattern&&(r=r.filter(e=>e.url.includes(t.urlPattern))),t?.limit&&(r=r.slice(-t.limit)),r}getNetworkEntry(e,t){return this.networkEntries.get(e)?.get(t)||null}async getResponseBody(e,t){await this.ensureAttached(e);try{let n=await this.send(e,`Network.getResponseBody`,{requestId:t});return{success:!0,body:n.body,base64Encoded:n.base64Encoded}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}subscribeToConsole(e,t,n){this.consoleCallbacks.has(e)||this.consoleCallbacks.set(e,new Map),this.consoleCallbacks.get(e).set(t,n)}unsubscribeFromConsole(e,t){let n=this.consoleCallbacks.get(e);n&&(n.delete(t),n.size===0&&this.consoleCallbacks.delete(e))}subscribeToNetwork(e,t,n){this.networkCallbacks.has(e)||this.networkCallbacks.set(e,new Map),this.networkCallbacks.get(e).set(t,n)}unsubscribeFromNetwork(e,t){let n=this.networkCallbacks.get(e);n&&(n.delete(t),n.size===0&&this.networkCallbacks.delete(e))}async evaluateScript(e,t){await this.ensureAttached(e);try{await this.send(e,`Runtime.enable`)}catch{}return this.send(e,`Runtime.evaluate`,{expression:t,returnByValue:!0,awaitPromise:!0,timeout:3e4})}async send(e,t,n){await this.ensureAttached(e);let r=this.targets.get(e);return chrome.debugger.sendCommand(r,t,n)}async sendCommand(e,t,n){return this.send(e,t,n)}async ensureAttached(e){let t=this.detachReasons.get(e);if(t)throw this.detachReasons.delete(e),new n(`debugger_detached`,`Debugger detached from tab ${e}: ${t}. Retry after closing any competing debugger.`,{tabId:e,reason:t});this.targets.has(e)||await this.attach(e)}async getViewportSize(e){let t=await this.send(e,`Page.getLayoutMetrics`),n=t.visualViewport||t.layoutViewport;return{width:Math.round(n.clientWidth),height:Math.round(n.clientHeight)}}async captureScreenshot(e){let t=await this.send(e,`Page.captureScreenshot`,{format:`png`,captureBeyondViewport:!1}),{width:n,height:r}=await this.getViewportSize(e);return{base64:t.data,width:n,height:r}}async captureRegion(e,t,n,r,i){return{base64:(await this.send(e,`Page.captureScreenshot`,{format:`png`,clip:{x:t,y:n,width:r,height:i,scale:1}})).data,width:r,height:i}}async dispatchMouseEvent(e,t,n,r,i={}){let a={type:t,x:Math.round(n),y:Math.round(r),modifiers:i.modifiers||0};(t===`mousePressed`||t===`mouseReleased`||t===`mouseMoved`)&&(a.button=i.button||`none`,(t===`mousePressed`||t===`mouseReleased`)&&(a.clickCount=i.clickCount||1)),t!==`mouseWheel`&&(a.buttons=i.buttons??0),t===`mouseWheel`&&(a.deltaX=i.deltaX||0,a.deltaY=i.deltaY||0),await this.send(e,`Input.dispatchMouseEvent`,a)}async click(e,t,n,r=`left`,i=1,a=0){let o=r===`left`?1:r===`right`?2:r===`middle`?4:0;await this.dispatchMouseEvent(e,`mouseMoved`,t,n,{button:`none`,buttons:0,modifiers:a}),await new Promise(e=>setTimeout(e,100));for(let s=1;s<=i;s++)await this.dispatchMouseEvent(e,`mousePressed`,t,n,{button:r,buttons:o,clickCount:s,modifiers:a}),await new Promise(e=>setTimeout(e,12)),await this.dispatchMouseEvent(e,`mouseReleased`,t,n,{button:r,buttons:0,clickCount:s,modifiers:a}),s<i&&await new Promise(e=>setTimeout(e,100))}async rightClick(e,t,n,r=0){await this.click(e,t,n,`right`,1,r)}async doubleClick(e,t,n,r=0){await this.click(e,t,n,`left`,2,r)}async tripleClick(e,t,n,r=0){await this.click(e,t,n,`left`,3,r)}async hover(e,t,n){await this.dispatchMouseEvent(e,`mouseMoved`,t,n,{button:`none`,buttons:0})}async drag(e,t,n,r,i,a=0){await this.dispatchMouseEvent(e,`mouseMoved`,t,n,{button:`none`,buttons:0}),await new Promise(e=>setTimeout(e,50)),await this.dispatchMouseEvent(e,`mousePressed`,t,n,{button:`left`,buttons:1,clickCount:1,modifiers:a}),await new Promise(e=>setTimeout(e,50)),await this.dispatchMouseEvent(e,`mouseMoved`,r,i,{button:`left`,buttons:1,modifiers:a}),await new Promise(e=>setTimeout(e,50)),await this.dispatchMouseEvent(e,`mouseReleased`,r,i,{button:`left`,buttons:0,clickCount:1,modifiers:a})}async scroll(e,t,n,r,i){await this.dispatchMouseEvent(e,`mouseWheel`,t,n,{deltaX:r,deltaY:i})}async type(e,t){for(let n of t)if(n===`
2
- `||n===`\r`)await this.pressKey(e,`Enter`);else if(this.getKeyDefinition(n)){let t=this.requiresShift(n);await this.pressKey(e,n,t?r.shift:0)}else await this.send(e,`Input.insertText`,{text:n})}requiresShift(e){return/[A-Z!@#$%^&*()_+{}|:"<>?~]/.test(e)}async dispatchKeyEvent(e,t,n,r=0){await this.send(e,`Input.dispatchKeyEvent`,{type:n.text?t:t===`keyDown`?`rawKeyDown`:t,key:n.key,code:n.code,windowsVirtualKeyCode:n.keyCode,modifiers:r,text:n.text??``,unmodifiedText:n.text??``,location:n.location??0})}async pressKey(e,t,n=0){let r=this.getKeyDefinition(t);if(!r)throw Error(`Unknown key: ${t}`);await this.dispatchKeyEvent(e,`keyDown`,r,n),await this.dispatchKeyEvent(e,`keyUp`,r,n)}async pressKeyChord(e,t){let n=t.toLowerCase().split(`+`),i=[],a=``;for(let e of n)e in r?i.push(e):a=e;let o=0;for(let e of i)o|=r[e]||0;a&&await this.pressKey(e,a,o)}getKeyDefinition(e){let t=e.toLowerCase();if(i[t])return i[t];if(e.length===1){let t=e.toUpperCase().charCodeAt(0);return{key:e,code:`Key${e.toUpperCase()}`,keyCode:t,text:e}}return null}parseModifiers(e){if(!e)return 0;let t=0,n=e.toLowerCase().split(`+`);for(let e of n){let n=e.trim();n in r&&(t|=r[n])}return t}},o=!1,s=!1,c=[];chrome.storage.local.get(`debugMode`).then(({debugMode:e})=>{if(o=!!e,s=!0,o)for(let e of c)console.log(`[Surf]`,...e);c.length=0}),chrome.storage.onChanged.addListener((e,t)=>{t===`local`&&e.debugMode&&(o=!!e.debugMode.newValue)});function l(...e){if(!s){c.push(e);return}o&&console.log(`[Surf]`,...e)}var u=t({initNativeMessaging:()=>x,postToNativeHost:()=>S,sendToNativeHost:()=>ee}),d=null,f=null,p=null,m=new Map,h=0,g=`surfBrowserInstanceId`,_=`surfBrowserEpoch`;function v(){if(globalThis.crypto?.randomUUID)return globalThis.crypto.randomUUID();let e=new Uint8Array(16);return globalThis.crypto.getRandomValues(e),Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}async function y(){let e=(await chrome.storage.local.get(g))[g];e||(e=v(),await chrome.storage.local.set({[g]:e}));let t=(await chrome.storage.session.get(_))[_];return t||(t=v(),await chrome.storage.session.set({[_]:t})),{browserInstanceId:e,browserEpoch:t}}async function b(e){let t=await y();d===e&&e.postMessage({type:`EXTENSION_HELLO`,protocolVersion:2,extensionVersion:chrome.runtime.getManifest().version,capabilities:[`browser-sessions`,`strict-targets`,`keyed-lanes`],...t})}function x(e){f=e,C()}function ee(e){return new Promise((t,n)=>{if(!d){n(Error(`Native host not connected`));return}if(e.type===`API_REQUEST`){d.postMessage(e),t({sent:!0});return}let r=++h;m.set(r,{resolve:t,reject:n}),d.postMessage({...e,id:r}),setTimeout(()=>{m.has(r)&&(m.delete(r),n(Error(`Native host request timeout`)))},1e4)})}function S(e){d&&d.postMessage(e)}function C(){p&&=(clearTimeout(p),null);try{let e=chrome.runtime.connectNative(`surf.browser.host`);d=e,l(`Connecting to native host...`),b(e).catch(e=>l(`Failed to send extension hello:`,e)),e.onMessage.addListener(async t=>{if(l(`Received from native host:`,t.type||t.id),t.type===`HOST_READY`){l(`Native host ready`),b(e).catch(e=>l(`Failed to refresh extension hello:`,e));return}if(t.type?.startsWith(`API_RESPONSE_`)){chrome.runtime.sendMessage(t).catch(()=>{});return}if(t.id&&m.has(t.id)){let{resolve:e}=m.get(t.id);m.delete(t.id),e(t);return}if(f)try{let n=await f(t);if(d!==e){l(`Cannot send response - native host disconnected:`,t.id);return}e.postMessage({id:t.id,...n})}catch(n){if(d!==e){l(`Cannot send error - native host disconnected:`,t.id);return}let r=n;e.postMessage({id:t.id,error:r instanceof Error?r.message:`Unknown error`,errorCode:typeof r?.code==`string`?r.code:void 0,errorDetails:r?.details})}}),e.onDisconnect.addListener(()=>{let t=chrome.runtime.lastError;l(`Native host disconnected:`,t?.message||`unknown reason`),d===e&&(d=null);for(let e of m.values())e.reject(Error(`Native host disconnected`));m.clear(),t?.message?.includes(`not found`)||(p=setTimeout(C,5e3))})}catch(e){l(`Failed to connect to native host:`,e),p=setTimeout(C,1e4)}}var w=`modulepreload`,T=function(e){return`/`+e},E={},D=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=T(t,n),t=s(t),t in E)return;E[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:w,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};l(`Service worker loaded`);var O=new a,k=new Map;function A(e,t){let n=Number(t?.frameId);return Number.isInteger(n)&&n>0?n:0}async function te(e,t){let n=Number(t);if(!(!Number.isInteger(n)||n<=0)&&!(await chrome.webNavigation.getAllFrames({tabId:e}))?.some(e=>e.frameId===n))throw S({type:`TARGET_EVENT`,event:`frame-reset`,tabId:e,frameId:n,reason:`missing-frame`}),new M(`frame_context_reset`,`Frame context ${n} is no longer available in tab ${e}`,{tabId:e,frameId:n,reason:`missing-frame`,recoveryCommand:`surf frame.list`})}function j(e){return!e||/^(?:about|arc|brave|chrome|chrome-extension|devtools|edge|extension|helium|moz-extension):/i.test(e)}var M=class extends Error{code;details;constructor(e,t,n){super(t),this.name=`BrowserCommandError`,this.code=e,this.details=n}};async function N(e){let t;try{t=await chrome.tabs.get(e)}catch{throw new M(`tab_gone`,`Tab ${e} no longer exists`,{tabId:e})}if(!t.id||t.windowId===void 0)throw new M(`tab_gone`,`Tab ${e} no longer has a browser window`,{tabId:e});return{tabId:t.id,windowId:t.windowId,url:t.url,title:t.title,active:!!t.active,status:t.status,restricted:j(t.url),groupId:t.groupId}}async function P(e,t=!0){let n,r,i=!1;if(e){if(n=await chrome.tabs.query({active:!0,windowId:e}),r=n[0],(!r||j(r.url))&&(n=await chrome.tabs.query({windowId:e}),r=n.find(e=>!j(e.url))),!r?.id&&t){let t=await chrome.tabs.create({windowId:e,url:`data:text/html,<html><head><title>Surf</title></head><body></body></html>`,active:!0});if(!t.id)throw new M(`target_create_failed`,`Failed to create tab in window ${e}`);await V(100),r=t,i=!0}}else n=await chrome.tabs.query({active:!0,lastFocusedWindow:!0}),r=n[0],(!r||j(r.url))&&(n=await chrome.tabs.query({active:!0,currentWindow:!0}),r=n[0]),(!r||j(r.url))&&(n=await chrome.tabs.query({active:!0}),r=n.find(e=>!j(e.url)));if(!r?.id)throw new M(`target_required`,`No active tab found. Use 'surf session.ensure <name> about:blank' or 'surf tab.new <url>'.`);return{tab:r,autoCreated:i}}async function F(e,t){try{let n=await chrome.tabs.group({tabIds:e});return await chrome.tabGroups.update(n,{title:`Surf: ${t}`,color:`blue`,collapsed:!1}),n}catch{return}}var I=new Map,L=0;function R(){return`screenshot_${++L}_${Date.now()}`}function z(e,t){if(I.set(e,t),I.size>10){let e=I.keys().next().value;e&&I.delete(e)}}function B(e){return I.get(e)||null}function V(e){return new Promise(t=>setTimeout(t,e))}var H={gemini:{openerSelector:`button[aria-label="Upload & tools"], button[aria-label="Open upload file menu"]`,closeSelector:`button[aria-label="Close upload file menu"]`,uploadItemSelector:`[data-test-id="local-images-files-uploader-button"], [data-testid="local-images-files-uploader-button"], button[aria-label^="Upload files"]`},chatgpt:{directInputSelector:`form input[type="file"]:not([accept*="image"]), input[type="file"]:not([accept*="image"]), input[type="file"]`,openerSelector:`button[data-testid="composer-plus-btn"], button[aria-label="Add files and more"]`}};async function U(e,t,n){let r=(await O.sendCommand(e,`Runtime.evaluate`,{expression:`(() => {
3
- const input = document.querySelector(${JSON.stringify(n)});
4
- if (!input || input.tagName !== 'INPUT' || input.type !== 'file') return null;
5
- return input;
6
- })()`,userGesture:!0}))?.result?.objectId;return r?(await O.sendCommand(e,`DOM.setFileInputFiles`,{files:t,objectId:r}),!0):!1}async function W(e,t,n){await O.sendCommand(e,`Page.setInterceptFileChooserDialog`,{enabled:!0});let r=null,i=null,a=()=>{r&&=(clearTimeout(r),null),i&&=(chrome.debugger.onEvent.removeListener(i),null)},o=(o,s)=>new Promise((c,l)=>{r=setTimeout(()=>{a(),l(Error(`${n} file chooser did not open within ${s/1e3}s (attempt ${o})`))},s),i=(n,r,i)=>{n.tabId===e&&r===`Page.fileChooserOpened`&&(a(),O.sendCommand(e,`DOM.setFileInputFiles`,{files:t,backendNodeId:i.backendNodeId}).then(()=>c()).catch(l))},chrome.debugger.onEvent.addListener(i)}),s=async()=>{if(n===`gemini`){await O.sendCommand(e,`Runtime.evaluate`,{expression:`document.querySelector(${JSON.stringify(H.gemini.closeSelector)})?.click()`,userGesture:!0}),await V(300),await O.sendCommand(e,`Runtime.evaluate`,{expression:`document.querySelector(${JSON.stringify(H.gemini.openerSelector)})?.click()`,userGesture:!0}),await V(500),await O.sendCommand(e,`Runtime.evaluate`,{expression:`document.querySelector(${JSON.stringify(H.gemini.uploadItemSelector)})?.click()`,userGesture:!0});return}await O.sendCommand(e,`Runtime.evaluate`,{expression:`document.querySelector(${JSON.stringify(H.chatgpt.openerSelector)})?.click()`,userGesture:!0})},c=[1e4,15e3,2e4],l=null;try{for(let e=1;e<=3;e++)try{let t=o(e,c[e-1]);await s(),await t;return}catch(t){l=t,a(),e<3&&await V(1e3)}throw Error(`${n} file upload failed after 3 attempts: ${l?.message}`)}finally{a();try{await O.sendCommand(e,`Page.setInterceptFileChooserDialog`,{enabled:!1})}catch{}}}async function ne(e,t,n){return await O.attach(t),await O.sendCommand(t,`DOM.enable`,{}),e===`chatgpt`&&await U(t,n,H.chatgpt.directInputSelector)||await W(t,n,e),{success:!0}}var G={button:`#FF6B6B`,input:`#4ECDC4`,select:`#45B7D1`,a:`#96CEB4`,textarea:`#FF8C42`,default:`#DDA0DD`};async function re(e,t,n){let r=q(e.base64),i=await createImageBitmap(r),a=new OffscreenCanvas(i.width,i.height),o=a.getContext(`2d`);if(!o)throw Error(`Failed to get canvas context`);o.drawImage(i,0,0),i.close();let s=Math.min(n.scaleX,n.scaleY);for(let e of t){let t=G[e.tag]||G.default,n=Math.round(e.bounds.x*s),r=Math.round(e.bounds.y*s),i=Math.round(e.bounds.width*s),c=Math.round(e.bounds.height*s);if(i<1||c<1)continue;o.strokeStyle=t,o.lineWidth=2,o.setLineDash([4,4]),o.strokeRect(n,r,i,c),o.setLineDash([]);let l=e.ref,u=Math.max(10,Math.min(16,Math.round(a.width*.01)));o.font=`bold ${u}px sans-serif`;let d=o.measureText(l).width+8,f=u+8,p=n+Math.floor((i-d)/2),m=r+2;(i<60||c<30)&&(m=r-f-2<0?r+c+2:r-f-2),p=Math.max(0,Math.min(a.width-d,p)),m=Math.max(0,Math.min(a.height-f,m)),o.fillStyle=t,o.fillRect(p,m,d,f),o.strokeStyle=`white`,o.lineWidth=1,o.strokeRect(p,m,d,f),o.fillStyle=`white`,o.textBaseline=`top`,o.fillText(l,p+4,m+4)}return{base64:await K(await a.convertToBlob({type:`image/png`})),width:a.width,height:a.height}}function K(e){return new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{let e=r.result.split(`,`)[1];t(e)},r.onerror=()=>n(Error(`Failed to convert blob to base64`)),r.readAsDataURL(e)})}function q(e,t=`image/png`){let n=atob(e),r=new Uint8Array(n.length);for(let e=0;e<n.length;e++)r[e]=n.charCodeAt(e);return new Blob([r],{type:t})}function ie(e){return`return (\n${e}\n);`}function ae(e){try{return Function(e),!0}catch(e){return!(e instanceof SyntaxError)}}async function oe(e,t){let n=(await O.evaluateScript(e,`(() => ({
1
+ var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r},n=class extends Error{code;details;constructor(e,t,n){super(t),this.name=`CDPControllerError`,this.code=e,this.details=n}};function r(e,t){let n=e instanceof Error?e.message:String(e),r=n.trim();if(r.startsWith(`{`)&&r.endsWith(`}`))try{let n=JSON.parse(r);if(n&&typeof n.message==`string`&&n.message.length>0){let r=Error(n.message,{cause:e});return typeof n.code==`number`&&(r.cdpCode=n.code),t&&(r.cdpMethod=t),r}}catch{}return e instanceof Error?e:Error(n)}var i={alt:1,ctrl:2,control:2,meta:4,cmd:4,command:4,win:4,windows:4,shift:8},a={enter:{key:`Enter`,code:`Enter`,keyCode:13,text:`\r`},tab:{key:`Tab`,code:`Tab`,keyCode:9},escape:{key:`Escape`,code:`Escape`,keyCode:27},backspace:{key:`Backspace`,code:`Backspace`,keyCode:8},delete:{key:`Delete`,code:`Delete`,keyCode:46},arrowup:{key:`ArrowUp`,code:`ArrowUp`,keyCode:38},arrowdown:{key:`ArrowDown`,code:`ArrowDown`,keyCode:40},arrowleft:{key:`ArrowLeft`,code:`ArrowLeft`,keyCode:37},arrowright:{key:`ArrowRight`,code:`ArrowRight`,keyCode:39},home:{key:`Home`,code:`Home`,keyCode:36},end:{key:`End`,code:`End`,keyCode:35},pageup:{key:`PageUp`,code:`PageUp`,keyCode:33},pagedown:{key:`PageDown`,code:`PageDown`,keyCode:34},space:{key:` `,code:`Space`,keyCode:32,text:` `},f1:{key:`F1`,code:`F1`,keyCode:112},f2:{key:`F2`,code:`F2`,keyCode:113},f3:{key:`F3`,code:`F3`,keyCode:114},f4:{key:`F4`,code:`F4`,keyCode:115},f5:{key:`F5`,code:`F5`,keyCode:116},f6:{key:`F6`,code:`F6`,keyCode:117},f7:{key:`F7`,code:`F7`,keyCode:118},f8:{key:`F8`,code:`F8`,keyCode:119},f9:{key:`F9`,code:`F9`,keyCode:120},f10:{key:`F10`,code:`F10`,keyCode:121},f11:{key:`F11`,code:`F11`,keyCode:122},f12:{key:`F12`,code:`F12`,keyCode:123}},o=class e{static SCREENSHOT_TIMEOUT_MS=5e3;targets=new Map;consoleMessages=new Map;networkRequests=new Map;networkEntries=new Map;consoleCallbacks=new Map;networkCallbacks=new Map;screencastCallbacks=new Map;networkRequestStartTimes=new Map;pendingDialogs=new Map;detachReasons=new Map;networkEntrySeq=0;networkBodyBytes=new Map;networkCapture=new Map;networkEventQueue=new Map;static debuggerListenerRegistered=!1;static DEFAULT_PER_BODY_BYTES=65536;static DEFAULT_TOTAL_BODY_BYTES=2097152;static STATIC_ASSET_TYPES=new Set([`image/png`,`image/jpeg`,`image/gif`,`image/webp`,`image/svg+xml`,`image/x-icon`,`font/woff`,`font/woff2`,`font/ttf`,`font/otf`,`application/font-woff`,`application/font-woff2`,`text/css`,`application/javascript`,`text/javascript`,`application/x-javascript`]);static BINARY_TYPES=new Set([`image/png`,`image/jpeg`,`image/gif`,`image/webp`,`image/x-icon`,`font/woff`,`font/woff2`,`font/ttf`,`font/otf`,`application/font-woff`,`application/font-woff2`,`application/octet-stream`,`application/pdf`,`application/zip`,`audio/mpeg`,`audio/wav`,`audio/ogg`,`video/mp4`,`video/webm`,`video/ogg`]);async attach(e){if(this.targets.has(e))return;let t={tabId:e};try{await chrome.debugger.attach(t,`1.3`)}catch(t){let r=t instanceof Error?t.message:String(t);throw/already attached/i.test(r)?new n(`debugger_busy`,`Another debugger already controls tab ${e}. Close DevTools or the competing debugger and retry.`,{tabId:e}):r.includes(`Cannot access`)||r.includes(`Cannot attach`)?new n(`restricted_target`,`Cannot control this page. Chrome restricts automation on chrome://, extensions, and web store pages.`,{tabId:e}):new n(`debugger_attach_failed`,`Failed to attach debugger: ${r}`,{tabId:e})}this.targets.set(e,t),this.detachReasons.delete(e),this.setupEventListener(),this.consoleMessages.set(e,[]),this.networkRequests.set(e,[]);try{await this.send(e,`Page.enable`)}catch{}}isAttached(e){return this.targets.has(e)}async detach(e){let t=this.targets.get(e),r;if(t){try{await chrome.debugger.detach(t)}catch(e){r=e instanceof Error?e.message:String(e),console.warn(`[CDPController] Error detaching:`,e)}this.targets.delete(e),this.consoleMessages.delete(e),this.networkRequests.delete(e),this.networkEntries.delete(e),this.networkBodyBytes.delete(e),this.networkCapture.delete(e),this.consoleCallbacks.delete(e),this.networkCallbacks.delete(e),this.notifyScreencastError(e,new n(`debugger_detached`,`Debugger detached from tab ${e}`,{tabId:e})),this.screencastCallbacks.delete(e),this.pendingDialogs.delete(e),this.clearRequestStartTimes(e),this.detachReasons.delete(e)}return r?{success:!1,error:r}:{success:!0}}async detachAll(){for(let e of this.targets.keys())await this.detach(e)}setupEventListener(){e.debuggerListenerRegistered||(e.debuggerListenerRegistered=!0,chrome.debugger.onEvent.addListener((e,t,n)=>{let r=e.tabId;r&&this.targets.has(r)&&this.enqueueCDPEvent(r,t,n)}),chrome.debugger.onDetach.addListener((e,t)=>{let r=e.tabId;r&&this.targets.has(r)&&(this.detachReasons.set(r,t||`unknown`),this.targets.delete(r),this.consoleMessages.delete(r),this.networkRequests.delete(r),this.networkEntries.delete(r),this.networkBodyBytes.delete(r),this.networkCapture.delete(r),this.consoleCallbacks.delete(r),this.networkCallbacks.delete(r),this.notifyScreencastError(r,new n(`debugger_detached`,`Debugger detached from tab ${r}: ${t||`unknown reason`}`,{tabId:r,reason:t||`unknown`})),this.screencastCallbacks.delete(r),this.pendingDialogs.delete(r),this.clearRequestStartTimes(r))}))}requestStartKey(e,t){return`${e}:${t}`}clearRequestStartTimes(e){let t=`${e}:`;for(let e of this.networkRequestStartTimes.keys())e.startsWith(t)&&this.networkRequestStartTimes.delete(e)}enqueueCDPEvent(e,t,n){let r=(this.networkEventQueue.get(e)||Promise.resolve()).catch(()=>void 0).then(()=>this.handleCDPEvent(e,t,n)).catch(()=>void 0);this.networkEventQueue.set(e,r),r.finally(()=>{this.networkEventQueue.get(e)===r&&this.networkEventQueue.delete(e)})}async drainNetworkEvents(e){await this.networkEventQueue.get(e)}async handleCDPEvent(e,t,n){switch(t){case`Runtime.consoleAPICalled`:this.handleRuntimeConsole(e,n);break;case`Runtime.exceptionThrown`:this.handleRuntimeException(e,n);break;case`Network.requestWillBeSent`:this.handleNetworkRequest(e,n);break;case`Network.responseReceived`:this.handleNetworkResponse(e,n);break;case`Network.loadingFailed`:this.handleNetworkFailed(e,n);break;case`Network.loadingFinished`:await this.handleLoadingFinished(e,n);break;case`Page.javascriptDialogOpening`:this.handleDialogOpening(e,n);break;case`Page.javascriptDialogClosed`:this.pendingDialogs.delete(e);break;case`Page.screencastFrame`:await this.handleScreencastFrame(e,n)}}async handleScreencastFrame(e,t){let n=Number(t?.sessionId);if(!Number.isInteger(n))return;try{await this.send(e,`Page.screencastFrameAck`,{sessionId:n})}catch(t){this.notifyScreencastError(e,t instanceof Error?t:Error(String(t)));return}let r=this.screencastCallbacks.get(e);if(!r)return;let i={data:typeof t?.data==`string`?t.data:``,metadata:t?.metadata,sessionId:n};for(let e of r.values())try{e.onFrame(i)}catch{}}notifyScreencastError(e,t){let n=this.screencastCallbacks.get(e);if(n)for(let e of n.values())try{e.onError(t)}catch{}}handleRuntimeConsole(e,t){let n=this.consoleMessages.get(e)||[],r=(t.args||[]).map(e=>e.value===void 0?e.description?e.description:``:String(e.value)).join(` `),i=t.stackTrace?.callFrames?.[0],a={type:t.type||`log`,text:r,timestamp:t.timestamp||Date.now(),url:i?.url,line:i?.lineNumber};n.push(a),n.length>1e3&&n.shift(),this.consoleMessages.set(e,n);let o=this.consoleCallbacks.get(e);if(o)for(let e of o.values())e(a)}handleRuntimeException(e,t){let n=this.consoleMessages.get(e)||[],r=t.exceptionDetails;if(!r)return;let i={type:`exception`,text:r.exception?.description||r.text||`Unknown exception`,timestamp:r.timestamp||Date.now(),url:r.url,line:r.lineNumber};n.push(i),n.length>1e3&&n.shift(),this.consoleMessages.set(e,n);let a=this.consoleCallbacks.get(e);if(a)for(let e of a.values())e(i)}handleNetworkRequest(e,t){let n=this.networkRequests.get(e)||[],r=t.request;if(!r)return;let i=t.timestamp?t.timestamp*1e3:Date.now();this.networkRequestStartTimes.set(this.requestStartKey(e,t.requestId),i);let a={};if(r.headers)for(let[e,t]of Object.entries(r.headers))a[e]=String(t);n.push({requestId:t.requestId,url:r.url,method:r.method,type:t.type,timestamp:i,requestHeaders:a,requestBody:r.postData}),n.length>500&&n.shift(),this.networkRequests.set(e,n),this.networkEntries.has(e)||this.networkEntries.set(e,new Map);let o=this.networkEntries.get(e),s=`r_${i}_${++this.networkEntrySeq}`,c={};if(r.headers)for(let[e,t]of Object.entries(r.headers))c[e]=String(t);let l=r.postData,u=l?l.length:void 0,d={id:s,ts:i,method:r.method,url:r.url,origin:this.extractOrigin(r.url),requestHeaders:c,requestBody:l,requestBodySize:u,tabId:e,tabUrl:t.documentURL,type:t.type,flags:[],bodyCapture:{mode:this.networkCapture.get(e)?.mode||`none`,complete:!1,reason:`pending`},_requestId:t.requestId,_responseReceived:!1,_loadingFinished:!1};if(o.size>500){let e=o.keys().next().value;e&&o.delete(e)}o.set(t.requestId,d)}handleNetworkResponse(e,t){let n=(this.networkRequests.get(e)||[]).find(e=>e.requestId===t.requestId);if(n){if(n.status=t.response?.status,n.mimeType=t.response?.mimeType,t.response?.headers){let e={};for(let[n,r]of Object.entries(t.response.headers))e[n]=String(r);n.responseHeaders=e}let r=this.networkCallbacks.get(e);if(r){let i=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),a=Date.now(),o=i?Math.round(a-i):void 0;for(let e of r.values())e({method:n.method,url:n.url,status:n.status,duration:o,timestamp:a})}}let r=this.networkEntries.get(e)?.get(t.requestId);if(r&&t.response){let n=t.response,i=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),a=t.timestamp?t.timestamp*1e3:Date.now();i&&(r.ttfb=Math.round(a-i)),r.status=n.status,r.statusText=n.statusText,r.mimeType=n.mimeType;let o={};if(n.headers)for(let[e,t]of Object.entries(n.headers))o[e]=String(t);r.responseHeaders=o,this.isBinaryType(n.mimeType)&&r.flags.push(`binary`),(n.mimeType?.includes(`protobuf`)||n.mimeType?.includes(`x-protobuf`)||n.mimeType?.includes(`application/grpc`))&&r.flags.push(`protobuf`),r._responseReceived=!0}}handleNetworkFailed(e,t){let n=(this.networkRequests.get(e)||[]).find(e=>e.requestId===t.requestId);if(n&&!n.status){n.status=0;let r=this.networkCallbacks.get(e);if(r){let i=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),a=Date.now(),o=i?Math.round(a-i):void 0;this.networkRequestStartTimes.delete(this.requestStartKey(e,t.requestId));for(let e of r.values())e({method:n.method,url:n.url,status:0,duration:o,timestamp:a})}}let r=this.networkEntries.get(e)?.get(t.requestId);if(r){let n=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),i=t.timestamp?t.timestamp*1e3:Date.now();n&&(r.duration=Math.round(i-n)),this.networkRequestStartTimes.delete(this.requestStartKey(e,t.requestId)),r.status=0,r.flags.push(`failed`),r._loadingFinished=!0}}handleDialogOpening(e,t){this.pendingDialogs.set(e,{type:t.type,message:t.message,defaultPrompt:t.defaultPrompt,timestamp:Date.now()})}async handleLoadingFinished(e,t){let n=(this.networkRequests.get(e)||[]).find(e=>e.requestId===t.requestId);if(n){let r=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),i=t.timestamp?t.timestamp*1e3:Date.now();r&&(n.duration=Math.round(i-r))}let r=this.networkEntries.get(e)?.get(t.requestId);if(!r)return;let i=this.networkRequestStartTimes.get(this.requestStartKey(e,t.requestId)),a=t.timestamp?t.timestamp*1e3:Date.now();i&&(r.duration=Math.round(a-i)),this.networkRequestStartTimes.delete(this.requestStartKey(e,t.requestId)),r.responseBodySize=t.encodedDataLength,r._loadingFinished=!0;let o=this.networkCapture.get(e)||{mode:`none`,perBodyBytes:0,totalBytes:0},s=Math.max(0,Number(t.encodedDataLength)||0),c=null;if(o.mode===`none`?c=`disabled`:o.mode===`text`&&(this.isStaticAsset(r.mimeType)||this.isBinaryType(r.mimeType))?c=`content-mode`:s>o.perBodyBytes?c=`per-body-cap`:(this.networkBodyBytes.get(e)||0)+s>o.totalBytes&&(c=`session-cap`),c){r.bodyCapture={mode:o.mode,complete:!1,reason:c},c.endsWith(`cap`)&&r.flags.push(`truncated`);return}try{let i=await this.send(e,`Network.getResponseBody`,{requestId:t.requestId}),a=typeof i.body==`string`?i.body:``,s=i.base64Encoded?Math.ceil(a.length*.75):new TextEncoder().encode(a).byteLength;if(s>o.perBodyBytes||(this.networkBodyBytes.get(e)||0)+s>o.totalBytes){r.flags.push(`truncated`),r.bodyCapture={mode:o.mode,complete:!1,reason:s>o.perBodyBytes?`per-body-cap`:`session-cap`};return}if(i.base64Encoded&&o.mode===`all`)r.responseBody=a,r.responseBodyEncoding=`base64`;else if(i.base64Encoded)try{r.responseBody=atob(a)}catch{r.bodyCapture={mode:o.mode,complete:!1,reason:`decode-failed`};return}else r.responseBody=a;this.networkBodyBytes.set(e,(this.networkBodyBytes.get(e)||0)+s),r.bodyCapture={mode:o.mode,complete:!0,capturedBytes:s},n&&(n.responseBody=r.responseBody)}catch{r.bodyCapture={mode:o.mode,complete:!1,reason:`unavailable`}}}extractOrigin(e){try{return new URL(e).origin}catch{return``}}isStaticAsset(t){return t?e.STATIC_ASSET_TYPES.has(t):!1}isBinaryType(t){return t?e.BINARY_TYPES.has(t):!1}async enableConsoleTracking(e){await this.ensureAttached(e);try{await this.send(e,`Runtime.enable`)}catch{}}async enableNetworkTracking(t,n={}){await this.ensureAttached(t);let r=n.bodyMode||`text`,i=n.perBodyBytes??e.DEFAULT_PER_BODY_BYTES,a=n.totalBytes??e.DEFAULT_TOTAL_BODY_BYTES;if(!Number.isInteger(i)||i<0||!Number.isInteger(a)||a<0)throw Error(`network body caps must be non-negative integers`);this.networkCapture.set(t,{mode:r,perBodyBytes:i,totalBytes:a}),this.networkBodyBytes.has(t)||this.networkBodyBytes.set(t,0);try{await this.send(t,`Network.enable`,{maxPostDataSize:65536})}catch{}}async disableNetworkTracking(e){if(await this.drainNetworkEvents(e),this.networkCapture.delete(e),this.networkBodyBytes.delete(e),!this.networkCallbacks.get(e)?.size)try{await this.send(e,`Network.disable`)}catch{}}async handleDialog(e,t,n){try{return await this.send(e,`Page.handleJavaScriptDialog`,{accept:t,promptText:n}),this.pendingDialogs.delete(e),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}getDialogInfo(e){return this.pendingDialogs.get(e)||null}async emulateNetwork(e,t){await this.ensureAttached(e);let n={offline:{offline:!0,latency:0,downloadThroughput:0,uploadThroughput:0},"slow-3g":{offline:!1,latency:2e3,downloadThroughput:5e4,uploadThroughput:5e4},"fast-3g":{offline:!1,latency:562.5,downloadThroughput:18e4,uploadThroughput:84375},"4g":{offline:!1,latency:100,downloadThroughput:4e6,uploadThroughput:3e6},reset:{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}},r=n[t.toLowerCase().replace(/\s+/g,`-`)];if(!r)return{success:!1,error:`Unknown preset: ${t}. Available: ${Object.keys(n).join(`, `)}`};try{return await this.send(e,`Network.enable`),await this.send(e,`Network.emulateNetworkConditions`,r),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateCPU(e,t){if(await this.ensureAttached(e),t<1)return{success:!1,error:`CPU throttling rate must be >= 1 (1 = no throttle, 4 = 4x slower)`};try{return await this.send(e,`Emulation.setCPUThrottlingRate`,{rate:t}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateGeolocation(e,t,n,r){await this.ensureAttached(e);try{return await this.send(e,`Emulation.setGeolocationOverride`,{latitude:t,longitude:n,accuracy:r||100}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async clearGeolocation(e){await this.ensureAttached(e);try{return await this.send(e,`Emulation.clearGeolocationOverride`),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateDevice(e,t){await this.ensureAttached(e);try{return await this.send(e,`Emulation.setDeviceMetricsOverride`,{width:t.width,height:t.height,deviceScaleFactor:t.deviceScaleFactor,mobile:t.mobile}),t.userAgent&&await this.send(e,`Emulation.setUserAgentOverride`,{userAgent:t.userAgent}),t.touch&&await this.send(e,`Emulation.setTouchEmulationEnabled`,{enabled:!0,maxTouchPoints:5}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async clearDeviceEmulation(e){await this.ensureAttached(e);try{return await this.send(e,`Emulation.clearDeviceMetricsOverride`),await this.send(e,`Emulation.setUserAgentOverride`,{userAgent:``}),await this.send(e,`Emulation.setTouchEmulationEnabled`,{enabled:!1}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateViewport(e,t){await this.ensureAttached(e);try{let n=await this.getViewportSize(e);return await this.send(e,`Emulation.setDeviceMetricsOverride`,{width:t.width||n.width,height:t.height||n.height,deviceScaleFactor:t.deviceScaleFactor||1,mobile:t.mobile||!1}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateTouch(e,t){await this.ensureAttached(e);try{return await this.send(e,`Emulation.setTouchEmulationEnabled`,{enabled:t,maxTouchPoints:t?5:0}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async startPerformanceTrace(e,t){await this.ensureAttached(e);try{return await this.send(e,`Performance.enable`),await this.send(e,`Tracing.start`,{categories:t?.join(`,`)||`devtools.timeline,v8.execute,disabled-by-default-devtools.timeline`,transferMode:`ReturnAsStream`}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async stopPerformanceTrace(e){await this.ensureAttached(e);try{await this.send(e,`Performance.enable`);let t=await this.send(e,`Performance.getMetrics`);await this.send(e,`Tracing.end`),await this.send(e,`Performance.disable`);let n={};for(let e of t.metrics||[])n[e.name]=e.value;return{success:!0,metrics:n}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async getPerformanceMetrics(e){await this.ensureAttached(e);try{await this.send(e,`Performance.enable`);let t=await this.send(e,`Performance.getMetrics`);await this.send(e,`Performance.disable`);let n={};for(let e of t.metrics||[])n[e.name]=e.value;return{success:!0,metrics:n}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async setFileInputBySelector(e,t,n){await this.ensureAttached(e);try{await this.send(e,`DOM.enable`);let r=await this.send(e,`DOM.getDocument`),i=await this.send(e,`DOM.querySelector`,{nodeId:r.root.nodeId,selector:t});return i.nodeId?(await this.send(e,`DOM.setFileInputFiles`,{nodeId:i.nodeId,files:n}),{success:!0}):{success:!1,error:`Could not find element by selector`}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async waitForLoad(e,t=3e4){await this.ensureAttached(e);let n=Date.now();try{for(;Date.now()-n<t;){let t=(await this.send(e,`Runtime.evaluate`,{expression:`document.readyState`,returnByValue:!0})).result?.value;if(t===`complete`)return{success:!0,readyState:t};await new Promise(e=>setTimeout(e,100))}return{success:!1,error:`Timeout waiting for page load (${t}ms)`}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async getFrames(e){await this.ensureAttached(e);try{await this.send(e,`Page.enable`);let t=await this.send(e,`Page.getFrameTree`),n=[],r=(e,t)=>{if(n.push({frameId:e.frame.id,url:e.frame.url,name:e.frame.name||``,parentId:t}),e.childFrames)for(let t of e.childFrames)r(t,e.frame.id)};return r(t.frameTree),{success:!0,frames:n}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async evaluateInFrame(e,t,n){await this.ensureAttached(e);try{let r=await this.send(e,`Page.createIsolatedWorld`,{frameId:t,worldName:`surf-isolated`}),i=`JSON.stringify((function() { ${n} })())`,a=await this.send(e,`Runtime.evaluate`,{expression:i,contextId:r.executionContextId,returnByValue:!0,awaitPromise:!0});if(a.exceptionDetails)return{success:!1,error:a.exceptionDetails.text||a.exceptionDetails.exception?.description||`Evaluation failed`};try{return{success:!0,result:JSON.parse(a.result?.value)}}catch{return{success:!0,result:a.result?.value}}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}getConsoleMessages(e,t){let n=this.consoleMessages.get(e)||[];if(t?.onlyErrors&&(n=n.filter(e=>e.type===`error`||e.type===`exception`)),t?.pattern)try{let e=new RegExp(t.pattern,`i`);n=n.filter(t=>e.test(t.text))}catch{n=n.filter(e=>e.text.includes(t.pattern))}return t?.limit&&(n=n.slice(-t.limit)),[...n]}clearConsoleMessages(e){this.consoleMessages.set(e,[])}getNetworkRequests(e,t){let n=this.networkRequests.get(e)||[];return t?.urlPattern&&(n=n.filter(e=>e.url.includes(t.urlPattern))),t?.limit&&(n=n.slice(-t.limit)),[...n]}clearNetworkRequests(e){this.networkRequests.set(e,[]),this.networkEntries.set(e,new Map),this.networkBodyBytes.set(e,0)}getNetworkEntries(e,t){let n=this.networkEntries.get(e),r=[];return r=n&&n.size>0?Array.from(n.values()):(this.networkRequests.get(e)||[]).map((t,n)=>({id:`r_${t.timestamp}_${n}`,ts:t.timestamp,method:t.method,url:t.url,origin:this.extractOrigin(t.url),requestHeaders:{},tabId:e,type:t.type,status:t.status,flags:[],bodyCapture:{mode:`none`,complete:!1,reason:`legacy`},_requestId:t.requestId,_responseReceived:!0,_loadingFinished:!0})),t?.includeStatic||(r=r.filter(e=>!this.isStaticAsset(e.mimeType))),t?.urlPattern&&(r=r.filter(e=>e.url.includes(t.urlPattern))),t?.limit&&(r=r.slice(-t.limit)),r}getNetworkEntry(e,t){return this.networkEntries.get(e)?.get(t)||null}async getResponseBody(e,t){await this.ensureAttached(e);try{let n=await this.send(e,`Network.getResponseBody`,{requestId:t});return{success:!0,body:n.body,base64Encoded:n.base64Encoded}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}subscribeToConsole(e,t,n){this.consoleCallbacks.has(e)||this.consoleCallbacks.set(e,new Map),this.consoleCallbacks.get(e).set(t,n)}unsubscribeFromConsole(e,t){let n=this.consoleCallbacks.get(e);n&&(n.delete(t),n.size===0&&this.consoleCallbacks.delete(e))}subscribeToNetwork(e,t,n){this.networkCallbacks.has(e)||this.networkCallbacks.set(e,new Map),this.networkCallbacks.get(e).set(t,n)}unsubscribeFromNetwork(e,t){let n=this.networkCallbacks.get(e);n&&(n.delete(t),n.size===0&&this.networkCallbacks.delete(e))}subscribeToScreencast(e,t,n,r=()=>{}){this.screencastCallbacks.has(e)||this.screencastCallbacks.set(e,new Map),this.screencastCallbacks.get(e).set(t,{onFrame:n,onError:r})}unsubscribeFromScreencast(e,t){let n=this.screencastCallbacks.get(e);n&&(n.delete(t),n.size===0&&this.screencastCallbacks.delete(e))}async startScreencast(e,t={}){return this.send(e,`Page.startScreencast`,{format:t.format||`jpeg`,quality:t.quality??80,everyNthFrame:t.everyNthFrame??1})}async stopScreencast(e){return this.send(e,`Page.stopScreencast`)}async compileScript(e,t){await this.ensureAttached(e);try{await this.send(e,`Runtime.enable`)}catch{}let n=await this.send(e,`Runtime.compileScript`,{expression:t,sourceURL:``,persistScript:!1});return n?.exceptionDetails?{parses:!1,error:n.exceptionDetails.exception?.description||n.exceptionDetails.text||`SyntaxError`}:{parses:!0}}async evaluateScript(e,t){await this.ensureAttached(e);try{await this.send(e,`Runtime.enable`)}catch{}return this.send(e,`Runtime.evaluate`,{expression:t,returnByValue:!0,awaitPromise:!0,timeout:3e4})}async send(e,t,n){await this.ensureAttached(e);let i=this.targets.get(e);try{return await chrome.debugger.sendCommand(i,t,n)}catch(e){throw r(e,t)}}async sendCommand(e,t,n){return this.send(e,t,n)}async ensureAttached(e){let t=this.detachReasons.get(e);if(t)throw this.detachReasons.delete(e),new n(`debugger_detached`,`Debugger detached from tab ${e}: ${t}. Retry after closing any competing debugger.`,{tabId:e,reason:t});this.targets.has(e)||await this.attach(e)}async getViewportSize(e){let t=await this.send(e,`Page.getLayoutMetrics`),n=t.visualViewport||t.layoutViewport;return{width:Math.round(n.clientWidth),height:Math.round(n.clientHeight)}}async captureScreenshot(e){return this.withScreenshotDeadline(e,(async()=>{let t=await this.send(e,`Page.captureScreenshot`,{format:`png`,captureBeyondViewport:!1}),{width:n,height:r}=await this.getViewportSize(e);return{base64:t.data,width:n,height:r}})())}async withScreenshotDeadline(t,r){let i,a=new Promise((r,a)=>{i=setTimeout(()=>a(new n(`screenshot_timeout`,`Screenshot capture timed out after ${e.SCREENSHOT_TIMEOUT_MS}ms`,{tabId:t,timeoutMs:e.SCREENSHOT_TIMEOUT_MS})),e.SCREENSHOT_TIMEOUT_MS)});try{return await Promise.race([r,a])}finally{i!==void 0&&clearTimeout(i)}}async captureRegion(e,t,n,r,i){return{base64:(await this.withScreenshotDeadline(e,this.send(e,`Page.captureScreenshot`,{format:`png`,clip:{x:t,y:n,width:r,height:i,scale:1}}))).data,width:r,height:i}}async dispatchMouseEvent(e,t,n,r,i={}){let a={type:t,x:Math.round(n),y:Math.round(r),modifiers:i.modifiers||0};(t===`mousePressed`||t===`mouseReleased`||t===`mouseMoved`)&&(a.button=i.button||`none`,(t===`mousePressed`||t===`mouseReleased`)&&(a.clickCount=i.clickCount||1)),t!==`mouseWheel`&&(a.buttons=i.buttons??0),t===`mouseWheel`&&(a.deltaX=i.deltaX||0,a.deltaY=i.deltaY||0),await this.send(e,`Input.dispatchMouseEvent`,a)}async click(e,t,n,r=`left`,i=1,a=0){let o=r===`left`?1:r===`right`?2:r===`middle`?4:0;await this.dispatchMouseEvent(e,`mouseMoved`,t,n,{button:`none`,buttons:0,modifiers:a}),await new Promise(e=>setTimeout(e,100));for(let s=1;s<=i;s++)await this.dispatchMouseEvent(e,`mousePressed`,t,n,{button:r,buttons:o,clickCount:s,modifiers:a}),await new Promise(e=>setTimeout(e,12)),await this.dispatchMouseEvent(e,`mouseReleased`,t,n,{button:r,buttons:0,clickCount:s,modifiers:a}),s<i&&await new Promise(e=>setTimeout(e,100))}async rightClick(e,t,n,r=0){await this.click(e,t,n,`right`,1,r)}async doubleClick(e,t,n,r=0){await this.click(e,t,n,`left`,2,r)}async tripleClick(e,t,n,r=0){await this.click(e,t,n,`left`,3,r)}async hover(e,t,n){await this.dispatchMouseEvent(e,`mouseMoved`,t,n,{button:`none`,buttons:0})}async drag(e,t,n,r,i,a=0){await this.dispatchMouseEvent(e,`mouseMoved`,t,n,{button:`none`,buttons:0}),await new Promise(e=>setTimeout(e,50)),await this.dispatchMouseEvent(e,`mousePressed`,t,n,{button:`left`,buttons:1,clickCount:1,modifiers:a}),await new Promise(e=>setTimeout(e,50)),await this.dispatchMouseEvent(e,`mouseMoved`,r,i,{button:`left`,buttons:1,modifiers:a}),await new Promise(e=>setTimeout(e,50)),await this.dispatchMouseEvent(e,`mouseReleased`,r,i,{button:`left`,buttons:0,clickCount:1,modifiers:a})}async scroll(e,t,n,r,i){await this.dispatchMouseEvent(e,`mouseWheel`,t,n,{deltaX:r,deltaY:i})}async type(e,t){for(let n of t)if(n===`
2
+ `||n===`\r`)await this.pressKey(e,`Enter`);else if(this.getKeyDefinition(n)){let t=this.requiresShift(n);await this.pressKey(e,n,t?i.shift:0)}else await this.send(e,`Input.insertText`,{text:n})}requiresShift(e){return/[A-Z!@#$%^&*()_+{}|:"<>?~]/.test(e)}async dispatchKeyEvent(e,t,n,r=0){await this.send(e,`Input.dispatchKeyEvent`,{type:n.text?t:t===`keyDown`?`rawKeyDown`:t,key:n.key,code:n.code,windowsVirtualKeyCode:n.keyCode,modifiers:r,text:n.text??``,unmodifiedText:n.text??``,location:n.location??0})}async pressKey(e,t,n=0){let r=this.getKeyDefinition(t);if(!r)throw Error(`Unknown key: ${t}`);await this.dispatchKeyEvent(e,`keyDown`,r,n),await this.dispatchKeyEvent(e,`keyUp`,r,n)}async pressKeyChord(e,t){let n=t.toLowerCase().split(`+`),r=[],a=``;for(let e of n)e in i?r.push(e):a=e;let o=0;for(let e of r)o|=i[e]||0;a&&await this.pressKey(e,a,o)}getKeyDefinition(e){let t=e.toLowerCase();if(a[t])return a[t];if(e.length===1){let t=e.toUpperCase().charCodeAt(0);return{key:e,code:`Key${e.toUpperCase()}`,keyCode:t,text:e}}return null}parseModifiers(e){if(!e)return 0;let t=0,n=e.toLowerCase().split(`+`);for(let e of n){let n=e.trim();n in i&&(t|=i[n])}return t}},s=!1,c=!1,l=[];chrome.storage.local.get(`debugMode`).then(({debugMode:e})=>{if(s=!!e,c=!0,s)for(let e of l)console.log(`[Surf]`,...e);l.length=0}),chrome.storage.onChanged.addListener((e,t)=>{t===`local`&&e.debugMode&&(s=!!e.debugMode.newValue)});function u(...e){if(!c){l.push(e);return}s&&console.log(`[Surf]`,...e)}function d(e){try{let t=new URL(e);return t.origin===`null`?null:t.origin}catch{return null}}function f(e){return e===``||e===`about:blank`||e.startsWith(`about:blank?`)||e===`about:srcdoc`}function p(e){return e!==null&&!e.split(/\s+/).includes(`allow-scripts`)}function m(e,t){return f(e)&&f(t)?!0:e===t}function h(e,t=80){return e.length<=t?e:`${e.slice(0,t-3)}...`}function ee(e){return e.name||e.id||``}function te(e){let t=d(e.mainPage.href),n=e.cdpFramesAvailable!==!1,r=e.extensionFrames.filter(e=>e.parentFrameId!==-1),i=[],a=e.extensionFrames.map(e=>{let n=d(e.url),i=e.parentFrameId===-1;return{...e,isMain:i,switchIndex:i?null:r.findIndex(t=>t.frameId===e.frameId),origin:n,crossOrigin:n!==null&&t!==null&&n!==t}}),o=e.cdpFrames.map(e=>{let n=d(e.url);return{...e,isMain:e.parentId===void 0,origin:n,crossOrigin:n!==null&&t!==null&&n!==t,extensionFrameIds:r.filter(t=>e.parentId!==void 0&&!f(e.url)&&m(t.url,e.url)).map(e=>e.frameId)}}),s=e.domIframes.map(n=>{let i=n.srcdoc||f(n.src),a=i?null:d(n.src),o=e=>!i&&m(e,n.src),s=ee(n),c=e=>e.parentId!==void 0&&(o(e.url)||s!==``&&e.name===s);return{...n,shadowHost:n.shadowHost??null,origin:a,crossOrigin:a!==null&&t!==null&&a!==t,blank:i,zeroSize:n.rect.width<=0||n.rect.height<=0,scriptsBlocked:p(n.sandbox),extensionFrameIds:r.filter(e=>o(e.url)).map(e=>e.frameId),cdpFrameIds:e.cdpFrames.filter(c).map(e=>e.frameId)}}),c=n?s.filter(e=>e.blank&&e.cdpFrameIds.length===0):[];c.length>0&&i.push(`${c.length} iframe(s) have no URL (about:blank or srcdoc): DOM indexes ${c.map(e=>e.domIndex).join(`, `)}. No CDP frame carries their name or id, so their content cannot be matched; give them a name or id. For frame.switch --index, use extension-inventory indexes, not DOM indexes.`);for(let t of s)if(t.scriptsBlocked&&i.push(`iframe ${t.domIndex} (${h(t.src)||`no src`}) is sandboxed without allow-scripts: no content script or page script runs inside it.`),t.zeroSize&&i.push(`iframe ${t.domIndex} (${h(t.src)||`no src`}) is rendered at ${t.rect.width}x${t.rect.height}: hidden, collapsed, or not yet laid out.`),!t.blank&&t.extensionFrameIds.length===0&&i.push(`iframe ${t.domIndex} (${h(t.src)}) has no matching extension frame: it may still be loading, be blocked, or have navigated elsewhere.`),t.extensionFrameIds.length>1&&i.push(`iframe ${t.domIndex} (${h(t.src)}) matches ${t.extensionFrameIds.length} extension frames by URL (${t.extensionFrameIds.join(`, `)}); use frame.switch --index to pick one.`),t.cdpFrameIds.length>1&&i.push(`iframe ${t.domIndex} (${h(t.src)}) matches ${t.cdpFrameIds.length} CDP frames (${t.cdpFrameIds.join(`, `)}); correlation is ambiguous, so frame.js requires an explicit CDP frame id.`),n&&!t.blank&&t.extensionFrameIds.length>0&&t.cdpFrameIds.length===0){let n=t.extensionFrameIds.every(t=>e.extensionFrames.find(e=>e.frameId===t)?.contentScriptReachable===!0);t.crossOrigin?i.push(`iframe ${t.domIndex} (${h(t.src)}) is out-of-process: it is missing from this tab's CDP frame tree, so frame.js cannot reach it; ${n?`its content script answers, so frame.switch, page.read and click by ref work there.`:`its content script is unreachable too, so nothing in this tab can drive it.`}`):i.push(`iframe ${t.domIndex} (${h(t.src)}) has an extension frame but no CDP frame: it is still loading, navigated, or runs out of process; retry, or use frame.switch.`)}for(let e of r){let t=s.filter(t=>t.extensionFrameIds.includes(e.frameId));t.length>1&&i.push(`extension frame ${e.frameId} (${h(e.url)}) matches ${t.length} DOM iframes (${t.map(e=>e.domIndex).join(`, `)}); correlation is ambiguous.`);let n=o.filter(t=>t.extensionFrameIds.includes(e.frameId));n.length>1&&i.push(`extension frame ${e.frameId} (${h(e.url)}) matches ${n.length} CDP frames (${n.map(e=>e.frameId).join(`, `)}) by URL; correlation is ambiguous.`)}for(let e of o){if(e.isMain)continue;let t=s.filter(t=>t.cdpFrameIds.includes(e.frameId));t.length>1&&i.push(`CDP frame ${e.frameId} (${h(e.url)}) matches ${t.length} DOM iframes (${t.map(e=>e.domIndex).join(`, `)}); correlation is ambiguous.`),e.extensionFrameIds.length>1&&i.push(`CDP frame ${e.frameId} (${h(e.url)}) matches ${e.extensionFrameIds.length} extension frames by URL (${e.extensionFrameIds.join(`, `)}); correlation is ambiguous.`)}for(let e of a)if(!e.isMain){if(!e.contentScriptReachable){let t=e.contentScriptError?` (${e.contentScriptError})`:``;i.push(`extension frame ${e.frameId} (${h(e.url)}) has no reachable content script${t}: page.read, click by ref and frame.switch will not work inside it; frame.js with its CDP frame id may.`)}e.errorOccurred&&i.push(`extension frame ${e.frameId} (${h(e.url)}) reported a navigation error.`)}let l=o.filter(e=>!e.isMain&&!f(e.url)&&e.extensionFrameIds.length===0);for(let e of l)i.push(`CDP frame ${e.frameId} (${h(e.url)}) is not reported by chrome.webNavigation: likely out-of-process or detached; only frame.js can reach it.`);let u=s.filter(e=>e.crossOrigin).length;if(u>0&&i.push(`${u} cross-origin iframe(s): selectors from the main page do not reach them; switch with frame.switch first.`),s.length!==r.length){let e=r.filter(e=>e.parentFrameId!==0).length,t=s.filter(e=>e.shadowHost).length,n=s.length===r.length-e;i.push(`DOM lists ${s.length} iframe(s)${t>0?` (${t} inside open shadow roots)`:``} but the extension sees ${r.length} child frame(s)${e>0?`, ${e} of them nested below another frame`:``}; ${n?`the nested frames account for the difference.`:`the rest live in closed shadow roots, were created after the snapshot, or are detached.`}`)}return{mainPage:{...e.mainPage,origin:t},counts:{domIframes:s.length,extensionFrames:a.length,cdpFrames:o.length},domIframes:s,extensionFrames:a,cdpFrames:o,warnings:i}}var ne=`(() => {
3
+ const describe = (el) => el.tagName.toLowerCase() + (el.id ? "#" + el.id : "") + (el.classList.length ? "." + Array.from(el.classList).slice(0, 2).join(".") : "");
4
+ const found = [];
5
+ // Walk open shadow roots too: querySelectorAll("iframe") on the document
6
+ // misses every frame a custom element renders inside its shadow tree.
7
+ const walk = (root, hostPath) => {
8
+ for (const el of root.querySelectorAll("iframe")) found.push({ el, hostPath });
9
+ for (const host of root.querySelectorAll("*")) {
10
+ if (host.shadowRoot) walk(host.shadowRoot, hostPath ? hostPath + " > " + describe(host) : describe(host));
11
+ }
12
+ };
13
+ walk(document, "");
14
+ const iframes = found.map(({ el, hostPath }, domIndex) => {
15
+ const rect = el.getBoundingClientRect();
16
+ return {
17
+ domIndex,
18
+ shadowHost: hostPath || null,
19
+ src: el.hasAttribute("srcdoc") ? "" : el.src || "",
20
+ srcAttribute: el.getAttribute("src") || "",
21
+ srcdoc: el.hasAttribute("srcdoc"),
22
+ title: el.title || "",
23
+ name: el.getAttribute("name") || "",
24
+ id: el.id || "",
25
+ sandbox: el.hasAttribute("sandbox") ? el.getAttribute("sandbox") : null,
26
+ allow: el.getAttribute("allow") || "",
27
+ rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
28
+ };
29
+ });
30
+ return { href: location.href, title: document.title, iframes };
31
+ })()`,g=[`challenge`,`login`,`not-found`,`error`],re=[`ready`,`empty`];function ie(e){switch(e){case`challenge`:return`page_challenge`;case`login`:return`page_login`;case`not-found`:return`page_not_found`;case`error`:return`page_error`;default:return null}}function ae(e){return e===`ready`||e===`empty`||e===`loading`||g.includes(e)}function oe(e){let t=Array.isArray(e)?e:typeof e==`string`?e.split(`,`):[],n=[];for(let e of t){let t=typeof e==`string`?e.trim():``;if(!ae(t)||!g.includes(t))throw Error(`Invalid --accept state "${String(e)}". Expected one of: challenge, login, not-found, error`);n.includes(t)||n.push(t)}return n}var se=2e4,ce=12e4;function le(e){let t=Number(e.timeoutMs),n=Number(e.intervalMs),r=Number.isFinite(t)&&t>0?Math.min(t,ce):se;return{timeoutMs:r,intervalMs:Math.min(Math.max(Number.isFinite(n)&&n>0?n:400,50),r)}}var ue=e=>new Promise(t=>setTimeout(t,e));async function de(e){let t=e.sleep??ue,n=e.now??Date.now,r=e.accept??[],i=n(),a=0,o={state:`loading`,evidence:[`no probe completed`]};for(;;){o=await e.probe(),a+=1;let s=n()-i;if(e.onPoll?.(o,a,s),re.includes(o.state))return{kind:`settled`,result:o,polls:a,waitedMs:s};if(g.includes(o.state))return{kind:r.includes(o.state)?`accepted`:`negative`,result:o,polls:a,waitedMs:s};let c=e.timeoutMs-(n()-i);if(c<=0)return{kind:`timeout`,result:o,polls:a,waitedMs:n()-i};await t(Math.min(e.intervalMs,c))}}var _=t({initNativeMessaging:()=>D,postToNativeHost:()=>O,sendToNativeHost:()=>me}),v=null,y=null,b=null,x=new Map,fe=0,S=null,C=`surfBrowserInstanceId`,w=`surfBrowserEpoch`;function T(){if(globalThis.crypto?.randomUUID)return globalThis.crypto.randomUUID();let e=new Uint8Array(16);return globalThis.crypto.getRandomValues(e),Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}async function pe(){let e=(await chrome.storage.local.get(C))[C];e||(e=T(),await chrome.storage.local.set({[C]:e}));let t=(await chrome.storage.session.get(w))[w];return t||(t=T(),await chrome.storage.session.set({[w]:t})),{browserInstanceId:e,browserEpoch:t}}async function E(e){let t=await pe();v===e&&e.postMessage({type:`EXTENSION_HELLO`,protocolVersion:2,extensionVersion:chrome.runtime.getManifest().version,capabilities:[`browser-sessions`,`strict-targets`,`keyed-lanes`,`video-recording`],...t})}function D(e,t){y=e,S=t||null,k()}function me(e){return new Promise((t,n)=>{if(!v){n(Error(`Native host not connected`));return}if(e.type===`API_REQUEST`){v.postMessage(e),t({sent:!0});return}let r=++fe;x.set(r,{resolve:t,reject:n}),v.postMessage({...e,id:r}),setTimeout(()=>{x.has(r)&&(x.delete(r),n(Error(`Native host request timeout`)))},1e4)})}function O(e){v&&v.postMessage(e)}function k(){b&&=(clearTimeout(b),null);try{let e=chrome.runtime.connectNative(`surf.browser.host`);v=e,u(`Connecting to native host...`),E(e).catch(e=>u(`Failed to send extension hello:`,e)),e.onMessage.addListener(async t=>{if(u(`Received from native host:`,t.type||t.id),t.type===`HOST_READY`){u(`Native host ready`),E(e).catch(e=>u(`Failed to refresh extension hello:`,e));return}if(t.type?.startsWith(`API_RESPONSE_`)){chrome.runtime.sendMessage(t).catch(()=>{});return}if(t.id&&x.has(t.id)){let{resolve:e}=x.get(t.id);x.delete(t.id),e(t);return}if(y)try{let n=await y(t);if(v!==e){u(`Cannot send response - native host disconnected:`,t.id);return}e.postMessage({id:t.id,...n})}catch(n){if(v!==e){u(`Cannot send error - native host disconnected:`,t.id);return}let r=n;e.postMessage({id:t.id,error:r instanceof Error?r.message:`Unknown error`,errorCode:typeof r?.code==`string`?r.code:void 0,errorDetails:r?.details})}}),e.onDisconnect.addListener(()=>{let t=chrome.runtime.lastError;if(u(`Native host disconnected:`,t?.message||`unknown reason`),v===e){v=null;try{Promise.resolve(S?.()).catch(e=>{u(`Native host disconnect cleanup failed:`,e)})}catch(e){u(`Native host disconnect cleanup failed:`,e)}}for(let e of x.values())e.reject(Error(`Native host disconnected`));x.clear(),t?.message?.includes(`not found`)||(b=setTimeout(k,5e3))})}catch(e){u(`Failed to connect to native host:`,e),b=setTimeout(k,1e4)}}var he=`modulepreload`,ge=function(e){return`/`+e},A={},j=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=ge(t,n),t=s(t),t in A)return;A[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:he,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};u(`Service worker loaded`);var M=new o,N=new Map,P=null;async function _e(){let e=P;if(e)try{await M.stopScreencast(e.tabId)}catch(e){u(`Failed to stop video screencast after native host disconnect:`,e)}finally{M.unsubscribeFromScreencast(e.tabId,e.recorderId),P?.recorderId===e.recorderId&&(P=null)}}function F(e,t){let n=Number(t?.frameId);return Number.isInteger(n)&&n>0?n:0}async function ve(e,t){let n=Number(t);if(!(!Number.isInteger(n)||n<=0)&&!(await chrome.webNavigation.getAllFrames({tabId:e}))?.some(e=>e.frameId===n))throw O({type:`TARGET_EVENT`,event:`frame-reset`,tabId:e,frameId:n,reason:`missing-frame`}),new L(`frame_context_reset`,`Frame context ${n} is no longer available in tab ${e}`,{tabId:e,frameId:n,reason:`missing-frame`,recoveryCommand:`surf frame.list`})}function I(e){return!e||/^(?:about|arc|brave|chrome|chrome-extension|devtools|edge|extension|helium|moz-extension):/i.test(e)}var L=class extends Error{code;details;constructor(e,t,n){super(t),this.name=`BrowserCommandError`,this.code=e,this.details=n}};async function R(e){let t;try{t=await chrome.tabs.get(e)}catch{throw new L(`tab_gone`,`Tab ${e} no longer exists`,{tabId:e})}if(!t.id||t.windowId===void 0)throw new L(`tab_gone`,`Tab ${e} no longer has a browser window`,{tabId:e});return{tabId:t.id,windowId:t.windowId,url:t.url,title:t.title,active:!!t.active,status:t.status,restricted:I(t.url),groupId:t.groupId}}async function z(e,t=!0){let n,r,i=!1;if(e){if(n=await chrome.tabs.query({active:!0,windowId:e}),r=n[0],(!r||I(r.url))&&(n=await chrome.tabs.query({windowId:e}),r=n.find(e=>!I(e.url))),!r?.id&&t){let t=await chrome.tabs.create({windowId:e,url:`data:text/html,<html><head><title>Surf</title></head><body></body></html>`,active:!0});if(!t.id)throw new L(`target_create_failed`,`Failed to create tab in window ${e}`);await W(100),r=t,i=!0}}else n=await chrome.tabs.query({active:!0,lastFocusedWindow:!0}),r=n[0],(!r||I(r.url))&&(n=await chrome.tabs.query({active:!0,currentWindow:!0}),r=n[0]),(!r||I(r.url))&&(n=await chrome.tabs.query({active:!0}),r=n.find(e=>!I(e.url)));if(!r?.id)throw new L(`target_required`,`No active tab found. Use 'surf session.ensure <name> about:blank' or 'surf tab.new <url>'.`);return{tab:r,autoCreated:i}}async function ye(e,t){try{let n=await chrome.tabs.group({tabIds:e});return await chrome.tabGroups.update(n,{title:`Surf: ${t}`,color:`blue`,collapsed:!1}),n}catch{return}}function B(e){let t=e&&typeof e==`object`?e:{},n={};for(let e of[`selector`,`text`,`urlPrefix`,`emptyText`]){let r=t[e];typeof r==`string`&&r.trim()!==``&&(n[e]=r)}return n}async function V(e,t){let n,r,i;try{let t=await chrome.tabs.get(e);n=t.status,i=t.pendingUrl,r=i||t.url}catch{}if(!r||r===`about:blank`)return{state:`loading`,evidence:[`tab URL is ${r||`empty`}`],href:r,tabStatus:n};if(I(r))return{state:`error`,evidence:[`restricted browser or extension page ${r}`],href:r,tabStatus:n};let a;try{a=await chrome.tabs.sendMessage(e,{type:`PAGE_READINESS`,expect:t},{frameId:0})}catch(e){return{state:`loading`,evidence:[`content script unreachable: ${e instanceof Error?e.message:String(e)}`],href:r,tabStatus:n}}if(a?.state)return i&&a.href!==i?{state:`loading`,evidence:[`navigation to ${i} pending; report is from ${a.href}`],href:a.href,tabStatus:n}:{...a,tabStatus:n};if(a?.code===`invalid_selector`)throw new L(`invalid_selector`,String(a.error||`Invalid CSS selector`),{selector:t.selector,tabId:e});return{state:`loading`,evidence:[a?.error?String(a.error):`content script returned no verdict`],href:r,tabStatus:n}}function H(e){let t=e.href?` at ${e.href}`:``,n=e.evidence.length>0?` (${e.evidence.join(`; `)})`:``;return`${e.state}${t}${n}`}async function be(e){let t=await M.evaluateScript(e,ne);if(t.exceptionDetails)throw Error(t.exceptionDetails.exception?.description||t.exceptionDetails.text||`Failed to collect the DOM iframe inventory`);let n=t.result?.value;if(!n||typeof n!=`object`||!Array.isArray(n.iframes))throw Error(`Unexpected DOM iframe inventory result shape`);return n}async function xe(e){let t=await chrome.webNavigation.getAllFrames({tabId:e})??[],n=[];for(let r of t){let t={frameId:r.frameId,parentFrameId:r.parentFrameId,url:r.url,errorOccurred:r.errorOccurred===!0,contentScriptReachable:!1};try{let n=await chrome.tabs.sendMessage(e,{type:`PING`},{frameId:r.frameId});n?.success?(t.contentScriptReachable=!0,t.contentScript={href:n.href,readyState:n.readyState}):t.contentScriptError=n?.error?String(n.error):`no response`}catch(e){t.contentScriptError=e instanceof Error?e.message:String(e)}n.push(t)}return n}var U=new Map,Se=0;function Ce(){return`screenshot_${++Se}_${Date.now()}`}function we(e,t){if(U.set(e,t),U.size>10){let e=U.keys().next().value;e&&U.delete(e)}}function Te(e){return U.get(e)||null}function W(e){return new Promise(t=>setTimeout(t,e))}var Ee=class extends Error{code;constructor(e,t){super(t),this.name=`ProviderUploadError`,this.code=e}};function G(e,t,n){return new Ee(t===`selector`?`attachment_selector_drift`:t===`chooser`?`attachment_chooser_interception`:`attachment_processing`,`${e} attachment ${t===`selector`?`UI selector drift`:t===`chooser`?`chooser interception`:`processing`}: ${n}`)}var K={gemini:{openerSelector:`button[aria-label="Upload & tools"], button[aria-label="Open upload file menu"]`,closeSelector:`button[aria-label="Close upload file menu"]`,uploadItemSelector:`[data-test-id="local-images-files-uploader-button"], [data-testid="local-images-files-uploader-button"], button[aria-label^="Upload files"]`},chatgpt:{directInputSelector:`form input[type="file"]:not([accept*="image"]), input[type="file"]:not([accept*="image"]), input[type="file"]`,openerSelector:`button[data-testid="composer-plus-btn"], button[aria-label="Add files and more"]`}};async function De(e,t,n){let r;try{r=await M.sendCommand(e,`Runtime.evaluate`,{expression:`(() => {
32
+ const input = document.querySelector(${JSON.stringify(n)});
33
+ if (!input || input.tagName !== 'INPUT' || input.type !== 'file') return null;
34
+ return input;
35
+ })()`,userGesture:!0})}catch(e){throw G(`ChatGPT`,`selector`,e instanceof Error?e.message:String(e))}if(r?.exceptionDetails)throw G(`ChatGPT`,`selector`,`file input selector evaluation failed`);let i=r?.result?.objectId;if(!i)return!1;try{await M.sendCommand(e,`DOM.setFileInputFiles`,{files:t,objectId:i})}catch(e){throw G(`ChatGPT`,`processing`,e instanceof Error?e.message:String(e))}return!0}async function Oe(e,t,n){try{await M.sendCommand(e,`Page.setInterceptFileChooserDialog`,{enabled:!0})}catch(e){throw G(n,`chooser`,e instanceof Error?e.message:String(e))}let r=null,i=null,a=()=>{r&&=(clearTimeout(r),null),i&&=(chrome.debugger.onEvent.removeListener(i),null)},o=(o,s)=>new Promise((c,l)=>{r=setTimeout(()=>{a(),l(Error(`${n} file chooser did not open within ${s/1e3}s (attempt ${o})`))},s),i=(r,i,o)=>{if(r.tabId===e&&i===`Page.fileChooserOpened`){if(a(),!o?.backendNodeId){l(G(n,`chooser`,`file chooser did not provide a backend node`));return}M.sendCommand(e,`DOM.setFileInputFiles`,{files:t,backendNodeId:o.backendNodeId}).then(()=>c()).catch(e=>l(G(n,`processing`,e instanceof Error?e.message:String(e))))}},chrome.debugger.onEvent.addListener(i)}),s=async()=>{if(n===`gemini`){await M.sendCommand(e,`Runtime.evaluate`,{expression:`document.querySelector(${JSON.stringify(K.gemini.closeSelector)})?.click()`,userGesture:!0}),await W(300),await M.sendCommand(e,`Runtime.evaluate`,{expression:`document.querySelector(${JSON.stringify(K.gemini.openerSelector)})?.click()`,userGesture:!0}),await W(500),await M.sendCommand(e,`Runtime.evaluate`,{expression:`document.querySelector(${JSON.stringify(K.gemini.uploadItemSelector)})?.click()`,userGesture:!0});return}let t;try{t=await M.sendCommand(e,`Runtime.evaluate`,{expression:`(() => { const button = document.querySelector(${JSON.stringify(K.chatgpt.openerSelector)}); if (!button) return false; button.click(); return true; })()`,userGesture:!0})}catch(e){throw G(`ChatGPT`,`selector`,e instanceof Error?e.message:String(e))}if(t?.exceptionDetails)throw G(`ChatGPT`,`selector`,`Add files selector evaluation failed`);if(t?.result?.value===!1||t?.result?.value===null)throw G(`ChatGPT`,`selector`,`Add files control was not found`)},c=[1e4,15e3,2e4],l=null;try{for(let e=1;e<=3;e++)try{let t=o(e,c[e-1]);await s(),await t;return}catch(t){l=t,a();let n=l?.code;if(n&&n!==`attachment_chooser_interception`)throw l;e<3&&await W(1e3)}throw l||G(n,`chooser`,`file chooser did not open`)}finally{a();try{await M.sendCommand(e,`Page.setInterceptFileChooserDialog`,{enabled:!1})}catch{}}}async function ke(e,t,n){try{await M.attach(t),await M.sendCommand(t,`DOM.enable`,{})}catch(t){throw G(e===`chatgpt`?`ChatGPT`:`Gemini`,`selector`,t instanceof Error?t.message:String(t))}return e===`chatgpt`&&await De(t,n,K.chatgpt.directInputSelector)||await Oe(t,n,e),{success:!0}}var q={button:`#FF6B6B`,input:`#4ECDC4`,select:`#45B7D1`,a:`#96CEB4`,textarea:`#FF8C42`,default:`#DDA0DD`};async function Ae(e,t,n){let r=Y(e.base64),i=await createImageBitmap(r),a=new OffscreenCanvas(i.width,i.height),o=a.getContext(`2d`);if(!o)throw Error(`Failed to get canvas context`);o.drawImage(i,0,0),i.close();let s=Math.min(n.scaleX,n.scaleY);for(let e of t){let t=q[e.tag]||q.default,n=Math.round(e.bounds.x*s),r=Math.round(e.bounds.y*s),i=Math.round(e.bounds.width*s),c=Math.round(e.bounds.height*s);if(i<1||c<1)continue;o.strokeStyle=t,o.lineWidth=2,o.setLineDash([4,4]),o.strokeRect(n,r,i,c),o.setLineDash([]);let l=e.ref,u=Math.max(10,Math.min(16,Math.round(a.width*.01)));o.font=`bold ${u}px sans-serif`;let d=o.measureText(l).width+8,f=u+8,p=n+Math.floor((i-d)/2),m=r+2;(i<60||c<30)&&(m=r-f-2<0?r+c+2:r-f-2),p=Math.max(0,Math.min(a.width-d,p)),m=Math.max(0,Math.min(a.height-f,m)),o.fillStyle=t,o.fillRect(p,m,d,f),o.strokeStyle=`white`,o.lineWidth=1,o.strokeRect(p,m,d,f),o.fillStyle=`white`,o.textBaseline=`top`,o.fillText(l,p+4,m+4)}return{base64:await J(await a.convertToBlob({type:`image/png`})),width:a.width,height:a.height}}function J(e){return new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{let e=r.result.split(`,`)[1];t(e)},r.onerror=()=>n(Error(`Failed to convert blob to base64`)),r.readAsDataURL(e)})}function Y(e,t=`image/png`){let n=atob(e),r=new Uint8Array(n.length);for(let e=0;e<n.length;e++)r[e]=n.charCodeAt(e);return new Blob([r],{type:t})}function je(e){return`return (\n${e}\n);`}async function Me(e,t){try{return Function(t),!0}catch(e){if(e instanceof SyntaxError)return!1}return(await M.compileScript(e,`(async () => { 'use strict'; ${t} })()`)).parses}async function Ne(e,t){let n=(await M.evaluateScript(e,`(() => ({
7
36
  viewportHeight: window.innerHeight,
8
37
  totalHeight: Math.min(document.documentElement.scrollHeight, ${t}),
9
38
  width: window.innerWidth,
10
39
  devicePixelRatio: window.devicePixelRatio || 1,
11
40
  originalScrollY: window.scrollY,
12
- }))()`)).result?.value;if(!n)throw Error(`Failed to get page dimensions`);let{viewportHeight:r,totalHeight:i,width:a,devicePixelRatio:o,originalScrollY:s}=n,c=[],l=0;for(;l<i;){await O.evaluateScript(e,`window.scrollTo(0, ${l})`),await new Promise(e=>setTimeout(e,300));let t=q((await O.captureScreenshot(e)).base64);c.push(await createImageBitmap(t)),l+=r}await O.evaluateScript(e,`window.scrollTo(0, ${s})`);let u=Math.round(a*o),d=Math.round(i*o),f=new OffscreenCanvas(u,d),p=f.getContext(`2d`);if(!p)throw Error(`Failed to get canvas context`);let m=0,h=Math.round(r*o);for(let e=0;e<c.length;e++){let t=c[e],n=d-m,r=Math.min(h,n);p.drawImage(t,0,0,t.width,r,0,m,t.width,r),m+=r,t.close()}return{base64:await K(await f.convertToBlob({type:`image/png`})),width:u,height:d}}var J=new Map,Y=new Map;chrome.webNavigation.onCompleted.addListener(e=>{if(e.frameId===0){chrome.tabs.get(e.tabId).then(t=>S({type:`TARGET_EVENT`,event:`navigation`,tabId:e.tabId,url:e.url,title:t.title})).catch(()=>S({type:`TARGET_EVENT`,event:`navigation`,tabId:e.tabId,url:e.url}));let t=J.get(e.tabId);t&&(t(),J.delete(e.tabId))}}),chrome.webNavigation.onErrorOccurred.addListener(e=>{if(e.frameId===0){let t=J.get(e.tabId);t&&(t(),J.delete(e.tabId))}}),chrome.tabs.onRemoved.addListener(e=>{S({type:`TARGET_EVENT`,event:`tab-removed`,tabId:e}),O.detach(e);for(let[t,n]of Y)n===e&&Y.delete(t);for(let[t,n]of k)n===e&&k.delete(t)}),chrome.windows.onRemoved.addListener(e=>{S({type:`TARGET_EVENT`,event:`window-removed`,windowId:e})});async function X(e,t=1e4){let n=Date.now()+t;for(;Date.now()<n;){try{if((await O.evaluateScript(e,`document.readyState`))?.result?.value===`complete`){await V(1500);return}}catch{}await V(200)}console.warn(`waitForRuntimeReady timed out for tab ${e}`)}async function Z(e,t,n,r,i,a=0){switch(n){case`click`:{let n=await chrome.tabs.sendMessage(e,{type:`CLICK_ELEMENT`,ref:t,button:`left`},{frameId:a});return n.error?n:{success:!0,action:`click`,ref:t}}case`fill`:{if(!r)return{error:`fill action requires --value`};let n=await chrome.tabs.sendMessage(e,{type:`FORM_INPUT`,ref:t,value:r},{frameId:a});return n.error?n:{success:!0,action:`fill`,ref:t,value:r}}case`hover`:{let n=await chrome.tabs.sendMessage(e,{type:`GET_ELEMENT_COORDINATES`,ref:t},{frameId:a});return n.error?n:(await i.hover(e,n.x,n.y),{success:!0,action:`hover`,ref:t})}case`text`:return await chrome.tabs.sendMessage(e,{type:`GET_ELEMENT_TEXT`,ref:t},{frameId:a});default:return{error:`Unknown action: ${n}. Use click|fill|hover|text`}}}chrome.runtime.onMessage.addListener((e,t,n)=>(Q(e,t).then(n).catch(e=>n({error:e.message})),!0));async function Q(e,t){let n=e.tabId;switch(e.type){case`GET_CURRENT_TAB_ID`:{let[e]=await chrome.tabs.query({active:!0,currentWindow:!0});return{tabId:e?.id}}case`TARGET_INSPECT`:{let t=Number(e.tabId);if(!Number.isInteger(t)||t<=0)throw new M(`target_required`,`TARGET_INSPECT requires a valid tabId`);return N(t)}case`TARGET_RESOLVE`:{let t=e.windowId===void 0?void 0:Number(e.windowId);if(t!==void 0&&(!Number.isInteger(t)||t<=0))throw new M(`target_invalid`,`windowId must be a positive integer`);let{tab:n,autoCreated:r}=await P(t,e.allowCreate!==!1);return{...await N(n.id),autoCreated:r}}case`SESSION_CREATE_TARGET`:{let t=String(e.name||``),n=typeof e.url==`string`&&e.url?e.url:`about:blank`,r=e.mode===`tab`?`tab`:`window`,i=e.focused===!0,a,o;if(r===`tab`){let t={url:n,active:i};if(e.windowId!==void 0){let n=Number(e.windowId);if(!Number.isInteger(n)||n<=0)throw new M(`target_invalid`,`--window-id must be a positive integer`);t.windowId=n}a=await chrome.tabs.create(t),o=a.windowId}else{let e=await chrome.windows.create({url:n,focused:i,type:`normal`});if(!e)throw new M(`target_create_failed`,`Failed to create target for session ${t}`);o=e.id,a=e.tabs?.[0],!a&&o!==void 0&&(a=(await chrome.tabs.query({windowId:o}))[0])}if(!a?.id||o===void 0)throw new M(`target_create_failed`,`Failed to create target for session ${t}`);let s=await F(a.id,t);return{...await N(a.id),mode:r,groupId:s}}case`SESSION_CLOSE_TARGET`:{let t=Number(e.tabId);if(!Number.isInteger(t)||t<=0)throw new M(`target_required`,`SESSION_CLOSE_TARGET requires a valid tabId`);try{await chrome.tabs.remove(t)}catch{return{success:!0,tabId:t,alreadyGone:!0}}return{success:!0,tabId:t}}case`EXECUTE_SCREENSHOT`:if(!n)throw Error(`No tabId provided`);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{let t,r={scaleX:1,scaleY:1},i=!1;if(e.fullpage){t=await oe(n,e.maxHeight||4e3);try{let e=await O.getViewportSize(n),i=t.width/e.width;r={scaleX:i,scaleY:i}}catch{}}else try{let e=await O.captureScreenshot(n);t=e;try{let t=await O.getViewportSize(n);r={scaleX:e.width/t.width,scaleY:e.height/t.height}}catch{}}catch(r){let a=await chrome.tabs.get(n);if(!a.windowId)throw r;if(e.strictTarget){let[e]=await chrome.tabs.query({active:!0,windowId:a.windowId});if(e?.id!==n)throw new M(`screenshot_target_not_visible`,`Cannot use screenshot fallback because tab ${n} is not visible in window ${a.windowId}`,{tabId:n,windowId:a.windowId,activeTabId:e?.id})}let o=(await chrome.tabs.captureVisibleTab(a.windowId,{format:`png`})).replace(/^data:image\/png;base64,/,``),s=atob(o),c=new Uint8Array(s.length);for(let e=0;e<s.length;e++)c[e]=s.charCodeAt(e);let l=new Blob([c],{type:`image/png`}),u=await createImageBitmap(l);t={base64:o,width:u.width,height:u.height},u.close(),i=!0}if(e.annotate&&!i)try{let e=await chrome.tabs.sendMessage(n,{type:`GET_ELEMENT_BOUNDS_FOR_ANNOTATION`},{frameId:0});e?.elements&&e.elements.length>0&&(t=await re(t,e.elements,r))}catch{}let a=R();return z(a,t),{...t,screenshotId:a}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}case`EXECUTE_CLICK`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?O.parseModifiers(e.modifiers):0;return await O.click(n,e.x,e.y,`left`,1,t),{success:!0}}case`EXECUTE_RIGHT_CLICK`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?O.parseModifiers(e.modifiers):0;return await O.rightClick(n,e.x,e.y,t),{success:!0}}case`EXECUTE_DOUBLE_CLICK`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?O.parseModifiers(e.modifiers):0;return await O.doubleClick(n,e.x,e.y,t),{success:!0}}case`EXECUTE_TRIPLE_CLICK`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?O.parseModifiers(e.modifiers):0;return await O.tripleClick(n,e.x,e.y,t),{success:!0}}case`EXECUTE_DRAG`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?O.parseModifiers(e.modifiers):0;return await O.drag(n,e.startX,e.startY,e.endX,e.endY,t),{success:!0}}case`EXECUTE_HOVER`:if(!n)throw Error(`No tabId provided`);return await O.hover(n,e.x,e.y),{success:!0};case`EXECUTE_TYPE`:if(!n)throw Error(`No tabId provided`);if(e.text===void 0||e.text===null)throw Error(`No text provided`);return await O.type(n,e.text),{success:!0};case`TYPE_SUBMIT`:if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);return await O.type(n,e.text),await O.pressKey(n,e.submitKey||`Enter`),{success:!0};case`CLICK_TYPE`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);let t=A(n,e),r=!1;if(e.ref)try{(await chrome.tabs.sendMessage(n,{type:`CLICK_ELEMENT`,ref:e.ref,button:`left`},{frameId:t})).error||(r=!0)}catch{}if(!r&&e.coordinate&&(await O.click(n,e.coordinate[0],e.coordinate[1],`left`,1,0),r=!0),!r){let e=await O.evaluateScript(n,`(() => {
41
+ }))()`)).result?.value;if(!n)throw Error(`Failed to get page dimensions`);let{viewportHeight:r,totalHeight:i,width:a,devicePixelRatio:o,originalScrollY:s}=n,c=[],l=0;for(;l<i;){await M.evaluateScript(e,`window.scrollTo(0, ${l})`),await new Promise(e=>setTimeout(e,300));let t=Y((await M.captureScreenshot(e)).base64);c.push(await createImageBitmap(t)),l+=r}await M.evaluateScript(e,`window.scrollTo(0, ${s})`);let u=Math.round(a*o),d=Math.round(i*o),f=new OffscreenCanvas(u,d),p=f.getContext(`2d`);if(!p)throw Error(`Failed to get canvas context`);let m=0,h=Math.round(r*o);for(let e=0;e<c.length;e++){let t=c[e],n=d-m,r=Math.min(h,n);p.drawImage(t,0,0,t.width,r,0,m,t.width,r),m+=r,t.close()}return{base64:await J(await f.convertToBlob({type:`image/png`})),width:u,height:d}}var X=new Map,Z=new Map;chrome.webNavigation.onCompleted.addListener(e=>{if(e.frameId===0){chrome.tabs.get(e.tabId).then(t=>O({type:`TARGET_EVENT`,event:`navigation`,tabId:e.tabId,url:e.url,title:t.title})).catch(()=>O({type:`TARGET_EVENT`,event:`navigation`,tabId:e.tabId,url:e.url}));let t=X.get(e.tabId);t&&(t(),X.delete(e.tabId))}}),chrome.webNavigation.onErrorOccurred.addListener(e=>{if(e.frameId===0){let t=X.get(e.tabId);t&&(t(),X.delete(e.tabId))}}),chrome.tabs.onRemoved.addListener(e=>{O({type:`TARGET_EVENT`,event:`tab-removed`,tabId:e}),M.detach(e);for(let[t,n]of Z)n===e&&Z.delete(t);for(let[t,n]of N)n===e&&N.delete(t);P?.tabId===e&&(P=null)}),chrome.windows.onRemoved.addListener(e=>{O({type:`TARGET_EVENT`,event:`window-removed`,windowId:e})});async function Q(e,t=1e4){let n=Date.now()+t;for(;Date.now()<n;){try{if((await M.evaluateScript(e,`document.readyState`))?.result?.value===`complete`){await W(1500);return}}catch{}await W(200)}console.warn(`waitForRuntimeReady timed out for tab ${e}`)}async function $(e,t,n,r,i,a=0){switch(n){case`click`:{let n=await chrome.tabs.sendMessage(e,{type:`CLICK_ELEMENT`,ref:t,button:`left`},{frameId:a});return n.error?n:{success:!0,action:`click`,ref:t}}case`fill`:{if(!r)return{error:`fill action requires --value`};let n=await chrome.tabs.sendMessage(e,{type:`FORM_INPUT`,ref:t,value:r},{frameId:a});return n.error?n:{success:!0,action:`fill`,ref:t,value:r}}case`hover`:{let n=await chrome.tabs.sendMessage(e,{type:`GET_ELEMENT_COORDINATES`,ref:t},{frameId:a});return n.error?n:(await i.hover(e,n.x,n.y),{success:!0,action:`hover`,ref:t})}case`text`:return await chrome.tabs.sendMessage(e,{type:`GET_ELEMENT_TEXT`,ref:t},{frameId:a});default:return{error:`Unknown action: ${n}. Use click|fill|hover|text`}}}chrome.runtime.onMessage.addListener((e,t,n)=>(Pe(e,t).then(n).catch(e=>n({error:e.message})),!0));async function Pe(e,t){let n=e.tabId;switch(e.type){case`GET_CURRENT_TAB_ID`:{let[e]=await chrome.tabs.query({active:!0,currentWindow:!0});return{tabId:e?.id}}case`TARGET_INSPECT`:{let t=Number(e.tabId);if(!Number.isInteger(t)||t<=0)throw new L(`target_required`,`TARGET_INSPECT requires a valid tabId`);return R(t)}case`TARGET_RESOLVE`:{let t=e.windowId===void 0?void 0:Number(e.windowId);if(t!==void 0&&(!Number.isInteger(t)||t<=0))throw new L(`target_invalid`,`windowId must be a positive integer`);let{tab:n,autoCreated:r}=await z(t,e.allowCreate!==!1);return{...await R(n.id),autoCreated:r}}case`SESSION_CREATE_TARGET`:{let t=String(e.name||``),n=typeof e.url==`string`&&e.url?e.url:`about:blank`,r=e.mode===`tab`?`tab`:`window`,i=e.focused===!0,a,o;if(r===`tab`){let t={url:n,active:i};if(e.windowId!==void 0){let n=Number(e.windowId);if(!Number.isInteger(n)||n<=0)throw new L(`target_invalid`,`--window-id must be a positive integer`);t.windowId=n}a=await chrome.tabs.create(t),o=a.windowId}else{let e=await chrome.windows.create({url:n,focused:i,type:`normal`});if(!e)throw new L(`target_create_failed`,`Failed to create target for session ${t}`);o=e.id,a=e.tabs?.[0],!a&&o!==void 0&&(a=(await chrome.tabs.query({windowId:o}))[0])}if(!a?.id||o===void 0)throw new L(`target_create_failed`,`Failed to create target for session ${t}`);let s=await ye(a.id,t);return{...await R(a.id),mode:r,groupId:s}}case`SESSION_CLOSE_TARGET`:{let t=Number(e.tabId);if(!Number.isInteger(t)||t<=0)throw new L(`target_required`,`SESSION_CLOSE_TARGET requires a valid tabId`);try{await chrome.tabs.remove(t)}catch{return{success:!0,tabId:t,alreadyGone:!0}}return{success:!0,tabId:t}}case`EXECUTE_SCREENSHOT`:if(!n)throw Error(`No tabId provided`);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{let t,r={scaleX:1,scaleY:1},i=!1;if(e.fullpage){t=await Ne(n,e.maxHeight||4e3);try{let e=await M.getViewportSize(n),i=t.width/e.width;r={scaleX:i,scaleY:i}}catch{}}else try{let e=await M.captureScreenshot(n);t=e;try{let t=await M.getViewportSize(n);r={scaleX:e.width/t.width,scaleY:e.height/t.height}}catch{}}catch(r){let a=await chrome.tabs.get(n);if(!a.windowId)throw r;if(e.strictTarget){let[e]=await chrome.tabs.query({active:!0,windowId:a.windowId});if(e?.id!==n)throw new L(`screenshot_target_not_visible`,`Cannot use screenshot fallback because tab ${n} is not visible in window ${a.windowId}`,{tabId:n,windowId:a.windowId,activeTabId:e?.id})}let o=(await chrome.tabs.captureVisibleTab(a.windowId,{format:`png`})).replace(/^data:image\/png;base64,/,``),s=atob(o),c=new Uint8Array(s.length);for(let e=0;e<s.length;e++)c[e]=s.charCodeAt(e);let l=new Blob([c],{type:`image/png`}),u=await createImageBitmap(l);t={base64:o,width:u.width,height:u.height},u.close(),i=!0}if(e.annotate&&!i)try{let e=await chrome.tabs.sendMessage(n,{type:`GET_ELEMENT_BOUNDS_FOR_ANNOTATION`},{frameId:0});e?.elements&&e.elements.length>0&&(t=await Ae(t,e.elements,r))}catch{}let a=Ce();return we(a,t),{...t,screenshotId:a}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}case`EXECUTE_CLICK`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?M.parseModifiers(e.modifiers):0;return await M.click(n,e.x,e.y,`left`,1,t),{success:!0}}case`EXECUTE_RIGHT_CLICK`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?M.parseModifiers(e.modifiers):0;return await M.rightClick(n,e.x,e.y,t),{success:!0}}case`EXECUTE_DOUBLE_CLICK`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?M.parseModifiers(e.modifiers):0;return await M.doubleClick(n,e.x,e.y,t),{success:!0}}case`EXECUTE_TRIPLE_CLICK`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?M.parseModifiers(e.modifiers):0;return await M.tripleClick(n,e.x,e.y,t),{success:!0}}case`EXECUTE_DRAG`:{if(!n)throw Error(`No tabId provided`);let t=e.modifiers?M.parseModifiers(e.modifiers):0;return await M.drag(n,e.startX,e.startY,e.endX,e.endY,t),{success:!0}}case`EXECUTE_HOVER`:if(!n)throw Error(`No tabId provided`);return await M.hover(n,e.x,e.y),{success:!0};case`EXECUTE_TYPE`:if(!n)throw Error(`No tabId provided`);if(e.text===void 0||e.text===null)throw Error(`No text provided`);return await M.type(n,e.text),{success:!0};case`TYPE_SUBMIT`:if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);return await M.type(n,e.text),await M.pressKey(n,e.submitKey||`Enter`),{success:!0};case`CLICK_TYPE`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);let t=F(n,e),r=!1;if(e.ref)try{(await chrome.tabs.sendMessage(n,{type:`CLICK_ELEMENT`,ref:e.ref,button:`left`},{frameId:t})).error||(r=!0)}catch{}if(!r&&e.coordinate&&(await M.click(n,e.coordinate[0],e.coordinate[1],`left`,1,0),r=!0),!r){let e=await M.evaluateScript(n,`(() => {
13
42
  const el = document.querySelector('textarea, input[type="text"], input[type="search"], input:not([type]), [contenteditable="true"]');
14
43
  if (!el) return null;
15
44
  const r = el.getBoundingClientRect();
16
45
  return { x: r.left + r.width/2, y: r.top + r.height/2 };
17
- })()`);e.result?.value&&(await O.click(n,e.result.value.x,e.result.value.y,`left`,1,0),r=!0)}return r?(await O.type(n,e.text),{success:!0}):{error:`Could not find input element`}}case`CLICK_TYPE_SUBMIT`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);let t=A(n,e),r=!1;if(e.ref)try{(await chrome.tabs.sendMessage(n,{type:`CLICK_ELEMENT`,ref:e.ref,button:`left`},{frameId:t})).error||(r=!0)}catch{}if(!r&&e.coordinate&&(await O.click(n,e.coordinate[0],e.coordinate[1],`left`,1,0),r=!0),!r){let e=await O.evaluateScript(n,`(() => {
46
+ })()`);e.result?.value&&(await M.click(n,e.result.value.x,e.result.value.y,`left`,1,0),r=!0)}return r?(await M.type(n,e.text),{success:!0}):{error:`Could not find input element`}}case`CLICK_TYPE_SUBMIT`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);let t=F(n,e),r=!1;if(e.ref)try{(await chrome.tabs.sendMessage(n,{type:`CLICK_ELEMENT`,ref:e.ref,button:`left`},{frameId:t})).error||(r=!0)}catch{}if(!r&&e.coordinate&&(await M.click(n,e.coordinate[0],e.coordinate[1],`left`,1,0),r=!0),!r){let e=await M.evaluateScript(n,`(() => {
18
47
  const el = document.querySelector('textarea, input[type="text"], input[type="search"], input:not([type]), [contenteditable="true"]');
19
48
  if (!el) return null;
20
49
  const r = el.getBoundingClientRect();
21
50
  return { x: r.left + r.width/2, y: r.top + r.height/2 };
22
- })()`);e.result?.value&&(await O.click(n,e.result.value.x,e.result.value.y,`left`,1,0),r=!0)}return r?(await O.type(n,e.text),await O.pressKey(n,e.submitKey||`Enter`),{success:!0}):{error:`Could not find input element`}}case`FIND_AND_TYPE`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);let t=(await O.evaluateScript(n,`(() => {
51
+ })()`);e.result?.value&&(await M.click(n,e.result.value.x,e.result.value.y,`left`,1,0),r=!0)}return r?(await M.type(n,e.text),await M.pressKey(n,e.submitKey||`Enter`),{success:!0}):{error:`Could not find input element`}}case`FIND_AND_TYPE`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);let t=(await M.evaluateScript(n,`(() => {
23
52
  const selectors = [
24
53
  'textarea:not([readonly]):not([disabled])',
25
54
  'input[type="text"]:not([readonly]):not([disabled])',
@@ -39,7 +68,7 @@ var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],en
39
68
  }
40
69
  }
41
70
  return { found: false };
42
- })()`)).result?.value;return t?.found?(await O.click(n,t.x,t.y,`left`,1,0),await O.type(n,e.text),e.submit&&await O.pressKey(n,e.submitKey||`Enter`),{success:!0,coordinates:{x:t.x,y:t.y}}):{error:`No input field found on page`}}case`AUTOCOMPLETE_SELECT`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);let t=A(n,e),r=!1;if(e.ref)try{(await chrome.tabs.sendMessage(n,{type:`CLICK_ELEMENT`,ref:e.ref,button:`left`},{frameId:t})).error||(r=!0)}catch{}if(!r&&e.coordinate&&(await O.click(n,e.coordinate[0],e.coordinate[1],`left`,1,0),r=!0),!r)return{error:`ref or coordinate required`};await new Promise(e=>setTimeout(e,100)),await O.type(n,e.text);let i=e.waitMs||500;if(await new Promise(e=>setTimeout(e,i)),e.index&&e.index>0)for(let t=0;t<e.index;t++)await O.pressKey(n,`ArrowDown`),await new Promise(e=>setTimeout(e,50));return await O.pressKey(n,`Enter`),{success:!0}}case`SET_INPUT_VALUE`:{if(!n)throw Error(`No tabId provided`);if(e.value===void 0)throw Error(`No value provided`);let t=e.selector,r=e.ref;if(!t&&!r)throw Error(`selector or ref required`);let i=r?`(() => {
71
+ })()`)).result?.value;return t?.found?(await M.click(n,t.x,t.y,`left`,1,0),await M.type(n,e.text),e.submit&&await M.pressKey(n,e.submitKey||`Enter`),{success:!0,coordinates:{x:t.x,y:t.y}}):{error:`No input field found on page`}}case`AUTOCOMPLETE_SELECT`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`No text provided`);let t=F(n,e),r=!1;if(e.ref)try{(await chrome.tabs.sendMessage(n,{type:`CLICK_ELEMENT`,ref:e.ref,button:`left`},{frameId:t})).error||(r=!0)}catch{}if(!r&&e.coordinate&&(await M.click(n,e.coordinate[0],e.coordinate[1],`left`,1,0),r=!0),!r)return{error:`ref or coordinate required`};await new Promise(e=>setTimeout(e,100)),await M.type(n,e.text);let i=e.waitMs||500;if(await new Promise(e=>setTimeout(e,i)),e.index&&e.index>0)for(let t=0;t<e.index;t++)await M.pressKey(n,`ArrowDown`),await new Promise(e=>setTimeout(e,50));return await M.pressKey(n,`Enter`),{success:!0}}case`SET_INPUT_VALUE`:{if(!n)throw Error(`No tabId provided`);if(e.value===void 0)throw Error(`No value provided`);let t=e.selector,r=e.ref;if(!t&&!r)throw Error(`selector or ref required`);let i=r?`(() => {
43
72
  const el = document.querySelector('[data-pi-ref="${r}"]') ||
44
73
  [...document.querySelectorAll('*')].find(e => e.getAttribute?.('data-ref') === '${r}');
45
74
  if (!el) return { error: 'Element not found' };
@@ -68,7 +97,7 @@ var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],en
68
97
  el.dispatchEvent(new Event('input', { bubbles: true }));
69
98
  el.dispatchEvent(new Event('change', { bubbles: true }));
70
99
  return { success: true, contentEditable: isContentEditable };
71
- })()`;return(await O.evaluateScript(n,i)).result?.value||{error:`Script failed`}}case`SMART_TYPE`:{if(!n)throw Error(`No tabId provided`);let{selector:t,text:r,clear:i=!0,submit:a=!1}=e;if(!t)throw Error(`selector required`);if(r===void 0)throw Error(`text required`);try{return await chrome.tabs.sendMessage(n,{type:`SMART_TYPE`,selector:t,text:r,clear:i,submit:a},{frameId:A(n,e)})}catch(e){throw Error(`Could not type into selector: ${e instanceof Error?e.message:String(e)}`)}}case`CLOSE_DIALOGS`:{if(!n)throw Error(`No tabId provided`);let t=e.maxAttempts||3;for(let e=0;e<t;e++)await O.pressKey(n,`Escape`),await new Promise(e=>setTimeout(e,100));return{success:!0}}case`PAGE_STATE`:if(!n)throw Error(`No tabId provided`);return(await O.evaluateScript(n,`(() => {
100
+ })()`;return(await M.evaluateScript(n,i)).result?.value||{error:`Script failed`}}case`SMART_TYPE`:{if(!n)throw Error(`No tabId provided`);let{selector:t,text:r,clear:i=!0,submit:a=!1}=e;if(!t)throw Error(`selector required`);if(r===void 0)throw Error(`text required`);try{return await chrome.tabs.sendMessage(n,{type:`SMART_TYPE`,selector:t,text:r,clear:i,submit:a},{frameId:F(n,e)})}catch(e){throw Error(`Could not type into selector: ${e instanceof Error?e.message:String(e)}`)}}case`CLOSE_DIALOGS`:{if(!n)throw Error(`No tabId provided`);let t=e.maxAttempts||3;for(let e=0;e<t;e++)await M.pressKey(n,`Escape`),await new Promise(e=>setTimeout(e,100));return{success:!0}}case`PAGE_STATE`:if(!n)throw Error(`No tabId provided`);return(await M.evaluateScript(n,`(() => {
72
101
  const hasModal = !!(
73
102
  document.querySelector('[role="dialog"]') ||
74
103
  document.querySelector('[role="alertdialog"]') ||
@@ -101,7 +130,7 @@ var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],en
101
130
  url: location.href,
102
131
  title: document.title
103
132
  };
104
- })()`)).result?.value||{error:`Failed to get page state`};case`EXECUTE_SCROLL`:{if(!n)throw Error(`No tabId provided`);let t=e.deltaX||0,r=e.deltaY||0,i=(e,t)=>{let n={x:window.scrollX,y:window.scrollY};window.scrollBy(e,t);let r={x:window.scrollX,y:window.scrollY};return{scrollX:r.x,scrollY:r.y,pageHeight:document.documentElement.scrollHeight,viewportHeight:window.innerHeight,scrolled:n.x!==r.x||n.y!==r.y}};try{return(await O.evaluateScript(n,`(${i.toString()})(${t}, ${r})`)).result?.value||{error:`Script failed`}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:n},func:i,args:[t,r]}))[0]?.result||{error:`Script failed`}}catch{return{error:`Cannot scroll on this page (restricted)`}}}}case`EXECUTE_KEY`:{if(!n)throw Error(`No tabId provided`);let t=e.key;if(!t)throw Error(`No key provided`);return t.includes(`+`)?await O.pressKeyChord(n,t):await O.pressKey(n,t),{success:!0}}case`EXECUTE_NAVIGATE`:{if(!n)throw Error(`No tabId provided`);if(!e.url)throw Error(`No url provided`);let t=new Promise(e=>{J.set(n,e),setTimeout(()=>{J.has(n)&&(J.delete(n),e())},3e4)});return await chrome.tabs.update(n,{url:e.url}),await t,await new Promise(e=>setTimeout(e,500)),{success:!0}}case`GET_VIEWPORT_SIZE`:if(!n)throw Error(`No tabId provided`);return await O.getViewportSize(n);case`READ_PAGE`:{if(!n)throw Error(`No tabId provided`);let t=A(n,e);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));let r;try{r=await chrome.tabs.sendMessage(n,{type:`GENERATE_ACCESSIBILITY_TREE`,options:e.options||{}},{frameId:t})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}if(e.options?.includeText)try{let i=await chrome.tabs.sendMessage(n,{type:`GET_PAGE_TEXT`,options:{compact:e.options?.compact===!0,maxBytes:e.options?.maxBytes}},{frameId:t});i?.text&&(r.text=i.text)}catch{}if(e.options?.includeScreenshot)try{let e=await O.captureScreenshot(n);return{...r,screenshot:e}}catch{return{...r,screenshotError:`Failed to capture screenshot`}}return r}case`GET_ELEMENT_COORDINATES`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:`GET_ELEMENT_COORDINATES`,ref:e.ref},{frameId:A(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`FORM_INPUT`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:`FORM_INPUT`,ref:e.ref,value:e.value},{frameId:A(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`EVAL_IN_PAGE`:if(!n)throw Error(`No tabId provided`);if(!e.code)throw Error(`No code provided`);try{return await chrome.tabs.sendMessage(n,{type:`EVAL_IN_PAGE`,code:e.code},{frameId:A(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`SCROLL_TO_ELEMENT`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:`SCROLL_TO_ELEMENT`,ref:e.ref},{frameId:A(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`SCROLL_TO_POSITION`:{if(!n)throw Error(`No tabId provided`);let t=e.position;if(t===void 0)throw Error(`position required ("top", "bottom", or number)`);let r=e.selector,i=(e,t)=>{let n=t&&document.querySelector(t)||[...document.querySelectorAll(`*`)].filter(e=>e.scrollHeight>e.clientHeight&&e.clientHeight>200).sort((e,t)=>t.scrollHeight-e.scrollHeight)[0]||document.documentElement;return n?(e===`bottom`?n.scrollTop=n.scrollHeight:e===`top`?n.scrollTop=0:typeof e==`number`&&(n.scrollTop=e),{scrollTop:n.scrollTop,scrollHeight:n.scrollHeight,clientHeight:n.clientHeight,atBottom:n.scrollTop+n.clientHeight>=n.scrollHeight-10,atTop:n.scrollTop<10}):{error:`No scrollable container found`}};try{let e=`(${i.toString()})(${JSON.stringify(t)}, ${JSON.stringify(r)})`;return(await O.evaluateScript(n,e)).result?.value||{error:`Script failed`}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:n},func:i,args:[t,r]}))[0]?.result||{error:`Script failed`}}catch{return{error:`Cannot scroll on this page (restricted)`}}}}case`GET_SCROLL_INFO`:{if(!n)throw Error(`No tabId provided`);let t=e.selector,r=e=>{let t=e&&document.querySelector(e)||[...document.querySelectorAll(`*`)].filter(e=>e.scrollHeight>e.clientHeight&&e.clientHeight>200).sort((e,t)=>t.scrollHeight-e.scrollHeight)[0]||document.documentElement;if(!t)return{error:`No scrollable container found`};let n=t.scrollHeight-t.clientHeight;return{scrollTop:t.scrollTop,scrollHeight:t.scrollHeight,clientHeight:t.clientHeight,atBottom:t.scrollTop+t.clientHeight>=t.scrollHeight-10,atTop:t.scrollTop<10,scrollPercentage:n>0?Math.round(t.scrollTop/n*100):100}};try{let e=`(${r.toString()})(${JSON.stringify(t)})`;return(await O.evaluateScript(n,e)).result?.value||{error:`Script failed`}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:n},func:r,args:[t]}))[0]?.result||{error:`Script failed`}}catch{return{error:`Cannot get scroll info on this page (restricted)`}}}}case`GET_PAGE_TEXT`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:`GET_PAGE_TEXT`},{frameId:A(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`GET_PAGE_HTML`:{if(!n)throw Error(`No tabId provided`);let t=(await chrome.scripting.executeScript({target:{tabId:n,frameIds:[A(n,e)]},func:(e,t)=>{if(e!==void 0&&(typeof e!=`string`||e.length===0))throw Error(`selector must be a non-empty string`);let n=e===void 0?document.documentElement:document.querySelector(e);if(!n)throw Error(`No element matches selector "${e}"`);let r=t?n.cloneNode(!0):n;if(t){if(r.matches(`script`))return``;r.querySelectorAll(`script`).forEach(e=>e.remove())}return(e===void 0&&document.doctype?`<!doctype ${document.doctype.name}>\n`:``)+r.outerHTML},args:[e.selector,e.stripScripts]}))[0]?.result;if(typeof t!=`string`)throw Error(`Page HTML extraction returned an invalid result`);return{html:t}}case`LOCATE_ROLE`:{if(!n)throw Error(`No tabId provided`);if(!e.role)throw Error(`role required`);let t=A(n,e);try{let r=await chrome.tabs.sendMessage(n,{type:`LOCATE_ROLE`,role:e.role,name:e.name,all:e.all},{frameId:t});return r.error?r:e.action&&r.ref?await Z(n,r.ref,e.action,e.value,O,t):r}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`LOCATE_TEXT`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`text required`);let t=A(n,e);try{let r=await chrome.tabs.sendMessage(n,{type:`LOCATE_TEXT`,text:e.text,exact:e.exact},{frameId:t});return r.error?r:e.action&&r.ref?await Z(n,r.ref,e.action,e.value,O,t):r}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`LOCATE_LABEL`:{if(!n)throw Error(`No tabId provided`);if(!e.label)throw Error(`label required`);let t=A(n,e);try{let r=await chrome.tabs.sendMessage(n,{type:`LOCATE_LABEL`,label:e.label},{frameId:t});return r.error?r:e.action&&r.ref?await Z(n,r.ref,e.action,e.value,O,t):r}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`GET_ELEMENT_STYLES`:{if(!n)throw Error(`No tabId provided`);if(!e.selector)throw Error(`selector required`);let t=A(n,e);try{return await chrome.tabs.sendMessage(n,{type:`GET_ELEMENT_STYLES`,selector:e.selector},{frameId:t})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`SELECT_OPTION`:{if(!n)throw Error(`No tabId provided`);if(!e.selector)throw Error(`selector required`);if(!e.values)throw Error(`values required`);let t=A(n,e);try{return await chrome.tabs.sendMessage(n,{type:`SELECT_OPTION`,selector:e.selector,values:e.values,by:e.by||`value`},{frameId:t})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`SHOW_AGENT_INDICATORS`:case`HIDE_AGENT_INDICATORS`:case`SHOW_STATIC_INDICATOR`:case`HIDE_STATIC_INDICATOR`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:e.type},{frameId:0})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`STOP_AGENT`:{let n=e.fromTabId,r;return n===`CURRENT_TAB`&&t.tab?.id?r=t.tab.id:typeof n==`number`&&(r=n),r&&chrome.runtime.sendMessage({type:`STOP_AGENT`,targetTabId:r}),{success:!0}}case`DISMISS_STATIC_INDICATOR`:return{success:!0};case`STATIC_INDICATOR_HEARTBEAT`:return{success:!0};case`CLICK_REF`:if(!n)throw Error(`No tabId provided`);try{let t=await chrome.tabs.sendMessage(n,{type:`CLICK_ELEMENT`,ref:e.ref,button:e.button||`left`},{frameId:A(n,e)});return t.error?{error:t.error}:{success:!0}}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`HOVER_REF`:if(!n)throw Error(`No tabId provided`);try{let t=await chrome.tabs.sendMessage(n,{type:`GET_ELEMENT_COORDINATES`,ref:e.ref},{frameId:A(n,e)});return t.error?{error:t.error}:(await O.hover(n,t.x,t.y),{success:!0})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`PING`:return{success:!0,status:`connected`};case`HEALTH_CHECK_URL`:{if(!e.url)throw Error(`No url provided`);let t=e.timeout||3e4,n=e.expect||200,r=Date.now(),i=null;for(;Date.now()-r<t;){try{let t=await fetch(e.url,{method:`GET`});if(await t.text(),t.status===n)return{success:!0,status:t.status,time:Date.now()-r};i=`Got status ${t.status}`}catch(e){i=e instanceof Error?e.message:String(e)}await new Promise(e=>setTimeout(e,500))}return{error:`Timeout waiting for ${e.url} to return ${n}`,lastError:i,time:Date.now()-r}}case`SMOKE_TEST`:{let t=e.urls||[],n=e.savePath!==void 0,r=e.failFast||!1;if(t.length===0)return{error:`No URLs provided for smoke test`};let i=[],a=0,o=0;for(let e of t){let t=Date.now(),s=[],c,l,u;try{l=new URL(e).hostname.replace(/[^a-zA-Z0-9.-]/g,`_`);let t=await chrome.tabs.create({url:e,active:!1});if(!t.id)throw Error(`Failed to create tab`);u=t.id;try{await O.enableConsoleTracking(u)}catch{}await new Promise(e=>{let t=r=>{r.tabId===u&&r.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(t),chrome.webNavigation.onErrorOccurred.removeListener(n),e())},n=r=>{r.tabId===u&&r.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(t),chrome.webNavigation.onErrorOccurred.removeListener(n),s.push(`Navigation error: ${r.error}`),e())};chrome.webNavigation.onCompleted.addListener(t),chrome.webNavigation.onErrorOccurred.addListener(n),setTimeout(()=>{chrome.webNavigation.onCompleted.removeListener(t),chrome.webNavigation.onErrorOccurred.removeListener(n),s.push(`Navigation timeout (30s)`),e()},3e4)}),await new Promise(e=>setTimeout(e,2e3));let r=O.getConsoleMessages(u,{onlyErrors:!0,limit:50});for(let e of r)s.push(`[${e.type}] ${e.text}`);if(n)try{c=(await O.captureScreenshot(u)).base64}catch{}}catch(e){s.push(e instanceof Error?e.message:String(e))}finally{if(u)try{await chrome.tabs.remove(u)}catch{}}let d=Date.now()-t,f=s.length===0?`pass`:`fail`;if(f===`pass`?a++:o++,i.push({url:e,status:f,time:d,errors:s,...c&&{screenshotBase64:c,hostname:l}}),r&&f===`fail`)break}return{results:i,summary:{pass:a,fail:o,total:i.length},savePath:e.savePath}}case`WAIT_FOR_ELEMENT`:{if(!n)throw Error(`No tabId provided`);if(!e.selector)throw Error(`No selector provided`);let t=A(n,e);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(n,{type:`WAIT_FOR_ELEMENT`,selector:e.selector,state:e.state||`visible`,timeout:e.timeout||2e4},{frameId:t})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}}case`WAIT_FOR_URL`:if(!n)throw Error(`No tabId provided`);if(!e.pattern)throw Error(`No URL pattern provided`);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(n,{type:`WAIT_FOR_URL`,pattern:e.pattern,timeout:e.timeout||2e4},{frameId:0})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}case`WAIT_FOR_NETWORK_IDLE`:if(!n)throw Error(`No tabId provided`);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(n,{type:`WAIT_FOR_NETWORK_IDLE`,timeout:e.timeout||1e4},{frameId:0})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}case`WAIT_FOR_DOM_STABLE`:if(!n)throw Error(`No tabId provided`);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(n,{type:`WAIT_FOR_DOM_STABLE`,stable:e.stable||100,timeout:e.timeout||5e3},{frameId:0})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}case`DIALOG_ACCEPT`:if(!n)throw Error(`No tabId provided`);return await O.handleDialog(n,!0,e.text);case`DIALOG_DISMISS`:if(!n)throw Error(`No tabId provided`);return await O.handleDialog(n,!1);case`DIALOG_INFO`:{if(!n)throw Error(`No tabId provided`);let e=O.getDialogInfo(n);return e?{hasDialog:!0,type:e.type,message:e.message,defaultPrompt:e.defaultPrompt}:{hasDialog:!1}}case`EMULATE_NETWORK`:{if(!n)throw Error(`No tabId provided`);if(!e.preset)throw Error(`No preset provided`);let t=await O.emulateNetwork(n,e.preset);if(!t.success)throw Error(t.error);return{success:!0,preset:e.preset}}case`EMULATE_CPU`:{if(!n)throw Error(`No tabId provided`);if(e.rate===void 0)throw Error(`No rate provided`);let t=await O.emulateCPU(n,e.rate);if(!t.success)throw Error(t.error);return{success:!0,rate:e.rate}}case`EMULATE_GEO`:{if(!n)throw Error(`No tabId provided`);if(e.clear){let e=await O.clearGeolocation(n);if(!e.success)throw Error(e.error);return{success:!0,cleared:!0}}if(e.latitude===void 0||e.longitude===void 0)throw Error(`Latitude and longitude required`);let t=await O.emulateGeolocation(n,e.latitude,e.longitude,e.accuracy);if(!t.success)throw Error(t.error);return{success:!0,latitude:e.latitude,longitude:e.longitude}}case`EMULATE_DEVICE_LIST`:return{devices:[`iPhone 12`,`iPhone 13`,`iPhone 14`,`iPhone 14 Pro`,`iPhone 14 Pro Max`,`iPhone SE`,`iPad`,`iPad Pro`,`iPad Mini`,`Pixel 5`,`Pixel 6`,`Pixel 7`,`Pixel 7 Pro`,`Galaxy S21`,`Galaxy S22`,`Galaxy S23`,`Galaxy Tab S7`,`Nest Hub`,`Nest Hub Max`]};case`EMULATE_DEVICE`:{if(!n)throw Error(`No tabId provided`);let t=e.device;if(t.toLowerCase()===`reset`){let e=await O.clearDeviceEmulation(n);if(!e.success)throw Error(e.error);return{success:!0,message:`Device emulation reset`}}let r={"iPhone 12":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1`},"iPhone 13":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1`},"iPhone 14":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1`},"iPhone 14 Pro":{width:393,height:852,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1`},"iPhone 14 Pro Max":{width:430,height:932,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1`},"iPhone SE":{width:375,height:667,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1`},iPad:{width:768,height:1024,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1`},"iPad Pro":{width:1024,height:1366,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1`},"iPad Mini":{width:768,height:1024,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1`},"Pixel 5":{width:393,height:851,deviceScaleFactor:2.75,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36`},"Pixel 6":{width:412,height:915,deviceScaleFactor:2.625,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36`},"Pixel 7":{width:412,height:915,deviceScaleFactor:2.625,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36`},"Pixel 7 Pro":{width:412,height:892,deviceScaleFactor:3.5,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 13; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36`},"Galaxy S21":{width:360,height:800,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36`},"Galaxy S22":{width:360,height:780,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 12; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36`},"Galaxy S23":{width:360,height:780,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36`},"Galaxy Tab S7":{width:800,height:1280,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Safari/537.36`},"Nest Hub":{width:1024,height:600,deviceScaleFactor:2,mobile:!1,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666`},"Nest Hub Max":{width:1280,height:800,deviceScaleFactor:2,mobile:!1,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666`}},i={iphone:`iPhone 14`,iphone14:`iPhone 14`,iphone13:`iPhone 13`,iphone12:`iPhone 12`,iphonese:`iPhone SE`,pixel:`Pixel 7`,pixel7:`Pixel 7`,pixel6:`Pixel 6`,galaxy:`Galaxy S23`,galaxys23:`Galaxy S23`,ipad:`iPad`,ipadpro:`iPad Pro`},a=r[t];if(a||=r[i[t.toLowerCase().replace(/\s+/g,``)]],!a){let e=t.toLowerCase(),n=null;for(let[t,i]of Object.entries(r)){let r=t.toLowerCase(),a=r.replace(/\s+/g,``);(r.includes(e)||e.includes(a))&&(!n||t.length>n.name.length)&&(n={name:t,preset:i})}n&&(a=n.preset)}if(!a)throw Error(`Unknown device: ${t}. Use --list to see available devices.`);let o=await O.emulateDevice(n,a);if(!o.success)throw Error(o.error);return{success:!0,device:t}}case`EMULATE_VIEWPORT`:{if(!n)throw Error(`No tabId provided`);if(!e.width&&!e.height)throw Error(`--width or --height required`);let t=await O.emulateViewport(n,{width:e.width,height:e.height,deviceScaleFactor:e.deviceScaleFactor,mobile:e.mobile});if(!t.success)throw Error(t.error);return{success:!0,width:e.width,height:e.height}}case`EMULATE_TOUCH`:{if(!n)throw Error(`No tabId provided`);let t=await O.emulateTouch(n,e.enabled);if(!t.success)throw Error(t.error);return{success:!0,enabled:e.enabled}}case`FORM_FILL`:if(!n)throw Error(`No tabId provided`);if(!e.data)throw Error(`No data provided`);return await chrome.tabs.sendMessage(n,{type:`FORM_FILL`,data:e.data},{frameId:A(n,e)});case`PERF_START`:{if(!n)throw Error(`No tabId provided`);let t=await O.startPerformanceTrace(n,e.categories);if(!t.success)throw Error(t.error);return{success:!0,message:`Performance tracing started`}}case`PERF_STOP`:{if(!n)throw Error(`No tabId provided`);let e=await O.stopPerformanceTrace(n);if(!e.success)throw Error(e.error);return{success:!0,metrics:e.metrics}}case`PERF_METRICS`:{if(!n)throw Error(`No tabId provided`);let e=await O.getPerformanceMetrics(n);if(!e.success)throw Error(e.error);return{success:!0,metrics:e.metrics}}case`UPLOAD_FILE`:{if(!n)throw Error(`No tabId provided`);if(!e.ref)throw Error(`No ref provided`);if(!e.files||!e.files.length)throw Error(`No files provided`);let t=await chrome.tabs.sendMessage(n,{type:`GET_FILE_INPUT_SELECTOR`,ref:e.ref},{frameId:A(n,e)});if(t.error)throw Error(t.error);let r=await O.setFileInputBySelector(n,t.selector,e.files);if(!r.success)throw Error(r.error);return{success:!0,filesSet:e.files.length}}case`WAIT_FOR_LOAD`:{if(!n)throw Error(`No tabId provided`);let t=await O.waitForLoad(n,e.timeout||3e4);if(!t.success)throw Error(t.error);return{success:!0,readyState:t.readyState}}case`GET_FRAMES`:{if(!n)throw Error(`No tabId provided`);let e=await O.getFrames(n);if(!e.success)throw Error(e.error);return{success:!0,frames:e.frames}}case`FRAME_SWITCH`:{if(!n)throw Error(`No tabId provided`);let{selector:t,name:r,index:i}=e;if(!t&&!r&&i===void 0)throw Error(`--selector, --name, or --index required`);let a=await chrome.webNavigation.getAllFrames({tabId:n});if(!a||a.length===0)throw Error(`No frames found in tab`);let o=a.filter(e=>e.frameId!==0);if(o.length===0)throw Error(`No iframes found on this page`);let s=null;if(i!==void 0){if(i<0||i>=o.length)throw Error(`Frame index ${i} out of range. Found ${o.length} frame(s).`);s=o[i]}else if(r){for(let e of o)try{if((await chrome.tabs.sendMessage(n,{type:`GET_FRAME_NAME`},{frameId:e.frameId}))?.name===r){s=e;break}}catch{}if(!s)throw Error(`Frame with name "${r}" not found`)}else if(t)try{let e=await chrome.tabs.sendMessage(n,{type:`GET_FRAME_BY_SELECTOR`,selector:t},{frameId:0});if(e?.error)throw Error(e.error);e?.url&&(s=o.find(t=>t.url===e.url)||null),!s&&o.length===1&&(s=o[0])}catch{throw Error(`Could not find frame with selector "${t}"`)}if(!s)throw Error(`Frame not found`);return{success:!0,frameId:s.frameId,url:s.url}}case`FRAME_MAIN`:if(!n)throw Error(`No tabId provided`);return{success:!0,message:`Returned to main frame`};case`EVALUATE_IN_FRAME`:{if(!n)throw Error(`No tabId provided`);if(!e.frameId)throw Error(`No frameId provided`);if(!e.code)throw Error(`No code provided`);let t=await O.evaluateInFrame(n,e.frameId,e.code);if(!t.success)throw Error(t.error);return{value:t.result}}case`EXECUTE_JAVASCRIPT`:if(!n)throw Error(`No tabId provided`);if(!e.code)throw Error(`No code provided`);try{await O.evaluateScript(n,`if(!window.piHelpers){const piHelpers={wait(ms){return new Promise(r=>setTimeout(r,ms))},async waitForSelector(sel,opts={}){const{state='visible',timeout=20000}=opts;const isVis=el=>el&&getComputedStyle(el).display!=='none'&&getComputedStyle(el).visibility!=='hidden'&&getComputedStyle(el).opacity!=='0'&&el.offsetWidth>0&&el.offsetHeight>0;const chk=()=>{const el=document.querySelector(sel);switch(state){case'attached':return el;case'detached':return el?null:document.body;case'hidden':return(!el||!isVis(el))?(el||document.body):null;default:return isVis(el)?el:null}};return new Promise((res,rej)=>{const r=chk();if(r){res(state==='detached'||state==='hidden'?null:r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(state==='detached'||state==='hidden'?null:r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['style','class','hidden']})})},async waitForText(text,opts={}){const{selector,timeout=20000}=opts;const chk=()=>{const root=selector?document.querySelector(selector):document.body;if(!root)return null;const w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);while(w.nextNode())if(w.currentNode.textContent?.includes(text))return w.currentNode.parentElement;return null};return new Promise((res,rej)=>{const r=chk();if(r){res(r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,characterData:true})})},async waitForHidden(sel,t=20000){await piHelpers.waitForSelector(sel,{state:'hidden',timeout:t})},getByRole(role,opts={}){const{name}=opts;const roles={button:['button','input[type=button]','input[type=submit]','input[type=reset]'],link:['a[href]'],textbox:['input:not([type])','input[type=text]','input[type=email]','input[type=password]','textarea'],checkbox:['input[type=checkbox]'],radio:['input[type=radio]'],combobox:['select'],heading:['h1','h2','h3','h4','h5','h6']};const cands=[...document.querySelectorAll('[role='+role+']')];if(roles[role])roles[role].forEach(s=>cands.push(...document.querySelectorAll(s+':not([role])')));if(!name)return cands[0]||null;const n=name.toLowerCase().trim();for(const el of cands){const l=el.getAttribute('aria-label')?.toLowerCase().trim();const t=el.textContent?.toLowerCase().trim();if(l===n||t===n||l?.includes(n)||t?.includes(n))return el}return null}};window.__piHelpers=piHelpers;window.piHelpers=piHelpers}`);let t=ie(e.code),r=`(async () => { 'use strict'; ${t} })()`,i=await O.evaluateScript(n,r);if(i.exceptionDetails&&!ae(t)&&(i=await O.evaluateScript(n,`(async () => { 'use strict'; ${e.code} })()`)),i.exceptionDetails)return{error:i.exceptionDetails.exception?.description||i.exceptionDetails.text||`Script execution failed`};let a=i.result?.value;return{output:(a===void 0?`undefined`:JSON.stringify(a,null,2))?.substring(0,5e4)||`undefined`}}catch(e){let t=e instanceof Error?e.message:`Script execution failed`;return t.includes(`Cannot access`)||t.includes(`Cannot attach`)?{error:`Cannot execute JavaScript on this page (restricted URL)`}:{error:t}}case`ANIMATE_AUDIT`:{if(!n)throw Error(`No tabId provided`);if(!e.selector||typeof e.selector!=`string`)throw Error(`selector required`);if(typeof e.durationMs==`boolean`)throw Error(`duration must be a number`);if(typeof e.fps==`boolean`)throw Error(`fps must be a number`);let t=e.durationMs===void 0?2e3:Number(e.durationMs),r=e.fps===void 0?10:Number(e.fps);if(!Number.isFinite(t)||t<100||t>1e4)throw Error(`duration must be between 100 and 10000 ms`);if(!Number.isFinite(r)||r<1||r>30)throw Error(`fps must be between 1 and 30`);try{let i=`(async () => {
133
+ })()`)).result?.value||{error:`Failed to get page state`};case`SEMANTIC_LOCAL_COMPARE`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.sendMessage(n,{type:`SEMANTIC_LOCAL_COMPARE`,ref:e.ref,predicate:e.predicate,expectedIdentity:e.expectedIdentity},{frameId:F(n,e)});case`SEMANTIC_SCROLL_SCOPE`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.sendMessage(n,{type:`SEMANTIC_SCROLL_SCOPE`,action:e.action,scopeToken:e.scopeToken,expectedIdentity:e.expectedIdentity},{frameId:F(n,e)});case`EXECUTE_SCROLL`:{if(!n)throw Error(`No tabId provided`);let t=e.deltaX||0,r=e.deltaY||0;if(e.expectedIdentity)return await chrome.tabs.sendMessage(n,{type:`SEMANTIC_SCROLL`,deltaX:t,deltaY:r,expectedIdentity:e.expectedIdentity},{frameId:F(n,e)});let i=(e,t)=>{let n={x:window.scrollX,y:window.scrollY};window.scrollBy(e,t);let r={x:window.scrollX,y:window.scrollY};return{scrollX:r.x,scrollY:r.y,pageHeight:document.documentElement.scrollHeight,viewportHeight:window.innerHeight,scrolled:n.x!==r.x||n.y!==r.y}};try{return(await M.evaluateScript(n,`(${i.toString()})(${t}, ${r})`)).result?.value||{error:`Script failed`}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:n},func:i,args:[t,r]}))[0]?.result||{error:`Script failed`}}catch{return{error:`Cannot scroll on this page (restricted)`}}}}case`EXECUTE_KEY`:{if(!n)throw Error(`No tabId provided`);let t=e.key;if(!t)throw Error(`No key provided`);return t.includes(`+`)?await M.pressKeyChord(n,t):await M.pressKey(n,t),{success:!0}}case`EXECUTE_NAVIGATE`:{if(!n)throw Error(`No tabId provided`);if(!e.url)throw Error(`No url provided`);if(e.expectedIdentity)return await chrome.tabs.sendMessage(n,{type:`SEMANTIC_NAVIGATE`,url:e.url,expectedIdentity:e.expectedIdentity},{frameId:F(n,e)});let t=new Promise(e=>{X.set(n,e),setTimeout(()=>{X.has(n)&&(X.delete(n),e())},3e4)});return await chrome.tabs.update(n,{url:e.url}),await t,await new Promise(e=>setTimeout(e,500)),{success:!0}}case`GET_VIEWPORT_SIZE`:if(!n)throw Error(`No tabId provided`);return await M.getViewportSize(n);case`READ_PAGE`:{if(!n)throw Error(`No tabId provided`);let t=F(n,e);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));let r;try{r=await chrome.tabs.sendMessage(n,{type:`GENERATE_ACCESSIBILITY_TREE`,options:e.options||{}},{frameId:t})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}if(e.options?.includeText)try{let i=await chrome.tabs.sendMessage(n,{type:`GET_PAGE_TEXT`,options:{compact:e.options?.compact===!0,maxBytes:e.options?.maxBytes}},{frameId:t});i?.text&&(r.text=i.text)}catch{}if(e.options?.includeScreenshot)try{let e=await M.captureScreenshot(n);return{...r,screenshot:e}}catch(e){return{...r,screenshotError:e instanceof Error?e.message:`Failed to capture screenshot`}}return r?.semanticObservation?.identity&&(r.semanticObservation.identity.tabId=n,r.semanticObservation.identity.frameId=t),r}case`GET_ELEMENT_COORDINATES`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:`GET_ELEMENT_COORDINATES`,ref:e.ref},{frameId:F(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`FORM_INPUT`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:`FORM_INPUT`,ref:e.ref,value:e.value},{frameId:F(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`EVAL_IN_PAGE`:if(!n)throw Error(`No tabId provided`);if(!e.code)throw Error(`No code provided`);try{return await chrome.tabs.sendMessage(n,{type:`EVAL_IN_PAGE`,code:e.code},{frameId:F(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`SCROLL_TO_ELEMENT`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:`SCROLL_TO_ELEMENT`,ref:e.ref},{frameId:F(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`SCROLL_TO_POSITION`:{if(!n)throw Error(`No tabId provided`);let t=e.position;if(t===void 0)throw Error(`position required ("top", "bottom", or number)`);let r=e.selector;if(e.expectedIdentity)return await chrome.tabs.sendMessage(n,{type:`SEMANTIC_SCROLL`,position:t,expectedIdentity:e.expectedIdentity},{frameId:F(n,e)});try{return await chrome.tabs.sendMessage(n,{type:`SCROLL_TO_POSITION`,position:t,selector:r},{frameId:F(n,e)})}catch{}let i=(e,t)=>{let n=t&&document.querySelector(t)||[...document.querySelectorAll(`*`)].filter(e=>e.scrollHeight>e.clientHeight&&e.clientHeight>200).sort((e,t)=>t.scrollHeight-e.scrollHeight)[0]||document.documentElement;return n?(e===`bottom`?n.scrollTop=n.scrollHeight:e===`top`?n.scrollTop=0:typeof e==`number`&&(n.scrollTop=e),{scrollTop:n.scrollTop,scrollHeight:n.scrollHeight,clientHeight:n.clientHeight,atBottom:n.scrollTop+n.clientHeight>=n.scrollHeight-10,atTop:n.scrollTop<10}):{error:`No scrollable container found`}};try{let e=`(${i.toString()})(${JSON.stringify(t)}, ${JSON.stringify(r)})`;return(await M.evaluateScript(n,e)).result?.value||{error:`Script failed`}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:n},func:i,args:[t,r]}))[0]?.result||{error:`Script failed`}}catch{return{error:`Cannot scroll on this page (restricted)`}}}}case`GET_SCROLL_INFO`:{if(!n)throw Error(`No tabId provided`);let t=e.selector,r=e=>{let t=e&&document.querySelector(e)||[...document.querySelectorAll(`*`)].filter(e=>e.scrollHeight>e.clientHeight&&e.clientHeight>200).sort((e,t)=>t.scrollHeight-e.scrollHeight)[0]||document.documentElement;if(!t)return{error:`No scrollable container found`};let n=t.scrollHeight-t.clientHeight;return{scrollTop:t.scrollTop,scrollHeight:t.scrollHeight,clientHeight:t.clientHeight,atBottom:t.scrollTop+t.clientHeight>=t.scrollHeight-10,atTop:t.scrollTop<10,scrollPercentage:n>0?Math.round(t.scrollTop/n*100):100}};try{let e=`(${r.toString()})(${JSON.stringify(t)})`;return(await M.evaluateScript(n,e)).result?.value||{error:`Script failed`}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:n},func:r,args:[t]}))[0]?.result||{error:`Script failed`}}catch{return{error:`Cannot get scroll info on this page (restricted)`}}}}case`GET_PAGE_TEXT`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:`GET_PAGE_TEXT`},{frameId:F(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`GET_PAGE_HTML`:{if(!n)throw Error(`No tabId provided`);let t=(await chrome.scripting.executeScript({target:{tabId:n,frameIds:[F(n,e)]},func:(e,t)=>{if(e!==void 0&&(typeof e!=`string`||e.length===0))throw Error(`selector must be a non-empty string`);let n=e===void 0?document.documentElement:document.querySelector(e);if(!n)throw Error(`No element matches selector "${e}"`);let r=t?n.cloneNode(!0):n;if(t){if(r.matches(`script`))return``;r.querySelectorAll(`script`).forEach(e=>e.remove())}return(e===void 0&&document.doctype?`<!doctype ${document.doctype.name}>\n`:``)+r.outerHTML},args:[e.selector,e.stripScripts]}))[0]?.result;if(typeof t!=`string`)throw Error(`Page HTML extraction returned an invalid result`);return{html:t}}case`LOCATE_ROLE`:{if(!n)throw Error(`No tabId provided`);if(!e.role)throw Error(`role required`);let t=F(n,e);try{let r=await chrome.tabs.sendMessage(n,{type:`LOCATE_ROLE`,role:e.role,name:e.name,all:e.all},{frameId:t});return r.error?r:e.action&&r.ref?await $(n,r.ref,e.action,e.value,M,t):r}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`LOCATE_TEXT`:{if(!n)throw Error(`No tabId provided`);if(!e.text)throw Error(`text required`);let t=F(n,e);try{let r=await chrome.tabs.sendMessage(n,{type:`LOCATE_TEXT`,text:e.text,exact:e.exact},{frameId:t});return r.error?r:e.action&&r.ref?await $(n,r.ref,e.action,e.value,M,t):r}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`LOCATE_LABEL`:{if(!n)throw Error(`No tabId provided`);if(!e.label)throw Error(`label required`);let t=F(n,e);try{let r=await chrome.tabs.sendMessage(n,{type:`LOCATE_LABEL`,label:e.label},{frameId:t});return r.error?r:e.action&&r.ref?await $(n,r.ref,e.action,e.value,M,t):r}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`GET_ELEMENT_STYLES`:{if(!n)throw Error(`No tabId provided`);if(!e.selector)throw Error(`selector required`);let t=F(n,e);try{return await chrome.tabs.sendMessage(n,{type:`GET_ELEMENT_STYLES`,selector:e.selector},{frameId:t})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`SELECT_OPTION`:{if(!n)throw Error(`No tabId provided`);if(!e.selector)throw Error(`selector required`);if(!e.values)throw Error(`values required`);let t=F(n,e);try{return await chrome.tabs.sendMessage(n,{type:`SELECT_OPTION`,selector:e.selector,values:e.values,by:e.by||`value`},{frameId:t})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`SHOW_AGENT_INDICATORS`:case`HIDE_AGENT_INDICATORS`:case`SHOW_STATIC_INDICATOR`:case`HIDE_STATIC_INDICATOR`:if(!n)throw Error(`No tabId provided`);try{return await chrome.tabs.sendMessage(n,{type:e.type},{frameId:0})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`STOP_AGENT`:{let n=e.fromTabId,r;return n===`CURRENT_TAB`&&t.tab?.id?r=t.tab.id:typeof n==`number`&&(r=n),r&&chrome.runtime.sendMessage({type:`STOP_AGENT`,targetTabId:r}),{success:!0}}case`DISMISS_STATIC_INDICATOR`:return{success:!0};case`STATIC_INDICATOR_HEARTBEAT`:return{success:!0};case`CLICK_REF`:if(!n)throw Error(`No tabId provided`);try{let t=await chrome.tabs.sendMessage(n,{type:`CLICK_ELEMENT`,ref:e.ref,button:e.button||`left`,expectedIdentity:e.expectedIdentity},{frameId:F(n,e)});return t.error?{error:t.error,code:t.code}:{success:!0}}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`HOVER_REF`:if(!n)throw Error(`No tabId provided`);try{let t=await chrome.tabs.sendMessage(n,{type:`GET_ELEMENT_COORDINATES`,ref:e.ref},{frameId:F(n,e)});return t.error?{error:t.error}:(await M.hover(n,t.x,t.y),{success:!0})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`PING`:return{success:!0,status:`connected`};case`HEALTH_CHECK_URL`:{if(!e.url)throw Error(`No url provided`);let t=e.timeout||3e4,n=e.expect||200,r=Date.now(),i=null;for(;Date.now()-r<t;){try{let t=await fetch(e.url,{method:`GET`});if(await t.text(),t.status===n)return{success:!0,status:t.status,time:Date.now()-r};i=`Got status ${t.status}`}catch(e){i=e instanceof Error?e.message:String(e)}await new Promise(e=>setTimeout(e,500))}return{error:`Timeout waiting for ${e.url} to return ${n}`,lastError:i,time:Date.now()-r}}case`SMOKE_TEST`:{let t=e.urls||[],n=e.savePath!==void 0,r=e.failFast||!1;if(t.length===0)return{error:`No URLs provided for smoke test`};let i=[],a=0,o=0;for(let e of t){let t=Date.now(),s=[],c,l,u;try{l=new URL(e).hostname.replace(/[^a-zA-Z0-9.-]/g,`_`);let t=await chrome.tabs.create({url:e,active:!1});if(!t.id)throw Error(`Failed to create tab`);u=t.id;try{await M.enableConsoleTracking(u)}catch{}await new Promise(e=>{let t=r=>{r.tabId===u&&r.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(t),chrome.webNavigation.onErrorOccurred.removeListener(n),e())},n=r=>{r.tabId===u&&r.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(t),chrome.webNavigation.onErrorOccurred.removeListener(n),s.push(`Navigation error: ${r.error}`),e())};chrome.webNavigation.onCompleted.addListener(t),chrome.webNavigation.onErrorOccurred.addListener(n),setTimeout(()=>{chrome.webNavigation.onCompleted.removeListener(t),chrome.webNavigation.onErrorOccurred.removeListener(n),s.push(`Navigation timeout (30s)`),e()},3e4)}),await new Promise(e=>setTimeout(e,2e3));let r=M.getConsoleMessages(u,{onlyErrors:!0,limit:50});for(let e of r)s.push(`[${e.type}] ${e.text}`);if(n)try{c=(await M.captureScreenshot(u)).base64}catch{}}catch(e){s.push(e instanceof Error?e.message:String(e))}finally{if(u)try{await chrome.tabs.remove(u)}catch{}}let d=Date.now()-t,f=s.length===0?`pass`:`fail`;if(f===`pass`?a++:o++,i.push({url:e,status:f,time:d,errors:s,...c&&{screenshotBase64:c,hostname:l}}),r&&f===`fail`)break}return{results:i,summary:{pass:a,fail:o,total:i.length},savePath:e.savePath}}case`WAIT_FOR_ELEMENT`:{if(!n)throw Error(`No tabId provided`);if(!e.selector)throw Error(`No selector provided`);let t=F(n,e);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(n,{type:`WAIT_FOR_ELEMENT`,selector:e.selector,state:e.state||`visible`,timeout:e.timeout||2e4},{frameId:t})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}}case`WAIT_FOR_URL`:if(!n)throw Error(`No tabId provided`);if(!e.pattern)throw Error(`No URL pattern provided`);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(n,{type:`WAIT_FOR_URL`,pattern:e.pattern,timeout:e.timeout||2e4},{frameId:0})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}case`WAIT_FOR_NETWORK_IDLE`:if(!n)throw Error(`No tabId provided`);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(n,{type:`WAIT_FOR_NETWORK_IDLE`,timeout:e.timeout||1e4},{frameId:0})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}case`PAGE_READINESS`:if(!n)throw Error(`No tabId provided`);return await V(n,B(e.expect));case`WAIT_FOR_READY`:{if(!n)throw Error(`No tabId provided`);let t=B(e.expect),r=le({timeoutMs:e.timeout,intervalMs:e.interval}),i=oe(e.accept),a=await de({...r,accept:i,probe:()=>V(n,t)}),o={state:a.result.state,evidence:a.result.evidence,href:a.result.href,title:a.result.title,readyState:a.result.readyState,tabStatus:a.result.tabStatus,polls:a.polls,waited:a.waitedMs,timeout:r.timeoutMs,interval:r.intervalMs};if(a.kind===`settled`||a.kind===`accepted`)return{accepted:a.kind===`accepted`,...o};throw a.kind===`timeout`?new L(`page_timeout`,`Page did not become ready within ${r.timeoutMs}ms; last state ${H(a.result)}`,{...o,tabId:n}):new L(ie(a.result.state)??`page_not_ready`,`Page is not ready: ${H(a.result)}`,{...o,tabId:n})}case`WAIT_FOR_DOM_STABLE`:if(!n)throw Error(`No tabId provided`);try{await chrome.tabs.sendMessage(n,{type:`HIDE_FOR_TOOL_USE`},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(n,{type:`WAIT_FOR_DOM_STABLE`,stable:e.stable||100,timeout:e.timeout||5e3},{frameId:0})}catch{return{error:`Content script not loaded. Try refreshing the page.`,pageContent:``,viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(n,{type:`SHOW_AFTER_TOOL_USE`},{frameId:0})}catch{}}case`DIALOG_ACCEPT`:if(!n)throw Error(`No tabId provided`);return await M.handleDialog(n,!0,e.text);case`DIALOG_DISMISS`:if(!n)throw Error(`No tabId provided`);return await M.handleDialog(n,!1);case`DIALOG_INFO`:{if(!n)throw Error(`No tabId provided`);let e=M.getDialogInfo(n);return e?{hasDialog:!0,type:e.type,message:e.message,defaultPrompt:e.defaultPrompt}:{hasDialog:!1}}case`EMULATE_NETWORK`:{if(!n)throw Error(`No tabId provided`);if(!e.preset)throw Error(`No preset provided`);let t=await M.emulateNetwork(n,e.preset);if(!t.success)throw Error(t.error);return{success:!0,preset:e.preset}}case`EMULATE_CPU`:{if(!n)throw Error(`No tabId provided`);if(e.rate===void 0)throw Error(`No rate provided`);let t=await M.emulateCPU(n,e.rate);if(!t.success)throw Error(t.error);return{success:!0,rate:e.rate}}case`EMULATE_GEO`:{if(!n)throw Error(`No tabId provided`);if(e.clear){let e=await M.clearGeolocation(n);if(!e.success)throw Error(e.error);return{success:!0,cleared:!0}}if(e.latitude===void 0||e.longitude===void 0)throw Error(`Latitude and longitude required`);let t=await M.emulateGeolocation(n,e.latitude,e.longitude,e.accuracy);if(!t.success)throw Error(t.error);return{success:!0,latitude:e.latitude,longitude:e.longitude}}case`EMULATE_DEVICE_LIST`:return{devices:[`iPhone 12`,`iPhone 13`,`iPhone 14`,`iPhone 14 Pro`,`iPhone 14 Pro Max`,`iPhone SE`,`iPad`,`iPad Pro`,`iPad Mini`,`Pixel 5`,`Pixel 6`,`Pixel 7`,`Pixel 7 Pro`,`Galaxy S21`,`Galaxy S22`,`Galaxy S23`,`Galaxy Tab S7`,`Nest Hub`,`Nest Hub Max`]};case`EMULATE_DEVICE`:{if(!n)throw Error(`No tabId provided`);let t=e.device;if(t.toLowerCase()===`reset`){let e=await M.clearDeviceEmulation(n);if(!e.success)throw Error(e.error);return{success:!0,message:`Device emulation reset`}}let r={"iPhone 12":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1`},"iPhone 13":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1`},"iPhone 14":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1`},"iPhone 14 Pro":{width:393,height:852,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1`},"iPhone 14 Pro Max":{width:430,height:932,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1`},"iPhone SE":{width:375,height:667,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1`},iPad:{width:768,height:1024,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1`},"iPad Pro":{width:1024,height:1366,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1`},"iPad Mini":{width:768,height:1024,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1`},"Pixel 5":{width:393,height:851,deviceScaleFactor:2.75,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36`},"Pixel 6":{width:412,height:915,deviceScaleFactor:2.625,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36`},"Pixel 7":{width:412,height:915,deviceScaleFactor:2.625,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36`},"Pixel 7 Pro":{width:412,height:892,deviceScaleFactor:3.5,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 13; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36`},"Galaxy S21":{width:360,height:800,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36`},"Galaxy S22":{width:360,height:780,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 12; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36`},"Galaxy S23":{width:360,height:780,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36`},"Galaxy Tab S7":{width:800,height:1280,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Safari/537.36`},"Nest Hub":{width:1024,height:600,deviceScaleFactor:2,mobile:!1,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666`},"Nest Hub Max":{width:1280,height:800,deviceScaleFactor:2,mobile:!1,touch:!0,userAgent:`Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666`}},i={iphone:`iPhone 14`,iphone14:`iPhone 14`,iphone13:`iPhone 13`,iphone12:`iPhone 12`,iphonese:`iPhone SE`,pixel:`Pixel 7`,pixel7:`Pixel 7`,pixel6:`Pixel 6`,galaxy:`Galaxy S23`,galaxys23:`Galaxy S23`,ipad:`iPad`,ipadpro:`iPad Pro`},a=r[t];if(a||=r[i[t.toLowerCase().replace(/\s+/g,``)]],!a){let e=t.toLowerCase(),n=null;for(let[t,i]of Object.entries(r)){let r=t.toLowerCase(),a=r.replace(/\s+/g,``);(r.includes(e)||e.includes(a))&&(!n||t.length>n.name.length)&&(n={name:t,preset:i})}n&&(a=n.preset)}if(!a)throw Error(`Unknown device: ${t}. Use --list to see available devices.`);let o=await M.emulateDevice(n,a);if(!o.success)throw Error(o.error);return{success:!0,device:t}}case`EMULATE_VIEWPORT`:{if(!n)throw Error(`No tabId provided`);if(!e.width&&!e.height)throw Error(`--width or --height required`);let t=await M.emulateViewport(n,{width:e.width,height:e.height,deviceScaleFactor:e.deviceScaleFactor,mobile:e.mobile});if(!t.success)throw Error(t.error);return{success:!0,width:e.width,height:e.height}}case`EMULATE_TOUCH`:{if(!n)throw Error(`No tabId provided`);let t=await M.emulateTouch(n,e.enabled);if(!t.success)throw Error(t.error);return{success:!0,enabled:e.enabled}}case`FORM_FILL`:if(!n)throw Error(`No tabId provided`);if(!e.data)throw Error(`No data provided`);return await chrome.tabs.sendMessage(n,{type:`FORM_FILL`,data:e.data,expectedIdentity:e.expectedIdentity},{frameId:F(n,e)});case`PERF_START`:{if(!n)throw Error(`No tabId provided`);let t=await M.startPerformanceTrace(n,e.categories);if(!t.success)throw Error(t.error);return{success:!0,message:`Performance tracing started`}}case`PERF_STOP`:{if(!n)throw Error(`No tabId provided`);let e=await M.stopPerformanceTrace(n);if(!e.success)throw Error(e.error);return{success:!0,metrics:e.metrics}}case`PERF_METRICS`:{if(!n)throw Error(`No tabId provided`);let e=await M.getPerformanceMetrics(n);if(!e.success)throw Error(e.error);return{success:!0,metrics:e.metrics}}case`UPLOAD_FILE`:{if(!n)throw Error(`No tabId provided`);if(!e.ref)throw Error(`No ref provided`);if(!e.files||!e.files.length)throw Error(`No files provided`);let t=await chrome.tabs.sendMessage(n,{type:`GET_FILE_INPUT_SELECTOR`,ref:e.ref},{frameId:F(n,e)});if(t.error)throw Error(t.error);let r=await M.setFileInputBySelector(n,t.selector,e.files);if(!r.success)throw Error(r.error);return{success:!0,filesSet:e.files.length}}case`WAIT_FOR_LOAD`:{if(!n)throw Error(`No tabId provided`);let t=await M.waitForLoad(n,e.timeout||3e4);if(!t.success)throw Error(t.error);return{success:!0,readyState:t.readyState}}case`GET_FRAMES`:{if(!n)throw Error(`No tabId provided`);let e=await M.getFrames(n);if(!e.success)throw Error(e.error);return{success:!0,frames:e.frames}}case`FRAME_DIAGNOSE`:{if(!n)throw Error(`No tabId provided`);let e=await xe(n),t={href:e.find(e=>e.parentFrameId===-1)?.url??``,title:``,iframes:[]},r=[],i=!0,a=[],o=!M.isAttached(n);try{if(o)try{await M.attach(n)}catch(e){let t=e instanceof Error?e.message:String(e);a.push(`CDP inventories unavailable: ${t}`),i=!1}if(M.isAttached(n)){try{t=await be(n)}catch(e){let t=e instanceof Error?e.message:String(e);a.push(`DOM iframe inventory unavailable: ${t}`)}try{let e=await M.getFrames(n);e.success?r=e.frames??[]:(a.push(`CDP frame tree unavailable: ${e.error}`),i=!1)}catch(e){let t=e instanceof Error?e.message:String(e);a.push(`CDP frame tree unavailable: ${t}`),i=!1}}}finally{if(o&&M.isAttached(n)){let e=await M.detach(n);e.success||a.push(`CDP detach failed: ${e.error}`)}}let s=te({mainPage:{href:t.href,title:t.title},domIframes:t.iframes,extensionFrames:e,cdpFrames:r,cdpFramesAvailable:i});return s.warnings.unshift(...a),s}case`FRAME_SWITCH`:{if(!n)throw Error(`No tabId provided`);let{selector:t,name:r,index:i}=e;if(!t&&!r&&i===void 0)throw Error(`--selector, --name, or --index required`);let a=await chrome.webNavigation.getAllFrames({tabId:n});if(!a||a.length===0)throw Error(`No frames found in tab`);let o=a.filter(e=>e.frameId!==0);if(o.length===0)throw Error(`No iframes found on this page`);let s=null;if(i!==void 0){if(i<0||i>=o.length)throw Error(`Frame index ${i} out of range. Found ${o.length} frame(s).`);s=o[i]}else if(r){for(let e of o)try{if((await chrome.tabs.sendMessage(n,{type:`GET_FRAME_NAME`},{frameId:e.frameId}))?.name===r){s=e;break}}catch{}if(!s)throw Error(`Frame with name "${r}" not found`)}else if(t)try{let e=await chrome.tabs.sendMessage(n,{type:`GET_FRAME_BY_SELECTOR`,selector:t},{frameId:0});if(e?.error)throw Error(e.error);e?.url&&(s=o.find(t=>t.url===e.url)||null),!s&&o.length===1&&(s=o[0])}catch{throw Error(`Could not find frame with selector "${t}"`)}if(!s)throw Error(`Frame not found`);return{success:!0,frameId:s.frameId,url:s.url}}case`FRAME_MAIN`:if(!n)throw Error(`No tabId provided`);return{success:!0,message:`Returned to main frame`};case`EVALUATE_IN_FRAME`:{if(!n)throw Error(`No tabId provided`);if(!e.frameId)throw Error(`No frameId provided`);if(!e.code)throw Error(`No code provided`);let t=await M.evaluateInFrame(n,e.frameId,e.code);if(!t.success)throw Error(t.error);return{value:t.result}}case`EXECUTE_JAVASCRIPT`:if(!n)throw Error(`No tabId provided`);if(!e.code)throw Error(`No code provided`);try{await M.evaluateScript(n,`if(!window.piHelpers){const piHelpers={wait(ms){return new Promise(r=>setTimeout(r,ms))},setValue(el,v,events=['input','change']){let p=Object.getPrototypeOf(el),s=null;while(p&&p!==Object.prototype){const d=Object.getOwnPropertyDescriptor(p,'value');if(d&&d.set){s=d.set;break}p=Object.getPrototypeOf(p)}if(s)s.call(el,v);else el.value=v;for(const n of events)el.dispatchEvent(new Event(n,{bubbles:n!=='blur'}));return el},async waitForSelector(sel,opts={}){const{state='visible',timeout=20000}=opts;const isVis=el=>el&&getComputedStyle(el).display!=='none'&&getComputedStyle(el).visibility!=='hidden'&&getComputedStyle(el).opacity!=='0'&&el.offsetWidth>0&&el.offsetHeight>0;const chk=()=>{const el=document.querySelector(sel);switch(state){case'attached':return el;case'detached':return el?null:document.body;case'hidden':return(!el||!isVis(el))?(el||document.body):null;default:return isVis(el)?el:null}};return new Promise((res,rej)=>{const r=chk();if(r){res(state==='detached'||state==='hidden'?null:r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(state==='detached'||state==='hidden'?null:r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['style','class','hidden']})})},async waitForText(text,opts={}){const{selector,timeout=20000}=opts;const chk=()=>{const root=selector?document.querySelector(selector):document.body;if(!root)return null;const w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);while(w.nextNode())if(w.currentNode.textContent?.includes(text))return w.currentNode.parentElement;return null};return new Promise((res,rej)=>{const r=chk();if(r){res(r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,characterData:true})})},async waitForHidden(sel,t=20000){await piHelpers.waitForSelector(sel,{state:'hidden',timeout:t})},getByRole(role,opts={}){const{name}=opts;const roles={button:['button','input[type=button]','input[type=submit]','input[type=reset]'],link:['a[href]'],textbox:['input:not([type])','input[type=text]','input[type=email]','input[type=password]','textarea'],checkbox:['input[type=checkbox]'],radio:['input[type=radio]'],combobox:['select'],heading:['h1','h2','h3','h4','h5','h6']};const cands=[...document.querySelectorAll('[role='+role+']')];if(roles[role])roles[role].forEach(s=>cands.push(...document.querySelectorAll(s+':not([role])')));if(!name)return cands[0]||null;const n=name.toLowerCase().trim();for(const el of cands){const l=el.getAttribute('aria-label')?.toLowerCase().trim();const t=el.textContent?.toLowerCase().trim();if(l===n||t===n||l?.includes(n)||t?.includes(n))return el}return null}};window.__piHelpers=piHelpers;window.piHelpers=piHelpers}`);let t=je(e.code),r=`(async () => { 'use strict'; ${t} })()`,i=await M.evaluateScript(n,r);if(i.exceptionDetails&&!await Me(n,t)&&(i=await M.evaluateScript(n,`(async () => { 'use strict'; ${e.code} })()`)),i.exceptionDetails)return{error:i.exceptionDetails.exception?.description||i.exceptionDetails.text||`Script execution failed`};let a=i.result?.value;return{output:(a===void 0?`undefined`:JSON.stringify(a,null,2))?.substring(0,5e4)||`undefined`}}catch(e){let t=e instanceof Error?e.message:`Script execution failed`;return t.includes(`Cannot access`)||t.includes(`Cannot attach`)?{error:`Cannot execute JavaScript on this page (restricted URL)`}:{error:t}}case`ANIMATE_AUDIT`:{if(!n)throw Error(`No tabId provided`);if(!e.selector||typeof e.selector!=`string`)throw Error(`selector required`);if(typeof e.durationMs==`boolean`)throw Error(`duration must be a number`);if(typeof e.fps==`boolean`)throw Error(`fps must be a number`);let t=e.durationMs===void 0?2e3:Number(e.durationMs),r=e.fps===void 0?10:Number(e.fps);if(!Number.isFinite(t)||t<100||t>1e4)throw Error(`duration must be between 100 and 10000 ms`);if(!Number.isFinite(r)||r<1||r>30)throw Error(`fps must be between 1 and 30`);try{let i=`(async () => {
105
134
  const selector = ${JSON.stringify(e.selector)};
106
135
  const durationMs = ${Math.round(t)};
107
136
  const fps = ${Math.round(r)};
@@ -159,7 +188,7 @@ var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],en
159
188
  sampleCount: samples.length,
160
189
  samples,
161
190
  };
162
- })()`,a=await O.evaluateScript(n,i);return a.exceptionDetails?{error:a.exceptionDetails.exception?.description||a.exceptionDetails.text||`Animation audit failed`}:a.result?.value??{error:`Animation audit returned no data`}}catch(e){let t=e instanceof Error?e.message:`Animation audit failed`;return t.includes(`Cannot access`)||t.includes(`Cannot attach`)?{error:`Cannot execute animation audit on this page (restricted URL)`}:{error:t}}}case`PERF_AUDIT`:{if(!n)throw Error(`No tabId provided`);if(typeof e.durationMs==`boolean`)throw Error(`duration must be a number`);if(e.trigger!==void 0&&typeof e.trigger!=`string`)throw Error(`trigger must be action:target`);let t=e.durationMs===void 0?3e3:Number(e.durationMs);if(!Number.isFinite(t)||t<100||t>1e4)throw Error(`duration must be between 100 and 10000 ms`);try{let r=`(async () => {
191
+ })()`,a=await M.evaluateScript(n,i);return a.exceptionDetails?{error:a.exceptionDetails.exception?.description||a.exceptionDetails.text||`Animation audit failed`}:a.result?.value??{error:`Animation audit returned no data`}}catch(e){let t=e instanceof Error?e.message:`Animation audit failed`;return t.includes(`Cannot access`)||t.includes(`Cannot attach`)?{error:`Cannot execute animation audit on this page (restricted URL)`}:{error:t}}}case`PERF_AUDIT`:{if(!n)throw Error(`No tabId provided`);if(typeof e.durationMs==`boolean`)throw Error(`duration must be a number`);if(e.trigger!==void 0&&typeof e.trigger!=`string`)throw Error(`trigger must be action:target`);let t=e.durationMs===void 0?3e3:Number(e.durationMs);if(!Number.isFinite(t)||t<100||t>1e4)throw Error(`duration must be between 100 and 10000 ms`);try{let r=`(async () => {
163
192
  const durationMs = ${Math.round(t)};
164
193
  const trigger = ${JSON.stringify(e.trigger||null)};
165
194
  const startedAt = Date.now();
@@ -340,7 +369,7 @@ var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],en
340
369
  },
341
370
  entries,
342
371
  };
343
- })()`,i=await O.evaluateScript(n,r);return i.exceptionDetails?{error:i.exceptionDetails.exception?.description||i.exceptionDetails.text||`Performance audit failed`}:i.result?.value??{error:`Performance audit returned no data`}}catch(e){let t=e instanceof Error?e.message:`Performance audit failed`;return t.includes(`Cannot access`)||t.includes(`Cannot attach`)?{error:`Cannot execute performance audit on this page (restricted URL)`}:{error:t}}}case`READ_CONSOLE_MESSAGES`:{if(!n)throw Error(`No tabId provided`);try{await O.enableConsoleTracking(n)}catch{}let t=O.getConsoleMessages(n,{onlyErrors:e.onlyErrors,pattern:e.pattern,limit:e.limit||100});return e.clear&&O.clearConsoleMessages(n),{messages:t}}case`CLEAR_CONSOLE_MESSAGES`:if(!n)throw Error(`No tabId provided`);return O.clearConsoleMessages(n),{success:!0};case`START_NETWORK_CAPTURE`:if(!n)throw Error(`No tabId provided`);return O.clearNetworkRequests(n),await O.enableNetworkTracking(n,{bodyMode:e.bodyMode||`text`,perBodyBytes:e.perBodyBytes,totalBytes:e.totalBodyBytes}),{success:!0};case`STOP_NETWORK_CAPTURE`:if(!n)throw Error(`No tabId provided`);return await O.disableNetworkTracking(n),{success:!0};case`GET_PLAYBOOK_RECORD_CONTEXT`:{if(!n)throw Error(`No tabId provided`);let e=await chrome.tabs.get(n),t;try{if(e.url){let n=new URL(e.url);(n.protocol===`http:`||n.protocol===`https:`)&&(t=n.origin)}}catch{}return{success:!0,origin:t,url:e.url}}case`START_PLAYBOOK_WATCH`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.sendMessage(n,{type:`PLAYBOOK_WATCH_START`,includeInputValues:e.includeInputValues===!0},{frameId:0}),{success:!0};case`STOP_PLAYBOOK_WATCH`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.sendMessage(n,{type:`PLAYBOOK_WATCH_STOP`},{frameId:0}).catch(()=>{}),{success:!0};case`PLAYBOOK_WATCH_EVENT`:return S({...e,tabId:t.tab?.id,type:`PLAYBOOK_WATCH_EVENT`}),{success:!0};case`READ_NETWORK_REQUESTS`:{if(!n)throw Error(`No tabId provided`);try{e.bodyMode!==void 0||e.perBodyBytes!==void 0||e.totalBodyBytes!==void 0?await O.enableNetworkTracking(n,{bodyMode:e.bodyMode,perBodyBytes:e.perBodyBytes,totalBytes:e.totalBodyBytes}):await O.enableNetworkTracking(n)}catch{}if(await O.drainNetworkEvents(n),e.full){let t=O.getNetworkEntries(n,{urlPattern:e.urlPattern});e.method&&(t=t.filter(t=>t.method===e.method)),e.status&&(t=t.filter(t=>t.status===e.status)),e.contentType&&(t=t.filter(t=>t.type===e.contentType)),e.clear&&O.clearNetworkRequests(n);let r=e.limit||100;return{entries:t.slice(0,r),format:e.format,verbose:e.verbose}}let t=O.getNetworkRequests(n,{urlPattern:e.urlPattern,limit:e.limit||100});return e.method&&(t=t.filter(t=>t.method===e.method)),e.status&&(t=t.filter(t=>t.status===e.status)),e.contentType&&(t=t.filter(t=>t.type===e.contentType)),e.clear&&O.clearNetworkRequests(n),{requests:t,format:e.format,verbose:e.verbose}}case`EXPORT_NETWORK_REQUESTS`:{if(!n)throw Error(`No tabId provided`);if(e.har&&e.jsonl)throw Error(`network export cannot combine HAR and JSONL`);try{e.bodyMode!==void 0||e.perBodyBytes!==void 0||e.totalBodyBytes!==void 0?await O.enableNetworkTracking(n,{bodyMode:e.bodyMode,perBodyBytes:e.perBodyBytes,totalBytes:e.totalBodyBytes}):await O.enableNetworkTracking(n)}catch{}await O.drainNetworkEvents(n);let t=O.getNetworkEntries(n,{});if(new TextEncoder().encode(JSON.stringify(t)).byteLength>16777216)throw Error(`network export source exceeds the 16 MiB native-message limit`);return{entries:t,har:!!e.har,jsonl:!!e.jsonl}}case`CLEAR_NETWORK_REQUESTS`:if(!n)throw Error(`No tabId provided`);return O.clearNetworkRequests(n),{success:!0};case`GET_NETWORK_ENTRIES`:{if(!n)throw Error(`No tabId provided`);try{await O.enableNetworkTracking(n)}catch{}await O.drainNetworkEvents(n);let t=O.getNetworkEntries(n,{urlPattern:e.urlPattern,includeStatic:!e.excludeStatic});return e.origin&&(t=t.filter(t=>t.origin===e.origin)),e.method&&(t=t.filter(t=>t.method===e.method)),e.status&&(t=t.filter(t=>t.status===e.status)),e.type&&(t=t.filter(t=>t.type===e.type)),e.since&&(t=t.filter(t=>t.ts>=e.since)),e.hasBody!==void 0&&(t=t.filter(t=>e.hasBody?t.responseBodySize&&t.responseBodySize>0:!t.responseBodySize)),e.last&&(t=t.slice(-e.last)),e.clear&&O.clearNetworkRequests(n),{entries:t}}case`GET_NETWORK_ENTRY`:{if(!n)throw Error(`No tabId provided`);if(!e.requestId)throw Error(`No requestId provided`);await O.drainNetworkEvents(n);let t=O.getNetworkEntry(n,e.requestId);return t||=O.getNetworkEntries(n,{}).find(t=>t.id===e.requestId)||null,t||=O.getNetworkEntries(n,{}).find(t=>t._requestId===e.requestId)||null,t?{entry:t}:{error:`Entry not found: ${e.requestId}`}}case`GET_RESPONSE_BODY`:{if(!n)throw Error(`No tabId provided`);if(!e.requestId)throw Error(`No requestId provided`);await O.drainNetworkEvents(n);let t=e.requestId;if(e.requestId.startsWith(`r_`)){let r=O.getNetworkEntries(n,{}).find(t=>t.id===e.requestId);r&&(t=r._requestId)}return await O.getResponseBody(n,t)}case`GET_NETWORK_ORIGINS`:{if(!n)throw Error(`No tabId provided`);await O.drainNetworkEvents(n);let e=O.getNetworkEntries(n,{}),t={};for(let n of e)t[n.origin]||(t[n.origin]={count:0,lastSeen:0,size:0}),t[n.origin].count++,t[n.origin].lastSeen=Math.max(t[n.origin].lastSeen,n.ts),t[n.origin].size+=n.responseBodySize||0;return{origins:t}}case`GET_NETWORK_STATS`:{if(!n)throw Error(`No tabId provided`);await O.drainNetworkEvents(n);let e=O.getNetworkEntries(n,{}),t={},r={},i={},a=0,o=1/0,s=0;for(let n of e){t[n.origin]||(t[n.origin]=0),t[n.origin]++;let e=n.method||`GET`;if(r[e]=(r[e]||0)+1,n.status){let e=`${Math.floor(n.status/100)}xx`;i[e]=(i[e]||0)+1}a+=n.responseBodySize||0,n.ts<o&&(o=n.ts),n.ts>s&&(s=n.ts)}return{stats:{totalRequests:e.length,totalSize:a,uniqueOrigins:Object.keys(t).length,startTime:o===1/0?null:o,duration:s&&o!==1/0?s-o:0,byMethod:r,byStatus:i}}}case`RESIZE_WINDOW`:{if(!n)throw Error(`No tabId provided`);if(e.width===void 0&&e.height===void 0)throw Error(`width or height required`);let t=await chrome.tabs.get(n);if(!t.windowId)throw Error(`Tab has no window`);let r=e.width===void 0||e.height===void 0?await chrome.windows.get(t.windowId):null,i=e.width===void 0?r?.width:e.width,a=e.height===void 0?r?.height:e.height;if(i===void 0||a===void 0)throw Error(`current window size unavailable`);return await chrome.windows.update(t.windowId,{width:Math.floor(i),height:Math.floor(a)}),{success:!0,width:i,height:a}}case`TABS_CREATE`:{let t=n?await chrome.tabs.get(n):null,r=await chrome.tabs.create({url:e.url||`about:blank`,active:!1});if(!r.id)throw Error(`Failed to create tab`);return t?.groupId&&t.groupId!==chrome.tabGroups.TAB_GROUP_ID_NONE&&await chrome.tabs.group({tabIds:r.id,groupId:t.groupId}),{success:!0,tabId:r.id,url:r.url||e.url||`about:blank`}}case`UPLOAD_IMAGE`:{if(!n)throw Error(`No tabId provided`);if(!e.screenshotId)throw Error(`screenshotId required`);if(!e.ref&&!e.coordinate)throw Error(`ref or coordinate required`);let t=B(e.screenshotId);if(!t)throw Error(`Screenshot not found: ${e.screenshotId}`);try{return await chrome.tabs.sendMessage(n,{type:`UPLOAD_IMAGE`,base64:t.base64,ref:e.ref,coordinate:e.coordinate,filename:e.filename||`screenshot.png`},{frameId:A(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`GET_TABS`:return{tabs:(await chrome.tabs.query({})).map(e=>({id:e.id,title:e.title,url:e.url}))};case`LIST_TABS`:{let t={};return e.windowId&&(t.windowId=e.windowId),{tabs:(await chrome.tabs.query(t)).map(e=>({id:e.id,title:e.title,url:e.url,active:e.active,windowId:e.windowId}))}}case`NEW_TAB`:{let t=e.urls||(e.url?[e.url]:[`about:blank`]),n=[];for(let r=0;r<t.length;r++){let i={url:t[r],active:r===0};e.windowId&&(i.windowId=e.windowId);let a=await chrome.tabs.create(i);a.id&&n.push({tabId:a.id,url:t[r]})}return n.length===1?{success:!0,tabId:n[0].tabId,url:n[0].url}:{success:!0,tabs:n}}case`SWITCH_TAB`:{let t=e.tabId;if(!t)throw Error(`No tabId provided`);let n=await chrome.tabs.update(t,{active:!0});return n.windowId&&await chrome.windows.update(n.windowId,{focused:!0}),{success:!0,tabId:t,url:n.url,title:n.title}}case`CLOSE_TAB`:{let t=e.tabIds||(e.tabId?[e.tabId]:[]);if(t.length===0)throw Error(`No tabId(s) provided`);return await chrome.tabs.remove(t),t.length===1?{success:!0,tabId:t[0]}:{success:!0,closed:t}}case`TAB_MOVE`:{let t=e.tabIds||(e.tabId?[e.tabId]:[]),n=(Array.isArray(t)?t:String(t).split(`,`)).map(e=>Number(e));if(n.length===0)throw Error(`No tabId(s) provided`);if(n.some(e=>!Number.isInteger(e)||e<=0))throw Error(`Invalid tabId(s)`);let r=Number(e.windowId);if(!Number.isInteger(r)||r<=0)throw Error(`No destination windowId provided`);let i=e.index===void 0?-1:Number(e.index);if(!Number.isInteger(i)||i<-1)throw Error(`Invalid tab index`);let a={windowId:r,index:i},o=n.length===1?await chrome.tabs.move(n[0],a):await chrome.tabs.move(n,a);return{success:!0,moved:n,destinationWindowId:r,index:i,tabs:Array.isArray(o)?o:[o]}}case`TABS_REGISTER`:{let t=n;if(!t){let n=e.windowId?{active:!0,windowId:e.windowId}:{active:!0,lastFocusedWindow:!0},[r]=await chrome.tabs.query(n);if(r&&!j(r.url))t=r.id;else throw Error(`Cannot register a restricted browser or extension page. Focus a regular web page, or pass an explicit tabId.`)}if(!t)throw Error(`No active tab found`);if(!e.name)throw Error(`No name provided`);return Y.set(e.name,t),{success:!0,name:e.name,tabId:t}}case`TABS_GET_BY_NAME`:{if(!e.name)throw Error(`No name provided`);let t=Y.get(e.name);if(!t)return{error:`No tab registered with name "${e.name}"`};try{let e=await chrome.tabs.get(t);return{tabId:t,url:e.url,title:e.title}}catch{return Y.delete(e.name),{error:`Tab "${e.name}" no longer exists`}}}case`TABS_LIST_NAMED`:{let e=[];for(let[t,n]of Y)try{let r=await chrome.tabs.get(n);e.push({name:t,tabId:n,url:r.url,title:r.title})}catch{Y.delete(t)}return{tabs:e}}case`TABS_UNREGISTER`:if(!e.name)throw Error(`No name provided`);return Y.delete(e.name)?{success:!0}:{success:!1,error:`No tab registered with name "${e.name}"`};case`GET_AUTH`:{let{sendToNativeHost:e}=await D(async()=>{let{sendToNativeHost:e}=await Promise.resolve().then(()=>u);return{sendToNativeHost:e}},void 0);try{return await e({type:`GET_AUTH`})}catch{return{auth:null,hint:`Native host not connected. Make sure surf native host is installed.`}}}case`NATIVE_API_REQUEST`:{let{sendToNativeHost:t}=await D(async()=>{let{sendToNativeHost:e}=await Promise.resolve().then(()=>u);return{sendToNativeHost:e}},void 0);try{return await t({type:`API_REQUEST`,streamId:e.streamId,url:e.url,method:e.method,headers:e.headers,body:e.body}),{sent:!0}}catch(e){return{error:e instanceof Error?e.message:`Unknown error`}}}case`STREAM_CONSOLE`:{if(!n)throw Error(`No tabId provided`);let t=e.streamId;try{return await O.enableConsoleTracking(n),k.set(t,n),O.subscribeToConsole(n,t,e=>{S({type:`STREAM_EVENT`,streamId:t,event:{type:`console_event`,level:e.type===`exception`?`error`:e.type,text:e.text,timestamp:e.timestamp,url:e.url,line:e.line}})}),{success:!0,streaming:!0}}catch(e){return S({type:`STREAM_ERROR`,streamId:t,error:e instanceof Error?e.message:`Failed to start console stream`}),{error:e instanceof Error?e.message:`Failed to start console stream`}}}case`STREAM_NETWORK`:{if(!n)throw Error(`No tabId provided`);let t=e.streamId;try{return await O.enableNetworkTracking(n),k.set(t,n),O.subscribeToNetwork(n,t,e=>{S({type:`STREAM_EVENT`,streamId:t,event:{type:`network_event`,method:e.method,url:e.url,status:e.status,duration:e.duration,timestamp:e.timestamp}})}),{success:!0,streaming:!0}}catch(e){return S({type:`STREAM_ERROR`,streamId:t,error:e instanceof Error?e.message:`Failed to start network stream`}),{error:e instanceof Error?e.message:`Failed to start network stream`}}}case`STREAM_STOP`:{let t=e.streamId,n=k.get(t);return n!==void 0&&(O.unsubscribeFromConsole(n,t),O.unsubscribeFromNetwork(n,t),k.delete(t)),{success:!0}}case`SEARCH_PAGE`:if(!n)throw Error(`No tabId provided`);if(!e.term)throw Error(`Search term required`);try{return await chrome.tabs.sendMessage(n,{type:`SEARCH_PAGE`,term:e.term,caseSensitive:e.caseSensitive||!1,limit:e.limit||10},{frameId:A(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`TAB_GROUP_CREATE`:{let t=[...e.tabIds||[]],r=e.name||`Surf`,i=[`grey`,`blue`,`red`,`yellow`,`green`,`pink`,`purple`,`cyan`,`orange`].includes(e.color)?e.color:`blue`;if(t.length===0&&n&&t.push(n),t.length===0)throw Error(`No tabs specified`);let a=t.length===1?t[0]:t,o=await chrome.tabGroups.query({title:r}),s;return o.length>0?(s=o[0].id,await chrome.tabs.group({tabIds:a,groupId:s})):(s=await chrome.tabs.group({tabIds:a}),await chrome.tabGroups.update(s,{title:r,color:i,collapsed:!1})),{success:!0,groupId:s,name:r,tabIds:t}}case`TAB_GROUP_REMOVE`:{let t=[...e.tabIds||[]];if(t.length===0&&n&&t.push(n),t.length===0)throw Error(`No tabs specified`);let r=t.length===1?t[0]:t;return await chrome.tabs.ungroup(r),{success:!0,ungrouped:t}}case`TAB_GROUPS_LIST`:{let e=await chrome.tabGroups.query({}),t=[];for(let n of e){let e=await chrome.tabs.query({groupId:n.id});t.push({id:n.id,name:n.title||`(unnamed)`,color:n.color,collapsed:n.collapsed,tabs:e.map(e=>({id:e.id,title:e.title,url:e.url}))})}return{groups:t}}case`CLICK_SELECTOR`:{if(!n)throw Error(`No tabId provided`);let t=e.selector,r=e.index||0,i=A(n,e);if(i>0){let[e]=await chrome.scripting.executeScript({target:{tabId:n,frameIds:[i]},func:(e,t)=>{let n=document.querySelectorAll(e);return n.length===0?{error:`No elements match selector`}:t>=n.length?{error:`Index ${t} out of range (found ${n.length} elements)`}:(n[t].click(),{success:!0,selector:e,index:t,matchCount:n.length})},args:[t,r]});return e?.result||{error:`Failed to click element`}}let a=`(() => {
372
+ })()`,i=await M.evaluateScript(n,r);return i.exceptionDetails?{error:i.exceptionDetails.exception?.description||i.exceptionDetails.text||`Performance audit failed`}:i.result?.value??{error:`Performance audit returned no data`}}catch(e){let t=e instanceof Error?e.message:`Performance audit failed`;return t.includes(`Cannot access`)||t.includes(`Cannot attach`)?{error:`Cannot execute performance audit on this page (restricted URL)`}:{error:t}}}case`READ_CONSOLE_MESSAGES`:{if(!n)throw Error(`No tabId provided`);try{await M.enableConsoleTracking(n)}catch{}let t=M.getConsoleMessages(n,{onlyErrors:e.onlyErrors,pattern:e.pattern,limit:e.limit||100});return e.clear&&M.clearConsoleMessages(n),{messages:t}}case`CLEAR_CONSOLE_MESSAGES`:if(!n)throw Error(`No tabId provided`);return M.clearConsoleMessages(n),{success:!0};case`START_NETWORK_CAPTURE`:if(!n)throw Error(`No tabId provided`);return M.clearNetworkRequests(n),await M.enableNetworkTracking(n,{bodyMode:e.bodyMode||`text`,perBodyBytes:e.perBodyBytes,totalBytes:e.totalBodyBytes}),{success:!0};case`STOP_NETWORK_CAPTURE`:if(!n)throw Error(`No tabId provided`);return await M.disableNetworkTracking(n),{success:!0};case`VIDEO_START`:{if(!n)throw Error(`No tabId provided`);let t=String(e.recorderId||``);if(!t)throw Error(`VIDEO_START requires recorderId`);if(P)throw Error(`A video recording is already active`);let r=Number(e.fps);if(!Number.isFinite(r)||r<=0||r>60)throw Error(`fps must be a number between 1 and 60`);M.subscribeToScreencast(n,t,e=>{O({type:`VIDEO_FRAME`,recorderId:t,tabId:n,data:e.data,metadata:e.metadata,sessionId:e.sessionId,receivedAt:Date.now()})},e=>{O({type:`VIDEO_ERROR`,recorderId:t,tabId:n,errorCode:e.code||`video_screencast_failed`,error:e.message})}),P={recorderId:t,tabId:n};try{if(await M.startScreencast(n,{format:`jpeg`,quality:Number.isFinite(Number(e.quality))?Number(e.quality):80,everyNthFrame:Number.isFinite(Number(e.everyNthFrame))?Number(e.everyNthFrame):1}),P?.recorderId!==t)throw Error(`Video screencast stopped while starting`);return{success:!0,recording:!0,recorderId:t,tabId:n,fps:r}}catch(e){throw P?.recorderId===t&&(P=null),M.unsubscribeFromScreencast(n,t),e}}case`VIDEO_STOP`:{let t=e.recorderId?String(e.recorderId):void 0,r=P;if(t&&r?.recorderId!==t&&(r=null),!t&&r?.tabId!==n&&(r=null),!r)return{success:!0,stopped:!1};let i;try{await M.stopScreencast(r.tabId)}catch(e){i=e}finally{P?.recorderId===r.recorderId&&(P=null),M.unsubscribeFromScreencast(r.tabId,r.recorderId)}if(i)throw i;return{success:!0,stopped:!0,recorderId:r.recorderId,tabId:r.tabId}}case`GET_PLAYBOOK_RECORD_CONTEXT`:{if(!n)throw Error(`No tabId provided`);let e=await chrome.tabs.get(n),t;try{if(e.url){let n=new URL(e.url);(n.protocol===`http:`||n.protocol===`https:`)&&(t=n.origin)}}catch{}return{success:!0,origin:t,url:e.url}}case`START_PLAYBOOK_WATCH`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.sendMessage(n,{type:`PLAYBOOK_WATCH_START`,includeInputValues:e.includeInputValues===!0},{frameId:0}),{success:!0};case`STOP_PLAYBOOK_WATCH`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.sendMessage(n,{type:`PLAYBOOK_WATCH_STOP`},{frameId:0}).catch(()=>{}),{success:!0};case`PLAYBOOK_WATCH_EVENT`:return O({...e,tabId:t.tab?.id,type:`PLAYBOOK_WATCH_EVENT`}),{success:!0};case`READ_NETWORK_REQUESTS`:{if(!n)throw Error(`No tabId provided`);try{e.bodyMode!==void 0||e.perBodyBytes!==void 0||e.totalBodyBytes!==void 0?await M.enableNetworkTracking(n,{bodyMode:e.bodyMode,perBodyBytes:e.perBodyBytes,totalBytes:e.totalBodyBytes}):await M.enableNetworkTracking(n)}catch{}if(await M.drainNetworkEvents(n),e.full){let t=M.getNetworkEntries(n,{urlPattern:e.urlPattern});e.method&&(t=t.filter(t=>t.method===e.method)),e.status&&(t=t.filter(t=>t.status===e.status)),e.contentType&&(t=t.filter(t=>t.type===e.contentType)),e.clear&&M.clearNetworkRequests(n);let r=e.limit||100;return{entries:t.slice(0,r),format:e.format,verbose:e.verbose}}let t=M.getNetworkRequests(n,{urlPattern:e.urlPattern,limit:e.limit||100});return e.method&&(t=t.filter(t=>t.method===e.method)),e.status&&(t=t.filter(t=>t.status===e.status)),e.contentType&&(t=t.filter(t=>t.type===e.contentType)),e.clear&&M.clearNetworkRequests(n),{requests:t,format:e.format,verbose:e.verbose}}case`EXPORT_NETWORK_REQUESTS`:{if(!n)throw Error(`No tabId provided`);if(e.har&&e.jsonl)throw Error(`network export cannot combine HAR and JSONL`);try{e.bodyMode!==void 0||e.perBodyBytes!==void 0||e.totalBodyBytes!==void 0?await M.enableNetworkTracking(n,{bodyMode:e.bodyMode,perBodyBytes:e.perBodyBytes,totalBytes:e.totalBodyBytes}):await M.enableNetworkTracking(n)}catch{}await M.drainNetworkEvents(n);let t=M.getNetworkEntries(n,{});if(new TextEncoder().encode(JSON.stringify(t)).byteLength>16777216)throw Error(`network export source exceeds the 16 MiB native-message limit`);return{entries:t,har:!!e.har,jsonl:!!e.jsonl}}case`CLEAR_NETWORK_REQUESTS`:if(!n)throw Error(`No tabId provided`);return M.clearNetworkRequests(n),{success:!0};case`GET_NETWORK_ENTRIES`:{if(!n)throw Error(`No tabId provided`);try{await M.enableNetworkTracking(n)}catch{}await M.drainNetworkEvents(n);let t=M.getNetworkEntries(n,{urlPattern:e.urlPattern,includeStatic:!e.excludeStatic});return e.origin&&(t=t.filter(t=>t.origin===e.origin)),e.method&&(t=t.filter(t=>t.method===e.method)),e.status&&(t=t.filter(t=>t.status===e.status)),e.type&&(t=t.filter(t=>t.type===e.type)),e.since&&(t=t.filter(t=>t.ts>=e.since)),e.hasBody!==void 0&&(t=t.filter(t=>e.hasBody?t.responseBodySize&&t.responseBodySize>0:!t.responseBodySize)),e.last&&(t=t.slice(-e.last)),e.clear&&M.clearNetworkRequests(n),{entries:t}}case`GET_NETWORK_ENTRY`:{if(!n)throw Error(`No tabId provided`);if(!e.requestId)throw Error(`No requestId provided`);await M.drainNetworkEvents(n);let t=M.getNetworkEntry(n,e.requestId);return t||=M.getNetworkEntries(n,{}).find(t=>t.id===e.requestId)||null,t||=M.getNetworkEntries(n,{}).find(t=>t._requestId===e.requestId)||null,t?{entry:t}:{error:`Entry not found: ${e.requestId}`}}case`GET_RESPONSE_BODY`:{if(!n)throw Error(`No tabId provided`);if(!e.requestId)throw Error(`No requestId provided`);await M.drainNetworkEvents(n);let t=e.requestId;if(e.requestId.startsWith(`r_`)){let r=M.getNetworkEntries(n,{}).find(t=>t.id===e.requestId);r&&(t=r._requestId)}return await M.getResponseBody(n,t)}case`GET_NETWORK_ORIGINS`:{if(!n)throw Error(`No tabId provided`);await M.drainNetworkEvents(n);let e=M.getNetworkEntries(n,{}),t={};for(let n of e)t[n.origin]||(t[n.origin]={count:0,lastSeen:0,size:0}),t[n.origin].count++,t[n.origin].lastSeen=Math.max(t[n.origin].lastSeen,n.ts),t[n.origin].size+=n.responseBodySize||0;return{origins:t}}case`GET_NETWORK_STATS`:{if(!n)throw Error(`No tabId provided`);await M.drainNetworkEvents(n);let e=M.getNetworkEntries(n,{}),t={},r={},i={},a=0,o=1/0,s=0;for(let n of e){t[n.origin]||(t[n.origin]=0),t[n.origin]++;let e=n.method||`GET`;if(r[e]=(r[e]||0)+1,n.status){let e=`${Math.floor(n.status/100)}xx`;i[e]=(i[e]||0)+1}a+=n.responseBodySize||0,n.ts<o&&(o=n.ts),n.ts>s&&(s=n.ts)}return{stats:{totalRequests:e.length,totalSize:a,uniqueOrigins:Object.keys(t).length,startTime:o===1/0?null:o,duration:s&&o!==1/0?s-o:0,byMethod:r,byStatus:i}}}case`RESIZE_WINDOW`:{if(!n)throw Error(`No tabId provided`);if(e.width===void 0&&e.height===void 0)throw Error(`width or height required`);let t=await chrome.tabs.get(n);if(!t.windowId)throw Error(`Tab has no window`);let r=e.width===void 0||e.height===void 0?await chrome.windows.get(t.windowId):null,i=e.width===void 0?r?.width:e.width,a=e.height===void 0?r?.height:e.height;if(i===void 0||a===void 0)throw Error(`current window size unavailable`);return await chrome.windows.update(t.windowId,{width:Math.floor(i),height:Math.floor(a)}),{success:!0,width:i,height:a}}case`TABS_CREATE`:{let t=n?await chrome.tabs.get(n):null,r=await chrome.tabs.create({url:e.url||`about:blank`,active:!1});if(!r.id)throw Error(`Failed to create tab`);return t?.groupId&&t.groupId!==chrome.tabGroups.TAB_GROUP_ID_NONE&&await chrome.tabs.group({tabIds:r.id,groupId:t.groupId}),{success:!0,tabId:r.id,url:r.url||e.url||`about:blank`}}case`UPLOAD_IMAGE`:{if(!n)throw Error(`No tabId provided`);if(!e.screenshotId)throw Error(`screenshotId required`);if(!e.ref&&!e.coordinate)throw Error(`ref or coordinate required`);let t=Te(e.screenshotId);if(!t)throw Error(`Screenshot not found: ${e.screenshotId}`);try{return await chrome.tabs.sendMessage(n,{type:`UPLOAD_IMAGE`,base64:t.base64,ref:e.ref,coordinate:e.coordinate,filename:e.filename||`screenshot.png`},{frameId:F(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}}case`GET_TABS`:return{tabs:(await chrome.tabs.query({})).map(e=>({id:e.id,title:e.title,url:e.url}))};case`LIST_TABS`:{let t={};return e.windowId&&(t.windowId=e.windowId),{tabs:(await chrome.tabs.query(t)).map(e=>({id:e.id,title:e.title,url:e.url,active:e.active,windowId:e.windowId}))}}case`NEW_TAB`:{let t=e.urls||(e.url?[e.url]:[`about:blank`]),n=[];for(let r=0;r<t.length;r++){let i={url:t[r],active:r===0};e.windowId&&(i.windowId=e.windowId);let a=await chrome.tabs.create(i);a.id&&n.push({tabId:a.id,url:t[r]})}return n.length===1?{success:!0,tabId:n[0].tabId,url:n[0].url}:{success:!0,tabs:n}}case`SWITCH_TAB`:{let t=e.tabId;if(!t)throw Error(`No tabId provided`);let n=await chrome.tabs.update(t,{active:!0});return n.windowId&&await chrome.windows.update(n.windowId,{focused:!0}),{success:!0,tabId:t,url:n.url,title:n.title}}case`CLOSE_TAB`:{let t=e.tabIds||(e.tabId?[e.tabId]:[]);if(t.length===0)throw Error(`No tabId(s) provided`);return await chrome.tabs.remove(t),t.length===1?{success:!0,tabId:t[0]}:{success:!0,closed:t}}case`TAB_MOVE`:{let t=e.tabIds||(e.tabId?[e.tabId]:[]),n=(Array.isArray(t)?t:String(t).split(`,`)).map(e=>Number(e));if(n.length===0)throw Error(`No tabId(s) provided`);if(n.some(e=>!Number.isInteger(e)||e<=0))throw Error(`Invalid tabId(s)`);let r=Number(e.windowId);if(!Number.isInteger(r)||r<=0)throw Error(`No destination windowId provided`);let i=e.index===void 0?-1:Number(e.index);if(!Number.isInteger(i)||i<-1)throw Error(`Invalid tab index`);let a={windowId:r,index:i},o=n.length===1?await chrome.tabs.move(n[0],a):await chrome.tabs.move(n,a);return{success:!0,moved:n,destinationWindowId:r,index:i,tabs:Array.isArray(o)?o:[o]}}case`TABS_REGISTER`:{let t=n;if(!t){let n=e.windowId?{active:!0,windowId:e.windowId}:{active:!0,lastFocusedWindow:!0},[r]=await chrome.tabs.query(n);if(r&&!I(r.url))t=r.id;else throw Error(`Cannot register a restricted browser or extension page. Focus a regular web page, or pass an explicit tabId.`)}if(!t)throw Error(`No active tab found`);if(!e.name)throw Error(`No name provided`);return Z.set(e.name,t),{success:!0,name:e.name,tabId:t}}case`TABS_GET_BY_NAME`:{if(!e.name)throw Error(`No name provided`);let t=Z.get(e.name);if(!t)return{error:`No tab registered with name "${e.name}"`};try{let e=await chrome.tabs.get(t);return{tabId:t,url:e.url,title:e.title}}catch{return Z.delete(e.name),{error:`Tab "${e.name}" no longer exists`}}}case`TABS_LIST_NAMED`:{let e=[];for(let[t,n]of Z)try{let r=await chrome.tabs.get(n);e.push({name:t,tabId:n,url:r.url,title:r.title})}catch{Z.delete(t)}return{tabs:e}}case`TABS_UNREGISTER`:if(!e.name)throw Error(`No name provided`);return Z.delete(e.name)?{success:!0}:{success:!1,error:`No tab registered with name "${e.name}"`};case`GET_AUTH`:{let{sendToNativeHost:e}=await j(async()=>{let{sendToNativeHost:e}=await Promise.resolve().then(()=>_);return{sendToNativeHost:e}},void 0);try{return await e({type:`GET_AUTH`})}catch{return{auth:null,hint:`Native host not connected. Make sure surf native host is installed.`}}}case`NATIVE_API_REQUEST`:{let{sendToNativeHost:t}=await j(async()=>{let{sendToNativeHost:e}=await Promise.resolve().then(()=>_);return{sendToNativeHost:e}},void 0);try{return await t({type:`API_REQUEST`,streamId:e.streamId,url:e.url,method:e.method,headers:e.headers,body:e.body}),{sent:!0}}catch(e){return{error:e instanceof Error?e.message:`Unknown error`}}}case`STREAM_CONSOLE`:{if(!n)throw Error(`No tabId provided`);let t=e.streamId;try{return await M.enableConsoleTracking(n),N.set(t,n),M.subscribeToConsole(n,t,e=>{O({type:`STREAM_EVENT`,streamId:t,event:{type:`console_event`,level:e.type===`exception`?`error`:e.type,text:e.text,timestamp:e.timestamp,url:e.url,line:e.line}})}),{success:!0,streaming:!0}}catch(e){return O({type:`STREAM_ERROR`,streamId:t,error:e instanceof Error?e.message:`Failed to start console stream`}),{error:e instanceof Error?e.message:`Failed to start console stream`}}}case`STREAM_NETWORK`:{if(!n)throw Error(`No tabId provided`);let t=e.streamId;try{return await M.enableNetworkTracking(n),N.set(t,n),M.subscribeToNetwork(n,t,e=>{O({type:`STREAM_EVENT`,streamId:t,event:{type:`network_event`,method:e.method,url:e.url,status:e.status,duration:e.duration,timestamp:e.timestamp}})}),{success:!0,streaming:!0}}catch(e){return O({type:`STREAM_ERROR`,streamId:t,error:e instanceof Error?e.message:`Failed to start network stream`}),{error:e instanceof Error?e.message:`Failed to start network stream`}}}case`STREAM_STOP`:{let t=e.streamId,n=N.get(t);return n!==void 0&&(M.unsubscribeFromConsole(n,t),M.unsubscribeFromNetwork(n,t),N.delete(t)),{success:!0}}case`SEARCH_PAGE`:if(!n)throw Error(`No tabId provided`);if(!e.term)throw Error(`Search term required`);try{return await chrome.tabs.sendMessage(n,{type:`SEARCH_PAGE`,term:e.term,caseSensitive:e.caseSensitive||!1,limit:e.limit||10},{frameId:F(n,e)})}catch{return{error:`Content script not loaded. Try refreshing the page.`}}case`TAB_GROUP_CREATE`:{let t=[...e.tabIds||[]],r=e.name||`Surf`,i=[`grey`,`blue`,`red`,`yellow`,`green`,`pink`,`purple`,`cyan`,`orange`].includes(e.color)?e.color:`blue`;if(t.length===0&&n&&t.push(n),t.length===0)throw Error(`No tabs specified`);let a=t.length===1?t[0]:t,o=await chrome.tabGroups.query({title:r}),s;return o.length>0?(s=o[0].id,await chrome.tabs.group({tabIds:a,groupId:s})):(s=await chrome.tabs.group({tabIds:a}),await chrome.tabGroups.update(s,{title:r,color:i,collapsed:!1})),{success:!0,groupId:s,name:r,tabIds:t}}case`TAB_GROUP_REMOVE`:{let t=[...e.tabIds||[]];if(t.length===0&&n&&t.push(n),t.length===0)throw Error(`No tabs specified`);let r=t.length===1?t[0]:t;return await chrome.tabs.ungroup(r),{success:!0,ungrouped:t}}case`TAB_GROUPS_LIST`:{let e=await chrome.tabGroups.query({}),t=[];for(let n of e){let e=await chrome.tabs.query({groupId:n.id});t.push({id:n.id,name:n.title||`(unnamed)`,color:n.color,collapsed:n.collapsed,tabs:e.map(e=>({id:e.id,title:e.title,url:e.url}))})}return{groups:t}}case`CLICK_SELECTOR`:{if(!n)throw Error(`No tabId provided`);let t=e.selector,r=e.index||0,i=F(n,e);if(i>0){let[e]=await chrome.scripting.executeScript({target:{tabId:n,frameIds:[i]},func:(e,t)=>{let n=document.querySelectorAll(e);return n.length===0?{error:`No elements match selector`}:t>=n.length?{error:`Index ${t} out of range (found ${n.length} elements)`}:(n[t].click(),{success:!0,selector:e,index:t,matchCount:n.length})},args:[t,r]});return e?.result||{error:`Failed to click element`}}let a=`(() => {
344
373
  const elements = document.querySelectorAll(${JSON.stringify(t)});
345
374
  if (elements.length === 0) return { error: "No elements match selector" };
346
375
  if (${r} >= elements.length) return { error: "Index " + ${r} + " out of range (found " + elements.length + " elements)" };
@@ -352,5 +381,5 @@ var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],en
352
381
  y: rect.top + rect.height / 2,
353
382
  count: elements.length
354
383
  };
355
- })()`,o=(await O.evaluateScript(n,a)).result?.value;return o?.error?{error:o.error}:o?(await O.click(n,o.x,o.y,`left`,1,0),{success:!0,selector:t,index:r,matchCount:o.count}):{error:`Failed to get element coordinates`}}case`COOKIE_LIST`:{if(!n)throw Error(`No tabId provided`);let e=(await chrome.tabs.get(n)).url;if(!e)throw Error(`Tab has no URL`);return{cookies:await chrome.cookies.getAll({url:e})}}case`COOKIE_GET`:{if(!n)throw Error(`No tabId provided`);let t=(await chrome.tabs.get(n)).url;if(!t)throw Error(`Tab has no URL`);if(!e.name)throw Error(`Cookie name required`);let r=await chrome.cookies.get({url:t,name:e.name});return r?{cookie:r}:{error:`Cookie "${e.name}" not found`}}case`COOKIE_SET`:{if(!n)throw Error(`No tabId provided`);let t=(await chrome.tabs.get(n)).url;if(!t)throw Error(`Tab has no URL`);if(!e.name)throw Error(`Cookie name required`);if(e.value===void 0)throw Error(`Cookie value required`);let r={url:t,name:e.name,value:e.value};if(e.expires){let t=new Date(e.expires).getTime()/1e3;if(isNaN(t))throw Error(`Invalid expiration date: ${e.expires}`);r.expirationDate=t}return{success:!0,cookie:await chrome.cookies.set(r)}}case`COOKIE_CLEAR`:{if(!n)throw Error(`No tabId provided`);let t=(await chrome.tabs.get(n)).url;if(!t)throw Error(`Tab has no URL`);if(!e.name)throw Error(`Cookie name required`);return await chrome.cookies.remove({url:t,name:e.name}),{success:!0,cleared:e.name}}case`COOKIE_CLEAR_ALL`:{if(!n)throw Error(`No tabId provided`);let e=(await chrome.tabs.get(n)).url;if(!e)throw Error(`Tab has no URL`);let t=await chrome.cookies.getAll({url:e});for(let n of t)await chrome.cookies.remove({url:e,name:n.name});return{success:!0,cleared:t.length}}case`TAB_RELOAD`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.reload(n,{bypassCache:e.hard||!1}),{success:!0};case`ZOOM_GET`:if(!n)throw Error(`No tabId provided`);return{zoom:await chrome.tabs.getZoom(n)};case`ZOOM_SET`:{if(!n)throw Error(`No tabId provided`);let t=e.level;if(t<.25||t>5)throw Error(`Zoom level must be between 0.25 and 5`);return await chrome.tabs.setZoom(n,t),{success:!0,zoom:t}}case`ZOOM_RESET`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.setZoom(n,0),{success:!0,zoom:1};case`BOOKMARK_ADD`:{if(!n)throw Error(`No tabId provided`);let t=await chrome.tabs.get(n),r={title:t.title||`Untitled`,url:t.url};if(e.folder){let t=(await chrome.bookmarks.search({title:e.folder})).find(e=>!e.url);t&&(r.parentId=t.id)}let i=await chrome.bookmarks.create(r);return{success:!0,bookmark:{id:i.id,title:i.title,url:i.url}}}case`BOOKMARK_REMOVE`:{if(!n)throw Error(`No tabId provided`);let e=await chrome.tabs.get(n);if(!e.url)throw Error(`Tab has no URL`);let t=await chrome.bookmarks.search({url:e.url});if(t.length===0)throw Error(`No bookmark found for this URL`);return await chrome.bookmarks.remove(t[0].id),{success:!0}}case`BOOKMARK_LIST`:{let t=typeof e.limit==`number`?e.limit:50,n=[];if(e.folder){let r=(await chrome.bookmarks.search({title:e.folder})).find(e=>!e.url);r&&(n=(await chrome.bookmarks.getChildren(r.id)).filter(e=>e.url).slice(0,t))}else n=await chrome.bookmarks.getRecent(t);return{bookmarks:n.map(e=>({id:e.id,title:e.title,url:e.url,dateAdded:e.dateAdded}))}}case`HISTORY_LIST`:{let t=typeof e.limit==`number`?e.limit:20;return{history:(await chrome.history.search({text:``,maxResults:t,startTime:0})).map(e=>({url:e.url,title:e.title,lastVisitTime:e.lastVisitTime,visitCount:e.visitCount}))}}case`HISTORY_SEARCH`:{let t=e.query,n=typeof e.limit==`number`?e.limit:20;return{history:(await chrome.history.search({text:t,maxResults:n,startTime:0})).map(e=>({url:e.url,title:e.title,lastVisitTime:e.lastVisitTime,visitCount:e.visitCount}))}}case`GET_CHATGPT_COOKIES`:{let e=await chrome.cookies.getAll({domain:`.chatgpt.com`}),t=await chrome.cookies.getAll({domain:`.openai.com`});return{cookies:[...e,...t]}}case`CHATGPT_NEW_TAB`:{let e=await chrome.tabs.create({url:`https://chatgpt.com/`,active:!0});if(!e.id)throw Error(`Failed to create tab`);return(await chrome.tabs.get(e.id)).status!==`complete`&&await new Promise(t=>{let n=(r,i)=>{r===e.id&&i.status===`complete`&&(chrome.tabs.onUpdated.removeListener(n),t())};chrome.tabs.onUpdated.addListener(n),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(n),t()},3e4)}),await O.attach(e.id),await X(e.id,1e4),{tabId:e.id}}case`CHATGPT_CLOSE_TAB`:{let t=e.tabId;if(t){try{await O.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`CHATGPT_CDP_COMMAND`:{let{method:t,params:n}=e;return await O.sendCommand(e.tabId,t,n||{})}case`CHATGPT_EVALUATE`:return await O.evaluateScript(e.tabId,e.expression);case`PERPLEXITY_NEW_TAB`:{let e=await chrome.tabs.create({url:`https://www.perplexity.ai/`,active:!0});if(!e.id)throw Error(`Failed to create tab`);return(await chrome.tabs.get(e.id)).status!==`complete`&&await new Promise(t=>{let n=(r,i)=>{r===e.id&&i.status===`complete`&&(chrome.tabs.onUpdated.removeListener(n),t())};chrome.tabs.onUpdated.addListener(n),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(n),t()},3e4)}),await O.attach(e.id),await X(e.id,1e4),{tabId:e.id}}case`PERPLEXITY_CLOSE_TAB`:{let t=e.tabId;if(t){try{await O.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`PERPLEXITY_CDP_COMMAND`:{let{method:t,params:n}=e;return await O.sendCommand(e.tabId,t,n||{})}case`PERPLEXITY_EVALUATE`:return await O.evaluateScript(e.tabId,e.expression);case`GET_TWITTER_COOKIES`:{let e=[`.x.com`,`.twitter.com`,`x.com`,`twitter.com`],t=[];for(let n of e)try{let e=await chrome.cookies.getAll({domain:n});t.push(...e)}catch{}for(let e of[`https://x.com`,`https://twitter.com`])try{let n=await chrome.cookies.getAll({url:e});t.push(...n)}catch{}let n=new Map;for(let e of t)(!n.get(e.name)||e.domain?.includes(`x.com`))&&n.set(e.name,e);return{cookies:Array.from(n.values())}}case`GROK_NEW_TAB`:{let e=await chrome.tabs.create({url:`https://x.com/i/grok`,active:!0});if(!e.id)throw Error(`Failed to create tab`);return(await chrome.tabs.get(e.id)).status!==`complete`&&await new Promise(t=>{let n=(r,i)=>{r===e.id&&i.status===`complete`&&(chrome.tabs.onUpdated.removeListener(n),t())};chrome.tabs.onUpdated.addListener(n),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(n),t()},3e4)}),await O.attach(e.id),await X(e.id,1e4),{tabId:e.id}}case`GROK_CLOSE_TAB`:{let t=e.tabId;if(t){try{await O.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`GROK_CDP_COMMAND`:{let{method:t,params:n}=e;return await O.sendCommand(e.tabId,t,n||{})}case`GROK_EVALUATE`:return await O.evaluateScript(e.tabId,e.expression);case`GEMINI_NEW_TAB`:{let e=await chrome.tabs.create({url:`https://gemini.google.com/app`,active:!0});if(!e.id)throw Error(`Failed to create tab`);return{tabId:e.id}}case`GEMINI_CLOSE_TAB`:{let t=e.tabId;if(t){try{await O.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`AI_UPLOAD_FILE_TO_TAB`:case`UPLOAD_FILE_TO_TAB`:{let{tabId:t,filePaths:n}=e,r=e.type===`UPLOAD_FILE_TO_TAB`?`gemini`:e.provider;if(!t||!n?.length)throw Error(`${e.type} requires tabId and filePaths`);if(r!==`gemini`&&r!==`chatgpt`)throw Error(`Unsupported upload provider: ${r}`);return ne(r,t,n)}case`GEMINI_FETCH_URL`:{let t=e.url;if(!t)throw Error(`No URL provided`);let n=await fetch(t,{credentials:`include`});if(!n.ok)throw Error(`Fetch failed: ${n.status}`);let r=await n.blob(),i=new FileReader;return{b64:await new Promise((e,t)=>{i.onload=()=>e(i.result.split(`,`)[1]),i.onerror=()=>t(Error(`FileReader failed`)),i.readAsDataURL(r)}),size:r.size,type:r.type}}case`AISTUDIO_NEW_TAB`:{let t=e.url||`https://aistudio.google.com/prompts/new_chat`,n=await chrome.tabs.create({url:t,active:!0});if(!n.id)throw Error(`Failed to create tab`);return(await chrome.tabs.get(n.id)).status!==`complete`&&await new Promise(e=>{let t=(r,i)=>{r===n.id&&i.status===`complete`&&(chrome.tabs.onUpdated.removeListener(t),e())};chrome.tabs.onUpdated.addListener(t),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(t),e()},3e4)}),await O.attach(n.id),await X(n.id,1e4),{tabId:n.id}}case`AISTUDIO_CLOSE_TAB`:{let t=e.tabId;if(t){try{await O.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`AISTUDIO_CDP_COMMAND`:{let{method:t,params:n}=e;return await O.sendCommand(e.tabId,t,n||{})}case`AISTUDIO_EVALUATE`:return await O.evaluateScript(e.tabId,e.expression);case`DOWNLOADS_SEARCH`:return{downloads:(await chrome.downloads.search(e.searchParams||{})).map(e=>({id:e.id,filename:e.filename,state:e.state,error:e.error}))};case`GET_GOOGLE_COOKIES`:{let e=[`.google.com`,`.gemini.google.com`,`accounts.google.com`,`www.google.com`],t=[];for(let n of e)try{let e=await chrome.cookies.getAll({domain:n});t.push(...e)}catch{}for(let e of[`https://gemini.google.com`,`https://aistudio.google.com`,`https://accounts.google.com`,`https://www.google.com`])try{let n=await chrome.cookies.getAll({url:e});t.push(...n)}catch{}let n=new Map;for(let e of t){let t=n.get(e.name);(!t||e.domain===`.google.com`&&e.path===`/`||!t.domain?.includes(`google.com`)&&e.domain?.includes(`google.com`))&&n.set(e.name,e)}return{cookies:Array.from(n.values())}}case`WINDOW_NEW`:{let t=e.url||`data:text/html,<html><head><title>Surf Agent</title></head><body style="font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;color:%23666"><div style="text-align:center"><h2>Agent Window</h2><p>Ready for automation</p></div></body></html>`,n={focused:e.focused!==!1,type:`normal`,url:t};e.width&&e.height&&(n.width=e.width,n.height=e.height),e.incognito&&(n.incognito=!0);let r=await chrome.windows.create(n);if(!r.id)throw Error(`Failed to create window`);let i=(await chrome.tabs.query({windowId:r.id}))[0];return i?.id&&await new Promise(e=>setTimeout(e,150)),{success:!0,windowId:r.id,tabId:i?.id,hint:`Use --window-id ${r.id} to target this window`}}case`WINDOW_LIST`:return{windows:(await chrome.windows.getAll({populate:!0})).map(t=>({id:t.id,focused:t.focused,type:t.type,state:t.state,width:t.width,height:t.height,tabCount:t.tabs?.length||0,tabs:e.includeTabs?t.tabs?.map(e=>({id:e.id,title:e.title,url:e.url,active:e.active})):void 0}))};case`WINDOW_FOCUS`:if(!e.windowId)throw Error(`No windowId provided`);return await chrome.windows.update(e.windowId,{focused:!0}),{success:!0,windowId:e.windowId};case`WINDOW_CLOSE`:if(!e.windowId)throw Error(`No windowId provided`);return await chrome.windows.remove(e.windowId),{success:!0,windowId:e.windowId};case`WINDOW_RESIZE`:{if(!e.windowId)throw Error(`No windowId provided`);let t={};e.width&&(t.width=e.width),e.height&&(t.height=e.height),e.left!==void 0&&(t.left=e.left),e.top!==void 0&&(t.top=e.top),e.state&&(t.state=e.state);let n=await chrome.windows.update(e.windowId,t);return{success:!0,windowId:e.windowId,width:n.width,height:n.height}}default:throw Error(`Unknown message type: ${e.type}`)}}chrome.runtime.onInstalled.addListener(e=>{l(`Extension installed/updated:`,e.reason)});var $=new Set(`LIST_TABS.NEW_TAB.TABS_NEW.CLOSE_TAB.CLOSE_TABS.TAB_MOVE.SWITCH_TAB.TABS_SWITCH.TABS_REGISTER.TABS_UNREGISTER.TABS_LIST_NAMED.TABS_GET_BY_NAME.CREATE_TAB_GROUP.UNGROUP_TABS.LIST_TAB_GROUPS.GET_HISTORY.SEARCH_HISTORY.GET_COOKIES.SET_COOKIE.DELETE_COOKIES.GET_BOOKMARKS.ADD_BOOKMARK.DELETE_BOOKMARK.DIALOG_DISMISS.DIALOG_ACCEPT.DIALOG_INFO.CHATGPT_NEW_TAB.CHATGPT_CLOSE_TAB.CHATGPT_EVALUATE.CHATGPT_CDP_COMMAND.GET_CHATGPT_COOKIES.GET_GOOGLE_COOKIES.GET_TWITTER_COOKIES.PERPLEXITY_NEW_TAB.PERPLEXITY_CLOSE_TAB.PERPLEXITY_EVALUATE.PERPLEXITY_CDP_COMMAND.GROK_NEW_TAB.GROK_CLOSE_TAB.GROK_EVALUATE.GROK_CDP_COMMAND.GEMINI_NEW_TAB.GEMINI_CLOSE_TAB.GEMINI_FETCH_URL.AI_UPLOAD_FILE_TO_TAB.UPLOAD_FILE_TO_TAB.AISTUDIO_NEW_TAB.AISTUDIO_CLOSE_TAB.AISTUDIO_EVALUATE.AISTUDIO_CDP_COMMAND.DOWNLOADS_SEARCH.WINDOW_NEW.WINDOW_LIST.WINDOW_FOCUS.WINDOW_CLOSE.WINDOW_RESIZE.TARGET_INSPECT.TARGET_RESOLVE.SESSION_CREATE_TARGET.SESSION_CLOSE_TARGET.EMULATE_DEVICE_LIST`.split(`.`));x(async e=>{let t=e.tabId,n=e.windowId,r=e.type?.startsWith(`DIALOG_`),i=!$.has(e.type),a=!1;if(t&&!r&&!$.has(e.type))try{await chrome.tabs.get(t)}catch{throw new M(`tab_gone`,`Tab ${t} no longer exists`,{tabId:t})}else if(!t&&i){if(e.strictTarget)throw new M(`target_required`,`Strict browser command requires an explicit tab binding`);let r=await P(n,!0);t=r.tab.id,a=r.autoCreated}t&&e.frameId!==void 0&&await te(t,e.frameId);let o=await Q({...e,tabId:t},{}),s=[];a&&s.push(`Auto-created tab in window ${n} (no usable tabs existed). Navigate to your target URL.`);let c;if(t)try{c=(await chrome.tabs.get(t)).windowId}catch{}return{...o,_resolvedTabId:t,_resolvedWindowId:c,_hint:s.length>0?s.join(` `):void 0}});
384
+ })()`,o=(await M.evaluateScript(n,a)).result?.value;return o?.error?{error:o.error}:o?(await M.click(n,o.x,o.y,`left`,1,0),{success:!0,selector:t,index:r,matchCount:o.count}):{error:`Failed to get element coordinates`}}case`COOKIE_LIST`:{if(!n)throw Error(`No tabId provided`);let e=(await chrome.tabs.get(n)).url;if(!e)throw Error(`Tab has no URL`);return{cookies:await chrome.cookies.getAll({url:e})}}case`COOKIE_GET`:{if(!n)throw Error(`No tabId provided`);let t=(await chrome.tabs.get(n)).url;if(!t)throw Error(`Tab has no URL`);if(!e.name)throw Error(`Cookie name required`);let r=await chrome.cookies.get({url:t,name:e.name});return r?{cookie:r}:{error:`Cookie "${e.name}" not found`}}case`COOKIE_SET`:{if(!n)throw Error(`No tabId provided`);let t=(await chrome.tabs.get(n)).url;if(!t)throw Error(`Tab has no URL`);if(!e.name)throw Error(`Cookie name required`);if(e.value===void 0)throw Error(`Cookie value required`);let r={url:t,name:e.name,value:e.value};if(e.expires){let t=new Date(e.expires).getTime()/1e3;if(isNaN(t))throw Error(`Invalid expiration date: ${e.expires}`);r.expirationDate=t}return{success:!0,cookie:await chrome.cookies.set(r)}}case`COOKIE_CLEAR`:{if(!n)throw Error(`No tabId provided`);let t=(await chrome.tabs.get(n)).url;if(!t)throw Error(`Tab has no URL`);if(!e.name)throw Error(`Cookie name required`);return await chrome.cookies.remove({url:t,name:e.name}),{success:!0,cleared:e.name}}case`COOKIE_CLEAR_ALL`:{if(!n)throw Error(`No tabId provided`);let e=(await chrome.tabs.get(n)).url;if(!e)throw Error(`Tab has no URL`);let t=await chrome.cookies.getAll({url:e});for(let n of t)await chrome.cookies.remove({url:e,name:n.name});return{success:!0,cleared:t.length}}case`TAB_RELOAD`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.reload(n,{bypassCache:e.hard||!1}),{success:!0};case`ZOOM_GET`:if(!n)throw Error(`No tabId provided`);return{zoom:await chrome.tabs.getZoom(n)};case`ZOOM_SET`:{if(!n)throw Error(`No tabId provided`);let t=e.level;if(t<.25||t>5)throw Error(`Zoom level must be between 0.25 and 5`);return await chrome.tabs.setZoom(n,t),{success:!0,zoom:t}}case`ZOOM_RESET`:if(!n)throw Error(`No tabId provided`);return await chrome.tabs.setZoom(n,0),{success:!0,zoom:1};case`BOOKMARK_ADD`:{if(!n)throw Error(`No tabId provided`);let t=await chrome.tabs.get(n),r={title:t.title||`Untitled`,url:t.url};if(e.folder){let t=(await chrome.bookmarks.search({title:e.folder})).find(e=>!e.url);t&&(r.parentId=t.id)}let i=await chrome.bookmarks.create(r);return{success:!0,bookmark:{id:i.id,title:i.title,url:i.url}}}case`BOOKMARK_REMOVE`:{if(!n)throw Error(`No tabId provided`);let e=await chrome.tabs.get(n);if(!e.url)throw Error(`Tab has no URL`);let t=await chrome.bookmarks.search({url:e.url});if(t.length===0)throw Error(`No bookmark found for this URL`);return await chrome.bookmarks.remove(t[0].id),{success:!0}}case`BOOKMARK_LIST`:{let t=typeof e.limit==`number`?e.limit:50,n=[];if(e.folder){let r=(await chrome.bookmarks.search({title:e.folder})).find(e=>!e.url);r&&(n=(await chrome.bookmarks.getChildren(r.id)).filter(e=>e.url).slice(0,t))}else n=await chrome.bookmarks.getRecent(t);return{bookmarks:n.map(e=>({id:e.id,title:e.title,url:e.url,dateAdded:e.dateAdded}))}}case`HISTORY_LIST`:{let t=typeof e.limit==`number`?e.limit:20;return{history:(await chrome.history.search({text:``,maxResults:t,startTime:0})).map(e=>({url:e.url,title:e.title,lastVisitTime:e.lastVisitTime,visitCount:e.visitCount}))}}case`HISTORY_SEARCH`:{let t=e.query,n=typeof e.limit==`number`?e.limit:20;return{history:(await chrome.history.search({text:t,maxResults:n,startTime:0})).map(e=>({url:e.url,title:e.title,lastVisitTime:e.lastVisitTime,visitCount:e.visitCount}))}}case`GET_CHATGPT_COOKIES`:{let e=await chrome.cookies.getAll({domain:`.chatgpt.com`}),t=await chrome.cookies.getAll({domain:`.openai.com`});return{cookies:[...e,...t]}}case`CHATGPT_NEW_TAB`:{let e=await chrome.tabs.create({url:`https://chatgpt.com/`,active:!0});if(!e.id)throw Error(`Failed to create tab`);return(await chrome.tabs.get(e.id)).status!==`complete`&&await new Promise(t=>{let n=(r,i)=>{r===e.id&&i.status===`complete`&&(chrome.tabs.onUpdated.removeListener(n),t())};chrome.tabs.onUpdated.addListener(n),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(n),t()},3e4)}),await M.attach(e.id),await Q(e.id,1e4),{tabId:e.id}}case`CHATGPT_CLOSE_TAB`:{let t=e.tabId;if(t){try{await M.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`CHATGPT_CDP_COMMAND`:{let{method:t,params:n}=e;return await M.sendCommand(e.tabId,t,n||{})}case`CHATGPT_EVALUATE`:return await M.evaluateScript(e.tabId,e.expression);case`PERPLEXITY_NEW_TAB`:{let e=await chrome.tabs.create({url:`https://www.perplexity.ai/`,active:!0});if(!e.id)throw Error(`Failed to create tab`);return(await chrome.tabs.get(e.id)).status!==`complete`&&await new Promise(t=>{let n=(r,i)=>{r===e.id&&i.status===`complete`&&(chrome.tabs.onUpdated.removeListener(n),t())};chrome.tabs.onUpdated.addListener(n),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(n),t()},3e4)}),await M.attach(e.id),await Q(e.id,1e4),{tabId:e.id}}case`PERPLEXITY_CLOSE_TAB`:{let t=e.tabId;if(t){try{await M.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`PERPLEXITY_CDP_COMMAND`:{let{method:t,params:n}=e;return await M.sendCommand(e.tabId,t,n||{})}case`PERPLEXITY_EVALUATE`:return await M.evaluateScript(e.tabId,e.expression);case`GET_TWITTER_COOKIES`:{let e=[`.x.com`,`.twitter.com`,`x.com`,`twitter.com`],t=[];for(let n of e)try{let e=await chrome.cookies.getAll({domain:n});t.push(...e)}catch{}for(let e of[`https://x.com`,`https://twitter.com`])try{let n=await chrome.cookies.getAll({url:e});t.push(...n)}catch{}let n=new Map;for(let e of t)(!n.get(e.name)||e.domain?.includes(`x.com`))&&n.set(e.name,e);return{cookies:Array.from(n.values())}}case`GROK_NEW_TAB`:{let e=await chrome.tabs.create({url:`https://x.com/i/grok`,active:!0});if(!e.id)throw Error(`Failed to create tab`);return(await chrome.tabs.get(e.id)).status!==`complete`&&await new Promise(t=>{let n=(r,i)=>{r===e.id&&i.status===`complete`&&(chrome.tabs.onUpdated.removeListener(n),t())};chrome.tabs.onUpdated.addListener(n),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(n),t()},3e4)}),await M.attach(e.id),await Q(e.id,1e4),{tabId:e.id}}case`GROK_CLOSE_TAB`:{let t=e.tabId;if(t){try{await M.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`GROK_CDP_COMMAND`:{let{method:t,params:n}=e;return await M.sendCommand(e.tabId,t,n||{})}case`GROK_EVALUATE`:return await M.evaluateScript(e.tabId,e.expression);case`GEMINI_NEW_TAB`:{let e=await chrome.tabs.create({url:`https://gemini.google.com/app`,active:!0});if(!e.id)throw Error(`Failed to create tab`);return{tabId:e.id}}case`GEMINI_CLOSE_TAB`:{let t=e.tabId;if(t){try{await M.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`AI_UPLOAD_FILE_TO_TAB`:case`UPLOAD_FILE_TO_TAB`:{let{tabId:t,filePaths:n}=e,r=e.type===`UPLOAD_FILE_TO_TAB`?`gemini`:e.provider;if(!t||!n?.length)throw Error(`${e.type} requires tabId and filePaths`);if(r!==`gemini`&&r!==`chatgpt`)throw Error(`Unsupported upload provider: ${r}`);return ke(r,t,n)}case`GEMINI_FETCH_URL`:{let t=e.url;if(!t)throw Error(`No URL provided`);let n=await fetch(t,{credentials:`include`});if(!n.ok)throw Error(`Fetch failed: ${n.status}`);let r=await n.blob(),i=new FileReader;return{b64:await new Promise((e,t)=>{i.onload=()=>e(i.result.split(`,`)[1]),i.onerror=()=>t(Error(`FileReader failed`)),i.readAsDataURL(r)}),size:r.size,type:r.type}}case`AISTUDIO_NEW_TAB`:{let t=e.url||`https://aistudio.google.com/prompts/new_chat`,n=await chrome.tabs.create({url:t,active:!0});if(!n.id)throw Error(`Failed to create tab`);return(await chrome.tabs.get(n.id)).status!==`complete`&&await new Promise(e=>{let t=(r,i)=>{r===n.id&&i.status===`complete`&&(chrome.tabs.onUpdated.removeListener(t),e())};chrome.tabs.onUpdated.addListener(t),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(t),e()},3e4)}),await M.attach(n.id),await Q(n.id,1e4),{tabId:n.id}}case`AISTUDIO_CLOSE_TAB`:{let t=e.tabId;if(t){try{await M.detach(t)}catch{}try{await chrome.tabs.remove(t)}catch{}}return{success:!0}}case`AISTUDIO_CDP_COMMAND`:{let{method:t,params:n}=e;return await M.sendCommand(e.tabId,t,n||{})}case`AISTUDIO_EVALUATE`:return await M.evaluateScript(e.tabId,e.expression);case`DOWNLOADS_SEARCH`:return{downloads:(await chrome.downloads.search(e.searchParams||{})).map(e=>({id:e.id,filename:e.filename,state:e.state,error:e.error}))};case`GET_GOOGLE_COOKIES`:{let e=[`.google.com`,`.gemini.google.com`,`accounts.google.com`,`www.google.com`],t=[];for(let n of e)try{let e=await chrome.cookies.getAll({domain:n});t.push(...e)}catch{}for(let e of[`https://gemini.google.com`,`https://aistudio.google.com`,`https://accounts.google.com`,`https://www.google.com`])try{let n=await chrome.cookies.getAll({url:e});t.push(...n)}catch{}let n=new Map;for(let e of t){let t=n.get(e.name);(!t||e.domain===`.google.com`&&e.path===`/`||!t.domain?.includes(`google.com`)&&e.domain?.includes(`google.com`))&&n.set(e.name,e)}return{cookies:Array.from(n.values())}}case`WINDOW_NEW`:{let t=e.url||`data:text/html,<html><head><title>Surf Agent</title></head><body style="font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;color:%23666"><div style="text-align:center"><h2>Agent Window</h2><p>Ready for automation</p></div></body></html>`,n={focused:e.focused!==!1,type:`normal`,url:t};e.width&&e.height&&(n.width=e.width,n.height=e.height),e.incognito&&(n.incognito=!0);let r=await chrome.windows.create(n);if(!r.id)throw Error(`Failed to create window`);let i=(await chrome.tabs.query({windowId:r.id}))[0];return i?.id&&await new Promise(e=>setTimeout(e,150)),{success:!0,windowId:r.id,tabId:i?.id,hint:`Use --window-id ${r.id} to target this window`}}case`WINDOW_LIST`:return{windows:(await chrome.windows.getAll({populate:!0})).map(t=>({id:t.id,focused:t.focused,type:t.type,state:t.state,width:t.width,height:t.height,tabCount:t.tabs?.length||0,tabs:e.includeTabs?t.tabs?.map(e=>({id:e.id,title:e.title,url:e.url,active:e.active})):void 0}))};case`WINDOW_FOCUS`:if(!e.windowId)throw Error(`No windowId provided`);return await chrome.windows.update(e.windowId,{focused:!0}),{success:!0,windowId:e.windowId};case`WINDOW_CLOSE`:if(!e.windowId)throw Error(`No windowId provided`);return await chrome.windows.remove(e.windowId),{success:!0,windowId:e.windowId};case`WINDOW_RESIZE`:{if(!e.windowId)throw Error(`No windowId provided`);let t={};e.width&&(t.width=e.width),e.height&&(t.height=e.height),e.left!==void 0&&(t.left=e.left),e.top!==void 0&&(t.top=e.top),e.state&&(t.state=e.state);let n=await chrome.windows.update(e.windowId,t);return{success:!0,windowId:e.windowId,width:n.width,height:n.height}}default:throw Error(`Unknown message type: ${e.type}`)}}chrome.runtime.onInstalled.addListener(e=>{u(`Extension installed/updated:`,e.reason)});var Fe=new Set(`LIST_TABS.NEW_TAB.TABS_NEW.CLOSE_TAB.CLOSE_TABS.TAB_MOVE.SWITCH_TAB.TABS_SWITCH.TABS_REGISTER.TABS_UNREGISTER.TABS_LIST_NAMED.TABS_GET_BY_NAME.CREATE_TAB_GROUP.UNGROUP_TABS.LIST_TAB_GROUPS.GET_HISTORY.SEARCH_HISTORY.GET_COOKIES.SET_COOKIE.DELETE_COOKIES.GET_BOOKMARKS.ADD_BOOKMARK.DELETE_BOOKMARK.DIALOG_DISMISS.DIALOG_ACCEPT.DIALOG_INFO.CHATGPT_NEW_TAB.CHATGPT_CLOSE_TAB.CHATGPT_EVALUATE.CHATGPT_CDP_COMMAND.GET_CHATGPT_COOKIES.GET_GOOGLE_COOKIES.GET_TWITTER_COOKIES.PERPLEXITY_NEW_TAB.PERPLEXITY_CLOSE_TAB.PERPLEXITY_EVALUATE.PERPLEXITY_CDP_COMMAND.GROK_NEW_TAB.GROK_CLOSE_TAB.GROK_EVALUATE.GROK_CDP_COMMAND.GEMINI_NEW_TAB.GEMINI_CLOSE_TAB.GEMINI_FETCH_URL.AI_UPLOAD_FILE_TO_TAB.UPLOAD_FILE_TO_TAB.AISTUDIO_NEW_TAB.AISTUDIO_CLOSE_TAB.AISTUDIO_EVALUATE.AISTUDIO_CDP_COMMAND.DOWNLOADS_SEARCH.WINDOW_NEW.WINDOW_LIST.WINDOW_FOCUS.WINDOW_CLOSE.WINDOW_RESIZE.TARGET_INSPECT.TARGET_RESOLVE.SESSION_CREATE_TARGET.SESSION_CLOSE_TARGET.EMULATE_DEVICE_LIST`.split(`.`));D(async e=>{let t=e.tabId,n=e.windowId,r=e.type?.startsWith(`DIALOG_`),i=!Fe.has(e.type),a=!1;if(t&&!r&&!Fe.has(e.type))try{await chrome.tabs.get(t)}catch{throw new L(`tab_gone`,`Tab ${t} no longer exists`,{tabId:t})}else if(!t&&i){if(e.strictTarget)throw new L(`target_required`,`Strict browser command requires an explicit tab binding`);let r=await z(n,!0);t=r.tab.id,a=r.autoCreated}t&&e.frameId!==void 0&&await ve(t,e.frameId);let o=await Pe({...e,tabId:t},{}),s=[];a&&s.push(`Auto-created tab in window ${n} (no usable tabs existed). Navigate to your target URL.`);let c;if(t)try{c=(await chrome.tabs.get(t)).windowId}catch{}return{...o,_resolvedTabId:t,_resolvedWindowId:c,_hint:s.length>0?s.join(` `):void 0}},_e);
356
385
  //# sourceMappingURL=index.js.map