browser-attach 0.0.0-stage → 0.1.2
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/CHANGELOG.md +30 -0
- package/LICENSE +21 -0
- package/README.md +103 -2
- package/bundle/bridge.mjs +33085 -0
- package/bundle/browser-attach.mjs +1451 -0
- package/bundle/build.json +1 -0
- package/bundle/extension/assets/eval-port.ts-CjQ6AQ5y.js +2 -0
- package/bundle/extension/assets/index-CFCX92ZZ.css +1 -0
- package/bundle/extension/assets/index.html-BVp3Bo-W.js +1 -0
- package/bundle/extension/assets/index.ts-B5VErDIP.js +5 -0
- package/bundle/extension/assets/isolated.ts-Ta0FhgRt.js +30 -0
- package/bundle/extension/assets/main.ts-35tWlP_X.js +3 -0
- package/bundle/extension/assets/network-patch.ts-B-brNKhX.js +2 -0
- package/bundle/extension/icons/icon-128.png +0 -0
- package/bundle/extension/icons/icon-16.png +0 -0
- package/bundle/extension/icons/icon-32.png +0 -0
- package/bundle/extension/icons/icon-48.png +0 -0
- package/bundle/extension/manifest.json +100 -0
- package/bundle/extension/service-worker-loader.js +1 -0
- package/bundle/extension/src/popup/index.html +21 -0
- package/package.json +62 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"build":"1d64b1f-mvsbxcwk","version":"0.1.2"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(){const s=globalThis;if(!s.__attachEvalPort){const t=new MessageChannel,a={port:t.port1,ready:!1};t.port1.addEventListener("message",r=>{var e;((e=r.data)==null?void 0:e.ready)===!0&&(a.ready=!0)}),t.port1.start(),s.__attachEvalPort=a;try{window.postMessage({channel:"__attach_eval__"},"*",[t.port2])}catch{}}
|
|
2
|
+
})()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{color-scheme:light dark;font-family:ui-sans-serif,system-ui,-apple-system,sans-serif}body{margin:0;padding:12px 14px;width:280px;font-size:12px;background:Canvas;color:CanvasText}header{display:flex;align-items:center;gap:8px;margin-bottom:8px}.dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#999}.dot-open{background:#16a34a}.dot-connecting{background:#d97706}.dot-closed{background:#dc2626}.dot-disabled{background:#9ca3af}#status-line{font-weight:500}#url-line{font-family:ui-monospace,monospace;font-size:11px;color:#6b7280;margin-top:2px;word-break:break-all}section{margin-top:12px;border-top:1px solid color-mix(in srgb,CanvasText 12%,transparent);padding-top:10px}h2{margin:0 0 6px;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:#6b7280;font-weight:600}#activity{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:4px}#activity li{display:flex;gap:6px;align-items:baseline;font-family:ui-monospace,monospace;font-size:11px}#activity li .tool{font-weight:600}#activity li.ok .tool{color:#16a34a}#activity li.err .tool{color:#dc2626}#activity li .ms{color:#9ca3af}#activity li.empty{color:#9ca3af;font-style:italic}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))s(e);new MutationObserver(e=>{for(const n of e)if(n.type==="childList")for(const r of n.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&s(r)}).observe(document,{childList:!0,subtree:!0});function c(e){const n={};return e.integrity&&(n.integrity=e.integrity),e.referrerPolicy&&(n.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?n.credentials="include":e.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function s(e){if(e.ep)return;e.ep=!0;const n=c(e);fetch(e.href,n)}})();const f=document.getElementById("status-dot"),d=document.getElementById("status-line"),p=document.getElementById("url-line"),i=document.getElementById("activity");function u(t){f.className=`dot dot-${t}`}function y(t,o){u(t.state);const c={open:"connected",connecting:"connecting…",closed:t.error?`closed: ${t.error}`:"closed",disabled:"disabled"};if(d.textContent=c[t.state],p.textContent=t.url??"",i.replaceChildren(),o.length===0){const e=document.createElement("li");e.className="empty",e.textContent="no tool calls yet",i.appendChild(e);return}const s=o.slice(-5).reverse();for(const e of s){const n=document.createElement("li");n.className=e.status==="ok"?"ok":e.status==="fail"?"err":"";const r=document.createElement("span");r.className="tool",r.textContent=e.tool;const l=document.createElement("span");l.className="ms",l.textContent=typeof e.elapsedMs=="number"?`${Math.round(e.elapsedMs)}ms`:"",n.append(r,l),i.appendChild(n)}}async function a(t){return new Promise((o,c)=>{chrome.runtime.sendMessage({source:"popup",type:t},s=>{const e=chrome.runtime.lastError;if(e)return c(new Error(e.message));o(s)})})}async function m(){try{const[t,o]=await Promise.all([a("bridge.status.get"),a("activity.get")]);y(t.status,o.entries??[])}catch(t){u("closed"),d.textContent=t instanceof Error?t.message:String(t)}}m();setInterval(m,1e3);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
var ut=Object.defineProperty;var ft=(e,t,n)=>t in e?ut(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Y=(e,t,n)=>ft(e,typeof t!="symbol"?t+"":t,n);const Me="[browser-attach]";function E(e){const t=e?`${Me}[${e}]`:Me,n=(o,r)=>(...a)=>{const[s,...i]=a;typeof s=="string"?r(`${t}[${o.toUpperCase()}] ${s}`,...i):r(`${t}[${o.toUpperCase()}]`,s,...i)};return{debug:n("debug",console.debug),info:n("info",console.info),warn:n("warn",console.warn),error:n("error",console.error)}}async function V(e){try{const t=await chrome.webNavigation.getAllFrames({tabId:e});return t?t.filter(n=>!n.errorOccurred).map(n=>({frameId:n.frameId,url:n.url,parentFrameId:n.parentFrameId,errorOccurred:n.errorOccurred})):[]}catch{return[]}}function W(e){const t=e.match(/^f(\d+):(.+)$/);return t?{frameId:parseInt(t[1],10),localRef:t[2]}:{frameId:0,localRef:e}}function Ve(e,t){return e===0?t:`f${e}:${t}`}class v extends Error{constructor(n,o={}){super(n);Y(this,"code");Y(this,"short_term");this.name="ToolFault",this.code=o.code,this.short_term=o.short_term??!0}toError(){return{message:this.message,code:this.code,short_term:this.short_term}}}function $(e,t){return new v(e,{short_term:!1,code:t})}function P(e,t){return new v(e,{short_term:!0,code:t})}function dt(e){return e instanceof v?e.toError():e instanceof Error?{message:e.message,short_term:!0}:{message:String(e),short_term:!0}}const Xe=E("tab-message"),Ge=3e4;async function L(e,t,n,o=Ge){const r={__quarry:!0,...n},a=`tab=${e} frame=${t}`;return new Promise((s,i)=>{const l=setTimeout(()=>{i(P(`content-script timeout after ${(o/1e3).toFixed(1)}s (${a})`,"TIMEOUT"))},o);try{chrome.tabs.sendMessage(e,r,{frameId:t},c=>{clearTimeout(l);const u=chrome.runtime.lastError;if(u){const h=u.message??"unknown error";return/back\/?forward[\s_-]?cache|message channel.*closed/i.test(h)?i(new v(`action triggered navigation; result payload lost as the page entered the back/forward cache (${a}). The action likely took effect — re-snapshot the new page.`,{code:"NAVIGATION_RACE",short_term:!1})):i(P(`tab.sendMessage failed (${a}): ${h}`,"SEND_MESSAGE_FAILED"))}if(!c)return i(P(`no response from content script (${a}). The tab may need a hard refresh (⌘+Shift+R) after the extension was reloaded.`,"NO_LISTENER"));if(!c.ok)return i(new v(c.message,{code:c.code,short_term:c.short_term??!0}));s(c.data)})}catch(c){clearTimeout(l),Xe.warn(`sendToFrame threw for ${a}`,c),i(c instanceof Error?c:new Error(String(c)))}})}function ae(e,t,n){return M(e,0,t,n)}const ht=/^(view-source|chrome|chrome-extension|chrome-untrusted|chrome-search|devtools|edge|brave|opera|vivaldi|about):/i,wt=/^https:\/\/(chromewebstore\.google\.com|chrome\.google\.com\/webstore|microsoftedge\.microsoft\.com\/addons)(\/|$)/i;function je(e){return!e||/^about:(blank|srcdoc)\b/i.test(e)?!1:ht.test(e)||wt.test(e)}async function Te(e){let t;try{const n=await chrome.tabs.get(e);t=n.pendingUrl||n.url}catch{return}if(je(t))throw $(`this page cannot be read or controlled by the extension (${t.split(/[?#]/)[0].slice(0,120)}). Browser-internal pages, view-source:, other extensions and the Chrome Web Store are off limits${/^view-source:/i.test(t)?"; navigate to the URL without the view-source: prefix, or use browser_request to fetch the source":""}.`,"RESTRICTED_PAGE")}const $e=new Map;async function mt(e,t){for(const n of chrome.runtime.getManifest().content_scripts??[]){const o=n.world??"ISOLATED";await chrome.scripting.executeScript({target:{tabId:e,frameIds:[t]},files:n.js??[],world:o,injectImmediately:!0})}}async function M(e,t,n,o=Ge){const r=a=>a instanceof Error&&/Receiving end does not exist/.test(a.message);try{return await L(e,t,n,o)}catch(a){if(!r(a))throw a}await Te(e),await new Promise(a=>setTimeout(a,300));try{return await L(e,t,n,o)}catch(a){const s=`${e}:${t}`,i=$e.get(s)??0;if(!r(a)||Date.now()-i<5e3)throw a;$e.set(s,Date.now()),await Te(e),Xe.warn(`no content script in tab=${e} frame=${t}; injecting`);try{await mt(e,t)}catch{throw a}return await new Promise(l=>setTimeout(l,150)),L(e,t,n,o)}}const ie=E("snapshot"),gt=6e3;async function Ye(e,t={}){const n=performance.now(),r=typeof t.limit=="number"&&Number.isFinite(t.limit)?Math.max(1,Math.floor(t.limit)):1e6,a=await V(e);if(a.length===0)return ie.warn(`no frames for tab=${e}`),{ok:!0,url:"",title:"",interactables:[],total_interactables:0,frames:[],coverage:{status:"unknown",reasons:["no_frames"]}};const s=await Promise.allSettled(a.map(w=>M(e,w.frameId,{op:"snapshot",budget:r},gt).then(p=>({frameId:w.frameId,data:p})))),i=s.map((w,p)=>w.status==="fulfilled"?{frameId:a[p].frameId,url:w.value.data.url,documentId:w.value.data.documentId,...w.value.data.coverage,failed:!1}:{frameId:a[p].frameId,failed:!0}),l=[];let c="",u="",h=!1;for(const w of s){if(w.status!=="fulfilled"){ie.debug("frame snapshot failed",w.reason);continue}const{frameId:p,data:g}=w.value;p===0&&(c=g.url,u=g.title,h=!0);for(const b of g.interactables)l.push({...b,ref:Ve(p,b.ref),frame_id:p===0?void 0:`f${p}`})}if(!h)try{const w=await chrome.tabs.get(e);c=w.url??"",u=w.title??""}catch{}const m=l.length,f=m>r?l.slice(0,r):l,d=(performance.now()-n).toFixed(0);ie.info(`snapshot complete: ${f.length}/${m} interactables across ${a.length} frame(s) in ${d}ms`,{url:c,title:u,limit:r});const y=i.some(w=>w.failed||w.truncated)||m>r;return{ok:!0,url:c,title:u,interactables:f,total_interactables:m,frames:i,coverage:{status:y?"partial":"complete_in_scope",scope:"interactive_visible_dom",returned:f.length,matched:i.some(w=>w.failed)?void 0:i.reduce((w,p)=>w+Number(p.matched),0),reasons:[...i.some(w=>w.failed)?["frame_failed"]:[],...i.some(w=>w.truncated)||m>r?["budget_cut"]:[]]}}}const Se=12,Ae=3,pt=4e3,yt=/^(\s*)- iframe "((?:[^"\\]|\\.)*)" \{\{frame:([\w-]+)\}\}$/;async function bt(e,t){const{frameId:n,localRef:o}=t.ref?W(t.ref):{frameId:0,localRef:void 0},r=await M(e,n,{op:"view",ref:o}),a=await vt(e,n,r),{probe:s,...i}=n?{...a,content:Ke(n,a.content)}:a;return{ok:!0,...i}}function Ke(e,t){return t.replace(/\[(e\d+)\]/g,`[f${e}:$1]`).replace(/\(in (e\d+)\)/g,`(in f${e}:$1)`)}async function vt(e,t,n){if(n.kind!=="html"||!n.content.includes("{{frame:"))return n;const o=await V(e),r=new Map;let a=[t],s=0;for(let y=1;y<=Ae&&a.length&&s<Se;y++){const w=o.filter(g=>a.includes(g.parentFrameId)).slice(0,Se-s);s+=w.length;const p=await Promise.allSettled(w.map(async g=>{var x;const b=await L(e,g.frameId,{op:"view"},pt);let k=b.probe;return k||(await new Promise(I=>setTimeout(I,150)),k=(x=await L(e,g.frameId,{op:"frames"},1e3).catch(()=>null))==null?void 0:x.probe),{frameId:g.frameId,data:b,probe:k}}));a=[];for(const g of p)g.status!=="fulfilled"||!g.value.probe||(r.set(g.value.probe,{frameId:g.value.frameId,data:{...g.value.data,content:Ke(g.value.frameId,g.value.data.content)}}),a.push(g.value.frameId))}let i=n.actions,l=n.texts,c=n.truncated;const u=(y,w)=>{const p=[];for(const g of y.split(`
|
|
2
|
+
`)){const b=yt.exec(g);if(!b){p.push(g);continue}const[,k,x,I]=b,A=r.get(I);if(!A||w<=0){p.push(`${k}- iframe "${x}" (not readable)`);continue}r.delete(I),i+=A.data.actions,l+=A.data.texts,c||(c=A.data.truncated);const _=u(A.data.content,w-1).filter(D=>D.trim());if(!_.length){p.push(`${k}- iframe "${x}" (empty)`);continue}p.push(`${k}- iframe "${x}" [f${A.frameId}]:`,..._.map(D=>`${k} ${D}`))}return p},h=[],m=[],f=[];for(const y of n.content.split(`
|
|
3
|
+
`))m.push(h.length),h.push(...u(y,Ae)),f.push(h.length-1);const d=n.viewport;return{...n,actions:i,texts:l,truncated:c,content:h.join(`
|
|
4
|
+
`),...d?{viewport:[m[d[0]]??0,f[d[1]]??h.length-1]}:{}}}class _t{constructor(t,n){Y(this,"tail",Promise.resolve());this.store=t,this.ops=n}locked(t){const n=this.tail.then(t);return this.tail=n.catch(()=>{}),n}openTab(t,n){return this.locked(async()=>{const o=await this.store.load(),r=o.windows[t];let a;if(r!==void 0&&await this.ops.exists(r))a=await this.ops.createTab(r,n);else{const s=await this.ops.createWindow(n);o.windows[t]=s.windowId,a=s.tabId}return o.tabs.includes(a)||o.tabs.push(a),await this.store.save(o),a})}adopt(t,n){return this.locked(async()=>{const o=await this.store.load();!o.tabs.includes(t)||o.tabs.includes(n)||(o.tabs.push(n),await this.store.save(o))})}forgetTab(t){return this.locked(async()=>{const n=await this.store.load();n.tabs.includes(t)&&await this.store.save({...n,tabs:n.tabs.filter(o=>o!==t)})})}forgetWindow(t){return this.locked(async()=>{const n=await this.store.load(),o=Object.keys(n.windows).filter(r=>n.windows[r]===t);if(o.length){for(const r of o)delete n.windows[r];await this.store.save(n)}})}async isAgentWindow(t){return Object.values((await this.store.load()).windows).includes(t)}async tabIds(){return(await this.store.load()).tabs}takeAll(){return this.locked(async()=>{const t=await this.store.load();return await this.store.save({windows:{},tabs:[]}),t.tabs})}}async function kt(e,t){switch(t.action){case"list":return xt(t.all,t.agentOnly);case"switch":return Et(t.tabId);case"new":return t.dedicated?At(t.session,t.url):Mt(t.url);case"close":return Rt(t.tabId);default:throw $(`tabs: unknown action "${t.action}"`,"TABS_BAD_ACTION")}}async function xt(e=!1,t=!1){const n=t?await St():null,o=(await chrome.tabs.query(e?{}:{currentWindow:!0})).filter(a=>!n||n.includes(a.id)),r=o.find(a=>a.active);return{ok:!0,action:"list",active:r==null?void 0:r.id,tabs:o.filter(a=>typeof a.id=="number").map(a=>({id:a.id,url:a.url??"",title:a.title??"",active:!!a.active,...e?{openerTabId:a.openerTabId,windowId:a.windowId}:{}}))}}async function Et(e){return await chrome.tabs.update(e,{active:!0}),{ok:!0,action:"switch",tabId:e}}async function Mt(e){const t=await chrome.tabs.create({url:e,active:!1});if(typeof t.id!="number")throw new Error("tabs.create returned no id");return{ok:!0,action:"new",tabId:t.id}}const ce="agentState",Tt={load:async()=>{const e=(await chrome.storage.session.get(ce))[ce];return{windows:{...e==null?void 0:e.windows},tabs:[...(e==null?void 0:e.tabs)??[]]}},save:e=>chrome.storage.session.set({[ce]:e})},B=new _t(Tt,{exists:async e=>{try{return await chrome.windows.get(e),!0}catch{return!1}},createWindow:async e=>{const t=await chrome.windows.create({url:e,focused:!1,type:"normal"});return{windowId:t.id,tabId:t.tabs[0].id}},createTab:async(e,t)=>{const n=await chrome.tabs.create({windowId:e,url:t,active:!0});if(typeof n.id!="number")throw new Error("tabs.create returned no id");return n.id}}),$t=e=>B.isAgentWindow(e),St=()=>B.tabIds();async function At(e,t){if(!e)throw $("tabs new: dedicated tabs need a session","TABS_NO_SESSION");return{ok:!0,action:"new",tabId:await B.openTab(e,t)}}chrome.tabs.onCreated.addListener(e=>{e.openerTabId!==void 0&&e.id!==void 0&&B.adopt(e.openerTabId,e.id)});chrome.tabs.onRemoved.addListener(e=>{B.forgetTab(e)});chrome.windows.onRemoved.addListener(e=>{B.forgetWindow(e)});async function It(){const e=await B.takeAll();for(const t of e)try{await chrome.tabs.remove(t)}catch{}return e.length}async function Rt(e){return await chrome.tabs.remove(e),{ok:!0,action:"close",tabId:e}}const Lt=1024,Nt=.7,Ot=550,Ie=10,Pt=16e3,Re=16384,N=200,Ct=12,we=3e3,Le=["#d7263d","#1b998b","#2e5eaa","#f46036","#7b2cbf","#0f7b3e","#c2185b","#5d4037","#00838f","#283593"],Ne=12,T=(e,t,n,o=!1)=>o?L(e,t,{op:"shot",q:n},we):M(e,t,{op:"shot",q:n});async function Dt(e,t){const n=t.format==="png"?"png":"jpeg",o=Math.min(1,Math.max(.1,t.quality??Nt)),r=Math.round(Math.min(4096,Math.max(100,t.maxWidth??Lt)));if(t.full&&t.ref)throw $("screenshot takes ref or full, not both","BAD_PARAMS");const a=await Ut(e),s={url:a.url??"",title:a.title??""};let i;t.full?i=await qt(e,a.windowId,r,!!t.annotate):t.ref?i=await Bt(e,a.windowId,t.ref,r,!!t.annotate):i=await Ft(e,a,r,!!t.annotate),t.annotate&&Ht(i.canvas,i.marks,i.region,i.f);const l=await i.canvas.convertToBlob({type:`image/${n}`,...n==="jpeg"?{quality:o}:{}}),c=new Uint8Array(await l.arrayBuffer());let u="";for(let m=0;m<c.length;m+=32768)u+=String.fromCharCode(...c.subarray(m,m+32768));const h=t.full?await T(e,0,{action:"metrics"}).catch(()=>null):null;return{ok:!0,...s,mode:t.full?"full":t.ref?"element":"viewport",image:{data:btoa(u),mime:`image/${n}`,bytes:c.length,width:i.canvas.width,height:i.canvas.height},viewportWidth:i.metrics.innerWidth,viewportHeight:i.metrics.innerHeight,scale:le(1/i.f,4),origin:{x:le(i.region.x,1),y:le(i.region.y-((h==null?void 0:h.scrollY)??0),1)},...i.extra,...t.annotate?{marks:i.marks.map(m=>({ref:m.ref,role:m.role,name:m.name})),...i.more?{moreMarks:i.more}:{}}:{}}}const le=(e,t)=>Math.round(e*10**t)/10**t;async function Ut(e){let t=await chrome.tabs.get(e);if(!t.active){if(!await $t(t.windowId))throw P("Tab is not the visible tab of its window; screenshot skipped to avoid switching the user's tabs.","NOT_VISIBLE_TAB");t=await chrome.tabs.update(e,{active:!0})??t,await new Promise(o=>setTimeout(o,120))}if((await chrome.windows.get(t.windowId)).state==="minimized")throw P("Window is minimized; nothing to capture.","WINDOW_MINIMIZED");return t}let ue=0;async function me(e){for(let t=0;;t++){const n=ue+Ot-Date.now();n>0&&await new Promise(o=>setTimeout(o,n));try{const o=await chrome.tabs.captureVisibleTab(e,{format:"png"});return ue=Date.now(),await createImageBitmap(await(await fetch(o)).blob())}catch(o){if(ue=Date.now(),t===0&&/MAX_CAPTURE_VISIBLE_TAB_CALLS_PER_SECOND|quota/i.test(String(o)))continue;throw o}}}function ge(e,t,n){let o=Math.max(1,Math.min(n,Math.round(e.w*t))),r=o/e.w;e.h*r>Re&&(r=Re/e.h,o=Math.max(1,Math.round(e.w*r)));const a=new OffscreenCanvas(o,Math.max(1,Math.round(e.h*r))),s=a.getContext("2d");return s.imageSmoothingQuality="high",{canvas:a,ctx:s,f:r}}async function Ft(e,t,n,o){const r=await T(e,0,{action:"metrics"}).catch(()=>null),a=o?await pe(e):{marks:[],more:0},s=await me(t.windowId),i=(r==null?void 0:r.innerWidth)??t.width??s.width,l=(r==null?void 0:r.innerHeight)??t.height??s.height,c={x:0,y:0,w:i,h:l},{canvas:u,ctx:h,f:m}=ge(c,s.width/i,n);return h.drawImage(s,0,0,u.width,u.height),s.close(),{canvas:u,region:c,f:m,metrics:{innerWidth:i,innerHeight:l},...a,extra:{}}}async function Bt(e,t,n,o,r){const{frameId:a,localRef:s}=W(n);let i=await T(e,a,{action:"rect",ref:s});a&&(i=await Wt(e,a,i));const l=await T(e,0,{action:"metrics"}),c=l.innerWidth,u=l.innerHeight,h=Math.max(0,i.x),m=Math.max(0,i.y),f=Math.min(c,i.x+i.w),d=Math.min(u,i.y+i.h);if(f-h<1||d-m<1)throw P(`ref "${n}" is not inside the viewport after scrolling it into view`,"NOT_VISIBLE");const y={x:h,y:m,w:f-h,h:d-m},w=r?await pe(e):{marks:[],more:0},p=await me(t),g=p.width/c,{canvas:b,ctx:k,f:x}=ge(y,g,o);k.drawImage(p,y.x*g,y.y*g,y.w*g,y.h*g,0,0,b.width,b.height),p.close();const I=y.w<i.w-1||y.h<i.h-1,A=w.marks.filter(_=>_.x<f&&_.x+_.w>h&&_.y<d&&_.y+_.h>m);return{canvas:b,region:y,f:x,metrics:l,marks:A,more:w.more,extra:{ref:n,...I?{clipped:!0}:{}}}}async function Wt(e,t,n){var s;const o=await V(e);let r=t,a=n;for(let i=0;r!==0&&i<8;i++){const l=((s=o.find(h=>h.frameId===r))==null?void 0:s.parentFrameId)??0,c=await L(e,r,{op:"frames"},we),u=c.probe?await T(e,l,{action:"frame",nonce:c.probe,rect:a}):null;if(!u)throw P(`could not place frame f${r} in its parent page (the iframe may be hidden or still loading)`,"FRAME_UNMAPPED");a=u,r=l}return a}async function pe(e){const t=await T(e,0,{action:"marks",max:N}),n=[...t.marks];let o=t.more;const r=(await V(e)).filter(a=>a.frameId!==0).slice(0,Ct);if(r.length){const a=new Map;await Promise.all([0,...r.map(c=>c.frameId)].map(async c=>{try{a.set(c,await L(e,c,{op:"frames"},we))}catch{}}));const s=new Map([[0,{x:0,y:0,clip:{x:0,y:0,w:1e6,h:1e6}}]]),i=(c,u=0)=>{var w,p,g;if(s.has(c))return s.get(c);const h=r.find(b=>b.frameId===c),m=(w=a.get(c))==null?void 0:w.probe,f=h&&m&&u<4?i(h.parentFrameId,u+1):null,d=f&&((g=(p=a.get(h.parentFrameId))==null?void 0:p.entries)==null?void 0:g.find(b=>b.nonce===m)),y=f&&d?{x:f.x+d.x,y:f.y+d.y,clip:Oe(f.clip,{x:f.x+d.x,y:f.y+d.y,w:d.w,h:d.h})}:null;return s.set(c,y),y};(await Promise.allSettled(r.map(c=>i(c.frameId)?T(e,c.frameId,{action:"marks",max:N},!0):Promise.reject(new Error("unplaced"))))).forEach((c,u)=>{if(c.status!=="fulfilled")return;const h=r[u].frameId,m=i(h);o+=c.value.more;for(const f of c.value.marks){const d=Oe(m.clip,{x:m.x+f.x,y:m.y+f.y,w:f.w,h:f.h});d.w>=3&&d.h>=3&&n.push({...f,...d,ref:`f${h}:${f.ref}`})}})}return n.length>N&&(o+=n.length-N,n.length=N),{marks:n,more:o}}function Oe(e,t){const n=Math.max(e.x,t.x),o=Math.max(e.y,t.y);return{x:n,y:o,w:Math.max(0,Math.min(e.x+e.w,t.x+t.w)-n),h:Math.max(0,Math.min(e.y+e.h,t.y+t.h)-o)}}async function qt(e,t,n,o){const r=await T(e,0,{action:"metrics"}),a=r.innerWidth,s=r.innerHeight,i=Math.max(s,Math.min(Pt,Ie*s));let l=r.pageHeight;const c=[],u=[],h=new Set;let m=0,f=0,d=0;try{for(let x=0,I=0;I<Ie+2;I++){const A=Math.max(0,Math.min(x,Math.min(l,i)-s)),_=await T(e,0,{action:"scroll",x:0,y:A});if(I>0&&await T(e,0,{action:"pin",hide:!0}),l=Math.max(l,_.pageHeight),o){const Ee=await pe(e);m+=Ee.more;for(const j of Ee.marks)h.has(j.ref)||(h.add(j.ref),u.push({...j,y:j.y+_.scrollY}))}const D=await me(t);f||(d=D.width/a,f=Math.min(n,Math.round(a*d))/a);const G=new OffscreenCanvas(Math.max(1,Math.round(a*f)),Math.max(1,Math.round(s*f)));G.getContext("2d").drawImage(D,0,0,G.width,G.height),D.close(),c.push({y:_.scrollY,canvas:G});const xe=_.scrollY+s;if(xe>=Math.min(l,i)-1||_.scrollY<A-1)break;x=xe}}finally{await T(e,0,{action:"pin",hide:!1}).catch(()=>{}),await T(e,0,{action:"scroll",x:r.scrollX,y:r.scrollY}).catch(()=>{})}const y=c[c.length-1],w=Math.min(i,y.y+s),p={x:0,y:0,w:a,h:w},{canvas:g,ctx:b,f:k}=ge(p,d,Math.round(a*f));for(const x of c)b.drawImage(x.canvas,0,x.y*k,g.width,s*k);return u.length>N&&(m+=u.length-N,u.length=N),{canvas:g,region:p,f:k,metrics:r,marks:u,more:m,extra:{pageHeight:Math.round(l),segments:c.length,...l>w+1?{truncated:!0}:{}}}}function Ht(e,t,n,o){const r=e.getContext("2d");r.font=`bold ${Ne}px sans-serif`,r.textBaseline="top";const a=[],s=e.width,i=e.height,l=Ne+4,c=t.map(u=>({x:(u.x-n.x)*o,y:(u.y-n.y)*o,w:u.w*o,h:u.h*o}));t.forEach((u,h)=>{const m=Le[h%Le.length],f=c[h];r.strokeStyle=m,r.lineWidth=2,r.strokeRect(Math.round(f.x)+1,Math.round(f.y)+1,Math.max(1,Math.round(f.w)-2),Math.max(1,Math.round(f.h)-2));const d=Math.ceil(r.measureText(u.ref).width)+6,y=[{x:f.x,y:f.y-l,w:d,h:l},{x:f.x,y:f.y,w:d,h:l},{x:f.x,y:f.y+f.h,w:d,h:l},{x:f.x+f.w-d,y:f.y-l,w:d,h:l},{x:f.x+f.w-d,y:f.y+f.h,w:d,h:l},{x:f.x-d,y:f.y,w:d,h:l},{x:f.x+f.w,y:f.y,w:d,h:l}].map(p=>({...p,x:Math.round(Math.min(Math.max(0,p.x),s-d)),y:Math.round(Math.min(Math.max(0,p.y),i-l))})),w=y.find(p=>!a.some(g=>fe(g,p))&&!c.some((g,b)=>b!==h&&!Vt(g,f)&&fe(g,p)))??y.find(p=>!a.some(g=>fe(g,p)))??y[0];a.push(w),r.fillStyle=m,r.fillRect(w.x,w.y,w.w,w.h),r.fillStyle="#fff",r.fillText(u.ref,w.x+3,w.y+2)})}const Vt=(e,t)=>e.x<=t.x&&e.y<=t.y&&e.x+e.w>=t.x+t.w&&e.y+e.h>=t.y+t.h,fe=(e,t)=>e.x<t.x+t.w&&t.x<e.x+e.w&&e.y<t.y+t.h&&t.y<e.y+e.h,Xt=4,Gt=20,jt=150,Yt=15e3;async function X(e,t){if(t!=null&&t.ref){const{frameId:r,localRef:a}=W(t.ref);return{frameId:r,ref:a}}const n=t==null?void 0:t.point;if(!n||!Number.isFinite(n.x)||!Number.isFinite(n.y))throw new v("target needs a ref (from browser_view) or x and y (CSS pixels of the viewport)",{code:"BAD_TARGET",short_term:!1});let o={frameId:0,point:{x:n.x,y:n.y}};for(let r=0;r<Xt;r++){const a=await M(e,o.frameId,{op:"hit",x:o.point.x,y:o.point.y});if(!a.frame)break;const s=(await V(e)).filter(c=>c.parentFrameId===o.frameId),l=(await Promise.allSettled(s.map(c=>L(e,c.frameId,{op:"frames"},2e3)))).findIndex(c=>c.status==="fulfilled"&&c.value.probe===a.frame.nonce);if(l<0)break;o={frameId:s[l].frameId,point:{x:a.frame.x,y:a.frame.y}}}return o}function Je(e,t){return t==null?void 0:t.replace(/^\[(e\d+)\]/,(n,o)=>`[${Ve(e,o)}]`)}function se(e){let t=!1,n=!1,o,r=!1;const a=[];let s=null;const i=d=>d.tabId===e&&d.frameId===0,l=d=>{i(d)&&(t=!0,n=!1,o=void 0)},c=d=>{i(d)&&t&&(n=!0,s==null||s())},u=d=>{i(d)&&t&&(n=!0,o=d.error,s==null||s())},h=d=>{i(d)&&(r=!0)},m=d=>{d.openerTabId===e&&d.id!==void 0&&a.push(d.id)};chrome.webNavigation.onBeforeNavigate.addListener(l),chrome.webNavigation.onCompleted.addListener(c),chrome.webNavigation.onErrorOccurred.addListener(u),chrome.webNavigation.onHistoryStateUpdated.addListener(h),chrome.webNavigation.onReferenceFragmentUpdated.addListener(h),chrome.tabs.onCreated.addListener(m);const f=()=>{chrome.webNavigation.onBeforeNavigate.removeListener(l),chrome.webNavigation.onCompleted.removeListener(c),chrome.webNavigation.onErrorOccurred.removeListener(u),chrome.webNavigation.onHistoryStateUpdated.removeListener(h),chrome.webNavigation.onReferenceFragmentUpdated.removeListener(h),chrome.tabs.onCreated.removeListener(m)};return{get started(){return t},async settle(d=Yt){try{t||await Pe(jt),t&&!n&&await Promise.race([new Promise(w=>{s=w}),Pe(d)]);const y={};return t&&!(o&&/ERR_ABORTED/.test(o))&&(y.navigated=!0),t&&!n&&(y.loading=!0),o&&!/ERR_ABORTED/.test(o)&&(y.navigation_error=o),!y.navigated&&r&&(y.same_document=!0),a.length&&(y.opened_tabs=[...a]),y}finally{f()}},dispose:f}}function ye(e){return e instanceof v&&e.code==="NAVIGATION_RACE"||e instanceof Error&&/message channel.*closed|back\/?forward/i.test(e.message)}async function q(e,t,n={}){const o=Math.max(0,Math.min(200,Math.floor(t??Gt)));let r=null,a;try{r=await Ye(e,{})}catch(u){a=u instanceof Error?u.message:String(u)}let s=(r==null?void 0:r.url)??"",i=(r==null?void 0:r.title)??"";if(!s)try{const u=await chrome.tabs.get(e);s=u.url??"",i=u.title??""}catch{}const l=((r==null?void 0:r.interactables)??[]).filter(u=>u.is_new),c={url:s,title:i,...n,interactables:(r==null?void 0:r.total_interactables)??0,new:l.slice(0,o).map(u=>`[${u.ref}] ${u.role}${u.name?` "${u.name.replace(/"/g,'\\"')}"`:""}`)};return l.length>o&&(c.more_new=l.length-o),!a&&je(s)&&(a="This page is browser-internal or otherwise restricted: it cannot be read or controlled."),a&&(c.note=a),c}const Pe=e=>new Promise(t=>setTimeout(t,e)),Kt=E("navigate"),Jt=3e4;async function zt(e,t){const{url:n,timeoutMs:o=Jt}=t;Kt.info(`navigate tab=${e} → ${n}`);try{new URL(n)}catch{throw $(`invalid URL: ${n}`,"INVALID_URL")}return await chrome.tabs.update(e,{url:n}),await Qt(e,o),{ok:!0,...await q(e,t.maxNew)}}function Qt(e,t){return new Promise((n,o)=>{const r=setTimeout(()=>{chrome.tabs.onUpdated.removeListener(a),o(P(`navigation timeout after ${t}ms`,"TIMEOUT"))},t),a=(s,i)=>{s===e&&i.status==="complete"&&(chrome.tabs.onUpdated.removeListener(a),clearTimeout(r),n())};chrome.tabs.onUpdated.addListener(a)})}const Zt=E("click");async function en(e,t){const n=await X(e,t.target);Zt.info(`click tab=${e} frame=${n.frameId} ${n.ref??`point=${n.point.x},${n.point.y}`}`);const o=se(e);let r=null;try{r=await M(e,n.frameId,{op:"click",ref:n.ref,point:n.point,button:t.button,double:t.double})}catch(s){if(!ye(s)&&!o.started)throw o.dispose(),s}const a=await o.settle();return{ok:!0,point:t.target.point??(r==null?void 0:r.point)??{x:0,y:0},...r!=null&&r.effects?{effects:{...r.effects,url_changed:r.effects.url_changed||!!a.navigated}}:{},...r!=null&&r.target?{target:Je(n.frameId,r.target)}:{},...await q(e,t.maxNew,a)}}const tn=E("type");async function nn(e,t){var s;if(!((s=t.target)!=null&&s.ref))throw $("type needs the ref of the field (from browser_view)","BAD_TARGET");const n=await X(e,t.target);tn.info(`type tab=${e} frame=${n.frameId} ref=${n.ref} len=${t.text.length}`);const o=se(e);let r=null;try{r=await M(e,n.frameId,{op:"type",ref:n.ref,text:t.text,clear:t.clear,submit:t.submit})}catch(i){if(!ye(i)&&!o.started)throw o.dispose(),i}const a=await o.settle();return{ok:!0,typed:(r==null?void 0:r.typed)??t.text,...r!=null&&r.effects?{effects:{...r.effects,url_changed:r.effects.url_changed||!!a.navigated}}:{},...await q(e,t.maxNew,a)}}async function on(e,t){const n=se(e);try{await ae(e,{op:"press_key",key:t.key,modifiers:t.modifiers})}catch(o){if(!ye(o)&&!n.started)throw n.dispose(),o}return{ok:!0,key:t.key,...await q(e,t.maxNew,await n.settle())}}const rn=E("select");async function an(e,t){const n=await X(e,t.target);rn.info(`select tab=${e} frame=${n.frameId} ${n.ref??"point"} values=${t.values.join(",")}`);const o=se(e);let r;try{r=await M(e,n.frameId,{op:"select",ref:n.ref,point:n.point,values:t.values})}catch(a){throw o.dispose(),a}return{ok:!0,values:r.values,...await q(e,t.maxNew,await o.settle())}}const sn=E("hover");async function cn(e,t){const n=await X(e,t.target);sn.info(`hover tab=${e} frame=${n.frameId} ${n.ref??`point=${n.point.x},${n.point.y}`}`);const o=await M(e,n.frameId,{op:"hover",ref:n.ref,point:n.point});return{ok:!0,point:t.target.point??o.point,...o.target?{target:Je(n.frameId,o.target)}:{},...await q(e,t.maxNew)}}async function ln(e,t){var r;if(!((r=t.files)!=null&&r.length))throw new Error("files must be a non-empty array");const n=await X(e,t.target),o=await M(e,n.frameId,{op:"set_files",ref:n.ref,point:n.point,files:t.files});return{ok:!0,count:o.count,names:o.names}}const un=200,ee=new Map;function ze(e){let t=ee.get(e);return t||(t={buf:[],waiters:[]},ee.set(e,t)),t}function fn(e,t){const n=ze(e);n.buf.push(t),n.buf.length>un&&n.buf.shift();for(let o=n.waiters.length-1;o>=0;o--){const r=n.waiters[o];r.pattern.test(t.url)&&(clearTimeout(r.timer),n.waiters.splice(o,1),r.resolve(t))}}function dn(e,t={}){const n=ee.get(e);if(!n)return[];let o=n.buf;if(typeof t.sinceMs=="number"){const r=Date.now()-t.sinceMs;o=o.filter(a=>a.ts>=r)}return typeof t.limit=="number"&&(o=o.slice(-t.limit)),o}function hn(e,t,n){return new Promise((o,r)=>{const a=ze(e),s=new RegExp(t);for(let l=a.buf.length-1;l>=0;l--)if(s.test(a.buf[l].url))return o(a.buf[l]);const i=setTimeout(()=>{const l=a.waiters.findIndex(c=>c.timer===i);l>=0&&a.waiters.splice(l,1),r(new Error(`wait_for_request timeout after ${(n/1e3).toFixed(1)}s — no request matched /${t}/`))},n);a.waiters.push({pattern:s,resolve:o,reject:r,timer:i})})}function wn(e){ee.delete(e)}const mn=3e4;async function gn(e,t){const n=t.timeoutMs??1e4,o=performance.now(),r=[];if(t.text||t.refExists||t.urlPattern){let a=0,s=t.refExists;if(s){const i=W(s);a=i.frameId,s=i.localRef}r.push(M(e,a,{op:"wait_for",text:t.text,refExists:s,urlPattern:t.urlPattern,timeoutMs:n},n+2e3).then(i=>({ok:!0,matched:i.matched,elapsedMs:i.elapsedMs})))}if(t.requestPattern&&r.push((async()=>(await hn(e,t.requestPattern,n),{ok:!0,matched:"request",elapsedMs:Math.round(performance.now()-o)}))()),r.length===0){const a=Math.min(Math.max(n,0),mn);return await new Promise(s=>setTimeout(s,a)),{ok:!0,matched:"timeout",elapsedMs:Math.round(performance.now()-o)}}return Promise.race(r)}function pn(e){const t=e.max_steps??25,n=e.step_wait_ms??250;return t*n+5e3}async function yn(e,t){var r;if((r=t.target)!=null&&r.ref){const{frameId:a,localRef:s}=W(t.target.ref),i=await M(e,a,{op:"scroll",ref:s});return{ok:!0,scrollX:i.scrollX,scrollY:i.scrollY,scrolled:i.scrolled,target:i.target}}const n=t.until==="page_end",o=await ae(e,{op:"scroll",y:t.y,dx:t.dx,dy:t.dy,until:t.until,max_steps:t.max_steps,step_wait_ms:t.step_wait_ms},n?pn(t):void 0);return{ok:!0,scrollX:o.scrollX,scrollY:o.scrollY,scrolled:o.scrolled,target:o.target,...o.steps!==void 0?{steps:o.steps}:{},...o.stop_reason!==void 0?{stop_reason:o.stop_reason}:{}}}async function bn(e,t){return{ok:!0,entries:dn(e,{limit:t.limit,sinceMs:t.sinceMs})}}const vn=E("user-scripts"),Qe="browser-attach",_n="script-src 'self' 'unsafe-eval'",Ce=15e3;function be(){let e;try{e=chrome.userScripts}catch{e=void 0}return e?typeof e.execute!="function"||typeof e.configureWorld!="function"?{api:null,reason:"too_old"}:{api:e}:{api:null,reason:"disabled"}}const kn=()=>be().api!==null;let De=null;function Ze(){const{api:e}=be();return e?De??(De=e.configureWorld({worldId:Qe,csp:_n,messaging:!1}).then(()=>!0,t=>(De=null,vn.warn("configureWorld failed",t),!1))):Promise.resolve(!1)}function Ue(e){return e==="too_old"?"The user-script fallback needs Chrome 135 or newer; ask the user to update Chrome.":`The user-script fallback is off. Ask the user to open chrome://extensions/?id=${chrome.runtime.id} and turn on "Allow User Scripts" for browser-attach (Chrome 138+; on Chrome 135-137 turn on Developer mode instead), then retry.`}async function xn(e,t,n,o){var u;const r=be();if(!r.api)throw new v(`${o} ${Ue(r.reason)}`,{code:"USER_SCRIPTS_UNAVAILABLE",short_term:!1});await Ze();const a=`(${En.toString()})(${JSON.stringify(t)}, ${n})`;let s;const i=new Promise((h,m)=>{s=setTimeout(()=>m(new v(`timed out after ${Ce/1e3}s in the user-script world: the expression did not return. It may hang, or return a Promise that never settles.`,{code:"EVAL_TIMEOUT",short_term:!1})),Ce)});let l;try{l=await Promise.race([r.api.execute({target:{tabId:e,frameIds:[0]},js:[{code:a}],world:"USER_SCRIPT",worldId:Qe,injectImmediately:!0}),i])}catch(h){if(h instanceof v)throw h;const m=h instanceof Error?h.message:String(h);throw/developer mode|user ?scripts/i.test(m)?new v(`${o} ${Ue("disabled")}`,{code:"USER_SCRIPTS_UNAVAILABLE",short_term:!1}):new v(`${o} The user-script fallback failed too: ${m}`,{code:"USER_SCRIPT_FAILED",short_term:!1})}finally{clearTimeout(s)}const c=(u=l[0])==null?void 0:u.result;if(!c||typeof c!="object")throw new v(`${o} The user-script world returned no result (the document may have navigated away).`,{code:"USER_SCRIPT_FAILED",short_term:!0});return c}async function En(e,t){const n=s=>s instanceof Error?`${s.name}: ${s.message}`:String(s),o=s=>s instanceof EvalError||/unsafe-eval|Content Security Policy|Trusted Type/i.test(n(s)),r=s=>{try{const i=JSON.stringify(s,(l,c)=>{if(typeof c=="bigint")return c.toString();if(typeof c=="function")return`[Function ${c.name||"anonymous"}]`;if(typeof c=="symbol")return c.toString();if(c instanceof NodeList||c instanceof HTMLCollection)return Array.from(c);if(c instanceof Element){const u=c.outerHTML;return u.length>300?u.slice(0,300)+"…":u}return c instanceof Node?c.nodeType===Node.TEXT_NODE?c.textContent:c.nodeName:c});return i===void 0?null:JSON.parse(i)}catch{return String(s)}};let a;try{a=new Function(`return (${e}
|
|
5
|
+
)`)}catch(s){if(o(s))return{ok:!1,kind:"blocked",message:n(s).slice(0,200)};try{a=new Function(e)}catch(i){return{ok:!1,kind:o(i)?"blocked":"threw",message:n(i).slice(0,500)}}}try{let s=a();return t&&s&&typeof s.then=="function"&&(s=await s),{ok:!0,value:r(s)}}catch(s){return{ok:!1,kind:"threw",message:n(s).slice(0,500)}}}const Mn=new Set(["EVAL_BLOCKED","PAGE_SANDBOXED","MAIN_UNREACHABLE"]),Tn=new Set(["SEND_MESSAGE_FAILED","NO_LISTENER"]);async function $n(e,t){let n;try{return{ok:!0,world:"main",value:(await ae(e,{op:"eval_js",expression:t.expression,awaitPromise:!!t.awaitPromise})).value}}catch(r){if(!(r instanceof v)||!r.code)throw r;if(Tn.has(r.code)&&kn())n="The page content scripts did not answer.";else if(Mn.has(r.code))n=r.message.charAt(0).toUpperCase()+r.message.slice(1);else throw r}const o=await xn(e,t.expression,!!t.awaitPromise,n);if(o.ok)return{ok:!0,world:"user_script",value:o.value,note:`${n} Ran in the user-script world instead: DOM access only, page JS variables are not visible.`};throw o.kind==="blocked"?new v(`${n} The user-script world blocked eval too (${o.message}); it was created before its configuration, so reloading the tab fixes it.`,{code:"EVAL_BLOCKED",short_term:!1}):new v(`the expression threw in the user-script world (DOM only, page JS variables are not visible): ${o.message}`,{code:"EVAL_THREW",short_term:!1})}async function Sn(e,t){const{frameId:n,localRef:o}=W(t.ref);return{ok:!0,values:(await M(e,n,{op:"inspect",ref:o,fields:t.fields})).values}}async function An(e,t){let n=t.url;if(n||(n=(await chrome.tabs.get(e)).url??""),!n)return{ok:!0,cookies:[]};const o=await chrome.cookies.getAll({url:n});return{ok:!0,cookies:(t.name?o.filter(a=>a.name===t.name):o).map(a=>({name:a.name,value:a.value,domain:a.domain,path:a.path,httpOnly:a.httpOnly,secure:a.secure,sameSite:a.sameSite}))}}const In=3e4;async function Rn(e,t){const o=(await chrome.tabs.get(e)).url;if(!o)throw new Error("active tab has no URL");let r,a;try{r=new URL(t.url,o),a=new URL(o)}catch(i){throw $(`invalid URL "${t.url}": ${i instanceof Error?i.message:String(i)}`,"INVALID_URL")}if(r.origin!==a.origin)throw $(`cross-origin not allowed. Active tab is ${a.origin}, request is to ${r.origin}. Navigate to the target origin first.`,"CROSS_ORIGIN_DENIED");const s=await ae(e,{op:"request",url:r.toString(),method:t.method,headers:t.headers,body:typeof t.body=="string"?t.body:void 0,json:t.json},In);return{ok:!0,status:s.status,response_ok:s.ok,headers:s.headers,body:s.body}}async function Ln(e,t){if(!Array.isArray(t.actions)||t.actions.length===0)throw $("actions must be a non-empty array","BATCH_EMPTY");if(t.actions.length>Fe)throw $(`batch size ${t.actions.length} exceeds cap ${Fe}`,"BATCH_TOO_LARGE");const n=t.stop_on_error??!0,o=[];let r="completed",a;for(let s=0;s<t.actions.length;s++){const i=t.actions[s];if(!i||typeof i.name!="string")throw $(`actions[${s}].name must be a string`,"BATCH_INVALID_ITEM");if(i.name==="batch")throw $(`actions[${s}]: batch cannot be nested`,"BATCH_NESTED");const l=await ve(e,i.name,i.input);if(o.push({name:i.name,ok:l.ok,result:l}),!l.ok&&n){r="error",a=s;break}if(l.ok&&(Nn(i.name,i.input)||l.navigated)){r="terminates_sequence",a=s;break}}return{ok:!0,items:o,terminated_at:a,termination_reason:r}}function Nn(e,t){if(e==="navigate")return!0;if(e==="tabs"){const n=t==null?void 0:t.action;return n==="switch"||n==="new"}return!1}const Fe=50;async function ve(e,t,n){try{return await On(e,t,n)}catch(o){const r=dt(o),a=r.message.startsWith("[")?r.message:`[${t}] ${r.message}`;return{ok:!1,error:{...r,message:a}}}}async function On(e,t,n){const o=n;switch(t){case"snapshot":return await Ye(e,o);case"view":return await bt(e,o);case"screenshot":return await Dt(e,o);case"navigate":return await zt(e,o);case"click":return await en(e,o);case"type":return await nn(e,o);case"press_key":return await on(e,o);case"select":return await an(e,o);case"hover":return await cn(e,o);case"upload_file":return await ln(e,o);case"wait_for":return await gn(e,o);case"scroll":return await yn(e,o);case"tabs":return await kt(e,o);case"network_log":return await bn(e,o);case"eval_js":return await $n(e,o);case"inspect":return await Sn(e,o);case"get_cookie":return await An(e,o);case"request":return await Rn(e,o);case"batch":return await Ln(e,o);default:{const r=t;throw new Error(`unknown tool: ${r}`)}}}async function et(){var n;const t=(n=(await chrome.tabs.query({active:!0,lastFocusedWindow:!0}))[0])==null?void 0:n.id;if(typeof t!="number")throw new Error("no active tab");return t}const Be=E("keepalive"),K="quarry-heartbeat",We=4.5;function Pn(){chrome.alarms.get(K).then(e=>{e||(chrome.alarms.create(K,{periodInMinutes:We}),Be.debug(`alarm ${K} installed @ every ${We}min`))}),chrome.alarms.onAlarm.addListener(e=>{e.name===K&&Be.debug("heartbeat tick")})}const Cn=20,Dn="local-2026-10-28T16:29:10.012Z",Un="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",Fn=62*Math.floor(256/62);function te(){const e=[];for(;e.length<22;){const t=new Uint8Array(16);crypto.getRandomValues(t);for(const n of t)if(!(n>=Fn)&&(e.push(Un[n%62]),e.length===22))break}return e.join("")}const R=1,Bn=17329,Wn="/mcp",de="browser-attach.bridge.config",tt={port:Bn,enabled:!0};async function _e(){const t=(await chrome.storage.local.get(de))[de];return{...tt,...t??{}}}const qn=new Set(["127.0.0.1","localhost","[::1]"]);function Hn(e){try{const t=new URL(e);return(t.protocol==="ws:"||t.protocol==="wss:")&&qn.has(t.hostname)}catch{return!1}}function nt(e){return e.url&&Hn(e.url)?e.url:`ws://127.0.0.1:${e.port}${Wn}`}let ot={state:"disabled"};function rt(){return ot}function ne(e){ot=e,chrome.runtime.sendMessage({source:"background",type:"bridge.status",status:e}).catch(()=>{}),Vn(e)}function Vn(e){var a;const t=chrome.action;if(!t)return;const n={open:{text:"●",color:"#16a34a"},connecting:{text:"●",color:"#d97706"},closed:{text:"●",color:"#dc2626"},disabled:{text:"",color:"#000000"}},{text:o,color:r}=n[e.state];t.setBadgeText({text:o}).catch(()=>{}),o&&t.setBadgeBackgroundColor({color:r}).catch(()=>{}),(a=t.setBadgeTextColor)==null||a.call(t,{color:"#ffffff"}).catch(()=>{})}const Xn=E("bridge"),S={socket:null};function O(e){if(!(!S.socket||S.socket.readyState!==WebSocket.OPEN))try{S.socket.send(JSON.stringify(e))}catch(t){Xn.warn("send failed",t)}}function Gn(e,t){const n={v:R,kind:"event",id:te(),topic:e,data:t};O(n)}const jn=E("bridge"),Yn=2e4,qe=45e3;let z=null,he=0;function Kn(){at(),he=Date.now(),z=setInterval(()=>{if(!(!S.socket||S.socket.readyState!==WebSocket.OPEN)){if(Date.now()-he>qe){jn.warn(`no pong in ${qe}ms — forcing reconnect`);try{S.socket.close(4e3,"no_pong")}catch{}return}O({v:R,kind:"ping",id:te(),ts:Date.now()})}},Yn)}function at(){z!==null&&(clearInterval(z),z=null)}function Jn(){he=Date.now()}const zn=120,H=[],oe=new Map;function st(e,t){chrome.runtime.sendMessage({source:"background",type:"activity.event",kind:e,entry:t}).catch(()=>{})}function Qn(e){const t={id:e.id,ts:Date.now(),tool:e.tool,params:e.params,tabId:e.tabId,status:"running"};for(H.push(t),oe.set(t.id,t);H.length>zn;){const n=H.shift();n&&oe.delete(n.id)}return st("add",t),t}function J(e){const t=oe.get(e.id);t&&(t.status=e.ok?"ok":"fail",t.elapsedMs=e.elapsedMs,t.outputPreview=e.outputPreview,t.message=e.message,st("update",t))}function Zn(){return H.slice()}function eo(){H.length=0,oe.clear(),chrome.runtime.sendMessage({source:"background",type:"activity.cleared"}).catch(()=>{})}function to(e,t){var o,r,a;if(t==null)return"";if(typeof t!="object")return String(t).slice(0,80);const n=t;switch(e){case"snapshot":{const s=((o=n.interactables)==null?void 0:o.length)??0,i=n.title??"";return`${s} items${i?` · ${i.slice(0,40)}`:""}`}case"navigate":return n.title??n.url??"ok";case"click":return n.point?`(${Math.round(n.point.x)},${Math.round(n.point.y)})`:"ok";case"type":return`typed ${String(n.typed??"").length} chars`;case"view":return`${n.actions??0} actions · ${n.texts??0} texts`;case"screenshot":{const s=n.image;return`${String(n.mode??"")} ${(s==null?void 0:s.width)??0}x${(s==null?void 0:s.height)??0}`}case"network_log":return`${((r=n.entries)==null?void 0:r.length)??0} entries`;case"tabs":return n.action==="list"?`${((a=n.tabs)==null?void 0:a.length)??0} tabs`:`${String(n.action??"")} #${String(n.tabId??"")}`;case"wait_for":return`matched ${String(n.matched??"")} · ${n.elapsedMs??0}ms`;default:return"ok"}}async function no(e){const t=performance.now(),n=typeof e.tabId=="number"?e.tabId:await et().catch(()=>{});Qn({id:e.id,tool:e.tool,params:e.params,tabId:n});try{if(typeof n!="number"){const a=Math.round(performance.now()-t),s=`[${e.tool}] no active tab`;J({id:e.id,ok:!1,elapsedMs:a,message:s}),O({v:R,kind:"result",id:e.id,ok:!1,message:s,code:"NO_ACTIVE_TAB",short_term:!0,elapsedMs:a});return}const o=await ve(n,e.tool,e.params),r=Math.round(performance.now()-t);if(o.ok)J({id:e.id,ok:!0,elapsedMs:r,outputPreview:to(e.tool,o)}),O({v:R,kind:"result",id:e.id,ok:!0,result:o,elapsedMs:r});else{const{message:a,code:s,short_term:i}=o.error;J({id:e.id,ok:!1,elapsedMs:r,message:a}),O({v:R,kind:"result",id:e.id,ok:!1,message:a,code:s,short_term:i,elapsedMs:r})}}catch(o){const r=o instanceof Error?o.message:String(o),a=Math.round(performance.now()-t);J({id:e.id,ok:!1,elapsedMs:a,message:r}),O({v:R,kind:"result",id:e.id,ok:!1,message:r,short_term:!0,elapsedMs:a})}}const U=E("bridge");let Q=1e3,Z=null,C=tt;async function oo(e){return C={...await _e(),...e},await chrome.storage.local.set({[de]:C}),await ct(),C}async function it(){if(C=await _e(),!C.enabled){ne({state:"disabled"});return}lt()}async function ct(){if(S.socket){try{S.socket.close()}catch{}S.socket=null}Z!==null&&(clearTimeout(Z),Z=null),await it()}const re="agent-tabs-stale";chrome.alarms.onAlarm.addListener(async e=>{var n;if(e.name!==re||((n=S.socket)==null?void 0:n.readyState)===WebSocket.OPEN)return;const t=await It();t&&U.info(`bridge gone for 30s: closed ${t} agent tab(s)`)});function He(e){chrome.alarms.get(re).then(o=>{o||chrome.alarms.create(re,{delayInMinutes:.5})});const t=nt(C),n=Q;ne({state:"closed",url:t,error:e,nextAttemptMs:n}),Z=setTimeout(lt,n),Q=Math.min(Q*2,5e3)}function lt(){if(!C.enabled)return;const e=nt(C),t=rt();let n=0;t.state==="connecting"?n=t.attempt+1:t.state==="closed"&&(n=1),ne({state:"connecting",url:e,attempt:n});let o;try{o=new WebSocket(e)}catch(r){He(r instanceof Error?r.message:String(r));return}S.socket=o,o.addEventListener("open",()=>{U.info("bridge open",{url:e}),Q=1e3,chrome.alarms.clear(re),ne({state:"open",url:e,sinceMs:Date.now()});const r={v:R,kind:"hello",id:te(),client:"extension",extensionVersion:chrome.runtime.getManifest().version??"0.0.0",agentProtocol:Cn,build:Dn};O(r),Kn()}),o.addEventListener("message",r=>{let a;try{a=JSON.parse(typeof r.data=="string"?r.data:String(r.data))}catch(s){U.warn("bad frame",s);return}if(a.v!==R){U.warn("unsupported frame version",a.v);return}a.kind==="command"?no(a).catch(s=>U.error("handleCommand",s)):a.kind==="pong"?Jn():a.kind==="ping"&&O({v:R,kind:"pong",id:te(),ts:Date.now(),echo:a.ts})}),o.addEventListener("close",r=>{U.info("bridge closed",{code:r.code,reason:r.reason}),S.socket=null,at(),He(r.reason||`closed (${r.code})`)}),o.addEventListener("error",()=>{U.warn("bridge socket error")})}const ke=e=>t=>!!t&&typeof t=="object"&&t.source===e&&typeof t.type=="string",ro=ke("sidepanel"),ao=ke("popup"),so=ke("content"),io="quarry-keepalive",F=E("sw");F.info("Service worker booted",{ts:Date.now()});Pn();Ze();it();chrome.runtime.onConnect.addListener(e=>{e.name===io&&(F.debug("keepalive port connected"),e.onDisconnect.addListener(()=>F.debug("keepalive port disconnected")))});chrome.runtime.onMessage.addListener((e,t,n)=>so(e)?(co(e,t),!1):ro(e)||ao(e)?(lo(e).then(n,o=>{F.error("handler error",o),n({source:"background",type:"error",message:o instanceof Error?o.message:String(o)})}),!0):!1);function co(e,t){var n,o;switch(e.type){case"cs:network":{const r=(n=t.tab)==null?void 0:n.id,a=e.entry;typeof r=="number"&&a&&fn(r,a);return}case"agent.stop":{try{Gn("agent.stop",{from:((o=t.tab)==null?void 0:o.id)??null})}catch{}return}default:F.debug("unhandled content message",e.type)}}async function lo(e){switch(e.type){case"ping":return{source:"background",type:"pong",reqId:e.reqId};case"browser_action":{const t=typeof e.tabId=="number"?e.tabId:await et(),n=e.tool,o=e.params??{},r=performance.now(),a=await ve(t,n,o),s=performance.now()-r;return s>1e3&&F.warn(`slow tool: ${n} took ${s.toFixed(0)}ms`),a.ok?{source:"background",type:"browser_action.result",reqId:e.reqId,tool:n,ok:!0,elapsedMs:s,result:a}:{source:"background",type:"browser_action.result",reqId:e.reqId,tool:n,ok:!1,elapsedMs:s,message:a.error.message,code:a.error.code,short_term:a.error.short_term}}case"bridge.status.get":return{source:"background",type:"bridge.status",reqId:e.reqId,status:rt()};case"bridge.config.get":{const t=await _e();return{source:"background",type:"bridge.config",reqId:e.reqId,config:t}}case"bridge.config.set":{const t=await oo(e.config);return{source:"background",type:"bridge.config",reqId:e.reqId,config:t}}case"bridge.reconnect":return await ct(),{source:"background",type:"ok",reqId:e.reqId};case"activity.get":return{source:"background",type:"activity.list",reqId:e.reqId,entries:Zn()};case"activity.clear":return eo(),{source:"background",type:"ok",reqId:e.reqId};default:return F.warn("unknown message type",e.type),{source:"background",type:"error",reqId:e.reqId,message:`unknown type: ${e.type}`}}}chrome.tabs.onRemoved.addListener(e=>{wn(e)});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
(function(){var _e=Object.defineProperty;var Te=(t,e,n)=>e in t?_e(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var rt=(t,e,n)=>Te(t,typeof e!="symbol"?e+"":e,n);const F=chrome==null?void 0:chrome.dom;var X,qt;const Mt=(qt=(X=F==null?void 0:F.openOrClosedShadowRoot)==null?void 0:X.bind)==null?void 0:qt.call(X,F);function _(t){if(t.shadowRoot)return t.shadowRoot;if(Mt)try{return Mt(t)}catch{return null}return null}const Lt=new WeakMap;function Vt(){const t=[],e=n=>{for(const r of Array.from(n.querySelectorAll("*"))){const o=_(r);if(o&&e(o),!(r instanceof HTMLIFrameElement||r.tagName==="FRAME"))continue;const i=r;t.push({nonce:lt(i),src:i.src,name:i.name,...Kt(i)})}};return document.documentElement&&e(document),t}function lt(t){var n;let e=Lt.get(t);e||(e=crypto.randomUUID(),Lt.set(t,e));try{(n=t.contentWindow)==null||n.postMessage({__frameProbe:e},"*")}catch{}return e}function Kt(t){const e=t.getBoundingClientRect(),n=getComputedStyle(t);return{x:e.x+t.clientLeft+(parseFloat(n.paddingLeft)||0),y:e.y+t.clientTop+(parseFloat(n.paddingTop)||0),w:t.clientWidth,h:t.clientHeight}}const B={nonce:null};addEventListener("message",t=>{var e;t.source===window.parent&&window.parent!==window&&typeof((e=t.data)==null?void 0:e.__frameProbe)=="string"&&(B.nonce=t.data.__frameProbe)});function Ae(){return{ok:!0,entries:Vt(),probe:B.nonce}}const jt=crypto.randomUUID();function*dt(t){const e=t instanceof Element?t:t.firstElementChild;if(!e)return;const n=[e];if(!(t instanceof Element)){let r=e.nextElementSibling;for(;r;)n.push(r),r=r.nextElementSibling;n.reverse()}for(;n.length>0;){const r=n.pop();yield r;const o=r.children;for(let c=o.length-1;c>=0;c--)n.push(o[c]);const i=_(r);if(i){const c=i.children;for(let s=c.length-1;s>=0;s--)n.push(c[s])}}}const Ce=new Set(["button","a","input","textarea","select"]),Me=new Set(["button","link","textbox","checkbox","radio","combobox","menuitem","tab","option","switch"]);function Gt(t,e=80){return t.length>e?t.slice(0,e-1).trimEnd()+"…":t}function zt(t){const e=t.getAttribute("role");return e?e.toLowerCase():null}function A(t){var o;const e=t.tagName.toLowerCase(),n=e==="a"&&!t.hasAttribute("href");if(Ce.has(e)&&!n)return!(e==="input"&&(t.getAttribute("type")??"").toLowerCase()==="hidden");const r=zt(t);if(r&&Me.has(r)||t.getAttribute("contenteditable")==="true"||t.hasAttribute("onclick")||t.hasAttribute("tabindex"))return!0;try{if(getComputedStyle(t).cursor==="pointer"&&(t.getAttribute("aria-label")||t.getAttribute("title")||(o=t.innerText)!=null&&o.trim())){const c=t.parentElement;if(c)try{if(getComputedStyle(c).cursor==="pointer")return!1}catch{}return!0}}catch{}return!1}function R(t){const e=zt(t);if(e)return e;switch(t.tagName.toLowerCase()){case"main":return"main";case"dialog":return"dialog";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return"heading";case"a":return t.hasAttribute("href")?"link":"generic";case"button":return"button";case"select":return"combobox";case"textarea":return"textbox";case"input":{const r=(t.getAttribute("type")??"text").toLowerCase();return["button","submit","reset","image"].includes(r)?"button":r==="checkbox"?"checkbox":r==="radio"?"radio":r==="file"?"file":"textbox"}}return t.getAttribute("contenteditable")==="true"?"textbox":"generic"}function H(t,e=80){return Gt(ke(t),e)}function Le(t,e=80){var i,c,s,a;const n=(i=t.getAttribute("aria-labelledby"))==null?void 0:i.trim().split(/\s+/).map(u=>{var l,d;return((d=(l=t.ownerDocument.getElementById(u))==null?void 0:l.textContent)==null?void 0:d.trim())??""}).join(" ").trim(),r=t.labels,o=n||((c=t.getAttribute("aria-label"))==null?void 0:c.trim())||(r!=null&&r.length?Array.from(r).map(u=>{var l;return((l=u.textContent)==null?void 0:l.trim())??""}).join(" ").trim():"")||((s=t.getAttribute("title"))==null?void 0:s.trim())||((a=t.getAttribute("alt"))==null?void 0:a.trim())||"";return Gt(o.replace(/\s+/g," "),e)}function ke(t){var l;const e=t.tagName.toLowerCase(),n=(l=t.getAttribute("aria-labelledby"))==null?void 0:l.trim().split(/\s+/).map(d=>{var h,f;return((f=(h=t.ownerDocument.getElementById(d))==null?void 0:h.textContent)==null?void 0:f.trim())??""}).join(" ");if(n!=null&&n.trim())return n.trim();const r=t.getAttribute("aria-label");if(r!=null&&r.trim())return r.trim();const o=t.labels;if(o!=null&&o.length)return Array.from(o).map(d=>{var f;const h=d.cloneNode(!0);return h.querySelectorAll("input, select, textarea").forEach(P=>P.remove()),((f=h.textContent)==null?void 0:f.trim())??""}).join(" ");const i=t.getAttribute("placeholder");if(i!=null&&i.trim())return i.trim();const c=t.getAttribute("alt");if(c!=null&&c.trim())return c.trim();const s=t.getAttribute("title");if(s!=null&&s.trim())return s.trim();if((e==="input"||e==="textarea"||e==="select")&&!G(t)){const d=t.value;if(d!=null&&d.trim())return d.trim()}const a=t.innerText;if(a!=null&&a.trim())return a.trim().replace(/\s+/g," ");const u=t.id;return u?`<${e}#${u}>`:`<${e}>`}function Zt(t){return t.disabled===!0||t.getAttribute("aria-disabled")==="true"?!0:t.hasAttribute("disabled")}const Se=/\b(current-password|new-password|one-time-code|cc-number|cc-csc)\b/i;function G(t){return t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement?t instanceof HTMLInputElement&&t.type==="password"?!0:Se.test(t.getAttribute("autocomplete")??""):!1}const ft="[redacted]";function ht(t){const e=Ie(t);return e&&G(t)?ft:e}function Ie(t){const e=t.tagName.toLowerCase();if(e==="input"||e==="textarea"||e==="select"){const n=t.value;if(typeof n=="string")return n}}function U(t){const e=t.getBoundingClientRect();return e.width<=0||e.height<=0?null:{x:e.left,y:e.top,width:e.width,height:e.height}}function q(t,e){if(e.width<=0||e.height<=0)return!1;const n=getComputedStyle(t);return!(n.display==="none"||n.visibility==="hidden"||n.visibility==="collapse"||parseFloat(n.opacity||"1")===0)}function $e(t){const e=window.innerWidth,n=window.innerHeight;return t.x<e&&t.y<n&&t.x+t.width>0&&t.y+t.height>0}function kt(t){const e=window.innerWidth,n=window.innerHeight;if($e(t))return 0;const r=t.x+t.width/2,o=t.y+t.height/2,i=Math.max(0,r<0?-r:r>e?r-e:0),c=Math.max(0,o<0?-o:o>n?o-n:0);return Math.sqrt(i*i+c*c)}const mt=Symbol("quarry.ref"),E=new Map;let V=0;function pt(){for(const[t,e]of E){const n=e.deref();(!n||!n.isConnected)&&E.delete(t)}}function Ne(){return V+=1,`e${V}`}function Re(t,e){try{t[mt]=e}catch{}E.set(e,new WeakRef(t))}function z(t){const e=t[mt];if(typeof e=="string"){if(!E.has(e)){E.set(e,new WeakRef(t));const r=parseInt(e.slice(1),10);Number.isFinite(r)&&r>V&&(V=r)}return{ref:e,is_new:!1}}const n=Ne();return Re(t,n),{ref:n,is_new:!0}}function Z(t){const e=t.includes(":")?t.split(":")[1]:t,n=E.get(e);if(n){const o=n.deref();if(o&&o.isConnected)return o;E.delete(e)}const r=Jt(document,e);return r&&E.set(e,new WeakRef(r)),r}function Jt(t,e){const n=t.querySelectorAll("*");for(let r=0;r<n.length;r++){const o=n[r];if(o[mt]===e)return o;const i=_(o);if(i){const c=Jt(i,e);if(c)return c}}return null}const He=1e6;function Pe(t={}){var c;pt();const e=t.budget??He,n=[];for(const s of dt(document)){if(!A(s))continue;const a=U(s);a&&q(s,a)&&n.push({el:s,bounds:a,distance:kt(a)})}const r=new Set(n.map(s=>s.el));for(const s of((c=t.extra)==null?void 0:c.call(t))??[]){if(r.has(s))continue;const a=U(s);a&&q(s,a)&&(r.add(s),n.push({el:s,bounds:a,distance:kt(a)}))}n.sort((s,a)=>s.distance-a.distance);const o=[],i=Math.min(n.length,e);for(let s=0;s<i;s++){const a=n[s],{ref:u,is_new:l}=z(a.el);o.push({ref:u,role:R(a.el),name:H(a.el),tag:a.el.tagName.toLowerCase(),value:ht(a.el),disabled:Zt(a.el),bounds:[a.bounds.x,a.bounds.y,a.bounds.x+a.bounds.width,a.bounds.y+a.bounds.height],...l?{is_new:!0}:{}})}return{documentId:jt,coverage:{matched:n.length,returned:o.length,truncated:n.length>i},url:location.href,title:document.title,interactables:o}}function ot(){return new Promise(t=>{if(document.readyState!=="loading")return t();document.addEventListener("DOMContentLoaded",()=>t(),{once:!0})})}class m extends Error{constructor(n,r={}){super(n);rt(this,"code");rt(this,"short_term");this.name="ActionError",this.code=r.code,this.short_term=r.short_term??!0}}function C(t){const e=Z(t);if(!e)throw new m(`ref "${t}" not found in DOM. The page may have changed — re-run snapshot or find before retrying.`,{code:"STALE_REF",short_term:!0});return e}function wt(t,e){let n=document.elementsFromPoint(t,e).find(r=>!r.closest('[id^="__quarry_"]'))??null;for(let r=n;r&&_(r)&&(r=_(r).elementFromPoint(t,e),!(!r||r===n));)n=r;return n}function J(t){if(t.ref)return{el:C(t.ref),ref:t.ref};const e=t.point;if(!e||!Number.isFinite(e.x)||!Number.isFinite(e.y))throw new m("a target needs ref or x/y",{code:"BAD_TARGET",short_term:!1});if(e.x<0||e.y<0||e.x>=innerWidth||e.y>=innerHeight)throw new m(`point (${e.x}, ${e.y}) is outside the ${innerWidth}x${innerHeight} viewport (CSS pixels)`,{code:"OUT_OF_VIEWPORT",short_term:!1});const n=wt(e.x,e.y);if(!n)throw new m(`nothing at point (${e.x}, ${e.y})`,{code:"NOT_FOUND",short_term:!0});return{el:n,at:{x:e.x,y:e.y},ref:z(n).ref}}function St(t){return t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement}function De(t){const e=wt(t.x,t.y);if(!e||!(e instanceof HTMLIFrameElement||e.tagName==="FRAME"))return{};const n=Kt(e);return{frame:{nonce:lt(e),x:t.x-n.x,y:t.y-n.y}}}const Qt=new Set(["H1","H2","H3","H4","H5","H6"]),Oe=new Set(["P","BLOCKQUOTE","FIGCAPTION"]),Fe=new Set(["LI","DT","DD","TD","TH","SUMMARY"]);function It(t){var r;const e=t.tagName;if(e==="PRE")return"pre";if(Qt.has(e))return"heading";if(Oe.has(e))return"paragraph";const n=(r=t.getAttribute("role"))==null?void 0:r.toLowerCase();return n==="heading"?"heading":n==="paragraph"?"paragraph":null}function We(t){const e=t.tagName;if(Qt.has(e))return parseInt(e.slice(1),10);const n=parseInt(t.getAttribute("aria-level")||"2",10);return Math.max(1,Math.min(6,isNaN(n)?2:n))}function Ye(t){var n;if(Fe.has(t.tagName))return!0;const e=(n=t.getAttribute("role"))==null?void 0:n.toLowerCase();return e==="listitem"||e==="cell"||e==="gridcell"||e==="rowheader"||e==="columnheader"}function Xe(t){var r;const e=t.tagName;if(e==="LI")return"li";if(e==="DT")return"dt";if(e==="DD")return"dd";if(e==="TD")return"td";if(e==="TH")return"th";if(e==="SUMMARY")return"summary";const n=(r=t.getAttribute("role"))==null?void 0:r.toLowerCase();return n==="listitem"?"li":n==="rowheader"||n==="columnheader"?"th":"td"}function Be(t){var o;const e=t.tagName,n=((o=t.getAttribute("role"))==null?void 0:o.toLowerCase())||"",r=(t.getAttribute("aria-label")||"").trim();return e==="MAIN"||n==="main"?{role:"main",label:r}:e==="NAV"||n==="navigation"?{role:"navigation",label:r}:e==="ASIDE"||n==="complementary"?{role:"complementary",label:r}:e==="ARTICLE"||n==="article"?{role:"article",label:r}:n==="banner"?{role:"banner",label:r}:n==="contentinfo"?{role:"contentinfo",label:r}:n==="region"&&r?{role:"region",label:r}:n==="search"?{role:"search",label:r}:n==="form"&&r?{role:"form",label:r}:e==="HEADER"&&!t.closest("article, section")?{role:"banner",label:r}:e==="FOOTER"&&!t.closest("article, section")?{role:"contentinfo",label:r}:e==="SECTION"&&r?{role:"region",label:r}:null}const N={map:null};function Ue(t){if(!N.map)return getComputedStyle(t);let e=N.map.get(t);return e||(e=getComputedStyle(t),N.map.set(t,e)),e}function yt(t){for(const e of x(t))if(!gt(e)&&(A(e)&&b(e)||yt(e)))return!0;return!1}function*x(t){for(const n of t.children)yield n;const e=_(t);if(e)for(const n of e.children)yield n}function b(t){const e=U(t);return e?q(t,e):!1}function gt(t){if(t!==document.body&&t.getAttribute("aria-hidden")==="true")return!0;const e=Ue(t);return e.display==="none"||e.visibility==="hidden"||e.visibility==="collapse"||parseFloat(e.opacity||"1")===0}function qe(t){if(t.children.length>0)return!1;const e=_(t);return!e||e.children.length===0}const bt=8,it={hit:!1};function k(t){return" ".repeat(Math.min(t,bt))}function p(t){return t.replace(/"/g,'\\"')}function xt(t){const e=(t||"").trim().replace(/\s+/g," ");return e.length>300&&(it.hit=!0),e.length>300?e.slice(0,300)+"…":e}function Ve(t){const e=[];for(const n of t.childNodes){if(n.nodeType!==3)continue;const r=(n.nodeValue||"").replace(/\s+/g," ").trim();r&&e.push(r)}return e.join(" ")}function te(t,e){if(e)return e;const n=t.getAttribute("title");if(n)return n.trim().slice(0,80);if(t.children.length===1&&t.children[0].tagName==="IMG"){const o=t.children[0].getAttribute("alt");if(o)return o.trim().slice(0,80)}const r=t.getAttribute("href");if(r){const o=r.replace(/[?#].*$/,"").replace(/\/$/,"").split("/").pop();if(o)return o.slice(0,80)}return""}function T(t,e){const n=e.getBoundingClientRect();if(n.bottom<=0||n.top>=innerHeight||n.right<=0||n.left>=innerWidth)return;const r=t.lines.length-1;t.viewport[0]<0&&(t.viewport[0]=r),t.viewport[1]=r}const Et=t=>t.within?` (in ${t.within})`:"";function Ke(t,e,n,r,o){const i=r?` "${p(r)}"`:"";t.lines.push(`${k(o)}- ${n}${i}:`),T(t,e)}function ct(t,e,n,r){const o=R(e);r??(r=te(e,H(e)));const{ref:i}=z(e),c=e instanceof HTMLInputElement&&(e.type==="checkbox"||e.type==="radio"),s=c?void 0:ht(e),a=Zt(e);let u=`${k(n)}- ${o}`;return a&&(u+=" (disabled)"),r&&(u+=`: "${p(r)}"`),u+=` [${i}]`,s&&(u+=` = ${JSON.stringify(s).slice(0,80)}`),c&&(u+=e.checked?" (checked)":" (unchecked)"),t.lines.push(u),T(t,e),t.actions++,i}function W(t,e,n,r,o=0){const i=xt(e.innerText??e.textContent);if(!i)return;const c=k(r);let s;n==="heading"?s=`${c}- h${Math.max(1,Math.min(6,o||2))}: "${p(i)}"`:n==="paragraph"?s=`${c}- p: "${p(i)}"`:n==="li"?s=`${c}- li: "${p(i)}"`:n==="blockquote"?s=`${c}- > "${p(i)}"`:n==="td"?s=`${c}- td: "${p(i)}"`:n==="th"?s=`${c}- th: "${p(i)}"`:n==="dt"?s=`${c}- dt: "${p(i)}"`:n==="dd"?s=`${c}- dd: "${p(i)}"`:n==="summary"?s=`${c}- summary: "${p(i)}"`:s=`${c}- text: "${p(i)}"`,t.lines.push(s+Et(t)),T(t,e),t.texts++}function je(t,e,n){const o=(e.innerText??e.textContent??"").replace(/\s+$/,"").split(`
|
|
2
|
+
`).map(c=>c.replace(/\s+$/,""));for(;o.length&&!o[0].trim();)o.shift();if(!o.length)return;const i=k(n);t.lines.push(`${i}- pre: |${Et(t)}`),T(t,e);for(const c of o)t.lines.push(`${i} ${c}`);T(t,e),t.texts++}function $t(t,e,n){if(!b(e))return;const r=xt(Ve(e));r&&r.length>=2&&(t.lines.push(`${k(n)}- text: "${p(r)}"${Et(t)}`),T(t,e),t.texts++)}const Ge=500,ze=new Set(["INPUT","SELECT","TEXTAREA","OPTION"]),ee=t=>t.id.startsWith("__quarry_"),ne=t=>t.tagName==="IFRAME"||t.tagName==="FRAME";function re(t,e,n){if(!b(e)||e.clientWidth<2||e.clientHeight<2)return;const r=e.src.replace(/^https?:\/\//,"").replace(/[?#].*$/,""),o=(e.getAttribute("title")||e.getAttribute("name")||r||"frame").trim().slice(0,80);t.lines.push(`${k(n)}- iframe "${p(o)}" {{frame:${lt(e)}}}`),T(t,e)}function st(t,e,n){if(!(gt(e)||ee(e))){if(ne(e))return re(t,e,n);if(A(e)){b(e)&&ct(t,e,n);return}for(const r of x(e))st(t,r,n)}}function oe(t,e,n,r=!1){if(!b(e)){for(const l of x(e))M(t,l,n);return}const o=(e.innerText??e.textContent??"").trim();if(!(r||!ze.has(e.tagName)&&(yt(e)||o.length>80&&e.children.length>0))){ct(t,e,n);return}const c=Le(e),s=ct(t,e,n,r?void 0:c&&o.includes(c.replace(/…$/,"").slice(0,40))?"":c),a=t.within;t.within=o.length<=Ge?s:null;const u=Math.min(n+1,bt);for(const l of x(e))M(t,l,u);t.within=a}function M(t,e,n){if(gt(e)||ee(e))return;if(ne(e))return re(t,e,n);if(A(e)&&!(e.getAttribute("tabindex")==="-1"&&It(e)&&!e.hasAttribute("onclick")&&!e.hasAttribute("role")))return oe(t,e,n);const r=Be(e),o=r?Math.min(n+1,bt):n;r&&Ke(t,e,r.role,r.label,n);const i=It(e);if(i==="heading"){b(e)&&W(t,e,"heading",o,We(e));for(const c of x(e))st(t,c,o);return}if(i==="paragraph"||i==="pre"){b(e)&&(i==="pre"?je(t,e,o):W(t,e,"paragraph",o));for(const c of x(e))st(t,c,o);return}if(Ye(e)){const c=Xe(e);if(yt(e)){$t(t,e,o);for(const s of x(e))M(t,s,o)}else b(e)&&W(t,e,c,o);return}if(qe(e)){if(b(e)){const c=xt(e.innerText??e.textContent);c&&c.length>=2&&W(t,e,"text",o)}return}$t(t,e,o);for(const c of x(e))M(t,c,o)}function Ze(){const t=document.contentType||"text/html";if(/html|xml|svg/i.test(t)||!document.body)return null;const e=document.body,n=e.querySelector(":scope > pre");let r=(n==null?void 0:n.textContent)??e.innerText;if(/json/i.test(t)&&r.length<5e6)try{r=JSON.stringify(JSON.parse(r),null,2)}catch{}return r}function Je(t={}){it.hit=!1,pt();const e={url:location.href,title:document.title,contentType:document.contentType,...B.nonce?{probe:B.nonce}:{}},n=t.ref?null:Ze();if(n!==null){const r=n.split(`
|
|
3
|
+
`),o=Math.max(1,document.documentElement.scrollHeight),i=Math.floor(scrollY/o*r.length),c=Math.min(r.length-1,Math.ceil((scrollY+innerHeight)/o*r.length));return{...e,kind:"text",actions:0,texts:r.length,truncated:!1,content:n,viewport:[i,c]}}N.map=new Map;try{const r={lines:[],actions:0,texts:0,within:null,viewport:[-1,-1]};if(t.ref){const o=Z(t.ref);if(!o)throw new m(`ref "${t.ref}" not found in DOM. The page may have changed — call browser_view again.`,{code:"STALE_REF",short_term:!0});A(o)?oe(r,o,0,!0):M(r,o,0)}else document.body&&M(r,document.body,0);return{...e,kind:"html",actions:r.actions,texts:r.texts,truncated:it.hit,content:r.lines.join(`
|
|
4
|
+
`),...r.viewport[0]>=0?{viewport:r.viewport}:{}}}finally{N.map=null}}const Nt=()=>new Promise(t=>requestAnimationFrame(()=>t())),vt=async()=>{await Nt(),await Nt()};async function Qe(t){switch(t.action){case"rect":return en(t.ref);case"frame":return nn(t.nonce,t.rect);case"marks":return on(t.max);case"metrics":return Rt();case"scroll":return scrollTo({left:t.x,top:t.y,behavior:"instant"}),await vt(),Rt();case"pin":return cn(t.hide)}}function Rt(){var e;const t=document.scrollingElement??document.documentElement;return{scrollX,scrollY,innerWidth,innerHeight,pageHeight:Math.max(t.scrollHeight,((e=document.body)==null?void 0:e.scrollHeight)??0),dpr:devicePixelRatio}}const tn=t=>t.top>=0&&t.left>=0&&t.bottom<=innerHeight&&t.right<=innerWidth;async function en(t){const e=C(t);let n=e.getBoundingClientRect();if(n.width<=0||n.height<=0)throw new m(`ref "${t}" has no size on the page (hidden or collapsed)`,{code:"NOT_VISIBLE"});return tn(n)||(e.scrollIntoView({block:n.height>innerHeight?"start":"center",inline:n.width>innerWidth?"start":"center",behavior:"instant"}),await vt(),n=e.getBoundingClientRect()),{x:n.x,y:n.y,w:n.width,h:n.height,vw:innerWidth,vh:innerHeight}}async function nn(t,e){const n=()=>Vt().find(d=>d.nonce===t);let r=n();if(!r)return null;const o=()=>({x:r.x+e.x,y:r.y+e.y,w:e.w,h:e.h,vw:innerWidth,vh:innerHeight}),i=o();(i.y<0||i.x<0||i.y+i.h>innerHeight||i.x+i.w>innerWidth)&&(scrollBy({left:i.x<0||i.x+i.w>innerWidth?i.x+i.w/2-innerWidth/2:0,top:i.y+Math.min(i.h,innerHeight)/2-innerHeight/2,behavior:"instant"}),await vt(),r=n()??r);const c=o(),s=Math.max(c.x,r.x),a=Math.max(c.y,r.y),u=Math.min(c.x+c.w,r.x+r.w),l=Math.min(c.y+c.h,r.y+r.h);return{...c,x:s,y:a,w:Math.max(0,u-s),h:Math.max(0,l-a)}}function rn(t,e){const n=[[.5,.5],[.25,.25],[.75,.25],[.25,.75],[.75,.75]];for(const[r,o]of n){const i=e.x+e.w*r,c=e.y+e.h*o;let s=wt(i,c);if(s){for(let a=s;a;a=a.parentNode??(a instanceof ShadowRoot?a.host:null))if(a===t)return!0;if(s instanceof Element&&s.contains(t))return!0}}return!1}function on(t=200){pt();const e=[];let n=0;for(const r of dt(document)){if(r.id.startsWith("__quarry_")||r.tagName==="IFRAME"||r.tagName==="FRAME"||!A(r))continue;const o=U(r);if(!o||!q(r,o))continue;const i=Math.max(0,o.x),c=Math.max(0,o.y),s=Math.min(innerWidth,o.x+o.width),a=Math.min(innerHeight,o.y+o.height);if(s-i<3||a-c<3)continue;const u={x:i,y:c,w:s-i,h:a-c};if(!(r.closest('[aria-hidden="true"]')||!rn(r,u))){if(e.length>=t){n++;continue}e.push({ref:z(r).ref,role:R(r),name:te(r,H(r,60)),...u})}}return{marks:e,more:n}}const S=new Map;function cn(t){const e=new Set;if(t){const n=innerWidth*innerHeight;for(const r of dt(document)){if(!(r instanceof HTMLElement)||r.id.startsWith("__quarry_"))continue;const o=getComputedStyle(r);if(o.position!=="fixed"&&o.position!=="sticky")continue;const i=r.getBoundingClientRect();if(!(i.width<=0||i.height<=0)&&!(i.width*i.height>n*.5)){if(o.position==="sticky"){const c=parseFloat(o.top),s=parseFloat(o.bottom);if(!(Number.isFinite(c)&&Math.abs(i.top-c)<1.5||Number.isFinite(s)&&Math.abs(innerHeight-i.bottom-s)<1.5))continue}e.add(r)}}}for(const[n,r]of S)e.has(n)||(r.value?n.style.setProperty("visibility",r.value,r.priority):n.style.removeProperty("visibility"),S.delete(n));for(const n of e)S.has(n)||(S.set(n,{value:n.style.getPropertyValue("visibility"),priority:n.style.getPropertyPriority("visibility")}),n.style.setProperty("visibility","hidden","important"));return{hidden:S.size}}function Q(t){var e;return((e=t.ownerDocument)==null?void 0:e.defaultView)||window}const Ht=4,K=3,ie=8,ce=20,sn=30,an=80,un=50,ln=130,dn=80,fn=120;function I(t,e){return t+Math.random()*(e-t)}function $(t){return new Promise(e=>setTimeout(e,t))}function tt(t){const e=t.getBoundingClientRect();return{x:e.left+e.width/2,y:e.top+e.height/2}}function se(t){return{x:t.x+(Math.random()-.5)*Ht,y:t.y+(Math.random()-.5)*Ht}}function v(t){return{bubbles:!0,cancelable:!0,composed:!0,clientX:t.clientX,clientY:t.clientY,screenX:t.clientX,screenY:t.clientY,button:t.button??0,buttons:t.buttons??0,pointerType:t.pointerType??"mouse",isPrimary:!0}}async function ae(t,e={}){const n=Q(t),r=n.PointerEvent||PointerEvent,o=n.MouseEvent||MouseEvent,{x:i,y:c}=e.at??se(tt(t)),s=e.button==="right"?2:e.button==="middle"?1:0,a=e.button==="right"?2:e.button==="middle"?4:1,u=v({clientX:i,clientY:c});t.dispatchEvent(new r("pointerover",u)),t.dispatchEvent(new o("mouseover",u)),t.dispatchEvent(new r("pointerenter",u)),t.dispatchEvent(new o("mouseenter",u));for(let f=1;f<=K;f++){const D=6*(1-f/K),O=i+(Math.random()-.5)*D,ve=c+(Math.random()-.5)*D,Ct=v({clientX:O,clientY:ve});t.dispatchEvent(new r("pointermove",Ct)),t.dispatchEvent(new o("mousemove",Ct)),await $(I(ie,ce))}await $(I(sn,an));const l=v({clientX:i,clientY:c,button:s,buttons:a});t.dispatchEvent(new r("pointerdown",l)),t.dispatchEvent(new o("mousedown",l));try{t.focus({preventScroll:!0})}catch{}await $(I(un,ln));const d=v({clientX:i,clientY:c,button:s,buttons:0});t.dispatchEvent(new r("pointerup",d)),t.dispatchEvent(new o("mouseup",d));const h=v({clientX:i,clientY:c,button:s,buttons:0});e.button!=="right"?(t.dispatchEvent(new o("click",h)),e.double&&(await $(I(dn,fn)),t.dispatchEvent(new o("click",h)),t.dispatchEvent(new o("dblclick",h)))):t.dispatchEvent(new o("contextmenu",h))}async function hn(t,e){const n=Q(t),r=n.PointerEvent||PointerEvent,o=n.MouseEvent||MouseEvent,{x:i,y:c}=e??se(tt(t)),s=v({clientX:i,clientY:c});t.dispatchEvent(new r("pointerover",s)),t.dispatchEvent(new o("mouseover",s)),t.dispatchEvent(new r("pointerenter",s)),t.dispatchEvent(new o("mouseenter",s));for(let a=1;a<=K;a++){const l=6*(1-a/K),d=i+(Math.random()-.5)*l,h=c+(Math.random()-.5)*l,f=v({clientX:d,clientY:h});t.dispatchEvent(new r("pointermove",f)),t.dispatchEvent(new o("mousemove",f)),await $(I(ie,ce))}}async function mn(t){try{await ae(t);try{t.focus({preventScroll:!0})}catch{}return!0}catch{return!1}}function Pt(t,e){const n=t instanceof HTMLTextAreaElement?HTMLTextAreaElement.prototype:HTMLInputElement.prototype,r=Object.getOwnPropertyDescriptor(n,"value"),o=r==null?void 0:r.set;o?o.call(t,e):t.value=e}function at(t,e,n="insertText"){const o=Q(t).InputEvent||InputEvent;try{t.dispatchEvent(new o("beforeinput",{bubbles:!0,cancelable:!0,composed:!0,data:e,inputType:n}))}catch{}try{t.dispatchEvent(new o("input",{bubbles:!0,cancelable:!1,composed:!0,data:e,inputType:n}))}catch{t.dispatchEvent(new Event("input",{bubbles:!0}))}}function ue(t){t.dispatchEvent(new Event("change",{bubbles:!0}))}const Dt={Enter:{key:"Enter",code:"Enter",keyCode:13,text:"\r"},Tab:{key:"Tab",code:"Tab",keyCode:9,text:" "},Escape:{key:"Escape",code:"Escape",keyCode:27},Backspace:{key:"Backspace",code:"Backspace",keyCode:8},Delete:{key:"Delete",code:"Delete",keyCode:46},ArrowLeft:{key:"ArrowLeft",code:"ArrowLeft",keyCode:37},ArrowRight:{key:"ArrowRight",code:"ArrowRight",keyCode:39},ArrowUp:{key:"ArrowUp",code:"ArrowUp",keyCode:38},ArrowDown:{key:"ArrowDown",code:"ArrowDown",keyCode:40},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:" "}};function pn(t){if(Dt[t])return Dt[t];if(t.length===1){const e=t.toUpperCase(),n=/[A-Z]/.test(e);return{key:t,code:n?`Key${e}`:`Digit${t}`,keyCode:e.charCodeAt(0),text:t}}throw new Error(`unknown key: ${t}`)}function ut(t,e){var s,a,u,l;const n=pn(e.key),o=(t instanceof Element?Q(t):t.defaultView||window).KeyboardEvent||KeyboardEvent,i={altKey:((s=e.modifiers)==null?void 0:s.includes("alt"))??!1,ctrlKey:((a=e.modifiers)==null?void 0:a.includes("ctrl"))??!1,metaKey:((u=e.modifiers)==null?void 0:u.includes("meta"))??!1,shiftKey:((l=e.modifiers)==null?void 0:l.includes("shift"))??!1},c={key:n.key,code:n.code,keyCode:n.keyCode??0,which:n.keyCode??0,bubbles:!0,cancelable:!0,composed:!0,...i};t.dispatchEvent(new o("keydown",c)),n.text&&t.dispatchEvent(new o("keypress",c)),t.dispatchEvent(new o("keyup",c))}const Ot="__quarry_indicators_installed__";let y=null,g=null,w=null,j=!1,le=-1,de=-1;const fe=2147483646,wn=2147483647;function et(){return window.top===window}function yn(){et()&&(window[Ot]||(window[Ot]=!0,he()))}function he(){if(document.getElementById("__quarry_indicators_styles__"))return;const t=`
|
|
5
|
+
@keyframes __quarry_glow_pulse {
|
|
6
|
+
0%, 100% { box-shadow:
|
|
7
|
+
inset 0 0 12px rgba(217, 119, 87, 0.45),
|
|
8
|
+
inset 0 0 24px rgba(217, 119, 87, 0.28),
|
|
9
|
+
inset 0 0 36px rgba(217, 119, 87, 0.12); }
|
|
10
|
+
50% { box-shadow:
|
|
11
|
+
inset 0 0 18px rgba(217, 119, 87, 0.65),
|
|
12
|
+
inset 0 0 30px rgba(217, 119, 87, 0.45),
|
|
13
|
+
inset 0 0 42px rgba(217, 119, 87, 0.18); }
|
|
14
|
+
}
|
|
15
|
+
@keyframes __quarry_fade_in { from { opacity: 0 } to { opacity: 1 } }
|
|
16
|
+
@keyframes __quarry_fade_out { from { opacity: 1 } to { opacity: 0 } }
|
|
17
|
+
@keyframes __quarry_slide_up { from { transform: translate(-50%, 16px); opacity: 0 } to { transform: translate(-50%, 0); opacity: 1 } }
|
|
18
|
+
`,e=document.createElement("style");e.id="__quarry_indicators_styles__",e.textContent=t,(document.head||document.documentElement).appendChild(e)}function gn(){if(y&&y.isConnected)return y;const t=document.createElement("div");return t.id="__quarry_glow__",t.setAttribute("aria-hidden","true"),Object.assign(t.style,{position:"fixed",inset:"0",pointerEvents:"none",zIndex:String(fe),opacity:"0",transition:"opacity 240ms cubic-bezier(0.2, 0, 0, 1)",animation:"__quarry_glow_pulse 2.4s ease-in-out infinite"}),document.body.appendChild(t),y=t,t}function me(){if(g&&g.isConnected)return g;const t=document.createElement("div");return t.id="__quarry_cursor__",t.setAttribute("aria-hidden","true"),Object.assign(t.style,{position:"fixed",top:"0",left:"0",width:"20px",height:"26px",pointerEvents:"none",zIndex:String(fe),opacity:"0",transform:"translate3d(-100px, -100px, 0)",transition:"transform 180ms cubic-bezier(0.2, 0, 0, 1), opacity 200ms ease-out",willChange:"transform, opacity"}),t.innerHTML=`
|
|
19
|
+
<svg width="20" height="26" viewBox="0 0 20 26" style="position:absolute;top:0;left:0;overflow:visible;
|
|
20
|
+
filter: drop-shadow(0 0 4px rgba(217,119,87,0.55)) drop-shadow(0 1px 3px rgba(0,0,0,0.35));">
|
|
21
|
+
<path d="M0 0 L0 18 L4.5 14 L7.5 21.5 L11 20 L8 13 L14 13 Z"
|
|
22
|
+
stroke="white" stroke-width="2.5" stroke-linejoin="round" fill="#D97757"/>
|
|
23
|
+
</svg>
|
|
24
|
+
`,document.body.appendChild(t),g=t,t}function bn(){if(w&&w.isConnected)return w;const t=document.createElement("div");t.id="__quarry_stop__",Object.assign(t.style,{position:"fixed",bottom:"20px",left:"50%",transform:"translate(-50%, 16px)",pointerEvents:"none",zIndex:String(wn),opacity:"0",transition:"opacity 200ms ease-out, transform 240ms cubic-bezier(0.2, 0, 0, 1)"});const e=document.createElement("button");return e.type="button",e.id="__quarry_stop_btn__",e.innerHTML=`
|
|
25
|
+
<svg width="14" height="14" viewBox="0 0 256 256" fill="currentColor" style="margin-right:8px;vertical-align:middle">
|
|
26
|
+
<path d="M128 20a108 108 0 1 0 108 108A108.12 108.12 0 0 0 128 20Zm0 192a84 84 0 1 1 84-84 84.09 84.09 0 0 1-84 84Zm40-112v56a12 12 0 0 1-12 12h-56a12 12 0 0 1-12-12v-56a12 12 0 0 1 12-12h56a12 12 0 0 1 12 12Z"/>
|
|
27
|
+
</svg>
|
|
28
|
+
<span style="vertical-align:middle">Stop browser-attach</span>
|
|
29
|
+
`,Object.assign(e.style,{pointerEvents:"auto",cursor:"pointer",userSelect:"none",display:"inline-flex",alignItems:"center",padding:"10px 16px",fontSize:"13px",fontWeight:"600",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',color:"#141413",background:"#FAF9F5",border:"0.5px solid rgba(31, 30, 29, 0.30)",borderRadius:"12px",boxShadow:"0 24px 48px rgba(217, 119, 87, 0.28), 0 4px 14px rgba(217, 119, 87, 0.20)",transition:"background 160ms ease-out, transform 120ms ease-out"}),e.addEventListener("mouseenter",()=>{e.style.background="#F5F4F0"}),e.addEventListener("mouseleave",()=>{e.style.background="#FAF9F5"}),e.addEventListener("mousedown",()=>{e.style.transform="scale(0.97)"}),e.addEventListener("mouseup",()=>{e.style.transform="scale(1)"}),e.addEventListener("click",()=>{try{chrome.runtime.sendMessage({source:"content",type:"agent.stop"})}catch{}}),t.appendChild(e),document.body.appendChild(t),w=t,t}function pe(){if(!et())return;if(!document.body){document.addEventListener("DOMContentLoaded",()=>pe(),{once:!0});return}he();const t=gn(),e=me(),n=bn();requestAnimationFrame(()=>{t.style.opacity="1",le>=0&&de>=0&&(e.style.opacity="1"),n.style.opacity="1",n.style.transform="translate(-50%, 0)"}),j=!0}function xn(){et()&&(j=!1,y&&(y.style.opacity="0"),g&&(g.style.opacity="0"),w&&(w.style.opacity="0",w.style.transform="translate(-50%, 16px)"),setTimeout(()=>{if(!j){try{y==null||y.remove()}catch{}try{g==null||g.remove()}catch{}try{w==null||w.remove()}catch{}y=null,g=null,w=null}},360))}function _t(t,e){if(!et()||(le=t,de=e,!j))return;const n=me();n.style.transform=`translate3d(${t-2}px, ${e-2}px, 0)`,n.style.opacity="1"}const En=400;function we(t){var u;const e=location.href,n=document.activeElement,r=((u=window.__quarry_dialogs__)==null?void 0:u.captured.length)??0;let o=0,i=0,c=0,s=!1;const a=new MutationObserver(l=>{for(const d of l)d.type==="childList"?(i+=d.addedNodes.length,c+=d.removedNodes.length,t&&t.contains(d.target)&&(s=!0)):(d.type==="attributes"||d.type==="characterData")&&(o+=1)});try{a.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,characterData:!0})}catch{}return{stop:()=>new Promise(l=>{let d=!1;const h=P=>{var O;if(d)return;d=!0,a.disconnect(),window.removeEventListener("pagehide",f);const D=((O=window.__quarry_dialogs__)==null?void 0:O.captured.length)??0;l({mutations:o+i+c,attr_mutations:o,added_nodes:i,removed_nodes:c,target_subtree_changed:s,url_changed:P||location.href!==e,focus_changed:document.activeElement!==n,dialog_opened:D>r})},f=()=>h(!0);window.addEventListener("pagehide",f,{once:!0}),setTimeout(()=>h(),En)})}}const vn=350,_n=400,Tn=600,An=450,ye="#b88150",Cn="rgba(184,129,80,0.10)";function Tt(t,e){try{const n="__rip_"+Date.now()+Math.random().toString(36).slice(2,6),r=document.createElement("style");r.id=n+"_s",r.textContent=`@keyframes ${n}{0%{transform:scale(0.6);opacity:0.95;border-width:1.5px}100%{transform:scale(1.9);opacity:0;border-width:0.5px}}`,document.head.appendChild(r);const o=document.createElement("div");o.style.cssText=["position:fixed",`left:${t}px`,`top:${e}px`,"width:18px","height:18px","margin:-9px 0 0 -9px","border-radius:50%",`border:1.5px solid ${ye}`,"background:transparent","pointer-events:none","z-index:2147483647","will-change:transform,opacity",`animation:${n} 620ms cubic-bezier(0.16,1,0.3,1) forwards`].join(";"),document.documentElement.appendChild(o),setTimeout(()=>{try{o.remove(),r.remove()}catch{}},700)}catch{}}function nt(t,e=An){try{const n=Z(t);if(!n)return;const r=n.getBoundingClientRect();if(r.width<=0||r.height<=0)return;const o=document.createElement("div");o.style.cssText=["position:fixed",`left:${r.left-1}px`,`top:${r.top-1}px`,`width:${r.width}px`,`height:${r.height}px`,`border:1px solid ${ye}`,`background:${Cn}`,"border-radius:3px","pointer-events:none","z-index:2147483647","opacity:0","transition:opacity 140ms cubic-bezier(0.4,0,0.2,1)"].join(";"),document.documentElement.appendChild(o),requestAnimationFrame(()=>{o.style.opacity="1"}),setTimeout(()=>{try{o.style.opacity="0",setTimeout(()=>{try{o.remove()}catch{}},160)}catch{}},e)}catch{}}function At(t){const e=getComputedStyle(t),n=e.overflowY!=="visible"&&e.overflowY!=="clip",r=e.overflowX!=="visible"&&e.overflowX!=="clip";if(!n&&!r)return!1;const o=t.scrollHeight-t.clientHeight>10,i=t.scrollWidth-t.clientWidth>10;return n&&o||r&&i}function L(t){if(!At(t))return!1;const e=t.scrollTop;t.scrollTop=e+1;const n=t.scrollTop!==e;if(t.scrollTop=e,n)return!0;const r=t.scrollLeft;t.scrollLeft=r+1;const o=t.scrollLeft!==r;return t.scrollLeft=r,o}function ge(t){let e=t.parentElement;for(;e;){if(L(e))return e;e=e.parentElement}return null}function Mn(t){const e=[...Array.from(t.children)];let n=null;for(;e.length;){const r=e.shift();if(At(r)&&L(r)){const o=r.getBoundingClientRect(),i=o.width*o.height;(!n||i>n.area)&&(n={el:r,area:i})}for(const o of r.children)e.push(o)}return(n==null?void 0:n.el)??null}function be(){const t=[document.querySelector("main"),document.querySelector('[role="main"]'),document.scrollingElement,document.documentElement,document.body];for(const r of t)if(r instanceof Element&&L(r))return r;const e=[],n=document.querySelectorAll("*");for(let r=0;r<n.length;r++){const o=n[r];if(!At(o))continue;const i=o.getBoundingClientRect();i.width<200||i.height<200||e.push({el:o,area:i.width*i.height})}e.sort((r,o)=>o.area-r.area);for(const r of e.slice(0,8))if(L(r.el))return r.el;return null}function xe(t){const e=t.tagName.toLowerCase();if(t.id)return`${e}#${t.id}`;if(typeof t.className=="string"&&t.className.trim()){const n=t.className.trim().split(/\s+/)[0];if(n)return`${e}.${n}`}return e}function Ft(t,e,n,r){const o=t.scrollTop,i=t.scrollLeft;typeof r=="number"?t.scrollTop=r:(t.scrollTop=o+n,t.scrollLeft=i+e);const c=t.scrollTop!==o||t.scrollLeft!==i;return{scrollX:t.scrollLeft,scrollY:t.scrollTop,scrolled:c,target:c?xe(t):"none"}}function Wt(t,e,n){const r=window.scrollX,o=window.scrollY;typeof n=="number"?window.scrollTo(0,n):window.scrollBy(t,e);const i=window.scrollX!==r||window.scrollY!==o;return{scrollX:window.scrollX,scrollY:window.scrollY,scrolled:i,target:i?"window":"none"}}function Ln(t){const e=L(t)?t:ge(t);if(e&&e!==document.scrollingElement&&e!==document.documentElement&&e!==document.body){const i=e.scrollTop,c=e.scrollLeft,s=t.getBoundingClientRect(),a=e.getBoundingClientRect(),u=i+(s.top-a.top)-(e.clientHeight-s.height)/2,l=c+(s.left-a.left)-(e.clientWidth-s.width)/2;e.scrollTop=Math.max(0,u),e.scrollLeft=Math.max(0,l);const d=e.scrollTop!==i||e.scrollLeft!==c;return{scrollX:e.scrollLeft,scrollY:e.scrollTop,scrolled:d,target:d?xe(e):"none"}}const n=window.scrollY,r=window.scrollX;try{t.scrollIntoView({block:"center",inline:"center",behavior:"instant"})}catch{}const o=window.scrollX!==r||window.scrollY!==n;return{scrollX:window.scrollX,scrollY:window.scrollY,scrolled:o,target:o?"window":"none"}}function kn(t){if(t.until==="page_end")return Sn(t.max_steps??25,t.step_wait_ms??250);const e=t.dx??0,n=t.dy??0,r=e!==0||n!==0,o=typeof t.y=="number";if(t.ref&&(r||o)){const i=C(t.ref),c=(L(i)?i:null)??Mn(i)??ge(i);return c?Ft(c,e,n,t.y):Wt(e,n,t.y)}if(t.ref)return Ln(C(t.ref));if(r||o){const i=Wt(e,n,t.y);if(i.scrolled)return i;const c=be();return c?Ft(c,e,n,t.y):i}return{scrollX:window.scrollX,scrollY:window.scrollY,scrolled:!1,target:"none"}}async function Sn(t,e){const n=be()??document.scrollingElement??document.documentElement,r=n===document.scrollingElement||n===document.documentElement,o=Math.max(120,Math.floor(window.innerHeight*.8)),i=u=>new Promise(l=>setTimeout(l,u));let c=0,s=0,a="max_steps";for(let u=0;u<t;u++){const l=r?window.scrollY:n.scrollTop;r?window.scrollBy(0,o):n.scrollTop=l+o,await i(e),c++;const d=r?window.scrollY:n.scrollTop;if(d!==l)s=0;else if(s++,s>=2){a="idle";break}const f=r?document.documentElement.scrollHeight-window.innerHeight:n.scrollHeight-n.clientHeight;if(d>=f-1){a="page_end";break}}return{scrollX:r?window.scrollX:n.scrollLeft,scrollY:r?window.scrollY:n.scrollTop,scrolled:c>0,target:r?"window":n.tagName.toLowerCase(),steps:c,stop_reason:a}}function In(t){const e=C(t.ref),n={};for(const r of t.fields)n[r]=$n(e,r);return{values:n}}function $n(t,e){switch(e){case"text":{const n=t.tagName.toLowerCase();return n==="input"||n==="textarea"||n==="select"?ht(t)??null:(t.innerText??t.textContent??"").trim()||null}case"value":{const n=t.value;return typeof n=="string"?n&&G(t)?ft:n:null}case"tag":return t.tagName.toLowerCase();case"role":return R(t);case"name":return H(t);case"checked":return t.checked?"true":"false";case"disabled":return t.disabled||t.getAttribute("aria-disabled")==="true"||t.hasAttribute("disabled")?"true":"false";case"html":return Yt(t,"outer");case"innerHtml":return Yt(t,"inner");case"has_handler":return Dn(t);default:return t.getAttribute(e)}}const Nn=new Set(["id","role","href","src","type","name","value","placeholder","alt","title","target","rel","disabled","readonly","checked","required","selected","multiple","hidden","for","lang","dir","contenteditable","tabindex","open","data-testid"]),Rn=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]);function Hn(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<")}function Pn(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function Yt(t,e){const n=o=>{let i="";for(const c of o.childNodes)c.nodeType===Node.TEXT_NODE?i+=Pn(c.nodeValue||""):c.nodeType===Node.ELEMENT_NODE&&(i+=r(c));return i},r=o=>{const i=o.tagName.toLowerCase();let c="";for(const s of Array.from(o.attributes))(Nn.has(s.name)||s.name.startsWith("aria-"))&&(c+=` ${s.name}="${s.name==="value"&&s.value&&G(o)?ft:Hn(s.value)}"`);return Rn.has(i)?`<${i}${c}>`:`<${i}${c}>${n(o)}</${i}>`};return e==="outer"?r(t):n(t)}function Dn(t){if(typeof t.onclick=="function")return"native";if(t.hasAttribute("onclick"))return"inline";for(const e of Object.keys(t)){if(e.startsWith("__reactProps")){const n=t[e];if(n&&typeof n=="object"&&"onClick"in n)return"react"}if(e.startsWith("__reactInternalInstance")||e.startsWith("__reactFiber"))return"react"}return A(t)?"semantic":"none"}const On=500,Xt=15e3,Fn=globalThis,Y=new Map;let Bt=!1;function Wn(t){return t.ready?Promise.resolve(!0):new Promise(e=>{const n=i=>{clearTimeout(o),t.port.removeEventListener("message",r),e(i)},r=i=>{var c;((c=i.data)==null?void 0:c.ready)===!0&&n(!0)},o=setTimeout(()=>n(t.ready),On);t.port.addEventListener("message",r)})}function Yn(){return self.origin==="null"?new m("this page is sandboxed (CSP sandbox): page scripts are disabled, so its MAIN world cannot run eval_js; reloading does not help.",{code:"PAGE_SANDBOXED",short_term:!1}):new m("the page MAIN world did not answer (page scripts disabled, or content scripts left stale by an extension reload).",{code:"MAIN_UNREACHABLE",short_term:!1})}async function Xn(t){const e=Fn.__attachEvalPort;if(!e||!await Wn(e))throw Yn();Bt||(Bt=!0,e.port.addEventListener("message",o=>{var c;const i=typeof((c=o.data)==null?void 0:c.id)=="string"?Y.get(o.data.id):void 0;i&&(Y.delete(o.data.id),i(o.data))}));const n=crypto.randomUUID(),r=await new Promise(o=>{const i=setTimeout(()=>{Y.delete(n),o(null)},Xt);Y.set(n,c=>{clearTimeout(i),o(c)}),e.port.postMessage({id:n,expression:t.expression,awaitPromise:!!t.awaitPromise})});if(!r)throw new m(`timed out after ${Xt/1e3}s: the expression did not return. It may hang, or return a Promise that never settles.`,{code:"EVAL_TIMEOUT",short_term:!1});if(r.ok)return{value:r.value};throw r.kind==="blocked"?new m(`this page's Content Security Policy forbids eval in the page MAIN world (${/Trusted Type/i.test(r.message)?"Trusted Types required":"no 'unsafe-eval'"}).`,{code:"EVAL_BLOCKED",short_term:!1}):new m(`the expression threw in the page MAIN world: ${r.message}`,{code:"EVAL_THREW",short_term:!1})}function Bn(t,e){const n=atob(t),r=new ArrayBuffer(n.length),o=new Uint8Array(r);for(let i=0;i<n.length;i++)o[i]=n.charCodeAt(i);return new Blob([r],{type:e})}function Un(t){var i;const e=J(t).el,n=e instanceof HTMLLabelElement&&e.control?e.control:((i=e.closest("label"))==null?void 0:i.control)??e;if(!(n instanceof HTMLInputElement)||n.type!=="file")throw new m(`target is not an <input type="file"> (got <${n.tagName.toLowerCase()} type="${n.type??""}">)`,{code:"WRONG_ELEMENT_KIND",short_term:!1});const r=[];for(const c of t.files){const s=c.mimeType||"application/octet-stream",a=Bn(c.data,s);r.push(new File([a],c.name,{type:s}))}const o=new DataTransfer;for(const c of r)o.items.add(c);return n.files=o.files,n.dispatchEvent(new Event("change",{bubbles:!0})),{count:r.length,names:r.map(c=>c.name)}}async function qn(t){const e=(t.method??"GET").toUpperCase(),n={...t.headers??{}};let r;t.json!==void 0?(n["Content-Type"]=n["Content-Type"]??"application/json",r=JSON.stringify(t.json)):typeof t.body=="string"&&(r=t.body);const o={method:e,headers:n,credentials:"include",mode:"same-origin"};r!==void 0&&e!=="GET"&&e!=="HEAD"&&(o.body=r);let i;try{i=await fetch(t.url,o)}catch(a){throw new m(`fetch failed: ${a instanceof Error?a.message:String(a)}`)}const c={};i.headers.forEach((a,u)=>{c[u]=a});const s=await i.text().catch(()=>"");return{status:i.status,ok:i.ok,headers:c,body:s}}const Vn=200,Kn=1e4;function jn(t){const e=t.timeoutMs??Kn,n=performance.now(),r=()=>t.text&&document.body&&document.body.innerText.includes(t.text)?"text":t.refExists&&Z(t.refExists)?"ref":t.urlPattern&&new RegExp(t.urlPattern).test(location.href)?"url":null;return new Promise((o,i)=>{const c=r();if(c)return o({matched:c,elapsedMs:0});const s=setInterval(()=>{const a=r();if(a){clearInterval(s),o({matched:a,elapsedMs:Math.round(performance.now()-n)});return}performance.now()-n>=e&&(clearInterval(s),i(new m(`wait_for timeout after ${e}ms`)))},Vn)})}async function Gn(t){const{el:e,at:n,ref:r}=J(t);if(!n)try{e.scrollIntoView({block:"center",inline:"center",behavior:"instant"})}catch{}nt(r,vn);const o=n?Ee(e,r):void 0,i=n??tt(e);_t(i.x,i.y);const c=we(e);await ae(e,{button:t.button,double:t.double,at:n}),Tt(i.x,i.y);const s=await c.stop();return{point:i,effects:s,...o?{target:o}:{}}}function Ee(t,e){const n=H(t);return`[${e}] ${R(t)}${n?` "${n}"`:""}`}async function zn(t){var o,i;const e=C(t.ref);try{e.scrollIntoView({block:"center",inline:"center",behavior:"instant"})}catch{}nt(t.ref,_n);const n=we(e);if(await mn(e),t.clear&&St(e))Pt(e,""),at(e,"","deleteContentBackward");else if(t.clear&&e.isContentEditable){const c=window.getSelection(),s=document.createRange();s.selectNodeContents(e),c==null||c.removeAllRanges(),c==null||c.addRange(s),(o=document.execCommand)==null||o.call(document,"delete")}if(t.text.length>0)if(St(e))Pt(e,(e.value||"")+t.text),at(e,t.text,"insertText");else if(e.isContentEditable)(i=document.execCommand)==null||i.call(document,"insertText",!1,t.text);else for(const c of t.text)try{ut(document,{key:c})}catch{}t.submit&&ut(e,{key:"Enter"}),ue(e);const r=await n.stop();return{typed:t.text,effects:r}}async function Zn(t){const{el:e,at:n,ref:r}=J(t);if(!n)try{e.scrollIntoView({block:"center",inline:"center",behavior:"instant"})}catch{}nt(r,Tn);const o=n?Ee(e,r):void 0,i=n??tt(e);return _t(i.x,i.y),await hn(e,n),Tt(i.x,i.y),{point:i,...o?{target:o}:{}}}function Jn(t){const e=document.activeElement&&document.activeElement!==document.body?document.activeElement:document;return ut(e,{key:t.key,modifiers:t.modifiers}),{key:t.key}}function Qn(t){const e=J(t).el,n=e.closest("select")??e;if(!(n instanceof HTMLSelectElement))throw new m(`target is not a <select> element (got <${n.tagName.toLowerCase()}>)`,{code:"WRONG_ELEMENT_KIND",short_term:!1});const r=[];let o=!1;for(const i of Array.from(n.options)){const c=t.values.includes(i.value)||t.values.includes(i.label);i.selected!==c&&(o=!0),i.selected=c,c&&r.push(i.value)}return o&&(at(n,"","insertText"),ue(n)),{values:r}}const Ut="__quarry_cs_init__",tr="__quarry_net__";window[Ut]||(window[Ut]=!0,er(),nr(),yn());function er(){chrome.runtime.onMessage.addListener((t,e,n)=>rr(t)?(or(t).then(r=>n({ok:!0,data:r}),r=>{const o=r instanceof Error?r.message:String(r),i=r&&typeof r=="object"&&"code"in r&&typeof r.code=="string"?r.code:void 0,c=r&&typeof r=="object"&&"short_term"in r&&typeof r.short_term=="boolean"?r.short_term:void 0;n({ok:!1,message:o,code:i,short_term:c})}),!0):!1)}function nr(){window.addEventListener("message",t=>{if(t.origin!==window.location.origin)return;const e=t.data;if(!(!e||e.channel!==tr||e.kind!=="entry"))try{chrome.runtime.sendMessage({source:"content",type:"cs:network",entry:e.entry})}catch{}})}function rr(t){return!!t&&typeof t=="object"&&t.__quarry===!0&&typeof t.op=="string"}async function or(t){switch(t.op){case"frames":return Ae();case"snapshot":return await ot(),Pe({budget:t.budget});case"click":return Gn(t);case"type":return zn(t);case"hover":return Zn(t);case"press_key":return Jn(t);case"scroll":return kn(t);case"select":return Qn(t);case"eval_js":return Xn(t);case"view":return await ot(),{...Je({ref:t.ref}),documentId:jt};case"shot":return await ot(),Qe(t.q);case"wait_for":return jn(t);case"inspect":return In(t);case"request":return qn(t);case"set_files":return Un(t);case"hit":return De(t);case"indicators.show":return pe(),{ok:!0};case"indicators.hide":return xn(),{ok:!0};case"indicators.cursor":return _t(t.x,t.y),{ok:!0};case"indicator.flash":return typeof t.x=="number"&&typeof t.y=="number"?Tt(t.x,t.y):t.ref&&nt(t.ref,t.durationMs??450),{ok:!0};default:{const e=t;throw new Error(`unknown content-script op: ${e.op}`)}}}
|
|
30
|
+
})()
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
(function(){const c="__quarry_main_init__",f="__attach_eval__",d="__quarry_dialogs__";let u=null;window[c]||(window[c]=!0,l(),p());function l(){const r=e=>{var n,o;if(u||((n=e.data)==null?void 0:n.channel)!==f||!((o=e.ports)!=null&&o[0]))return;e.stopImmediatePropagation(),window.removeEventListener("message",r,!0);const i=u=e.ports[0];i.onmessage=async t=>{var s;typeof((s=t.data)==null?void 0:s.id)=="string"&&i.postMessage({id:t.data.id,...await g(String(t.data.expression),!!t.data.awaitPromise)})},i.postMessage({ready:!0})};window.addEventListener("message",r,!0)}async function g(r,e){const i=t=>t instanceof Error?`${t.name}: ${t.message}`:String(t),n=t=>t instanceof EvalError||/unsafe-eval|Content Security Policy|Trusted Type/i.test(i(t));let o;try{o=new Function(`return (${r}
|
|
2
|
+
)`)}catch(t){if(n(t))return{ok:!1,kind:"blocked",message:i(t).slice(0,200)};try{o=new Function(r)}catch(s){return{ok:!1,kind:n(s)?"blocked":"threw",message:i(s).slice(0,500)}}}try{let t=o();return e&&t&&typeof t.then=="function"&&(t=await t),{ok:!0,value:w(t)}}catch(t){return{ok:!1,kind:"threw",message:i(t).slice(0,500)}}}function w(r){try{const e=JSON.stringify(r,(i,n)=>{if(typeof n=="bigint")return n.toString();if(typeof n=="function")return`[Function ${n.name||"anonymous"}]`;if(typeof n=="symbol")return n.toString();if(n instanceof NodeList||n instanceof HTMLCollection)return Array.from(n);if(n instanceof Element){const o=n.outerHTML;return o.length>300?o.slice(0,300)+"…":o}return n instanceof Node?n.nodeType===Node.TEXT_NODE?n.textContent:n.nodeName:n});return e===void 0?null:JSON.parse(e)}catch{return String(r)}}function p(){window[d]={captured:[]},window.alert=function(r){a({type:"alert",message:String(r??""),ts:Date.now()})},window.confirm=function(r){return a({type:"confirm",message:String(r??""),ts:Date.now()}),!0},window.prompt=function(r,e){return a({type:"prompt",message:String(r??""),defaultValue:e==null?void 0:String(e),ts:Date.now()}),e==null?"":String(e)}}function a(r){const e=window[d];e&&e.captured.push(r)}
|
|
3
|
+
})()
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(){const u="__quarry_net_patch_init__",d="__quarry_net__";function f(o){try{window.postMessage({channel:d,kind:"entry",entry:o},window.location.origin)}catch{}}window[u]||(window[u]=!0,h(),p());function h(){const o=window.fetch;if(typeof o!="function")return;const n=async function(...i){const s=Date.now(),[t,e]=i,r=typeof t=="string"?t:t instanceof URL?t.toString():t.url,l=((e==null?void 0:e.method)??(t==null?void 0:t.method)??"GET").toUpperCase();let a;try{const c=await o.apply(this,i);return a=c.status,c}finally{f({ts:s,method:l,url:r,status:a,type:"fetch",durationMs:Date.now()-s})}};try{Object.defineProperty(n,"toString",{value:()=>o.toString(),writable:!1,configurable:!1}),Object.defineProperty(n,"name",{value:o.name||"fetch"})}catch{}window.fetch=n}function p(){const o=window.XMLHttpRequest;if(typeof o!="function")return;const n=o.prototype,i=n.open,s=n.send;n.open=function(...t){const[e,r]=t;return this.__quarry_meta={method:String(e||"GET").toUpperCase(),url:typeof r=="string"?r:r instanceof URL?r.toString():String(r),startTs:Date.now()},i.apply(this,t)},n.send=function(t){const e=this.__quarry_meta,r=()=>{e&&f({ts:e.startTs,method:e.method,url:e.url,status:this.status,type:"xhr",durationMs:Date.now()-e.startTs})};return this.addEventListener("loadend",r,{once:!0}),s.call(this,t)};try{Object.defineProperty(n.open,"toString",{value:()=>i.toString(),writable:!1,configurable:!1}),Object.defineProperty(n.send,"toString",{value:()=>s.toString(),writable:!1,configurable:!1})}catch{}}
|
|
2
|
+
})()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 3,
|
|
3
|
+
"name": "browser-attach",
|
|
4
|
+
"version": "0.1.2",
|
|
5
|
+
"description": "Lets AI coding agents like Claude Code and Codex work in your own Chrome, in their own window. Needs the browser-attach CLI.",
|
|
6
|
+
"icons": {
|
|
7
|
+
"16": "icons/icon-16.png",
|
|
8
|
+
"32": "icons/icon-32.png",
|
|
9
|
+
"48": "icons/icon-48.png",
|
|
10
|
+
"128": "icons/icon-128.png"
|
|
11
|
+
},
|
|
12
|
+
"permissions": [
|
|
13
|
+
"tabs",
|
|
14
|
+
"storage",
|
|
15
|
+
"cookies",
|
|
16
|
+
"scripting",
|
|
17
|
+
"alarms",
|
|
18
|
+
"webNavigation",
|
|
19
|
+
"userScripts"
|
|
20
|
+
],
|
|
21
|
+
"host_permissions": [
|
|
22
|
+
"<all_urls>"
|
|
23
|
+
],
|
|
24
|
+
"background": {
|
|
25
|
+
"service_worker": "service-worker-loader.js",
|
|
26
|
+
"type": "module"
|
|
27
|
+
},
|
|
28
|
+
"content_scripts": [
|
|
29
|
+
{
|
|
30
|
+
"js": [
|
|
31
|
+
"assets/isolated.ts-Ta0FhgRt.js"
|
|
32
|
+
],
|
|
33
|
+
"matches": [
|
|
34
|
+
"<all_urls>"
|
|
35
|
+
],
|
|
36
|
+
"run_at": "document_start",
|
|
37
|
+
"all_frames": true,
|
|
38
|
+
"match_about_blank": true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"js": [
|
|
42
|
+
"assets/eval-port.ts-CjQ6AQ5y.js"
|
|
43
|
+
],
|
|
44
|
+
"matches": [
|
|
45
|
+
"<all_urls>"
|
|
46
|
+
],
|
|
47
|
+
"run_at": "document_start",
|
|
48
|
+
"all_frames": true,
|
|
49
|
+
"match_about_blank": true
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"js": [
|
|
53
|
+
"assets/main.ts-35tWlP_X.js"
|
|
54
|
+
],
|
|
55
|
+
"matches": [
|
|
56
|
+
"<all_urls>"
|
|
57
|
+
],
|
|
58
|
+
"run_at": "document_start",
|
|
59
|
+
"all_frames": true,
|
|
60
|
+
"match_about_blank": true,
|
|
61
|
+
"world": "MAIN"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"js": [
|
|
65
|
+
"assets/network-patch.ts-B-brNKhX.js"
|
|
66
|
+
],
|
|
67
|
+
"matches": [
|
|
68
|
+
"<all_urls>"
|
|
69
|
+
],
|
|
70
|
+
"run_at": "document_start",
|
|
71
|
+
"all_frames": true,
|
|
72
|
+
"match_about_blank": true,
|
|
73
|
+
"world": "MAIN"
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"action": {
|
|
77
|
+
"default_title": "browser-attach",
|
|
78
|
+
"default_popup": "src/popup/index.html",
|
|
79
|
+
"default_icon": {
|
|
80
|
+
"16": "icons/icon-16.png",
|
|
81
|
+
"32": "icons/icon-32.png",
|
|
82
|
+
"48": "icons/icon-48.png",
|
|
83
|
+
"128": "icons/icon-128.png"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"web_accessible_resources": [
|
|
87
|
+
{
|
|
88
|
+
"matches": [
|
|
89
|
+
"<all_urls>"
|
|
90
|
+
],
|
|
91
|
+
"resources": [
|
|
92
|
+
"assets/isolated.ts-Ta0FhgRt.js",
|
|
93
|
+
"assets/eval-port.ts-CjQ6AQ5y.js",
|
|
94
|
+
"assets/main.ts-35tWlP_X.js",
|
|
95
|
+
"assets/network-patch.ts-B-brNKhX.js"
|
|
96
|
+
],
|
|
97
|
+
"use_dynamic_url": false
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './assets/index.ts-B5VErDIP.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>browser-attach</title>
|
|
6
|
+
<script type="module" crossorigin src="/assets/index.html-BVp3Bo-W.js"></script>
|
|
7
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CFCX92ZZ.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<header>
|
|
11
|
+
<strong>browser-attach</strong>
|
|
12
|
+
<span id="status-dot" class="dot dot-disabled"></span>
|
|
13
|
+
</header>
|
|
14
|
+
<div id="status-line">connecting…</div>
|
|
15
|
+
<div id="url-line"></div>
|
|
16
|
+
<section>
|
|
17
|
+
<h2>Recent activity</h2>
|
|
18
|
+
<ol id="activity"></ol>
|
|
19
|
+
</section>
|
|
20
|
+
</body>
|
|
21
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-attach",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Drive your real, logged-in Chrome from the shell or an AI agent: a Chrome extension plus a local CLI/daemon, no debug port.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Shun <liushun0574@gmail.com> (https://github.com/ShunL12324)",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ShunL12324/browser-attach.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/ShunL12324/browser-attach#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/ShunL12324/browser-attach/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"browser",
|
|
17
|
+
"automation",
|
|
18
|
+
"chrome",
|
|
19
|
+
"chrome-extension",
|
|
20
|
+
"cli",
|
|
21
|
+
"mcp",
|
|
22
|
+
"claude-code",
|
|
23
|
+
"ai-agent",
|
|
24
|
+
"codex"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20"
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"browser-attach": "bundle/browser-attach.mjs"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"bundle/",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE",
|
|
36
|
+
"CHANGELOG.md"
|
|
37
|
+
],
|
|
38
|
+
"workspaces": [
|
|
39
|
+
"packages/*"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"test": "npm run build:bridge && node scripts/run-unit-tests.mjs",
|
|
43
|
+
"build": "npm run build -w browser-attach-protocol && npm run build -w browser-attach-mcp && npm run build -w browser-attach-extension",
|
|
44
|
+
"build:protocol": "npm run build -w browser-attach-protocol",
|
|
45
|
+
"build:extension": "npm run build:protocol && npm run build -w browser-attach-extension",
|
|
46
|
+
"build:bridge": "npm run build:protocol && npm run build -w browser-attach-mcp",
|
|
47
|
+
"build:package": "node scripts/build-package.mjs",
|
|
48
|
+
"prepack": "npm run build && node scripts/build-package.mjs",
|
|
49
|
+
"check-version": "node scripts/check-version.mjs",
|
|
50
|
+
"dev:extension": "npm run dev --workspace browser-attach-extension",
|
|
51
|
+
"pack:extension": "npm run pack --workspace browser-attach-extension",
|
|
52
|
+
"typecheck": "npm run build:protocol && tsc --noEmit -p packages/bridge && tsc --noEmit -p packages/extension",
|
|
53
|
+
"test:e2e:tool-actions": "node tests/e2e/tools/tool-actions.mjs",
|
|
54
|
+
"test:e2e:tool-view": "node tests/e2e/tools/tool-view.mjs",
|
|
55
|
+
"test:e2e:eval-js-worlds": "node tests/e2e/tools/eval-js-worlds.mjs",
|
|
56
|
+
"test:e2e:screenshot": "node tests/e2e/tools/screenshot.mjs",
|
|
57
|
+
"test:e2e:cli-basic": "node tests/e2e/cli/cli-basic.mjs",
|
|
58
|
+
"test:e2e:cli-shot": "node tests/e2e/cli/cli-shot.mjs",
|
|
59
|
+
"test:e2e:multi-client": "node tests/e2e/cli/multi-client.mjs"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"esbuild": "^0.21.5"
|
|
63
|
+
}
|
|
64
|
+
}
|