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