surf-cli 2.5.2 → 2.6.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.
package/README.md CHANGED
@@ -72,10 +72,20 @@ surf tab.list
72
72
  ```bash
73
73
  surf install <extension-id> # Chrome (default)
74
74
  surf install <extension-id> --browser brave # Brave
75
+ surf install <extension-id> --browser helium # Helium
75
76
  surf install <extension-id> --browser all # All supported browsers
76
77
  ```
77
78
 
78
- Supported: `chrome`, `chromium`, `brave`, `edge`, `arc`
79
+ Supported: `chrome`, `chromium`, `brave`, `edge`, `arc`, `helium`
80
+
81
+ **Package Manager Installs (Nix, Homebrew, etc.)**
82
+ If surf is installed via a package manager that stores binaries in non-standard locations, set these environment variables before running `surf install`:
83
+ ```bash
84
+ export SURF_NODE_PATH=/path/to/node
85
+ export SURF_HOST_PATH=/path/to/native/host.cjs
86
+ export SURF_EXTENSION_PATH=/path/to/extension/dist
87
+ ```
88
+ See [Environment Variables](#environment-variables) for details.
79
89
 
80
90
  ### Uninstall
81
91
 
@@ -315,9 +325,20 @@ surf grok "find viral AI posts" --deep-search # DeepSearch mode
315
325
  surf grok "quick question" --model fast # Models: auto, fast, expert, thinking
316
326
  surf grok --validate # Check UI and available models
317
327
  surf grok --validate --save-models # Save discovered models to settings
328
+
329
+ # AI Studio (queries aistudio.google.com using your Google login)
330
+ surf aistudio "explain quantum computing"
331
+ surf aistudio "redteam this" --with-page # Include page context
332
+ surf aistudio "quick answer" --model gemini-3-flash-preview # Model selection
333
+
334
+ # AI Studio App Builder (generates full web apps from a prompt)
335
+ surf aistudio.build "build a portfolio site"
336
+ surf aistudio.build "todo app" --model gemini-3.1-pro-preview # Model override
337
+ surf aistudio.build "crm dashboard" --output ./out # Extract zip to directory
338
+ surf aistudio.build "game" --keep-open --timeout 600 # Keep tab open, 10min timeout
318
339
  ```
319
340
 
320
- Each AI tool uses your existing browser login - no API keys needed. Just be logged into the respective service in Chrome (chatgpt.com, gemini.google.com, perplexity.ai, or x.com).
341
+ Each AI tool uses your existing browser login - no API keys needed. Just be logged into the respective service in Chrome (chatgpt.com, gemini.google.com, perplexity.ai, x.com, or aistudio.google.com).
321
342
 
322
343
  **Grok troubleshooting:** If queries fail, run `surf grok --validate` to check if the UI structure changed. Use `--save-models` to update the model cache in `surf.json`. Default model is "thinking" (Grok 4.1 Thinking).
323
344
 
@@ -511,6 +532,26 @@ surf workflow.validate ./my-workflow.json
511
532
  --network-path <path> # Custom path for network logs (default: /tmp/surf, or SURF_NETWORK_PATH env)
512
533
  ```
513
534
 
535
+ ## Environment Variables
536
+
537
+ ```bash
538
+ SURF_NETWORK_PATH # Path for network capture logs (default: /tmp/surf)
539
+ SURF_NODE_PATH # Path to node binary (for native host wrapper)
540
+ SURF_HOST_PATH # Path to native/host.cjs (for native host wrapper)
541
+ SURF_EXTENSION_PATH # Path to extension dist/ directory
542
+ ```
543
+
544
+ **Use cases:**
545
+ - `SURF_NODE_PATH` / `SURF_HOST_PATH`: Package manager installs (e.g., Nix) that store binaries in non-standard locations
546
+ - `SURF_EXTENSION_PATH`: Package managers that create stable symlinks instead of changing paths on reinstall
547
+
548
+ **Example (Nix):**
549
+ ```bash
550
+ export SURF_NODE_PATH=~/.local/share/surf-cli/node
551
+ export SURF_HOST_PATH=~/.local/share/surf-cli/native/host.cjs
552
+ export SURF_EXTENSION_PATH=~/.local/share/surf-cli/extension
553
+ ```
554
+
514
555
  ## Socket API
515
556
 
516
557
  For programmatic integration, send JSON to `/tmp/surf.sock`:
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Surf",
4
- "version": "0.1.0",
4
+ "version": "2.5.2",
5
5
  "description": "Browser automation CLI for AI agents",
6
6
  "options_page": "options/options.html",
7
7
  "icons": {
@@ -1,11 +1,11 @@
1
- var ge=Object.defineProperty;var Se=(t,i,e)=>i in t?ge(t,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[i]=e;var O=(t,i,e)=>Se(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(m){return Promise.all(m.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(m=>{if(m=Ie(m),m in ue)return;ue[m]=!0;const E=m.endsWith(".css"),T=E?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${m}"]${T}`))return;const g=document.createElement("link");if(g.rel=E?"stylesheet":ve,E||(g.as="script"),g.crossOrigin="",g.href=m,y&&g.setAttribute("nonce",y),document.head.appendChild(g),E)return new Promise((p,v)=>{g.addEventListener("load",p),g.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${m}`)))})}))}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}},N=class N{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(){N.debuggerListenerRegistered||(N.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 m,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=(m=e.stackTrace)==null?void 0:m.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,S]of Object.entries(s.headers))l[v]=String(S);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,m=`r_${d}_${y}`,E={};if(s.headers)for(const[v,S]of Object.entries(s.headers))E[v]=String(S);const T=s.postData,g=T?T.length:void 0,p={id:m,ts:d,method:s.method,url:s.url,origin:this.extractOrigin(s.url),requestHeaders:E,requestBody:T,requestBodySize:g,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,m,E,T,g;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,(m=e.response)!=null&&m.headers){const v={};for(const[S,k]of Object.entries(e.response.headers))v[S]=String(k);s.responseHeaders=v}const p=this.networkCallbacks.get(i);if(p){const v=this.networkRequestStartTimes.get(e.requestId),S=Date.now(),k=v?Math.round(S-v):void 0;for(const x of p.values())x({method:s.method,url:s.url,status:s.status,duration:k,timestamp:S})}}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),S=e.timestamp?e.timestamp*1e3:Date.now();v&&(l.ttfb=Math.round(S-v)),l.status=p.status,l.statusText=p.statusText,l.mimeType=p.mimeType;const k={};if(p.headers)for(const[x,U]of Object.entries(p.headers))k[x]=String(U);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")||(g=p.mimeType)!=null&&g.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),m=Date.now(),E=y?Math.round(m-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:m})}}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)<=N.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>N.MAX_INLINE_BODY_SIZE&&(s.responseBody=s.responseBody.slice(0,N.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)<=N.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>N.MAX_INLINE_BODY_SIZE&&(l.responseBody=l.responseBody.slice(0,N.MAX_INLINE_BODY_SIZE),l.flags.push("truncated"))}catch{}}extractOrigin(i){try{return new URL(i).origin}catch{return""}}isStaticAsset(i){return i?N.STATIC_ASSET_TYPES.has(i):!1}isBinaryType(i){return i?N.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} })())`,m=await this.send(i,"Runtime.evaluate",{expression:y,contextId:f.executionContextId,returnByValue:!0,awaitPromise:!0});if(m.exceptionDetails)return{success:!1,error:m.exceptionDetails.text||((s=m.exceptionDetails.exception)==null?void 0:s.description)||"Evaluation failed"};try{return{success:!0,result:JSON.parse((d=m.result)==null?void 0:d.value)}}catch{return{success:!0,result:(l=m.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(m=>setTimeout(m,12)),await this.dispatchMouseEvent(i,"mouseReleased",e,n,{button:s,buttons:0,clickCount:y,modifiers:l}),y<d&&await new Promise(m=>setTimeout(m,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(N,"debuggerListenerRegistered",!1),O(N,"MAX_INLINE_BODY_SIZE",16*1024),O(N,"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(N,"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=N,re=!1,pe=!1;const ae=[];chrome.storage.local.get("debugMode").then(({debugMode:t})=>{if(re=!!t,pe=!0,re)for(const i of ae)console.log("[Surf]",...i);ae.length=0});chrome.storage.onChanged.addListener((t,i)=>{i==="local"&&t.debugMode&&(re=!!t.debugMode.newValue)});function q(...t){if(!pe){ae.push(t);return}re&&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 Ne=0;function Ae(){return`screenshot_${++Ne}_${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,g=Math.round(E.bounds.x*f),p=Math.round(E.bounds.y*f),v=Math.round(E.bounds.width*f),S=Math.round(E.bounds.height*f);if(v<1||S<1)continue;l.strokeStyle=T,l.lineWidth=2,l.setLineDash([4,4]),l.strokeRect(g,p,v,S),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 U=l.measureText(k).width,F=4,M=U+F*2,A=x+F*2;let r=g+Math.floor((v-M)/2),o=p+2;(v<60||S<30)&&(o=p-A-2<0?p+S+2:p-A-2),r=Math.max(0,Math.min(d.width-M,r)),o=Math.max(0,Math.min(d.height-A,o)),l.fillStyle=T,l.fillRect(r,o,M,A),l.strokeStyle="white",l.lineWidth=1,l.strokeRect(r,o,M,A),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
+ 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,`(() => ({
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,m=[];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),A=be(M.base64);m.push(await createImageBitmap(A)),E+=s}await u.evaluateScript(t,`window.scrollTo(0, ${y})`);const T=Math.round(l*f),g=Math.round(d*f),p=new OffscreenCanvas(T,g),v=p.getContext("2d");if(!v)throw new Error("Failed to get canvas context");let S=0;const k=Math.round(s*f);for(let M=0;M<m.length;M++){const A=m[M],r=g-S,o=Math.min(k,r);v.drawImage(A,0,0,A.width,o,0,S,A.width,o),S+=o,A.close()}const x=await p.convertToBlob({type:"image/png"});return{base64:await me(x),width:T,height:g}}const G=new Map,B=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 B)e===t&&B.delete(i);for(const[i,e]of $)e===t&&$.delete(i)});async function ie(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,m,E,T,g,p,v,S,k,x,U,F,M,A;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=Ae();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)==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,`(() => {
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();
@@ -140,7 +140,7 @@ var ge=Object.defineProperty;var Se=(t,i,e)=>i in t?ge(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((m=t.options)!=null&&m.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,b=c&&document.querySelector(c)||w();return b?(h==="bottom"?b.scrollTop=b.scrollHeight:h==="top"?b.scrollTop=0:typeof h=="number"&&(b.scrollTop=h),{scrollTop:b.scrollTop,scrollHeight:b.scrollHeight,clientHeight:b.clientHeight,atBottom:b.scrollTop+b.clientHeight>=b.scrollHeight-10,atTop:b.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((g=(await chrome.scripting.executeScript({target:{tabId:e},func:a,args:[r,o]}))[0])==null?void 0:g.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"&&((S=i.tab)!=null&&S.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 b of r){const I=Date.now(),_=[];let R,Z,P;try{Z=new URL(b).hostname.replace(/[^a-zA-Z0-9.-]/g,"_");const K=await chrome.tabs.create({url:b,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,oe=_.length===0?"pass":"fail";if(oe==="pass"?c++:w++,h.push({url:b,status:oe,time:H,errors:_,...R&&{screenshotBase64:R,hostname:Z}}),a&&oe==="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[b,I]of Object.entries(o)){const _=b.toLowerCase(),R=_.replace(/\s+/g,"");(_.includes(c)||c.includes(R))&&(!w||b.length>w.name.length)&&(w={name:b,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(b=>b.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 b of c)try{const I=await chrome.tabs.sendMessage(e,{type:"GET_FRAME_NAME"},{frameId:b.frameId});if((I==null?void 0:I.name)===o){w=b;break}}catch{}if(!w)throw new Error(`Frame with name "${o}" not found`)}else if(r)try{const b=await chrome.tabs.sendMessage(e,{type:"GET_FRAME_BY_SELECTOR",selector:r},{frameId:0});if(b!=null&&b.error)throw new Error(b.error);b!=null&&b.url&&(w=c.find(I=>I.url===b.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,b=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>b&&(b=I.ts)}return{stats:{totalRequests:r.length,totalSize:c,uniqueOrigins:Object.keys(o).length,startTime:w===1/0?null:w,duration:b&&w!==1/0?b-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 B.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=B.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 B.delete(t.name),{error:`Tab "${t.name}" no longer exists`}}}case"TABS_LIST_NAMED":{const r=[];for(const[o,a]of B)try{const h=await chrome.tabs.get(a);r.push({name:o,tabId:a,url:h.url,title:h.title})}catch{B.delete(o)}return{tabs:r}}case"TABS_UNREGISTER":{if(!t.name)throw new Error("No name provided");return B.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=`(() => {
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
144
  const elements = document.querySelectorAll(${JSON.stringify(r)});
145
145
  if (elements.length === 0) return { error: "No elements match selector" };
146
146
  if (${o} >= elements.length) return { error: "Index " + ${o} + " out of range (found " + elements.length + " elements)" };
@@ -152,5 +152,5 @@ var ge=Object.defineProperty;var Se=(t,i,e)=>i in t?ge(t,i,{enumerable:!0,config
152
152
  y: rect.top + rect.height / 2,
153
153
  count: elements.length
154
154
  };
155
- })()`,c=(U=(await u.evaluateScript(e,a)).result)==null?void 0:U.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 ie(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 ie(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 ie(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"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://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"))&&((A=c.domain)!=null&&A.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","WINDOW_NEW","WINDOW_LIST","WINDOW_FOCUS","WINDOW_CLOSE","WINDOW_RESIZE","EMULATE_DEVICE_LIST"]);Ee(async t=>{var y,m,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 g,p;if(e){g=await chrome.tabs.query({active:!0,windowId:e}),p=g[0];const v=S=>!S||S.startsWith("chrome://")||S.startsWith("chrome-extension://")||S==="about:blank";if((!p||v(p.url))&&(g=await chrome.tabs.query({windowId:e}),p=g.find(S=>!v(S.url))),!(p!=null&&p.id)){const S=await chrome.tabs.create({windowId:e,url:"data:text/html,<html><head><title>Surf</title></head><body></body></html>",active:!0});if(!S.id)throw new Error(`Failed to create tab in window ${e}`);await new Promise(k=>setTimeout(k,100)),p=S,d=!0}}else if(g=await chrome.tabs.query({active:!0,lastFocusedWindow:!0}),p=g[0],(!p||(m=p.url)!=null&&m.startsWith("chrome-extension://"))&&(g=await chrome.tabs.query({active:!0,currentWindow:!0}),p=g[0]),(!p||(E=p.url)!=null&&E.startsWith("chrome-extension://")||(T=p.url)!=null&&T.startsWith("chrome://"))&&(g=await chrome.tabs.query({active:!0}),p=g.find(v=>{var S,k;return!((S=v.url)!=null&&S.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
+ })()`,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}});
156
156
  //# sourceMappingURL=index.js.map