surf-cli 2.7.0 → 2.7.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.
|
@@ -140,7 +140,7 @@ const te="modulepreload",re=function(o){return"/"+o},$={},V=function(i,t,e){let
|
|
|
140
140
|
url: location.href,
|
|
141
141
|
title: document.title
|
|
142
142
|
};
|
|
143
|
-
})()`)).result?.value||{error:"Failed to get page state"}}case"EXECUTE_SCROLL":{if(!t)throw new Error("No tabId provided");const e=o.deltaX||0,r=o.deltaY||0;try{const n=await l.getViewportSize(t),s=o.x??n.width/2,a=o.y??n.height/2;await l.scroll(t,s,a,e,r)}catch{try{const n=(s,a)=>(window.scrollBy(s,a),{scrollX:window.scrollX,scrollY:window.scrollY});await chrome.scripting.executeScript({target:{tabId:t},func:n,args:[e,r]})}catch{return{error:"Cannot scroll on this page (restricted)"}}}return{success:!0}}case"EXECUTE_KEY":{if(!t)throw new Error("No tabId provided");const e=o.key;if(!e)throw new Error("No key provided");return e.includes("+")?await l.pressKeyChord(t,e):await l.pressKey(t,e),{success:!0}}case"EXECUTE_NAVIGATE":{if(!t)throw new Error("No tabId provided");if(!o.url)throw new Error("No url provided");const e=new Promise(r=>{k.set(t,r),setTimeout(()=>{k.has(t)&&(k.delete(t),r())},3e4)});return await chrome.tabs.update(t,{url:o.url}),await e,await new Promise(r=>setTimeout(r,500)),{success:!0}}case"GET_VIEWPORT_SIZE":{if(!t)throw new Error("No tabId provided");return await l.getViewportSize(t)}case"READ_PAGE":{if(!t)throw new Error("No tabId provided");const e=b(t);try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(n=>setTimeout(n,50));let r;try{r=await chrome.tabs.sendMessage(t,{type:"GENERATE_ACCESSIBILITY_TREE",options:o.options||{}},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}if(o.options?.includeText)try{const n=await chrome.tabs.sendMessage(t,{type:"GET_PAGE_TEXT"},{frameId:e});n?.text&&(r.text=n.text)}catch{}if(o.options?.includeScreenshot)try{const n=await l.captureScreenshot(t);return{...r,screenshot:n}}catch{return{...r,screenshotError:"Failed to capture screenshot"}}return r}case"GET_ELEMENT_COORDINATES":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_COORDINATES",ref:o.ref},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"FORM_INPUT":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"FORM_INPUT",ref:o.ref,value:o.value},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"EVAL_IN_PAGE":{if(!t)throw new Error("No tabId provided");if(!o.code)throw new Error("No code provided");try{return await chrome.tabs.sendMessage(t,{type:"EVAL_IN_PAGE",code:o.code},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SCROLL_TO_ELEMENT":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"SCROLL_TO_ELEMENT",ref:o.ref},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SCROLL_TO_POSITION":{if(!t)throw new Error("No tabId provided");const e=o.position;if(e===void 0)throw new Error('position required ("top", "bottom", or number)');const r=o.selector,n=(s,a)=>{const c=()=>[...document.querySelectorAll("*")].filter(h=>h.scrollHeight>h.clientHeight&&h.clientHeight>200).sort((h,f)=>f.scrollHeight-h.scrollHeight)[0]||document.documentElement,u=a&&document.querySelector(a)||c();return u?(s==="bottom"?u.scrollTop=u.scrollHeight:s==="top"?u.scrollTop=0:typeof s=="number"&&(u.scrollTop=s),{scrollTop:u.scrollTop,scrollHeight:u.scrollHeight,clientHeight:u.clientHeight,atBottom:u.scrollTop+u.clientHeight>=u.scrollHeight-10,atTop:u.scrollTop<10}):{error:"No scrollable container found"}};try{const s=`(${n.toString()})(${JSON.stringify(e)}, ${JSON.stringify(r)})`;return(await l.evaluateScript(t,s)).result?.value||{error:"Script failed"}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:t},func:n,args:[e,r]}))[0]?.result||{error:"Script failed"}}catch{return{error:"Cannot scroll on this page (restricted)"}}}}case"GET_SCROLL_INFO":{if(!t)throw new Error("No tabId provided");const e=o.selector,r=n=>{const s=()=>[...document.querySelectorAll("*")].filter(d=>d.scrollHeight>d.clientHeight&&d.clientHeight>200).sort((d,h)=>h.scrollHeight-d.scrollHeight)[0]||document.documentElement,a=n&&document.querySelector(n)||s();if(!a)return{error:"No scrollable container found"};const c=a.scrollHeight-a.clientHeight;return{scrollTop:a.scrollTop,scrollHeight:a.scrollHeight,clientHeight:a.clientHeight,atBottom:a.scrollTop+a.clientHeight>=a.scrollHeight-10,atTop:a.scrollTop<10,scrollPercentage:c>0?Math.round(a.scrollTop/c*100):100}};try{const n=`(${r.toString()})(${JSON.stringify(e)})`;return(await l.evaluateScript(t,n)).result?.value||{error:"Script failed"}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:t},func:r,args:[e]}))[0]?.result||{error:"Script failed"}}catch{return{error:"Cannot get scroll info on this page (restricted)"}}}}case"GET_PAGE_TEXT":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"GET_PAGE_TEXT"},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_ROLE":{if(!t)throw new Error("No tabId provided");if(!o.role)throw new Error("role required");const e=b(t);try{const r=await chrome.tabs.sendMessage(t,{type:"LOCATE_ROLE",role:o.role,name:o.name,all:o.all},{frameId:e});return r.error?r:o.action&&r.ref?await G(t,r.ref,o.action,o.value,l,e):r}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_TEXT":{if(!t)throw new Error("No tabId provided");if(!o.text)throw new Error("text required");const e=b(t);try{const r=await chrome.tabs.sendMessage(t,{type:"LOCATE_TEXT",text:o.text,exact:o.exact},{frameId:e});return r.error?r:o.action&&r.ref?await G(t,r.ref,o.action,o.value,l,e):r}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_LABEL":{if(!t)throw new Error("No tabId provided");if(!o.label)throw new Error("label required");const e=b(t);try{const r=await chrome.tabs.sendMessage(t,{type:"LOCATE_LABEL",label:o.label},{frameId:e});return r.error?r:o.action&&r.ref?await G(t,r.ref,o.action,o.value,l,e):r}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"GET_ELEMENT_STYLES":{if(!t)throw new Error("No tabId provided");if(!o.selector)throw new Error("selector required");const e=b(t);try{return await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_STYLES",selector:o.selector},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SELECT_OPTION":{if(!t)throw new Error("No tabId provided");if(!o.selector)throw new Error("selector required");if(!o.values)throw new Error("values required");const e=b(t);try{return await chrome.tabs.sendMessage(t,{type:"SELECT_OPTION",selector:o.selector,values:o.values,by:o.by||"value"},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SHOW_AGENT_INDICATORS":case"HIDE_AGENT_INDICATORS":case"SHOW_STATIC_INDICATOR":case"HIDE_STATIC_INDICATOR":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:o.type})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"STOP_AGENT":{const e=o.fromTabId;let r;return e==="CURRENT_TAB"&&i.tab?.id?r=i.tab.id:typeof e=="number"&&(r=e),r&&chrome.runtime.sendMessage({type:"STOP_AGENT",targetTabId:r}),{success:!0}}case"DISMISS_STATIC_INDICATOR":return{success:!0};case"STATIC_INDICATOR_HEARTBEAT":return{success:!0};case"CLICK_REF":{if(!t)throw new Error("No tabId provided");try{const e=await chrome.tabs.sendMessage(t,{type:"CLICK_ELEMENT",ref:o.ref,button:o.button||"left"},{frameId:b(t)});return e.error?{error:e.error}:{success:!0}}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"HOVER_REF":{if(!t)throw new Error("No tabId provided");try{const e=await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_COORDINATES",ref:o.ref},{frameId:b(t)});return e.error?{error:e.error}:(await l.hover(t,e.x,e.y),{success:!0})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"PING":return{success:!0,status:"connected"};case"HEALTH_CHECK_URL":{if(!o.url)throw new Error("No url provided");const e=o.timeout||3e4,r=o.expect||200,n=Date.now(),s=500;let a=null;for(;Date.now()-n<e;){try{const c=await fetch(o.url,{method:"GET"});if(await c.text(),c.status===r)return{success:!0,status:c.status,time:Date.now()-n};a=`Got status ${c.status}`}catch(c){a=c instanceof Error?c.message:String(c)}await new Promise(c=>setTimeout(c,s))}return{error:`Timeout waiting for ${o.url} to return ${r}`,lastError:a,time:Date.now()-n}}case"SMOKE_TEST":{const e=o.urls||[],r=o.savePath!==void 0,n=o.failFast||!1;if(e.length===0)return{error:"No URLs provided for smoke test"};const s=[];let a=0,c=0;for(const u of e){const d=Date.now(),h=[];let f,w,p;try{w=new URL(u).hostname.replace(/[^a-zA-Z0-9.-]/g,"_");const S=await chrome.tabs.create({url:u,active:!1});if(!S.id)throw new Error("Failed to create tab");p=S.id;try{await l.enableConsoleTracking(p)}catch{}await new Promise(m=>{const y=T=>{T.tabId===p&&T.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(y),chrome.webNavigation.onErrorOccurred.removeListener(g),m())},g=T=>{T.tabId===p&&T.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(y),chrome.webNavigation.onErrorOccurred.removeListener(g),h.push(`Navigation error: ${T.error}`),m())};chrome.webNavigation.onCompleted.addListener(y),chrome.webNavigation.onErrorOccurred.addListener(g),setTimeout(()=>{chrome.webNavigation.onCompleted.removeListener(y),chrome.webNavigation.onErrorOccurred.removeListener(g),h.push("Navigation timeout (30s)"),m()},3e4)}),await new Promise(m=>setTimeout(m,2e3));const N=l.getConsoleMessages(p,{onlyErrors:!0,limit:50});for(const m of N)h.push(`[${m.type}] ${m.text}`);if(r)try{f=(await l.captureScreenshot(p)).base64}catch{}}catch(S){h.push(S instanceof Error?S.message:String(S))}finally{if(p)try{await chrome.tabs.remove(p)}catch{}}const E=Date.now()-d,_=h.length===0?"pass":"fail";if(_==="pass"?a++:c++,s.push({url:u,status:_,time:E,errors:h,...f&&{screenshotBase64:f,hostname:w}}),n&&_==="fail")break}return{results:s,summary:{pass:a,fail:c,total:s.length},savePath:o.savePath}}case"WAIT_FOR_ELEMENT":{if(!t)throw new Error("No tabId provided");if(!o.selector)throw new Error("No selector provided");const e=b(t);try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(r=>setTimeout(r,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_ELEMENT",selector:o.selector,state:o.state||"visible",timeout:o.timeout||2e4},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_URL":{if(!t)throw new Error("No tabId provided");if(!o.pattern)throw new Error("No URL pattern provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_URL",pattern:o.pattern,timeout:o.timeout||2e4},{frameId:0})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_NETWORK_IDLE":{if(!t)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_NETWORK_IDLE",timeout:o.timeout||1e4},{frameId:0})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_DOM_STABLE":{if(!t)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_DOM_STABLE",stable:o.stable||100,timeout:o.timeout||5e3},{frameId:0})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"},{frameId:0})}catch{}}}case"DIALOG_ACCEPT":{if(!t)throw new Error("No tabId provided");return await l.handleDialog(t,!0,o.text)}case"DIALOG_DISMISS":{if(!t)throw new Error("No tabId provided");return await l.handleDialog(t,!1)}case"DIALOG_INFO":{if(!t)throw new Error("No tabId provided");const e=l.getDialogInfo(t);return e?{hasDialog:!0,type:e.type,message:e.message,defaultPrompt:e.defaultPrompt}:{hasDialog:!1}}case"EMULATE_NETWORK":{if(!t)throw new Error("No tabId provided");if(!o.preset)throw new Error("No preset provided");const e=await l.emulateNetwork(t,o.preset);if(!e.success)throw new Error(e.error);return{success:!0,preset:o.preset}}case"EMULATE_CPU":{if(!t)throw new Error("No tabId provided");if(o.rate===void 0)throw new Error("No rate provided");const e=await l.emulateCPU(t,o.rate);if(!e.success)throw new Error(e.error);return{success:!0,rate:o.rate}}case"EMULATE_GEO":{if(!t)throw new Error("No tabId provided");if(o.clear){const r=await l.clearGeolocation(t);if(!r.success)throw new Error(r.error);return{success:!0,cleared:!0}}if(o.latitude===void 0||o.longitude===void 0)throw new Error("Latitude and longitude required");const e=await l.emulateGeolocation(t,o.latitude,o.longitude,o.accuracy);if(!e.success)throw new Error(e.error);return{success:!0,latitude:o.latitude,longitude:o.longitude}}case"EMULATE_DEVICE_LIST":return{devices:["iPhone 12","iPhone 13","iPhone 14","iPhone 14 Pro","iPhone 14 Pro Max","iPhone SE","iPad","iPad Pro","iPad Mini","Pixel 5","Pixel 6","Pixel 7","Pixel 7 Pro","Galaxy S21","Galaxy S22","Galaxy S23","Galaxy Tab S7","Nest Hub","Nest Hub Max"]};case"EMULATE_DEVICE":{if(!t)throw new Error("No tabId provided");const e=o.device;if(e.toLowerCase()==="reset"){const a=await l.clearDeviceEmulation(t);if(!a.success)throw new Error(a.error);return{success:!0,message:"Device emulation reset"}}const r={"iPhone 12":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"},"iPhone 13":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1"},"iPhone 14":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"},"iPhone 14 Pro":{width:393,height:852,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"},"iPhone 14 Pro Max":{width:430,height:932,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"},"iPhone SE":{width:375,height:667,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1"},iPad:{width:768,height:1024,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"},"iPad Pro":{width:1024,height:1366,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"},"iPad Mini":{width:768,height:1024,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"},"Pixel 5":{width:393,height:851,deviceScaleFactor:2.75,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36"},"Pixel 6":{width:412,height:915,deviceScaleFactor:2.625,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36"},"Pixel 7":{width:412,height:915,deviceScaleFactor:2.625,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36"},"Pixel 7 Pro":{width:412,height:892,deviceScaleFactor:3.5,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 13; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36"},"Galaxy S21":{width:360,height:800,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36"},"Galaxy S22":{width:360,height:780,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 12; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36"},"Galaxy S23":{width:360,height:780,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 13; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36"},"Galaxy Tab S7":{width:800,height:1280,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Safari/537.36"},"Nest Hub":{width:1024,height:600,deviceScaleFactor:2,mobile:!1,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666"},"Nest Hub Max":{width:1280,height:800,deviceScaleFactor:2,mobile:!1,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666"}};let n=r[e];if(!n){const a=e.toLowerCase();let c=null;for(const[u,d]of Object.entries(r)){const h=u.toLowerCase(),f=h.replace(/\s+/g,"");(h.includes(a)||a.includes(f))&&(!c||u.length>c.name.length)&&(c={name:u,preset:d})}c&&(n=c.preset)}if(!n)throw new Error(`Unknown device: ${e}. Use --list to see available devices.`);const s=await l.emulateDevice(t,n);if(!s.success)throw new Error(s.error);return{success:!0,device:e}}case"EMULATE_VIEWPORT":{if(!t)throw new Error("No tabId provided");if(!o.width&&!o.height)throw new Error("--width or --height required");const e=await l.emulateViewport(t,{width:o.width,height:o.height,deviceScaleFactor:o.deviceScaleFactor,mobile:o.mobile});if(!e.success)throw new Error(e.error);return{success:!0,width:o.width,height:o.height}}case"EMULATE_TOUCH":{if(!t)throw new Error("No tabId provided");const e=await l.emulateTouch(t,o.enabled);if(!e.success)throw new Error(e.error);return{success:!0,enabled:o.enabled}}case"FORM_FILL":{if(!t)throw new Error("No tabId provided");if(!o.data)throw new Error("No data provided");return await chrome.tabs.sendMessage(t,{type:"FORM_FILL",data:o.data},{frameId:b(t)})}case"PERF_START":{if(!t)throw new Error("No tabId provided");const e=await l.startPerformanceTrace(t,o.categories);if(!e.success)throw new Error(e.error);return{success:!0,message:"Performance tracing started"}}case"PERF_STOP":{if(!t)throw new Error("No tabId provided");const e=await l.stopPerformanceTrace(t);if(!e.success)throw new Error(e.error);return{success:!0,metrics:e.metrics}}case"PERF_METRICS":{if(!t)throw new Error("No tabId provided");const e=await l.getPerformanceMetrics(t);if(!e.success)throw new Error(e.error);return{success:!0,metrics:e.metrics}}case"UPLOAD_FILE":{if(!t)throw new Error("No tabId provided");if(!o.ref)throw new Error("No ref provided");if(!o.files||!o.files.length)throw new Error("No files provided");const e=await chrome.tabs.sendMessage(t,{type:"GET_FILE_INPUT_SELECTOR",ref:o.ref},{frameId:b(t)});if(e.error)throw new Error(e.error);const r=await l.setFileInputBySelector(t,e.selector,o.files);if(!r.success)throw new Error(r.error);return{success:!0,filesSet:o.files.length}}case"WAIT_FOR_LOAD":{if(!t)throw new Error("No tabId provided");const e=await l.waitForLoad(t,o.timeout||3e4);if(!e.success)throw new Error(e.error);return{success:!0,readyState:e.readyState}}case"GET_FRAMES":{if(!t)throw new Error("No tabId provided");const e=await l.getFrames(t);if(!e.success)throw new Error(e.error);return{success:!0,frames:e.frames}}case"FRAME_SWITCH":{if(!t)throw new Error("No tabId provided");const{selector:e,name:r,index:n}=o;if(!e&&!r&&n===void 0)throw new Error("--selector, --name, or --index required");const s=await chrome.webNavigation.getAllFrames({tabId:t});if(!s||s.length===0)throw new Error("No frames found in tab");const a=s.filter(u=>u.frameId!==0);if(a.length===0)throw new Error("No iframes found on this page");let c=null;if(n!==void 0){if(n<0||n>=a.length)throw new Error(`Frame index ${n} out of range. Found ${a.length} frame(s).`);c=a[n]}else if(r){for(const u of a)try{if((await chrome.tabs.sendMessage(t,{type:"GET_FRAME_NAME"},{frameId:u.frameId}))?.name===r){c=u;break}}catch{}if(!c)throw new Error(`Frame with name "${r}" not found`)}else if(e)try{const u=await chrome.tabs.sendMessage(t,{type:"GET_FRAME_BY_SELECTOR",selector:e},{frameId:0});if(u?.error)throw new Error(u.error);u?.url&&(c=a.find(d=>d.url===u.url)||null),!c&&a.length===1&&(c=a[0])}catch{throw new Error(`Could not find frame with selector "${e}"`)}if(!c)throw new Error("Frame not found");return F.set(t,c.frameId),{success:!0,frameId:c.frameId,url:c.url}}case"FRAME_MAIN":{if(!t)throw new Error("No tabId provided");return F.delete(t),{success:!0,message:"Returned to main frame"}}case"EVALUATE_IN_FRAME":{if(!t)throw new Error("No tabId provided");if(!o.frameId)throw new Error("No frameId provided");if(!o.code)throw new Error("No code provided");const e=await l.evaluateInFrame(t,o.frameId,o.code);if(!e.success)throw new Error(e.error);return{value:e.result}}case"EXECUTE_JAVASCRIPT":{if(!t)throw new Error("No tabId provided");if(!o.code)throw new Error("No code provided");try{await l.evaluateScript(t,"if(!window.piHelpers){const piHelpers={wait(ms){return new Promise(r=>setTimeout(r,ms))},async waitForSelector(sel,opts={}){const{state='visible',timeout=20000}=opts;const isVis=el=>el&&getComputedStyle(el).display!=='none'&&getComputedStyle(el).visibility!=='hidden'&&getComputedStyle(el).opacity!=='0'&&el.offsetWidth>0&&el.offsetHeight>0;const chk=()=>{const el=document.querySelector(sel);switch(state){case'attached':return el;case'detached':return el?null:document.body;case'hidden':return(!el||!isVis(el))?(el||document.body):null;default:return isVis(el)?el:null}};return new Promise((res,rej)=>{const r=chk();if(r){res(state==='detached'||state==='hidden'?null:r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(state==='detached'||state==='hidden'?null:r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['style','class','hidden']})})},async waitForText(text,opts={}){const{selector,timeout=20000}=opts;const chk=()=>{const root=selector?document.querySelector(selector):document.body;if(!root)return null;const w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);while(w.nextNode())if(w.currentNode.textContent?.includes(text))return w.currentNode.parentElement;return null};return new Promise((res,rej)=>{const r=chk();if(r){res(r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,characterData:true})})},async waitForHidden(sel,t=20000){await piHelpers.waitForSelector(sel,{state:'hidden',timeout:t})},getByRole(role,opts={}){const{name}=opts;const roles={button:['button','input[type=button]','input[type=submit]','input[type=reset]'],link:['a[href]'],textbox:['input:not([type])','input[type=text]','input[type=email]','input[type=password]','textarea'],checkbox:['input[type=checkbox]'],radio:['input[type=radio]'],combobox:['select'],heading:['h1','h2','h3','h4','h5','h6']};const cands=[...document.querySelectorAll('[role='+role+']')];if(roles[role])roles[role].forEach(s=>cands.push(...document.querySelectorAll(s+':not([role])')));if(!name)return cands[0]||null;const n=name.toLowerCase().trim();for(const el of cands){const l=el.getAttribute('aria-label')?.toLowerCase().trim();const t=el.textContent?.toLowerCase().trim();if(l===n||t===n||l?.includes(n)||t?.includes(n))return el}return null}};window.__piHelpers=piHelpers;window.piHelpers=piHelpers}");const n=`(async () => { 'use strict'; ${o.code.replace(/`/g,"\\`").replace(/\$/g,"\\$")} })()`,s=await l.evaluateScript(t,n);if(s.exceptionDetails)return{error:s.exceptionDetails.exception?.description||s.exceptionDetails.text||"Script execution failed"};const a=s.result?.value;return{output:(a===void 0?"undefined":JSON.stringify(a,null,2))?.substring(0,5e4)||"undefined"}}catch(e){const r=e instanceof Error?e.message:"Script execution failed";return r.includes("Cannot access")||r.includes("Cannot attach")?{error:"Cannot execute JavaScript on this page (restricted URL)"}:{error:r}}}case"READ_CONSOLE_MESSAGES":{if(!t)throw new Error("No tabId provided");try{await l.enableConsoleTracking(t)}catch{}const e=l.getConsoleMessages(t,{onlyErrors:o.onlyErrors,pattern:o.pattern,limit:o.limit||100});return o.clear&&l.clearConsoleMessages(t),{messages:e}}case"CLEAR_CONSOLE_MESSAGES":{if(!t)throw new Error("No tabId provided");return l.clearConsoleMessages(t),{success:!0}}case"READ_NETWORK_REQUESTS":{if(!t)throw new Error("No tabId provided");try{await l.enableNetworkTracking(t)}catch{}if(o.full){let r=l.getNetworkEntries(t,{urlPattern:o.urlPattern});o.method&&(r=r.filter(s=>s.method===o.method)),o.status&&(r=r.filter(s=>s.status===o.status)),o.contentType&&(r=r.filter(s=>s.type===o.contentType)),o.clear&&l.clearNetworkRequests(t);const n=o.limit||100;return{entries:r.slice(0,n),format:o.format,verbose:o.verbose}}let e=l.getNetworkRequests(t,{urlPattern:o.urlPattern,limit:o.limit||100});return o.method&&(e=e.filter(r=>r.method===o.method)),o.status&&(e=e.filter(r=>r.status===o.status)),o.contentType&&(e=e.filter(r=>r.type===o.contentType)),o.clear&&l.clearNetworkRequests(t),{requests:e,format:o.format,verbose:o.verbose}}case"CLEAR_NETWORK_REQUESTS":{if(!t)throw new Error("No tabId provided");return l.clearNetworkRequests(t),{success:!0}}case"GET_NETWORK_ENTRIES":{if(!t)throw new Error("No tabId provided");try{await l.enableNetworkTracking(t)}catch{}let e=l.getNetworkEntries(t,{urlPattern:o.urlPattern,includeStatic:!o.excludeStatic});return o.origin&&(e=e.filter(r=>r.origin===o.origin)),o.method&&(e=e.filter(r=>r.method===o.method)),o.status&&(e=e.filter(r=>r.status===o.status)),o.type&&(e=e.filter(r=>r.type===o.type)),o.since&&(e=e.filter(r=>r.ts>=o.since)),o.hasBody!==void 0&&(e=e.filter(r=>o.hasBody?r.responseBodySize&&r.responseBodySize>0:!r.responseBodySize)),o.last&&(e=e.slice(-o.last)),o.clear&&l.clearNetworkRequests(t),{entries:e}}case"GET_NETWORK_ENTRY":{if(!t)throw new Error("No tabId provided");if(!o.requestId)throw new Error("No requestId provided");let e=l.getNetworkEntry(t,o.requestId);return e||(e=l.getNetworkEntries(t,{}).find(n=>n.id===o.requestId)||null),e||(e=l.getNetworkEntries(t,{}).find(n=>n._requestId===o.requestId)||null),e?{entry:e}:{error:`Entry not found: ${o.requestId}`}}case"GET_RESPONSE_BODY":{if(!t)throw new Error("No tabId provided");if(!o.requestId)throw new Error("No requestId provided");let e=o.requestId;if(o.requestId.startsWith("r_")){const s=l.getNetworkEntries(t,{}).find(a=>a.id===o.requestId);s&&(e=s._requestId)}return await l.getResponseBody(t,e)}case"GET_NETWORK_ORIGINS":{if(!t)throw new Error("No tabId provided");const e=l.getNetworkEntries(t,{}),r={};for(const n of e)r[n.origin]||(r[n.origin]={count:0,lastSeen:0,size:0}),r[n.origin].count++,r[n.origin].lastSeen=Math.max(r[n.origin].lastSeen,n.ts),r[n.origin].size+=n.responseBodySize||0;return{origins:r}}case"GET_NETWORK_STATS":{if(!t)throw new Error("No tabId provided");const e=l.getNetworkEntries(t,{}),r={},n={},s={};let a=0,c=1/0,u=0;for(const d of e){r[d.origin]||(r[d.origin]=0),r[d.origin]++;const h=d.method||"GET";if(n[h]=(n[h]||0)+1,d.status){const f=`${Math.floor(d.status/100)}xx`;s[f]=(s[f]||0)+1}a+=d.responseBodySize||0,d.ts<c&&(c=d.ts),d.ts>u&&(u=d.ts)}return{stats:{totalRequests:e.length,totalSize:a,uniqueOrigins:Object.keys(r).length,startTime:c===1/0?null:c,duration:u&&c!==1/0?u-c:0,byMethod:n,byStatus:s}}}case"RESIZE_WINDOW":{if(!t)throw new Error("No tabId provided");if(!o.width||!o.height)throw new Error("width and height required");const e=await chrome.tabs.get(t);if(!e.windowId)throw new Error("Tab has no window");return await chrome.windows.update(e.windowId,{width:Math.floor(o.width),height:Math.floor(o.height)}),{success:!0,width:o.width,height:o.height}}case"TABS_CREATE":{const e=t?await chrome.tabs.get(t):null,r=await chrome.tabs.create({url:o.url||"about:blank",active:!1});if(!r.id)throw new Error("Failed to create tab");return e?.groupId&&e.groupId!==chrome.tabGroups.TAB_GROUP_ID_NONE&&await chrome.tabs.group({tabIds:r.id,groupId:e.groupId}),{success:!0,tabId:r.id,url:r.url||o.url||"about:blank"}}case"UPLOAD_IMAGE":{if(!t)throw new Error("No tabId provided");if(!o.screenshotId)throw new Error("screenshotId required");if(!o.ref&&!o.coordinate)throw new Error("ref or coordinate required");const e=le(o.screenshotId);if(!e)throw new Error(`Screenshot not found: ${o.screenshotId}`);try{return await chrome.tabs.sendMessage(t,{type:"UPLOAD_IMAGE",base64:e.base64,ref:o.ref,coordinate:o.coordinate,filename:o.filename||"screenshot.png"},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"GET_TABS":return{tabs:(await chrome.tabs.query({})).map(r=>({id:r.id,title:r.title,url:r.url}))};case"LIST_TABS":{const e={};return o.windowId&&(e.windowId=o.windowId),{tabs:(await chrome.tabs.query(e)).map(n=>({id:n.id,title:n.title,url:n.url,active:n.active,windowId:n.windowId}))}}case"NEW_TAB":{const e=o.urls||(o.url?[o.url]:["about:blank"]),r=[];for(let n=0;n<e.length;n++){const s={url:e[n],active:n===0};o.windowId&&(s.windowId=o.windowId);const a=await chrome.tabs.create(s);a.id&&r.push({tabId:a.id,url:e[n]})}return r.length===1?{success:!0,tabId:r[0].tabId,url:r[0].url}:{success:!0,tabs:r}}case"SWITCH_TAB":{const e=o.tabId;if(!e)throw new Error("No tabId provided");const r=await chrome.tabs.update(e,{active:!0});return r.windowId&&await chrome.windows.update(r.windowId,{focused:!0}),{success:!0,tabId:e,url:r.url,title:r.title}}case"CLOSE_TAB":{const e=o.tabIds||(o.tabId?[o.tabId]:[]);if(e.length===0)throw new Error("No tabId(s) provided");return await chrome.tabs.remove(e),e.length===1?{success:!0,tabId:e[0]}:{success:!0,closed:e}}case"TABS_REGISTER":{if(!t)throw new Error("No tabId provided");if(!o.name)throw new Error("No name provided");return A.set(o.name,t),{success:!0,name:o.name,tabId:t}}case"TABS_GET_BY_NAME":{if(!o.name)throw new Error("No name provided");const e=A.get(o.name);if(!e)return{error:`No tab registered with name "${o.name}"`};try{const r=await chrome.tabs.get(e);return{tabId:e,url:r.url,title:r.title}}catch{return A.delete(o.name),{error:`Tab "${o.name}" no longer exists`}}}case"TABS_LIST_NAMED":{const e=[];for(const[r,n]of A)try{const s=await chrome.tabs.get(n);e.push({name:r,tabId:n,url:s.url,title:s.title})}catch{A.delete(r)}return{tabs:e}}case"TABS_UNREGISTER":{if(!o.name)throw new Error("No name provided");return A.delete(o.name)?{success:!0}:{success:!1,error:`No tab registered with name "${o.name}"`}}case"GET_AUTH":{const{sendToNativeHost:e}=await V(async()=>{const{sendToNativeHost:r}=await Promise.resolve().then(()=>X);return{sendToNativeHost:r}},void 0);try{return await e({type:"GET_AUTH"})}catch{return{auth:null,hint:"Native host not connected. Make sure surf native host is installed."}}}case"NATIVE_API_REQUEST":{const{sendToNativeHost:e}=await V(async()=>{const{sendToNativeHost:r}=await Promise.resolve().then(()=>X);return{sendToNativeHost:r}},void 0);try{return await e({type:"API_REQUEST",streamId:o.streamId,url:o.url,method:o.method,headers:o.headers,body:o.body}),{sent:!0}}catch(r){return{error:r instanceof Error?r.message:"Unknown error"}}}case"STREAM_CONSOLE":{if(!t)throw new Error("No tabId provided");const e=o.streamId;try{return await l.enableConsoleTracking(t),M.set(e,t),l.subscribeToConsole(t,e,r=>{x({type:"STREAM_EVENT",streamId:e,event:{type:"console_event",level:r.type==="exception"?"error":r.type,text:r.text,timestamp:r.timestamp,url:r.url,line:r.line}})}),{success:!0,streaming:!0}}catch(r){return x({type:"STREAM_ERROR",streamId:e,error:r instanceof Error?r.message:"Failed to start console stream"}),{error:r instanceof Error?r.message:"Failed to start console stream"}}}case"STREAM_NETWORK":{if(!t)throw new Error("No tabId provided");const e=o.streamId;try{return await l.enableNetworkTracking(t),M.set(e,t),l.subscribeToNetwork(t,e,r=>{x({type:"STREAM_EVENT",streamId:e,event:{type:"network_event",method:r.method,url:r.url,status:r.status,duration:r.duration,timestamp:r.timestamp}})}),{success:!0,streaming:!0}}catch(r){return x({type:"STREAM_ERROR",streamId:e,error:r instanceof Error?r.message:"Failed to start network stream"}),{error:r instanceof Error?r.message:"Failed to start network stream"}}}case"STREAM_STOP":{const e=o.streamId,r=M.get(e);return r!==void 0&&(l.unsubscribeFromConsole(r,e),l.unsubscribeFromNetwork(r,e),M.delete(e)),{success:!0}}case"SEARCH_PAGE":{if(!t)throw new Error("No tabId provided");if(!o.term)throw new Error("Search term required");try{return await chrome.tabs.sendMessage(t,{type:"SEARCH_PAGE",term:o.term,caseSensitive:o.caseSensitive||!1,limit:o.limit||10},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"TAB_GROUP_CREATE":{const e=[...o.tabIds||[]],r=o.name||"Surf",s=["grey","blue","red","yellow","green","pink","purple","cyan","orange"].includes(o.color)?o.color:"blue";if(e.length===0&&t&&e.push(t),e.length===0)throw new Error("No tabs specified");const a=await chrome.tabGroups.query({title:r});let c;return a.length>0?(c=a[0].id,await chrome.tabs.group({tabIds:e,groupId:c})):(c=await chrome.tabs.group({tabIds:e}),await chrome.tabGroups.update(c,{title:r,color:s,collapsed:!1})),{success:!0,groupId:c,name:r,tabIds:e}}case"TAB_GROUP_REMOVE":{const e=[...o.tabIds||[]];if(e.length===0&&t&&e.push(t),e.length===0)throw new Error("No tabs specified");return await chrome.tabs.ungroup(e),{success:!0,ungrouped:e}}case"TAB_GROUPS_LIST":{const e=await chrome.tabGroups.query({}),r=[];for(const n of e){const s=await chrome.tabs.query({groupId:n.id});r.push({id:n.id,name:n.title||"(unnamed)",color:n.color,collapsed:n.collapsed,tabs:s.map(a=>({id:a.id,title:a.title,url:a.url}))})}return{groups:r}}case"CLICK_SELECTOR":{if(!t)throw new Error("No tabId provided");const e=o.selector,r=o.index||0,n=`(() => {
|
|
143
|
+
})()`)).result?.value||{error:"Failed to get page state"}}case"EXECUTE_SCROLL":{if(!t)throw new Error("No tabId provided");const e=o.deltaX||0,r=o.deltaY||0,n=(s,a)=>{const c={x:window.scrollX,y:window.scrollY};window.scrollBy(s,a);const u={x:window.scrollX,y:window.scrollY};return{scrollX:u.x,scrollY:u.y,scrolled:c.x!==u.x||c.y!==u.y}};try{return(await l.evaluateScript(t,`(${n.toString()})(${e}, ${r})`)).result?.value||{error:"Script failed"}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:t},func:n,args:[e,r]}))[0]?.result||{error:"Script failed"}}catch{return{error:"Cannot scroll on this page (restricted)"}}}}case"EXECUTE_KEY":{if(!t)throw new Error("No tabId provided");const e=o.key;if(!e)throw new Error("No key provided");return e.includes("+")?await l.pressKeyChord(t,e):await l.pressKey(t,e),{success:!0}}case"EXECUTE_NAVIGATE":{if(!t)throw new Error("No tabId provided");if(!o.url)throw new Error("No url provided");const e=new Promise(r=>{k.set(t,r),setTimeout(()=>{k.has(t)&&(k.delete(t),r())},3e4)});return await chrome.tabs.update(t,{url:o.url}),await e,await new Promise(r=>setTimeout(r,500)),{success:!0}}case"GET_VIEWPORT_SIZE":{if(!t)throw new Error("No tabId provided");return await l.getViewportSize(t)}case"READ_PAGE":{if(!t)throw new Error("No tabId provided");const e=b(t);try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(n=>setTimeout(n,50));let r;try{r=await chrome.tabs.sendMessage(t,{type:"GENERATE_ACCESSIBILITY_TREE",options:o.options||{}},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}if(o.options?.includeText)try{const n=await chrome.tabs.sendMessage(t,{type:"GET_PAGE_TEXT"},{frameId:e});n?.text&&(r.text=n.text)}catch{}if(o.options?.includeScreenshot)try{const n=await l.captureScreenshot(t);return{...r,screenshot:n}}catch{return{...r,screenshotError:"Failed to capture screenshot"}}return r}case"GET_ELEMENT_COORDINATES":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_COORDINATES",ref:o.ref},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"FORM_INPUT":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"FORM_INPUT",ref:o.ref,value:o.value},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"EVAL_IN_PAGE":{if(!t)throw new Error("No tabId provided");if(!o.code)throw new Error("No code provided");try{return await chrome.tabs.sendMessage(t,{type:"EVAL_IN_PAGE",code:o.code},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SCROLL_TO_ELEMENT":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"SCROLL_TO_ELEMENT",ref:o.ref},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SCROLL_TO_POSITION":{if(!t)throw new Error("No tabId provided");const e=o.position;if(e===void 0)throw new Error('position required ("top", "bottom", or number)');const r=o.selector,n=(s,a)=>{const c=()=>[...document.querySelectorAll("*")].filter(h=>h.scrollHeight>h.clientHeight&&h.clientHeight>200).sort((h,f)=>f.scrollHeight-h.scrollHeight)[0]||document.documentElement,u=a&&document.querySelector(a)||c();return u?(s==="bottom"?u.scrollTop=u.scrollHeight:s==="top"?u.scrollTop=0:typeof s=="number"&&(u.scrollTop=s),{scrollTop:u.scrollTop,scrollHeight:u.scrollHeight,clientHeight:u.clientHeight,atBottom:u.scrollTop+u.clientHeight>=u.scrollHeight-10,atTop:u.scrollTop<10}):{error:"No scrollable container found"}};try{const s=`(${n.toString()})(${JSON.stringify(e)}, ${JSON.stringify(r)})`;return(await l.evaluateScript(t,s)).result?.value||{error:"Script failed"}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:t},func:n,args:[e,r]}))[0]?.result||{error:"Script failed"}}catch{return{error:"Cannot scroll on this page (restricted)"}}}}case"GET_SCROLL_INFO":{if(!t)throw new Error("No tabId provided");const e=o.selector,r=n=>{const s=()=>[...document.querySelectorAll("*")].filter(d=>d.scrollHeight>d.clientHeight&&d.clientHeight>200).sort((d,h)=>h.scrollHeight-d.scrollHeight)[0]||document.documentElement,a=n&&document.querySelector(n)||s();if(!a)return{error:"No scrollable container found"};const c=a.scrollHeight-a.clientHeight;return{scrollTop:a.scrollTop,scrollHeight:a.scrollHeight,clientHeight:a.clientHeight,atBottom:a.scrollTop+a.clientHeight>=a.scrollHeight-10,atTop:a.scrollTop<10,scrollPercentage:c>0?Math.round(a.scrollTop/c*100):100}};try{const n=`(${r.toString()})(${JSON.stringify(e)})`;return(await l.evaluateScript(t,n)).result?.value||{error:"Script failed"}}catch{try{return(await chrome.scripting.executeScript({target:{tabId:t},func:r,args:[e]}))[0]?.result||{error:"Script failed"}}catch{return{error:"Cannot get scroll info on this page (restricted)"}}}}case"GET_PAGE_TEXT":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:"GET_PAGE_TEXT"},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_ROLE":{if(!t)throw new Error("No tabId provided");if(!o.role)throw new Error("role required");const e=b(t);try{const r=await chrome.tabs.sendMessage(t,{type:"LOCATE_ROLE",role:o.role,name:o.name,all:o.all},{frameId:e});return r.error?r:o.action&&r.ref?await G(t,r.ref,o.action,o.value,l,e):r}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_TEXT":{if(!t)throw new Error("No tabId provided");if(!o.text)throw new Error("text required");const e=b(t);try{const r=await chrome.tabs.sendMessage(t,{type:"LOCATE_TEXT",text:o.text,exact:o.exact},{frameId:e});return r.error?r:o.action&&r.ref?await G(t,r.ref,o.action,o.value,l,e):r}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"LOCATE_LABEL":{if(!t)throw new Error("No tabId provided");if(!o.label)throw new Error("label required");const e=b(t);try{const r=await chrome.tabs.sendMessage(t,{type:"LOCATE_LABEL",label:o.label},{frameId:e});return r.error?r:o.action&&r.ref?await G(t,r.ref,o.action,o.value,l,e):r}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"GET_ELEMENT_STYLES":{if(!t)throw new Error("No tabId provided");if(!o.selector)throw new Error("selector required");const e=b(t);try{return await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_STYLES",selector:o.selector},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SELECT_OPTION":{if(!t)throw new Error("No tabId provided");if(!o.selector)throw new Error("selector required");if(!o.values)throw new Error("values required");const e=b(t);try{return await chrome.tabs.sendMessage(t,{type:"SELECT_OPTION",selector:o.selector,values:o.values,by:o.by||"value"},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"SHOW_AGENT_INDICATORS":case"HIDE_AGENT_INDICATORS":case"SHOW_STATIC_INDICATOR":case"HIDE_STATIC_INDICATOR":{if(!t)throw new Error("No tabId provided");try{return await chrome.tabs.sendMessage(t,{type:o.type})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"STOP_AGENT":{const e=o.fromTabId;let r;return e==="CURRENT_TAB"&&i.tab?.id?r=i.tab.id:typeof e=="number"&&(r=e),r&&chrome.runtime.sendMessage({type:"STOP_AGENT",targetTabId:r}),{success:!0}}case"DISMISS_STATIC_INDICATOR":return{success:!0};case"STATIC_INDICATOR_HEARTBEAT":return{success:!0};case"CLICK_REF":{if(!t)throw new Error("No tabId provided");try{const e=await chrome.tabs.sendMessage(t,{type:"CLICK_ELEMENT",ref:o.ref,button:o.button||"left"},{frameId:b(t)});return e.error?{error:e.error}:{success:!0}}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"HOVER_REF":{if(!t)throw new Error("No tabId provided");try{const e=await chrome.tabs.sendMessage(t,{type:"GET_ELEMENT_COORDINATES",ref:o.ref},{frameId:b(t)});return e.error?{error:e.error}:(await l.hover(t,e.x,e.y),{success:!0})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"PING":return{success:!0,status:"connected"};case"HEALTH_CHECK_URL":{if(!o.url)throw new Error("No url provided");const e=o.timeout||3e4,r=o.expect||200,n=Date.now(),s=500;let a=null;for(;Date.now()-n<e;){try{const c=await fetch(o.url,{method:"GET"});if(await c.text(),c.status===r)return{success:!0,status:c.status,time:Date.now()-n};a=`Got status ${c.status}`}catch(c){a=c instanceof Error?c.message:String(c)}await new Promise(c=>setTimeout(c,s))}return{error:`Timeout waiting for ${o.url} to return ${r}`,lastError:a,time:Date.now()-n}}case"SMOKE_TEST":{const e=o.urls||[],r=o.savePath!==void 0,n=o.failFast||!1;if(e.length===0)return{error:"No URLs provided for smoke test"};const s=[];let a=0,c=0;for(const u of e){const d=Date.now(),h=[];let f,w,p;try{w=new URL(u).hostname.replace(/[^a-zA-Z0-9.-]/g,"_");const S=await chrome.tabs.create({url:u,active:!1});if(!S.id)throw new Error("Failed to create tab");p=S.id;try{await l.enableConsoleTracking(p)}catch{}await new Promise(m=>{const y=T=>{T.tabId===p&&T.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(y),chrome.webNavigation.onErrorOccurred.removeListener(g),m())},g=T=>{T.tabId===p&&T.frameId===0&&(chrome.webNavigation.onCompleted.removeListener(y),chrome.webNavigation.onErrorOccurred.removeListener(g),h.push(`Navigation error: ${T.error}`),m())};chrome.webNavigation.onCompleted.addListener(y),chrome.webNavigation.onErrorOccurred.addListener(g),setTimeout(()=>{chrome.webNavigation.onCompleted.removeListener(y),chrome.webNavigation.onErrorOccurred.removeListener(g),h.push("Navigation timeout (30s)"),m()},3e4)}),await new Promise(m=>setTimeout(m,2e3));const N=l.getConsoleMessages(p,{onlyErrors:!0,limit:50});for(const m of N)h.push(`[${m.type}] ${m.text}`);if(r)try{f=(await l.captureScreenshot(p)).base64}catch{}}catch(S){h.push(S instanceof Error?S.message:String(S))}finally{if(p)try{await chrome.tabs.remove(p)}catch{}}const E=Date.now()-d,_=h.length===0?"pass":"fail";if(_==="pass"?a++:c++,s.push({url:u,status:_,time:E,errors:h,...f&&{screenshotBase64:f,hostname:w}}),n&&_==="fail")break}return{results:s,summary:{pass:a,fail:c,total:s.length},savePath:o.savePath}}case"WAIT_FOR_ELEMENT":{if(!t)throw new Error("No tabId provided");if(!o.selector)throw new Error("No selector provided");const e=b(t);try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(r=>setTimeout(r,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_ELEMENT",selector:o.selector,state:o.state||"visible",timeout:o.timeout||2e4},{frameId:e})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_URL":{if(!t)throw new Error("No tabId provided");if(!o.pattern)throw new Error("No URL pattern provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_URL",pattern:o.pattern,timeout:o.timeout||2e4},{frameId:0})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_NETWORK_IDLE":{if(!t)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_NETWORK_IDLE",timeout:o.timeout||1e4},{frameId:0})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"})}catch{}}}case"WAIT_FOR_DOM_STABLE":{if(!t)throw new Error("No tabId provided");try{await chrome.tabs.sendMessage(t,{type:"HIDE_FOR_TOOL_USE"},{frameId:0})}catch{}await new Promise(e=>setTimeout(e,50));try{return await chrome.tabs.sendMessage(t,{type:"WAIT_FOR_DOM_STABLE",stable:o.stable||100,timeout:o.timeout||5e3},{frameId:0})}catch{return{error:"Content script not loaded. Try refreshing the page.",pageContent:"",viewport:{width:0,height:0}}}finally{try{await chrome.tabs.sendMessage(t,{type:"SHOW_AFTER_TOOL_USE"},{frameId:0})}catch{}}}case"DIALOG_ACCEPT":{if(!t)throw new Error("No tabId provided");return await l.handleDialog(t,!0,o.text)}case"DIALOG_DISMISS":{if(!t)throw new Error("No tabId provided");return await l.handleDialog(t,!1)}case"DIALOG_INFO":{if(!t)throw new Error("No tabId provided");const e=l.getDialogInfo(t);return e?{hasDialog:!0,type:e.type,message:e.message,defaultPrompt:e.defaultPrompt}:{hasDialog:!1}}case"EMULATE_NETWORK":{if(!t)throw new Error("No tabId provided");if(!o.preset)throw new Error("No preset provided");const e=await l.emulateNetwork(t,o.preset);if(!e.success)throw new Error(e.error);return{success:!0,preset:o.preset}}case"EMULATE_CPU":{if(!t)throw new Error("No tabId provided");if(o.rate===void 0)throw new Error("No rate provided");const e=await l.emulateCPU(t,o.rate);if(!e.success)throw new Error(e.error);return{success:!0,rate:o.rate}}case"EMULATE_GEO":{if(!t)throw new Error("No tabId provided");if(o.clear){const r=await l.clearGeolocation(t);if(!r.success)throw new Error(r.error);return{success:!0,cleared:!0}}if(o.latitude===void 0||o.longitude===void 0)throw new Error("Latitude and longitude required");const e=await l.emulateGeolocation(t,o.latitude,o.longitude,o.accuracy);if(!e.success)throw new Error(e.error);return{success:!0,latitude:o.latitude,longitude:o.longitude}}case"EMULATE_DEVICE_LIST":return{devices:["iPhone 12","iPhone 13","iPhone 14","iPhone 14 Pro","iPhone 14 Pro Max","iPhone SE","iPad","iPad Pro","iPad Mini","Pixel 5","Pixel 6","Pixel 7","Pixel 7 Pro","Galaxy S21","Galaxy S22","Galaxy S23","Galaxy Tab S7","Nest Hub","Nest Hub Max"]};case"EMULATE_DEVICE":{if(!t)throw new Error("No tabId provided");const e=o.device;if(e.toLowerCase()==="reset"){const a=await l.clearDeviceEmulation(t);if(!a.success)throw new Error(a.error);return{success:!0,message:"Device emulation reset"}}const r={"iPhone 12":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"},"iPhone 13":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1"},"iPhone 14":{width:390,height:844,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"},"iPhone 14 Pro":{width:393,height:852,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"},"iPhone 14 Pro Max":{width:430,height:932,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"},"iPhone SE":{width:375,height:667,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1"},iPad:{width:768,height:1024,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"},"iPad Pro":{width:1024,height:1366,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"},"iPad Mini":{width:768,height:1024,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"},"Pixel 5":{width:393,height:851,deviceScaleFactor:2.75,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36"},"Pixel 6":{width:412,height:915,deviceScaleFactor:2.625,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36"},"Pixel 7":{width:412,height:915,deviceScaleFactor:2.625,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36"},"Pixel 7 Pro":{width:412,height:892,deviceScaleFactor:3.5,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 13; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36"},"Galaxy S21":{width:360,height:800,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36"},"Galaxy S22":{width:360,height:780,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 12; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36"},"Galaxy S23":{width:360,height:780,deviceScaleFactor:3,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 13; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36"},"Galaxy Tab S7":{width:800,height:1280,deviceScaleFactor:2,mobile:!0,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Safari/537.36"},"Nest Hub":{width:1024,height:600,deviceScaleFactor:2,mobile:!1,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666"},"Nest Hub Max":{width:1280,height:800,deviceScaleFactor:2,mobile:!1,touch:!0,userAgent:"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666"}};let n=r[e];if(!n){const a=e.toLowerCase();let c=null;for(const[u,d]of Object.entries(r)){const h=u.toLowerCase(),f=h.replace(/\s+/g,"");(h.includes(a)||a.includes(f))&&(!c||u.length>c.name.length)&&(c={name:u,preset:d})}c&&(n=c.preset)}if(!n)throw new Error(`Unknown device: ${e}. Use --list to see available devices.`);const s=await l.emulateDevice(t,n);if(!s.success)throw new Error(s.error);return{success:!0,device:e}}case"EMULATE_VIEWPORT":{if(!t)throw new Error("No tabId provided");if(!o.width&&!o.height)throw new Error("--width or --height required");const e=await l.emulateViewport(t,{width:o.width,height:o.height,deviceScaleFactor:o.deviceScaleFactor,mobile:o.mobile});if(!e.success)throw new Error(e.error);return{success:!0,width:o.width,height:o.height}}case"EMULATE_TOUCH":{if(!t)throw new Error("No tabId provided");const e=await l.emulateTouch(t,o.enabled);if(!e.success)throw new Error(e.error);return{success:!0,enabled:o.enabled}}case"FORM_FILL":{if(!t)throw new Error("No tabId provided");if(!o.data)throw new Error("No data provided");return await chrome.tabs.sendMessage(t,{type:"FORM_FILL",data:o.data},{frameId:b(t)})}case"PERF_START":{if(!t)throw new Error("No tabId provided");const e=await l.startPerformanceTrace(t,o.categories);if(!e.success)throw new Error(e.error);return{success:!0,message:"Performance tracing started"}}case"PERF_STOP":{if(!t)throw new Error("No tabId provided");const e=await l.stopPerformanceTrace(t);if(!e.success)throw new Error(e.error);return{success:!0,metrics:e.metrics}}case"PERF_METRICS":{if(!t)throw new Error("No tabId provided");const e=await l.getPerformanceMetrics(t);if(!e.success)throw new Error(e.error);return{success:!0,metrics:e.metrics}}case"UPLOAD_FILE":{if(!t)throw new Error("No tabId provided");if(!o.ref)throw new Error("No ref provided");if(!o.files||!o.files.length)throw new Error("No files provided");const e=await chrome.tabs.sendMessage(t,{type:"GET_FILE_INPUT_SELECTOR",ref:o.ref},{frameId:b(t)});if(e.error)throw new Error(e.error);const r=await l.setFileInputBySelector(t,e.selector,o.files);if(!r.success)throw new Error(r.error);return{success:!0,filesSet:o.files.length}}case"WAIT_FOR_LOAD":{if(!t)throw new Error("No tabId provided");const e=await l.waitForLoad(t,o.timeout||3e4);if(!e.success)throw new Error(e.error);return{success:!0,readyState:e.readyState}}case"GET_FRAMES":{if(!t)throw new Error("No tabId provided");const e=await l.getFrames(t);if(!e.success)throw new Error(e.error);return{success:!0,frames:e.frames}}case"FRAME_SWITCH":{if(!t)throw new Error("No tabId provided");const{selector:e,name:r,index:n}=o;if(!e&&!r&&n===void 0)throw new Error("--selector, --name, or --index required");const s=await chrome.webNavigation.getAllFrames({tabId:t});if(!s||s.length===0)throw new Error("No frames found in tab");const a=s.filter(u=>u.frameId!==0);if(a.length===0)throw new Error("No iframes found on this page");let c=null;if(n!==void 0){if(n<0||n>=a.length)throw new Error(`Frame index ${n} out of range. Found ${a.length} frame(s).`);c=a[n]}else if(r){for(const u of a)try{if((await chrome.tabs.sendMessage(t,{type:"GET_FRAME_NAME"},{frameId:u.frameId}))?.name===r){c=u;break}}catch{}if(!c)throw new Error(`Frame with name "${r}" not found`)}else if(e)try{const u=await chrome.tabs.sendMessage(t,{type:"GET_FRAME_BY_SELECTOR",selector:e},{frameId:0});if(u?.error)throw new Error(u.error);u?.url&&(c=a.find(d=>d.url===u.url)||null),!c&&a.length===1&&(c=a[0])}catch{throw new Error(`Could not find frame with selector "${e}"`)}if(!c)throw new Error("Frame not found");return F.set(t,c.frameId),{success:!0,frameId:c.frameId,url:c.url}}case"FRAME_MAIN":{if(!t)throw new Error("No tabId provided");return F.delete(t),{success:!0,message:"Returned to main frame"}}case"EVALUATE_IN_FRAME":{if(!t)throw new Error("No tabId provided");if(!o.frameId)throw new Error("No frameId provided");if(!o.code)throw new Error("No code provided");const e=await l.evaluateInFrame(t,o.frameId,o.code);if(!e.success)throw new Error(e.error);return{value:e.result}}case"EXECUTE_JAVASCRIPT":{if(!t)throw new Error("No tabId provided");if(!o.code)throw new Error("No code provided");try{await l.evaluateScript(t,"if(!window.piHelpers){const piHelpers={wait(ms){return new Promise(r=>setTimeout(r,ms))},async waitForSelector(sel,opts={}){const{state='visible',timeout=20000}=opts;const isVis=el=>el&&getComputedStyle(el).display!=='none'&&getComputedStyle(el).visibility!=='hidden'&&getComputedStyle(el).opacity!=='0'&&el.offsetWidth>0&&el.offsetHeight>0;const chk=()=>{const el=document.querySelector(sel);switch(state){case'attached':return el;case'detached':return el?null:document.body;case'hidden':return(!el||!isVis(el))?(el||document.body):null;default:return isVis(el)?el:null}};return new Promise((res,rej)=>{const r=chk();if(r){res(state==='detached'||state==='hidden'?null:r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(state==='detached'||state==='hidden'?null:r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['style','class','hidden']})})},async waitForText(text,opts={}){const{selector,timeout=20000}=opts;const chk=()=>{const root=selector?document.querySelector(selector):document.body;if(!root)return null;const w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);while(w.nextNode())if(w.currentNode.textContent?.includes(text))return w.currentNode.parentElement;return null};return new Promise((res,rej)=>{const r=chk();if(r){res(r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,characterData:true})})},async waitForHidden(sel,t=20000){await piHelpers.waitForSelector(sel,{state:'hidden',timeout:t})},getByRole(role,opts={}){const{name}=opts;const roles={button:['button','input[type=button]','input[type=submit]','input[type=reset]'],link:['a[href]'],textbox:['input:not([type])','input[type=text]','input[type=email]','input[type=password]','textarea'],checkbox:['input[type=checkbox]'],radio:['input[type=radio]'],combobox:['select'],heading:['h1','h2','h3','h4','h5','h6']};const cands=[...document.querySelectorAll('[role='+role+']')];if(roles[role])roles[role].forEach(s=>cands.push(...document.querySelectorAll(s+':not([role])')));if(!name)return cands[0]||null;const n=name.toLowerCase().trim();for(const el of cands){const l=el.getAttribute('aria-label')?.toLowerCase().trim();const t=el.textContent?.toLowerCase().trim();if(l===n||t===n||l?.includes(n)||t?.includes(n))return el}return null}};window.__piHelpers=piHelpers;window.piHelpers=piHelpers}");const n=`(async () => { 'use strict'; ${o.code.replace(/`/g,"\\`").replace(/\$/g,"\\$")} })()`,s=await l.evaluateScript(t,n);if(s.exceptionDetails)return{error:s.exceptionDetails.exception?.description||s.exceptionDetails.text||"Script execution failed"};const a=s.result?.value;return{output:(a===void 0?"undefined":JSON.stringify(a,null,2))?.substring(0,5e4)||"undefined"}}catch(e){const r=e instanceof Error?e.message:"Script execution failed";return r.includes("Cannot access")||r.includes("Cannot attach")?{error:"Cannot execute JavaScript on this page (restricted URL)"}:{error:r}}}case"READ_CONSOLE_MESSAGES":{if(!t)throw new Error("No tabId provided");try{await l.enableConsoleTracking(t)}catch{}const e=l.getConsoleMessages(t,{onlyErrors:o.onlyErrors,pattern:o.pattern,limit:o.limit||100});return o.clear&&l.clearConsoleMessages(t),{messages:e}}case"CLEAR_CONSOLE_MESSAGES":{if(!t)throw new Error("No tabId provided");return l.clearConsoleMessages(t),{success:!0}}case"READ_NETWORK_REQUESTS":{if(!t)throw new Error("No tabId provided");try{await l.enableNetworkTracking(t)}catch{}if(o.full){let r=l.getNetworkEntries(t,{urlPattern:o.urlPattern});o.method&&(r=r.filter(s=>s.method===o.method)),o.status&&(r=r.filter(s=>s.status===o.status)),o.contentType&&(r=r.filter(s=>s.type===o.contentType)),o.clear&&l.clearNetworkRequests(t);const n=o.limit||100;return{entries:r.slice(0,n),format:o.format,verbose:o.verbose}}let e=l.getNetworkRequests(t,{urlPattern:o.urlPattern,limit:o.limit||100});return o.method&&(e=e.filter(r=>r.method===o.method)),o.status&&(e=e.filter(r=>r.status===o.status)),o.contentType&&(e=e.filter(r=>r.type===o.contentType)),o.clear&&l.clearNetworkRequests(t),{requests:e,format:o.format,verbose:o.verbose}}case"CLEAR_NETWORK_REQUESTS":{if(!t)throw new Error("No tabId provided");return l.clearNetworkRequests(t),{success:!0}}case"GET_NETWORK_ENTRIES":{if(!t)throw new Error("No tabId provided");try{await l.enableNetworkTracking(t)}catch{}let e=l.getNetworkEntries(t,{urlPattern:o.urlPattern,includeStatic:!o.excludeStatic});return o.origin&&(e=e.filter(r=>r.origin===o.origin)),o.method&&(e=e.filter(r=>r.method===o.method)),o.status&&(e=e.filter(r=>r.status===o.status)),o.type&&(e=e.filter(r=>r.type===o.type)),o.since&&(e=e.filter(r=>r.ts>=o.since)),o.hasBody!==void 0&&(e=e.filter(r=>o.hasBody?r.responseBodySize&&r.responseBodySize>0:!r.responseBodySize)),o.last&&(e=e.slice(-o.last)),o.clear&&l.clearNetworkRequests(t),{entries:e}}case"GET_NETWORK_ENTRY":{if(!t)throw new Error("No tabId provided");if(!o.requestId)throw new Error("No requestId provided");let e=l.getNetworkEntry(t,o.requestId);return e||(e=l.getNetworkEntries(t,{}).find(n=>n.id===o.requestId)||null),e||(e=l.getNetworkEntries(t,{}).find(n=>n._requestId===o.requestId)||null),e?{entry:e}:{error:`Entry not found: ${o.requestId}`}}case"GET_RESPONSE_BODY":{if(!t)throw new Error("No tabId provided");if(!o.requestId)throw new Error("No requestId provided");let e=o.requestId;if(o.requestId.startsWith("r_")){const s=l.getNetworkEntries(t,{}).find(a=>a.id===o.requestId);s&&(e=s._requestId)}return await l.getResponseBody(t,e)}case"GET_NETWORK_ORIGINS":{if(!t)throw new Error("No tabId provided");const e=l.getNetworkEntries(t,{}),r={};for(const n of e)r[n.origin]||(r[n.origin]={count:0,lastSeen:0,size:0}),r[n.origin].count++,r[n.origin].lastSeen=Math.max(r[n.origin].lastSeen,n.ts),r[n.origin].size+=n.responseBodySize||0;return{origins:r}}case"GET_NETWORK_STATS":{if(!t)throw new Error("No tabId provided");const e=l.getNetworkEntries(t,{}),r={},n={},s={};let a=0,c=1/0,u=0;for(const d of e){r[d.origin]||(r[d.origin]=0),r[d.origin]++;const h=d.method||"GET";if(n[h]=(n[h]||0)+1,d.status){const f=`${Math.floor(d.status/100)}xx`;s[f]=(s[f]||0)+1}a+=d.responseBodySize||0,d.ts<c&&(c=d.ts),d.ts>u&&(u=d.ts)}return{stats:{totalRequests:e.length,totalSize:a,uniqueOrigins:Object.keys(r).length,startTime:c===1/0?null:c,duration:u&&c!==1/0?u-c:0,byMethod:n,byStatus:s}}}case"RESIZE_WINDOW":{if(!t)throw new Error("No tabId provided");if(!o.width||!o.height)throw new Error("width and height required");const e=await chrome.tabs.get(t);if(!e.windowId)throw new Error("Tab has no window");return await chrome.windows.update(e.windowId,{width:Math.floor(o.width),height:Math.floor(o.height)}),{success:!0,width:o.width,height:o.height}}case"TABS_CREATE":{const e=t?await chrome.tabs.get(t):null,r=await chrome.tabs.create({url:o.url||"about:blank",active:!1});if(!r.id)throw new Error("Failed to create tab");return e?.groupId&&e.groupId!==chrome.tabGroups.TAB_GROUP_ID_NONE&&await chrome.tabs.group({tabIds:r.id,groupId:e.groupId}),{success:!0,tabId:r.id,url:r.url||o.url||"about:blank"}}case"UPLOAD_IMAGE":{if(!t)throw new Error("No tabId provided");if(!o.screenshotId)throw new Error("screenshotId required");if(!o.ref&&!o.coordinate)throw new Error("ref or coordinate required");const e=le(o.screenshotId);if(!e)throw new Error(`Screenshot not found: ${o.screenshotId}`);try{return await chrome.tabs.sendMessage(t,{type:"UPLOAD_IMAGE",base64:e.base64,ref:o.ref,coordinate:o.coordinate,filename:o.filename||"screenshot.png"},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"GET_TABS":return{tabs:(await chrome.tabs.query({})).map(r=>({id:r.id,title:r.title,url:r.url}))};case"LIST_TABS":{const e={};return o.windowId&&(e.windowId=o.windowId),{tabs:(await chrome.tabs.query(e)).map(n=>({id:n.id,title:n.title,url:n.url,active:n.active,windowId:n.windowId}))}}case"NEW_TAB":{const e=o.urls||(o.url?[o.url]:["about:blank"]),r=[];for(let n=0;n<e.length;n++){const s={url:e[n],active:n===0};o.windowId&&(s.windowId=o.windowId);const a=await chrome.tabs.create(s);a.id&&r.push({tabId:a.id,url:e[n]})}return r.length===1?{success:!0,tabId:r[0].tabId,url:r[0].url}:{success:!0,tabs:r}}case"SWITCH_TAB":{const e=o.tabId;if(!e)throw new Error("No tabId provided");const r=await chrome.tabs.update(e,{active:!0});return r.windowId&&await chrome.windows.update(r.windowId,{focused:!0}),{success:!0,tabId:e,url:r.url,title:r.title}}case"CLOSE_TAB":{const e=o.tabIds||(o.tabId?[o.tabId]:[]);if(e.length===0)throw new Error("No tabId(s) provided");return await chrome.tabs.remove(e),e.length===1?{success:!0,tabId:e[0]}:{success:!0,closed:e}}case"TABS_REGISTER":{if(!t)throw new Error("No tabId provided");if(!o.name)throw new Error("No name provided");return A.set(o.name,t),{success:!0,name:o.name,tabId:t}}case"TABS_GET_BY_NAME":{if(!o.name)throw new Error("No name provided");const e=A.get(o.name);if(!e)return{error:`No tab registered with name "${o.name}"`};try{const r=await chrome.tabs.get(e);return{tabId:e,url:r.url,title:r.title}}catch{return A.delete(o.name),{error:`Tab "${o.name}" no longer exists`}}}case"TABS_LIST_NAMED":{const e=[];for(const[r,n]of A)try{const s=await chrome.tabs.get(n);e.push({name:r,tabId:n,url:s.url,title:s.title})}catch{A.delete(r)}return{tabs:e}}case"TABS_UNREGISTER":{if(!o.name)throw new Error("No name provided");return A.delete(o.name)?{success:!0}:{success:!1,error:`No tab registered with name "${o.name}"`}}case"GET_AUTH":{const{sendToNativeHost:e}=await V(async()=>{const{sendToNativeHost:r}=await Promise.resolve().then(()=>X);return{sendToNativeHost:r}},void 0);try{return await e({type:"GET_AUTH"})}catch{return{auth:null,hint:"Native host not connected. Make sure surf native host is installed."}}}case"NATIVE_API_REQUEST":{const{sendToNativeHost:e}=await V(async()=>{const{sendToNativeHost:r}=await Promise.resolve().then(()=>X);return{sendToNativeHost:r}},void 0);try{return await e({type:"API_REQUEST",streamId:o.streamId,url:o.url,method:o.method,headers:o.headers,body:o.body}),{sent:!0}}catch(r){return{error:r instanceof Error?r.message:"Unknown error"}}}case"STREAM_CONSOLE":{if(!t)throw new Error("No tabId provided");const e=o.streamId;try{return await l.enableConsoleTracking(t),M.set(e,t),l.subscribeToConsole(t,e,r=>{x({type:"STREAM_EVENT",streamId:e,event:{type:"console_event",level:r.type==="exception"?"error":r.type,text:r.text,timestamp:r.timestamp,url:r.url,line:r.line}})}),{success:!0,streaming:!0}}catch(r){return x({type:"STREAM_ERROR",streamId:e,error:r instanceof Error?r.message:"Failed to start console stream"}),{error:r instanceof Error?r.message:"Failed to start console stream"}}}case"STREAM_NETWORK":{if(!t)throw new Error("No tabId provided");const e=o.streamId;try{return await l.enableNetworkTracking(t),M.set(e,t),l.subscribeToNetwork(t,e,r=>{x({type:"STREAM_EVENT",streamId:e,event:{type:"network_event",method:r.method,url:r.url,status:r.status,duration:r.duration,timestamp:r.timestamp}})}),{success:!0,streaming:!0}}catch(r){return x({type:"STREAM_ERROR",streamId:e,error:r instanceof Error?r.message:"Failed to start network stream"}),{error:r instanceof Error?r.message:"Failed to start network stream"}}}case"STREAM_STOP":{const e=o.streamId,r=M.get(e);return r!==void 0&&(l.unsubscribeFromConsole(r,e),l.unsubscribeFromNetwork(r,e),M.delete(e)),{success:!0}}case"SEARCH_PAGE":{if(!t)throw new Error("No tabId provided");if(!o.term)throw new Error("Search term required");try{return await chrome.tabs.sendMessage(t,{type:"SEARCH_PAGE",term:o.term,caseSensitive:o.caseSensitive||!1,limit:o.limit||10},{frameId:b(t)})}catch{return{error:"Content script not loaded. Try refreshing the page."}}}case"TAB_GROUP_CREATE":{const e=[...o.tabIds||[]],r=o.name||"Surf",s=["grey","blue","red","yellow","green","pink","purple","cyan","orange"].includes(o.color)?o.color:"blue";if(e.length===0&&t&&e.push(t),e.length===0)throw new Error("No tabs specified");const a=await chrome.tabGroups.query({title:r});let c;return a.length>0?(c=a[0].id,await chrome.tabs.group({tabIds:e,groupId:c})):(c=await chrome.tabs.group({tabIds:e}),await chrome.tabGroups.update(c,{title:r,color:s,collapsed:!1})),{success:!0,groupId:c,name:r,tabIds:e}}case"TAB_GROUP_REMOVE":{const e=[...o.tabIds||[]];if(e.length===0&&t&&e.push(t),e.length===0)throw new Error("No tabs specified");return await chrome.tabs.ungroup(e),{success:!0,ungrouped:e}}case"TAB_GROUPS_LIST":{const e=await chrome.tabGroups.query({}),r=[];for(const n of e){const s=await chrome.tabs.query({groupId:n.id});r.push({id:n.id,name:n.title||"(unnamed)",color:n.color,collapsed:n.collapsed,tabs:s.map(a=>({id:a.id,title:a.title,url:a.url}))})}return{groups:r}}case"CLICK_SELECTOR":{if(!t)throw new Error("No tabId provided");const e=o.selector,r=o.index||0,n=`(() => {
|
|
144
144
|
const elements = document.querySelectorAll(${JSON.stringify(e)});
|
|
145
145
|
if (elements.length === 0) return { error: "No elements match selector" };
|
|
146
146
|
if (${r} >= elements.length) return { error: "Index " + ${r} + " out of range (found " + elements.length + " elements)" };
|