@mindstudio-ai/browser-agent 0.1.45 → 0.1.46
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/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -108,7 +108,7 @@ ${h}
|
|
|
108
108
|
white-space: nowrap;
|
|
109
109
|
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
|
110
110
|
">Remy</div>
|
|
111
|
-
`,t.style.cssText=["position: fixed","z-index: 2147483647","pointer-events: none","opacity: 0","transition: opacity 300ms ease, left 600ms cubic-bezier(0.4, 0, 0, 1), top 600ms cubic-bezier(0.4, 0, 0, 1)","will-change: left, top, opacity"].join("; ");let n=document.createElement("div");n.id=fn,n.style.cssText=["position: fixed","top: 0","left: 0","width: 100vw","height: 100vh","background: white","opacity: 0","z-index: 2147483646","pointer-events: none","transition: opacity 600ms ease-out"].join("; "),document.documentElement.appendChild(n),document.documentElement.appendChild(t),e.cameraEl=t,e.flashEl=n}function qs(e,t){let{cameraEl:n}=E().screenshot;n&&(n.style.left=`${e}px`,n.style.top=`${t}px`,n.style.opacity="1")}function xo(e,t){let{cameraEl:n}=E().screenshot;n&&(n.style.left=`${e}px`,n.style.top=`${t}px`)}async function js(){let{flashEl:e}=E().screenshot;e&&(e.style.transition="none",e.style.opacity="0.7",e.offsetWidth,e.style.transition="opacity 600ms ease-out",e.style.opacity="0",await O(600))}function Ys(){let{cameraEl:e}=E().screenshot;e&&(e.style.opacity="0")}function Vs(){let e=E().screenshot;document.getElementById(dn)?.remove(),document.getElementById(fn)?.remove(),e.cameraEl=null,e.flashEl=null}function zs(e,t,n){return new Promise(r=>{let i=e.scrollTop,o=t-i;if(Math.abs(o)<1){r();return}let a=Math.abs(o),c=Math.max(n,a/2),l=performance.now();function u(d){let f=d-l,m=Math.min(f/c,1),g=m<.5?4*m*m*m:1-Math.pow(-2*m+2,3)/2;e.scrollTop=i+o*g,m<1?requestAnimationFrame(u):r()}requestAnimationFrame(u)})}async function Ge(e){let t=E().screenshot;if(t.capturing)throw new Error("Screenshot already in progress");t.capturing=!0,wo();try{return await Xs(e)}finally{t.capturing=!1,bo()}}async function Xs(e){await Vr();let t=window.innerWidth,n=window.innerHeight;if(e?.viewportOnly)return await Ks(t,n);let r=Se(),i=r!==document.documentElement,o=r.scrollTop,a=r.style.scrollBehavior;r.style.scrollBehavior="auto",Us();try{let s=Math.random()<.5?t+30:-60,c=n*.3+Math.random()*n*.4;qs(s,c),await O(200);let l=t*.4+Math.random()*t*.15,u=n*.35+Math.random()*n*.15;xo(l,u),await O(700);let d=[],f=0,m=i?r.clientHeight:n,g=()=>i?r.scrollHeight:Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),h=50,p=g();for(;f<p&&d.length<h;){let k=d.length,N=g();if(N<=0){console.warn("[screenshot] skipping chunk \u2014 page height is 0");break}if(N-f<m*.05&&d.length>0)break;let I=N-m,L=Math.min(f,I);Math.abs(L-r.scrollTop)>1&&(await zs(r,L,Os),xo(l,u),await O(Hs)),js();let H=r.scrollTop,U=Math.min(m,N-H);if(U<=0){console.warn("[screenshot] skipping chunk \u2014 captureHeight is 0 (page may have shrunk)"),f+=m;continue}let G=i?r.getBoundingClientRect():null;try{let R=await(await D(document.body,{embedFonts:!0,exclude:So})).toCanvas({width:t});if(R&&G){let P=R.width/t,_=R.width;if(k===0&&G.top>0){let J=Math.round(G.top*P),Z=document.createElement("canvas");Z.width=_,Z.height=J;let le=Z.getContext("2d");le&&(le.drawImage(R,0,0,_,J,0,0,_,J),d.push({y:0,canvas:Z}))}let K=Math.round(G.top*P),W=Math.round(U*P),q=document.createElement("canvas");q.width=_,q.height=W;let j=q.getContext("2d");j&&(j.drawImage(R,0,K,_,W,0,0,_,W),d.push({y:G.top+H,canvas:q}));let V=G.bottom;if(f+m>=p&&V<n){let J=Math.round(V*P),Z=R.height-J;if(Z>0){let le=document.createElement("canvas");le.width=_,le.height=Z;let Je=le.getContext("2d");Je&&(Je.drawImage(R,0,J,_,Z,0,0,_,Z),d.push({y:G.top+N,canvas:le}))}}}else if(R){let P=R.width/t,_=Math.round(H*P),K=Math.min(H+U,N),W=Math.round(K*P)-_,q=R.width,j=document.createElement("canvas");j.width=q,j.height=W;let V=j.getContext("2d");V&&(V.drawImage(R,0,_,q,W,0,0,q,W),d.push({y:H,canvas:j}))}}catch(T){console.error("[screenshot] snapdom capture failed for chunk",k,T)}f+=m}if(f<p&&console.warn(`[screenshot] page truncated \u2014 captured ${d.length} chunks but page is ${p}px tall`),d.length===0)throw new Error("Screenshot capture produced no image data");let y=d[0].canvas.width,x=0;for(let k of d)x+=k.canvas.height;let b=document.createElement("canvas");b.width=y,b.height=x;let w=b.getContext("2d");if(!w)throw new Error("Failed to create output canvas");let S=0;for(let k of d)w.drawImage(k.canvas,0,S),S+=k.canvas.height;let v=b.toDataURL("image/jpeg",1).replace(/^data:image\/jpeg;base64,/,"");if(!v)throw new Error("Canvas export produced no image data");return{image:v,width:b.width,height:b.height}}finally{Ys(),Vs(),r.style.scrollBehavior="auto",r.scrollTop=o,r.style.scrollBehavior=a}}function Gs(){let e=document.getElementById("__mindstudio-notes-overlay");if(!e)return null;let t=window.scrollX,n=window.scrollY,r=e.style.cssText;return e.style.position="absolute",e.style.inset="auto",e.style.left=`${t}px`,e.style.top=`${n}px`,e.style.width=`${window.innerWidth}px`,e.style.height=`${window.innerHeight}px`,()=>{e.style.cssText=r}}async function Ks(e,t){let n=Gs();try{let i=await(await D(document.body,{embedFonts:!0,exclude:So})).toCanvas({width:e,scale:Me});if(!i)throw new Error("SnapDOM viewport capture returned empty result");let o=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),a=document.createElement("canvas");a.width=e*Me,a.height=t*Me;let s=a.getContext("2d");if(!s)throw new Error("Failed to create canvas context");let c=window.scrollY/o*i.height,l=t/o*i.height;s.drawImage(i,0,c,i.width,l,0,0,e*Me,t*Me);let d=a.toDataURL("image/jpeg",1).replace(/^data:image\/jpeg;base64,/,"");if(!d)throw new Error("Canvas export produced no image data");return{image:d,width:e*Me,height:t*Me}}finally{n?.()}}var Js=["backgroundColor","color","fontFamily","fontSize","fontWeight","fontStyle","lineHeight","letterSpacing","textAlign","textDecoration","textTransform","padding","paddingTop","paddingRight","paddingBottom","paddingLeft","margin","marginTop","marginRight","marginBottom","marginLeft","borderRadius","borderColor","borderWidth","borderStyle","boxShadow","opacity","width","height","display","flexDirection","justifyContent","alignItems","gap"];function Zs(e,t){let n=t??Js;if(e.ref||e.text||e.role||e.label||e.selector){let{element:o,matched:a}=fe(e);return{...Eo(o,e.ref,n),matched:a}}let r=$e(),i=[];for(let[o,a]of r)a.isConnected&&i.push(Eo(a,o,n));return i}function Eo(e,t,n){let r=window.getComputedStyle(e),i={};t&&(i.ref=t),i.tag=e.tagName.toLowerCase();let o=e.textContent?.trim();o&&(i.text=o.length>60?o.slice(0,60)+"\u2026":o);for(let a of n){let s=r.getPropertyValue(a.replace(/([A-Z])/g,"-$1").toLowerCase());s&&(i[a]=s)}return i}var Co=150,xt=100,vt="__mindstudio_pending_nav",Mo=300,ko=1e4;function Qs(e){try{let t=new URL(e,window.location.origin);return t.origin!==window.location.origin?!1:t.pathname===window.location.pathname&&t.search===window.location.search&&t.hash===window.location.hash}catch{return!1}}function Ao(e){try{let t=new URL(e,window.location.origin);return t.origin!==window.location.origin?!1:(Qs(e)||(window.history.pushState(null,"",t.pathname+t.search+t.hash),window.dispatchEvent(new PopStateEvent("popstate"))),!0)}catch{return!1}}async function mn(e=300,t=2e3){return new Promise(n=>{let r=Date.now()+t,i=Date.now(),o=Se(),a=window.scrollY,s=window.scrollX,c=document.body.scrollTop,l=document.documentElement.scrollTop,u=document.body.scrollHeight,d=document.body.scrollWidth,f=o.scrollTop,m=o.scrollLeft;function g(){if(Date.now()>r){n();return}let h=window.scrollY,p=window.scrollX,y=document.body.scrollTop,x=document.documentElement.scrollTop,b=document.body.scrollHeight,w=document.body.scrollWidth,S=o.scrollTop,C=o.scrollLeft;(h!==a||p!==s||y!==c||x!==l||b!==u||w!==d||S!==f||C!==m)&&(a=h,s=p,c=y,l=x,u=b,d=w,f=S,m=C,i=Date.now()),Date.now()-i>=e?n():requestAnimationFrame(g)}requestAnimationFrame(g)})}var ec=350;async function pn(e){let t=tc(e),n=t.map(a=>({el:a,top:a.scrollTop,left:a.scrollLeft})),r=document.documentElement.style.scrollBehavior;document.documentElement.style.scrollBehavior="auto",e.scrollIntoView({block:"center",inline:"nearest",behavior:"instant"}),document.documentElement.style.scrollBehavior=r;let i=t.map(a=>({top:a.scrollTop,left:a.scrollLeft})),o=[];for(let a=0;a<t.length;a++)(n[a].top!==i[a].top||n[a].left!==i[a].left)&&o.push({el:t[a],fromTop:n[a].top,fromLeft:n[a].left,toTop:i[a].top,toLeft:i[a].left});if(o.length===0){await new Promise(a=>requestAnimationFrame(()=>a()));return}for(let a of o)a.el.scrollTop=a.fromTop,a.el.scrollLeft=a.fromLeft;await new Promise(a=>{let s=performance.now();function c(l){let u=l-s,d=Math.min(u/ec,1),f=1-Math.pow(1-d,3);for(let m of o)m.el.scrollTop=m.fromTop+(m.toTop-m.fromTop)*f,m.el.scrollLeft=m.fromLeft+(m.toLeft-m.fromLeft)*f;d<1?requestAnimationFrame(c):a()}requestAnimationFrame(c)})}function tc(e){let t=[],n=e.parentElement;for(;n;){let r=getComputedStyle(n),i=r.overflowY,o=r.overflowX;(i==="auto"||i==="scroll"||o==="auto"||o==="scroll")&&t.push(n),n=n.parentElement}return t.push(document.scrollingElement||document.documentElement),t}async function St(e,t){let n=Date.now(),r=[],i=[],o="",a=!1,s=new Set(["click","type","select"]),c=t.some(l=>s.has(l.command));c&&(Xe(!0),cn()),Nt();try{for(let l=0;l<t.length;l++){let u=t[l],d=u.command;try{if(l>0&&await O(Co+Math.random()*xt-xt/2),d==="navigate"){let m=u.url;if(!m)throw new Error('navigate command requires a "url" field');if(Ao(m)){r.push({index:l,command:d,result:"ok"}),await O(Mo);continue}let g=t.slice(l+1);if(g.length>0)try{sessionStorage.setItem(vt,JSON.stringify({id:e,startTime:n,completedSteps:r,remainingSteps:g,stepOffset:l+1}))}catch{}r.push({index:l,command:d,result:"ok"}),a=!0,window.location.href=m,await new Promise((h,p)=>{setTimeout(()=>p(new Error("Navigation did not complete within timeout")),ko)})}let f=await Lo(u);r.push({index:l,command:d,...f})}catch(f){r.push({index:l,command:d,error:f instanceof Error?f.message:String(f)});break}}try{o=await Le()}catch{}}finally{i=Rt(),c&&(Xe(!1),wt())}return{id:e,steps:r,snapshot:o,logs:i,duration:Date.now()-n}}async function $o(){let e=null;try{let o=sessionStorage.getItem(vt);if(!o)return null;sessionStorage.removeItem(vt),e=JSON.parse(o)}catch{return null}if(!e)return null;let t=[...e.completedSteps],n=[],r="",i=e.remainingSteps.some(o=>o.command==="click"||o.command==="type"||o.command==="select");i&&(Xe(!0),cn()),Nt();try{for(let o=0;o<e.remainingSteps.length;o++){let a=e.remainingSteps[o],s=a.command,c=e.stepOffset+o;try{if(o>0&&await O(Co+Math.random()*xt-xt/2),s==="navigate"){let u=a.url;if(!u)throw new Error('navigate command requires a "url" field');if(Ao(u)){t.push({index:c,command:s,result:"ok"}),await O(Mo);continue}let d=e.remainingSteps.slice(o+1);if(d.length>0)try{sessionStorage.setItem(vt,JSON.stringify({id:e.id,startTime:e.startTime,completedSteps:t,remainingSteps:d,stepOffset:c+1}))}catch{}t.push({index:c,command:s,result:"ok"}),window.location.href=u,await new Promise((f,m)=>{setTimeout(()=>m(new Error("Navigation did not complete within timeout")),ko)})}let l=await Lo(a);t.push({index:c,command:s,...l})}catch(l){t.push({index:c,command:s,error:l instanceof Error?l.message:String(l)});break}}try{r=await Le()}catch{}}finally{n=Rt(),i&&(Xe(!1),wt())}return{id:e.id,steps:t,snapshot:r,logs:n,duration:Date.now()-e.startTime}}async function Lo(e){switch(e.command){case"snapshot":return{result:await Le()};case"click":{let{element:t,matched:n}=fe(e);return await pn(t),await yt(t),await go(),It(t),await mn(),await O(1e3),{result:"ok",matched:n}}case"type":{let{element:t,matched:n}=fe(e),r=e.text;if(!r&&r!=="")throw new Error('type command requires a "text" field');return await pn(t),await yt(t),await Hn(t,r,{clear:!!e.clear}),await mn(),{result:"ok",matched:n}}case"select":{let{element:t,matched:n}=fe(e),r=e.option;if(!r)throw new Error('select command requires an "option" field');await pn(t),await yt(t);let i=Bn(t,r);return await mn(),{result:`selected "${i}"`,matched:n}}case"wait":{let{matched:t,elapsed:n}=await On(e);return{result:"ok",matched:t,elapsed:n}}case"styles":{let t=e.properties;return{result:Zs(e,t)}}case"evaluate":{let t=e.script;if(!t)throw new Error('evaluate command requires a "script" field');return{result:await Wn(t)}}case"screenshotFullPage":{let t=Se();t.scrollTop=0,await O(500);let{image:n,width:r,height:i}=await Ge(),o=e.uploadUrl,a=e.uploadFields;if(o&&a){let s=atob(n),c=new Uint8Array(s.length);for(let f=0;f<s.length;f++)c[f]=s.charCodeAt(f);let l=new FormData;for(let[f,m]of Object.entries(a))l.append(f,m);l.append("file",new Blob([c],{type:"image/jpeg"}),"screenshot.jpg");let u=await fetch(o,{method:"POST",body:l});if(!u.ok)throw new Error(`Screenshot upload failed: ${u.status}`);let d=e._publicUrl;return{result:{width:r,height:i,uploaded:!0,...d?{_publicUrl:d}:{}}}}return{result:{image:n,width:r,height:i}}}case"screenshotViewport":{let{image:t,width:n,height:r}=await Ge({viewportOnly:!0}),i=e.uploadUrl,o=e.uploadFields;if(i&&o){let a=atob(t),s=new Uint8Array(a.length);for(let d=0;d<a.length;d++)s[d]=a.charCodeAt(d);let c=new FormData;for(let[d,f]of Object.entries(o))c.append(d,f);c.append("file",new Blob([s],{type:"image/jpeg"}),"screenshot.jpg");let l=await fetch(i,{method:"POST",body:c});if(!l.ok)throw new Error(`Screenshot upload failed: ${l.status}`);let u=e._publicUrl;return{result:{width:n,height:r,uploaded:!0,...u?{_publicUrl:u}:{}}}}return{result:{image:t,width:n,height:r}}}case"reload":return location.reload(),{result:"ok"};default:throw new Error(`Unknown command: ${e.command}`)}}var nc="/__mindstudio_dev__/ws",rc=1e3,oc=1e4;function No(){let e=E().ws;e.ws||(xn(Ro),window.addEventListener("beforeunload",()=>{e.closing=!0,e.ws&&e.ws.close()}),_o())}function Ro(){let{ws:e}=E().ws;return e&&e.readyState===WebSocket.OPEN?e:null}function ic(){return`${location.protocol==="https:"?"wss:":"ws:"}//${location.host}${nc}`}function ac(){return window.location.search.includes("mode=iframe")?"iframe":"standalone"}function _o(){let e=E().ws;if(!e.closing){try{e.ws=new WebSocket(ic())}catch{To();return}e.ws.onopen=()=>{try{e.ws.send(JSON.stringify({type:"hello",mode:ac(),url:location.href,viewport:{w:window.innerWidth,h:window.innerHeight}}))}catch{e.ws?.close()}},e.ws.onmessage=t=>{let n;try{n=JSON.parse(t.data)}catch{return}switch(n.type){case"ack":e.clientId=n.clientId,e.reconnectDelay=rc,sc();break;case"command":lc(n.id,n.steps);break;case"broadcast":cc(n.action,n.payload);break}},e.ws.onclose=()=>{e.ws=null,e.clientId=null,e.closing||To()},e.ws.onerror=()=>{}}}function To(){let e=E().ws;e.closing||(setTimeout(()=>_o(),e.reconnectDelay),e.reconnectDelay=Math.min(e.reconnectDelay*2,oc))}async function lc(e,t){let n=E().ws;if(n.busy){Et({id:e,steps:[],snapshot:"",logs:[],duration:0,error:"Browser agent is busy"});return}n.busy=!0,hn("command-started",{id:e,steps:t.map(r=>r.command)});try{let r=await St(e,t);Et(r),hn("command-completed",{id:e,success:!0})}catch{Et({id:e,steps:[],snapshot:"",logs:[],duration:0}),hn("command-completed",{id:e,success:!1})}finally{E().ws.busy=!1}}function Et(e){try{let t=Ro();t&&t.send(JSON.stringify({type:"result",...e}))}catch{}}async function sc(){let e=await $o();e&&Et(e)}function hn(e,t){window.parent!==window&&window.parent.postMessage({channel:"mindstudio-browser-agent",command:e,...t},"*")}function cc(e,t){e==="reload"&&location.reload()}var Po="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",uc=200,Fo=`
|
|
111
|
+
`,t.style.cssText=["position: fixed","z-index: 2147483647","pointer-events: none","opacity: 0","transition: opacity 300ms ease, left 600ms cubic-bezier(0.4, 0, 0, 1), top 600ms cubic-bezier(0.4, 0, 0, 1)","will-change: left, top, opacity"].join("; ");let n=document.createElement("div");n.id=fn,n.style.cssText=["position: fixed","top: 0","left: 0","width: 100vw","height: 100vh","background: white","opacity: 0","z-index: 2147483646","pointer-events: none","transition: opacity 600ms ease-out"].join("; "),document.documentElement.appendChild(n),document.documentElement.appendChild(t),e.cameraEl=t,e.flashEl=n}function qs(e,t){let{cameraEl:n}=E().screenshot;n&&(n.style.left=`${e}px`,n.style.top=`${t}px`,n.style.opacity="1")}function xo(e,t){let{cameraEl:n}=E().screenshot;n&&(n.style.left=`${e}px`,n.style.top=`${t}px`)}async function js(){let{flashEl:e}=E().screenshot;e&&(e.style.transition="none",e.style.opacity="0.7",e.offsetWidth,e.style.transition="opacity 600ms ease-out",e.style.opacity="0",await O(600))}function Ys(){let{cameraEl:e}=E().screenshot;e&&(e.style.opacity="0")}function Vs(){let e=E().screenshot;document.getElementById(dn)?.remove(),document.getElementById(fn)?.remove(),e.cameraEl=null,e.flashEl=null}function zs(e,t,n){return new Promise(r=>{let i=e.scrollTop,o=t-i;if(Math.abs(o)<1){r();return}let a=Math.abs(o),c=Math.max(n,a/2),l=performance.now();function u(d){let f=d-l,m=Math.min(f/c,1),g=m<.5?4*m*m*m:1-Math.pow(-2*m+2,3)/2;e.scrollTop=i+o*g,m<1?requestAnimationFrame(u):r()}requestAnimationFrame(u)})}async function Ge(e){let t=E().screenshot;if(t.capturing)throw new Error("Screenshot already in progress");t.capturing=!0,wo();try{return await Xs(e)}finally{t.capturing=!1,bo()}}async function Xs(e){await Vr();let t=window.innerWidth,n=window.innerHeight;if(e?.viewportOnly)return await Ks(t,n);let r=Se(),i=r!==document.documentElement,o=r.scrollTop,a=r.style.scrollBehavior;r.style.scrollBehavior="auto",Us();try{let s=Math.random()<.5?t+30:-60,c=n*.3+Math.random()*n*.4;qs(s,c),await O(200);let l=t*.4+Math.random()*t*.15,u=n*.35+Math.random()*n*.15;xo(l,u),await O(700);let d=[],f=0,m=i?r.clientHeight:n,g=()=>i?r.scrollHeight:Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),h=50,p=g();for(;f<p&&d.length<h;){let k=d.length,N=g();if(N<=0){console.warn("[screenshot] skipping chunk \u2014 page height is 0");break}if(N-f<m*.05&&d.length>0)break;let I=N-m,L=Math.min(f,I);Math.abs(L-r.scrollTop)>1&&(await zs(r,L,Os),xo(l,u),await O(Hs)),js();let H=r.scrollTop,U=Math.min(m,N-H);if(U<=0){console.warn("[screenshot] skipping chunk \u2014 captureHeight is 0 (page may have shrunk)"),f+=m;continue}let G=i?r.getBoundingClientRect():null;try{let R=await(await D(document.body,{embedFonts:!0,exclude:So})).toCanvas({scale:1});if(R&&G){let P=R.width/t,_=R.width;if(k===0&&G.top>0){let J=Math.round(G.top*P),Z=document.createElement("canvas");Z.width=_,Z.height=J;let le=Z.getContext("2d");le&&(le.drawImage(R,0,0,_,J,0,0,_,J),d.push({y:0,canvas:Z}))}let K=Math.round(G.top*P),W=Math.round(U*P),q=document.createElement("canvas");q.width=_,q.height=W;let j=q.getContext("2d");j&&(j.drawImage(R,0,K,_,W,0,0,_,W),d.push({y:G.top+H,canvas:q}));let V=G.bottom;if(f+m>=p&&V<n){let J=Math.round(V*P),Z=R.height-J;if(Z>0){let le=document.createElement("canvas");le.width=_,le.height=Z;let Je=le.getContext("2d");Je&&(Je.drawImage(R,0,J,_,Z,0,0,_,Z),d.push({y:G.top+N,canvas:le}))}}}else if(R){let P=R.width/t,_=Math.round(H*P),K=Math.min(H+U,N),W=Math.round(K*P)-_,q=R.width,j=document.createElement("canvas");j.width=q,j.height=W;let V=j.getContext("2d");V&&(V.drawImage(R,0,_,q,W,0,0,q,W),d.push({y:H,canvas:j}))}}catch(T){console.error("[screenshot] snapdom capture failed for chunk",k,T)}f+=m}if(f<p&&console.warn(`[screenshot] page truncated \u2014 captured ${d.length} chunks but page is ${p}px tall`),d.length===0)throw new Error("Screenshot capture produced no image data");let y=d[0].canvas.width,x=0;for(let k of d)x+=k.canvas.height;let b=document.createElement("canvas");b.width=y,b.height=x;let w=b.getContext("2d");if(!w)throw new Error("Failed to create output canvas");let S=0;for(let k of d)w.drawImage(k.canvas,0,S),S+=k.canvas.height;let v=b.toDataURL("image/jpeg",1).replace(/^data:image\/jpeg;base64,/,"");if(!v)throw new Error("Canvas export produced no image data");return{image:v,width:b.width,height:b.height}}finally{Ys(),Vs(),r.style.scrollBehavior="auto",r.scrollTop=o,r.style.scrollBehavior=a}}function Gs(){let e=document.getElementById("__mindstudio-notes-overlay");if(!e)return null;let t=window.scrollX,n=window.scrollY,r=e.style.cssText;return e.style.position="absolute",e.style.inset="auto",e.style.left=`${t}px`,e.style.top=`${n}px`,e.style.width=`${window.innerWidth}px`,e.style.height=`${window.innerHeight}px`,()=>{e.style.cssText=r}}async function Ks(e,t){let n=Gs();try{let i=await(await D(document.body,{embedFonts:!0,exclude:So})).toCanvas({scale:Me});if(!i)throw new Error("SnapDOM viewport capture returned empty result");let o=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),a=document.createElement("canvas");a.width=e*Me,a.height=t*Me;let s=a.getContext("2d");if(!s)throw new Error("Failed to create canvas context");let c=window.scrollY/o*i.height,l=t/o*i.height;s.drawImage(i,0,c,i.width,l,0,0,e*Me,t*Me);let d=a.toDataURL("image/jpeg",1).replace(/^data:image\/jpeg;base64,/,"");if(!d)throw new Error("Canvas export produced no image data");return{image:d,width:e*Me,height:t*Me}}finally{n?.()}}var Js=["backgroundColor","color","fontFamily","fontSize","fontWeight","fontStyle","lineHeight","letterSpacing","textAlign","textDecoration","textTransform","padding","paddingTop","paddingRight","paddingBottom","paddingLeft","margin","marginTop","marginRight","marginBottom","marginLeft","borderRadius","borderColor","borderWidth","borderStyle","boxShadow","opacity","width","height","display","flexDirection","justifyContent","alignItems","gap"];function Zs(e,t){let n=t??Js;if(e.ref||e.text||e.role||e.label||e.selector){let{element:o,matched:a}=fe(e);return{...Eo(o,e.ref,n),matched:a}}let r=$e(),i=[];for(let[o,a]of r)a.isConnected&&i.push(Eo(a,o,n));return i}function Eo(e,t,n){let r=window.getComputedStyle(e),i={};t&&(i.ref=t),i.tag=e.tagName.toLowerCase();let o=e.textContent?.trim();o&&(i.text=o.length>60?o.slice(0,60)+"\u2026":o);for(let a of n){let s=r.getPropertyValue(a.replace(/([A-Z])/g,"-$1").toLowerCase());s&&(i[a]=s)}return i}var Co=150,xt=100,vt="__mindstudio_pending_nav",Mo=300,ko=1e4;function Qs(e){try{let t=new URL(e,window.location.origin);return t.origin!==window.location.origin?!1:t.pathname===window.location.pathname&&t.search===window.location.search&&t.hash===window.location.hash}catch{return!1}}function Ao(e){try{let t=new URL(e,window.location.origin);return t.origin!==window.location.origin?!1:(Qs(e)||(window.history.pushState(null,"",t.pathname+t.search+t.hash),window.dispatchEvent(new PopStateEvent("popstate"))),!0)}catch{return!1}}async function mn(e=300,t=2e3){return new Promise(n=>{let r=Date.now()+t,i=Date.now(),o=Se(),a=window.scrollY,s=window.scrollX,c=document.body.scrollTop,l=document.documentElement.scrollTop,u=document.body.scrollHeight,d=document.body.scrollWidth,f=o.scrollTop,m=o.scrollLeft;function g(){if(Date.now()>r){n();return}let h=window.scrollY,p=window.scrollX,y=document.body.scrollTop,x=document.documentElement.scrollTop,b=document.body.scrollHeight,w=document.body.scrollWidth,S=o.scrollTop,C=o.scrollLeft;(h!==a||p!==s||y!==c||x!==l||b!==u||w!==d||S!==f||C!==m)&&(a=h,s=p,c=y,l=x,u=b,d=w,f=S,m=C,i=Date.now()),Date.now()-i>=e?n():requestAnimationFrame(g)}requestAnimationFrame(g)})}var ec=350;async function pn(e){let t=tc(e),n=t.map(a=>({el:a,top:a.scrollTop,left:a.scrollLeft})),r=document.documentElement.style.scrollBehavior;document.documentElement.style.scrollBehavior="auto",e.scrollIntoView({block:"center",inline:"nearest",behavior:"instant"}),document.documentElement.style.scrollBehavior=r;let i=t.map(a=>({top:a.scrollTop,left:a.scrollLeft})),o=[];for(let a=0;a<t.length;a++)(n[a].top!==i[a].top||n[a].left!==i[a].left)&&o.push({el:t[a],fromTop:n[a].top,fromLeft:n[a].left,toTop:i[a].top,toLeft:i[a].left});if(o.length===0){await new Promise(a=>requestAnimationFrame(()=>a()));return}for(let a of o)a.el.scrollTop=a.fromTop,a.el.scrollLeft=a.fromLeft;await new Promise(a=>{let s=performance.now();function c(l){let u=l-s,d=Math.min(u/ec,1),f=1-Math.pow(1-d,3);for(let m of o)m.el.scrollTop=m.fromTop+(m.toTop-m.fromTop)*f,m.el.scrollLeft=m.fromLeft+(m.toLeft-m.fromLeft)*f;d<1?requestAnimationFrame(c):a()}requestAnimationFrame(c)})}function tc(e){let t=[],n=e.parentElement;for(;n;){let r=getComputedStyle(n),i=r.overflowY,o=r.overflowX;(i==="auto"||i==="scroll"||o==="auto"||o==="scroll")&&t.push(n),n=n.parentElement}return t.push(document.scrollingElement||document.documentElement),t}async function St(e,t){let n=Date.now(),r=[],i=[],o="",a=!1,s=new Set(["click","type","select"]),c=t.some(l=>s.has(l.command));c&&(Xe(!0),cn()),Nt();try{for(let l=0;l<t.length;l++){let u=t[l],d=u.command;try{if(l>0&&await O(Co+Math.random()*xt-xt/2),d==="navigate"){let m=u.url;if(!m)throw new Error('navigate command requires a "url" field');if(Ao(m)){r.push({index:l,command:d,result:"ok"}),await O(Mo);continue}let g=t.slice(l+1);if(g.length>0)try{sessionStorage.setItem(vt,JSON.stringify({id:e,startTime:n,completedSteps:r,remainingSteps:g,stepOffset:l+1}))}catch{}r.push({index:l,command:d,result:"ok"}),a=!0,window.location.href=m,await new Promise((h,p)=>{setTimeout(()=>p(new Error("Navigation did not complete within timeout")),ko)})}let f=await Lo(u);r.push({index:l,command:d,...f})}catch(f){r.push({index:l,command:d,error:f instanceof Error?f.message:String(f)});break}}try{o=await Le()}catch{}}finally{i=Rt(),c&&(Xe(!1),wt())}return{id:e,steps:r,snapshot:o,logs:i,duration:Date.now()-n}}async function $o(){let e=null;try{let o=sessionStorage.getItem(vt);if(!o)return null;sessionStorage.removeItem(vt),e=JSON.parse(o)}catch{return null}if(!e)return null;let t=[...e.completedSteps],n=[],r="",i=e.remainingSteps.some(o=>o.command==="click"||o.command==="type"||o.command==="select");i&&(Xe(!0),cn()),Nt();try{for(let o=0;o<e.remainingSteps.length;o++){let a=e.remainingSteps[o],s=a.command,c=e.stepOffset+o;try{if(o>0&&await O(Co+Math.random()*xt-xt/2),s==="navigate"){let u=a.url;if(!u)throw new Error('navigate command requires a "url" field');if(Ao(u)){t.push({index:c,command:s,result:"ok"}),await O(Mo);continue}let d=e.remainingSteps.slice(o+1);if(d.length>0)try{sessionStorage.setItem(vt,JSON.stringify({id:e.id,startTime:e.startTime,completedSteps:t,remainingSteps:d,stepOffset:c+1}))}catch{}t.push({index:c,command:s,result:"ok"}),window.location.href=u,await new Promise((f,m)=>{setTimeout(()=>m(new Error("Navigation did not complete within timeout")),ko)})}let l=await Lo(a);t.push({index:c,command:s,...l})}catch(l){t.push({index:c,command:s,error:l instanceof Error?l.message:String(l)});break}}try{r=await Le()}catch{}}finally{n=Rt(),i&&(Xe(!1),wt())}return{id:e.id,steps:t,snapshot:r,logs:n,duration:Date.now()-e.startTime}}async function Lo(e){switch(e.command){case"snapshot":return{result:await Le()};case"click":{let{element:t,matched:n}=fe(e);return await pn(t),await yt(t),await go(),It(t),await mn(),await O(1e3),{result:"ok",matched:n}}case"type":{let{element:t,matched:n}=fe(e),r=e.text;if(!r&&r!=="")throw new Error('type command requires a "text" field');return await pn(t),await yt(t),await Hn(t,r,{clear:!!e.clear}),await mn(),{result:"ok",matched:n}}case"select":{let{element:t,matched:n}=fe(e),r=e.option;if(!r)throw new Error('select command requires an "option" field');await pn(t),await yt(t);let i=Bn(t,r);return await mn(),{result:`selected "${i}"`,matched:n}}case"wait":{let{matched:t,elapsed:n}=await On(e);return{result:"ok",matched:t,elapsed:n}}case"styles":{let t=e.properties;return{result:Zs(e,t)}}case"evaluate":{let t=e.script;if(!t)throw new Error('evaluate command requires a "script" field');return{result:await Wn(t)}}case"screenshotFullPage":{let t=Se();t.scrollTop=0,await O(500);let{image:n,width:r,height:i}=await Ge(),o=e.uploadUrl,a=e.uploadFields;if(o&&a){let s=atob(n),c=new Uint8Array(s.length);for(let f=0;f<s.length;f++)c[f]=s.charCodeAt(f);let l=new FormData;for(let[f,m]of Object.entries(a))l.append(f,m);l.append("file",new Blob([c],{type:"image/jpeg"}),"screenshot.jpg");let u=await fetch(o,{method:"POST",body:l});if(!u.ok)throw new Error(`Screenshot upload failed: ${u.status}`);let d=e._publicUrl;return{result:{width:r,height:i,uploaded:!0,...d?{_publicUrl:d}:{}}}}return{result:{image:n,width:r,height:i}}}case"screenshotViewport":{let{image:t,width:n,height:r}=await Ge({viewportOnly:!0}),i=e.uploadUrl,o=e.uploadFields;if(i&&o){let a=atob(t),s=new Uint8Array(a.length);for(let d=0;d<a.length;d++)s[d]=a.charCodeAt(d);let c=new FormData;for(let[d,f]of Object.entries(o))c.append(d,f);c.append("file",new Blob([s],{type:"image/jpeg"}),"screenshot.jpg");let l=await fetch(i,{method:"POST",body:c});if(!l.ok)throw new Error(`Screenshot upload failed: ${l.status}`);let u=e._publicUrl;return{result:{width:n,height:r,uploaded:!0,...u?{_publicUrl:u}:{}}}}return{result:{image:t,width:n,height:r}}}case"reload":return location.reload(),{result:"ok"};default:throw new Error(`Unknown command: ${e.command}`)}}var nc="/__mindstudio_dev__/ws",rc=1e3,oc=1e4;function No(){let e=E().ws;e.ws||(xn(Ro),window.addEventListener("beforeunload",()=>{e.closing=!0,e.ws&&e.ws.close()}),_o())}function Ro(){let{ws:e}=E().ws;return e&&e.readyState===WebSocket.OPEN?e:null}function ic(){return`${location.protocol==="https:"?"wss:":"ws:"}//${location.host}${nc}`}function ac(){return window.location.search.includes("mode=iframe")?"iframe":"standalone"}function _o(){let e=E().ws;if(!e.closing){try{e.ws=new WebSocket(ic())}catch{To();return}e.ws.onopen=()=>{try{e.ws.send(JSON.stringify({type:"hello",mode:ac(),url:location.href,viewport:{w:window.innerWidth,h:window.innerHeight}}))}catch{e.ws?.close()}},e.ws.onmessage=t=>{let n;try{n=JSON.parse(t.data)}catch{return}switch(n.type){case"ack":e.clientId=n.clientId,e.reconnectDelay=rc,sc();break;case"command":lc(n.id,n.steps);break;case"broadcast":cc(n.action,n.payload);break}},e.ws.onclose=()=>{e.ws=null,e.clientId=null,e.closing||To()},e.ws.onerror=()=>{}}}function To(){let e=E().ws;e.closing||(setTimeout(()=>_o(),e.reconnectDelay),e.reconnectDelay=Math.min(e.reconnectDelay*2,oc))}async function lc(e,t){let n=E().ws;if(n.busy){Et({id:e,steps:[],snapshot:"",logs:[],duration:0,error:"Browser agent is busy"});return}n.busy=!0,hn("command-started",{id:e,steps:t.map(r=>r.command)});try{let r=await St(e,t);Et(r),hn("command-completed",{id:e,success:!0})}catch{Et({id:e,steps:[],snapshot:"",logs:[],duration:0}),hn("command-completed",{id:e,success:!1})}finally{E().ws.busy=!1}}function Et(e){try{let t=Ro();t&&t.send(JSON.stringify({type:"result",...e}))}catch{}}async function sc(){let e=await $o();e&&Et(e)}function hn(e,t){window.parent!==window&&window.parent.postMessage({channel:"mindstudio-browser-agent",command:e,...t},"*")}function cc(e,t){e==="reload"&&location.reload()}var Po="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",uc=200,Fo=`
|
|
112
112
|
all: initial !important;
|
|
113
113
|
display: block !important;
|
|
114
114
|
box-sizing: border-box !important;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindstudio-ai/browser-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.46",
|
|
4
4
|
"description": "Browser-side agent for MindStudio dev previews — captures logs, provides DOM snapshots, and enables remote interaction.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|