surf-cli 2.6.0 → 2.7.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,21 +1,21 @@
1
- var Se=Object.defineProperty;var ge=(t,i,e)=>i in t?Se(t,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[i]=e;var O=(t,i,e)=>ge(t,typeof i!="symbol"?i+"":i,e);const ve="modulepreload",Ie=function(t){return"/"+t},ue={},de=function(i,e,n){let s=Promise.resolve();if(e&&e.length>0){let l=function(b){return Promise.all(b.map(E=>Promise.resolve(E).then(T=>({status:"fulfilled",value:T}),T=>({status:"rejected",reason:T}))))};document.getElementsByTagName("link");const f=document.querySelector("meta[property=csp-nonce]"),y=(f==null?void 0:f.nonce)||(f==null?void 0:f.getAttribute("nonce"));s=l(e.map(b=>{if(b=Ie(b),b in ue)return;ue[b]=!0;const E=b.endsWith(".css"),T=E?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${b}"]${T}`))return;const S=document.createElement("link");if(S.rel=E?"stylesheet":ve,E||(S.as="script"),S.crossOrigin="",S.href=b,y&&S.setAttribute("nonce",y),document.head.appendChild(S),E)return new Promise((p,v)=>{S.addEventListener("load",p),S.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${b}`)))})}))}function d(l){const f=new Event("vite:preloadError",{cancelable:!0});if(f.payload=l,window.dispatchEvent(f),!f.defaultPrevented)throw l}return s.then(l=>{for(const f of l||[])f.status==="rejected"&&d(f.reason);return i().catch(d)})},Y={alt:1,ctrl:2,control:2,meta:4,cmd:4,command:4,win:4,windows:4,shift:8},he={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 A{constructor(){O(this,"targets",new Map);O(this,"consoleMessages",new Map);O(this,"networkRequests",new Map);O(this,"networkEntries",new Map);O(this,"consoleCallbacks",new Map);O(this,"networkCallbacks",new Map);O(this,"networkRequestStartTimes",new Map);O(this,"pendingDialogs",new Map);O(this,"networkEntrySeq",0)}async attach(i){if(this.targets.has(i))return;const e={tabId:i};try{await chrome.debugger.attach(e,"1.3")}catch(n){const s=n instanceof Error?n.message:String(n);throw s.includes("Cannot access")||s.includes("Cannot attach")?new Error("Cannot control this page. Chrome restricts automation on chrome://, extensions, and web store pages."):new Error(`Failed to attach debugger: ${s}`)}this.targets.set(i,e),this.setupEventListener(),this.consoleMessages.set(i,[]),this.networkRequests.set(i,[]);try{await this.send(i,"Page.enable")}catch{}}async detach(i){const e=this.targets.get(i);if(e){try{await chrome.debugger.detach(e)}catch(n){console.warn("[CDPController] Error detaching:",n)}this.targets.delete(i),this.consoleMessages.delete(i),this.networkRequests.delete(i),this.networkEntries.delete(i),this.consoleCallbacks.delete(i),this.networkCallbacks.delete(i),this.pendingDialogs.delete(i)}}async detachAll(){for(const i of this.targets.keys())await this.detach(i)}setupEventListener(){A.debuggerListenerRegistered||(A.debuggerListenerRegistered=!0,chrome.debugger.onEvent.addListener((i,e,n)=>{const s=i.tabId;!s||!this.targets.has(s)||this.handleCDPEvent(s,e,n)}),chrome.debugger.onDetach.addListener((i,e)=>{const n=i.tabId;n&&this.targets.has(n)&&(this.targets.delete(n),this.consoleMessages.delete(n),this.networkRequests.delete(n),this.networkEntries.delete(n),this.consoleCallbacks.delete(n),this.networkCallbacks.delete(n))}))}handleCDPEvent(i,e,n){switch(e){case"Runtime.consoleAPICalled":this.handleRuntimeConsole(i,n);break;case"Runtime.exceptionThrown":this.handleRuntimeException(i,n);break;case"Network.requestWillBeSent":this.handleNetworkRequest(i,n);break;case"Network.responseReceived":this.handleNetworkResponse(i,n);break;case"Network.loadingFailed":this.handleNetworkFailed(i,n);break;case"Network.loadingFinished":this.handleLoadingFinished(i,n);break;case"Page.javascriptDialogOpening":this.handleDialogOpening(i,n);break;case"Page.javascriptDialogClosed":this.pendingDialogs.delete(i);break}}handleRuntimeConsole(i,e){var b,E;const n=this.consoleMessages.get(i)||[],d=(e.args||[]).map(T=>T.value!==void 0?String(T.value):T.description?T.description:"").join(" "),l=(E=(b=e.stackTrace)==null?void 0:b.callFrames)==null?void 0:E[0],f={type:e.type||"log",text:d,timestamp:e.timestamp||Date.now(),url:l==null?void 0:l.url,line:l==null?void 0:l.lineNumber};n.push(f),n.length>1e3&&n.shift(),this.consoleMessages.set(i,n);const y=this.consoleCallbacks.get(i);if(y)for(const T of y.values())T(f)}handleRuntimeException(i,e){var f;const n=this.consoleMessages.get(i)||[],s=e.exceptionDetails;if(!s)return;const d={type:"exception",text:((f=s.exception)==null?void 0:f.description)||s.text||"Unknown exception",timestamp:s.timestamp||Date.now(),url:s.url,line:s.lineNumber};n.push(d),n.length>1e3&&n.shift(),this.consoleMessages.set(i,n);const l=this.consoleCallbacks.get(i);if(l)for(const y of l.values())y(d)}handleNetworkRequest(i,e){const n=this.networkRequests.get(i)||[],s=e.request;if(!s)return;const d=e.timestamp?e.timestamp*1e3:Date.now();this.networkRequestStartTimes.set(e.requestId,d);const l={};if(s.headers)for(const[v,g]of Object.entries(s.headers))l[v]=String(g);n.push({requestId:e.requestId,url:s.url,method:s.method,type:e.type,timestamp:d,requestHeaders:l,requestBody:s.postData}),n.length>500&&n.shift(),this.networkRequests.set(i,n),this.networkEntries.has(i)||this.networkEntries.set(i,new Map);const f=this.networkEntries.get(i),y=++this.networkEntrySeq,b=`r_${d}_${y}`,E={};if(s.headers)for(const[v,g]of Object.entries(s.headers))E[v]=String(g);const T=s.postData,S=T?T.length:void 0,p={id:b,ts:d,method:s.method,url:s.url,origin:this.extractOrigin(s.url),requestHeaders:E,requestBody:T,requestBodySize:S,tabId:i,tabUrl:e.documentURL,type:e.type,flags:[],_requestId:e.requestId,_responseReceived:!1,_loadingFinished:!1};if(f.size>500){const v=f.keys().next().value;v&&f.delete(v)}f.set(e.requestId,p)}handleNetworkResponse(i,e){var f,y,b,E,T,S;const s=(this.networkRequests.get(i)||[]).find(p=>p.requestId===e.requestId);if(s){if(s.status=(f=e.response)==null?void 0:f.status,s.mimeType=(y=e.response)==null?void 0:y.mimeType,(b=e.response)!=null&&b.headers){const v={};for(const[g,k]of Object.entries(e.response.headers))v[g]=String(k);s.responseHeaders=v}const p=this.networkCallbacks.get(i);if(p){const v=this.networkRequestStartTimes.get(e.requestId),g=Date.now(),k=v?Math.round(g-v):void 0;for(const x of p.values())x({method:s.method,url:s.url,status:s.status,duration:k,timestamp:g})}}const d=this.networkEntries.get(i),l=d==null?void 0:d.get(e.requestId);if(l&&e.response){const p=e.response,v=this.networkRequestStartTimes.get(e.requestId),g=e.timestamp?e.timestamp*1e3:Date.now();v&&(l.ttfb=Math.round(g-v)),l.status=p.status,l.statusText=p.statusText,l.mimeType=p.mimeType;const k={};if(p.headers)for(const[x,B]of Object.entries(p.headers))k[x]=String(B);l.responseHeaders=k,this.isBinaryType(p.mimeType)&&l.flags.push("binary"),((E=p.mimeType)!=null&&E.includes("protobuf")||(T=p.mimeType)!=null&&T.includes("x-protobuf")||(S=p.mimeType)!=null&&S.includes("application/grpc"))&&l.flags.push("protobuf"),l._responseReceived=!0}}handleNetworkFailed(i,e){const s=(this.networkRequests.get(i)||[]).find(f=>f.requestId===e.requestId);if(s&&!s.status){s.status=0;const f=this.networkCallbacks.get(i);if(f){const y=this.networkRequestStartTimes.get(e.requestId),b=Date.now(),E=y?Math.round(b-y):void 0;this.networkRequestStartTimes.delete(e.requestId);for(const T of f.values())T({method:s.method,url:s.url,status:0,duration:E,timestamp:b})}}const d=this.networkEntries.get(i),l=d==null?void 0:d.get(e.requestId);if(l){const f=this.networkRequestStartTimes.get(e.requestId),y=e.timestamp?e.timestamp*1e3:Date.now();f&&(l.duration=Math.round(y-f)),this.networkRequestStartTimes.delete(e.requestId),l.status=0,l.flags.push("failed"),l._loadingFinished=!0}}handleDialogOpening(i,e){this.pendingDialogs.set(i,{type:e.type,message:e.message,defaultPrompt:e.defaultPrompt,timestamp:Date.now()})}async handleLoadingFinished(i,e){const s=(this.networkRequests.get(i)||[]).find(E=>E.requestId===e.requestId);if(s){const E=this.networkRequestStartTimes.get(e.requestId),T=e.timestamp?e.timestamp*1e3:Date.now();if(E&&(s.duration=Math.round(T-E)),!this.isStaticAsset(s.mimeType)&&!this.isBinaryType(s.mimeType)&&(e.encodedDataLength||0)<=A.MAX_INLINE_BODY_SIZE)try{const p=await this.send(i,"Network.getResponseBody",{requestId:e.requestId});if(p.base64Encoded)try{s.responseBody=atob(p.body)}catch{s.responseBody=p.body}else s.responseBody=p.body;s.responseBody&&s.responseBody.length>A.MAX_INLINE_BODY_SIZE&&(s.responseBody=s.responseBody.slice(0,A.MAX_INLINE_BODY_SIZE))}catch{}}const d=this.networkEntries.get(i),l=d==null?void 0:d.get(e.requestId);if(!l)return;const f=this.networkRequestStartTimes.get(e.requestId),y=e.timestamp?e.timestamp*1e3:Date.now();if(f&&(l.duration=Math.round(y-f)),this.networkRequestStartTimes.delete(e.requestId),l.responseBodySize=e.encodedDataLength,l._loadingFinished=!0,!this.isStaticAsset(l.mimeType)&&!this.isBinaryType(l.mimeType)&&(e.encodedDataLength||0)<=A.MAX_INLINE_BODY_SIZE)try{const E=await this.send(i,"Network.getResponseBody",{requestId:e.requestId});if(E.base64Encoded)try{l.responseBody=atob(E.body)}catch{l.responseBody=E.body,l.flags.push("binary")}else l.responseBody=E.body;l.responseBody&&l.responseBody.length>A.MAX_INLINE_BODY_SIZE&&(l.responseBody=l.responseBody.slice(0,A.MAX_INLINE_BODY_SIZE),l.flags.push("truncated"))}catch{}}extractOrigin(i){try{return new URL(i).origin}catch{return""}}isStaticAsset(i){return i?A.STATIC_ASSET_TYPES.has(i):!1}isBinaryType(i){return i?A.BINARY_TYPES.has(i):!1}async enableConsoleTracking(i){await this.ensureAttached(i);try{await this.send(i,"Runtime.enable")}catch{}}async enableNetworkTracking(i){await this.ensureAttached(i);try{await this.send(i,"Network.enable",{maxPostDataSize:65536})}catch{}}async handleDialog(i,e,n){try{return await this.send(i,"Page.handleJavaScriptDialog",{accept:e,promptText:n}),this.pendingDialogs.delete(i),{success:!0}}catch(s){return{success:!1,error:s instanceof Error?s.message:String(s)}}}getDialogInfo(i){return this.pendingDialogs.get(i)||null}async emulateNetwork(i,e){await this.ensureAttached(i);const 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}},s=n[e.toLowerCase().replace(/\s+/g,"-")];if(!s)return{success:!1,error:`Unknown preset: ${e}. Available: ${Object.keys(n).join(", ")}`};try{return await this.send(i,"Network.enable"),await this.send(i,"Network.emulateNetworkConditions",s),{success:!0}}catch(d){return{success:!1,error:d instanceof Error?d.message:String(d)}}}async emulateCPU(i,e){if(await this.ensureAttached(i),e<1)return{success:!1,error:"CPU throttling rate must be >= 1 (1 = no throttle, 4 = 4x slower)"};try{return await this.send(i,"Emulation.setCPUThrottlingRate",{rate:e}),{success:!0}}catch(n){return{success:!1,error:n instanceof Error?n.message:String(n)}}}async emulateGeolocation(i,e,n,s){await this.ensureAttached(i);try{return await this.send(i,"Emulation.setGeolocationOverride",{latitude:e,longitude:n,accuracy:s||100}),{success:!0}}catch(d){return{success:!1,error:d instanceof Error?d.message:String(d)}}}async clearGeolocation(i){await this.ensureAttached(i);try{return await this.send(i,"Emulation.clearGeolocationOverride"),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateDevice(i,e){await this.ensureAttached(i);try{return await this.send(i,"Emulation.setDeviceMetricsOverride",{width:e.width,height:e.height,deviceScaleFactor:e.deviceScaleFactor,mobile:e.mobile}),e.userAgent&&await this.send(i,"Emulation.setUserAgentOverride",{userAgent:e.userAgent}),e.touch&&await this.send(i,"Emulation.setTouchEmulationEnabled",{enabled:!0,maxTouchPoints:5}),{success:!0}}catch(n){return{success:!1,error:n instanceof Error?n.message:String(n)}}}async clearDeviceEmulation(i){await this.ensureAttached(i);try{return await this.send(i,"Emulation.clearDeviceMetricsOverride"),await this.send(i,"Emulation.setUserAgentOverride",{userAgent:""}),await this.send(i,"Emulation.setTouchEmulationEnabled",{enabled:!1}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateViewport(i,e){await this.ensureAttached(i);try{const n=await this.getViewportSize(i);return await this.send(i,"Emulation.setDeviceMetricsOverride",{width:e.width||n.width,height:e.height||n.height,deviceScaleFactor:e.deviceScaleFactor||1,mobile:e.mobile||!1}),{success:!0}}catch(n){return{success:!1,error:n instanceof Error?n.message:String(n)}}}async emulateTouch(i,e){await this.ensureAttached(i);try{return await this.send(i,"Emulation.setTouchEmulationEnabled",{enabled:e,maxTouchPoints:e?5:0}),{success:!0}}catch(n){return{success:!1,error:n instanceof Error?n.message:String(n)}}}async startPerformanceTrace(i,e){await this.ensureAttached(i);try{return await this.send(i,"Performance.enable"),await this.send(i,"Tracing.start",{categories:(e==null?void 0:e.join(","))||"devtools.timeline,v8.execute,disabled-by-default-devtools.timeline",transferMode:"ReturnAsStream"}),{success:!0}}catch(n){return{success:!1,error:n instanceof Error?n.message:String(n)}}}async stopPerformanceTrace(i){await this.ensureAttached(i);try{await this.send(i,"Performance.enable");const e=await this.send(i,"Performance.getMetrics");await this.send(i,"Tracing.end"),await this.send(i,"Performance.disable");const n={};for(const s of e.metrics||[])n[s.name]=s.value;return{success:!0,metrics:n}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async getPerformanceMetrics(i){await this.ensureAttached(i);try{await this.send(i,"Performance.enable");const e=await this.send(i,"Performance.getMetrics");await this.send(i,"Performance.disable");const n={};for(const s of e.metrics||[])n[s.name]=s.value;return{success:!0,metrics:n}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async setFileInputBySelector(i,e,n){await this.ensureAttached(i);try{await this.send(i,"DOM.enable");const s=await this.send(i,"DOM.getDocument"),d=await this.send(i,"DOM.querySelector",{nodeId:s.root.nodeId,selector:e});return d.nodeId?(await this.send(i,"DOM.setFileInputFiles",{nodeId:d.nodeId,files:n}),{success:!0}):{success:!1,error:"Could not find element by selector"}}catch(s){return{success:!1,error:s instanceof Error?s.message:String(s)}}}async waitForLoad(i,e=3e4){var s;await this.ensureAttached(i);const n=Date.now();try{for(;Date.now()-n<e;){const l=(s=(await this.send(i,"Runtime.evaluate",{expression:"document.readyState",returnByValue:!0})).result)==null?void 0:s.value;if(l==="complete")return{success:!0,readyState:l};await new Promise(f=>setTimeout(f,100))}return{success:!1,error:`Timeout waiting for page load (${e}ms)`}}catch(d){return{success:!1,error:d instanceof Error?d.message:String(d)}}}async getFrames(i){await this.ensureAttached(i);try{await this.send(i,"Page.enable");const e=await this.send(i,"Page.getFrameTree"),n=[],s=(d,l)=>{if(n.push({frameId:d.frame.id,url:d.frame.url,name:d.frame.name||"",parentId:l}),d.childFrames)for(const f of d.childFrames)s(f,d.frame.id)};return s(e.frameTree),{success:!0,frames:n}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async evaluateInFrame(i,e,n){var s,d,l;await this.ensureAttached(i);try{const f=await this.send(i,"Page.createIsolatedWorld",{frameId:e,worldName:"surf-isolated"}),y=`JSON.stringify((function() { ${n} })())`,b=await this.send(i,"Runtime.evaluate",{expression:y,contextId:f.executionContextId,returnByValue:!0,awaitPromise:!0});if(b.exceptionDetails)return{success:!1,error:b.exceptionDetails.text||((s=b.exceptionDetails.exception)==null?void 0:s.description)||"Evaluation failed"};try{return{success:!0,result:JSON.parse((d=b.result)==null?void 0:d.value)}}catch{return{success:!0,result:(l=b.result)==null?void 0:l.value}}}catch(f){return{success:!1,error:f instanceof Error?f.message:String(f)}}}getConsoleMessages(i,e){let n=this.consoleMessages.get(i)||[];if(e!=null&&e.onlyErrors&&(n=n.filter(s=>s.type==="error"||s.type==="exception")),e!=null&&e.pattern)try{const s=new RegExp(e.pattern,"i");n=n.filter(d=>s.test(d.text))}catch{n=n.filter(d=>d.text.includes(e.pattern))}return e!=null&&e.limit&&(n=n.slice(-e.limit)),[...n]}clearConsoleMessages(i){this.consoleMessages.set(i,[])}getNetworkRequests(i,e){let n=this.networkRequests.get(i)||[];return e!=null&&e.urlPattern&&(n=n.filter(s=>s.url.includes(e.urlPattern))),e!=null&&e.limit&&(n=n.slice(-e.limit)),[...n]}clearNetworkRequests(i){this.networkRequests.set(i,[]),this.networkEntries.set(i,new Map)}getNetworkEntries(i,e){const n=this.networkEntries.get(i);let s=[];return n&&n.size>0?s=Array.from(n.values()):s=(this.networkRequests.get(i)||[]).map((l,f)=>({id:`r_${l.timestamp}_${f}`,ts:l.timestamp,method:l.method,url:l.url,origin:this.extractOrigin(l.url),requestHeaders:{},tabId:i,type:l.type,status:l.status,flags:[],_requestId:l.requestId,_responseReceived:!0,_loadingFinished:!0})),e!=null&&e.includeStatic||(s=s.filter(d=>!this.isStaticAsset(d.mimeType))),e!=null&&e.urlPattern&&(s=s.filter(d=>d.url.includes(e.urlPattern))),e!=null&&e.limit&&(s=s.slice(-e.limit)),s}getNetworkEntry(i,e){const n=this.networkEntries.get(i);return(n==null?void 0:n.get(e))||null}async getResponseBody(i,e){await this.ensureAttached(i);try{const n=await this.send(i,"Network.getResponseBody",{requestId:e});return{success:!0,body:n.body,base64Encoded:n.base64Encoded}}catch(n){return{success:!1,error:n instanceof Error?n.message:String(n)}}}subscribeToConsole(i,e,n){this.consoleCallbacks.has(i)||this.consoleCallbacks.set(i,new Map),this.consoleCallbacks.get(i).set(e,n)}unsubscribeFromConsole(i,e){const n=this.consoleCallbacks.get(i);n&&(n.delete(e),n.size===0&&this.consoleCallbacks.delete(i))}subscribeToNetwork(i,e,n){this.networkCallbacks.has(i)||this.networkCallbacks.set(i,new Map),this.networkCallbacks.get(i).set(e,n)}unsubscribeFromNetwork(i,e){const n=this.networkCallbacks.get(i);n&&(n.delete(e),n.size===0&&this.networkCallbacks.delete(i))}async evaluateScript(i,e){await this.ensureAttached(i);try{await this.send(i,"Runtime.enable")}catch{}return this.send(i,"Runtime.evaluate",{expression:e,returnByValue:!0,awaitPromise:!0,timeout:1e4})}async send(i,e,n){await this.ensureAttached(i);const s=this.targets.get(i);return chrome.debugger.sendCommand(s,e,n)}async sendCommand(i,e,n){return this.send(i,e,n)}async ensureAttached(i){this.targets.has(i)||await this.attach(i)}async getViewportSize(i){const e=await this.send(i,"Page.getLayoutMetrics"),n=e.visualViewport||e.layoutViewport;return{width:Math.round(n.clientWidth),height:Math.round(n.clientHeight)}}async captureScreenshot(i){const e=await this.send(i,"Page.captureScreenshot",{format:"png",captureBeyondViewport:!1}),{width:n,height:s}=await this.getViewportSize(i);return{base64:e.data,width:n,height:s}}async captureRegion(i,e,n,s,d){return{base64:(await this.send(i,"Page.captureScreenshot",{format:"png",clip:{x:e,y:n,width:s,height:d,scale:1}})).data,width:s,height:d}}async dispatchMouseEvent(i,e,n,s,d={}){const l={type:e,x:Math.round(n),y:Math.round(s),modifiers:d.modifiers||0};(e==="mousePressed"||e==="mouseReleased"||e==="mouseMoved")&&(l.button=d.button||"none",(e==="mousePressed"||e==="mouseReleased")&&(l.clickCount=d.clickCount||1)),e!=="mouseWheel"&&(l.buttons=d.buttons??0),e==="mouseWheel"&&(l.deltaX=d.deltaX||0,l.deltaY=d.deltaY||0),await this.send(i,"Input.dispatchMouseEvent",l)}async click(i,e,n,s="left",d=1,l=0){const f=s==="left"?1:s==="right"?2:s==="middle"?4:0;await this.dispatchMouseEvent(i,"mouseMoved",e,n,{button:"none",buttons:0,modifiers:l}),await new Promise(y=>setTimeout(y,100));for(let y=1;y<=d;y++)await this.dispatchMouseEvent(i,"mousePressed",e,n,{button:s,buttons:f,clickCount:y,modifiers:l}),await new Promise(b=>setTimeout(b,12)),await this.dispatchMouseEvent(i,"mouseReleased",e,n,{button:s,buttons:0,clickCount:y,modifiers:l}),y<d&&await new Promise(b=>setTimeout(b,100))}async rightClick(i,e,n,s=0){await this.click(i,e,n,"right",1,s)}async doubleClick(i,e,n,s=0){await this.click(i,e,n,"left",2,s)}async tripleClick(i,e,n,s=0){await this.click(i,e,n,"left",3,s)}async hover(i,e,n){await this.dispatchMouseEvent(i,"mouseMoved",e,n,{button:"none",buttons:0})}async drag(i,e,n,s,d,l=0){await this.dispatchMouseEvent(i,"mouseMoved",e,n,{button:"none",buttons:0}),await new Promise(f=>setTimeout(f,50)),await this.dispatchMouseEvent(i,"mousePressed",e,n,{button:"left",buttons:1,clickCount:1,modifiers:l}),await new Promise(f=>setTimeout(f,50)),await this.dispatchMouseEvent(i,"mouseMoved",s,d,{button:"left",buttons:1,modifiers:l}),await new Promise(f=>setTimeout(f,50)),await this.dispatchMouseEvent(i,"mouseReleased",s,d,{button:"left",buttons:0,clickCount:1,modifiers:l})}async scroll(i,e,n,s,d){await this.dispatchMouseEvent(i,"mouseWheel",e,n,{deltaX:s,deltaY:d})}async type(i,e){for(const n of e)if(n===`
2
- `||n==="\r")await this.pressKey(i,"Enter");else if(this.getKeyDefinition(n)){const d=this.requiresShift(n);await this.pressKey(i,n,d?Y.shift:0)}else await this.send(i,"Input.insertText",{text:n})}requiresShift(i){return/[A-Z!@#$%^&*()_+{}|:"<>?~]/.test(i)}async dispatchKeyEvent(i,e,n,s=0){await this.send(i,"Input.dispatchKeyEvent",{type:n.text?e:e==="keyDown"?"rawKeyDown":e,key:n.key,code:n.code,windowsVirtualKeyCode:n.keyCode,modifiers:s,text:n.text??"",unmodifiedText:n.text??"",location:n.location??0})}async pressKey(i,e,n=0){const s=this.getKeyDefinition(e);if(!s)throw new Error(`Unknown key: ${e}`);await this.dispatchKeyEvent(i,"keyDown",s,n),await this.dispatchKeyEvent(i,"keyUp",s,n)}async pressKeyChord(i,e){const n=e.toLowerCase().split("+"),s=[];let d="";for(const f of n)f in Y?s.push(f):d=f;let l=0;for(const f of s)l|=Y[f]||0;d&&await this.pressKey(i,d,l)}getKeyDefinition(i){const e=i.toLowerCase();if(he[e])return he[e];if(i.length===1){const n=i.toUpperCase().charCodeAt(0);return{key:i,code:`Key${i.toUpperCase()}`,keyCode:n,text:i}}return null}parseModifiers(i){if(!i)return 0;let e=0;const n=i.toLowerCase().split("+");for(const s of n){const d=s.trim();d in Y&&(e|=Y[d])}return e}};O(A,"debuggerListenerRegistered",!1),O(A,"MAX_INLINE_BODY_SIZE",16*1024),O(A,"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"])),O(A,"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"]));let se=A,oe=!1,pe=!1;const ae=[];chrome.storage.local.get("debugMode").then(({debugMode:t})=>{if(oe=!!t,pe=!0,oe)for(const i of ae)console.log("[Surf]",...i);ae.length=0});chrome.storage.onChanged.addListener((t,i)=>{i==="local"&&t.debugMode&&(oe=!!t.debugMode.newValue)});function q(...t){if(!pe){ae.push(t);return}oe&&console.log("[Surf]",...t)}const te=new Map;function _e(t){const{type:i,streamId:e}=t;if(!e||!te.has(e))return!1;const n=te.get(e);switch(i){case"API_RESPONSE_START":return n.onStart(t.status,t.headers),!0;case"API_RESPONSE_CHUNK":return n.onChunk(t.chunk),!0;case"API_RESPONSE_END":return n.onEnd(),te.delete(e),!0;case"API_RESPONSE_ERROR":return n.onError(t.error),te.delete(e),!0;default:return!1}}let L=null,ce=null,X=null,V=new Map,Ce=0;function Ee(t){ce=t,le()}function ke(t){return new Promise((i,e)=>{if(!L){e(new Error("Native host not connected"));return}if(t.type==="API_REQUEST"){L.postMessage(t),i({sent:!0});return}const n=++Ce;V.set(n,{resolve:i,reject:e}),L.postMessage({...t,id:n}),setTimeout(()=>{V.has(n)&&(V.delete(n),e(new Error("Native host request timeout")))},1e4)})}function z(t){L&&L.postMessage(t)}function le(){X&&(clearTimeout(X),X=null);try{L=chrome.runtime.connectNative("surf.browser.host"),q("Connecting to native host..."),L.onMessage.addListener(async t=>{var i;if(q("Received from native host:",t.type||t.id),t.type==="HOST_READY"){q("Native host ready");return}if((i=t.type)!=null&&i.startsWith("API_RESPONSE_")){_e(t),chrome.runtime.sendMessage(t).catch(()=>{});return}if(t.id&&V.has(t.id)){const{resolve:e}=V.get(t.id);V.delete(t.id),e(t);return}if(ce)try{const e=await ce(t);if(!L){q("Cannot send response - native host disconnected:",t.id);return}L.postMessage({id:t.id,...e})}catch(e){if(!L){q("Cannot send error - native host disconnected:",t.id);return}L.postMessage({id:t.id,error:e instanceof Error?e.message:"Unknown error"})}}),L.onDisconnect.addListener(()=>{var i;const t=chrome.runtime.lastError;q("Native host disconnected:",(t==null?void 0:t.message)||"unknown reason"),L=null,(i=t==null?void 0:t.message)!=null&&i.includes("not found")||(X=setTimeout(le,5e3))})}catch(t){q("Failed to connect to native host:",t),X=setTimeout(le,1e4)}}const we=Object.freeze(Object.defineProperty({__proto__:null,initNativeMessaging:Ee,postToNativeHost:z,sendToNativeHost:ke},Symbol.toStringTag,{value:"Module"}));q("Service worker loaded");const u=new se,$=new Map,J=new Map;function C(t){return J.get(t)??0}const j=new Map;let Ae=0;function Ne(){return`screenshot_${++Ae}_${Date.now()}`}function Oe(t,i){if(j.set(t,i),j.size>10){const e=j.keys().next().value;e&&j.delete(e)}}function Me(t){return j.get(t)||null}const fe={button:"#FF6B6B",input:"#4ECDC4",select:"#45B7D1",a:"#96CEB4",textarea:"#FF8C42",default:"#DDA0DD"};async function Re(t,i,e){const n=be(t.base64),s=await createImageBitmap(n),d=new OffscreenCanvas(s.width,s.height),l=d.getContext("2d");if(!l)throw new Error("Failed to get canvas context");l.drawImage(s,0,0),s.close();const f=Math.min(e.scaleX,e.scaleY);for(const E of i){const T=fe[E.tag]||fe.default,S=Math.round(E.bounds.x*f),p=Math.round(E.bounds.y*f),v=Math.round(E.bounds.width*f),g=Math.round(E.bounds.height*f);if(v<1||g<1)continue;l.strokeStyle=T,l.lineWidth=2,l.setLineDash([4,4]),l.strokeRect(S,p,v,g),l.setLineDash([]);const k=E.ref,x=Math.max(10,Math.min(16,Math.round(d.width*.01)));l.font=`bold ${x}px sans-serif`;const B=l.measureText(k).width,F=4,M=B+F*2,N=x+F*2;let r=S+Math.floor((v-M)/2),o=p+2;(v<60||g<30)&&(o=p-N-2<0?p+g+2:p-N-2),r=Math.max(0,Math.min(d.width-M,r)),o=Math.max(0,Math.min(d.height-N,o)),l.fillStyle=T,l.fillRect(r,o,M,N),l.strokeStyle="white",l.lineWidth=1,l.strokeRect(r,o,M,N),l.fillStyle="white",l.textBaseline="top",l.fillText(k,r+F,o+F)}const y=await d.convertToBlob({type:"image/png"});return{base64:await me(y),width:d.width,height:d.height}}function me(t){return new Promise((i,e)=>{const n=new FileReader;n.onload=()=>{const d=n.result.split(",")[1];i(d)},n.onerror=()=>e(new Error("Failed to convert blob to base64")),n.readAsDataURL(t)})}function be(t,i="image/png"){const e=atob(t),n=new Uint8Array(e.length);for(let s=0;s<e.length;s++)n[s]=e.charCodeAt(s);return new Blob([n],{type:i})}async function Le(t,i){var F;const n=(F=(await u.evaluateScript(t,`(() => ({
1
+ const te="modulepreload",re=function(o){return"/"+o},$={},V=function(i,t,e){let r=Promise.resolve();if(t&&t.length>0){let u=function(d){return Promise.all(d.map(h=>Promise.resolve(h).then(f=>({status:"fulfilled",value:f}),f=>({status:"rejected",reason:f}))))};var s=u;document.getElementsByTagName("link");const a=document.querySelector("meta[property=csp-nonce]"),c=a?.nonce||a?.getAttribute("nonce");r=u(t.map(d=>{if(d=re(d),d in $)return;$[d]=!0;const h=d.endsWith(".css"),f=h?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${d}"]${f}`))return;const w=document.createElement("link");if(w.rel=h?"stylesheet":te,h||(w.as="script"),w.crossOrigin="",w.href=d,c&&w.setAttribute("nonce",c),document.head.appendChild(w),h)return new Promise((p,E)=>{w.addEventListener("load",p),w.addEventListener("error",()=>E(new Error(`Unable to preload CSS for ${d}`)))})}))}function n(a){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=a,window.dispatchEvent(c),!c.defaultPrevented)throw a}return r.then(a=>{for(const c of a||[])c.status==="rejected"&&n(c.reason);return i().catch(n)})},L={alt:1,ctrl:2,control:2,meta:4,cmd:4,command:4,win:4,windows:4,shift:8},Y={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}};class I{targets=new Map;consoleMessages=new Map;networkRequests=new Map;networkEntries=new Map;consoleCallbacks=new Map;networkCallbacks=new Map;networkRequestStartTimes=new Map;pendingDialogs=new Map;networkEntrySeq=0;static debuggerListenerRegistered=!1;static MAX_INLINE_BODY_SIZE=16*1024;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(i){if(this.targets.has(i))return;const t={tabId:i};try{await chrome.debugger.attach(t,"1.3")}catch(e){const r=e instanceof Error?e.message:String(e);if(r.includes("Already attached")){this.targets.set(i,t);return}throw r.includes("Cannot access")||r.includes("Cannot attach")?new Error("Cannot control this page. Chrome restricts automation on chrome://, extensions, and web store pages."):new Error(`Failed to attach debugger: ${r}`)}this.targets.set(i,t),this.setupEventListener(),this.consoleMessages.set(i,[]),this.networkRequests.set(i,[]);try{await this.send(i,"Page.enable")}catch{}}async detach(i){const t=this.targets.get(i);if(t){try{await chrome.debugger.detach(t)}catch(e){console.warn("[CDPController] Error detaching:",e)}this.targets.delete(i),this.consoleMessages.delete(i),this.networkRequests.delete(i),this.networkEntries.delete(i),this.consoleCallbacks.delete(i),this.networkCallbacks.delete(i),this.pendingDialogs.delete(i)}}async detachAll(){for(const i of this.targets.keys())await this.detach(i)}setupEventListener(){I.debuggerListenerRegistered||(I.debuggerListenerRegistered=!0,chrome.debugger.onEvent.addListener((i,t,e)=>{const r=i.tabId;!r||!this.targets.has(r)||this.handleCDPEvent(r,t,e)}),chrome.debugger.onDetach.addListener((i,t)=>{const e=i.tabId;e&&this.targets.has(e)&&(this.targets.delete(e),this.consoleMessages.delete(e),this.networkRequests.delete(e),this.networkEntries.delete(e),this.consoleCallbacks.delete(e),this.networkCallbacks.delete(e))}))}handleCDPEvent(i,t,e){switch(t){case"Runtime.consoleAPICalled":this.handleRuntimeConsole(i,e);break;case"Runtime.exceptionThrown":this.handleRuntimeException(i,e);break;case"Network.requestWillBeSent":this.handleNetworkRequest(i,e);break;case"Network.responseReceived":this.handleNetworkResponse(i,e);break;case"Network.loadingFailed":this.handleNetworkFailed(i,e);break;case"Network.loadingFinished":this.handleLoadingFinished(i,e);break;case"Page.javascriptDialogOpening":this.handleDialogOpening(i,e);break;case"Page.javascriptDialogClosed":this.pendingDialogs.delete(i);break}}handleRuntimeConsole(i,t){const e=this.consoleMessages.get(i)||[],n=(t.args||[]).map(u=>u.value!==void 0?String(u.value):u.description?u.description:"").join(" "),s=t.stackTrace?.callFrames?.[0],a={type:t.type||"log",text:n,timestamp:t.timestamp||Date.now(),url:s?.url,line:s?.lineNumber};e.push(a),e.length>1e3&&e.shift(),this.consoleMessages.set(i,e);const c=this.consoleCallbacks.get(i);if(c)for(const u of c.values())u(a)}handleRuntimeException(i,t){const e=this.consoleMessages.get(i)||[],r=t.exceptionDetails;if(!r)return;const n={type:"exception",text:r.exception?.description||r.text||"Unknown exception",timestamp:r.timestamp||Date.now(),url:r.url,line:r.lineNumber};e.push(n),e.length>1e3&&e.shift(),this.consoleMessages.set(i,e);const s=this.consoleCallbacks.get(i);if(s)for(const a of s.values())a(n)}handleNetworkRequest(i,t){const e=this.networkRequests.get(i)||[],r=t.request;if(!r)return;const n=t.timestamp?t.timestamp*1e3:Date.now();this.networkRequestStartTimes.set(t.requestId,n);const s={};if(r.headers)for(const[p,E]of Object.entries(r.headers))s[p]=String(E);e.push({requestId:t.requestId,url:r.url,method:r.method,type:t.type,timestamp:n,requestHeaders:s,requestBody:r.postData}),e.length>500&&e.shift(),this.networkRequests.set(i,e),this.networkEntries.has(i)||this.networkEntries.set(i,new Map);const a=this.networkEntries.get(i),c=++this.networkEntrySeq,u=`r_${n}_${c}`,d={};if(r.headers)for(const[p,E]of Object.entries(r.headers))d[p]=String(E);const h=r.postData,f=h?h.length:void 0,w={id:u,ts:n,method:r.method,url:r.url,origin:this.extractOrigin(r.url),requestHeaders:d,requestBody:h,requestBodySize:f,tabId:i,tabUrl:t.documentURL,type:t.type,flags:[],_requestId:t.requestId,_responseReceived:!1,_loadingFinished:!1};if(a.size>500){const p=a.keys().next().value;p&&a.delete(p)}a.set(t.requestId,w)}handleNetworkResponse(i,t){const r=(this.networkRequests.get(i)||[]).find(a=>a.requestId===t.requestId);if(r){if(r.status=t.response?.status,r.mimeType=t.response?.mimeType,t.response?.headers){const c={};for(const[u,d]of Object.entries(t.response.headers))c[u]=String(d);r.responseHeaders=c}const a=this.networkCallbacks.get(i);if(a){const c=this.networkRequestStartTimes.get(t.requestId),u=Date.now(),d=c?Math.round(u-c):void 0;for(const h of a.values())h({method:r.method,url:r.url,status:r.status,duration:d,timestamp:u})}}const s=this.networkEntries.get(i)?.get(t.requestId);if(s&&t.response){const a=t.response,c=this.networkRequestStartTimes.get(t.requestId),u=t.timestamp?t.timestamp*1e3:Date.now();c&&(s.ttfb=Math.round(u-c)),s.status=a.status,s.statusText=a.statusText,s.mimeType=a.mimeType;const d={};if(a.headers)for(const[h,f]of Object.entries(a.headers))d[h]=String(f);s.responseHeaders=d,this.isBinaryType(a.mimeType)&&s.flags.push("binary"),(a.mimeType?.includes("protobuf")||a.mimeType?.includes("x-protobuf")||a.mimeType?.includes("application/grpc"))&&s.flags.push("protobuf"),s._responseReceived=!0}}handleNetworkFailed(i,t){const r=(this.networkRequests.get(i)||[]).find(a=>a.requestId===t.requestId);if(r&&!r.status){r.status=0;const a=this.networkCallbacks.get(i);if(a){const c=this.networkRequestStartTimes.get(t.requestId),u=Date.now(),d=c?Math.round(u-c):void 0;this.networkRequestStartTimes.delete(t.requestId);for(const h of a.values())h({method:r.method,url:r.url,status:0,duration:d,timestamp:u})}}const s=this.networkEntries.get(i)?.get(t.requestId);if(s){const a=this.networkRequestStartTimes.get(t.requestId),c=t.timestamp?t.timestamp*1e3:Date.now();a&&(s.duration=Math.round(c-a)),this.networkRequestStartTimes.delete(t.requestId),s.status=0,s.flags.push("failed"),s._loadingFinished=!0}}handleDialogOpening(i,t){this.pendingDialogs.set(i,{type:t.type,message:t.message,defaultPrompt:t.defaultPrompt,timestamp:Date.now()})}async handleLoadingFinished(i,t){const r=(this.networkRequests.get(i)||[]).find(d=>d.requestId===t.requestId);if(r){const d=this.networkRequestStartTimes.get(t.requestId),h=t.timestamp?t.timestamp*1e3:Date.now();if(d&&(r.duration=Math.round(h-d)),!this.isStaticAsset(r.mimeType)&&!this.isBinaryType(r.mimeType)&&(t.encodedDataLength||0)<=I.MAX_INLINE_BODY_SIZE)try{const w=await this.send(i,"Network.getResponseBody",{requestId:t.requestId});if(w.base64Encoded)try{r.responseBody=atob(w.body)}catch{r.responseBody=w.body}else r.responseBody=w.body;r.responseBody&&r.responseBody.length>I.MAX_INLINE_BODY_SIZE&&(r.responseBody=r.responseBody.slice(0,I.MAX_INLINE_BODY_SIZE))}catch{}}const s=this.networkEntries.get(i)?.get(t.requestId);if(!s)return;const a=this.networkRequestStartTimes.get(t.requestId),c=t.timestamp?t.timestamp*1e3:Date.now();if(a&&(s.duration=Math.round(c-a)),this.networkRequestStartTimes.delete(t.requestId),s.responseBodySize=t.encodedDataLength,s._loadingFinished=!0,!this.isStaticAsset(s.mimeType)&&!this.isBinaryType(s.mimeType)&&(t.encodedDataLength||0)<=I.MAX_INLINE_BODY_SIZE)try{const d=await this.send(i,"Network.getResponseBody",{requestId:t.requestId});if(d.base64Encoded)try{s.responseBody=atob(d.body)}catch{s.responseBody=d.body,s.flags.push("binary")}else s.responseBody=d.body;s.responseBody&&s.responseBody.length>I.MAX_INLINE_BODY_SIZE&&(s.responseBody=s.responseBody.slice(0,I.MAX_INLINE_BODY_SIZE),s.flags.push("truncated"))}catch{}}extractOrigin(i){try{return new URL(i).origin}catch{return""}}isStaticAsset(i){return i?I.STATIC_ASSET_TYPES.has(i):!1}isBinaryType(i){return i?I.BINARY_TYPES.has(i):!1}async enableConsoleTracking(i){await this.ensureAttached(i);try{await this.send(i,"Runtime.enable")}catch{}}async enableNetworkTracking(i){await this.ensureAttached(i);try{await this.send(i,"Network.enable",{maxPostDataSize:65536})}catch{}}async handleDialog(i,t,e){try{return await this.send(i,"Page.handleJavaScriptDialog",{accept:t,promptText:e}),this.pendingDialogs.delete(i),{success:!0}}catch(r){return{success:!1,error:r instanceof Error?r.message:String(r)}}}getDialogInfo(i){return this.pendingDialogs.get(i)||null}async emulateNetwork(i,t){await this.ensureAttached(i);const e={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=e[t.toLowerCase().replace(/\s+/g,"-")];if(!r)return{success:!1,error:`Unknown preset: ${t}. Available: ${Object.keys(e).join(", ")}`};try{return await this.send(i,"Network.enable"),await this.send(i,"Network.emulateNetworkConditions",r),{success:!0}}catch(n){return{success:!1,error:n instanceof Error?n.message:String(n)}}}async emulateCPU(i,t){if(await this.ensureAttached(i),t<1)return{success:!1,error:"CPU throttling rate must be >= 1 (1 = no throttle, 4 = 4x slower)"};try{return await this.send(i,"Emulation.setCPUThrottlingRate",{rate:t}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async emulateGeolocation(i,t,e,r){await this.ensureAttached(i);try{return await this.send(i,"Emulation.setGeolocationOverride",{latitude:t,longitude:e,accuracy:r||100}),{success:!0}}catch(n){return{success:!1,error:n instanceof Error?n.message:String(n)}}}async clearGeolocation(i){await this.ensureAttached(i);try{return await this.send(i,"Emulation.clearGeolocationOverride"),{success:!0}}catch(t){return{success:!1,error:t instanceof Error?t.message:String(t)}}}async emulateDevice(i,t){await this.ensureAttached(i);try{return await this.send(i,"Emulation.setDeviceMetricsOverride",{width:t.width,height:t.height,deviceScaleFactor:t.deviceScaleFactor,mobile:t.mobile}),t.userAgent&&await this.send(i,"Emulation.setUserAgentOverride",{userAgent:t.userAgent}),t.touch&&await this.send(i,"Emulation.setTouchEmulationEnabled",{enabled:!0,maxTouchPoints:5}),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async clearDeviceEmulation(i){await this.ensureAttached(i);try{return await this.send(i,"Emulation.clearDeviceMetricsOverride"),await this.send(i,"Emulation.setUserAgentOverride",{userAgent:""}),await this.send(i,"Emulation.setTouchEmulationEnabled",{enabled:!1}),{success:!0}}catch(t){return{success:!1,error:t instanceof Error?t.message:String(t)}}}async emulateViewport(i,t){await this.ensureAttached(i);try{const e=await this.getViewportSize(i);return await this.send(i,"Emulation.setDeviceMetricsOverride",{width:t.width||e.width,height:t.height||e.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(i,t){await this.ensureAttached(i);try{return await this.send(i,"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(i,t){await this.ensureAttached(i);try{return await this.send(i,"Performance.enable"),await this.send(i,"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(i){await this.ensureAttached(i);try{await this.send(i,"Performance.enable");const t=await this.send(i,"Performance.getMetrics");await this.send(i,"Tracing.end"),await this.send(i,"Performance.disable");const e={};for(const r of t.metrics||[])e[r.name]=r.value;return{success:!0,metrics:e}}catch(t){return{success:!1,error:t instanceof Error?t.message:String(t)}}}async getPerformanceMetrics(i){await this.ensureAttached(i);try{await this.send(i,"Performance.enable");const t=await this.send(i,"Performance.getMetrics");await this.send(i,"Performance.disable");const e={};for(const r of t.metrics||[])e[r.name]=r.value;return{success:!0,metrics:e}}catch(t){return{success:!1,error:t instanceof Error?t.message:String(t)}}}async setFileInputBySelector(i,t,e){await this.ensureAttached(i);try{await this.send(i,"DOM.enable");const r=await this.send(i,"DOM.getDocument"),n=await this.send(i,"DOM.querySelector",{nodeId:r.root.nodeId,selector:t});return n.nodeId?(await this.send(i,"DOM.setFileInputFiles",{nodeId:n.nodeId,files:e}),{success:!0}):{success:!1,error:"Could not find element by selector"}}catch(r){return{success:!1,error:r instanceof Error?r.message:String(r)}}}async waitForLoad(i,t=3e4){await this.ensureAttached(i);const e=Date.now();try{for(;Date.now()-e<t;){const n=(await this.send(i,"Runtime.evaluate",{expression:"document.readyState",returnByValue:!0})).result?.value;if(n==="complete")return{success:!0,readyState:n};await new Promise(s=>setTimeout(s,100))}return{success:!1,error:`Timeout waiting for page load (${t}ms)`}}catch(r){return{success:!1,error:r instanceof Error?r.message:String(r)}}}async getFrames(i){await this.ensureAttached(i);try{await this.send(i,"Page.enable");const t=await this.send(i,"Page.getFrameTree"),e=[],r=(n,s)=>{if(e.push({frameId:n.frame.id,url:n.frame.url,name:n.frame.name||"",parentId:s}),n.childFrames)for(const a of n.childFrames)r(a,n.frame.id)};return r(t.frameTree),{success:!0,frames:e}}catch(t){return{success:!1,error:t instanceof Error?t.message:String(t)}}}async evaluateInFrame(i,t,e){await this.ensureAttached(i);try{const r=await this.send(i,"Page.createIsolatedWorld",{frameId:t,worldName:"surf-isolated"}),n=`JSON.stringify((function() { ${e} })())`,s=await this.send(i,"Runtime.evaluate",{expression:n,contextId:r.executionContextId,returnByValue:!0,awaitPromise:!0});if(s.exceptionDetails)return{success:!1,error:s.exceptionDetails.text||s.exceptionDetails.exception?.description||"Evaluation failed"};try{return{success:!0,result:JSON.parse(s.result?.value)}}catch{return{success:!0,result:s.result?.value}}}catch(r){return{success:!1,error:r instanceof Error?r.message:String(r)}}}getConsoleMessages(i,t){let e=this.consoleMessages.get(i)||[];if(t?.onlyErrors&&(e=e.filter(r=>r.type==="error"||r.type==="exception")),t?.pattern)try{const r=new RegExp(t.pattern,"i");e=e.filter(n=>r.test(n.text))}catch{e=e.filter(n=>n.text.includes(t.pattern))}return t?.limit&&(e=e.slice(-t.limit)),[...e]}clearConsoleMessages(i){this.consoleMessages.set(i,[])}getNetworkRequests(i,t){let e=this.networkRequests.get(i)||[];return t?.urlPattern&&(e=e.filter(r=>r.url.includes(t.urlPattern))),t?.limit&&(e=e.slice(-t.limit)),[...e]}clearNetworkRequests(i){this.networkRequests.set(i,[]),this.networkEntries.set(i,new Map)}getNetworkEntries(i,t){const e=this.networkEntries.get(i);let r=[];return e&&e.size>0?r=Array.from(e.values()):r=(this.networkRequests.get(i)||[]).map((s,a)=>({id:`r_${s.timestamp}_${a}`,ts:s.timestamp,method:s.method,url:s.url,origin:this.extractOrigin(s.url),requestHeaders:{},tabId:i,type:s.type,status:s.status,flags:[],_requestId:s.requestId,_responseReceived:!0,_loadingFinished:!0})),t?.includeStatic||(r=r.filter(n=>!this.isStaticAsset(n.mimeType))),t?.urlPattern&&(r=r.filter(n=>n.url.includes(t.urlPattern))),t?.limit&&(r=r.slice(-t.limit)),r}getNetworkEntry(i,t){return this.networkEntries.get(i)?.get(t)||null}async getResponseBody(i,t){await this.ensureAttached(i);try{const e=await this.send(i,"Network.getResponseBody",{requestId:t});return{success:!0,body:e.body,base64Encoded:e.base64Encoded}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}subscribeToConsole(i,t,e){this.consoleCallbacks.has(i)||this.consoleCallbacks.set(i,new Map),this.consoleCallbacks.get(i).set(t,e)}unsubscribeFromConsole(i,t){const e=this.consoleCallbacks.get(i);e&&(e.delete(t),e.size===0&&this.consoleCallbacks.delete(i))}subscribeToNetwork(i,t,e){this.networkCallbacks.has(i)||this.networkCallbacks.set(i,new Map),this.networkCallbacks.get(i).set(t,e)}unsubscribeFromNetwork(i,t){const e=this.networkCallbacks.get(i);e&&(e.delete(t),e.size===0&&this.networkCallbacks.delete(i))}async evaluateScript(i,t){await this.ensureAttached(i);try{await this.send(i,"Runtime.enable")}catch{}return this.send(i,"Runtime.evaluate",{expression:t,returnByValue:!0,awaitPromise:!0,timeout:3e4})}async send(i,t,e){await this.ensureAttached(i);const r=this.targets.get(i);return chrome.debugger.sendCommand(r,t,e)}async sendCommand(i,t,e){return this.send(i,t,e)}async ensureAttached(i){this.targets.has(i)||await this.attach(i)}async getViewportSize(i){const t=await this.send(i,"Page.getLayoutMetrics"),e=t.visualViewport||t.layoutViewport;return{width:Math.round(e.clientWidth),height:Math.round(e.clientHeight)}}async captureScreenshot(i){const t=await this.send(i,"Page.captureScreenshot",{format:"png",captureBeyondViewport:!1}),{width:e,height:r}=await this.getViewportSize(i);return{base64:t.data,width:e,height:r}}async captureRegion(i,t,e,r,n){return{base64:(await this.send(i,"Page.captureScreenshot",{format:"png",clip:{x:t,y:e,width:r,height:n,scale:1}})).data,width:r,height:n}}async dispatchMouseEvent(i,t,e,r,n={}){const s={type:t,x:Math.round(e),y:Math.round(r),modifiers:n.modifiers||0};(t==="mousePressed"||t==="mouseReleased"||t==="mouseMoved")&&(s.button=n.button||"none",(t==="mousePressed"||t==="mouseReleased")&&(s.clickCount=n.clickCount||1)),t!=="mouseWheel"&&(s.buttons=n.buttons??0),t==="mouseWheel"&&(s.deltaX=n.deltaX||0,s.deltaY=n.deltaY||0),await this.send(i,"Input.dispatchMouseEvent",s)}async click(i,t,e,r="left",n=1,s=0){const a=r==="left"?1:r==="right"?2:r==="middle"?4:0;await this.dispatchMouseEvent(i,"mouseMoved",t,e,{button:"none",buttons:0,modifiers:s}),await new Promise(c=>setTimeout(c,100));for(let c=1;c<=n;c++)await this.dispatchMouseEvent(i,"mousePressed",t,e,{button:r,buttons:a,clickCount:c,modifiers:s}),await new Promise(u=>setTimeout(u,12)),await this.dispatchMouseEvent(i,"mouseReleased",t,e,{button:r,buttons:0,clickCount:c,modifiers:s}),c<n&&await new Promise(u=>setTimeout(u,100))}async rightClick(i,t,e,r=0){await this.click(i,t,e,"right",1,r)}async doubleClick(i,t,e,r=0){await this.click(i,t,e,"left",2,r)}async tripleClick(i,t,e,r=0){await this.click(i,t,e,"left",3,r)}async hover(i,t,e){await this.dispatchMouseEvent(i,"mouseMoved",t,e,{button:"none",buttons:0})}async drag(i,t,e,r,n,s=0){await this.dispatchMouseEvent(i,"mouseMoved",t,e,{button:"none",buttons:0}),await new Promise(a=>setTimeout(a,50)),await this.dispatchMouseEvent(i,"mousePressed",t,e,{button:"left",buttons:1,clickCount:1,modifiers:s}),await new Promise(a=>setTimeout(a,50)),await this.dispatchMouseEvent(i,"mouseMoved",r,n,{button:"left",buttons:1,modifiers:s}),await new Promise(a=>setTimeout(a,50)),await this.dispatchMouseEvent(i,"mouseReleased",r,n,{button:"left",buttons:0,clickCount:1,modifiers:s})}async scroll(i,t,e,r,n){await this.dispatchMouseEvent(i,"mouseWheel",t,e,{deltaX:r,deltaY:n})}async type(i,t){for(const e of t)if(e===`
2
+ `||e==="\r")await this.pressKey(i,"Enter");else if(this.getKeyDefinition(e)){const n=this.requiresShift(e);await this.pressKey(i,e,n?L.shift:0)}else await this.send(i,"Input.insertText",{text:e})}requiresShift(i){return/[A-Z!@#$%^&*()_+{}|:"<>?~]/.test(i)}async dispatchKeyEvent(i,t,e,r=0){await this.send(i,"Input.dispatchKeyEvent",{type:e.text?t:t==="keyDown"?"rawKeyDown":t,key:e.key,code:e.code,windowsVirtualKeyCode:e.keyCode,modifiers:r,text:e.text??"",unmodifiedText:e.text??"",location:e.location??0})}async pressKey(i,t,e=0){const r=this.getKeyDefinition(t);if(!r)throw new Error(`Unknown key: ${t}`);await this.dispatchKeyEvent(i,"keyDown",r,e),await this.dispatchKeyEvent(i,"keyUp",r,e)}async pressKeyChord(i,t){const e=t.toLowerCase().split("+"),r=[];let n="";for(const a of e)a in L?r.push(a):n=a;let s=0;for(const a of r)s|=L[a]||0;n&&await this.pressKey(i,n,s)}getKeyDefinition(i){const t=i.toLowerCase();if(Y[t])return Y[t];if(i.length===1){const e=i.toUpperCase().charCodeAt(0);return{key:i,code:`Key${i.toUpperCase()}`,keyCode:e,text:i}}return null}parseModifiers(i){if(!i)return 0;let t=0;const e=i.toLowerCase().split("+");for(const r of e){const n=r.trim();n in L&&(t|=L[n])}return t}}let B=!1,j=!1;const H=[];chrome.storage.local.get("debugMode").then(({debugMode:o})=>{if(B=!!o,j=!0,B)for(const i of H)console.log("[Surf]",...i);H.length=0});chrome.storage.onChanged.addListener((o,i)=>{i==="local"&&o.debugMode&&(B=!!o.debugMode.newValue)});function C(...o){if(!j){H.push(o);return}B&&console.log("[Surf]",...o)}const q=new Map;function oe(o){const{type:i,streamId:t}=o;if(!t||!q.has(t))return!1;const e=q.get(t);switch(i){case"API_RESPONSE_START":return e.onStart(o.status,o.headers),!0;case"API_RESPONSE_CHUNK":return e.onChunk(o.chunk),!0;case"API_RESPONSE_END":return e.onEnd(),q.delete(t),!0;case"API_RESPONSE_ERROR":return e.onError(o.error),q.delete(t),!0;default:return!1}}let v=null,K=null,P=null,R=new Map,ie=0;function J(o){K=o,W()}function ne(o){return new Promise((i,t)=>{if(!v){t(new Error("Native host not connected"));return}if(o.type==="API_REQUEST"){v.postMessage(o),i({sent:!0});return}const e=++ie;R.set(e,{resolve:i,reject:t}),v.postMessage({...o,id:e}),setTimeout(()=>{R.has(e)&&(R.delete(e),t(new Error("Native host request timeout")))},1e4)})}function x(o){v&&v.postMessage(o)}function W(){P&&(clearTimeout(P),P=null);try{v=chrome.runtime.connectNative("surf.browser.host"),C("Connecting to native host..."),v.onMessage.addListener(async o=>{if(C("Received from native host:",o.type||o.id),o.type==="HOST_READY"){C("Native host ready");return}if(o.type?.startsWith("API_RESPONSE_")){oe(o),chrome.runtime.sendMessage(o).catch(()=>{});return}if(o.id&&R.has(o.id)){const{resolve:i}=R.get(o.id);R.delete(o.id),i(o);return}if(K)try{const i=await K(o);if(!v){C("Cannot send response - native host disconnected:",o.id);return}v.postMessage({id:o.id,...i})}catch(i){if(!v){C("Cannot send error - native host disconnected:",o.id);return}v.postMessage({id:o.id,error:i instanceof Error?i.message:"Unknown error"})}}),v.onDisconnect.addListener(()=>{const o=chrome.runtime.lastError;C("Native host disconnected:",o?.message||"unknown reason"),v=null,o?.message?.includes("not found")||(P=setTimeout(W,5e3))})}catch(o){C("Failed to connect to native host:",o),P=setTimeout(W,1e4)}}const X=Object.freeze(Object.defineProperty({__proto__:null,initNativeMessaging:J,postToNativeHost:x,sendToNativeHost:ne},Symbol.toStringTag,{value:"Module"}));C("Service worker loaded");const l=new I,M=new Map,F=new Map;function b(o){return F.get(o)??0}const D=new Map;let se=0;function ae(){return`screenshot_${++se}_${Date.now()}`}function ce(o,i){if(D.set(o,i),D.size>10){const t=D.keys().next().value;t&&D.delete(t)}}function le(o){return D.get(o)||null}const z={button:"#FF6B6B",input:"#4ECDC4",select:"#45B7D1",a:"#96CEB4",textarea:"#FF8C42",default:"#DDA0DD"};async function ue(o,i,t){const e=Q(o.base64),r=await createImageBitmap(e),n=new OffscreenCanvas(r.width,r.height),s=n.getContext("2d");if(!s)throw new Error("Failed to get canvas context");s.drawImage(r,0,0),r.close();const a=Math.min(t.scaleX,t.scaleY);for(const d of i){const h=z[d.tag]||z.default,f=Math.round(d.bounds.x*a),w=Math.round(d.bounds.y*a),p=Math.round(d.bounds.width*a),E=Math.round(d.bounds.height*a);if(p<1||E<1)continue;s.strokeStyle=h,s.lineWidth=2,s.setLineDash([4,4]),s.strokeRect(f,w,p,E),s.setLineDash([]);const _=d.ref,S=Math.max(10,Math.min(16,Math.round(n.width*.01)));s.font=`bold ${S}px sans-serif`;const N=s.measureText(_).width,m=4,y=N+m*2,g=S+m*2;let T=f+Math.floor((p-y)/2),O=w+2;(p<60||E<30)&&(O=w-g-2<0?w+E+2:w-g-2),T=Math.max(0,Math.min(n.width-y,T)),O=Math.max(0,Math.min(n.height-g,O)),s.fillStyle=h,s.fillRect(T,O,y,g),s.strokeStyle="white",s.lineWidth=1,s.strokeRect(T,O,y,g),s.fillStyle="white",s.textBaseline="top",s.fillText(_,T+m,O+m)}const c=await n.convertToBlob({type:"image/png"});return{base64:await Z(c),width:n.width,height:n.height}}function Z(o){return new Promise((i,t)=>{const e=new FileReader;e.onload=()=>{const n=e.result.split(",")[1];i(n)},e.onerror=()=>t(new Error("Failed to convert blob to base64")),e.readAsDataURL(o)})}function Q(o,i="image/png"){const t=atob(o),e=new Uint8Array(t.length);for(let r=0;r<t.length;r++)e[r]=t.charCodeAt(r);return new Blob([e],{type:i})}async function de(o,i){const e=(await l.evaluateScript(o,`(() => ({
3
3
  viewportHeight: window.innerHeight,
4
4
  totalHeight: Math.min(document.documentElement.scrollHeight, ${i}),
5
5
  width: window.innerWidth,
6
6
  devicePixelRatio: window.devicePixelRatio || 1,
7
7
  originalScrollY: window.scrollY,
8
- }))()`)).result)==null?void 0:F.value;if(!n)throw new Error("Failed to get page dimensions");const{viewportHeight:s,totalHeight:d,width:l,devicePixelRatio:f,originalScrollY:y}=n,b=[];let E=0;for(;E<d;){await u.evaluateScript(t,`window.scrollTo(0, ${E})`),await new Promise(r=>setTimeout(r,300));const M=await u.captureScreenshot(t),N=be(M.base64);b.push(await createImageBitmap(N)),E+=s}await u.evaluateScript(t,`window.scrollTo(0, ${y})`);const T=Math.round(l*f),S=Math.round(d*f),p=new OffscreenCanvas(T,S),v=p.getContext("2d");if(!v)throw new Error("Failed to get canvas context");let g=0;const k=Math.round(s*f);for(let M=0;M<b.length;M++){const N=b[M],r=S-g,o=Math.min(k,r);v.drawImage(N,0,0,N.width,o,0,g,N.width,o),g+=o,N.close()}const x=await p.convertToBlob({type:"image/png"});return{base64:await me(x),width:T,height:S}}const G=new Map,U=new Map;chrome.webNavigation.onCompleted.addListener(t=>{if(t.frameId===0){J.delete(t.tabId);const i=G.get(t.tabId);i&&(i(),G.delete(t.tabId))}});chrome.webNavigation.onErrorOccurred.addListener(t=>{if(t.frameId===0){const i=G.get(t.tabId);i&&(i(),G.delete(t.tabId))}});chrome.tabs.onRemoved.addListener(t=>{u.detach(t),J.delete(t);for(const[i,e]of U)e===t&&U.delete(i);for(const[i,e]of $)e===t&&$.delete(i)});async function re(t,i=1e4){var s;const e=Date.now()+i,n=d=>new Promise(l=>setTimeout(l,d));for(;Date.now()<e;){try{const d=await u.evaluateScript(t,"document.readyState");if(((s=d==null?void 0:d.result)==null?void 0:s.value)==="complete"){await n(1500);return}}catch{}await n(200)}console.warn(`waitForRuntimeReady timed out for tab ${t}`)}async function ne(t,i,e,n,s,d=0){switch(e){case"click":{const l=await chrome.tabs.sendMessage(t,{type:"CLICK_ELEMENT",ref:i,button:"left"},{frameId:d});return l.error?l:{success:!0,action:"click",ref:i}}case"fill":{if(!n)return{error:"fill action requires --value"};const l=await chrome.tabs.sendMessage(t,{type:"FORM_INPUT",ref:i,value:n},{frameId:d});return l.error?l:{success:!0,action:"fill",ref:i,value:n}}case"hover":{const l=await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_COORDINATES",ref:i},{frameId:d});return l.error?l:(await s.hover(t,l.x,l.y),{success:!0,action:"hover",ref:i})}case"text":return await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_TEXT",ref:i},{frameId:d});default:return{error:`Unknown action: ${e}. Use click|fill|hover|text`}}}chrome.runtime.onMessage.addListener((t,i,e)=>(ye(t,i).then(e).catch(n=>e({error:n.message})),!0));async function ye(t,i){var n,s,d,l,f,y,b,E,T,S,p,v,g,k,x,B,F,M,N;const e=t.tabId;switch(t.type){case"GET_CURRENT_TAB_ID":{const[r]=await chrome.tabs.query({active:!0,currentWindow:!0});return{tabId:r==null?void 0:r.id}}case"EXECUTE_SCREENSHOT":{if(!e)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(e,{type:"HIDE_FOR_TOOL_USE"})}catch{}await new Promise(r=>setTimeout(r,50));try{let r,o={scaleX:1,scaleY:1},a=!1;if(t.fullpage){r=await Le(e,t.maxHeight||4e3);try{const c=await u.getViewportSize(e),w=r.width/c.width;o={scaleX:w,scaleY:w}}catch{}}else try{const c=await u.captureScreenshot(e);r=c;try{const w=await u.getViewportSize(e);o={scaleX:c.width/w.width,scaleY:c.height/w.height}}catch{}}catch(c){const w=await chrome.tabs.get(e);if(!w.windowId)throw c;const I=(await chrome.tabs.captureVisibleTab(w.windowId,{format:"png"})).replace(/^data:image\/png;base64,/,""),_=atob(I),R=new Uint8Array(_.length);for(let H=0;H<_.length;H++)R[H]=_.charCodeAt(H);const Z=new Blob([R],{type:"image/png"}),P=await createImageBitmap(Z);r={base64:I,width:P.width,height:P.height},P.close(),a=!0}if(t.annotate&&!a)try{const c=await chrome.tabs.sendMessage(e,{type:"GET_ELEMENT_BOUNDS_FOR_ANNOTATION"},{frameId:0});c!=null&&c.elements&&c.elements.length>0&&(r=await Re(r,c.elements,o))}catch{}const h=Ne();return Oe(h,r),{...r,screenshotId:h}}finally{try{await chrome.tabs.sendMessage(e,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"EXECUTE_CLICK":{if(!e)throw new Error("No tabId provided");const r=t.modifiers?u.parseModifiers(t.modifiers):0;return await u.click(e,t.x,t.y,"left",1,r),{success:!0}}case"EXECUTE_RIGHT_CLICK":{if(!e)throw new Error("No tabId provided");const r=t.modifiers?u.parseModifiers(t.modifiers):0;return await u.rightClick(e,t.x,t.y,r),{success:!0}}case"EXECUTE_DOUBLE_CLICK":{if(!e)throw new Error("No tabId provided");const r=t.modifiers?u.parseModifiers(t.modifiers):0;return await u.doubleClick(e,t.x,t.y,r),{success:!0}}case"EXECUTE_TRIPLE_CLICK":{if(!e)throw new Error("No tabId provided");const r=t.modifiers?u.parseModifiers(t.modifiers):0;return await u.tripleClick(e,t.x,t.y,r),{success:!0}}case"EXECUTE_DRAG":{if(!e)throw new Error("No tabId provided");const r=t.modifiers?u.parseModifiers(t.modifiers):0;return await u.drag(e,t.startX,t.startY,t.endX,t.endY,r),{success:!0}}case"EXECUTE_HOVER":{if(!e)throw new Error("No tabId provided");return await u.hover(e,t.x,t.y),{success:!0}}case"EXECUTE_TYPE":{if(!e)throw new Error("No tabId provided");if(t.text===void 0||t.text===null)throw new Error("No text provided");return await u.type(e,t.text),{success:!0}}case"TYPE_SUBMIT":{if(!e)throw new Error("No tabId provided");if(!t.text)throw new Error("No text provided");return await u.type(e,t.text),await u.pressKey(e,t.submitKey||"Enter"),{success:!0}}case"CLICK_TYPE":{if(!e)throw new Error("No tabId provided");if(!t.text)throw new Error("No text provided");const r=C(e);let o=!1;if(t.ref)try{(await chrome.tabs.sendMessage(e,{type:"CLICK_ELEMENT",ref:t.ref,button:"left"},{frameId:r})).error||(o=!0)}catch{}if(!o&&t.coordinate&&(await u.click(e,t.coordinate[0],t.coordinate[1],"left",1,0),o=!0),!o){const a=await u.evaluateScript(e,`(() => {
8
+ }))()`)).result?.value;if(!e)throw new Error("Failed to get page dimensions");const{viewportHeight:r,totalHeight:n,width:s,devicePixelRatio:a,originalScrollY:c}=e,u=[];let d=0;for(;d<n;){await l.evaluateScript(o,`window.scrollTo(0, ${d})`),await new Promise(g=>setTimeout(g,300));const m=await l.captureScreenshot(o),y=Q(m.base64);u.push(await createImageBitmap(y)),d+=r}await l.evaluateScript(o,`window.scrollTo(0, ${c})`);const h=Math.round(s*a),f=Math.round(n*a),w=new OffscreenCanvas(h,f),p=w.getContext("2d");if(!p)throw new Error("Failed to get canvas context");let E=0;const _=Math.round(r*a);for(let m=0;m<u.length;m++){const y=u[m],g=f-E,T=Math.min(_,g);p.drawImage(y,0,0,y.width,T,0,E,y.width,T),E+=T,y.close()}const S=await w.convertToBlob({type:"image/png"});return{base64:await Z(S),width:h,height:f}}const k=new Map,A=new Map;chrome.webNavigation.onCompleted.addListener(o=>{if(o.frameId===0){F.delete(o.tabId);const i=k.get(o.tabId);i&&(i(),k.delete(o.tabId))}});chrome.webNavigation.onErrorOccurred.addListener(o=>{if(o.frameId===0){const i=k.get(o.tabId);i&&(i(),k.delete(o.tabId))}});chrome.tabs.onRemoved.addListener(o=>{l.detach(o),F.delete(o);for(const[i,t]of A)t===o&&A.delete(i);for(const[i,t]of M)t===o&&M.delete(i)});async function U(o,i=1e4){const t=Date.now()+i,e=r=>new Promise(n=>setTimeout(n,r));for(;Date.now()<t;){try{if((await l.evaluateScript(o,"document.readyState"))?.result?.value==="complete"){await e(1500);return}}catch{}await e(200)}console.warn(`waitForRuntimeReady timed out for tab ${o}`)}async function G(o,i,t,e,r,n=0){switch(t){case"click":{const s=await chrome.tabs.sendMessage(o,{type:"CLICK_ELEMENT",ref:i,button:"left"},{frameId:n});return s.error?s:{success:!0,action:"click",ref:i}}case"fill":{if(!e)return{error:"fill action requires --value"};const s=await chrome.tabs.sendMessage(o,{type:"FORM_INPUT",ref:i,value:e},{frameId:n});return s.error?s:{success:!0,action:"fill",ref:i,value:e}}case"hover":{const s=await chrome.tabs.sendMessage(o,{type:"GET_ELEMENT_COORDINATES",ref:i},{frameId:n});return s.error?s:(await r.hover(o,s.x,s.y),{success:!0,action:"hover",ref:i})}case"text":return await chrome.tabs.sendMessage(o,{type:"GET_ELEMENT_TEXT",ref:i},{frameId:n});default:return{error:`Unknown action: ${t}. Use click|fill|hover|text`}}}chrome.runtime.onMessage.addListener((o,i,t)=>(ee(o,i).then(t).catch(e=>t({error:e.message})),!0));async function ee(o,i){const t=o.tabId;switch(o.type){case"GET_CURRENT_TAB_ID":{const[e]=await chrome.tabs.query({active:!0,currentWindow:!0});return{tabId:e?.id}}case"EXECUTE_SCREENSHOT":{if(!t)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"})}catch{}await new Promise(e=>setTimeout(e,50));try{let e,r={scaleX:1,scaleY:1},n=!1;if(o.fullpage){e=await de(t,o.maxHeight||4e3);try{const a=await l.getViewportSize(t),c=e.width/a.width;r={scaleX:c,scaleY:c}}catch{}}else try{const a=await l.captureScreenshot(t);e=a;try{const c=await l.getViewportSize(t);r={scaleX:a.width/c.width,scaleY:a.height/c.height}}catch{}}catch(a){const c=await chrome.tabs.get(t);if(!c.windowId)throw a;const d=(await chrome.tabs.captureVisibleTab(c.windowId,{format:"png"})).replace(/^data:image\/png;base64,/,""),h=atob(d),f=new Uint8Array(h.length);for(let E=0;E<h.length;E++)f[E]=h.charCodeAt(E);const w=new Blob([f],{type:"image/png"}),p=await createImageBitmap(w);e={base64:d,width:p.width,height:p.height},p.close(),n=!0}if(o.annotate&&!n)try{const a=await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_BOUNDS_FOR_ANNOTATION"},{frameId:0});a?.elements&&a.elements.length>0&&(e=await ue(e,a.elements,r))}catch{}const s=ae();return ce(s,e),{...e,screenshotId:s}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"EXECUTE_CLICK":{if(!t)throw new Error("No tabId provided");const e=o.modifiers?l.parseModifiers(o.modifiers):0;return await l.click(t,o.x,o.y,"left",1,e),{success:!0}}case"EXECUTE_RIGHT_CLICK":{if(!t)throw new Error("No tabId provided");const e=o.modifiers?l.parseModifiers(o.modifiers):0;return await l.rightClick(t,o.x,o.y,e),{success:!0}}case"EXECUTE_DOUBLE_CLICK":{if(!t)throw new Error("No tabId provided");const e=o.modifiers?l.parseModifiers(o.modifiers):0;return await l.doubleClick(t,o.x,o.y,e),{success:!0}}case"EXECUTE_TRIPLE_CLICK":{if(!t)throw new Error("No tabId provided");const e=o.modifiers?l.parseModifiers(o.modifiers):0;return await l.tripleClick(t,o.x,o.y,e),{success:!0}}case"EXECUTE_DRAG":{if(!t)throw new Error("No tabId provided");const e=o.modifiers?l.parseModifiers(o.modifiers):0;return await l.drag(t,o.startX,o.startY,o.endX,o.endY,e),{success:!0}}case"EXECUTE_HOVER":{if(!t)throw new Error("No tabId provided");return await l.hover(t,o.x,o.y),{success:!0}}case"EXECUTE_TYPE":{if(!t)throw new Error("No tabId provided");if(o.text===void 0||o.text===null)throw new Error("No text provided");return await l.type(t,o.text),{success:!0}}case"TYPE_SUBMIT":{if(!t)throw new Error("No tabId provided");if(!o.text)throw new Error("No text provided");return await l.type(t,o.text),await l.pressKey(t,o.submitKey||"Enter"),{success:!0}}case"CLICK_TYPE":{if(!t)throw new Error("No tabId provided");if(!o.text)throw new Error("No text provided");const e=b(t);let r=!1;if(o.ref)try{(await chrome.tabs.sendMessage(t,{type:"CLICK_ELEMENT",ref:o.ref,button:"left"},{frameId:e})).error||(r=!0)}catch{}if(!r&&o.coordinate&&(await l.click(t,o.coordinate[0],o.coordinate[1],"left",1,0),r=!0),!r){const n=await l.evaluateScript(t,`(() => {
9
9
  const el = document.querySelector('textarea, input[type="text"], input[type="search"], input:not([type]), [contenteditable="true"]');
10
10
  if (!el) return null;
11
11
  const r = el.getBoundingClientRect();
12
12
  return { x: r.left + r.width/2, y: r.top + r.height/2 };
13
- })()`);(n=a.result)!=null&&n.value&&(await u.click(e,a.result.value.x,a.result.value.y,"left",1,0),o=!0)}return o?(await u.type(e,t.text),{success:!0}):{error:"Could not find input element"}}case"CLICK_TYPE_SUBMIT":{if(!e)throw new Error("No tabId provided");if(!t.text)throw new Error("No text provided");const r=C(e);let o=!1;if(t.ref)try{(await chrome.tabs.sendMessage(e,{type:"CLICK_ELEMENT",ref:t.ref,button:"left"},{frameId:r})).error||(o=!0)}catch{}if(!o&&t.coordinate&&(await u.click(e,t.coordinate[0],t.coordinate[1],"left",1,0),o=!0),!o){const a=await u.evaluateScript(e,`(() => {
13
+ })()`);n.result?.value&&(await l.click(t,n.result.value.x,n.result.value.y,"left",1,0),r=!0)}return r?(await l.type(t,o.text),{success:!0}):{error:"Could not find input element"}}case"CLICK_TYPE_SUBMIT":{if(!t)throw new Error("No tabId provided");if(!o.text)throw new Error("No text provided");const e=b(t);let r=!1;if(o.ref)try{(await chrome.tabs.sendMessage(t,{type:"CLICK_ELEMENT",ref:o.ref,button:"left"},{frameId:e})).error||(r=!0)}catch{}if(!r&&o.coordinate&&(await l.click(t,o.coordinate[0],o.coordinate[1],"left",1,0),r=!0),!r){const n=await l.evaluateScript(t,`(() => {
14
14
  const el = document.querySelector('textarea, input[type="text"], input[type="search"], input:not([type]), [contenteditable="true"]');
15
15
  if (!el) return null;
16
16
  const r = el.getBoundingClientRect();
17
17
  return { x: r.left + r.width/2, y: r.top + r.height/2 };
18
- })()`);(s=a.result)!=null&&s.value&&(await u.click(e,a.result.value.x,a.result.value.y,"left",1,0),o=!0)}return o?(await u.type(e,t.text),await u.pressKey(e,t.submitKey||"Enter"),{success:!0}):{error:"Could not find input element"}}case"FIND_AND_TYPE":{if(!e)throw new Error("No tabId provided");if(!t.text)throw new Error("No text provided");const o=(d=(await u.evaluateScript(e,`(() => {
18
+ })()`);n.result?.value&&(await l.click(t,n.result.value.x,n.result.value.y,"left",1,0),r=!0)}return r?(await l.type(t,o.text),await l.pressKey(t,o.submitKey||"Enter"),{success:!0}):{error:"Could not find input element"}}case"FIND_AND_TYPE":{if(!t)throw new Error("No tabId provided");if(!o.text)throw new Error("No text provided");const r=(await l.evaluateScript(t,`(() => {
19
19
  const selectors = [
20
20
  'textarea:not([readonly]):not([disabled])',
21
21
  'input[type="text"]:not([readonly]):not([disabled])',
@@ -35,38 +35,38 @@ var Se=Object.defineProperty;var ge=(t,i,e)=>i in t?Se(t,i,{enumerable:!0,config
35
35
  }
36
36
  }
37
37
  return { found: false };
38
- })()`)).result)==null?void 0:d.value;return o!=null&&o.found?(await u.click(e,o.x,o.y,"left",1,0),await u.type(e,t.text),t.submit&&await u.pressKey(e,t.submitKey||"Enter"),{success:!0,coordinates:{x:o.x,y:o.y}}):{error:"No input field found on page"}}case"AUTOCOMPLETE_SELECT":{if(!e)throw new Error("No tabId provided");if(!t.text)throw new Error("No text provided");const r=C(e);let o=!1;if(t.ref)try{(await chrome.tabs.sendMessage(e,{type:"CLICK_ELEMENT",ref:t.ref,button:"left"},{frameId:r})).error||(o=!0)}catch{}if(!o&&t.coordinate&&(await u.click(e,t.coordinate[0],t.coordinate[1],"left",1,0),o=!0),!o)return{error:"ref or coordinate required"};await new Promise(h=>setTimeout(h,100)),await u.type(e,t.text);const a=t.waitMs||500;if(await new Promise(h=>setTimeout(h,a)),t.index&&t.index>0)for(let h=0;h<t.index;h++)await u.pressKey(e,"ArrowDown"),await new Promise(c=>setTimeout(c,50));return await u.pressKey(e,"Enter"),{success:!0}}case"SET_INPUT_VALUE":{if(!e)throw new Error("No tabId provided");if(t.value===void 0)throw new Error("No value provided");const r=t.selector,o=t.ref;if(!r&&!o)throw new Error("selector or ref required");const a=o?`(() => {
39
- const el = document.querySelector('[data-pi-ref="${o}"]') ||
40
- [...document.querySelectorAll('*')].find(e => e.getAttribute?.('data-ref') === '${o}');
38
+ })()`)).result?.value;return r?.found?(await l.click(t,r.x,r.y,"left",1,0),await l.type(t,o.text),o.submit&&await l.pressKey(t,o.submitKey||"Enter"),{success:!0,coordinates:{x:r.x,y:r.y}}):{error:"No input field found on page"}}case"AUTOCOMPLETE_SELECT":{if(!t)throw new Error("No tabId provided");if(!o.text)throw new Error("No text provided");const e=b(t);let r=!1;if(o.ref)try{(await chrome.tabs.sendMessage(t,{type:"CLICK_ELEMENT",ref:o.ref,button:"left"},{frameId:e})).error||(r=!0)}catch{}if(!r&&o.coordinate&&(await l.click(t,o.coordinate[0],o.coordinate[1],"left",1,0),r=!0),!r)return{error:"ref or coordinate required"};await new Promise(s=>setTimeout(s,100)),await l.type(t,o.text);const n=o.waitMs||500;if(await new Promise(s=>setTimeout(s,n)),o.index&&o.index>0)for(let s=0;s<o.index;s++)await l.pressKey(t,"ArrowDown"),await new Promise(a=>setTimeout(a,50));return await l.pressKey(t,"Enter"),{success:!0}}case"SET_INPUT_VALUE":{if(!t)throw new Error("No tabId provided");if(o.value===void 0)throw new Error("No value provided");const e=o.selector,r=o.ref;if(!e&&!r)throw new Error("selector or ref required");const n=r?`(() => {
39
+ const el = document.querySelector('[data-pi-ref="${r}"]') ||
40
+ [...document.querySelectorAll('*')].find(e => e.getAttribute?.('data-ref') === '${r}');
41
41
  if (!el) return { error: 'Element not found' };
42
42
  el.focus();
43
43
  const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';
44
44
  const target = isContentEditable ? (el.querySelector('p') || el) : el;
45
45
  if (isContentEditable) {
46
- target.textContent = ${JSON.stringify(t.value)};
46
+ target.textContent = ${JSON.stringify(o.value)};
47
47
  } else {
48
- el.value = ${JSON.stringify(t.value)};
48
+ el.value = ${JSON.stringify(o.value)};
49
49
  }
50
50
  el.dispatchEvent(new Event('input', { bubbles: true }));
51
51
  el.dispatchEvent(new Event('change', { bubbles: true }));
52
52
  return { success: true, contentEditable: isContentEditable };
53
53
  })()`:`(() => {
54
- const el = document.querySelector(${JSON.stringify(r)});
55
- if (!el) return { error: 'Element not found: ' + ${JSON.stringify(r)} };
54
+ const el = document.querySelector(${JSON.stringify(e)});
55
+ if (!el) return { error: 'Element not found: ' + ${JSON.stringify(e)} };
56
56
  el.focus();
57
57
  const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';
58
58
  const target = isContentEditable ? (el.querySelector('p') || el) : el;
59
59
  if (isContentEditable) {
60
- target.textContent = ${JSON.stringify(t.value)};
60
+ target.textContent = ${JSON.stringify(o.value)};
61
61
  } else {
62
- el.value = ${JSON.stringify(t.value)};
62
+ el.value = ${JSON.stringify(o.value)};
63
63
  }
64
64
  el.dispatchEvent(new Event('input', { bubbles: true }));
65
65
  el.dispatchEvent(new Event('change', { bubbles: true }));
66
66
  return { success: true, contentEditable: isContentEditable };
67
- })()`;return((l=(await u.evaluateScript(e,a)).result)==null?void 0:l.value)||{error:"Script failed"}}case"SMART_TYPE":{if(!e)throw new Error("No tabId provided");const{selector:r,text:o,clear:a=!0,submit:h=!1}=t;if(!r)throw new Error("selector required");if(o===void 0)throw new Error("text required");const c=`(() => {
68
- const el = document.querySelector(${JSON.stringify(r)});
69
- if (!el) return { error: 'Element not found: ' + ${JSON.stringify(r)} };
67
+ })()`;return(await l.evaluateScript(t,n)).result?.value||{error:"Script failed"}}case"SMART_TYPE":{if(!t)throw new Error("No tabId provided");const{selector:e,text:r,clear:n=!0,submit:s=!1}=o;if(!e)throw new Error("selector required");if(r===void 0)throw new Error("text required");const a=`(() => {
68
+ const el = document.querySelector(${JSON.stringify(e)});
69
+ if (!el) return { error: 'Element not found: ' + ${JSON.stringify(e)} };
70
70
 
71
71
  const isContentEditable = el.isContentEditable ||
72
72
  el.getAttribute('contenteditable') === 'true';
@@ -77,7 +77,7 @@ var Se=Object.defineProperty;var ge=(t,i,e)=>i in t?Se(t,i,{enumerable:!0,config
77
77
 
78
78
  target.focus();
79
79
 
80
- if (${a}) {
80
+ if (${n}) {
81
81
  if (useContentEditable) {
82
82
  target.textContent = '';
83
83
  } else {
@@ -86,15 +86,15 @@ var Se=Object.defineProperty;var ge=(t,i,e)=>i in t?Se(t,i,{enumerable:!0,config
86
86
  }
87
87
 
88
88
  if (useContentEditable) {
89
- target.textContent = ${JSON.stringify(o)};
89
+ target.textContent = ${JSON.stringify(r)};
90
90
  } else {
91
- target.value = ${JSON.stringify(o)};
91
+ target.value = ${JSON.stringify(r)};
92
92
  }
93
93
 
94
94
  target.dispatchEvent(new Event('input', { bubbles: true }));
95
95
  target.dispatchEvent(new Event('change', { bubbles: true }));
96
96
 
97
- if (${h}) {
97
+ if (${s}) {
98
98
  const form = el.closest('form');
99
99
  const submitBtn = document.querySelector('button[type="submit"], button[data-testid*="send"], button[aria-label*="Send"]');
100
100
  if (submitBtn) {
@@ -107,7 +107,7 @@ var Se=Object.defineProperty;var ge=(t,i,e)=>i in t?Se(t,i,{enumerable:!0,config
107
107
  }
108
108
 
109
109
  return { success: true, contentEditable: useContentEditable };
110
- })()`;return((f=(await u.evaluateScript(e,c)).result)==null?void 0:f.value)||{error:"Script failed"}}case"CLOSE_DIALOGS":{if(!e)throw new Error("No tabId provided");const r=t.maxAttempts||3;for(let o=0;o<r;o++)await u.pressKey(e,"Escape"),await new Promise(a=>setTimeout(a,100));return{success:!0}}case"PAGE_STATE":{if(!e)throw new Error("No tabId provided");return((y=(await u.evaluateScript(e,`(() => {
110
+ })()`;return(await l.evaluateScript(t,a)).result?.value||{error:"Script failed"}}case"CLOSE_DIALOGS":{if(!t)throw new Error("No tabId provided");const e=o.maxAttempts||3;for(let r=0;r<e;r++)await l.pressKey(t,"Escape"),await new Promise(n=>setTimeout(n,100));return{success:!0}}case"PAGE_STATE":{if(!t)throw new Error("No tabId provided");return(await l.evaluateScript(t,`(() => {
111
111
  const hasModal = !!(
112
112
  document.querySelector('[role="dialog"]') ||
113
113
  document.querySelector('[role="alertdialog"]') ||
@@ -140,17 +140,17 @@ var Se=Object.defineProperty;var ge=(t,i,e)=>i in t?Se(t,i,{enumerable:!0,config
140
140
  url: location.href,
141
141
  title: document.title
142
142
  };
143
- })()`)).result)==null?void 0:y.value)||{error:"Failed to get page state"}}case"EXECUTE_SCROLL":{if(!e)throw new Error("No tabId provided");const r=t.deltaX||0,o=t.deltaY||0;try{const a=await u.getViewportSize(e),h=t.x??a.width/2,c=t.y??a.height/2;await u.scroll(e,h,c,r,o)}catch{try{const a=(h,c)=>(window.scrollBy(h,c),{scrollX:window.scrollX,scrollY:window.scrollY});await chrome.scripting.executeScript({target:{tabId:e},func:a,args:[r,o]})}catch{return{error:"Cannot scroll on this page (restricted)"}}}return{success:!0}}case"EXECUTE_KEY":{if(!e)throw new Error("No tabId provided");const r=t.key;if(!r)throw new Error("No key provided");return r.includes("+")?await u.pressKeyChord(e,r):await u.pressKey(e,r),{success:!0}}case"EXECUTE_NAVIGATE":{if(!e)throw new Error("No tabId provided");if(!t.url)throw new Error("No url provided");const r=new Promise(o=>{G.set(e,o),setTimeout(()=>{G.has(e)&&(G.delete(e),o())},3e4)});return await chrome.tabs.update(e,{url:t.url}),await r,await new Promise(o=>setTimeout(o,500)),{success:!0}}case"GET_VIEWPORT_SIZE":{if(!e)throw new Error("No tabId provided");return await u.getViewportSize(e)}case"READ_PAGE":{if(!e)throw new Error("No tabId provided");const r=C(e);try{await chrome.tabs.sendMessage(e,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(a=>setTimeout(a,50));let o;try{o=await chrome.tabs.sendMessage(e,{type:"GENERATE_ACCESSIBILITY_TREE",options:t.options||{}},{frameId:r})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(e,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}if((b=t.options)!=null&&b.includeText)try{const a=await chrome.tabs.sendMessage(e,{type:"GET_PAGE_TEXT"},{frameId:r});a!=null&&a.text&&(o.text=a.text)}catch{}if((E=t.options)!=null&&E.includeScreenshot)try{const a=await u.captureScreenshot(e);return{...o,screenshot:a}}catch{return{...o,screenshotError:"Failed to capture screenshot"}}return o}case"GET_ELEMENT_COORDINATES":{if(!e)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(e,{type:"GET_ELEMENT_COORDINATES",ref:t.ref},{frameId:C(e)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"FORM_INPUT":{if(!e)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(e,{type:"FORM_INPUT",ref:t.ref,value:t.value},{frameId:C(e)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"EVAL_IN_PAGE":{if(!e)throw new Error("No tabId provided");if(!t.code)throw new Error("No code provided");try{return await chrome.tabs.sendMessage(e,{type:"EVAL_IN_PAGE",code:t.code},{frameId:C(e)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SCROLL_TO_ELEMENT":{if(!e)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(e,{type:"SCROLL_TO_ELEMENT",ref:t.ref},{frameId:C(e)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SCROLL_TO_POSITION":{if(!e)throw new Error("No tabId provided");const r=t.position;if(r===void 0)throw new Error('position required ("top", "bottom", or number)');const o=t.selector,a=(h,c)=>{const w=()=>[...document.querySelectorAll("*")].filter(_=>_.scrollHeight>_.clientHeight&&_.clientHeight>200).sort((_,R)=>R.scrollHeight-_.scrollHeight)[0]||document.documentElement,m=c&&document.querySelector(c)||w();return m?(h==="bottom"?m.scrollTop=m.scrollHeight:h==="top"?m.scrollTop=0:typeof h=="number"&&(m.scrollTop=h),{scrollTop:m.scrollTop,scrollHeight:m.scrollHeight,clientHeight:m.clientHeight,atBottom:m.scrollTop+m.clientHeight>=m.scrollHeight-10,atTop:m.scrollTop<10}):{error:"No scrollable container found"}};try{const h=`(${a.toString()})(${JSON.stringify(r)}, ${JSON.stringify(o)})`;return((T=(await u.evaluateScript(e,h)).result)==null?void 0:T.value)||{error:"Script failed"}}catch{try{return((S=(await chrome.scripting.executeScript({target:{tabId:e},func:a,args:[r,o]}))[0])==null?void 0:S.result)||{error:"Script failed"}}catch{return{error:"Cannot scroll on this page (restricted)"}}}}case"GET_SCROLL_INFO":{if(!e)throw new Error("No tabId provided");const r=t.selector,o=a=>{const h=()=>[...document.querySelectorAll("*")].filter(I=>I.scrollHeight>I.clientHeight&&I.clientHeight>200).sort((I,_)=>_.scrollHeight-I.scrollHeight)[0]||document.documentElement,c=a&&document.querySelector(a)||h();if(!c)return{error:"No scrollable container found"};const w=c.scrollHeight-c.clientHeight;return{scrollTop:c.scrollTop,scrollHeight:c.scrollHeight,clientHeight:c.clientHeight,atBottom:c.scrollTop+c.clientHeight>=c.scrollHeight-10,atTop:c.scrollTop<10,scrollPercentage:w>0?Math.round(c.scrollTop/w*100):100}};try{const a=`(${o.toString()})(${JSON.stringify(r)})`;return((p=(await u.evaluateScript(e,a)).result)==null?void 0:p.value)||{error:"Script failed"}}catch{try{return((v=(await chrome.scripting.executeScript({target:{tabId:e},func:o,args:[r]}))[0])==null?void 0:v.result)||{error:"Script failed"}}catch{return{error:"Cannot get scroll info on this page (restricted)"}}}}case"GET_PAGE_TEXT":{if(!e)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(e,{type:"GET_PAGE_TEXT"},{frameId:C(e)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_ROLE":{if(!e)throw new Error("No tabId provided");if(!t.role)throw new Error("role required");const r=C(e);try{const o=await chrome.tabs.sendMessage(e,{type:"LOCATE_ROLE",role:t.role,name:t.name,all:t.all},{frameId:r});return o.error?o:t.action&&o.ref?await ne(e,o.ref,t.action,t.value,u,r):o}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_TEXT":{if(!e)throw new Error("No tabId provided");if(!t.text)throw new Error("text required");const r=C(e);try{const o=await chrome.tabs.sendMessage(e,{type:"LOCATE_TEXT",text:t.text,exact:t.exact},{frameId:r});return o.error?o:t.action&&o.ref?await ne(e,o.ref,t.action,t.value,u,r):o}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_LABEL":{if(!e)throw new Error("No tabId provided");if(!t.label)throw new Error("label required");const r=C(e);try{const o=await chrome.tabs.sendMessage(e,{type:"LOCATE_LABEL",label:t.label},{frameId:r});return o.error?o:t.action&&o.ref?await ne(e,o.ref,t.action,t.value,u,r):o}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"GET_ELEMENT_STYLES":{if(!e)throw new Error("No tabId provided");if(!t.selector)throw new Error("selector required");const r=C(e);try{return await chrome.tabs.sendMessage(e,{type:"GET_ELEMENT_STYLES",selector:t.selector},{frameId:r})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SELECT_OPTION":{if(!e)throw new Error("No tabId provided");if(!t.selector)throw new Error("selector required");if(!t.values)throw new Error("values required");const r=C(e);try{return await chrome.tabs.sendMessage(e,{type:"SELECT_OPTION",selector:t.selector,values:t.values,by:t.by||"value"},{frameId:r})}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(!e)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(e,{type:t.type})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"STOP_AGENT":{const r=t.fromTabId;let o;return r==="CURRENT_TAB"&&((g=i.tab)!=null&&g.id)?o=i.tab.id:typeof r=="number"&&(o=r),o&&chrome.runtime.sendMessage({type:"STOP_AGENT",targetTabId:o}),{success:!0}}case"DISMISS_STATIC_INDICATOR":return{success:!0};case"STATIC_INDICATOR_HEARTBEAT":return{success:!0};case"CLICK_REF":{if(!e)throw new Error("No tabId provided");try{const r=await chrome.tabs.sendMessage(e,{type:"CLICK_ELEMENT",ref:t.ref,button:t.button||"left"},{frameId:C(e)});return r.error?{error:r.error}:{success:!0}}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"HOVER_REF":{if(!e)throw new Error("No tabId provided");try{const r=await chrome.tabs.sendMessage(e,{type:"GET_ELEMENT_COORDINATES",ref:t.ref},{frameId:C(e)});return r.error?{error:r.error}:(await u.hover(e,r.x,r.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(!t.url)throw new Error("No url provided");const r=t.timeout||3e4,o=t.expect||200,a=Date.now(),h=500;let c=null;for(;Date.now()-a<r;){try{const w=await fetch(t.url,{method:"GET"});if(await w.text(),w.status===o)return{success:!0,status:w.status,time:Date.now()-a};c=`Got status ${w.status}`}catch(w){c=w instanceof Error?w.message:String(w)}await new Promise(w=>setTimeout(w,h))}return{error:`Timeout waiting for ${t.url} to return ${o}`,lastError:c,time:Date.now()-a}}case"SMOKE_TEST":{const r=t.urls||[],o=t.savePath!==void 0,a=t.failFast||!1;if(r.length===0)return{error:"No URLs provided for smoke test"};const h=[];let c=0,w=0;for(const m of r){const I=Date.now(),_=[];let R,Z,P;try{Z=new URL(m).hostname.replace(/[^a-zA-Z0-9.-]/g,"_");const K=await chrome.tabs.create({url:m,active:!1});if(!K.id)throw new Error("Failed to create tab");P=K.id;try{await u.enableConsoleTracking(P)}catch{}await new Promise(D=>{const Q=W=>{W.tabId===P&&W.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(Q),chrome.webNavigation.onErrorOccurred.removeListener(ee),D())},ee=W=>{W.tabId===P&&W.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(Q),chrome.webNavigation.onErrorOccurred.removeListener(ee),_.push(`Navigation error: ${W.error}`),D())};chrome.webNavigation.onCompleted.addListener(Q),chrome.webNavigation.onErrorOccurred.addListener(ee),setTimeout(()=>{chrome.webNavigation.onCompleted.removeListener(Q),chrome.webNavigation.onErrorOccurred.removeListener(ee),_.push("Navigation timeout (30s)"),D()},3e4)}),await new Promise(D=>setTimeout(D,2e3));const Te=u.getConsoleMessages(P,{onlyErrors:!0,limit:50});for(const D of Te)_.push(`[${D.type}] ${D.text}`);if(o)try{R=(await u.captureScreenshot(P)).base64}catch{}}catch(K){_.push(K instanceof Error?K.message:String(K))}finally{if(P)try{await chrome.tabs.remove(P)}catch{}}const H=Date.now()-I,ie=_.length===0?"pass":"fail";if(ie==="pass"?c++:w++,h.push({url:m,status:ie,time:H,errors:_,...R&&{screenshotBase64:R,hostname:Z}}),a&&ie==="fail")break}return{results:h,summary:{pass:c,fail:w,total:h.length},savePath:t.savePath}}case"WAIT_FOR_ELEMENT":{if(!e)throw new Error("No tabId provided");if(!t.selector)throw new Error("No selector provided");const r=C(e);try{await chrome.tabs.sendMessage(e,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(o=>setTimeout(o,50));try{return await chrome.tabs.sendMessage(e,{type:"WAIT_FOR_ELEMENT",selector:t.selector,state:t.state||"visible",timeout:t.timeout||2e4},{frameId:r})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(e,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_URL":{if(!e)throw new Error("No tabId provided");if(!t.pattern)throw new Error("No URL pattern provided");try{await chrome.tabs.sendMessage(e,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(r=>setTimeout(r,50));try{return await chrome.tabs.sendMessage(e,{type:"WAIT_FOR_URL",pattern:t.pattern,timeout:t.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(e,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_NETWORK_IDLE":{if(!e)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(e,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(r=>setTimeout(r,50));try{return await chrome.tabs.sendMessage(e,{type:"WAIT_FOR_NETWORK_IDLE",timeout:t.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(e,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_DOM_STABLE":{if(!e)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(e,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(r=>setTimeout(r,50));try{return await chrome.tabs.sendMessage(e,{type:"WAIT_FOR_DOM_STABLE",stable:t.stable||100,timeout:t.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(e,{type:"SHOW_AFTER_TOOL_USE"},{frameId:0})}catch{}}}case"DIALOG_ACCEPT":{if(!e)throw new Error("No tabId provided");return await u.handleDialog(e,!0,t.text)}case"DIALOG_DISMISS":{if(!e)throw new Error("No tabId provided");return await u.handleDialog(e,!1)}case"DIALOG_INFO":{if(!e)throw new Error("No tabId provided");const r=u.getDialogInfo(e);return r?{hasDialog:!0,type:r.type,message:r.message,defaultPrompt:r.defaultPrompt}:{hasDialog:!1}}case"EMULATE_NETWORK":{if(!e)throw new Error("No tabId provided");if(!t.preset)throw new Error("No preset provided");const r=await u.emulateNetwork(e,t.preset);if(!r.success)throw new Error(r.error);return{success:!0,preset:t.preset}}case"EMULATE_CPU":{if(!e)throw new Error("No tabId provided");if(t.rate===void 0)throw new Error("No rate provided");const r=await u.emulateCPU(e,t.rate);if(!r.success)throw new Error(r.error);return{success:!0,rate:t.rate}}case"EMULATE_GEO":{if(!e)throw new Error("No tabId provided");if(t.clear){const o=await u.clearGeolocation(e);if(!o.success)throw new Error(o.error);return{success:!0,cleared:!0}}if(t.latitude===void 0||t.longitude===void 0)throw new Error("Latitude and longitude required");const r=await u.emulateGeolocation(e,t.latitude,t.longitude,t.accuracy);if(!r.success)throw new Error(r.error);return{success:!0,latitude:t.latitude,longitude:t.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(!e)throw new Error("No tabId provided");const r=t.device;if(r.toLowerCase()==="reset"){const c=await u.clearDeviceEmulation(e);if(!c.success)throw new Error(c.error);return{success:!0,message:"Device emulation reset"}}const o={"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"}};let a=o[r];if(!a){const c=r.toLowerCase();let w=null;for(const[m,I]of Object.entries(o)){const _=m.toLowerCase(),R=_.replace(/\s+/g,"");(_.includes(c)||c.includes(R))&&(!w||m.length>w.name.length)&&(w={name:m,preset:I})}w&&(a=w.preset)}if(!a)throw new Error(`Unknown device: ${r}. Use --list to see available devices.`);const h=await u.emulateDevice(e,a);if(!h.success)throw new Error(h.error);return{success:!0,device:r}}case"EMULATE_VIEWPORT":{if(!e)throw new Error("No tabId provided");if(!t.width&&!t.height)throw new Error("--width or --height required");const r=await u.emulateViewport(e,{width:t.width,height:t.height,deviceScaleFactor:t.deviceScaleFactor,mobile:t.mobile});if(!r.success)throw new Error(r.error);return{success:!0,width:t.width,height:t.height}}case"EMULATE_TOUCH":{if(!e)throw new Error("No tabId provided");const r=await u.emulateTouch(e,t.enabled);if(!r.success)throw new Error(r.error);return{success:!0,enabled:t.enabled}}case"FORM_FILL":{if(!e)throw new Error("No tabId provided");if(!t.data)throw new Error("No data provided");return await chrome.tabs.sendMessage(e,{type:"FORM_FILL",data:t.data},{frameId:C(e)})}case"PERF_START":{if(!e)throw new Error("No tabId provided");const r=await u.startPerformanceTrace(e,t.categories);if(!r.success)throw new Error(r.error);return{success:!0,message:"Performance tracing started"}}case"PERF_STOP":{if(!e)throw new Error("No tabId provided");const r=await u.stopPerformanceTrace(e);if(!r.success)throw new Error(r.error);return{success:!0,metrics:r.metrics}}case"PERF_METRICS":{if(!e)throw new Error("No tabId provided");const r=await u.getPerformanceMetrics(e);if(!r.success)throw new Error(r.error);return{success:!0,metrics:r.metrics}}case"UPLOAD_FILE":{if(!e)throw new Error("No tabId provided");if(!t.ref)throw new Error("No ref provided");if(!t.files||!t.files.length)throw new Error("No files provided");const r=await chrome.tabs.sendMessage(e,{type:"GET_FILE_INPUT_SELECTOR",ref:t.ref},{frameId:C(e)});if(r.error)throw new Error(r.error);const o=await u.setFileInputBySelector(e,r.selector,t.files);if(!o.success)throw new Error(o.error);return{success:!0,filesSet:t.files.length}}case"WAIT_FOR_LOAD":{if(!e)throw new Error("No tabId provided");const r=await u.waitForLoad(e,t.timeout||3e4);if(!r.success)throw new Error(r.error);return{success:!0,readyState:r.readyState}}case"GET_FRAMES":{if(!e)throw new Error("No tabId provided");const r=await u.getFrames(e);if(!r.success)throw new Error(r.error);return{success:!0,frames:r.frames}}case"FRAME_SWITCH":{if(!e)throw new Error("No tabId provided");const{selector:r,name:o,index:a}=t;if(!r&&!o&&a===void 0)throw new Error("--selector, --name, or --index required");const h=await chrome.webNavigation.getAllFrames({tabId:e});if(!h||h.length===0)throw new Error("No frames found in tab");const c=h.filter(m=>m.frameId!==0);if(c.length===0)throw new Error("No iframes found on this page");let w=null;if(a!==void 0){if(a<0||a>=c.length)throw new Error(`Frame index ${a} out of range. Found ${c.length} frame(s).`);w=c[a]}else if(o){for(const m of c)try{const I=await chrome.tabs.sendMessage(e,{type:"GET_FRAME_NAME"},{frameId:m.frameId});if((I==null?void 0:I.name)===o){w=m;break}}catch{}if(!w)throw new Error(`Frame with name "${o}" not found`)}else if(r)try{const m=await chrome.tabs.sendMessage(e,{type:"GET_FRAME_BY_SELECTOR",selector:r},{frameId:0});if(m!=null&&m.error)throw new Error(m.error);m!=null&&m.url&&(w=c.find(I=>I.url===m.url)||null),!w&&c.length===1&&(w=c[0])}catch{throw new Error(`Could not find frame with selector "${r}"`)}if(!w)throw new Error("Frame not found");return J.set(e,w.frameId),{success:!0,frameId:w.frameId,url:w.url}}case"FRAME_MAIN":{if(!e)throw new Error("No tabId provided");return J.delete(e),{success:!0,message:"Returned to main frame"}}case"EVALUATE_IN_FRAME":{if(!e)throw new Error("No tabId provided");if(!t.frameId)throw new Error("No frameId provided");if(!t.code)throw new Error("No code provided");const r=await u.evaluateInFrame(e,t.frameId,t.code);if(!r.success)throw new Error(r.error);return{value:r.result}}case"EXECUTE_JAVASCRIPT":{if(!e)throw new Error("No tabId provided");if(!t.code)throw new Error("No code provided");try{await u.evaluateScript(e,"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}");const a=`(async () => { 'use strict'; ${t.code.replace(/`/g,"\\`").replace(/\$/g,"\\$")} })()`,h=await u.evaluateScript(e,a);if(h.exceptionDetails)return{error:((k=h.exceptionDetails.exception)==null?void 0:k.description)||h.exceptionDetails.text||"Script execution failed"};const c=(x=h.result)==null?void 0:x.value,w=c===void 0?"undefined":JSON.stringify(c,null,2);return{output:(w==null?void 0:w.substring(0,5e4))||"undefined"}}catch(r){const o=r instanceof Error?r.message:"Script execution failed";return o.includes("Cannot access")||o.includes("Cannot attach")?{error:"Cannot execute JavaScript on this page (restricted URL)"}:{error:o}}}case"READ_CONSOLE_MESSAGES":{if(!e)throw new Error("No tabId provided");try{await u.enableConsoleTracking(e)}catch{}const r=u.getConsoleMessages(e,{onlyErrors:t.onlyErrors,pattern:t.pattern,limit:t.limit||100});return t.clear&&u.clearConsoleMessages(e),{messages:r}}case"CLEAR_CONSOLE_MESSAGES":{if(!e)throw new Error("No tabId provided");return u.clearConsoleMessages(e),{success:!0}}case"READ_NETWORK_REQUESTS":{if(!e)throw new Error("No tabId provided");try{await u.enableNetworkTracking(e)}catch{}if(t.full){let o=u.getNetworkEntries(e,{urlPattern:t.urlPattern});t.method&&(o=o.filter(h=>h.method===t.method)),t.status&&(o=o.filter(h=>h.status===t.status)),t.contentType&&(o=o.filter(h=>h.type===t.contentType)),t.clear&&u.clearNetworkRequests(e);const a=t.limit||100;return{entries:o.slice(0,a),format:t.format,verbose:t.verbose}}let r=u.getNetworkRequests(e,{urlPattern:t.urlPattern,limit:t.limit||100});return t.method&&(r=r.filter(o=>o.method===t.method)),t.status&&(r=r.filter(o=>o.status===t.status)),t.contentType&&(r=r.filter(o=>o.type===t.contentType)),t.clear&&u.clearNetworkRequests(e),{requests:r,format:t.format,verbose:t.verbose}}case"CLEAR_NETWORK_REQUESTS":{if(!e)throw new Error("No tabId provided");return u.clearNetworkRequests(e),{success:!0}}case"GET_NETWORK_ENTRIES":{if(!e)throw new Error("No tabId provided");try{await u.enableNetworkTracking(e)}catch{}let r=u.getNetworkEntries(e,{urlPattern:t.urlPattern,includeStatic:!t.excludeStatic});return t.origin&&(r=r.filter(o=>o.origin===t.origin)),t.method&&(r=r.filter(o=>o.method===t.method)),t.status&&(r=r.filter(o=>o.status===t.status)),t.type&&(r=r.filter(o=>o.type===t.type)),t.since&&(r=r.filter(o=>o.ts>=t.since)),t.hasBody!==void 0&&(r=r.filter(o=>t.hasBody?o.responseBodySize&&o.responseBodySize>0:!o.responseBodySize)),t.last&&(r=r.slice(-t.last)),t.clear&&u.clearNetworkRequests(e),{entries:r}}case"GET_NETWORK_ENTRY":{if(!e)throw new Error("No tabId provided");if(!t.requestId)throw new Error("No requestId provided");let r=u.getNetworkEntry(e,t.requestId);return r||(r=u.getNetworkEntries(e,{}).find(a=>a.id===t.requestId)||null),r||(r=u.getNetworkEntries(e,{}).find(a=>a._requestId===t.requestId)||null),r?{entry:r}:{error:`Entry not found: ${t.requestId}`}}case"GET_RESPONSE_BODY":{if(!e)throw new Error("No tabId provided");if(!t.requestId)throw new Error("No requestId provided");let r=t.requestId;if(t.requestId.startsWith("r_")){const h=u.getNetworkEntries(e,{}).find(c=>c.id===t.requestId);h&&(r=h._requestId)}return await u.getResponseBody(e,r)}case"GET_NETWORK_ORIGINS":{if(!e)throw new Error("No tabId provided");const r=u.getNetworkEntries(e,{}),o={};for(const a of r)o[a.origin]||(o[a.origin]={count:0,lastSeen:0,size:0}),o[a.origin].count++,o[a.origin].lastSeen=Math.max(o[a.origin].lastSeen,a.ts),o[a.origin].size+=a.responseBodySize||0;return{origins:o}}case"GET_NETWORK_STATS":{if(!e)throw new Error("No tabId provided");const r=u.getNetworkEntries(e,{}),o={},a={},h={};let c=0,w=1/0,m=0;for(const I of r){o[I.origin]||(o[I.origin]=0),o[I.origin]++;const _=I.method||"GET";if(a[_]=(a[_]||0)+1,I.status){const R=`${Math.floor(I.status/100)}xx`;h[R]=(h[R]||0)+1}c+=I.responseBodySize||0,I.ts<w&&(w=I.ts),I.ts>m&&(m=I.ts)}return{stats:{totalRequests:r.length,totalSize:c,uniqueOrigins:Object.keys(o).length,startTime:w===1/0?null:w,duration:m&&w!==1/0?m-w:0,byMethod:a,byStatus:h}}}case"RESIZE_WINDOW":{if(!e)throw new Error("No tabId provided");if(!t.width||!t.height)throw new Error("width and height required");const r=await chrome.tabs.get(e);if(!r.windowId)throw new Error("Tab has no window");return await chrome.windows.update(r.windowId,{width:Math.floor(t.width),height:Math.floor(t.height)}),{success:!0,width:t.width,height:t.height}}case"TABS_CREATE":{const r=e?await chrome.tabs.get(e):null,o=await chrome.tabs.create({url:t.url||"about:blank",active:!1});if(!o.id)throw new Error("Failed to create tab");return r!=null&&r.groupId&&r.groupId!==chrome.tabGroups.TAB_GROUP_ID_NONE&&await chrome.tabs.group({tabIds:o.id,groupId:r.groupId}),{success:!0,tabId:o.id,url:o.url||t.url||"about:blank"}}case"UPLOAD_IMAGE":{if(!e)throw new Error("No tabId provided");if(!t.screenshotId)throw new Error("screenshotId required");if(!t.ref&&!t.coordinate)throw new Error("ref or coordinate required");const r=Me(t.screenshotId);if(!r)throw new Error(`Screenshot not found: ${t.screenshotId}`);try{return await chrome.tabs.sendMessage(e,{type:"UPLOAD_IMAGE",base64:r.base64,ref:t.ref,coordinate:t.coordinate,filename:t.filename||"screenshot.png"},{frameId:C(e)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"GET_TABS":return{tabs:(await chrome.tabs.query({})).map(o=>({id:o.id,title:o.title,url:o.url}))};case"LIST_TABS":{const r={};return t.windowId&&(r.windowId=t.windowId),{tabs:(await chrome.tabs.query(r)).map(a=>({id:a.id,title:a.title,url:a.url,active:a.active,windowId:a.windowId}))}}case"NEW_TAB":{const r=t.urls||(t.url?[t.url]:["about:blank"]),o=[];for(let a=0;a<r.length;a++){const h={url:r[a],active:a===0};t.windowId&&(h.windowId=t.windowId);const c=await chrome.tabs.create(h);c.id&&o.push({tabId:c.id,url:r[a]})}return o.length===1?{success:!0,tabId:o[0].tabId,url:o[0].url}:{success:!0,tabs:o}}case"SWITCH_TAB":{const r=t.tabId;if(!r)throw new Error("No tabId provided");const o=await chrome.tabs.update(r,{active:!0});return o.windowId&&await chrome.windows.update(o.windowId,{focused:!0}),{success:!0,tabId:r,url:o.url,title:o.title}}case"CLOSE_TAB":{const r=t.tabIds||(t.tabId?[t.tabId]:[]);if(r.length===0)throw new Error("No tabId(s) provided");return await chrome.tabs.remove(r),r.length===1?{success:!0,tabId:r[0]}:{success:!0,closed:r}}case"TABS_REGISTER":{if(!e)throw new Error("No tabId provided");if(!t.name)throw new Error("No name provided");return U.set(t.name,e),{success:!0,name:t.name,tabId:e}}case"TABS_GET_BY_NAME":{if(!t.name)throw new Error("No name provided");const r=U.get(t.name);if(!r)return{error:`No tab registered with name "${t.name}"`};try{const o=await chrome.tabs.get(r);return{tabId:r,url:o.url,title:o.title}}catch{return U.delete(t.name),{error:`Tab "${t.name}" no longer exists`}}}case"TABS_LIST_NAMED":{const r=[];for(const[o,a]of U)try{const h=await chrome.tabs.get(a);r.push({name:o,tabId:a,url:h.url,title:h.title})}catch{U.delete(o)}return{tabs:r}}case"TABS_UNREGISTER":{if(!t.name)throw new Error("No name provided");return U.delete(t.name)?{success:!0}:{success:!1,error:`No tab registered with name "${t.name}"`}}case"GET_AUTH":{const{sendToNativeHost:r}=await de(async()=>{const{sendToNativeHost:o}=await Promise.resolve().then(()=>we);return{sendToNativeHost:o}},void 0);try{return await r({type:"GET_AUTH"})}catch{return{auth:null,hint:"Native host not connected. Make sure surf native host is installed."}}}case"NATIVE_API_REQUEST":{const{sendToNativeHost:r}=await de(async()=>{const{sendToNativeHost:o}=await Promise.resolve().then(()=>we);return{sendToNativeHost:o}},void 0);try{return await r({type:"API_REQUEST",streamId:t.streamId,url:t.url,method:t.method,headers:t.headers,body:t.body}),{sent:!0}}catch(o){return{error:o instanceof Error?o.message:"Unknown error"}}}case"STREAM_CONSOLE":{if(!e)throw new Error("No tabId provided");const r=t.streamId;try{return await u.enableConsoleTracking(e),$.set(r,e),u.subscribeToConsole(e,r,o=>{z({type:"STREAM_EVENT",streamId:r,event:{type:"console_event",level:o.type==="exception"?"error":o.type,text:o.text,timestamp:o.timestamp,url:o.url,line:o.line}})}),{success:!0,streaming:!0}}catch(o){return z({type:"STREAM_ERROR",streamId:r,error:o instanceof Error?o.message:"Failed to start console stream"}),{error:o instanceof Error?o.message:"Failed to start console stream"}}}case"STREAM_NETWORK":{if(!e)throw new Error("No tabId provided");const r=t.streamId;try{return await u.enableNetworkTracking(e),$.set(r,e),u.subscribeToNetwork(e,r,o=>{z({type:"STREAM_EVENT",streamId:r,event:{type:"network_event",method:o.method,url:o.url,status:o.status,duration:o.duration,timestamp:o.timestamp}})}),{success:!0,streaming:!0}}catch(o){return z({type:"STREAM_ERROR",streamId:r,error:o instanceof Error?o.message:"Failed to start network stream"}),{error:o instanceof Error?o.message:"Failed to start network stream"}}}case"STREAM_STOP":{const r=t.streamId,o=$.get(r);return o!==void 0&&(u.unsubscribeFromConsole(o,r),u.unsubscribeFromNetwork(o,r),$.delete(r)),{success:!0}}case"SEARCH_PAGE":{if(!e)throw new Error("No tabId provided");if(!t.term)throw new Error("Search term required");try{return await chrome.tabs.sendMessage(e,{type:"SEARCH_PAGE",term:t.term,caseSensitive:t.caseSensitive||!1,limit:t.limit||10},{frameId:C(e)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"TAB_GROUP_CREATE":{const r=[...t.tabIds||[]],o=t.name||"Surf",h=["grey","blue","red","yellow","green","pink","purple","cyan","orange"].includes(t.color)?t.color:"blue";if(r.length===0&&e&&r.push(e),r.length===0)throw new Error("No tabs specified");const c=await chrome.tabGroups.query({title:o});let w;return c.length>0?(w=c[0].id,await chrome.tabs.group({tabIds:r,groupId:w})):(w=await chrome.tabs.group({tabIds:r}),await chrome.tabGroups.update(w,{title:o,color:h,collapsed:!1})),{success:!0,groupId:w,name:o,tabIds:r}}case"TAB_GROUP_REMOVE":{const r=[...t.tabIds||[]];if(r.length===0&&e&&r.push(e),r.length===0)throw new Error("No tabs specified");return await chrome.tabs.ungroup(r),{success:!0,ungrouped:r}}case"TAB_GROUPS_LIST":{const r=await chrome.tabGroups.query({}),o=[];for(const a of r){const h=await chrome.tabs.query({groupId:a.id});o.push({id:a.id,name:a.title||"(unnamed)",color:a.color,collapsed:a.collapsed,tabs:h.map(c=>({id:c.id,title:c.title,url:c.url}))})}return{groups:o}}case"CLICK_SELECTOR":{if(!e)throw new Error("No tabId provided");const r=t.selector,o=t.index||0,a=`(() => {
144
- const elements = document.querySelectorAll(${JSON.stringify(r)});
143
+ })()`)).result?.value||{error:"Failed to get page state"}}case"EXECUTE_SCROLL":{if(!t)throw new Error("No tabId provided");const e=o.deltaX||0,r=o.deltaY||0;try{const n=await l.getViewportSize(t),s=o.x??n.width/2,a=o.y??n.height/2;await l.scroll(t,s,a,e,r)}catch{try{const n=(s,a)=>(window.scrollBy(s,a),{scrollX:window.scrollX,scrollY:window.scrollY});await chrome.scripting.executeScript({target:{tabId:t},func:n,args:[e,r]})}catch{return{error:"Cannot scroll on this page (restricted)"}}}return{success:!0}}case"EXECUTE_KEY":{if(!t)throw new Error("No tabId provided");const e=o.key;if(!e)throw new Error("No key provided");return e.includes("+")?await l.pressKeyChord(t,e):await l.pressKey(t,e),{success:!0}}case"EXECUTE_NAVIGATE":{if(!t)throw new Error("No tabId provided");if(!o.url)throw new Error("No url provided");const e=new Promise(r=>{k.set(t,r),setTimeout(()=>{k.has(t)&&(k.delete(t),r())},3e4)});return await chrome.tabs.update(t,{url:o.url}),await e,await new Promise(r=>setTimeout(r,500)),{success:!0}}case"GET_VIEWPORT_SIZE":{if(!t)throw new Error("No tabId provided");return await l.getViewportSize(t)}case"READ_PAGE":{if(!t)throw new Error("No tabId provided");const e=b(t);try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(n=>setTimeout(n,50));let r;try{r=await chrome.tabs.sendMessage(t,{type:"GENERATE_ACCESSIBILITY_TREE",options:o.options||{}},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}if(o.options?.includeText)try{const n=await chrome.tabs.sendMessage(t,{type:"GET_PAGE_TEXT"},{frameId:e});n?.text&&(r.text=n.text)}catch{}if(o.options?.includeScreenshot)try{const n=await l.captureScreenshot(t);return{...r,screenshot:n}}catch{return{...r,screenshotError:"Failed to capture screenshot"}}return r}case"GET_ELEMENT_COORDINATES":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_COORDINATES",ref:o.ref},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"FORM_INPUT":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"FORM_INPUT",ref:o.ref,value:o.value},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"EVAL_IN_PAGE":{if(!t)throw new Error("No tabId provided");if(!o.code)throw new Error("No code provided");try{return await chrome.tabs.sendMessage(t,{type:"EVAL_IN_PAGE",code:o.code},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SCROLL_TO_ELEMENT":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"SCROLL_TO_ELEMENT",ref:o.ref},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SCROLL_TO_POSITION":{if(!t)throw new Error("No tabId provided");const e=o.position;if(e===void 0)throw new Error('position required ("top", "bottom", or number)');const r=o.selector,n=(s,a)=>{const c=()=>[...document.querySelectorAll("*")].filter(h=>h.scrollHeight>h.clientHeight&&h.clientHeight>200).sort((h,f)=>f.scrollHeight-h.scrollHeight)[0]||document.documentElement,u=a&&document.querySelector(a)||c();return u?(s==="bottom"?u.scrollTop=u.scrollHeight:s==="top"?u.scrollTop=0:typeof s=="number"&&(u.scrollTop=s),{scrollTop:u.scrollTop,scrollHeight:u.scrollHeight,clientHeight:u.clientHeight,atBottom:u.scrollTop+u.clientHeight>=u.scrollHeight-10,atTop:u.scrollTop<10}):{error:"No scrollable container found"}};try{const s=`(${n.toString()})(${JSON.stringify(e)}, ${JSON.stringify(r)})`;return(await l.evaluateScript(t,s)).result?.value||{error:"Script failed"}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:t},func:n,args:[e,r]}))[0]?.result||{error:"Script failed"}}catch{return{error:"Cannot scroll on this page (restricted)"}}}}case"GET_SCROLL_INFO":{if(!t)throw new Error("No tabId provided");const e=o.selector,r=n=>{const s=()=>[...document.querySelectorAll("*")].filter(d=>d.scrollHeight>d.clientHeight&&d.clientHeight>200).sort((d,h)=>h.scrollHeight-d.scrollHeight)[0]||document.documentElement,a=n&&document.querySelector(n)||s();if(!a)return{error:"No scrollable container found"};const c=a.scrollHeight-a.clientHeight;return{scrollTop:a.scrollTop,scrollHeight:a.scrollHeight,clientHeight:a.clientHeight,atBottom:a.scrollTop+a.clientHeight>=a.scrollHeight-10,atTop:a.scrollTop<10,scrollPercentage:c>0?Math.round(a.scrollTop/c*100):100}};try{const n=`(${r.toString()})(${JSON.stringify(e)})`;return(await l.evaluateScript(t,n)).result?.value||{error:"Script failed"}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:t},func:r,args:[e]}))[0]?.result||{error:"Script failed"}}catch{return{error:"Cannot get scroll info on this page (restricted)"}}}}case"GET_PAGE_TEXT":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"GET_PAGE_TEXT"},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_ROLE":{if(!t)throw new Error("No tabId provided");if(!o.role)throw new Error("role required");const e=b(t);try{const r=await chrome.tabs.sendMessage(t,{type:"LOCATE_ROLE",role:o.role,name:o.name,all:o.all},{frameId:e});return r.error?r:o.action&&r.ref?await G(t,r.ref,o.action,o.value,l,e):r}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_TEXT":{if(!t)throw new Error("No tabId provided");if(!o.text)throw new Error("text required");const e=b(t);try{const r=await chrome.tabs.sendMessage(t,{type:"LOCATE_TEXT",text:o.text,exact:o.exact},{frameId:e});return r.error?r:o.action&&r.ref?await G(t,r.ref,o.action,o.value,l,e):r}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_LABEL":{if(!t)throw new Error("No tabId provided");if(!o.label)throw new Error("label required");const e=b(t);try{const r=await chrome.tabs.sendMessage(t,{type:"LOCATE_LABEL",label:o.label},{frameId:e});return r.error?r:o.action&&r.ref?await G(t,r.ref,o.action,o.value,l,e):r}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"GET_ELEMENT_STYLES":{if(!t)throw new Error("No tabId provided");if(!o.selector)throw new Error("selector required");const e=b(t);try{return await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_STYLES",selector:o.selector},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SELECT_OPTION":{if(!t)throw new Error("No tabId provided");if(!o.selector)throw new Error("selector required");if(!o.values)throw new Error("values required");const e=b(t);try{return await chrome.tabs.sendMessage(t,{type:"SELECT_OPTION",selector:o.selector,values:o.values,by:o.by||"value"},{frameId:e})}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(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:o.type})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"STOP_AGENT":{const e=o.fromTabId;let r;return e==="CURRENT_TAB"&&i.tab?.id?r=i.tab.id:typeof e=="number"&&(r=e),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(!t)throw new Error("No tabId provided");try{const e=await chrome.tabs.sendMessage(t,{type:"CLICK_ELEMENT",ref:o.ref,button:o.button||"left"},{frameId:b(t)});return e.error?{error:e.error}:{success:!0}}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"HOVER_REF":{if(!t)throw new Error("No tabId provided");try{const e=await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_COORDINATES",ref:o.ref},{frameId:b(t)});return e.error?{error:e.error}:(await l.hover(t,e.x,e.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(!o.url)throw new Error("No url provided");const e=o.timeout||3e4,r=o.expect||200,n=Date.now(),s=500;let a=null;for(;Date.now()-n<e;){try{const c=await fetch(o.url,{method:"GET"});if(await c.text(),c.status===r)return{success:!0,status:c.status,time:Date.now()-n};a=`Got status ${c.status}`}catch(c){a=c instanceof Error?c.message:String(c)}await new Promise(c=>setTimeout(c,s))}return{error:`Timeout waiting for ${o.url} to return ${r}`,lastError:a,time:Date.now()-n}}case"SMOKE_TEST":{const e=o.urls||[],r=o.savePath!==void 0,n=o.failFast||!1;if(e.length===0)return{error:"No URLs provided for smoke test"};const s=[];let a=0,c=0;for(const u of e){const d=Date.now(),h=[];let f,w,p;try{w=new URL(u).hostname.replace(/[^a-zA-Z0-9.-]/g,"_");const S=await chrome.tabs.create({url:u,active:!1});if(!S.id)throw new Error("Failed to create tab");p=S.id;try{await l.enableConsoleTracking(p)}catch{}await new Promise(m=>{const y=T=>{T.tabId===p&&T.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(y),chrome.webNavigation.onErrorOccurred.removeListener(g),m())},g=T=>{T.tabId===p&&T.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(y),chrome.webNavigation.onErrorOccurred.removeListener(g),h.push(`Navigation error: ${T.error}`),m())};chrome.webNavigation.onCompleted.addListener(y),chrome.webNavigation.onErrorOccurred.addListener(g),setTimeout(()=>{chrome.webNavigation.onCompleted.removeListener(y),chrome.webNavigation.onErrorOccurred.removeListener(g),h.push("Navigation timeout (30s)"),m()},3e4)}),await new Promise(m=>setTimeout(m,2e3));const N=l.getConsoleMessages(p,{onlyErrors:!0,limit:50});for(const m of N)h.push(`[${m.type}] ${m.text}`);if(r)try{f=(await l.captureScreenshot(p)).base64}catch{}}catch(S){h.push(S instanceof Error?S.message:String(S))}finally{if(p)try{await chrome.tabs.remove(p)}catch{}}const E=Date.now()-d,_=h.length===0?"pass":"fail";if(_==="pass"?a++:c++,s.push({url:u,status:_,time:E,errors:h,...f&&{screenshotBase64:f,hostname:w}}),n&&_==="fail")break}return{results:s,summary:{pass:a,fail:c,total:s.length},savePath:o.savePath}}case"WAIT_FOR_ELEMENT":{if(!t)throw new Error("No tabId provided");if(!o.selector)throw new Error("No selector provided");const e=b(t);try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(r=>setTimeout(r,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_ELEMENT",selector:o.selector,state:o.state||"visible",timeout:o.timeout||2e4},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_URL":{if(!t)throw new Error("No tabId provided");if(!o.pattern)throw new Error("No URL pattern provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_URL",pattern:o.pattern,timeout:o.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(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_NETWORK_IDLE":{if(!t)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_NETWORK_IDLE",timeout:o.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(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_DOM_STABLE":{if(!t)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_DOM_STABLE",stable:o.stable||100,timeout:o.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(t,{type:"SHOW_AFTER_TOOL_USE"},{frameId:0})}catch{}}}case"DIALOG_ACCEPT":{if(!t)throw new Error("No tabId provided");return await l.handleDialog(t,!0,o.text)}case"DIALOG_DISMISS":{if(!t)throw new Error("No tabId provided");return await l.handleDialog(t,!1)}case"DIALOG_INFO":{if(!t)throw new Error("No tabId provided");const e=l.getDialogInfo(t);return e?{hasDialog:!0,type:e.type,message:e.message,defaultPrompt:e.defaultPrompt}:{hasDialog:!1}}case"EMULATE_NETWORK":{if(!t)throw new Error("No tabId provided");if(!o.preset)throw new Error("No preset provided");const e=await l.emulateNetwork(t,o.preset);if(!e.success)throw new Error(e.error);return{success:!0,preset:o.preset}}case"EMULATE_CPU":{if(!t)throw new Error("No tabId provided");if(o.rate===void 0)throw new Error("No rate provided");const e=await l.emulateCPU(t,o.rate);if(!e.success)throw new Error(e.error);return{success:!0,rate:o.rate}}case"EMULATE_GEO":{if(!t)throw new Error("No tabId provided");if(o.clear){const r=await l.clearGeolocation(t);if(!r.success)throw new Error(r.error);return{success:!0,cleared:!0}}if(o.latitude===void 0||o.longitude===void 0)throw new Error("Latitude and longitude required");const e=await l.emulateGeolocation(t,o.latitude,o.longitude,o.accuracy);if(!e.success)throw new Error(e.error);return{success:!0,latitude:o.latitude,longitude:o.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(!t)throw new Error("No tabId provided");const e=o.device;if(e.toLowerCase()==="reset"){const a=await l.clearDeviceEmulation(t);if(!a.success)throw new Error(a.error);return{success:!0,message:"Device emulation reset"}}const 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"}};let n=r[e];if(!n){const a=e.toLowerCase();let c=null;for(const[u,d]of Object.entries(r)){const h=u.toLowerCase(),f=h.replace(/\s+/g,"");(h.includes(a)||a.includes(f))&&(!c||u.length>c.name.length)&&(c={name:u,preset:d})}c&&(n=c.preset)}if(!n)throw new Error(`Unknown device: ${e}. Use --list to see available devices.`);const s=await l.emulateDevice(t,n);if(!s.success)throw new Error(s.error);return{success:!0,device:e}}case"EMULATE_VIEWPORT":{if(!t)throw new Error("No tabId provided");if(!o.width&&!o.height)throw new Error("--width or --height required");const e=await l.emulateViewport(t,{width:o.width,height:o.height,deviceScaleFactor:o.deviceScaleFactor,mobile:o.mobile});if(!e.success)throw new Error(e.error);return{success:!0,width:o.width,height:o.height}}case"EMULATE_TOUCH":{if(!t)throw new Error("No tabId provided");const e=await l.emulateTouch(t,o.enabled);if(!e.success)throw new Error(e.error);return{success:!0,enabled:o.enabled}}case"FORM_FILL":{if(!t)throw new Error("No tabId provided");if(!o.data)throw new Error("No data provided");return await chrome.tabs.sendMessage(t,{type:"FORM_FILL",data:o.data},{frameId:b(t)})}case"PERF_START":{if(!t)throw new Error("No tabId provided");const e=await l.startPerformanceTrace(t,o.categories);if(!e.success)throw new Error(e.error);return{success:!0,message:"Performance tracing started"}}case"PERF_STOP":{if(!t)throw new Error("No tabId provided");const e=await l.stopPerformanceTrace(t);if(!e.success)throw new Error(e.error);return{success:!0,metrics:e.metrics}}case"PERF_METRICS":{if(!t)throw new Error("No tabId provided");const e=await l.getPerformanceMetrics(t);if(!e.success)throw new Error(e.error);return{success:!0,metrics:e.metrics}}case"UPLOAD_FILE":{if(!t)throw new Error("No tabId provided");if(!o.ref)throw new Error("No ref provided");if(!o.files||!o.files.length)throw new Error("No files provided");const e=await chrome.tabs.sendMessage(t,{type:"GET_FILE_INPUT_SELECTOR",ref:o.ref},{frameId:b(t)});if(e.error)throw new Error(e.error);const r=await l.setFileInputBySelector(t,e.selector,o.files);if(!r.success)throw new Error(r.error);return{success:!0,filesSet:o.files.length}}case"WAIT_FOR_LOAD":{if(!t)throw new Error("No tabId provided");const e=await l.waitForLoad(t,o.timeout||3e4);if(!e.success)throw new Error(e.error);return{success:!0,readyState:e.readyState}}case"GET_FRAMES":{if(!t)throw new Error("No tabId provided");const e=await l.getFrames(t);if(!e.success)throw new Error(e.error);return{success:!0,frames:e.frames}}case"FRAME_SWITCH":{if(!t)throw new Error("No tabId provided");const{selector:e,name:r,index:n}=o;if(!e&&!r&&n===void 0)throw new Error("--selector, --name, or --index required");const s=await chrome.webNavigation.getAllFrames({tabId:t});if(!s||s.length===0)throw new Error("No frames found in tab");const a=s.filter(u=>u.frameId!==0);if(a.length===0)throw new Error("No iframes found on this page");let c=null;if(n!==void 0){if(n<0||n>=a.length)throw new Error(`Frame index ${n} out of range. Found ${a.length} frame(s).`);c=a[n]}else if(r){for(const u of a)try{if((await chrome.tabs.sendMessage(t,{type:"GET_FRAME_NAME"},{frameId:u.frameId}))?.name===r){c=u;break}}catch{}if(!c)throw new Error(`Frame with name "${r}" not found`)}else if(e)try{const u=await chrome.tabs.sendMessage(t,{type:"GET_FRAME_BY_SELECTOR",selector:e},{frameId:0});if(u?.error)throw new Error(u.error);u?.url&&(c=a.find(d=>d.url===u.url)||null),!c&&a.length===1&&(c=a[0])}catch{throw new Error(`Could not find frame with selector "${e}"`)}if(!c)throw new Error("Frame not found");return F.set(t,c.frameId),{success:!0,frameId:c.frameId,url:c.url}}case"FRAME_MAIN":{if(!t)throw new Error("No tabId provided");return F.delete(t),{success:!0,message:"Returned to main frame"}}case"EVALUATE_IN_FRAME":{if(!t)throw new Error("No tabId provided");if(!o.frameId)throw new Error("No frameId provided");if(!o.code)throw new Error("No code provided");const e=await l.evaluateInFrame(t,o.frameId,o.code);if(!e.success)throw new Error(e.error);return{value:e.result}}case"EXECUTE_JAVASCRIPT":{if(!t)throw new Error("No tabId provided");if(!o.code)throw new Error("No code provided");try{await l.evaluateScript(t,"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}");const n=`(async () => { 'use strict'; ${o.code.replace(/`/g,"\\`").replace(/\$/g,"\\$")} })()`,s=await l.evaluateScript(t,n);if(s.exceptionDetails)return{error:s.exceptionDetails.exception?.description||s.exceptionDetails.text||"Script execution failed"};const a=s.result?.value;return{output:(a===void 0?"undefined":JSON.stringify(a,null,2))?.substring(0,5e4)||"undefined"}}catch(e){const r=e instanceof Error?e.message:"Script execution failed";return r.includes("Cannot access")||r.includes("Cannot attach")?{error:"Cannot execute JavaScript on this page (restricted URL)"}:{error:r}}}case"READ_CONSOLE_MESSAGES":{if(!t)throw new Error("No tabId provided");try{await l.enableConsoleTracking(t)}catch{}const e=l.getConsoleMessages(t,{onlyErrors:o.onlyErrors,pattern:o.pattern,limit:o.limit||100});return o.clear&&l.clearConsoleMessages(t),{messages:e}}case"CLEAR_CONSOLE_MESSAGES":{if(!t)throw new Error("No tabId provided");return l.clearConsoleMessages(t),{success:!0}}case"READ_NETWORK_REQUESTS":{if(!t)throw new Error("No tabId provided");try{await l.enableNetworkTracking(t)}catch{}if(o.full){let r=l.getNetworkEntries(t,{urlPattern:o.urlPattern});o.method&&(r=r.filter(s=>s.method===o.method)),o.status&&(r=r.filter(s=>s.status===o.status)),o.contentType&&(r=r.filter(s=>s.type===o.contentType)),o.clear&&l.clearNetworkRequests(t);const n=o.limit||100;return{entries:r.slice(0,n),format:o.format,verbose:o.verbose}}let e=l.getNetworkRequests(t,{urlPattern:o.urlPattern,limit:o.limit||100});return o.method&&(e=e.filter(r=>r.method===o.method)),o.status&&(e=e.filter(r=>r.status===o.status)),o.contentType&&(e=e.filter(r=>r.type===o.contentType)),o.clear&&l.clearNetworkRequests(t),{requests:e,format:o.format,verbose:o.verbose}}case"CLEAR_NETWORK_REQUESTS":{if(!t)throw new Error("No tabId provided");return l.clearNetworkRequests(t),{success:!0}}case"GET_NETWORK_ENTRIES":{if(!t)throw new Error("No tabId provided");try{await l.enableNetworkTracking(t)}catch{}let e=l.getNetworkEntries(t,{urlPattern:o.urlPattern,includeStatic:!o.excludeStatic});return o.origin&&(e=e.filter(r=>r.origin===o.origin)),o.method&&(e=e.filter(r=>r.method===o.method)),o.status&&(e=e.filter(r=>r.status===o.status)),o.type&&(e=e.filter(r=>r.type===o.type)),o.since&&(e=e.filter(r=>r.ts>=o.since)),o.hasBody!==void 0&&(e=e.filter(r=>o.hasBody?r.responseBodySize&&r.responseBodySize>0:!r.responseBodySize)),o.last&&(e=e.slice(-o.last)),o.clear&&l.clearNetworkRequests(t),{entries:e}}case"GET_NETWORK_ENTRY":{if(!t)throw new Error("No tabId provided");if(!o.requestId)throw new Error("No requestId provided");let e=l.getNetworkEntry(t,o.requestId);return e||(e=l.getNetworkEntries(t,{}).find(n=>n.id===o.requestId)||null),e||(e=l.getNetworkEntries(t,{}).find(n=>n._requestId===o.requestId)||null),e?{entry:e}:{error:`Entry not found: ${o.requestId}`}}case"GET_RESPONSE_BODY":{if(!t)throw new Error("No tabId provided");if(!o.requestId)throw new Error("No requestId provided");let e=o.requestId;if(o.requestId.startsWith("r_")){const s=l.getNetworkEntries(t,{}).find(a=>a.id===o.requestId);s&&(e=s._requestId)}return await l.getResponseBody(t,e)}case"GET_NETWORK_ORIGINS":{if(!t)throw new Error("No tabId provided");const e=l.getNetworkEntries(t,{}),r={};for(const n of e)r[n.origin]||(r[n.origin]={count:0,lastSeen:0,size:0}),r[n.origin].count++,r[n.origin].lastSeen=Math.max(r[n.origin].lastSeen,n.ts),r[n.origin].size+=n.responseBodySize||0;return{origins:r}}case"GET_NETWORK_STATS":{if(!t)throw new Error("No tabId provided");const e=l.getNetworkEntries(t,{}),r={},n={},s={};let a=0,c=1/0,u=0;for(const d of e){r[d.origin]||(r[d.origin]=0),r[d.origin]++;const h=d.method||"GET";if(n[h]=(n[h]||0)+1,d.status){const f=`${Math.floor(d.status/100)}xx`;s[f]=(s[f]||0)+1}a+=d.responseBodySize||0,d.ts<c&&(c=d.ts),d.ts>u&&(u=d.ts)}return{stats:{totalRequests:e.length,totalSize:a,uniqueOrigins:Object.keys(r).length,startTime:c===1/0?null:c,duration:u&&c!==1/0?u-c:0,byMethod:n,byStatus:s}}}case"RESIZE_WINDOW":{if(!t)throw new Error("No tabId provided");if(!o.width||!o.height)throw new Error("width and height required");const e=await chrome.tabs.get(t);if(!e.windowId)throw new Error("Tab has no window");return await chrome.windows.update(e.windowId,{width:Math.floor(o.width),height:Math.floor(o.height)}),{success:!0,width:o.width,height:o.height}}case"TABS_CREATE":{const e=t?await chrome.tabs.get(t):null,r=await chrome.tabs.create({url:o.url||"about:blank",active:!1});if(!r.id)throw new Error("Failed to create tab");return e?.groupId&&e.groupId!==chrome.tabGroups.TAB_GROUP_ID_NONE&&await chrome.tabs.group({tabIds:r.id,groupId:e.groupId}),{success:!0,tabId:r.id,url:r.url||o.url||"about:blank"}}case"UPLOAD_IMAGE":{if(!t)throw new Error("No tabId provided");if(!o.screenshotId)throw new Error("screenshotId required");if(!o.ref&&!o.coordinate)throw new Error("ref or coordinate required");const e=le(o.screenshotId);if(!e)throw new Error(`Screenshot not found: ${o.screenshotId}`);try{return await chrome.tabs.sendMessage(t,{type:"UPLOAD_IMAGE",base64:e.base64,ref:o.ref,coordinate:o.coordinate,filename:o.filename||"screenshot.png"},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"GET_TABS":return{tabs:(await chrome.tabs.query({})).map(r=>({id:r.id,title:r.title,url:r.url}))};case"LIST_TABS":{const e={};return o.windowId&&(e.windowId=o.windowId),{tabs:(await chrome.tabs.query(e)).map(n=>({id:n.id,title:n.title,url:n.url,active:n.active,windowId:n.windowId}))}}case"NEW_TAB":{const e=o.urls||(o.url?[o.url]:["about:blank"]),r=[];for(let n=0;n<e.length;n++){const s={url:e[n],active:n===0};o.windowId&&(s.windowId=o.windowId);const a=await chrome.tabs.create(s);a.id&&r.push({tabId:a.id,url:e[n]})}return r.length===1?{success:!0,tabId:r[0].tabId,url:r[0].url}:{success:!0,tabs:r}}case"SWITCH_TAB":{const e=o.tabId;if(!e)throw new Error("No tabId provided");const r=await chrome.tabs.update(e,{active:!0});return r.windowId&&await chrome.windows.update(r.windowId,{focused:!0}),{success:!0,tabId:e,url:r.url,title:r.title}}case"CLOSE_TAB":{const e=o.tabIds||(o.tabId?[o.tabId]:[]);if(e.length===0)throw new Error("No tabId(s) provided");return await chrome.tabs.remove(e),e.length===1?{success:!0,tabId:e[0]}:{success:!0,closed:e}}case"TABS_REGISTER":{if(!t)throw new Error("No tabId provided");if(!o.name)throw new Error("No name provided");return A.set(o.name,t),{success:!0,name:o.name,tabId:t}}case"TABS_GET_BY_NAME":{if(!o.name)throw new Error("No name provided");const e=A.get(o.name);if(!e)return{error:`No tab registered with name "${o.name}"`};try{const r=await chrome.tabs.get(e);return{tabId:e,url:r.url,title:r.title}}catch{return A.delete(o.name),{error:`Tab "${o.name}" no longer exists`}}}case"TABS_LIST_NAMED":{const e=[];for(const[r,n]of A)try{const s=await chrome.tabs.get(n);e.push({name:r,tabId:n,url:s.url,title:s.title})}catch{A.delete(r)}return{tabs:e}}case"TABS_UNREGISTER":{if(!o.name)throw new Error("No name provided");return A.delete(o.name)?{success:!0}:{success:!1,error:`No tab registered with name "${o.name}"`}}case"GET_AUTH":{const{sendToNativeHost:e}=await V(async()=>{const{sendToNativeHost:r}=await Promise.resolve().then(()=>X);return{sendToNativeHost:r}},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":{const{sendToNativeHost:e}=await V(async()=>{const{sendToNativeHost:r}=await Promise.resolve().then(()=>X);return{sendToNativeHost:r}},void 0);try{return await e({type:"API_REQUEST",streamId:o.streamId,url:o.url,method:o.method,headers:o.headers,body:o.body}),{sent:!0}}catch(r){return{error:r instanceof Error?r.message:"Unknown error"}}}case"STREAM_CONSOLE":{if(!t)throw new Error("No tabId provided");const e=o.streamId;try{return await l.enableConsoleTracking(t),M.set(e,t),l.subscribeToConsole(t,e,r=>{x({type:"STREAM_EVENT",streamId:e,event:{type:"console_event",level:r.type==="exception"?"error":r.type,text:r.text,timestamp:r.timestamp,url:r.url,line:r.line}})}),{success:!0,streaming:!0}}catch(r){return x({type:"STREAM_ERROR",streamId:e,error:r instanceof Error?r.message:"Failed to start console stream"}),{error:r instanceof Error?r.message:"Failed to start console stream"}}}case"STREAM_NETWORK":{if(!t)throw new Error("No tabId provided");const e=o.streamId;try{return await l.enableNetworkTracking(t),M.set(e,t),l.subscribeToNetwork(t,e,r=>{x({type:"STREAM_EVENT",streamId:e,event:{type:"network_event",method:r.method,url:r.url,status:r.status,duration:r.duration,timestamp:r.timestamp}})}),{success:!0,streaming:!0}}catch(r){return x({type:"STREAM_ERROR",streamId:e,error:r instanceof Error?r.message:"Failed to start network stream"}),{error:r instanceof Error?r.message:"Failed to start network stream"}}}case"STREAM_STOP":{const e=o.streamId,r=M.get(e);return r!==void 0&&(l.unsubscribeFromConsole(r,e),l.unsubscribeFromNetwork(r,e),M.delete(e)),{success:!0}}case"SEARCH_PAGE":{if(!t)throw new Error("No tabId provided");if(!o.term)throw new Error("Search term required");try{return await chrome.tabs.sendMessage(t,{type:"SEARCH_PAGE",term:o.term,caseSensitive:o.caseSensitive||!1,limit:o.limit||10},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"TAB_GROUP_CREATE":{const e=[...o.tabIds||[]],r=o.name||"Surf",s=["grey","blue","red","yellow","green","pink","purple","cyan","orange"].includes(o.color)?o.color:"blue";if(e.length===0&&t&&e.push(t),e.length===0)throw new Error("No tabs specified");const a=await chrome.tabGroups.query({title:r});let c;return a.length>0?(c=a[0].id,await chrome.tabs.group({tabIds:e,groupId:c})):(c=await chrome.tabs.group({tabIds:e}),await chrome.tabGroups.update(c,{title:r,color:s,collapsed:!1})),{success:!0,groupId:c,name:r,tabIds:e}}case"TAB_GROUP_REMOVE":{const e=[...o.tabIds||[]];if(e.length===0&&t&&e.push(t),e.length===0)throw new Error("No tabs specified");return await chrome.tabs.ungroup(e),{success:!0,ungrouped:e}}case"TAB_GROUPS_LIST":{const e=await chrome.tabGroups.query({}),r=[];for(const n of e){const s=await chrome.tabs.query({groupId:n.id});r.push({id:n.id,name:n.title||"(unnamed)",color:n.color,collapsed:n.collapsed,tabs:s.map(a=>({id:a.id,title:a.title,url:a.url}))})}return{groups:r}}case"CLICK_SELECTOR":{if(!t)throw new Error("No tabId provided");const e=o.selector,r=o.index||0,n=`(() => {
144
+ const elements = document.querySelectorAll(${JSON.stringify(e)});
145
145
  if (elements.length === 0) return { error: "No elements match selector" };
146
- if (${o} >= elements.length) return { error: "Index " + ${o} + " out of range (found " + elements.length + " elements)" };
146
+ if (${r} >= elements.length) return { error: "Index " + ${r} + " out of range (found " + elements.length + " elements)" };
147
147
 
148
- const el = elements[${o}];
148
+ const el = elements[${r}];
149
149
  const rect = el.getBoundingClientRect();
150
150
  return {
151
151
  x: rect.left + rect.width / 2,
152
152
  y: rect.top + rect.height / 2,
153
153
  count: elements.length
154
154
  };
155
- })()`,c=(B=(await u.evaluateScript(e,a)).result)==null?void 0:B.value;return c!=null&&c.error?{error:c.error}:c?(await u.click(e,c.x,c.y,"left",1,0),{success:!0,selector:r,index:o,matchCount:c.count}):{error:"Failed to get element coordinates"}}case"COOKIE_LIST":{if(!e)throw new Error("No tabId provided");const o=(await chrome.tabs.get(e)).url;if(!o)throw new Error("Tab has no URL");return{cookies:await chrome.cookies.getAll({url:o})}}case"COOKIE_GET":{if(!e)throw new Error("No tabId provided");const o=(await chrome.tabs.get(e)).url;if(!o)throw new Error("Tab has no URL");if(!t.name)throw new Error("Cookie name required");const a=await chrome.cookies.get({url:o,name:t.name});return a?{cookie:a}:{error:`Cookie "${t.name}" not found`}}case"COOKIE_SET":{if(!e)throw new Error("No tabId provided");const o=(await chrome.tabs.get(e)).url;if(!o)throw new Error("Tab has no URL");if(!t.name)throw new Error("Cookie name required");if(t.value===void 0)throw new Error("Cookie value required");const a={url:o,name:t.name,value:t.value};if(t.expires){const c=new Date(t.expires).getTime()/1e3;if(isNaN(c))throw new Error(`Invalid expiration date: ${t.expires}`);a.expirationDate=c}return{success:!0,cookie:await chrome.cookies.set(a)}}case"COOKIE_CLEAR":{if(!e)throw new Error("No tabId provided");const o=(await chrome.tabs.get(e)).url;if(!o)throw new Error("Tab has no URL");if(!t.name)throw new Error("Cookie name required");return await chrome.cookies.remove({url:o,name:t.name}),{success:!0,cleared:t.name}}case"COOKIE_CLEAR_ALL":{if(!e)throw new Error("No tabId provided");const o=(await chrome.tabs.get(e)).url;if(!o)throw new Error("Tab has no URL");const a=await chrome.cookies.getAll({url:o});for(const h of a)await chrome.cookies.remove({url:o,name:h.name});return{success:!0,cleared:a.length}}case"TAB_RELOAD":{if(!e)throw new Error("No tabId provided");return await chrome.tabs.reload(e,{bypassCache:t.hard||!1}),{success:!0}}case"ZOOM_GET":{if(!e)throw new Error("No tabId provided");return{zoom:await chrome.tabs.getZoom(e)}}case"ZOOM_SET":{if(!e)throw new Error("No tabId provided");const r=t.level;if(r<.25||r>5)throw new Error("Zoom level must be between 0.25 and 5");return await chrome.tabs.setZoom(e,r),{success:!0,zoom:r}}case"ZOOM_RESET":{if(!e)throw new Error("No tabId provided");return await chrome.tabs.setZoom(e,0),{success:!0,zoom:1}}case"BOOKMARK_ADD":{if(!e)throw new Error("No tabId provided");const r=await chrome.tabs.get(e),o={title:r.title||"Untitled",url:r.url};if(t.folder){const c=(await chrome.bookmarks.search({title:t.folder})).find(w=>!w.url);c&&(o.parentId=c.id)}const a=await chrome.bookmarks.create(o);return{success:!0,bookmark:{id:a.id,title:a.title,url:a.url}}}case"BOOKMARK_REMOVE":{if(!e)throw new Error("No tabId provided");const r=await chrome.tabs.get(e);if(!r.url)throw new Error("Tab has no URL");const o=await chrome.bookmarks.search({url:r.url});if(o.length===0)throw new Error("No bookmark found for this URL");return await chrome.bookmarks.remove(o[0].id),{success:!0}}case"BOOKMARK_LIST":{const r=typeof t.limit=="number"?t.limit:50;let o=[];if(t.folder){const h=(await chrome.bookmarks.search({title:t.folder})).find(c=>!c.url);h&&(o=(await chrome.bookmarks.getChildren(h.id)).filter(w=>w.url).slice(0,r))}else o=await chrome.bookmarks.getRecent(r);return{bookmarks:o.map(a=>({id:a.id,title:a.title,url:a.url,dateAdded:a.dateAdded}))}}case"HISTORY_LIST":{const r=typeof t.limit=="number"?t.limit:20;return{history:(await chrome.history.search({text:"",maxResults:r,startTime:0})).map(a=>({url:a.url,title:a.title,lastVisitTime:a.lastVisitTime,visitCount:a.visitCount}))}}case"HISTORY_SEARCH":{const r=t.query,o=typeof t.limit=="number"?t.limit:20;return{history:(await chrome.history.search({text:r,maxResults:o,startTime:0})).map(h=>({url:h.url,title:h.title,lastVisitTime:h.lastVisitTime,visitCount:h.visitCount}))}}case"GET_CHATGPT_COOKIES":{const r=await chrome.cookies.getAll({domain:".chatgpt.com"}),o=await chrome.cookies.getAll({domain:".openai.com"});return{cookies:[...r,...o]}}case"CHATGPT_NEW_TAB":{const r=await chrome.tabs.create({url:"https://chatgpt.com/",active:!0});if(!r.id)throw new Error("Failed to create tab");return(await chrome.tabs.get(r.id)).status!=="complete"&&await new Promise(a=>{const h=(c,w)=>{c===r.id&&w.status==="complete"&&(chrome.tabs.onUpdated.removeListener(h),a())};chrome.tabs.onUpdated.addListener(h),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(h),a()},3e4)}),await u.attach(r.id),await re(r.id,1e4),{tabId:r.id}}case"CHATGPT_CLOSE_TAB":{const r=t.tabId;if(r){try{await u.detach(r)}catch{}try{await chrome.tabs.remove(r)}catch{}}return{success:!0}}case"CHATGPT_CDP_COMMAND":{const{method:r,params:o}=t;return await u.sendCommand(t.tabId,r,o||{})}case"CHATGPT_EVALUATE":return await u.evaluateScript(t.tabId,t.expression);case"PERPLEXITY_NEW_TAB":{const r=await chrome.tabs.create({url:"https://www.perplexity.ai/",active:!0});if(!r.id)throw new Error("Failed to create tab");return(await chrome.tabs.get(r.id)).status!=="complete"&&await new Promise(a=>{const h=(c,w)=>{c===r.id&&w.status==="complete"&&(chrome.tabs.onUpdated.removeListener(h),a())};chrome.tabs.onUpdated.addListener(h),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(h),a()},3e4)}),await u.attach(r.id),await re(r.id,1e4),{tabId:r.id}}case"PERPLEXITY_CLOSE_TAB":{const r=t.tabId;if(r){try{await u.detach(r)}catch{}try{await chrome.tabs.remove(r)}catch{}}return{success:!0}}case"PERPLEXITY_CDP_COMMAND":{const{method:r,params:o}=t;return await u.sendCommand(t.tabId,r,o||{})}case"PERPLEXITY_EVALUATE":return await u.evaluateScript(t.tabId,t.expression);case"GET_TWITTER_COOKIES":{const r=[".x.com",".twitter.com","x.com","twitter.com"],o=[];for(const c of r)try{const w=await chrome.cookies.getAll({domain:c});o.push(...w)}catch{}const a=["https://x.com","https://twitter.com"];for(const c of a)try{const w=await chrome.cookies.getAll({url:c});o.push(...w)}catch{}const h=new Map;for(const c of o)(!h.get(c.name)||(F=c.domain)!=null&&F.includes("x.com"))&&h.set(c.name,c);return{cookies:Array.from(h.values())}}case"GROK_NEW_TAB":{const r=await chrome.tabs.create({url:"https://x.com/i/grok",active:!0});if(!r.id)throw new Error("Failed to create tab");return(await chrome.tabs.get(r.id)).status!=="complete"&&await new Promise(a=>{const h=(c,w)=>{c===r.id&&w.status==="complete"&&(chrome.tabs.onUpdated.removeListener(h),a())};chrome.tabs.onUpdated.addListener(h),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(h),a()},3e4)}),await u.attach(r.id),await re(r.id,1e4),{tabId:r.id}}case"GROK_CLOSE_TAB":{const r=t.tabId;if(r){try{await u.detach(r)}catch{}try{await chrome.tabs.remove(r)}catch{}}return{success:!0}}case"GROK_CDP_COMMAND":{const{method:r,params:o}=t;return await u.sendCommand(t.tabId,r,o||{})}case"GROK_EVALUATE":return await u.evaluateScript(t.tabId,t.expression);case"AISTUDIO_NEW_TAB":{const r=t.url||"https://aistudio.google.com/prompts/new_chat",o=await chrome.tabs.create({url:r,active:!0});if(!o.id)throw new Error("Failed to create tab");return(await chrome.tabs.get(o.id)).status!=="complete"&&await new Promise(h=>{const c=(w,m)=>{w===o.id&&m.status==="complete"&&(chrome.tabs.onUpdated.removeListener(c),h())};chrome.tabs.onUpdated.addListener(c),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(c),h()},3e4)}),await u.attach(o.id),await re(o.id,1e4),{tabId:o.id}}case"AISTUDIO_CLOSE_TAB":{const r=t.tabId;if(r){try{await u.detach(r)}catch{}try{await chrome.tabs.remove(r)}catch{}}return{success:!0}}case"AISTUDIO_CDP_COMMAND":{const{method:r,params:o}=t;return await u.sendCommand(t.tabId,r,o||{})}case"AISTUDIO_EVALUATE":return await u.evaluateScript(t.tabId,t.expression);case"DOWNLOADS_SEARCH":return{downloads:(await chrome.downloads.search(t.searchParams||{})).map(o=>({id:o.id,filename:o.filename,state:o.state,error:o.error}))};case"GET_GOOGLE_COOKIES":{const r=[".google.com",".gemini.google.com","accounts.google.com","www.google.com"],o=[];for(const c of r)try{const w=await chrome.cookies.getAll({domain:c});o.push(...w)}catch{}const a=["https://gemini.google.com","https://aistudio.google.com","https://accounts.google.com","https://www.google.com"];for(const c of a)try{const w=await chrome.cookies.getAll({url:c});o.push(...w)}catch{}const h=new Map;for(const c of o){const w=h.get(c.name);(!w||c.domain===".google.com"&&c.path==="/"||!((M=w.domain)!=null&&M.includes("google.com"))&&((N=c.domain)!=null&&N.includes("google.com")))&&h.set(c.name,c)}return{cookies:Array.from(h.values())}}case"WINDOW_NEW":{const r=t.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>',o={focused:t.focused!==!1,type:"normal",url:r};t.width&&t.height&&(o.width=t.width,o.height=t.height),t.incognito&&(o.incognito=!0);const a=await chrome.windows.create(o);if(!a.id)throw new Error("Failed to create window");const c=(await chrome.tabs.query({windowId:a.id}))[0];return c!=null&&c.id&&await new Promise(w=>setTimeout(w,150)),{success:!0,windowId:a.id,tabId:c==null?void 0:c.id,hint:`Use --window-id ${a.id} to target this window`}}case"WINDOW_LIST":return{windows:(await chrome.windows.getAll({populate:!0})).map(o=>{var a,h;return{id:o.id,focused:o.focused,type:o.type,state:o.state,width:o.width,height:o.height,tabCount:((a=o.tabs)==null?void 0:a.length)||0,tabs:t.includeTabs?(h=o.tabs)==null?void 0:h.map(c=>({id:c.id,title:c.title,url:c.url,active:c.active})):void 0}})};case"WINDOW_FOCUS":{if(!t.windowId)throw new Error("No windowId provided");return await chrome.windows.update(t.windowId,{focused:!0}),{success:!0,windowId:t.windowId}}case"WINDOW_CLOSE":{if(!t.windowId)throw new Error("No windowId provided");return await chrome.windows.remove(t.windowId),{success:!0,windowId:t.windowId}}case"WINDOW_RESIZE":{if(!t.windowId)throw new Error("No windowId provided");const r={};t.width&&(r.width=t.width),t.height&&(r.height=t.height),t.left!==void 0&&(r.left=t.left),t.top!==void 0&&(r.top=t.top),t.state&&(r.state=t.state);const o=await chrome.windows.update(t.windowId,r);return{success:!0,windowId:t.windowId,width:o.width,height:o.height}}default:throw new Error(`Unknown message type: ${t.type}`)}}chrome.runtime.onInstalled.addListener(t=>{q("Extension installed/updated:",t.reason)});const Pe=new Set(["LIST_TABS","NEW_TAB","TABS_NEW","CLOSE_TABS","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","AISTUDIO_NEW_TAB","AISTUDIO_CLOSE_TAB","AISTUDIO_EVALUATE","AISTUDIO_CDP_COMMAND","DOWNLOADS_SEARCH","WINDOW_NEW","WINDOW_LIST","WINDOW_FOCUS","WINDOW_CLOSE","WINDOW_RESIZE","EMULATE_DEVICE_LIST"]);Ee(async t=>{var y,b,E,T;let i=t.tabId;const e=t.windowId,n=(y=t.type)==null?void 0:y.startsWith("DIALOG_"),s=!Pe.has(t.type);let d=!1;if(i&&!n)try{await chrome.tabs.get(i)}catch{throw new Error(`Invalid tab ID: ${i}. Use 'surf tab.list' to see available tabs.`)}else if(!i&&s){let S,p;if(e){S=await chrome.tabs.query({active:!0,windowId:e}),p=S[0];const v=g=>!g||g.startsWith("chrome://")||g.startsWith("chrome-extension://")||g==="about:blank";if((!p||v(p.url))&&(S=await chrome.tabs.query({windowId:e}),p=S.find(g=>!v(g.url))),!(p!=null&&p.id)){const g=await chrome.tabs.create({windowId:e,url:"data:text/html,<html><head><title>Surf</title></head><body></body></html>",active:!0});if(!g.id)throw new Error(`Failed to create tab in window ${e}`);await new Promise(k=>setTimeout(k,100)),p=g,d=!0}}else if(S=await chrome.tabs.query({active:!0,lastFocusedWindow:!0}),p=S[0],(!p||(b=p.url)!=null&&b.startsWith("chrome-extension://"))&&(S=await chrome.tabs.query({active:!0,currentWindow:!0}),p=S[0]),(!p||(E=p.url)!=null&&E.startsWith("chrome-extension://")||(T=p.url)!=null&&T.startsWith("chrome://"))&&(S=await chrome.tabs.query({active:!0}),p=S.find(v=>{var g,k;return!((g=v.url)!=null&&g.startsWith("chrome-extension://"))&&!((k=v.url)!=null&&k.startsWith("chrome://"))})),!(p!=null&&p.id))throw new Error("No active tab found. Use 'surf tab.new <url>' to create one, or 'surf tab.list' to see available tabs.");i=p.id}const l=await ye({...t,tabId:i},{}),f=[];return d&&f.push(`Auto-created tab in window ${e} (no usable tabs existed). Navigate to your target URL.`),{...l,_resolvedTabId:i,_hint:f.length>0?f.join(" "):void 0}});
155
+ })()`,a=(await l.evaluateScript(t,n)).result?.value;return a?.error?{error:a.error}:a?(await l.click(t,a.x,a.y,"left",1,0),{success:!0,selector:e,index:r,matchCount:a.count}):{error:"Failed to get element coordinates"}}case"COOKIE_LIST":{if(!t)throw new Error("No tabId provided");const r=(await chrome.tabs.get(t)).url;if(!r)throw new Error("Tab has no URL");return{cookies:await chrome.cookies.getAll({url:r})}}case"COOKIE_GET":{if(!t)throw new Error("No tabId provided");const r=(await chrome.tabs.get(t)).url;if(!r)throw new Error("Tab has no URL");if(!o.name)throw new Error("Cookie name required");const n=await chrome.cookies.get({url:r,name:o.name});return n?{cookie:n}:{error:`Cookie "${o.name}" not found`}}case"COOKIE_SET":{if(!t)throw new Error("No tabId provided");const r=(await chrome.tabs.get(t)).url;if(!r)throw new Error("Tab has no URL");if(!o.name)throw new Error("Cookie name required");if(o.value===void 0)throw new Error("Cookie value required");const n={url:r,name:o.name,value:o.value};if(o.expires){const a=new Date(o.expires).getTime()/1e3;if(isNaN(a))throw new Error(`Invalid expiration date: ${o.expires}`);n.expirationDate=a}return{success:!0,cookie:await chrome.cookies.set(n)}}case"COOKIE_CLEAR":{if(!t)throw new Error("No tabId provided");const r=(await chrome.tabs.get(t)).url;if(!r)throw new Error("Tab has no URL");if(!o.name)throw new Error("Cookie name required");return await chrome.cookies.remove({url:r,name:o.name}),{success:!0,cleared:o.name}}case"COOKIE_CLEAR_ALL":{if(!t)throw new Error("No tabId provided");const r=(await chrome.tabs.get(t)).url;if(!r)throw new Error("Tab has no URL");const n=await chrome.cookies.getAll({url:r});for(const s of n)await chrome.cookies.remove({url:r,name:s.name});return{success:!0,cleared:n.length}}case"TAB_RELOAD":{if(!t)throw new Error("No tabId provided");return await chrome.tabs.reload(t,{bypassCache:o.hard||!1}),{success:!0}}case"ZOOM_GET":{if(!t)throw new Error("No tabId provided");return{zoom:await chrome.tabs.getZoom(t)}}case"ZOOM_SET":{if(!t)throw new Error("No tabId provided");const e=o.level;if(e<.25||e>5)throw new Error("Zoom level must be between 0.25 and 5");return await chrome.tabs.setZoom(t,e),{success:!0,zoom:e}}case"ZOOM_RESET":{if(!t)throw new Error("No tabId provided");return await chrome.tabs.setZoom(t,0),{success:!0,zoom:1}}case"BOOKMARK_ADD":{if(!t)throw new Error("No tabId provided");const e=await chrome.tabs.get(t),r={title:e.title||"Untitled",url:e.url};if(o.folder){const a=(await chrome.bookmarks.search({title:o.folder})).find(c=>!c.url);a&&(r.parentId=a.id)}const n=await chrome.bookmarks.create(r);return{success:!0,bookmark:{id:n.id,title:n.title,url:n.url}}}case"BOOKMARK_REMOVE":{if(!t)throw new Error("No tabId provided");const e=await chrome.tabs.get(t);if(!e.url)throw new Error("Tab has no URL");const r=await chrome.bookmarks.search({url:e.url});if(r.length===0)throw new Error("No bookmark found for this URL");return await chrome.bookmarks.remove(r[0].id),{success:!0}}case"BOOKMARK_LIST":{const e=typeof o.limit=="number"?o.limit:50;let r=[];if(o.folder){const s=(await chrome.bookmarks.search({title:o.folder})).find(a=>!a.url);s&&(r=(await chrome.bookmarks.getChildren(s.id)).filter(c=>c.url).slice(0,e))}else r=await chrome.bookmarks.getRecent(e);return{bookmarks:r.map(n=>({id:n.id,title:n.title,url:n.url,dateAdded:n.dateAdded}))}}case"HISTORY_LIST":{const e=typeof o.limit=="number"?o.limit:20;return{history:(await chrome.history.search({text:"",maxResults:e,startTime:0})).map(n=>({url:n.url,title:n.title,lastVisitTime:n.lastVisitTime,visitCount:n.visitCount}))}}case"HISTORY_SEARCH":{const e=o.query,r=typeof o.limit=="number"?o.limit:20;return{history:(await chrome.history.search({text:e,maxResults:r,startTime:0})).map(s=>({url:s.url,title:s.title,lastVisitTime:s.lastVisitTime,visitCount:s.visitCount}))}}case"GET_CHATGPT_COOKIES":{const e=await chrome.cookies.getAll({domain:".chatgpt.com"}),r=await chrome.cookies.getAll({domain:".openai.com"});return{cookies:[...e,...r]}}case"CHATGPT_NEW_TAB":{const e=await chrome.tabs.create({url:"https://chatgpt.com/",active:!0});if(!e.id)throw new Error("Failed to create tab");return(await chrome.tabs.get(e.id)).status!=="complete"&&await new Promise(n=>{const s=(a,c)=>{a===e.id&&c.status==="complete"&&(chrome.tabs.onUpdated.removeListener(s),n())};chrome.tabs.onUpdated.addListener(s),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(s),n()},3e4)}),await l.attach(e.id),await U(e.id,1e4),{tabId:e.id}}case"CHATGPT_CLOSE_TAB":{const e=o.tabId;if(e){try{await l.detach(e)}catch{}try{await chrome.tabs.remove(e)}catch{}}return{success:!0}}case"CHATGPT_CDP_COMMAND":{const{method:e,params:r}=o;return await l.sendCommand(o.tabId,e,r||{})}case"CHATGPT_EVALUATE":return await l.evaluateScript(o.tabId,o.expression);case"PERPLEXITY_NEW_TAB":{const e=await chrome.tabs.create({url:"https://www.perplexity.ai/",active:!0});if(!e.id)throw new Error("Failed to create tab");return(await chrome.tabs.get(e.id)).status!=="complete"&&await new Promise(n=>{const s=(a,c)=>{a===e.id&&c.status==="complete"&&(chrome.tabs.onUpdated.removeListener(s),n())};chrome.tabs.onUpdated.addListener(s),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(s),n()},3e4)}),await l.attach(e.id),await U(e.id,1e4),{tabId:e.id}}case"PERPLEXITY_CLOSE_TAB":{const e=o.tabId;if(e){try{await l.detach(e)}catch{}try{await chrome.tabs.remove(e)}catch{}}return{success:!0}}case"PERPLEXITY_CDP_COMMAND":{const{method:e,params:r}=o;return await l.sendCommand(o.tabId,e,r||{})}case"PERPLEXITY_EVALUATE":return await l.evaluateScript(o.tabId,o.expression);case"GET_TWITTER_COOKIES":{const e=[".x.com",".twitter.com","x.com","twitter.com"],r=[];for(const a of e)try{const c=await chrome.cookies.getAll({domain:a});r.push(...c)}catch{}const n=["https://x.com","https://twitter.com"];for(const a of n)try{const c=await chrome.cookies.getAll({url:a});r.push(...c)}catch{}const s=new Map;for(const a of r)(!s.get(a.name)||a.domain?.includes("x.com"))&&s.set(a.name,a);return{cookies:Array.from(s.values())}}case"GROK_NEW_TAB":{const e=await chrome.tabs.create({url:"https://x.com/i/grok",active:!0});if(!e.id)throw new Error("Failed to create tab");return(await chrome.tabs.get(e.id)).status!=="complete"&&await new Promise(n=>{const s=(a,c)=>{a===e.id&&c.status==="complete"&&(chrome.tabs.onUpdated.removeListener(s),n())};chrome.tabs.onUpdated.addListener(s),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(s),n()},3e4)}),await l.attach(e.id),await U(e.id,1e4),{tabId:e.id}}case"GROK_CLOSE_TAB":{const e=o.tabId;if(e){try{await l.detach(e)}catch{}try{await chrome.tabs.remove(e)}catch{}}return{success:!0}}case"GROK_CDP_COMMAND":{const{method:e,params:r}=o;return await l.sendCommand(o.tabId,e,r||{})}case"GROK_EVALUATE":return await l.evaluateScript(o.tabId,o.expression);case"GEMINI_NEW_TAB":{const e=await chrome.tabs.create({url:"https://gemini.google.com/app",active:!0});if(!e.id)throw new Error("Failed to create tab");return{tabId:e.id}}case"GEMINI_CLOSE_TAB":{const e=o.tabId;if(e){try{await l.detach(e)}catch{}try{await chrome.tabs.remove(e)}catch{}}return{success:!0}}case"UPLOAD_FILE_TO_TAB":{const{tabId:e,filePaths:r}=o;if(!e||!r?.length)throw new Error("UPLOAD_FILE_TO_TAB requires tabId and filePaths");await l.attach(e),await l.sendCommand(e,"DOM.enable",{}),await l.sendCommand(e,"Page.setInterceptFileChooserDialog",{enabled:!0});let n=null,s=null;const a=()=>{n&&(clearTimeout(n),n=null),s&&(chrome.debugger.onEvent.removeListener(s),s=null)},c=(w,p)=>new Promise((E,_)=>{n=setTimeout(()=>{a(),_(new Error(`File chooser did not open within ${p/1e3}s (attempt ${w})`))},p),s=(S,N,m)=>{S.tabId===e&&N==="Page.fileChooserOpened"&&(a(),l.sendCommand(e,"DOM.setFileInputFiles",{files:r,backendNodeId:m.backendNodeId}).then(()=>E()).catch(_))},chrome.debugger.onEvent.addListener(s)}),u=async()=>{await l.sendCommand(e,"Runtime.evaluate",{expression:`document.querySelector('button[aria-label="Close upload file menu"]')?.click()`,userGesture:!0}),await new Promise(w=>setTimeout(w,300)),await l.sendCommand(e,"Runtime.evaluate",{expression:`document.querySelector('button[aria-label="Open upload file menu"]')?.click()`,userGesture:!0}),await new Promise(w=>setTimeout(w,500)),await l.sendCommand(e,"Runtime.evaluate",{expression:`document.querySelector('[data-test-id="local-images-files-uploader-button"]')?.click()`,userGesture:!0})},d=3,h=[1e4,15e3,2e4];let f=null;try{for(let w=1;w<=d;w++)try{const p=c(w,h[w-1]);return await u(),await p,{success:!0}}catch(p){f=p,a(),w<d&&await new Promise(E=>setTimeout(E,1e3))}throw new Error(`File upload failed after ${d} attempts: ${f?.message}`)}finally{a();try{await l.sendCommand(e,"Page.setInterceptFileChooserDialog",{enabled:!1})}catch{}}}case"GEMINI_FETCH_URL":{const e=o.url;if(!e)throw new Error("No URL provided");const r=await fetch(e,{credentials:"include"});if(!r.ok)throw new Error(`Fetch failed: ${r.status}`);const n=await r.blob(),s=new FileReader;return{b64:await new Promise((c,u)=>{s.onload=()=>c(s.result.split(",")[1]),s.onerror=()=>u(new Error("FileReader failed")),s.readAsDataURL(n)}),size:n.size,type:n.type}}case"AISTUDIO_NEW_TAB":{const e=o.url||"https://aistudio.google.com/prompts/new_chat",r=await chrome.tabs.create({url:e,active:!0});if(!r.id)throw new Error("Failed to create tab");return(await chrome.tabs.get(r.id)).status!=="complete"&&await new Promise(s=>{const a=(c,u)=>{c===r.id&&u.status==="complete"&&(chrome.tabs.onUpdated.removeListener(a),s())};chrome.tabs.onUpdated.addListener(a),setTimeout(()=>{chrome.tabs.onUpdated.removeListener(a),s()},3e4)}),await l.attach(r.id),await U(r.id,1e4),{tabId:r.id}}case"AISTUDIO_CLOSE_TAB":{const e=o.tabId;if(e){try{await l.detach(e)}catch{}try{await chrome.tabs.remove(e)}catch{}}return{success:!0}}case"AISTUDIO_CDP_COMMAND":{const{method:e,params:r}=o;return await l.sendCommand(o.tabId,e,r||{})}case"AISTUDIO_EVALUATE":return await l.evaluateScript(o.tabId,o.expression);case"DOWNLOADS_SEARCH":return{downloads:(await chrome.downloads.search(o.searchParams||{})).map(r=>({id:r.id,filename:r.filename,state:r.state,error:r.error}))};case"GET_GOOGLE_COOKIES":{const e=[".google.com",".gemini.google.com","accounts.google.com","www.google.com"],r=[];for(const a of e)try{const c=await chrome.cookies.getAll({domain:a});r.push(...c)}catch{}const n=["https://gemini.google.com","https://aistudio.google.com","https://accounts.google.com","https://www.google.com"];for(const a of n)try{const c=await chrome.cookies.getAll({url:a});r.push(...c)}catch{}const s=new Map;for(const a of r){const c=s.get(a.name);(!c||a.domain===".google.com"&&a.path==="/"||!c.domain?.includes("google.com")&&a.domain?.includes("google.com"))&&s.set(a.name,a)}return{cookies:Array.from(s.values())}}case"WINDOW_NEW":{const e=o.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>',r={focused:o.focused!==!1,type:"normal",url:e};o.width&&o.height&&(r.width=o.width,r.height=o.height),o.incognito&&(r.incognito=!0);const n=await chrome.windows.create(r);if(!n.id)throw new Error("Failed to create window");const a=(await chrome.tabs.query({windowId:n.id}))[0];return a?.id&&await new Promise(c=>setTimeout(c,150)),{success:!0,windowId:n.id,tabId:a?.id,hint:`Use --window-id ${n.id} to target this window`}}case"WINDOW_LIST":return{windows:(await chrome.windows.getAll({populate:!0})).map(r=>({id:r.id,focused:r.focused,type:r.type,state:r.state,width:r.width,height:r.height,tabCount:r.tabs?.length||0,tabs:o.includeTabs?r.tabs?.map(n=>({id:n.id,title:n.title,url:n.url,active:n.active})):void 0}))};case"WINDOW_FOCUS":{if(!o.windowId)throw new Error("No windowId provided");return await chrome.windows.update(o.windowId,{focused:!0}),{success:!0,windowId:o.windowId}}case"WINDOW_CLOSE":{if(!o.windowId)throw new Error("No windowId provided");return await chrome.windows.remove(o.windowId),{success:!0,windowId:o.windowId}}case"WINDOW_RESIZE":{if(!o.windowId)throw new Error("No windowId provided");const e={};o.width&&(e.width=o.width),o.height&&(e.height=o.height),o.left!==void 0&&(e.left=o.left),o.top!==void 0&&(e.top=o.top),o.state&&(e.state=o.state);const r=await chrome.windows.update(o.windowId,e);return{success:!0,windowId:o.windowId,width:r.width,height:r.height}}default:throw new Error(`Unknown message type: ${o.type}`)}}chrome.runtime.onInstalled.addListener(o=>{C("Extension installed/updated:",o.reason)});const he=new Set(["LIST_TABS","NEW_TAB","TABS_NEW","CLOSE_TABS","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","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","EMULATE_DEVICE_LIST"]);J(async o=>{let i=o.tabId;const t=o.windowId,e=o.type?.startsWith("DIALOG_"),r=!he.has(o.type);let n=!1;if(i&&!e)try{await chrome.tabs.get(i)}catch{throw new Error(`Invalid tab ID: ${i}. Use 'surf tab.list' to see available tabs.`)}else if(!i&&r){let c,u;if(t){c=await chrome.tabs.query({active:!0,windowId:t}),u=c[0];const d=h=>!h||h.startsWith("chrome://")||h.startsWith("chrome-extension://")||h==="about:blank";if((!u||d(u.url))&&(c=await chrome.tabs.query({windowId:t}),u=c.find(h=>!d(h.url))),!u?.id){const h=await chrome.tabs.create({windowId:t,url:"data:text/html,<html><head><title>Surf</title></head><body></body></html>",active:!0});if(!h.id)throw new Error(`Failed to create tab in window ${t}`);await new Promise(f=>setTimeout(f,100)),u=h,n=!0}}else if(c=await chrome.tabs.query({active:!0,lastFocusedWindow:!0}),u=c[0],(!u||u.url?.startsWith("chrome-extension://"))&&(c=await chrome.tabs.query({active:!0,currentWindow:!0}),u=c[0]),(!u||u.url?.startsWith("chrome-extension://")||u.url?.startsWith("chrome://"))&&(c=await chrome.tabs.query({active:!0}),u=c.find(d=>!d.url?.startsWith("chrome-extension://")&&!d.url?.startsWith("chrome://"))),!u?.id)throw new Error("No active tab found. Use 'surf tab.new <url>' to create one, or 'surf tab.list' to see available tabs.");i=u.id}const s=await ee({...o,tabId:i},{}),a=[];return n&&a.push(`Auto-created tab in window ${t} (no usable tabs existed). Navigate to your target URL.`),{...s,_resolvedTabId:i,_hint:a.length>0?a.join(" "):void 0}});
156
156
  //# sourceMappingURL=index.js.map