@shiplightai/mcp 0.1.70 → 0.1.71
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 +12 -11
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -127,7 +127,7 @@ ${h.join(`
|
|
|
127
127
|
|
|
128
128
|
`,p.some(m=>m)){Ce.log(`Locator validation on unsigned-in page failed (some passed when should fail). Results: ${JSON.stringify(p)}`),Ce.log(`Validation logs:
|
|
129
129
|
${h.join(`
|
|
130
|
-
`)}`);continue}}return Ce.log("Generated validation locators passed dual validation"),d}catch(d){Ce.log(`Failed to generate validation expressions (attempt ${u+1}/${a}): ${d.message}`)}return Ce.log("Failed to generate valid locators after max retries"),null}finally{s&&await s.close()}}var Vie,jt,kp,Pv,Mg,Ov,_a,Fg,Ip,zr,Pp,Bg,Op,TM,Np,Dp,CM,Nv,$g,Dv,va,Lv,xa,uu,Ea,du,Rp,jg,Mv,pu,Fv,Bv,kM,IM,$v,Ug,jv,PM,OM,NM,Hv,Gv,DM,RM,Wv,LM,Lp,Mp,Fp,Hg,Kv,Jv,MM,FM,hu,BM,$M,Yv,Xv,jM,UM,HM,qM,Zv,GM,WM,VM,qg,Qv,ex,tx,zM,rx,Xie,Qie,KM,Bp,JM,YM,XM,ZM,QM,e3,t3,r3,Sa,kl,nx,n3,Cp,
|
|
130
|
+
`)}`);continue}}return Ce.log("Generated validation locators passed dual validation"),d}catch(d){Ce.log(`Failed to generate validation expressions (attempt ${u+1}/${a}): ${d.message}`)}return Ce.log("Failed to generate valid locators after max retries"),null}finally{s&&await s.close()}}var Vie,jt,kp,Pv,Mg,Ov,_a,Fg,Ip,zr,Pp,Bg,Op,TM,Np,Dp,CM,Nv,$g,Dv,va,Lv,xa,uu,Ea,du,Rp,jg,Mv,pu,Fv,Bv,kM,IM,$v,Ug,jv,PM,OM,NM,Hv,Gv,DM,RM,Wv,LM,Lp,Mp,Fp,Hg,Kv,Jv,MM,FM,hu,BM,$M,Yv,Xv,jM,UM,HM,qM,Zv,GM,WM,VM,qg,Qv,ex,tx,zM,rx,Xie,Qie,fu,Gg,KM,Bp,JM,YM,XM,ZM,QM,e3,t3,r3,Sa,kl,nx,n3,Cp,mu,ese,tse,$p,ix,sx,ox,ax,Vg,i3,kv,s3,lu,o3,a3,l3,di,c3,u3,rse,nse,d3,p3,Yg=mt(()=>{"use strict";au();wa();ei();qn();Vie=AM(import.meta.url),jt=_e(e=>{"use strict";var t=Symbol.for("yaml.alias"),r=Symbol.for("yaml.document"),n=Symbol.for("yaml.map"),i=Symbol.for("yaml.pair"),s=Symbol.for("yaml.scalar"),o=Symbol.for("yaml.seq"),a=Symbol.for("yaml.node.type"),l=E=>!!E&&typeof E=="object"&&E[a]===t,u=E=>!!E&&typeof E=="object"&&E[a]===r,d=E=>!!E&&typeof E=="object"&&E[a]===n,p=E=>!!E&&typeof E=="object"&&E[a]===i,h=E=>!!E&&typeof E=="object"&&E[a]===s,m=E=>!!E&&typeof E=="object"&&E[a]===o;function y(E){if(E&&typeof E=="object")switch(E[a]){case n:case o:return!0}return!1}function b(E){if(E&&typeof E=="object")switch(E[a]){case t:case n:case s:case o:return!0}return!1}var w=E=>(h(E)||y(E))&&!!E.anchor;e.ALIAS=t,e.DOC=r,e.MAP=n,e.NODE_TYPE=a,e.PAIR=i,e.SCALAR=s,e.SEQ=o,e.hasAnchor=w,e.isAlias=l,e.isCollection=y,e.isDocument=u,e.isMap=d,e.isNode=b,e.isPair=p,e.isScalar=h,e.isSeq=m}),kp=_e(e=>{"use strict";var t=jt(),r=Symbol("break visit"),n=Symbol("skip children"),i=Symbol("remove node");function s(h,m){let y=u(m);t.isDocument(h)?o(null,h.contents,y,Object.freeze([h]))===i&&(h.contents=null):o(null,h,y,Object.freeze([]))}s.BREAK=r,s.SKIP=n,s.REMOVE=i;function o(h,m,y,b){let w=d(h,m,y,b);if(t.isNode(w)||t.isPair(w))return p(h,b,w),o(h,w,y,b);if(typeof w!="symbol"){if(t.isCollection(m)){b=Object.freeze(b.concat(m));for(let E=0;E<m.items.length;++E){let x=o(E,m.items[E],y,b);if(typeof x=="number")E=x-1;else{if(x===r)return r;x===i&&(m.items.splice(E,1),E-=1)}}}else if(t.isPair(m)){b=Object.freeze(b.concat(m));let E=o("key",m.key,y,b);if(E===r)return r;E===i&&(m.key=null);let x=o("value",m.value,y,b);if(x===r)return r;x===i&&(m.value=null)}}return w}async function a(h,m){let y=u(m);t.isDocument(h)?await l(null,h.contents,y,Object.freeze([h]))===i&&(h.contents=null):await l(null,h,y,Object.freeze([]))}a.BREAK=r,a.SKIP=n,a.REMOVE=i;async function l(h,m,y,b){let w=await d(h,m,y,b);if(t.isNode(w)||t.isPair(w))return p(h,b,w),l(h,w,y,b);if(typeof w!="symbol"){if(t.isCollection(m)){b=Object.freeze(b.concat(m));for(let E=0;E<m.items.length;++E){let x=await l(E,m.items[E],y,b);if(typeof x=="number")E=x-1;else{if(x===r)return r;x===i&&(m.items.splice(E,1),E-=1)}}}else if(t.isPair(m)){b=Object.freeze(b.concat(m));let E=await l("key",m.key,y,b);if(E===r)return r;E===i&&(m.key=null);let x=await l("value",m.value,y,b);if(x===r)return r;x===i&&(m.value=null)}}return w}function u(h){return typeof h=="object"&&(h.Collection||h.Node||h.Value)?Object.assign({Alias:h.Node,Map:h.Node,Scalar:h.Node,Seq:h.Node},h.Value&&{Map:h.Value,Scalar:h.Value,Seq:h.Value},h.Collection&&{Map:h.Collection,Seq:h.Collection},h):h}function d(h,m,y,b){if(typeof y=="function")return y(h,m,b);if(t.isMap(m))return y.Map?.(h,m,b);if(t.isSeq(m))return y.Seq?.(h,m,b);if(t.isPair(m))return y.Pair?.(h,m,b);if(t.isScalar(m))return y.Scalar?.(h,m,b);if(t.isAlias(m))return y.Alias?.(h,m,b)}function p(h,m,y){let b=m[m.length-1];if(t.isCollection(b))b.items[h]=y;else if(t.isPair(b))h==="key"?b.key=y:b.value=y;else if(t.isDocument(b))b.contents=y;else{let w=t.isAlias(b)?"alias":"scalar";throw new Error(`Cannot replace node with ${w} parent`)}}e.visit=s,e.visitAsync=a}),Pv=_e(e=>{"use strict";var t=jt(),r=kp(),n={"!":"%21",",":"%2C","[":"%5B","]":"%5D","{":"%7B","}":"%7D"},i=o=>o.replace(/[!,[\]{}]/g,a=>n[a]),s=class Us{constructor(a,l){this.docStart=null,this.docEnd=!1,this.yaml=Object.assign({},Us.defaultYaml,a),this.tags=Object.assign({},Us.defaultTags,l)}clone(){let a=new Us(this.yaml,this.tags);return a.docStart=this.docStart,a}atDocument(){let a=new Us(this.yaml,this.tags);switch(this.yaml.version){case"1.1":this.atNextDocument=!0;break;case"1.2":this.atNextDocument=!1,this.yaml={explicit:Us.defaultYaml.explicit,version:"1.2"},this.tags=Object.assign({},Us.defaultTags);break}return a}add(a,l){this.atNextDocument&&(this.yaml={explicit:Us.defaultYaml.explicit,version:"1.1"},this.tags=Object.assign({},Us.defaultTags),this.atNextDocument=!1);let u=a.trim().split(/[ \t]+/),d=u.shift();switch(d){case"%TAG":{if(u.length!==2&&(l(0,"%TAG directive should contain exactly two parts"),u.length<2))return!1;let[p,h]=u;return this.tags[p]=h,!0}case"%YAML":{if(this.yaml.explicit=!0,u.length!==1)return l(0,"%YAML directive should contain exactly one part"),!1;let[p]=u;if(p==="1.1"||p==="1.2")return this.yaml.version=p,!0;{let h=/^\d+\.\d+$/.test(p);return l(6,`Unsupported YAML version ${p}`,h),!1}}default:return l(0,`Unknown directive ${d}`,!0),!1}}tagName(a,l){if(a==="!")return"!";if(a[0]!=="!")return l(`Not a valid tag: ${a}`),null;if(a[1]==="<"){let h=a.slice(2,-1);return h==="!"||h==="!!"?(l(`Verbatim tags aren't resolved, so ${a} is invalid.`),null):(a[a.length-1]!==">"&&l("Verbatim tags must end with a >"),h)}let[,u,d]=a.match(/^(.*!)([^!]*)$/s);d||l(`The ${a} tag has no suffix`);let p=this.tags[u];if(p)try{return p+decodeURIComponent(d)}catch(h){return l(String(h)),null}return u==="!"?a:(l(`Could not resolve tag: ${a}`),null)}tagString(a){for(let[l,u]of Object.entries(this.tags))if(a.startsWith(u))return l+i(a.substring(u.length));return a[0]==="!"?a:`!<${a}>`}toString(a){let l=this.yaml.explicit?[`%YAML ${this.yaml.version||"1.2"}`]:[],u=Object.entries(this.tags),d;if(a&&u.length>0&&t.isNode(a.contents)){let p={};r.visit(a.contents,(h,m)=>{t.isNode(m)&&m.tag&&(p[m.tag]=!0)}),d=Object.keys(p)}else d=[];for(let[p,h]of u)p==="!!"&&h==="tag:yaml.org,2002:"||(!a||d.some(m=>m.startsWith(h)))&&l.push(`%TAG ${p} ${h}`);return l.join(`
|
|
131
131
|
`)}};s.defaultYaml={explicit:!1,version:"1.2"},s.defaultTags={"!!":"tag:yaml.org,2002:"},e.Directives=s}),Mg=_e(e=>{"use strict";var t=jt(),r=kp();function n(a){if(/[\x00-\x19\s,[\]{}]/.test(a)){let l=`Anchor must not contain whitespace or control characters: ${JSON.stringify(a)}`;throw new Error(l)}return!0}function i(a){let l=new Set;return r.visit(a,{Value(u,d){d.anchor&&l.add(d.anchor)}}),l}function s(a,l){for(let u=1;;++u){let d=`${a}${u}`;if(!l.has(d))return d}}function o(a,l){let u=[],d=new Map,p=null;return{onAnchor:h=>{u.push(h),p??(p=i(a));let m=s(l,p);return p.add(m),m},setAnchors:()=>{for(let h of u){let m=d.get(h);if(typeof m=="object"&&m.anchor&&(t.isScalar(m.node)||t.isCollection(m.node)))m.node.anchor=m.anchor;else{let y=new Error("Failed to resolve repeated object (this should not happen)");throw y.source=h,y}}},sourceObjects:d}}e.anchorIsValid=n,e.anchorNames=i,e.createNodeAnchors=o,e.findNewAnchor=s}),Ov=_e(e=>{"use strict";function t(r,n,i,s){if(s&&typeof s=="object")if(Array.isArray(s))for(let o=0,a=s.length;o<a;++o){let l=s[o],u=t(r,s,String(o),l);u===void 0?delete s[o]:u!==l&&(s[o]=u)}else if(s instanceof Map)for(let o of Array.from(s.keys())){let a=s.get(o),l=t(r,s,o,a);l===void 0?s.delete(o):l!==a&&s.set(o,l)}else if(s instanceof Set)for(let o of Array.from(s)){let a=t(r,s,o,o);a===void 0?s.delete(o):a!==o&&(s.delete(o),s.add(a))}else for(let[o,a]of Object.entries(s)){let l=t(r,s,o,a);l===void 0?delete s[o]:l!==a&&(s[o]=l)}return r.call(n,i,s)}e.applyReviver=t}),_a=_e(e=>{"use strict";var t=jt();function r(n,i,s){if(Array.isArray(n))return n.map((o,a)=>r(o,String(a),s));if(n&&typeof n.toJSON=="function"){if(!s||!t.hasAnchor(n))return n.toJSON(i,s);let o={aliasCount:0,count:1,res:void 0};s.anchors.set(n,o),s.onCreate=l=>{o.res=l,delete s.onCreate};let a=n.toJSON(i,s);return s.onCreate&&s.onCreate(a),a}return typeof n=="bigint"&&!s?.keep?Number(n):n}e.toJS=r}),Fg=_e(e=>{"use strict";var t=Ov(),r=jt(),n=_a(),i=class{constructor(s){Object.defineProperty(this,r.NODE_TYPE,{value:s})}clone(){let s=Object.create(Object.getPrototypeOf(this),Object.getOwnPropertyDescriptors(this));return this.range&&(s.range=this.range.slice()),s}toJS(s,{mapAsMap:o,maxAliasCount:a,onAnchor:l,reviver:u}={}){if(!r.isDocument(s))throw new TypeError("A document argument is required");let d={anchors:new Map,doc:s,keep:!0,mapAsMap:o===!0,mapKeyWarned:!1,maxAliasCount:typeof a=="number"?a:100},p=n.toJS(this,"",d);if(typeof l=="function")for(let{count:h,res:m}of d.anchors.values())l(m,h);return typeof u=="function"?t.applyReviver(u,{"":p},"",p):p}};e.NodeBase=i}),Ip=_e(e=>{"use strict";var t=Mg(),r=kp(),n=jt(),i=Fg(),s=_a(),o=class extends i.NodeBase{constructor(l){super(n.ALIAS),this.source=l,Object.defineProperty(this,"tag",{set(){throw new Error("Alias nodes cannot have tags")}})}resolve(l,u){let d;u?.aliasResolveCache?d=u.aliasResolveCache:(d=[],r.visit(l,{Node:(h,m)=>{(n.isAlias(m)||n.hasAnchor(m))&&d.push(m)}}),u&&(u.aliasResolveCache=d));let p;for(let h of d){if(h===this)break;h.anchor===this.source&&(p=h)}return p}toJSON(l,u){if(!u)return{source:this.source};let{anchors:d,doc:p,maxAliasCount:h}=u,m=this.resolve(p,u);if(!m){let b=`Unresolved alias (the anchor must be set before the alias): ${this.source}`;throw new ReferenceError(b)}let y=d.get(m);if(y||(s.toJS(m,null,u),y=d.get(m)),y?.res===void 0){let b="This should not happen: Alias anchor was not resolved?";throw new ReferenceError(b)}if(h>=0&&(y.count+=1,y.aliasCount===0&&(y.aliasCount=a(p,m,d)),y.count*y.aliasCount>h)){let b="Excessive alias count indicates a resource exhaustion attack";throw new ReferenceError(b)}return y.res}toString(l,u,d){let p=`*${this.source}`;if(l){if(t.anchorIsValid(this.source),l.options.verifyAliasOrder&&!l.anchors.has(this.source)){let h=`Unresolved alias (the anchor must be set before the alias): ${this.source}`;throw new Error(h)}if(l.implicitKey)return`${p} `}return p}};function a(l,u,d){if(n.isAlias(u)){let p=u.resolve(l),h=d&&p&&d.get(p);return h?h.count*h.aliasCount:0}else if(n.isCollection(u)){let p=0;for(let h of u.items){let m=a(l,h,d);m>p&&(p=m)}return p}else if(n.isPair(u)){let p=a(l,u.key,d),h=a(l,u.value,d);return Math.max(p,h)}return 1}e.Alias=o}),zr=_e(e=>{"use strict";var t=jt(),r=Fg(),n=_a(),i=o=>!o||typeof o!="function"&&typeof o!="object",s=class extends r.NodeBase{constructor(o){super(t.SCALAR),this.value=o}toJSON(o,a){return a?.keep?this.value:n.toJS(this.value,o,a)}toString(){return String(this.value)}};s.BLOCK_FOLDED="BLOCK_FOLDED",s.BLOCK_LITERAL="BLOCK_LITERAL",s.PLAIN="PLAIN",s.QUOTE_DOUBLE="QUOTE_DOUBLE",s.QUOTE_SINGLE="QUOTE_SINGLE",e.Scalar=s,e.isScalarValue=i}),Pp=_e(e=>{"use strict";var t=Ip(),r=jt(),n=zr(),i="tag:yaml.org,2002:";function s(a,l,u){if(l){let d=u.filter(h=>h.tag===l),p=d.find(h=>!h.format)??d[0];if(!p)throw new Error(`Tag ${l} not found`);return p}return u.find(d=>d.identify?.(a)&&!d.format)}function o(a,l,u){if(r.isDocument(a)&&(a=a.contents),r.isNode(a))return a;if(r.isPair(a)){let x=u.schema[r.MAP].createNode?.(u.schema,null,u);return x.items.push(a),x}(a instanceof String||a instanceof Number||a instanceof Boolean||typeof BigInt<"u"&&a instanceof BigInt)&&(a=a.valueOf());let{aliasDuplicateObjects:d,onAnchor:p,onTagObj:h,schema:m,sourceObjects:y}=u,b;if(d&&a&&typeof a=="object"){if(b=y.get(a),b)return b.anchor??(b.anchor=p(a)),new t.Alias(b.anchor);b={anchor:null,node:null},y.set(a,b)}l?.startsWith("!!")&&(l=i+l.slice(2));let w=s(a,l,m.tags);if(!w){if(a&&typeof a.toJSON=="function"&&(a=a.toJSON()),!a||typeof a!="object"){let x=new n.Scalar(a);return b&&(b.node=x),x}w=a instanceof Map?m[r.MAP]:Symbol.iterator in Object(a)?m[r.SEQ]:m[r.MAP]}h&&(h(w),delete u.onTagObj);let E=w?.createNode?w.createNode(u.schema,a,u):typeof w?.nodeClass?.from=="function"?w.nodeClass.from(u.schema,a,u):new n.Scalar(a);return l?E.tag=l:w.default||(E.tag=w.tag),b&&(b.node=E),E}e.createNode=o}),Bg=_e(e=>{"use strict";var t=Pp(),r=jt(),n=Fg();function i(a,l,u){let d=u;for(let p=l.length-1;p>=0;--p){let h=l[p];if(typeof h=="number"&&Number.isInteger(h)&&h>=0){let m=[];m[h]=d,d=m}else d=new Map([[h,d]])}return t.createNode(d,void 0,{aliasDuplicateObjects:!1,keepUndefined:!1,onAnchor:()=>{throw new Error("This should not happen, please report a bug.")},schema:a,sourceObjects:new Map})}var s=a=>a==null||typeof a=="object"&&!!a[Symbol.iterator]().next().done,o=class extends n.NodeBase{constructor(a,l){super(a),Object.defineProperty(this,"schema",{value:l,configurable:!0,enumerable:!1,writable:!0})}clone(a){let l=Object.create(Object.getPrototypeOf(this),Object.getOwnPropertyDescriptors(this));return a&&(l.schema=a),l.items=l.items.map(u=>r.isNode(u)||r.isPair(u)?u.clone(a):u),this.range&&(l.range=this.range.slice()),l}addIn(a,l){if(s(a))this.add(l);else{let[u,...d]=a,p=this.get(u,!0);if(r.isCollection(p))p.addIn(d,l);else if(p===void 0&&this.schema)this.set(u,i(this.schema,d,l));else throw new Error(`Expected YAML collection at ${u}. Remaining path: ${d}`)}}deleteIn(a){let[l,...u]=a;if(u.length===0)return this.delete(l);let d=this.get(l,!0);if(r.isCollection(d))return d.deleteIn(u);throw new Error(`Expected YAML collection at ${l}. Remaining path: ${u}`)}getIn(a,l){let[u,...d]=a,p=this.get(u,!0);return d.length===0?!l&&r.isScalar(p)?p.value:p:r.isCollection(p)?p.getIn(d,l):void 0}hasAllNullValues(a){return this.items.every(l=>{if(!r.isPair(l))return!1;let u=l.value;return u==null||a&&r.isScalar(u)&&u.value==null&&!u.commentBefore&&!u.comment&&!u.tag})}hasIn(a){let[l,...u]=a;if(u.length===0)return this.has(l);let d=this.get(l,!0);return r.isCollection(d)?d.hasIn(u):!1}setIn(a,l){let[u,...d]=a;if(d.length===0)this.set(u,l);else{let p=this.get(u,!0);if(r.isCollection(p))p.setIn(d,l);else if(p===void 0&&this.schema)this.set(u,i(this.schema,d,l));else throw new Error(`Expected YAML collection at ${u}. Remaining path: ${d}`)}}};e.Collection=o,e.collectionFromPath=i,e.isEmptyPath=s}),Op=_e(e=>{"use strict";var t=i=>i.replace(/^(?!$)(?: $)?/gm,"#");function r(i,s){return/^\n+$/.test(i)?i.substring(1):s?i.replace(/^(?! *$)/gm,s):i}var n=(i,s,o)=>i.endsWith(`
|
|
132
132
|
`)?r(o,s):o.includes(`
|
|
133
133
|
`)?`
|
|
@@ -265,7 +265,7 @@ ${h.comment}`:h.comment}this.doc.range[2]=h.offset;break}default:this.errors.pus
|
|
|
265
265
|
`)+1;for(;h!==0;)this.onNewLine(this.offset+h),h=this.source.indexOf(`
|
|
266
266
|
`,h)+1}yield*this.pop();break;default:yield*this.pop(),yield*this.step()}}*blockMap(p){let h=p.items[p.items.length-1];switch(this.type){case"newline":if(this.onKeyLine=!1,h.value){let m="end"in h.value?h.value.end:void 0;(Array.isArray(m)?m[m.length-1]:void 0)?.type==="comment"?m?.push(this.sourceToken):p.items.push({start:[this.sourceToken]})}else h.sep?h.sep.push(this.sourceToken):h.start.push(this.sourceToken);return;case"space":case"comment":if(h.value)p.items.push({start:[this.sourceToken]});else if(h.sep)h.sep.push(this.sourceToken);else{if(this.atIndentedComment(h.start,p.indent)){let m=p.items[p.items.length-2]?.value?.end;if(Array.isArray(m)){Array.prototype.push.apply(m,h.start),m.push(this.sourceToken),p.items.pop();return}}h.start.push(this.sourceToken)}return}if(this.indent>=p.indent){let m=!this.onKeyLine&&this.indent===p.indent,y=m&&(h.sep||h.explicitKey)&&this.type!=="seq-item-ind",b=[];if(y&&h.sep&&!h.value){let w=[];for(let E=0;E<h.sep.length;++E){let x=h.sep[E];switch(x.type){case"newline":w.push(E);break;case"space":break;case"comment":x.indent>p.indent&&(w.length=0);break;default:w.length=0}}w.length>=2&&(b=h.sep.splice(w[1]))}switch(this.type){case"anchor":case"tag":y||h.value?(b.push(this.sourceToken),p.items.push({start:b}),this.onKeyLine=!0):h.sep?h.sep.push(this.sourceToken):h.start.push(this.sourceToken);return;case"explicit-key-ind":!h.sep&&!h.explicitKey?(h.start.push(this.sourceToken),h.explicitKey=!0):y||h.value?(b.push(this.sourceToken),p.items.push({start:b,explicitKey:!0})):this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken],explicitKey:!0}]}),this.onKeyLine=!0;return;case"map-value-ind":if(h.explicitKey)if(h.sep)if(h.value)p.items.push({start:[],key:null,sep:[this.sourceToken]});else if(i(h.sep,"map-value-ind"))this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:b,key:null,sep:[this.sourceToken]}]});else if(o(h.key)&&!i(h.sep,"newline")){let w=l(h.start),E=h.key,x=h.sep;x.push(this.sourceToken),delete h.key,delete h.sep,this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:w,key:E,sep:x}]})}else b.length>0?h.sep=h.sep.concat(b,this.sourceToken):h.sep.push(this.sourceToken);else if(i(h.start,"newline"))Object.assign(h,{key:null,sep:[this.sourceToken]});else{let w=l(h.start);this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:w,key:null,sep:[this.sourceToken]}]})}else h.sep?h.value||y?p.items.push({start:b,key:null,sep:[this.sourceToken]}):i(h.sep,"map-value-ind")?this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[],key:null,sep:[this.sourceToken]}]}):h.sep.push(this.sourceToken):Object.assign(h,{key:null,sep:[this.sourceToken]});this.onKeyLine=!0;return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{let w=this.flowScalar(this.type);y||h.value?(p.items.push({start:b,key:w,sep:[]}),this.onKeyLine=!0):h.sep?this.stack.push(w):(Object.assign(h,{key:w,sep:[]}),this.onKeyLine=!0);return}default:{let w=this.startBlockValue(p);if(w){if(w.type==="block-seq"){if(!h.explicitKey&&h.sep&&!i(h.sep,"newline")){yield*this.pop({type:"error",offset:this.offset,message:"Unexpected block-seq-ind on same line with key",source:this.source});return}}else m&&p.items.push({start:b});this.stack.push(w);return}}}}yield*this.pop(),yield*this.step()}*blockSequence(p){let h=p.items[p.items.length-1];switch(this.type){case"newline":if(h.value){let m="end"in h.value?h.value.end:void 0;(Array.isArray(m)?m[m.length-1]:void 0)?.type==="comment"?m?.push(this.sourceToken):p.items.push({start:[this.sourceToken]})}else h.start.push(this.sourceToken);return;case"space":case"comment":if(h.value)p.items.push({start:[this.sourceToken]});else{if(this.atIndentedComment(h.start,p.indent)){let m=p.items[p.items.length-2]?.value?.end;if(Array.isArray(m)){Array.prototype.push.apply(m,h.start),m.push(this.sourceToken),p.items.pop();return}}h.start.push(this.sourceToken)}return;case"anchor":case"tag":if(h.value||this.indent<=p.indent)break;h.start.push(this.sourceToken);return;case"seq-item-ind":if(this.indent!==p.indent)break;h.value||i(h.start,"seq-item-ind")?p.items.push({start:[this.sourceToken]}):h.start.push(this.sourceToken);return}if(this.indent>p.indent){let m=this.startBlockValue(p);if(m){this.stack.push(m);return}}yield*this.pop(),yield*this.step()}*flowCollection(p){let h=p.items[p.items.length-1];if(this.type==="flow-error-end"){let m;do yield*this.pop(),m=this.peek(1);while(m?.type==="flow-collection")}else if(p.end.length===0){switch(this.type){case"comma":case"explicit-key-ind":!h||h.sep?p.items.push({start:[this.sourceToken]}):h.start.push(this.sourceToken);return;case"map-value-ind":!h||h.value?p.items.push({start:[],key:null,sep:[this.sourceToken]}):h.sep?h.sep.push(this.sourceToken):Object.assign(h,{key:null,sep:[this.sourceToken]});return;case"space":case"comment":case"newline":case"anchor":case"tag":!h||h.value?p.items.push({start:[this.sourceToken]}):h.sep?h.sep.push(this.sourceToken):h.start.push(this.sourceToken);return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{let y=this.flowScalar(this.type);!h||h.value?p.items.push({start:[],key:y,sep:[]}):h.sep?this.stack.push(y):Object.assign(h,{key:y,sep:[]});return}case"flow-map-end":case"flow-seq-end":p.end.push(this.sourceToken);return}let m=this.startBlockValue(p);m?this.stack.push(m):(yield*this.pop(),yield*this.step())}else{let m=this.peek(2);if(m.type==="block-map"&&(this.type==="map-value-ind"&&m.indent===p.indent||this.type==="newline"&&!m.items[m.items.length-1].sep))yield*this.pop(),yield*this.step();else if(this.type==="map-value-ind"&&m.type!=="flow-collection"){let y=a(m),b=l(y);u(p);let w=p.end.splice(1,p.end.length);w.push(this.sourceToken);let E={type:"block-map",offset:p.offset,indent:p.indent,items:[{start:b,key:p,sep:w}]};this.onKeyLine=!0,this.stack[this.stack.length-1]=E}else yield*this.lineEnd(p)}}flowScalar(p){if(this.onNewLine){let h=this.source.indexOf(`
|
|
267
267
|
`)+1;for(;h!==0;)this.onNewLine(this.offset+h),h=this.source.indexOf(`
|
|
268
|
-
`,h)+1}return{type:p,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(p){switch(this.type){case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return this.flowScalar(this.type);case"block-scalar-header":return{type:"block-scalar",offset:this.offset,indent:this.indent,props:[this.sourceToken],source:""};case"flow-map-start":case"flow-seq-start":return{type:"flow-collection",offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case"seq-item-ind":return{type:"block-seq",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case"explicit-key-ind":{this.onKeyLine=!0;let h=a(p),m=l(h);return m.push(this.sourceToken),{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:m,explicitKey:!0}]}}case"map-value-ind":{this.onKeyLine=!0;let h=a(p),m=l(h);return{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:m,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(p,h){return this.type!=="comment"||this.indent<=h?!1:p.every(m=>m.type==="newline"||m.type==="space")}*documentEnd(p){this.type!=="doc-mode"&&(p.end?p.end.push(this.sourceToken):p.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop()))}*lineEnd(p){switch(this.type){case"comma":case"doc-start":case"doc-end":case"flow-seq-end":case"flow-map-end":case"map-value-ind":yield*this.pop(),yield*this.step();break;case"newline":this.onKeyLine=!1;case"space":case"comment":default:p.end?p.end.push(this.sourceToken):p.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop())}}};e.Parser=d}),zM=_e(e=>{"use strict";var t=Zv(),r=Lp(),n=Mp(),i=Nv(),s=jt(),o=ex(),a=tx();function l(m){let y=m.prettyErrors!==!1;return{lineCounter:m.lineCounter||y&&new o.LineCounter||null,prettyErrors:y}}function u(m,y={}){let{lineCounter:b,prettyErrors:w}=l(y),E=new a.Parser(b?.addNewLine),x=new t.Composer(y),C=Array.from(x.compose(E.parse(m)));if(w&&b)for(let R of C)R.errors.forEach(n.prettifyError(m,b)),R.warnings.forEach(n.prettifyError(m,b));return C.length>0?C:Object.assign([],{empty:!0},x.streamInfo())}function d(m,y={}){let{lineCounter:b,prettyErrors:w}=l(y),E=new a.Parser(b?.addNewLine),x=new t.Composer(y),C=null;for(let R of x.compose(E.parse(m),!0,m.length))if(!C)C=R;else if(C.options.logLevel!=="silent"){C.errors.push(new n.YAMLParseError(R.range.slice(0,2),"MULTIPLE_DOCS","Source contains multiple documents; please use YAML.parseAllDocuments()"));break}return w&&b&&(C.errors.forEach(n.prettifyError(m,b)),C.warnings.forEach(n.prettifyError(m,b))),C}function p(m,y,b){let w;typeof y=="function"?w=y:b===void 0&&y&&typeof y=="object"&&(b=y);let E=d(m,b);if(!E)return null;if(E.warnings.forEach(x=>i.warn(E.options.logLevel,x)),E.errors.length>0){if(E.options.logLevel!=="silent")throw E.errors[0];E.errors=[]}return E.toJS(Object.assign({reviver:w},b))}function h(m,y,b){let w=null;if(typeof y=="function"||Array.isArray(y)?w=y:b===void 0&&y&&(b=y),typeof b=="string"&&(b=b.length),typeof b=="number"){let E=Math.round(b);b=E<1?void 0:E>8?{indent:8}:{indent:E}}if(m===void 0){let{keepUndefined:E}=b??y??{};if(!E)return}return s.isDocument(m)&&!w?m.toString(b):new r.Document(m,w,b).toString(b)}e.parse=p,e.parseAllDocuments=u,e.parseDocument=d,e.stringify=h}),rx=_e(e=>{"use strict";var t=Zv(),r=Lp(),n=Wv(),i=Mp(),s=Ip(),o=jt(),a=va(),l=zr(),u=xa(),d=Ea(),p=qg(),h=Qv(),m=ex(),y=tx(),b=zM(),w=kp();e.Composer=t.Composer,e.Document=r.Document,e.Schema=n.Schema,e.YAMLError=i.YAMLError,e.YAMLParseError=i.YAMLParseError,e.YAMLWarning=i.YAMLWarning,e.Alias=s.Alias,e.isAlias=o.isAlias,e.isCollection=o.isCollection,e.isDocument=o.isDocument,e.isMap=o.isMap,e.isNode=o.isNode,e.isPair=o.isPair,e.isScalar=o.isScalar,e.isSeq=o.isSeq,e.Pair=a.Pair,e.Scalar=l.Scalar,e.YAMLMap=u.YAMLMap,e.YAMLSeq=d.YAMLSeq,e.CST=p,e.Lexer=h.Lexer,e.LineCounter=m.LineCounter,e.Parser=y.Parser,e.parse=b.parse,e.parseAllDocuments=b.parseAllDocuments,e.parseDocument=b.parseDocument,e.stringify=b.stringify,e.visit=w.visit,e.visitAsync=w.visitAsync}),Xie=Hr(rx(),1),Qie=Hr(rx(),1),KM="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",Bp=112,JM=1920,YM=1080,XM=1920,ZM=1080-Bp,QM=1280,e3=720,t3=500,r3=500,Sa="Desktop Chrome",kl=(e=>(e.Chromium="chromium",e.Firefox="firefox",e.Webkit="webkit",e))(kl||{}),nx={"Blackberry PlayBook":{name:"Blackberry PlayBook",userAgent:"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/26.0 Safari/536.2+",screen:{width:600,height:1024},viewport:{width:600,height:1024},deviceScaleFactor:1,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"BlackBerry Z30":{name:"BlackBerry Z30",userAgent:"Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/26.0 Mobile Safari/537.10+",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy Note 3":{name:"Galaxy Note 3",userAgent:"Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy Note II":{name:"Galaxy Note II",userAgent:"Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy S III":{name:"Galaxy S III",userAgent:"Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy S5":{name:"Galaxy S5",userAgent:"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S8":{name:"Galaxy S8",userAgent:"Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:740},viewport:{width:360,height:740},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S9+":{name:"Galaxy S9+",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:320,height:658},viewport:{width:320,height:658},deviceScaleFactor:4.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S24":{name:"Galaxy S24",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-S921U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:780},viewport:{width:360,height:780},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy A55":{name:"Galaxy A55",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:480,height:1040},viewport:{width:480,height:1040},deviceScaleFactor:2.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy Tab S4":{name:"Galaxy Tab S4",userAgent:"Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:712,height:1138},viewport:{width:712,height:1138},deviceScaleFactor:2.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy Tab S9":{name:"Galaxy Tab S9",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-X710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:640,height:1024},viewport:{width:640,height:1024},deviceScaleFactor:2.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"iPad (gen 5)":{name:"iPad (gen 5)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 6)":{name:"iPad (gen 6)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 7)":{name:"iPad (gen 7)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:810,height:1080},viewport:{width:810,height:1080},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 11)":{name:"iPad (gen 11)",userAgent:"Mozilla/5.0 (iPad; CPU OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/19E241 Safari/604.1",screen:{width:656,height:944},viewport:{width:656,height:944},deviceScaleFactor:2.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad Mini":{name:"iPad Mini",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad Pro 11":{name:"iPad Pro 11",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:834,height:1194},viewport:{width:834,height:1194},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 6":{name:"iPhone 6",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 6 Plus":{name:"iPhone 6 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 7":{name:"iPhone 7",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 7 Plus":{name:"iPhone 7 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 8":{name:"iPhone 8",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 8 Plus":{name:"iPhone 8 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone SE":{name:"iPhone SE",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/26.0 Mobile/14E304 Safari/602.1",screen:{width:320,height:568},viewport:{width:320,height:568},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone SE (3rd gen)":{name:"iPhone SE (3rd gen)",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/26.0 Mobile/19E241 Safari/602.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone X":{name:"iPhone X",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:812},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone XR":{name:"iPhone XR",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:896},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11":{name:"iPhone 11",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:715},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11 Pro":{name:"iPhone 11 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:635},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11 Pro Max":{name:"iPhone 11 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:715},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12":{name:"iPhone 12",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Pro":{name:"iPhone 12 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Pro Max":{name:"iPhone 12 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Mini":{name:"iPhone 12 Mini",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:629},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13":{name:"iPhone 13",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Pro":{name:"iPhone 13 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Pro Max":{name:"iPhone 13 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Mini":{name:"iPhone 13 Mini",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:629},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14":{name:"iPhone 14",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Plus":{name:"iPhone 14 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Pro":{name:"iPhone 14 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:660},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Pro Max":{name:"iPhone 14 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:740},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15":{name:"iPhone 15",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:659},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Plus":{name:"iPhone 15 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:739},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Pro":{name:"iPhone 15 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:659},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Pro Max":{name:"iPhone 15 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:739},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Kindle Fire HDX":{name:"Kindle Fire HDX",userAgent:"Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true",screen:{width:800,height:1280},viewport:{width:800,height:1280},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"LG Optimus L70":{name:"LG Optimus L70",userAgent:"Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:384,height:640},viewport:{width:384,height:640},deviceScaleFactor:1.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Microsoft Lumia 550":{name:"Microsoft Lumia 550",userAgent:"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36 Edge/14.14263",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Microsoft Lumia 950":{name:"Microsoft Lumia 950",userAgent:"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36 Edge/14.14263",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:4,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 10":{name:"Nexus 10",userAgent:"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:800,height:1280},viewport:{width:800,height:1280},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 4":{name:"Nexus 4",userAgent:"Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:384,height:640},viewport:{width:384,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 5":{name:"Nexus 5",userAgent:"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 5X":{name:"Nexus 5X",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 6":{name:"Nexus 6",userAgent:"Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 6P":{name:"Nexus 6P",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 7":{name:"Nexus 7",userAgent:"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:600,height:960},viewport:{width:600,height:960},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nokia Lumia 520":{name:"Nokia Lumia 520",userAgent:"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)",screen:{width:320,height:533},viewport:{width:320,height:533},deviceScaleFactor:1.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nokia N9":{name:"Nokia N9",userAgent:"Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13",screen:{width:480,height:854},viewport:{width:480,height:854},deviceScaleFactor:1,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Pixel 2":{name:"Pixel 2",userAgent:"Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:411,height:731},viewport:{width:411,height:731},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 2 XL":{name:"Pixel 2 XL",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:411,height:823},viewport:{width:411,height:823},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 3":{name:"Pixel 3",userAgent:"Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:393,height:786},viewport:{width:393,height:786},deviceScaleFactor:2.75,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 4":{name:"Pixel 4",userAgent:"Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:353,height:745},viewport:{width:353,height:745},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 4a (5G)":{name:"Pixel 4a (5G)",userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:892},viewport:{width:412,height:765},deviceScaleFactor:2.63,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 5":{name:"Pixel 5",userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:393,height:851},viewport:{width:393,height:727},deviceScaleFactor:2.75,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 7":{name:"Pixel 7",userAgent:"Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:915},viewport:{width:412,height:839},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Moto G4":{name:"Moto G4",userAgent:"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Desktop Chrome HiDPI":{name:"Desktop Chrome HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Edge HiDPI":{name:"Desktop Edge HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Firefox HiDPI":{name:"Desktop Firefox HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0.1) Gecko/20100101 Firefox/142.0.1",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"firefox"},"Desktop Safari":{name:"Desktop Safari",userAgent:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"webkit"},"Desktop Chrome":{name:"Desktop Chrome",displayName:"Playwright Chromium",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Chrome Medium Resolution":{name:"Desktop Chrome Medium Resolution",displayName:"Playwright Chromium",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Chrome (Branded)":{name:"Desktop Chrome (Branded)",displayName:"Google Chrome",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"chrome"},"Desktop Chrome Medium Resolution (Branded)":{name:"Desktop Chrome Medium Resolution (Branded)",displayName:"Google Chrome",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"chrome"},"Desktop Edge":{name:"Desktop Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1920,height:1080},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Edge (Branded)":{name:"Desktop Edge (Branded)",displayName:"Microsoft Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"msedge"},"Desktop Edge Medium Resolution (Branded)":{name:"Desktop Edge Medium Resolution (Branded)",displayName:"Microsoft Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"msedge"},"Desktop Firefox":{name:"Desktop Firefox",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0.1) Gecko/20100101 Firefox/142.0.1",screen:{width:1920,height:1080},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"firefox"}},n3={desktop:["Desktop Chrome","Desktop Chrome Medium Resolution","Desktop Chrome (Branded)","Desktop Chrome Medium Resolution (Branded)","Desktop Edge (Branded)","Desktop Edge Medium Resolution (Branded)","Desktop Safari"],mobile:["iPhone 15 Pro Max","iPhone 15 Pro","iPhone 15 Plus","iPhone 15","iPhone 14 Pro Max","iPhone 14 Pro","iPhone 14 Plus","iPhone 14","iPhone 13 Pro Max","iPhone 13 Pro","iPhone 13","iPhone 13 Mini","iPhone 12 Pro Max","iPhone 12 Pro","iPhone 12","iPhone 12 Mini","iPhone 11 Pro Max","iPhone 11 Pro","iPhone 11","iPhone XR","iPhone X","iPhone SE (3rd gen)","iPhone SE","iPhone 8 Plus","iPhone 8","iPhone 7 Plus","iPhone 7","iPhone 6 Plus","iPhone 6","Galaxy S24","Galaxy A55","Galaxy S9+","Galaxy S8","Galaxy S5","Galaxy Note 3","Galaxy Note II","Galaxy S III","Pixel 7","Pixel 5","Pixel 4a (5G)","Pixel 4","Pixel 3","Pixel 2 XL","Pixel 2","Nexus 6P","Nexus 6","Nexus 5X","Nexus 5","Nexus 4","Moto G4","LG Optimus L70","Microsoft Lumia 950","Microsoft Lumia 550","Nokia Lumia 520","Nokia N9","BlackBerry Z30"]},Cp=(e,t=!1)=>{let r=["chromium"];return t&&r.push("webkit"),n3[e].map(n=>nx[n]).filter(n=>n.defaultBrowserType&&r.includes(n.defaultBrowserType))},fu=e=>nx[e],ese={desktop:{label:"Desktop",type:"desktop",devices:Cp("desktop")},mobile:{label:"Mobile Web",type:"mobile",devices:Cp("mobile")}},tse={desktop:{label:"Desktop",type:"desktop",devices:Cp("desktop",!0)},mobile:{label:"Mobile Web",type:"mobile",devices:Cp("mobile",!0)}},$p=(e,t=!1)=>{let r={userAgent:KM,viewport:{width:XM,height:ZM},isMobile:!1,hasTouch:!1};if(!e||e===Sa)return r;let n=fu(e);if(!n)return r;let{width:i,height:s}=n.viewport,o=Math.max(t3/i,1),a=Math.max(r3/s,1),l=Math.max(o,a),u={width:Math.round(i*l),height:Math.round(s*l)};return{userAgent:n.userAgent,viewport:t?u:n.viewport,isMobile:n.isMobile,hasTouch:n.hasTouch}},ix=e=>{let t={width:JM,height:YM};if(!e||e===Sa)return t;let r=$p(e);return r.viewport?{width:r.viewport.width,height:r.viewport.height+Bp}:t},sx=e=>{let t={width:QM,height:e3};if(!e||e===Sa)return t;let r=$p(e);return r.viewport?{width:r.viewport.width,height:r.viewport.height}:t},ox=e=>!e||e===Sa?void 0:fu(e)?.channel,ax=e=>!e||e===Sa?"chromium":fu(e)?.defaultBrowserType??"chromium",mu=(e=>(e.PASSWORD="password",e.OAUTH2="oauth2",e.SSO="sso",e.API="api",e))(mu||{}),Gg=(e=>(e.SMS="sms",e.EMAIL="email",e.TOTP="totp",e))(Gg||{});Vg=class lx{constructor(){Pg(this,"data",{}),Pg(this,"sensitive",new Set)}get(t){return this.data[t]}set(t,r,n=!1){this.data[t]=r,n?this.sensitive.add(t):this.sensitive.has(t)&&this.sensitive.delete(t)}getAll(){return{...this.data}}isSensitive(t){return this.sensitive.has(t)}getAllSensitiveKeys(){return new Set(this.sensitive)}delete(t){return this.sensitive.delete(t),delete this.data[t]}clear(){this.data={},this.sensitive.clear()}has(t){return t in this.data}get size(){return Object.keys(this.data).length}merge(t){for(let[r,n]of Object.entries(t.getAll()))this.set(r,n,t.isSensitive(r))}toJSON(){return{data:{...this.data},sensitiveKeys:Array.from(this.sensitive)}}static fromJSON(t){let r=new lx;if(t.data){let n=new Set(t.sensitiveKeys||[]);for(let[i,s]of Object.entries(t.data))r.set(i,s,n.has(i))}return r}},i3=Ve.enum(["JS_CODE","AI_MODE"]),kv=Ve.object({type:i3,expression:Ve.string()}),s3=Ve.enum(["DRAFT","STEP","ACTION","IF_ELSE","WHILE_LOOP"]),lu=Ve.object({uid:Ve.string(),type:s3,comment:Ve.string().optional()}),o3=Ve.object({action_data:Ve.object({action_name:Ve.string(),kwargs:Ve.record(Ve.any()).optional(),args:Ve.array(Ve.any()).optional()}),action_description:Ve.string().optional(),url:Ve.string().optional(),xpath:Ve.string().nullable().optional(),locator:Ve.string().nullable().optional(),css_selector:Ve.string().nullable().optional(),unique_selector:Ve.string().nullable().optional(),element_index:Ve.number().nullable().optional(),frame_path:Ve.array(Ve.any()).optional(),artifacts:Ve.record(Ve.any()).optional(),feedback:Ve.string().optional(),original_browser_use_action:Ve.any().optional()}).passthrough(),a3=lu.extend({type:Ve.literal("DRAFT"),description:Ve.string()}),l3=lu.extend({type:Ve.literal("ACTION"),description:Ve.string(),action_entity:o3.optional(),locator:Ve.string().optional(),use_pure_vision:Ve.boolean().optional()}),di=Ve.lazy(()=>Ve.union([a3,l3,lu.extend({type:Ve.literal("STEP"),description:Ve.string().optional().default(""),statements:Ve.array(di),reference_id:Ve.number().optional(),template_path:Ve.string().optional(),template_params:Ve.record(Ve.string()).optional()}),lu.extend({type:Ve.literal("IF_ELSE"),description:Ve.string().optional(),condition:kv,then:Ve.array(di),else:Ve.array(di).optional()}),lu.extend({type:Ve.literal("WHILE_LOOP"),description:Ve.string().optional(),condition:kv,body:Ve.array(di),timeout_ms:Ve.number().optional()})])),c3=Ve.object({name:Ve.string(),statements:Ve.array(di),teardown:Ve.array(di).optional(),skip:Ve.union([Ve.boolean(),Ve.string()]).optional(),timeout:Ve.number().optional(),fail:Ve.union([Ve.boolean(),Ve.string()]).optional(),only:Ve.boolean().optional(),slow:Ve.boolean().optional()}),u3=Ve.object({tests:Ve.array(c3).min(1),beforeAll:Ve.array(di).optional(),afterAll:Ve.array(di).optional(),beforeEach:Ve.array(di).optional(),afterEach:Ve.array(di).optional()}),rse=Ve.object({comment:Ve.string().optional(),version:Ve.string().optional(),goal:Ve.string().optional(),url:Ve.string().optional(),baseURL:Ve.string().optional(),final_feedback:Ve.string().optional(),completed:Ve.boolean().optional(),success:Ve.boolean().optional(),statements:Ve.array(di).optional(),teardown:Ve.array(di).optional(),last_modified_at:Ve.string().optional(),testGroup:u3.optional()}).refine(e=>e.testGroup!==void 0?e.goal===void 0&&(e.statements===void 0||e.statements.length===0):e.goal!==void 0,{message:"TestFlow must have either goal/statements (single test) or testGroup (suite), not both"}),nse=1024*1024,d3=5e3,p3=1e4});var dx={};Li(dx,{default:()=>E3});import{createRequire as h3}from"module";var wse,f3,cx,m3,g3,y3,b3,ux,w3,_3,v3,x3,E3,px=mt(()=>{"use strict";qn();wse=h3(import.meta.url),f3=_e((e,t)=>{"use strict";var r=1e3,n=r*60,i=n*60,s=i*24,o=s*7,a=s*365.25;t.exports=function(h,m){m=m||{};var y=typeof h;if(y==="string"&&h.length>0)return l(h);if(y==="number"&&isFinite(h))return m.long?d(h):u(h);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(h))};function l(h){if(h=String(h),!(h.length>100)){var m=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(h);if(m){var y=parseFloat(m[1]),b=(m[2]||"ms").toLowerCase();switch(b){case"years":case"year":case"yrs":case"yr":case"y":return y*a;case"weeks":case"week":case"w":return y*o;case"days":case"day":case"d":return y*s;case"hours":case"hour":case"hrs":case"hr":case"h":return y*i;case"minutes":case"minute":case"mins":case"min":case"m":return y*n;case"seconds":case"second":case"secs":case"sec":case"s":return y*r;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return y;default:return}}}}function u(h){var m=Math.abs(h);return m>=s?Math.round(h/s)+"d":m>=i?Math.round(h/i)+"h":m>=n?Math.round(h/n)+"m":m>=r?Math.round(h/r)+"s":h+"ms"}function d(h){var m=Math.abs(h);return m>=s?p(h,m,s,"day"):m>=i?p(h,m,i,"hour"):m>=n?p(h,m,n,"minute"):m>=r?p(h,m,r,"second"):h+" ms"}function p(h,m,y,b){var w=m>=y*1.5;return Math.round(h/y)+" "+b+(w?"s":"")}}),cx=_e((e,t)=>{"use strict";function r(n){s.debug=s,s.default=s,s.coerce=p,s.disable=u,s.enable=a,s.enabled=d,s.humanize=f3(),s.destroy=h,Object.keys(n).forEach(m=>{s[m]=n[m]}),s.names=[],s.skips=[],s.formatters={};function i(m){let y=0;for(let b=0;b<m.length;b++)y=(y<<5)-y+m.charCodeAt(b),y|=0;return s.colors[Math.abs(y)%s.colors.length]}s.selectColor=i;function s(m){let y,b=null,w,E;function x(...C){if(!x.enabled)return;let R=x,k=Number(new Date),T=k-(y||k);R.diff=T,R.prev=y,R.curr=k,y=k,C[0]=s.coerce(C[0]),typeof C[0]!="string"&&C.unshift("%O");let D=0;C[0]=C[0].replace(/%([a-zA-Z%])/g,(O,I)=>{if(O==="%%")return"%";D++;let L=s.formatters[I];if(typeof L=="function"){let F=C[D];O=L.call(R,F),C.splice(D,1),D--}return O}),s.formatArgs.call(R,C),(R.log||s.log).apply(R,C)}return x.namespace=m,x.useColors=s.useColors(),x.color=s.selectColor(m),x.extend=o,x.destroy=s.destroy,Object.defineProperty(x,"enabled",{enumerable:!0,configurable:!1,get:()=>b!==null?b:(w!==s.namespaces&&(w=s.namespaces,E=s.enabled(m)),E),set:C=>{b=C}}),typeof s.init=="function"&&s.init(x),x}function o(m,y){let b=s(this.namespace+(typeof y>"u"?":":y)+m);return b.log=this.log,b}function a(m){s.save(m),s.namespaces=m,s.names=[],s.skips=[];let y=(typeof m=="string"?m:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let b of y)b[0]==="-"?s.skips.push(b.slice(1)):s.names.push(b)}function l(m,y){let b=0,w=0,E=-1,x=0;for(;b<m.length;)if(w<y.length&&(y[w]===m[b]||y[w]==="*"))y[w]==="*"?(E=w,x=b,w++):(b++,w++);else if(E!==-1)w=E+1,x++,b=x;else return!1;for(;w<y.length&&y[w]==="*";)w++;return w===y.length}function u(){let m=[...s.names,...s.skips.map(y=>"-"+y)].join(",");return s.enable(""),m}function d(m){for(let y of s.skips)if(l(m,y))return!1;for(let y of s.names)if(l(m,y))return!0;return!1}function p(m){return m instanceof Error?m.stack||m.message:m}function h(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return s.enable(s.load()),s}t.exports=r}),m3=_e((e,t)=>{"use strict";e.formatArgs=n,e.save=i,e.load=s,e.useColors=r,e.storage=o(),e.destroy=(()=>{let l=!1;return()=>{l||(l=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})(),e.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function r(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let l;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&(l=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(l[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function n(l){if(l[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+l[0]+(this.useColors?"%c ":" ")+"+"+t.exports.humanize(this.diff),!this.useColors)return;let u="color: "+this.color;l.splice(1,0,u,"color: inherit");let d=0,p=0;l[0].replace(/%[a-zA-Z%]/g,h=>{h!=="%%"&&(d++,h==="%c"&&(p=d))}),l.splice(p,0,u)}e.log=console.debug||console.log||(()=>{});function i(l){try{l?e.storage.setItem("debug",l):e.storage.removeItem("debug")}catch{}}function s(){let l;try{l=e.storage.getItem("debug")||e.storage.getItem("DEBUG")}catch{}return!l&&typeof process<"u"&&"env"in process&&(l=process.env.DEBUG),l}function o(){try{return localStorage}catch{}}t.exports=cx()(e);var{formatters:a}=t.exports;a.j=function(l){try{return JSON.stringify(l)}catch(u){return"[UnexpectedJSONParseError]: "+u.message}}}),g3=_e((e,t)=>{"use strict";t.exports=(r,n=process.argv)=>{let i=r.startsWith("-")?"":r.length===1?"-":"--",s=n.indexOf(i+r),o=n.indexOf("--");return s!==-1&&(o===-1||s<o)}}),y3=_e((e,t)=>{"use strict";var r=qe("os"),n=qe("tty"),i=g3(),{env:s}=process,o;i("no-color")||i("no-colors")||i("color=false")||i("color=never")?o=0:(i("color")||i("colors")||i("color=true")||i("color=always"))&&(o=1),"FORCE_COLOR"in s&&(s.FORCE_COLOR==="true"?o=1:s.FORCE_COLOR==="false"?o=0:o=s.FORCE_COLOR.length===0?1:Math.min(parseInt(s.FORCE_COLOR,10),3));function a(d){return d===0?!1:{level:d,hasBasic:!0,has256:d>=2,has16m:d>=3}}function l(d,p){if(o===0)return 0;if(i("color=16m")||i("color=full")||i("color=truecolor"))return 3;if(i("color=256"))return 2;if(d&&!p&&o===void 0)return 0;let h=o||0;if(s.TERM==="dumb")return h;if(process.platform==="win32"){let m=r.release().split(".");return Number(m[0])>=10&&Number(m[2])>=10586?Number(m[2])>=14931?3:2:1}if("CI"in s)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some(m=>m in s)||s.CI_NAME==="codeship"?1:h;if("TEAMCITY_VERSION"in s)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(s.TEAMCITY_VERSION)?1:0;if(s.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in s){let m=parseInt((s.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(s.TERM_PROGRAM){case"iTerm.app":return m>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(s.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(s.TERM)||"COLORTERM"in s?1:h}function u(d){let p=l(d,d&&d.isTTY);return a(p)}t.exports={supportsColor:u,stdout:a(l(!0,n.isatty(1))),stderr:a(l(!0,n.isatty(2)))}}),b3=_e((e,t)=>{"use strict";var r=qe("tty"),n=qe("util");e.init=d,e.log=a,e.formatArgs=s,e.save=l,e.load=u,e.useColors=i,e.destroy=n.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."),e.colors=[6,2,3,4,5,1];try{let h=y3();h&&(h.stderr||h).level>=2&&(e.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch{}e.inspectOpts=Object.keys(process.env).filter(h=>/^debug_/i.test(h)).reduce((h,m)=>{let y=m.substring(6).toLowerCase().replace(/_([a-z])/g,(w,E)=>E.toUpperCase()),b=process.env[m];return/^(yes|on|true|enabled)$/i.test(b)?b=!0:/^(no|off|false|disabled)$/i.test(b)?b=!1:b==="null"?b=null:b=Number(b),h[y]=b,h},{});function i(){return"colors"in e.inspectOpts?!!e.inspectOpts.colors:r.isatty(process.stderr.fd)}function s(h){let{namespace:m,useColors:y}=this;if(y){let b=this.color,w="\x1B[3"+(b<8?b:"8;5;"+b),E=` ${w};1m${m} \x1B[0m`;h[0]=E+h[0].split(`
|
|
268
|
+
`,h)+1}return{type:p,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(p){switch(this.type){case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return this.flowScalar(this.type);case"block-scalar-header":return{type:"block-scalar",offset:this.offset,indent:this.indent,props:[this.sourceToken],source:""};case"flow-map-start":case"flow-seq-start":return{type:"flow-collection",offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case"seq-item-ind":return{type:"block-seq",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case"explicit-key-ind":{this.onKeyLine=!0;let h=a(p),m=l(h);return m.push(this.sourceToken),{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:m,explicitKey:!0}]}}case"map-value-ind":{this.onKeyLine=!0;let h=a(p),m=l(h);return{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:m,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(p,h){return this.type!=="comment"||this.indent<=h?!1:p.every(m=>m.type==="newline"||m.type==="space")}*documentEnd(p){this.type!=="doc-mode"&&(p.end?p.end.push(this.sourceToken):p.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop()))}*lineEnd(p){switch(this.type){case"comma":case"doc-start":case"doc-end":case"flow-seq-end":case"flow-map-end":case"map-value-ind":yield*this.pop(),yield*this.step();break;case"newline":this.onKeyLine=!1;case"space":case"comment":default:p.end?p.end.push(this.sourceToken):p.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop())}}};e.Parser=d}),zM=_e(e=>{"use strict";var t=Zv(),r=Lp(),n=Mp(),i=Nv(),s=jt(),o=ex(),a=tx();function l(m){let y=m.prettyErrors!==!1;return{lineCounter:m.lineCounter||y&&new o.LineCounter||null,prettyErrors:y}}function u(m,y={}){let{lineCounter:b,prettyErrors:w}=l(y),E=new a.Parser(b?.addNewLine),x=new t.Composer(y),C=Array.from(x.compose(E.parse(m)));if(w&&b)for(let R of C)R.errors.forEach(n.prettifyError(m,b)),R.warnings.forEach(n.prettifyError(m,b));return C.length>0?C:Object.assign([],{empty:!0},x.streamInfo())}function d(m,y={}){let{lineCounter:b,prettyErrors:w}=l(y),E=new a.Parser(b?.addNewLine),x=new t.Composer(y),C=null;for(let R of x.compose(E.parse(m),!0,m.length))if(!C)C=R;else if(C.options.logLevel!=="silent"){C.errors.push(new n.YAMLParseError(R.range.slice(0,2),"MULTIPLE_DOCS","Source contains multiple documents; please use YAML.parseAllDocuments()"));break}return w&&b&&(C.errors.forEach(n.prettifyError(m,b)),C.warnings.forEach(n.prettifyError(m,b))),C}function p(m,y,b){let w;typeof y=="function"?w=y:b===void 0&&y&&typeof y=="object"&&(b=y);let E=d(m,b);if(!E)return null;if(E.warnings.forEach(x=>i.warn(E.options.logLevel,x)),E.errors.length>0){if(E.options.logLevel!=="silent")throw E.errors[0];E.errors=[]}return E.toJS(Object.assign({reviver:w},b))}function h(m,y,b){let w=null;if(typeof y=="function"||Array.isArray(y)?w=y:b===void 0&&y&&(b=y),typeof b=="string"&&(b=b.length),typeof b=="number"){let E=Math.round(b);b=E<1?void 0:E>8?{indent:8}:{indent:E}}if(m===void 0){let{keepUndefined:E}=b??y??{};if(!E)return}return s.isDocument(m)&&!w?m.toString(b):new r.Document(m,w,b).toString(b)}e.parse=p,e.parseAllDocuments=u,e.parseDocument=d,e.stringify=h}),rx=_e(e=>{"use strict";var t=Zv(),r=Lp(),n=Wv(),i=Mp(),s=Ip(),o=jt(),a=va(),l=zr(),u=xa(),d=Ea(),p=qg(),h=Qv(),m=ex(),y=tx(),b=zM(),w=kp();e.Composer=t.Composer,e.Document=r.Document,e.Schema=n.Schema,e.YAMLError=i.YAMLError,e.YAMLParseError=i.YAMLParseError,e.YAMLWarning=i.YAMLWarning,e.Alias=s.Alias,e.isAlias=o.isAlias,e.isCollection=o.isCollection,e.isDocument=o.isDocument,e.isMap=o.isMap,e.isNode=o.isNode,e.isPair=o.isPair,e.isScalar=o.isScalar,e.isSeq=o.isSeq,e.Pair=a.Pair,e.Scalar=l.Scalar,e.YAMLMap=u.YAMLMap,e.YAMLSeq=d.YAMLSeq,e.CST=p,e.Lexer=h.Lexer,e.LineCounter=m.LineCounter,e.Parser=y.Parser,e.parse=b.parse,e.parseAllDocuments=b.parseAllDocuments,e.parseDocument=b.parseDocument,e.stringify=b.stringify,e.visit=w.visit,e.visitAsync=w.visitAsync}),Xie=Hr(rx(),1),Qie=Hr(rx(),1),fu=(e=>(e.PASSWORD="password",e.OAUTH2="oauth2",e.SSO="sso",e.API="api",e))(fu||{}),Gg=(e=>(e.SMS="sms",e.EMAIL="email",e.TOTP="totp",e))(Gg||{});KM="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",Bp=112,JM=1920,YM=1080,XM=1920,ZM=1080-Bp,QM=1280,e3=720,t3=500,r3=500,Sa="Desktop Chrome",kl=(e=>(e.Chromium="chromium",e.Firefox="firefox",e.Webkit="webkit",e))(kl||{}),nx={"Blackberry PlayBook":{name:"Blackberry PlayBook",userAgent:"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/26.0 Safari/536.2+",screen:{width:600,height:1024},viewport:{width:600,height:1024},deviceScaleFactor:1,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"BlackBerry Z30":{name:"BlackBerry Z30",userAgent:"Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/26.0 Mobile Safari/537.10+",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy Note 3":{name:"Galaxy Note 3",userAgent:"Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy Note II":{name:"Galaxy Note II",userAgent:"Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy S III":{name:"Galaxy S III",userAgent:"Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy S5":{name:"Galaxy S5",userAgent:"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S8":{name:"Galaxy S8",userAgent:"Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:740},viewport:{width:360,height:740},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S9+":{name:"Galaxy S9+",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:320,height:658},viewport:{width:320,height:658},deviceScaleFactor:4.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S24":{name:"Galaxy S24",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-S921U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:780},viewport:{width:360,height:780},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy A55":{name:"Galaxy A55",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:480,height:1040},viewport:{width:480,height:1040},deviceScaleFactor:2.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy Tab S4":{name:"Galaxy Tab S4",userAgent:"Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:712,height:1138},viewport:{width:712,height:1138},deviceScaleFactor:2.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy Tab S9":{name:"Galaxy Tab S9",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-X710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:640,height:1024},viewport:{width:640,height:1024},deviceScaleFactor:2.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"iPad (gen 5)":{name:"iPad (gen 5)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 6)":{name:"iPad (gen 6)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 7)":{name:"iPad (gen 7)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:810,height:1080},viewport:{width:810,height:1080},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 11)":{name:"iPad (gen 11)",userAgent:"Mozilla/5.0 (iPad; CPU OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/19E241 Safari/604.1",screen:{width:656,height:944},viewport:{width:656,height:944},deviceScaleFactor:2.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad Mini":{name:"iPad Mini",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad Pro 11":{name:"iPad Pro 11",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:834,height:1194},viewport:{width:834,height:1194},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 6":{name:"iPhone 6",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 6 Plus":{name:"iPhone 6 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 7":{name:"iPhone 7",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 7 Plus":{name:"iPhone 7 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 8":{name:"iPhone 8",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 8 Plus":{name:"iPhone 8 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone SE":{name:"iPhone SE",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/26.0 Mobile/14E304 Safari/602.1",screen:{width:320,height:568},viewport:{width:320,height:568},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone SE (3rd gen)":{name:"iPhone SE (3rd gen)",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/26.0 Mobile/19E241 Safari/602.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone X":{name:"iPhone X",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:812},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone XR":{name:"iPhone XR",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:896},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11":{name:"iPhone 11",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:715},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11 Pro":{name:"iPhone 11 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:635},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11 Pro Max":{name:"iPhone 11 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:715},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12":{name:"iPhone 12",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Pro":{name:"iPhone 12 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Pro Max":{name:"iPhone 12 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Mini":{name:"iPhone 12 Mini",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:629},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13":{name:"iPhone 13",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Pro":{name:"iPhone 13 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Pro Max":{name:"iPhone 13 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Mini":{name:"iPhone 13 Mini",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:629},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14":{name:"iPhone 14",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Plus":{name:"iPhone 14 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Pro":{name:"iPhone 14 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:660},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Pro Max":{name:"iPhone 14 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:740},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15":{name:"iPhone 15",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:659},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Plus":{name:"iPhone 15 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:739},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Pro":{name:"iPhone 15 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:659},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Pro Max":{name:"iPhone 15 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:739},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Kindle Fire HDX":{name:"Kindle Fire HDX",userAgent:"Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true",screen:{width:800,height:1280},viewport:{width:800,height:1280},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"LG Optimus L70":{name:"LG Optimus L70",userAgent:"Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:384,height:640},viewport:{width:384,height:640},deviceScaleFactor:1.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Microsoft Lumia 550":{name:"Microsoft Lumia 550",userAgent:"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36 Edge/14.14263",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Microsoft Lumia 950":{name:"Microsoft Lumia 950",userAgent:"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36 Edge/14.14263",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:4,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 10":{name:"Nexus 10",userAgent:"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:800,height:1280},viewport:{width:800,height:1280},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 4":{name:"Nexus 4",userAgent:"Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:384,height:640},viewport:{width:384,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 5":{name:"Nexus 5",userAgent:"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 5X":{name:"Nexus 5X",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 6":{name:"Nexus 6",userAgent:"Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 6P":{name:"Nexus 6P",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 7":{name:"Nexus 7",userAgent:"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:600,height:960},viewport:{width:600,height:960},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nokia Lumia 520":{name:"Nokia Lumia 520",userAgent:"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)",screen:{width:320,height:533},viewport:{width:320,height:533},deviceScaleFactor:1.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nokia N9":{name:"Nokia N9",userAgent:"Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13",screen:{width:480,height:854},viewport:{width:480,height:854},deviceScaleFactor:1,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Pixel 2":{name:"Pixel 2",userAgent:"Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:411,height:731},viewport:{width:411,height:731},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 2 XL":{name:"Pixel 2 XL",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:411,height:823},viewport:{width:411,height:823},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 3":{name:"Pixel 3",userAgent:"Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:393,height:786},viewport:{width:393,height:786},deviceScaleFactor:2.75,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 4":{name:"Pixel 4",userAgent:"Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:353,height:745},viewport:{width:353,height:745},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 4a (5G)":{name:"Pixel 4a (5G)",userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:892},viewport:{width:412,height:765},deviceScaleFactor:2.63,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 5":{name:"Pixel 5",userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:393,height:851},viewport:{width:393,height:727},deviceScaleFactor:2.75,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 7":{name:"Pixel 7",userAgent:"Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:915},viewport:{width:412,height:839},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Moto G4":{name:"Moto G4",userAgent:"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Desktop Chrome HiDPI":{name:"Desktop Chrome HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Edge HiDPI":{name:"Desktop Edge HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Firefox HiDPI":{name:"Desktop Firefox HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0.1) Gecko/20100101 Firefox/142.0.1",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"firefox"},"Desktop Safari":{name:"Desktop Safari",userAgent:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"webkit"},"Desktop Chrome":{name:"Desktop Chrome",displayName:"Playwright Chromium",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Chrome Medium Resolution":{name:"Desktop Chrome Medium Resolution",displayName:"Playwright Chromium",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Chrome (Branded)":{name:"Desktop Chrome (Branded)",displayName:"Google Chrome",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"chrome"},"Desktop Chrome Medium Resolution (Branded)":{name:"Desktop Chrome Medium Resolution (Branded)",displayName:"Google Chrome",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"chrome"},"Desktop Edge":{name:"Desktop Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1920,height:1080},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Edge (Branded)":{name:"Desktop Edge (Branded)",displayName:"Microsoft Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"msedge"},"Desktop Edge Medium Resolution (Branded)":{name:"Desktop Edge Medium Resolution (Branded)",displayName:"Microsoft Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"msedge"},"Desktop Firefox":{name:"Desktop Firefox",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0.1) Gecko/20100101 Firefox/142.0.1",screen:{width:1920,height:1080},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"firefox"}},n3={desktop:["Desktop Chrome","Desktop Chrome Medium Resolution","Desktop Chrome (Branded)","Desktop Chrome Medium Resolution (Branded)","Desktop Edge (Branded)","Desktop Edge Medium Resolution (Branded)","Desktop Safari"],mobile:["iPhone 15 Pro Max","iPhone 15 Pro","iPhone 15 Plus","iPhone 15","iPhone 14 Pro Max","iPhone 14 Pro","iPhone 14 Plus","iPhone 14","iPhone 13 Pro Max","iPhone 13 Pro","iPhone 13","iPhone 13 Mini","iPhone 12 Pro Max","iPhone 12 Pro","iPhone 12","iPhone 12 Mini","iPhone 11 Pro Max","iPhone 11 Pro","iPhone 11","iPhone XR","iPhone X","iPhone SE (3rd gen)","iPhone SE","iPhone 8 Plus","iPhone 8","iPhone 7 Plus","iPhone 7","iPhone 6 Plus","iPhone 6","Galaxy S24","Galaxy A55","Galaxy S9+","Galaxy S8","Galaxy S5","Galaxy Note 3","Galaxy Note II","Galaxy S III","Pixel 7","Pixel 5","Pixel 4a (5G)","Pixel 4","Pixel 3","Pixel 2 XL","Pixel 2","Nexus 6P","Nexus 6","Nexus 5X","Nexus 5","Nexus 4","Moto G4","LG Optimus L70","Microsoft Lumia 950","Microsoft Lumia 550","Nokia Lumia 520","Nokia N9","BlackBerry Z30"]},Cp=(e,t=!1)=>{let r=["chromium"];return t&&r.push("webkit"),n3[e].map(n=>nx[n]).filter(n=>n.defaultBrowserType&&r.includes(n.defaultBrowserType))},mu=e=>nx[e],ese={desktop:{label:"Desktop",type:"desktop",devices:Cp("desktop")},mobile:{label:"Mobile Web",type:"mobile",devices:Cp("mobile")}},tse={desktop:{label:"Desktop",type:"desktop",devices:Cp("desktop",!0)},mobile:{label:"Mobile Web",type:"mobile",devices:Cp("mobile",!0)}},$p=(e,t=!1)=>{let r={userAgent:KM,viewport:{width:XM,height:ZM},isMobile:!1,hasTouch:!1};if(!e||e===Sa)return r;let n=mu(e);if(!n)return r;let{width:i,height:s}=n.viewport,o=Math.max(t3/i,1),a=Math.max(r3/s,1),l=Math.max(o,a),u={width:Math.round(i*l),height:Math.round(s*l)};return{userAgent:n.userAgent,viewport:t?u:n.viewport,isMobile:n.isMobile,hasTouch:n.hasTouch}},ix=e=>{let t={width:JM,height:YM};if(!e||e===Sa)return t;let r=$p(e);return r.viewport?{width:r.viewport.width,height:r.viewport.height+Bp}:t},sx=e=>{let t={width:QM,height:e3};if(!e||e===Sa)return t;let r=$p(e);return r.viewport?{width:r.viewport.width,height:r.viewport.height}:t},ox=e=>!e||e===Sa?void 0:mu(e)?.channel,ax=e=>!e||e===Sa?"chromium":mu(e)?.defaultBrowserType??"chromium",Vg=class lx{constructor(){Pg(this,"data",{}),Pg(this,"sensitive",new Set)}get(t){return this.data[t]}set(t,r,n=!1){this.data[t]=r,n?this.sensitive.add(t):this.sensitive.has(t)&&this.sensitive.delete(t)}getAll(){return{...this.data}}isSensitive(t){return this.sensitive.has(t)}getAllSensitiveKeys(){return new Set(this.sensitive)}delete(t){return this.sensitive.delete(t),delete this.data[t]}clear(){this.data={},this.sensitive.clear()}has(t){return t in this.data}get size(){return Object.keys(this.data).length}merge(t){for(let[r,n]of Object.entries(t.getAll()))this.set(r,n,t.isSensitive(r))}toJSON(){return{data:{...this.data},sensitiveKeys:Array.from(this.sensitive)}}static fromJSON(t){let r=new lx;if(t.data){let n=new Set(t.sensitiveKeys||[]);for(let[i,s]of Object.entries(t.data))r.set(i,s,n.has(i))}return r}},i3=Ve.enum(["JS_CODE","AI_MODE"]),kv=Ve.object({type:i3,expression:Ve.string()}),s3=Ve.enum(["DRAFT","STEP","ACTION","IF_ELSE","WHILE_LOOP"]),lu=Ve.object({uid:Ve.string(),type:s3,comment:Ve.string().optional()}),o3=Ve.object({action_data:Ve.object({action_name:Ve.string(),kwargs:Ve.record(Ve.any()).optional(),args:Ve.array(Ve.any()).optional()}),action_description:Ve.string().optional(),url:Ve.string().optional(),xpath:Ve.string().nullable().optional(),locator:Ve.string().nullable().optional(),css_selector:Ve.string().nullable().optional(),unique_selector:Ve.string().nullable().optional(),element_index:Ve.number().nullable().optional(),frame_path:Ve.array(Ve.any()).optional(),artifacts:Ve.record(Ve.any()).optional(),feedback:Ve.string().optional(),original_browser_use_action:Ve.any().optional()}).passthrough(),a3=lu.extend({type:Ve.literal("DRAFT"),description:Ve.string()}),l3=lu.extend({type:Ve.literal("ACTION"),description:Ve.string(),action_entity:o3.optional(),locator:Ve.string().optional(),use_pure_vision:Ve.boolean().optional()}),di=Ve.lazy(()=>Ve.union([a3,l3,lu.extend({type:Ve.literal("STEP"),description:Ve.string().optional().default(""),statements:Ve.array(di),reference_id:Ve.number().optional(),template_path:Ve.string().optional(),template_params:Ve.record(Ve.string()).optional()}),lu.extend({type:Ve.literal("IF_ELSE"),description:Ve.string().optional(),condition:kv,then:Ve.array(di),else:Ve.array(di).optional()}),lu.extend({type:Ve.literal("WHILE_LOOP"),description:Ve.string().optional(),condition:kv,body:Ve.array(di),timeout_ms:Ve.number().optional()})])),c3=Ve.object({name:Ve.string(),statements:Ve.array(di),teardown:Ve.array(di).optional(),skip:Ve.union([Ve.boolean(),Ve.string()]).optional(),timeout:Ve.number().optional(),fail:Ve.union([Ve.boolean(),Ve.string()]).optional(),only:Ve.boolean().optional(),slow:Ve.boolean().optional()}),u3=Ve.object({tests:Ve.array(c3).min(1),beforeAll:Ve.array(di).optional(),afterAll:Ve.array(di).optional(),beforeEach:Ve.array(di).optional(),afterEach:Ve.array(di).optional()}),rse=Ve.object({comment:Ve.string().optional(),version:Ve.string().optional(),goal:Ve.string().optional(),url:Ve.string().optional(),baseURL:Ve.string().optional(),final_feedback:Ve.string().optional(),completed:Ve.boolean().optional(),success:Ve.boolean().optional(),statements:Ve.array(di).optional(),teardown:Ve.array(di).optional(),last_modified_at:Ve.string().optional(),testGroup:u3.optional()}).refine(e=>e.testGroup!==void 0?e.goal===void 0&&(e.statements===void 0||e.statements.length===0):e.goal!==void 0,{message:"TestFlow must have either goal/statements (single test) or testGroup (suite), not both"}),nse=1024*1024,d3=5e3,p3=1e4});var dx={};Li(dx,{default:()=>E3});import{createRequire as h3}from"module";var wse,f3,cx,m3,g3,y3,b3,ux,w3,_3,v3,x3,E3,px=mt(()=>{"use strict";qn();wse=h3(import.meta.url),f3=_e((e,t)=>{"use strict";var r=1e3,n=r*60,i=n*60,s=i*24,o=s*7,a=s*365.25;t.exports=function(h,m){m=m||{};var y=typeof h;if(y==="string"&&h.length>0)return l(h);if(y==="number"&&isFinite(h))return m.long?d(h):u(h);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(h))};function l(h){if(h=String(h),!(h.length>100)){var m=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(h);if(m){var y=parseFloat(m[1]),b=(m[2]||"ms").toLowerCase();switch(b){case"years":case"year":case"yrs":case"yr":case"y":return y*a;case"weeks":case"week":case"w":return y*o;case"days":case"day":case"d":return y*s;case"hours":case"hour":case"hrs":case"hr":case"h":return y*i;case"minutes":case"minute":case"mins":case"min":case"m":return y*n;case"seconds":case"second":case"secs":case"sec":case"s":return y*r;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return y;default:return}}}}function u(h){var m=Math.abs(h);return m>=s?Math.round(h/s)+"d":m>=i?Math.round(h/i)+"h":m>=n?Math.round(h/n)+"m":m>=r?Math.round(h/r)+"s":h+"ms"}function d(h){var m=Math.abs(h);return m>=s?p(h,m,s,"day"):m>=i?p(h,m,i,"hour"):m>=n?p(h,m,n,"minute"):m>=r?p(h,m,r,"second"):h+" ms"}function p(h,m,y,b){var w=m>=y*1.5;return Math.round(h/y)+" "+b+(w?"s":"")}}),cx=_e((e,t)=>{"use strict";function r(n){s.debug=s,s.default=s,s.coerce=p,s.disable=u,s.enable=a,s.enabled=d,s.humanize=f3(),s.destroy=h,Object.keys(n).forEach(m=>{s[m]=n[m]}),s.names=[],s.skips=[],s.formatters={};function i(m){let y=0;for(let b=0;b<m.length;b++)y=(y<<5)-y+m.charCodeAt(b),y|=0;return s.colors[Math.abs(y)%s.colors.length]}s.selectColor=i;function s(m){let y,b=null,w,E;function x(...C){if(!x.enabled)return;let R=x,k=Number(new Date),T=k-(y||k);R.diff=T,R.prev=y,R.curr=k,y=k,C[0]=s.coerce(C[0]),typeof C[0]!="string"&&C.unshift("%O");let D=0;C[0]=C[0].replace(/%([a-zA-Z%])/g,(O,I)=>{if(O==="%%")return"%";D++;let L=s.formatters[I];if(typeof L=="function"){let F=C[D];O=L.call(R,F),C.splice(D,1),D--}return O}),s.formatArgs.call(R,C),(R.log||s.log).apply(R,C)}return x.namespace=m,x.useColors=s.useColors(),x.color=s.selectColor(m),x.extend=o,x.destroy=s.destroy,Object.defineProperty(x,"enabled",{enumerable:!0,configurable:!1,get:()=>b!==null?b:(w!==s.namespaces&&(w=s.namespaces,E=s.enabled(m)),E),set:C=>{b=C}}),typeof s.init=="function"&&s.init(x),x}function o(m,y){let b=s(this.namespace+(typeof y>"u"?":":y)+m);return b.log=this.log,b}function a(m){s.save(m),s.namespaces=m,s.names=[],s.skips=[];let y=(typeof m=="string"?m:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let b of y)b[0]==="-"?s.skips.push(b.slice(1)):s.names.push(b)}function l(m,y){let b=0,w=0,E=-1,x=0;for(;b<m.length;)if(w<y.length&&(y[w]===m[b]||y[w]==="*"))y[w]==="*"?(E=w,x=b,w++):(b++,w++);else if(E!==-1)w=E+1,x++,b=x;else return!1;for(;w<y.length&&y[w]==="*";)w++;return w===y.length}function u(){let m=[...s.names,...s.skips.map(y=>"-"+y)].join(",");return s.enable(""),m}function d(m){for(let y of s.skips)if(l(m,y))return!1;for(let y of s.names)if(l(m,y))return!0;return!1}function p(m){return m instanceof Error?m.stack||m.message:m}function h(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return s.enable(s.load()),s}t.exports=r}),m3=_e((e,t)=>{"use strict";e.formatArgs=n,e.save=i,e.load=s,e.useColors=r,e.storage=o(),e.destroy=(()=>{let l=!1;return()=>{l||(l=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})(),e.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function r(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let l;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&(l=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(l[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function n(l){if(l[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+l[0]+(this.useColors?"%c ":" ")+"+"+t.exports.humanize(this.diff),!this.useColors)return;let u="color: "+this.color;l.splice(1,0,u,"color: inherit");let d=0,p=0;l[0].replace(/%[a-zA-Z%]/g,h=>{h!=="%%"&&(d++,h==="%c"&&(p=d))}),l.splice(p,0,u)}e.log=console.debug||console.log||(()=>{});function i(l){try{l?e.storage.setItem("debug",l):e.storage.removeItem("debug")}catch{}}function s(){let l;try{l=e.storage.getItem("debug")||e.storage.getItem("DEBUG")}catch{}return!l&&typeof process<"u"&&"env"in process&&(l=process.env.DEBUG),l}function o(){try{return localStorage}catch{}}t.exports=cx()(e);var{formatters:a}=t.exports;a.j=function(l){try{return JSON.stringify(l)}catch(u){return"[UnexpectedJSONParseError]: "+u.message}}}),g3=_e((e,t)=>{"use strict";t.exports=(r,n=process.argv)=>{let i=r.startsWith("-")?"":r.length===1?"-":"--",s=n.indexOf(i+r),o=n.indexOf("--");return s!==-1&&(o===-1||s<o)}}),y3=_e((e,t)=>{"use strict";var r=qe("os"),n=qe("tty"),i=g3(),{env:s}=process,o;i("no-color")||i("no-colors")||i("color=false")||i("color=never")?o=0:(i("color")||i("colors")||i("color=true")||i("color=always"))&&(o=1),"FORCE_COLOR"in s&&(s.FORCE_COLOR==="true"?o=1:s.FORCE_COLOR==="false"?o=0:o=s.FORCE_COLOR.length===0?1:Math.min(parseInt(s.FORCE_COLOR,10),3));function a(d){return d===0?!1:{level:d,hasBasic:!0,has256:d>=2,has16m:d>=3}}function l(d,p){if(o===0)return 0;if(i("color=16m")||i("color=full")||i("color=truecolor"))return 3;if(i("color=256"))return 2;if(d&&!p&&o===void 0)return 0;let h=o||0;if(s.TERM==="dumb")return h;if(process.platform==="win32"){let m=r.release().split(".");return Number(m[0])>=10&&Number(m[2])>=10586?Number(m[2])>=14931?3:2:1}if("CI"in s)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some(m=>m in s)||s.CI_NAME==="codeship"?1:h;if("TEAMCITY_VERSION"in s)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(s.TEAMCITY_VERSION)?1:0;if(s.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in s){let m=parseInt((s.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(s.TERM_PROGRAM){case"iTerm.app":return m>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(s.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(s.TERM)||"COLORTERM"in s?1:h}function u(d){let p=l(d,d&&d.isTTY);return a(p)}t.exports={supportsColor:u,stdout:a(l(!0,n.isatty(1))),stderr:a(l(!0,n.isatty(2)))}}),b3=_e((e,t)=>{"use strict";var r=qe("tty"),n=qe("util");e.init=d,e.log=a,e.formatArgs=s,e.save=l,e.load=u,e.useColors=i,e.destroy=n.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."),e.colors=[6,2,3,4,5,1];try{let h=y3();h&&(h.stderr||h).level>=2&&(e.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch{}e.inspectOpts=Object.keys(process.env).filter(h=>/^debug_/i.test(h)).reduce((h,m)=>{let y=m.substring(6).toLowerCase().replace(/_([a-z])/g,(w,E)=>E.toUpperCase()),b=process.env[m];return/^(yes|on|true|enabled)$/i.test(b)?b=!0:/^(no|off|false|disabled)$/i.test(b)?b=!1:b==="null"?b=null:b=Number(b),h[y]=b,h},{});function i(){return"colors"in e.inspectOpts?!!e.inspectOpts.colors:r.isatty(process.stderr.fd)}function s(h){let{namespace:m,useColors:y}=this;if(y){let b=this.color,w="\x1B[3"+(b<8?b:"8;5;"+b),E=` ${w};1m${m} \x1B[0m`;h[0]=E+h[0].split(`
|
|
269
269
|
`).join(`
|
|
270
270
|
`+E),h.push(w+"m+"+t.exports.humanize(this.diff)+"\x1B[0m")}else h[0]=o()+m+" "+h[0]}function o(){return e.inspectOpts.hideDate?"":new Date().toISOString()+" "}function a(...h){return process.stderr.write(n.formatWithOptions(e.inspectOpts,...h)+`
|
|
271
271
|
`)}function l(h){h?process.env.DEBUG=h:delete process.env.DEBUG}function u(){return process.env.DEBUG}function d(h){h.inspectOpts={};let m=Object.keys(e.inspectOpts);for(let y=0;y<m.length;y++)h.inspectOpts[m[y]]=e.inspectOpts[m[y]]}t.exports=cx()(e);var{formatters:p}=t.exports;p.o=function(h){return this.inspectOpts.colors=this.useColors,n.inspect(h,this.inspectOpts).split(`
|
|
@@ -4686,7 +4686,7 @@ https://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety
|
|
|
4686
4686
|
`);this.baseURL=o.baseURL,this.timeout=o.timeout??dw.DEFAULT_TIMEOUT,this.logger=o.logger??console;let a="warn";this.logLevel=a,this.logLevel=tI(o.logLevel,"ClientOptions.logLevel",this)??tI(ec("OPENAI_LOG"),"process.env['OPENAI_LOG']",this)??a,this.fetchOptions=o.fetchOptions,this.maxRetries=o.maxRetries??2,this.fetch=o.fetch??jK(),_t(this,Yh,HK,"f"),this._options=o,this.apiKey=typeof t=="string"?t:"Missing Key",this.organization=r,this.project=n,this.webhookSecret=i}withOptions(e){return new this.constructor({...this._options,baseURL:this.baseURL,maxRetries:this.maxRetries,timeout:this.timeout,logger:this.logger,logLevel:this.logLevel,fetch:this.fetch,fetchOptions:this.fetchOptions,apiKey:this.apiKey,organization:this.organization,project:this.project,webhookSecret:this.webhookSecret,...e})}defaultQuery(){return this._options.defaultQuery}validateHeaders({values:e,nulls:t}){}async authHeaders(e){return tt([{Authorization:`Bearer ${this.apiKey}`}])}stringifyQuery(e){return KK(e,{arrayFormat:"brackets"})}getUserAgent(){return`${this.constructor.name}/JS ${nc}`}defaultIdempotencyKey(){return`stainless-node-retry-${U2()}`}makeStatusError(e,t,r,n){return Kn.generate(e,t,r,n)}async _callApiKey(){let e=this._options.apiKey;if(typeof e!="function")return!1;let t;try{t=await e()}catch(r){throw r instanceof gt?r:new gt(`Failed to get token from 'apiKey' function: ${r.message}`,{cause:r})}if(typeof t!="string"||!t)throw new gt(`Expected 'apiKey' function argument to return a string but it returned ${t}`);return this.apiKey=t,!0}buildURL(e,t,r){let n=!Se(this,Db,"m",pO).call(this)&&r||this.baseURL,i=PK(e)?new URL(e):new URL(n+(n.endsWith("/")&&e.startsWith("/")?e.slice(1):e)),s=this.defaultQuery();return OK(s)||(t={...s,...t}),typeof t=="object"&&t&&!Array.isArray(t)&&(i.search=this.stringifyQuery(t)),i.toString()}async prepareOptions(e){await this._callApiKey()}async prepareRequest(e,{url:t,options:r}){}get(e,t){return this.methodRequest("get",e,t)}post(e,t){return this.methodRequest("post",e,t)}patch(e,t){return this.methodRequest("patch",e,t)}put(e,t){return this.methodRequest("put",e,t)}delete(e,t){return this.methodRequest("delete",e,t)}methodRequest(e,t,r){return this.request(Promise.resolve(r).then(n=>({method:e,path:t,...n})))}request(e,t=null){return new cP(this,this.makeRequest(e,t,void 0))}async makeRequest(e,t,r){let n=await e,i=n.maxRetries??this.maxRetries;t==null&&(t=i),await this.prepareOptions(n);let{req:s,url:o,timeout:a}=await this.buildRequest(n,{retryCount:i-t});await this.prepareRequest(s,{url:o,options:n});let l="log_"+(Math.random()*(1<<24)|0).toString(16).padStart(6,"0"),u=r===void 0?"":`, retryOf: ${r}`,d=Date.now();if(bn(this).debug(`[${l}] sending request`,ja({retryOfRequestLogID:r,method:n.method,url:o,options:n,headers:s.headers})),n.signal?.aborted)throw new wi;let p=new AbortController,h=await this.fetchWithTimeout(o,s,a,p).catch(bb),m=Date.now();if(h instanceof globalThis.Error){let w=`retrying, ${t} attempts remaining`;if(n.signal?.aborted)throw new wi;let E=yb(h)||/timed? ?out/i.test(String(h)+("cause"in h?String(h.cause):""));if(t)return bn(this).info(`[${l}] connection ${E?"timed out":"failed"} - ${w}`),bn(this).debug(`[${l}] connection ${E?"timed out":"failed"} (${w})`,ja({retryOfRequestLogID:r,url:o,durationMs:m-d,message:h.message})),this.retryRequest(n,t,r??l);throw bn(this).info(`[${l}] connection ${E?"timed out":"failed"} - error; no more retries left`),bn(this).debug(`[${l}] connection ${E?"timed out":"failed"} (error; no more retries left)`,ja({retryOfRequestLogID:r,url:o,durationMs:m-d,message:h.message})),E?new Gb:new _f({cause:h})}let y=[...h.headers.entries()].filter(([w])=>w==="x-request-id").map(([w,E])=>", "+w+": "+JSON.stringify(E)).join(""),b=`[${l}${u}${y}] ${s.method} ${o} ${h.ok?"succeeded":"failed"} with status ${h.status} in ${m-d}ms`;if(!h.ok){let w=await this.shouldRetry(h);if(t&&w){let k=`retrying, ${t} attempts remaining`;return await UK(h.body),bn(this).info(`${b} - ${k}`),bn(this).debug(`[${l}] response error (${k})`,ja({retryOfRequestLogID:r,url:h.url,status:h.status,headers:h.headers,durationMs:m-d})),this.retryRequest(n,t,r??l,h.headers)}let E=w?"error; no more retries left":"error; not retryable";bn(this).info(`${b} - ${E}`);let x=await h.text().catch(k=>bb(k).message),C=RK(x),R=C?void 0:x;throw bn(this).debug(`[${l}] response error (${E})`,ja({retryOfRequestLogID:r,url:h.url,status:h.status,headers:h.headers,message:R,durationMs:Date.now()-d})),this.makeStatusError(h.status,C,R,h.headers)}return bn(this).info(b),bn(this).debug(`[${l}] response start`,ja({retryOfRequestLogID:r,url:h.url,status:h.status,headers:h.headers,durationMs:m-d})),{response:h,options:n,controller:p,requestLogID:l,retryOfRequestLogID:r,startTime:d}}getAPIList(e,t,r){return this.requestAPIList(t,r&&"then"in r?r.then(n=>({method:"get",path:e,...n})):{method:"get",path:e,...r})}requestAPIList(e,t){let r=this.makeRequest(t,null,void 0);return new nJ(this,r,e)}async fetchWithTimeout(e,t,r,n){let{signal:i,method:s,...o}=t||{},a=this._makeAbort(n);i&&i.addEventListener("abort",a,{once:!0});let l=setTimeout(a,r),u=globalThis.ReadableStream&&o.body instanceof globalThis.ReadableStream||typeof o.body=="object"&&o.body!==null&&Symbol.asyncIterator in o.body,d={signal:n.signal,...u?{duplex:"half"}:{},method:"GET",...o};s&&(d.method=s.toUpperCase());try{return await this.fetch.call(void 0,e,d)}finally{clearTimeout(l)}}async shouldRetry(e){let t=e.headers.get("x-should-retry");return t==="true"?!0:t==="false"?!1:e.status===408||e.status===409||e.status===429||e.status>=500}async retryRequest(e,t,r,n){let i,s=n?.get("retry-after-ms");if(s){let a=parseFloat(s);Number.isNaN(a)||(i=a)}let o=n?.get("retry-after");if(o&&!i){let a=parseFloat(o);Number.isNaN(a)?i=Date.parse(o)-Date.now():i=a*1e3}if(!(i&&0<=i&&i<60*1e3)){let a=e.maxRetries??this.maxRetries;i=this.calculateDefaultRetryTimeoutMillis(t,a)}return await vd(i),this.makeRequest(e,t-1,r)}calculateDefaultRetryTimeoutMillis(e,t){let r=t-e,n=Math.min(.5*Math.pow(2,r),8),i=1-Math.random()*.25;return n*i*1e3}async buildRequest(e,{retryCount:t=0}={}){let r={...e},{method:n,path:i,query:s,defaultBaseURL:o}=r,a=this.buildURL(i,s,o);"timeout"in r&&DK("timeout",r.timeout),r.timeout=r.timeout??this.timeout;let{bodyHeaders:l,body:u}=this.buildBody({options:r}),d=await this.buildHeaders({options:e,method:n,bodyHeaders:l,retryCount:t});return{req:{method:n,headers:d,...r.signal&&{signal:r.signal},...globalThis.ReadableStream&&u instanceof globalThis.ReadableStream&&{duplex:"half"},...u&&{body:u},...this.fetchOptions??{},...r.fetchOptions??{}},url:a,timeout:r.timeout}}async buildHeaders({options:e,method:t,bodyHeaders:r,retryCount:n}){let i={};this.idempotencyHeader&&t!=="get"&&(e.idempotencyKey||(e.idempotencyKey=this.defaultIdempotencyKey()),i[this.idempotencyHeader]=e.idempotencyKey);let s=tt([i,{Accept:"application/json","User-Agent":this.getUserAgent(),"X-Stainless-Retry-Count":String(n),...e.timeout?{"X-Stainless-Timeout":String(Math.trunc(e.timeout/1e3))}:{},...$K(),"OpenAI-Organization":this.organization,"OpenAI-Project":this.project},await this.authHeaders(e),this._options.defaultHeaders,r,e.headers]);return this.validateHeaders(s),s.values}_makeAbort(e){return()=>e.abort()}buildBody({options:{body:e,headers:t}}){if(!e)return{bodyHeaders:void 0,body:void 0};let r=tt([t]);return ArrayBuffer.isView(e)||e instanceof ArrayBuffer||e instanceof DataView||typeof e=="string"&&r.values.has("content-type")||globalThis.Blob&&e instanceof globalThis.Blob||e instanceof FormData||e instanceof URLSearchParams||globalThis.ReadableStream&&e instanceof globalThis.ReadableStream?{bodyHeaders:void 0,body:e}:typeof e=="object"&&(Symbol.asyncIterator in e||Symbol.iterator in e&&"next"in e&&typeof e.next=="function")?{bodyHeaders:void 0,body:eP(e)}:typeof e=="object"&&r.values.get("content-type")==="application/x-www-form-urlencoded"?{bodyHeaders:{"content-type":"application/x-www-form-urlencoded"},body:this.stringifyQuery(e)}:Se(this,Yh,"f").call(this,{body:e,headers:r})}};dw=kt,Yh=new WeakMap,Db=new WeakSet,pO=function(){return this.baseURL!=="https://api.openai.com/v1"};kt.OpenAI=dw;kt.DEFAULT_TIMEOUT=6e5;kt.OpenAIError=gt;kt.APIError=Kn;kt.APIConnectionError=_f;kt.APIConnectionTimeoutError=Gb;kt.APIUserAbortError=wi;kt.NotFoundError=W2;kt.ConflictError=V2;kt.RateLimitError=K2;kt.BadRequestError=H2;kt.AuthenticationError=q2;kt.InternalServerError=J2;kt.PermissionDeniedError=G2;kt.UnprocessableEntityError=z2;kt.InvalidWebhookSignatureError=id;kt.toFile=lJ;kt.Completions=BP;kt.Chat=Zb;kt.Embeddings=UP;kt.Files=qP;kt.Images=JP;kt.Audio=Ed;kt.Moderations=XP;kt.Models=YP;kt.FineTuning=gc;kt.Graders=lw;kt.VectorStores=If;kt.Webhooks=dO;kt.Beta=mc;kt.Batches=PP;kt.Uploads=uw;kt.Responses=Cf;kt.Realtime=Tf;kt.Conversations=rw;kt.Evals=iw;kt.Containers=tw;kt.Skills=kf;kt.Videos=cO;FJ="gpt-5.4",BJ={type:"computer"},bI=4;jJ={google:TK,openai:$J};hO=!1;oY=Bh.object({screenshotDescription:Bh.string().describe(`Description of the screenshot content, listing out key elements along with their Set of Mark indices,
|
|
4687
4687
|
and a description of their location: formatting example: [12] A red button with text "Submit", next to [11]
|
|
4688
4688
|
[45] A modal dialog titled "Confirmation",
|
|
4689
|
-
in the center of the screen`),explanation:Bh.string().describe("Step by step reasoning explaining your conclusion about the statement"),conclusion:Bh.enum(["true","false","unknown"]).describe("Whether the statement is true, false, or unknown if you cannot make a conclusion")});$h=null;});var bO={};Li(bO,{LoginType:()=>
|
|
4689
|
+
in the center of the screen`),explanation:Bh.string().describe("Step by step reasoning explaining your conclusion about the statement"),conclusion:Bh.enum(["true","false","unknown"]).describe("Whether the statement is true, false, or unknown if you cannot make a conclusion")});$h=null;});var bO={};Li(bO,{LoginType:()=>fu,checkLocators:()=>cu,createUnsignedInContext:()=>Kg,generateAndValidateLoginLocators:()=>jp,generateValidationLocators:()=>Jg,validateLogin:()=>gu,validateLoginLocators:()=>zg});import{createRequire as dY}from"module";var Dme,wO=mt(()=>{"use strict";Yg();au();wa();ei();qn();Dme=dY(import.meta.url)});var s_={};Li(s_,{ActionHandler:()=>Zs,ActionHelper:()=>Ku,Agent:()=>tl,AgentServices:()=>_D,AgentStepEventTypes:()=>vD,AgentTaskFailedError:()=>xD,BrowserManager:()=>Qw,DEFAULT_EVENT_LISTENER_LIMIT:()=>v0,DomService:()=>ni,EVENT_LISTENER_CANDIDATE_SELECTORS:()=>_0,HistoryTreeProcessor:()=>WA,INIT_SCRIPT:()=>Tp,INTERACTION_EVENT_TYPES:()=>qu,INTERACTIVE_ROLES:()=>yh,LogLevel:()=>Og,LoginType:()=>fu,MCPToolProvider:()=>RQ,OpenAIToolProvider:()=>Lb,SDK_VERSION:()=>wte,ToolRegistry:()=>Hu,TwoFactorAuthType:()=>Gg,VariableStore:()=>Vg,WebAgent:()=>tl,configureSdk:()=>Ep,createAgent:()=>bte,createAgentContext:()=>Nd,createToolRegistry:()=>OQ,createToolRegistryWithCapabilities:()=>NQ,discoverChromiumCdpUrl:()=>qQ,ensureToolsRegistered:()=>Xw,evaluateStatement:()=>Jl,executeStep:()=>Kl,exportMCPTools:()=>LQ,filterInteractionListeners:()=>qA,generateActionStep:()=>Vu,getActionEntityLocatorInfo:()=>Gr,getBrowserCdpUrl:()=>Ng,getCapabilitySummary:()=>DQ,getFramePath:()=>E0,getModel:()=>Xs,getPageInfo:()=>Av,getPageWsUrl:()=>Sv,getPlatformFromDeviceName:()=>QN,getProviderOptions:()=>Bo,getSdkConfig:()=>xn,getToolRegistry:()=>Zw,injectUserFunction:()=>aN,isInteractionEventType:()=>HA,isInteractiveRole:()=>UA,loadKnowledgeMappings:()=>bY,loadKnowledges:()=>yY,loadUserFunctions:()=>gY,logger:()=>te,newBrowserContext:()=>Ev,parseSSEStream:()=>fY,parseSdkLogLevelFromEnv:()=>wv,pickBestLocator:()=>_h,pickBestLocatorForElement:()=>vh,pickBestLocators:()=>KA,registerBrowser:()=>JN,replaceVariables:()=>Wg,runTask:()=>Yl,setWindowBounds:()=>Dg,toolRegistry:()=>Er,unregisterBrowser:()=>YN});import{createRequire as pY}from"module";import*as oN from"fs/promises";import*as Tc from"vm";import*as kw from"fs/promises";import{z as _O}from"zod";import{generateText as vY}from"ai";import{z as io}from"zod";import Ka from"fs";import MQ from"os";import Sd from"path";import{chromium as YO,firefox as FQ,webkit as BQ}from"playwright";import{execFileSync as jQ}from"child_process";import*as XN from"fs";import*as ZN from"path";import*as eD from"fs";import*as Cd from"path";import*as ln from"fs";import*as Fn from"path";import{z as sN}from"zod";import{generateText as _te,Output as vte}from"ai";import*as em from"fs";import xte from"p-retry";import{z as jf}from"zod";async function fY(e,t){if(!e.body)throw new Error("Response body is null");let r=e.body.getReader(),n=new TextDecoder,i="";try{for(;;){let{done:s,value:o}=await r.read();if(s)break;i+=n.decode(o,{stream:!0});let a=i.split(`
|
|
4690
4690
|
`);i=a.pop()||"";for(let l of a){let u=null;if(l.startsWith("data: "))try{let d=l.slice(6);d.trim()&&(u=JSON.parse(d))}catch(d){console.error(`Failed to parse SSE event: ${l}`,d);continue}u&&t(u)}}}finally{r.releaseLock()}}async function mY(e,t){let r=await import(e),n=Object.keys(r),i=new Tc.SyntheticModule(n,function(){for(let s of n)this.setExport(s,r[s])},{context:t});return await i.link(()=>{throw new Error("Nested imports not supported in VM context")}),await i.evaluate(),i}function aN(e,t,r,n=!1){if(e[t])if(n)te.info(`Overriding existing function: ${t}`),delete e[t];else{te.error(`The name ${t} is already defined in the global scope`);return}try{let i;if(Tc.isContext(e)?i=new Tc.Script(r,{importModuleDynamically:async s=>mY(s,e)}).runInContext(e):i=(0,eval)(r),typeof i!="function")throw new Error("The injected code must be a function");e[t]=i}catch(i){te.error(`Error injecting user function ${t}: ${i.message}`)}}async function gY(e,t,r=!1){try{let n=await oN.readFile(t,"utf8"),i=JSON.parse(n);te.info(`Loading ${Object.keys(i).length} user functions...`);for(let[s,o]of Object.entries(i))aN(e,s,o,r)}catch(n){throw te.error("Failed to load user functions:",n),n}}async function yY(e){try{let t=await kw.readFile(e,"utf8"),r=JSON.parse(t);return te.info(`Loaded ${r.length} knowledges from file`),r}catch(t){if(t.code==="ENOENT")return te.debug("No knowledges file found"),[];throw te.error("Failed to load knowledges:",t),t}}async function bY(e){try{let t=await kw.readFile(e,"utf8"),r=JSON.parse(t);return te.info(`Loaded ${r.length} knowledge mappings from file`),r}catch(t){if(t.code==="ENOENT")return te.debug("No knowledge mappings file found"),[];throw te.error("Failed to load knowledge mappings:",t),t}}function _Y(e){e.register({name:"perform_accurate_operation",description:"Perform an operation that requires accurate interaction like dragging or interacting with a specific area of an element. Only use this action when neccecary.",schema:wY,usesElementIndex:!1,async execute(t,r){let{instruction:n}=t,i={page:r.page,agentServices:r.agentServices,domService:r.domService},s=await Pf(n,i,{});if(s.status==="error"||!s.actionEntity)return{success:!1,actionEntity:{action_description:n,action_data:{action_name:"perform_accurate_operation",kwargs:{instruction:n}}},error:s.error||"Failed to generate action"};let{actionEntity:o}=s,a=await Wu(o,i);return{success:a.success,actionEntity:o,message:a.success?`Successfully executed action: ${o.action_data?.action_name}`:void 0,error:a.error}}})}function xY(e){return e.type===Kt.Tag||e.type===Kt.Script||e.type===Kt.Style}function Ow(e){return xY(e)}function NY(e){return e.type===Kt.CDATA}function DY(e){return e.type===Kt.Text}function RY(e){return e.type===Kt.Comment}function LY(e){return e.type===Kt.Directive}function MY(e){return e.type===Kt.Root}function hN(e,t=!1){let r;if(DY(e))r=new bw(e.data);else if(RY(e))r=new cN(e.data);else if(Ow(e)){let n=t?pw(e.children):[],i=new pN(e.name,{...e.attribs},n);n.forEach(s=>s.parent=i),e.namespace!=null&&(i.namespace=e.namespace),e["x-attribsNamespace"]&&(i["x-attribsNamespace"]={...e["x-attribsNamespace"]}),e["x-attribsPrefix"]&&(i["x-attribsPrefix"]={...e["x-attribsPrefix"]}),r=i}else if(NY(e)){let n=t?pw(e.children):[],i=new dN(n);n.forEach(s=>s.parent=i),r=i}else if(MY(e)){let n=t?pw(e.children):[],i=new ww(n);n.forEach(s=>s.parent=i),e["x-mode"]&&(i["x-mode"]=e["x-mode"]),r=i}else if(LY(e)){let n=new uN(e.name,e.data);e["x-name"]!=null&&(n["x-name"]=e["x-name"],n["x-publicId"]=e["x-publicId"],n["x-systemId"]=e["x-systemId"]),r=n}else throw new Error(`Not implemented yet: ${e.type}`);return r.startIndex=e.startIndex,r.endIndex=e.endIndex,e.sourceCodeLocation!=null&&(r.sourceCodeLocation=e.sourceCodeLocation),r}function pw(e){let t=e.map(r=>hN(r,!0));for(let r=1;r<t.length;r++)t[r].prev=t[r-1],t[r-1].next=t[r];return t}function $Y(e){let t=[...e.matchAll(BY)].map(n=>n.index||0);t.unshift(-1);let r=_w(t,0,t.length);return n=>fN(r,n)}function _w(e,t,r){if(r-t==1)return{offset:e[t],index:t+1};let n=Math.ceil((t+r)/2),i=_w(e,t,n),s=_w(e,n,r);return{offset:i.offset,low:i,high:s}}function fN(e,t){return function(r){return Object.prototype.hasOwnProperty.call(r,"index")}(e)?{line:e.index,column:t-e.offset}:fN(e.high.offset<t?e.high:e.low,t)}function mN(e,t="",r={}){let n=typeof t!="string"?t:r,i=typeof t=="string"?t:"",s=e.map(jY),o=!!n.lineNumbers;return function(a,l=0){let u=o?$Y(a):()=>({line:0,column:0}),d=l,p=[];e:for(;d<a.length;){let h=!1;for(let m of s){m.regex.lastIndex=d;let y=m.regex.exec(a);if(y&&y[0].length>0){if(!m.discard){let b=u(d),w=typeof m.replace=="string"?y[0].replace(new RegExp(m.regex.source,m.regex.flags),m.replace):y[0];p.push({state:i,name:m.name,text:w,offset:d,len:y[0].length,line:b.line,column:b.column})}if(d=m.regex.lastIndex,h=!0,m.push){let b=m.push(a,d);p.push(...b.tokens),d=b.offset}if(m.pop)break e;break}}if(!h)break}return{tokens:p,offset:d,complete:a.length<=d}}}function jY(e,t){return{...e,regex:UY(e,t)}}function UY(e,t){if(e.name.length===0)throw new Error(`Rule #${t} has empty name, which is not allowed.`);if(function(r){return Object.prototype.hasOwnProperty.call(r,"regex")}(e))return function(r){if(r.global)throw new Error(`Regular expression /${r.source}/${r.flags} contains the global flag, which is not allowed.`);return r.sticky?r:new RegExp(r.source,r.flags+"y")}(e.regex);if(function(r){return Object.prototype.hasOwnProperty.call(r,"str")}(e)){if(e.str.length===0)throw new Error(`Rule #${t} ("${e.name}") has empty "str" property, which is not allowed.`);return new RegExp(xO(e.str),"y")}return new RegExp(xO(e.name),"y")}function xO(e){return e.replace(/[-[\]{}()*+!<=:?./\\^$|#\s,]/g,"\\$&")}function ao(e,t){return(r,n)=>{let i=n,s;return n<r.tokens.length?(s=e(r.tokens[n],r,n),s!==void 0&&i++):t?.(r,n),s===void 0?{matched:!1}:{matched:!0,position:i,value:s}}}function Nw(e,t){return e.matched?{matched:!0,position:e.position,value:t(e.value,e.position)}:e}function qf(e,t){return e.matched?t(e):e}function kn(e,t){return(r,n)=>Nw(e(r,n),(i,s)=>t(i,r,n,s))}function Gf(e,t){return(r,n)=>{let i=e(r,n);return i.matched?i:{matched:!0,position:n,value:t}}}function Xf(...e){return(t,r)=>{for(let n of e){let i=n(t,r);if(i.matched)return i}return{matched:!1}}}function Qa(e,t){return(r,n)=>{let i=e(r,n);return i.matched?i:t(r,n)}}function HY(e,t){return(r,n)=>{let i=[],s=!0;do{let o=e(r,n);o.matched&&t(o.value,i.length+1,r,n,o.position)?(i.push(o.value),n=o.position):s=!1}while(s);return{matched:!0,position:n,value:i}}}function Dw(e){return HY(e,()=>!0)}function qY(e){return Bn(e,Dw(e),(t,r)=>[t,...r])}function Bn(e,t,r){return(n,i)=>qf(e(n,i),s=>Nw(t(n,s.position),(o,a)=>r(s.value,o,n,i,a)))}function GY(e,t){return Bn(e,t,r=>r)}function EO(e,t){return Bn(e,t,(r,n)=>n)}function Rw(e,t,r,n){return(i,s)=>qf(e(i,s),o=>qf(t(i,o.position),a=>Nw(r(i,a.position),(l,u)=>n(o.value,a.value,l,i,s,u))))}function gN(e,t,r){return Rw(e,t,r,(n,i)=>i)}function WY(...e){return(t,r)=>{let n=[],i=r;for(let s of e){let o=s(t,i);if(o.matched)n.push(o.value),i=o.position;else return{matched:!1}}return{matched:!0,position:i,value:n}}}function VY(...e){return zY(WY(...e))}function zY(e){return kn(e,t=>t.flatMap(r=>r))}function KY(e,t){return(r,n)=>{let i=!0,s=e,o=n;do{let a=t(s,r,o)(r,o);a.matched?(s=a.value,o=a.position):i=!1}while(i);return{matched:!0,position:o,value:s}}}function JY(e,t,r){return KY(e,n=>kn(t,(i,s,o,a)=>r(n,i,s,o,a)))}function yN(e,t,r){return YY(e,n=>JY(n,Bn(t,r,(i,s)=>[i,s]),(i,[s,o])=>s(i,o)))}function YY(e,t){return(r,n)=>qf(e(r,n),i=>t(i.value,r,n,i.position)(r,i.position))}function _N([e,t,r],[n,i,s]){return[e+n,t+i,r+s]}function sX(e){return e.reduce(_N,[0,0,0])}function Lw(e){let t=iX(e);return cX({tokens:t.tokens,options:void 0},0).value}function Sr(e){return ao(t=>t.name===e?!0:void 0)}function Ec(e){return gN(vw,e,vw)}function SX(e,t){if(!(typeof t=="string"||t instanceof String))throw new Error("Expected a selector string. Actual input is not a string!");let r=nX(t);if(!r.complete)throw new Error(`The input "${t}" was only partially tokenized, stopped at offset ${r.offset}!
|
|
4691
4691
|
`+CO(t,r.offset));let n=Ec(e)({tokens:r.tokens,options:void 0},0);if(!n.matched)throw new Error(`No match for "${t}" input!`);if(n.position<r.tokens.length){let i=r.tokens[n.position];throw new Error(`The input "${t}" was only partially parsed, stopped at offset ${i.offset}!
|
|
4692
4692
|
`+CO(t,i.offset,i.len))}return n.value}function CO(e,t,r=1){return`${e.replace(/(\t)|(\r)|(\n)/g,(n,i,s)=>i?"\u2409":s?"\u240D":"\u240A")}
|
|
@@ -4796,7 +4796,7 @@ If you cannot find an activation code, explain what you found instead.`,o=[{role
|
|
|
4796
4796
|
`:this._stackItem.inlineTextBuilder.startNewLine())}addWordBreakOpportunity(){(this._stackItem instanceof xs||this._stackItem instanceof Ya||this._stackItem instanceof Xa)&&(this._stackItem.inlineTextBuilder.wordBreakOpportunity=!0)}addInline(e,{noWordTransform:t=!1}={}){if(this._stackItem instanceof xs||this._stackItem instanceof Ya||this._stackItem instanceof Xa){if(this._stackItem.isPre){this._stackItem.rawText+=e;return}if(!(e.length===0||this._stackItem.stashedLineBreaks&&!this.whitespaceProcessor.testContainsWords(e))){if(this.options.preserveNewlines){let r=this.whitespaceProcessor.countNewlinesNoWords(e);if(r>0){this._stackItem.inlineTextBuilder.startNewLine(r);return}}this._stackItem.stashedLineBreaks&&this._stackItem.inlineTextBuilder.startNewLine(this._stackItem.stashedLineBreaks),this.whitespaceProcessor.shrinkWrapAdd(e,this._stackItem.inlineTextBuilder,t?void 0:this._getCombinedWordTransformer(),this._stackItem.isNoWrap),this._stackItem.stashedLineBreaks=0}}}addLiteral(e){if((this._stackItem instanceof xs||this._stackItem instanceof Ya||this._stackItem instanceof Xa)&&e.length!==0){if(this._stackItem.isPre){this._stackItem.rawText+=e;return}this._stackItem.stashedLineBreaks&&this._stackItem.inlineTextBuilder.startNewLine(this._stackItem.stashedLineBreaks),this.whitespaceProcessor.addLiteral(e,this._stackItem.inlineTextBuilder,this._stackItem.isNoWrap),this._stackItem.stashedLineBreaks=0}}openBlock({leadingLineBreaks:e=1,reservedLineLength:t=0,isPre:r=!1}={}){let n=Math.max(20,this._stackItem.inlineTextBuilder.maxLineLength-t);this._stackItem=new xs(this.options,this._stackItem,e,n),r&&(this._stackItem.isPre=!0)}closeBlock({trailingLineBreaks:e=1,blockTransform:t=void 0}={}){let r=this._popStackItem(),n=t?t(za(r)):za(r);Rf(this._stackItem,n,r.leadingLineBreaks,Math.max(r.stashedLineBreaks,e))}openList({maxPrefixLength:e=0,prefixAlign:t="left",interRowLineBreaks:r=1,leadingLineBreaks:n=2}={}){this._stackItem=new VO(this.options,this._stackItem,{interRowLineBreaks:r,leadingLineBreaks:n,maxLineLength:this._stackItem.inlineTextBuilder.maxLineLength,maxPrefixLength:e,prefixAlign:t})}openListItem({prefix:e=""}={}){if(!(this._stackItem instanceof VO))throw new Error("Can't add a list item to something that is not a list! Check the formatter.");let t=this._stackItem,r=Math.max(e.length,t.maxPrefixLength),n=Math.max(20,t.inlineTextBuilder.maxLineLength-r);this._stackItem=new Ya(this.options,t,{prefix:e,maxLineLength:n,leadingLineBreaks:t.interRowLineBreaks})}closeListItem(){let e=this._popStackItem(),t=e.next,r=Math.max(e.prefix.length,t.maxPrefixLength),n=`
|
|
4797
4797
|
`+" ".repeat(r),i=(t.prefixAlign==="right"?e.prefix.padStart(r):e.prefix.padEnd(r))+za(e).replace(/\n/g,n);Rf(t,i,e.leadingLineBreaks,Math.max(e.stashedLineBreaks,t.interRowLineBreaks))}closeList({trailingLineBreaks:e=2}={}){let t=this._popStackItem(),r=za(t);r&&Rf(this._stackItem,r,t.leadingLineBreaks,e)}openTable(){this._stackItem=new zO(this._stackItem)}openTableRow(){if(!(this._stackItem instanceof zO))throw new Error("Can't add a table row to something that is not a table! Check the formatter.");this._stackItem=new KO(this._stackItem)}openTableCell({maxColumnWidth:e=void 0}={}){if(!(this._stackItem instanceof KO))throw new Error("Can't add a table cell to something that is not a table row! Check the formatter.");this._stackItem=new Xa(this.options,this._stackItem,e)}closeTableCell({colspan:e=1,rowspan:t=1}={}){let r=this._popStackItem(),n=FN(za(r),`
|
|
4798
4798
|
`);r.next.cells.push({colspan:e,rowspan:t,text:n})}closeTableRow(){let e=this._popStackItem();e.next.rows.push(e.cells)}closeTable({tableToString:e,leadingLineBreaks:t=2,trailingLineBreaks:r=2}){let n=this._popStackItem(),i=e(n.rows);i&&Rf(this._stackItem,i,t,r)}toString(){return za(this._stackItem.getRoot())}};VZ=Object.freeze({__proto__:null,block:jZ,blockHtml:GZ,blockString:BZ,blockTag:HZ,inline:$Z,inlineHtml:qZ,inlineString:FZ,inlineSurround:WZ,inlineTag:UZ,skip:MZ});hQ=Object.freeze({__proto__:null,anchor:sQ,blockquote:nQ,dataTable:WN,heading:rQ,horizontalLine:QZ,image:iQ,lineBreak:XZ,orderedList:aQ,paragraph:eQ,pre:tQ,table:dQ,unorderedList:oQ,wbr:ZZ}),fQ={baseElements:{selectors:["body"],orderBy:"selectors",returnDomByDefault:!0},decodeEntities:!0,encodeCharacters:{},formatters:{},limits:{ellipsis:"...",maxBaseElements:void 0,maxChildNodes:void 0,maxDepth:void 0,maxInputLength:1<<24},longWordSplit:{forceWrapOnLimit:!1,wrapCharacters:[]},preserveNewlines:!1,selectors:[{selector:"*",format:"inline"},{selector:"a",format:"anchor",options:{baseUrl:null,hideLinkHrefIfSameAsText:!1,ignoreHref:!1,linkBrackets:["[","]"],noAnchorUrl:!0}},{selector:"article",format:"block",options:{leadingLineBreaks:1,trailingLineBreaks:1}},{selector:"aside",format:"block",options:{leadingLineBreaks:1,trailingLineBreaks:1}},{selector:"blockquote",format:"blockquote",options:{leadingLineBreaks:2,trailingLineBreaks:2,trimEmptyLines:!0}},{selector:"br",format:"lineBreak"},{selector:"div",format:"block",options:{leadingLineBreaks:1,trailingLineBreaks:1}},{selector:"footer",format:"block",options:{leadingLineBreaks:1,trailingLineBreaks:1}},{selector:"form",format:"block",options:{leadingLineBreaks:1,trailingLineBreaks:1}},{selector:"h1",format:"heading",options:{leadingLineBreaks:3,trailingLineBreaks:2,uppercase:!0}},{selector:"h2",format:"heading",options:{leadingLineBreaks:3,trailingLineBreaks:2,uppercase:!0}},{selector:"h3",format:"heading",options:{leadingLineBreaks:3,trailingLineBreaks:2,uppercase:!0}},{selector:"h4",format:"heading",options:{leadingLineBreaks:2,trailingLineBreaks:2,uppercase:!0}},{selector:"h5",format:"heading",options:{leadingLineBreaks:2,trailingLineBreaks:2,uppercase:!0}},{selector:"h6",format:"heading",options:{leadingLineBreaks:2,trailingLineBreaks:2,uppercase:!0}},{selector:"header",format:"block",options:{leadingLineBreaks:1,trailingLineBreaks:1}},{selector:"hr",format:"horizontalLine",options:{leadingLineBreaks:2,length:void 0,trailingLineBreaks:2}},{selector:"img",format:"image",options:{baseUrl:null,linkBrackets:["[","]"]}},{selector:"main",format:"block",options:{leadingLineBreaks:1,trailingLineBreaks:1}},{selector:"nav",format:"block",options:{leadingLineBreaks:1,trailingLineBreaks:1}},{selector:"ol",format:"orderedList",options:{leadingLineBreaks:2,trailingLineBreaks:2}},{selector:"p",format:"paragraph",options:{leadingLineBreaks:2,trailingLineBreaks:2}},{selector:"pre",format:"pre",options:{leadingLineBreaks:2,trailingLineBreaks:2}},{selector:"section",format:"block",options:{leadingLineBreaks:1,trailingLineBreaks:1}},{selector:"table",format:"table",options:{colSpacing:3,leadingLineBreaks:2,maxColumnWidth:60,rowSpacing:0,trailingLineBreaks:2,uppercaseHeaderCells:!0}},{selector:"ul",format:"unorderedList",options:{itemPrefix:" * ",leadingLineBreaks:2,trailingLineBreaks:2}},{selector:"wbr",format:"wbr"}],tables:[],whitespaceCharacters:` \r
|
|
4799
|
-
\f\u200B`,wordwrap:80},mQ=(e,t,r)=>[...e,...t],VN=(e,t,r)=>[...t],gQ=(e,t,r)=>e.some(n=>typeof n=="object")?mQ(e,t):VN(e,t);SQ=class{getMailgunConfig(){let e=xn().env||{};if(e.MAILGUN_API_KEY)return{apiKey:e.MAILGUN_API_KEY,domain:e.MAILGUN_DOMAIN||""}}async execute(e,t,r){let n=t.action_data;if(!n)throw new Error("Action data not found");let i=this.getMailgunConfig();if(!i)throw new Error("Mailgun configuration not provided. Please configure MAILGUN_API_KEY and MAILGUN_DOMAIN in SDK config.");let s=n.kwargs,o=r.getModel?.()||"gemini-2.5-pro",a=await EQ(i,{model:o,forward_email:s.forward_email,extraction_type:s.extraction_type,prompt:s.prompt,filters:{from_email:s.filter_from_email,to_email:s.filter_to_email,subject:s.filter_subject,body_contains:s.filter_body_contains},timeout:s.timeout});if(a.status==="success"&&a.data){let l=a.result_variable?.replace(/^\$/,"")||zN(s.extraction_type);r.variableStore.set(l,a.data),te.info(`[extract_email_content] Extracted and saved to ${l}`)}else throw new Error(a.message||"Failed to extract email content")}transpile(e){let t=e.action_data?.kwargs||{};return['await agent.execAction("extract_email_content", page, {',` action_data: { kwargs: ${JSON.stringify(t)} },`,"});"]}},AQ=io.object({forward_email:io.string().describe("Email address where emails are forwarded to (Mailgun inbox)"),extraction_type:io.enum(["verification_code","activation_link","custom"]).describe("Type of content to extract: verification_code for OTP codes, activation_link for magic links, custom for custom prompts"),prompt:io.string().optional().describe("Custom extraction prompt (required when extraction_type is custom)"),filter_from_email:io.string().optional().describe("Filter emails by sender address"),filter_to_email:io.string().optional().describe("Filter emails by recipient address"),filter_subject:io.string().optional().describe("Filter emails by subject (partial match)"),filter_body_contains:io.string().optional().describe("Filter emails by body content (partial match)"),timeout:io.number().optional().describe("Timeout in seconds for polling (default: 60)")});Lf=null;IQ=[Uw(Er),Hw(Er),qw(Er),Gw(Er),Ww(Er),Vw(Er),zw(Er),Kw(Er),Yw(Er),Jw(Er)],PQ=Promise.all(IQ);RQ=class{constructor(e,t){this.registry=e,this.getContext=t}getToolDefinitions(){return this.registry.getTools().filter(e=>e.availability.mcp).map(e=>({name:e.name,description:e.description,inputSchema:hf(e.schema)}))}getToolDefinitionsFiltered(e){let t=new Set(e);return this.registry.getTools().filter(r=>t.has(r.name)&&r.availability.mcp).map(r=>({name:r.name,description:r.description,inputSchema:hf(r.schema)}))}async createServer(e="web-sdk-tools"){throw new Error("MCP server creation not yet implemented. Install and configure an MCP SDK like @modelcontextprotocol/sdk")}async executeTool(e,t){let r=await this.getContext(),n=await this.registry.execute(e,t,r);return{content:[{type:"text",text:n.success?n.message||"Tool executed successfully":n.error||"Tool execution failed"}]}}getToolCount(){return this.registry.size()}getToolNames(){return this.registry.getToolNames()}};Qw=class{constructor(e={}){e.testDir&&(this.testDir=e.testDir,this.videoBasePath=Sd.join(e.testDir,"videos"),this.statesBasePath=Sd.join(e.testDir,"states"),this.downloadsBasePath=Sd.join(e.testDir,"downloads"),Ka.mkdirSync(this.videoBasePath,{recursive:!0}),Ka.mkdirSync(this.statesBasePath,{recursive:!0}),Ka.mkdirSync(this.downloadsBasePath,{recursive:!0})),this.terminationTimeout=e.terminationTimeout??null,this.defaultHeadless=e.headless??!1,this.additionalArgs=e.additionalArgs??[]}async launchBrowser(e={}){let t=e.debugPort,r=e.headless??this.defaultHeadless,n=ax(e.deviceName),i=ox(e.deviceName),s=n===kl.Chromium,o=!!e.extensionPath;te.info(`[BrowserManager] Launching ${n} browser for device: ${e.deviceName||"default"}${t?` on port ${t}`:""}`);let a={headless:r};if(s){o&&r&&(te.warn("[BrowserManager] Extension requested in headless mode; forcing headed mode to load extension."),r=!1,a.headless=!1);let k=[];(e.enableCamera||e.enableMicrophone)&&(k.push("--use-fake-device-for-media-stream","--use-fake-ui-for-media-stream"),e.enableMicrophone&&e.fakeAudioCapturePath&&(k.push(`--use-file-for-fake-audio-capture=${e.fakeAudioCapturePath}`),te.info(`[BrowserManager] Using fake audio capture file: ${e.fakeAudioCapturePath}`)));let T=o&&e.extensionPath?[`--disable-extensions-except=${e.extensionPath}`,`--load-extension=${e.extensionPath}`]:[];a.args=[...xv(t,e.disableSecurity??!0,r),...k,...T,...this.additionalArgs],i&&(a.channel=i,te.debug(`[BrowserManager] Launching browser with channel: ${i}`))}let l=$p(e.deviceName),u=sx(e.deviceName),d={acceptDownloads:!0,...l,timezoneId:e.timezoneId||"America/Los_Angeles",locale:e.locale||"en-US"};e.viewport&&(d.viewport=e.viewport,d.screen=e.viewport),e.isMobile!==void 0&&(d.isMobile=e.isMobile),e.hasTouch!==void 0&&(d.hasTouch=e.hasTouch),e.userAgent&&(d.userAgent=e.userAgent),e.colorScheme&&(d.colorScheme=e.colorScheme),e.geolocation&&(d.geolocation=e.geolocation,d.permissions=[...d.permissions||[],"geolocation"]);let p=o&&s?e.localStorageStatePath:void 0;e.localStorageStatePath&&!p&&(d.storageState=e.localStorageStatePath),e.recordVideo&&this.videoBasePath&&(d.recordVideo={dir:this.videoBasePath,size:{width:u.width,height:u.height}}),e.proxy&&(d.proxy=e.proxy),e.extraHTTPHeaders&&Object.keys(e.extraHTTPHeaders).length>0&&(d.extraHTTPHeaders=e.extraHTTPHeaders);let h,m,y,b=!1;if(s&&(o||e.userDataDir)){if(e.userDataDir)y=e.userDataDir;else{let T=this.testDir||Ka.mkdtempSync(Sd.join(MQ.tmpdir(),"shiplight-"));y=Sd.join(T,`ext-profile-${Date.now()}`),Ka.mkdirSync(y,{recursive:!0}),b=!0}let k={...a,...d};m=await YO.launchPersistentContext(y,k),p&&(await $Q(m,p),te.info(`[BrowserManager] Loaded storage state into persistent context from ${p}`)),h=m.browser(),te.info(`[BrowserManager] Launched persistent context${e.extensionPath?` for extension at ${e.extensionPath}`:` with profile at ${y}`}`)}else{switch(n){case kl.Firefox:h=await FQ.launch(a);break;case kl.Webkit:h=await BQ.launch(a);break;case kl.Chromium:default:h=await YO.launch(a);break}m=await h.newContext(d)}if(m.addInitScript(Tp),s){let k=["clipboard-read","clipboard-write"];e.enableCamera&&k.push("camera"),e.enableMicrophone&&k.push("microphone");try{await m.grantPermissions(k),te.info(`[BrowserManager] Granted permissions: ${k.join(", ")}`)}catch(T){te.warn("[BrowserManager] Failed to grant permissions:",T)}}else(e.enableCamera||e.enableMicrophone)&&te.warn("[BrowserManager] Camera/microphone enabled but browser is not Chromium; ignoring.");if(e.cookies&&e.cookies.length>0){let k=(Date.now()+31536e6)/1e3,T=e.cookies.map(D=>({...D,expires:k}));await m.addCookies(T),te.info(`[BrowserManager] Added ${e.cookies.length} cookies to browser context with expires=${k}`)}let w=e.viewport,E=w?{width:w.width,height:w.height+Bp}:ix(e.deviceName);if(te.info(`[BrowserManager] windowSize=${JSON.stringify(E)}`),s){let k=async T=>{try{await Dg(T,E.width,E.height),w&&await T.setViewportSize(w)}catch(D){te.warn("[BrowserManager] Failed to set window bounds via CDP:",D)}};for(let T of m.pages())await k(T);m.on("page",k)}let x="";if(s&&t!==void 0)try{x=await Ng(t)}catch(k){te.warn("[BrowserManager] Failed to get CDP WebSocket URL:",k)}let C=null;x&&(C=await JN({cdpUrl:x,label:`agent ${e.deviceName??n}`,pid:process.pid}),C&&te.info(`[BrowserManager] Registered browser with dev-box registry id=${C}`));let R={debugPort:t,browser:h,context:m,startTime:new Date,timeout:null,browserWsUrl:x,downloadsBasePath:this.downloadsBasePath,browserType:n,userDataDir:y,isTempUserDataDir:b,registryId:C};if(this.terminationTimeout!==null){let k=setTimeout(()=>{te.info(`[BrowserManager] Browser auto-terminated after ${this.terminationTimeout}ms`),this.terminateBrowser(R).catch(T=>te.error("[BrowserManager] Error terminating browser:",T))},this.terminationTimeout);R.timeout=k}return R}async terminateBrowser(e){if(e.timeout&&clearTimeout(e.timeout),await YN(e.registryId??null),await e.context.close(),await e.browser.close(),e.isTempUserDataDir&&e.userDataDir)try{Ka.rmSync(e.userDataDir,{recursive:!0,force:!0})}catch(t){te.warn("[BrowserManager] Failed to clean up temp user data dir:",e.userDataDir,t)}}getVideoBasePath(){return this.videoBasePath}getStatesBasePath(){return this.statesBasePath}getDownloadsBasePath(){return this.downloadsBasePath}};QN=e=>{if(!e||e===Sa)return"desktop";let t=fu(e);return t&&t.isMobile?"mobile":"desktop"},GQ=(e=>(e.Desktop="desktop",e.Mobile="mobile",e))(GQ||{}),WQ=class{constructor(e){this.currentPage=null,this.currentIndex=-1,this.context=e,this.initialize()}initialize(){this.context.on("page",async t=>{await this.handleNewPage(t)});let e=this.context.pages();e.length>0&&(this.currentPage=e[0],this.currentIndex=0);for(let t of e)this.setupPageListeners(t)}async handleNewPage(e){try{this.setupPageListeners(e);let t=this.context.pages().indexOf(e);await this.setCurrentPage(e,t)}catch{}}setupPageListeners(e){e.on("close",async()=>{await this.handlePageClose(e)})}async handlePageClose(e){try{if(this.currentPage===e){let t=this.context.pages(),r=t.slice().reverse().find(n=>!n.isClosed());r&&await this.setCurrentPage(r,t.indexOf(r))}}catch{}}async setCurrentPage(e,t){let r=this.currentPage!==e;this.currentPage=e,this.currentIndex=t,r&&await e.bringToFront()}async switchToPage(e){let t=this.context.pages();if(e<0||e>=t.length)throw new Error(`Invalid page index: ${e}. Available pages: 0-${t.length-1}`);let r=t[e];if(r.isClosed())throw new Error(`Page at index ${e} is closed`);return await this.setCurrentPage(r,e),r}async closePage(e){let t=this.context.pages();if(e<0||e>=t.length)throw new Error(`Invalid page index: ${e}. Available pages: 0-${t.length-1}`);let r=t[e];if(r.isClosed())throw new Error(`Page at index ${e} is already closed`);await r.close()}getCurrentPage(){return this.currentPage}getCurrentIndex(){return this.currentIndex}getAllPages(){return this.context.pages()}getPageCount(){return this.context.pages().length}};el=class extends Error{constructor(e,t){super(e,t),this.name="OTPError"}},tD=class extends el{constructor(e){super(e),this.name="SecretError"}},JQ=class extends tD{constructor(e,t){super(`Secret must be at least ${e} bytes (${e*8} bits), got ${t} bytes`),this.name="SecretTooShortError"}},YQ=class extends tD{constructor(e,t){super(`Secret must not exceed ${e} bytes, got ${t} bytes`),this.name="SecretTooLongError"}},e_=class extends el{constructor(e){super(e),this.name="CounterError"}},XQ=class extends e_{constructor(){super("Counter must be non-negative"),this.name="CounterNegativeError"}},XO=class extends e_{constructor(){super("Counter exceeds maximum safe integer value"),this.name="CounterOverflowError"}},ZQ=class extends e_{constructor(){super("Counter must be a finite integer"),this.name="CounterNotIntegerError"}},rD=class extends el{constructor(e){super(e),this.name="TimeError"}},QQ=class extends rD{constructor(){super("Time must be non-negative"),this.name="TimeNegativeError"}},eee=class extends rD{constructor(){super("Time must be a finite number"),this.name="TimeNotFiniteError"}},nD=class extends el{constructor(e){super(e),this.name="PeriodError"}},tee=class extends nD{constructor(e){super(`Period must be at least ${e} second(s)`),this.name="PeriodTooSmallError"}},ree=class extends nD{constructor(e){super(`Period must not exceed ${e} seconds`),this.name="PeriodTooLargeError"}},iD=class extends el{constructor(e,t){super(e,t),this.name="CryptoError"}},Mf=class extends iD{constructor(e,t){super(`HMAC computation failed: ${e}`,t),this.name="HMACError"}},nee=class extends iD{constructor(e,t){super(`Random byte generation failed: ${e}`,t),this.name="RandomBytesError"}},sD=class extends el{constructor(e){super(e),this.name="PluginError"}},iee=class extends sD{constructor(){super("Crypto plugin is required."),this.name="CryptoPluginMissingError"}},see=class extends sD{constructor(){super("Base32 plugin is required."),this.name="Base32PluginMissingError"}},Za=class extends el{constructor(e){super(e),this.name="ConfigurationError"}},oee=class extends Za{constructor(){super("Secret is required. Use generateSecret() to create one, or provide via { secret: 'YOUR_BASE32_SECRET' }"),this.name="SecretMissingError"}},aee=new TextEncoder,cge=new TextDecoder,lee=16,cee=64,uee=1,dee=3600,pee=Number.MAX_SAFE_INTEGER,hee=99,oD=Symbol("otplib.guardrails.override");kd=Object.freeze({MIN_SECRET_BYTES:lee,MAX_SECRET_BYTES:cee,MIN_PERIOD:uee,MAX_PERIOD:dee,MAX_COUNTER:pee,MAX_WINDOW:hee,[oD]:!1});Eee=class{constructor(e){this.crypto=e}get plugin(){return this.crypto}async hmac(e,t,r){try{let n=this.crypto.hmac(e,t,r);return n instanceof Promise?await n:n}catch(n){let i=n instanceof Error?n.message:String(n);throw new Mf(i,{cause:n})}}hmacSync(e,t,r){try{let n=this.crypto.hmac(e,t,r);if(n instanceof Promise)throw new Mf("Crypto plugin does not support synchronous HMAC operations");return n}catch(n){if(n instanceof Mf)throw n;let i=n instanceof Error?n.message:String(n);throw new Mf(i,{cause:n})}}randomBytes(e){try{return this.crypto.randomBytes(e)}catch(t){let r=t instanceof Error?t.message:String(t);throw new nee(r,{cause:t})}}};hD=(e,t)=>t===0?e:hD(t,e%t),Kf=(e,t)=>e+(t-hD(e,t)),mw=(()=>{let e=[];for(let t=0;t<40;t++)e.push(2**t);return e})();eN=Pee(Ree(5),Oee("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"),Dee(5),Nee("")),Lee=class{constructor(){ge(this,"name","scure")}encode(e,t={}){let{padding:r=!1}=t,n=eN.encode(e);return r?n:n.replace(/=+$/,"")}decode(e){try{let t=e.toUpperCase(),r=t.padEnd(Math.ceil(t.length/8)*8,"=");return eN.decode(r)}catch(t){throw t instanceof Error?new Error(`Invalid Base32 string: ${t.message}`):new Error("Invalid Base32 string")}}},Mee=Object.freeze(new Lee);fD=e=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,e])}),mD=class{constructor(e,t){if(ge(this,"oHash"),ge(this,"iHash"),ge(this,"blockLen"),ge(this,"outputLen"),ge(this,"finished",!1),ge(this,"destroyed",!1),Bee(e),Jf(t,void 0,"key"),this.iHash=e.create(),typeof this.iHash.update!="function")throw new Error("Expected instance of class which extends utils.Hash");this.blockLen=this.iHash.blockLen,this.outputLen=this.iHash.outputLen;let r=this.blockLen,n=new Uint8Array(r);n.set(t.length>r?e.create().update(t).digest():t);for(let i=0;i<n.length;i++)n[i]^=54;this.iHash.update(n),this.oHash=e.create();for(let i=0;i<n.length;i++)n[i]^=106;this.oHash.update(n),Zo(n)}update(e){return Yf(this),this.iHash.update(e),this}digestInto(e){Yf(this),Jf(e,this.outputLen,"output"),this.finished=!0,this.iHash.digestInto(e),this.oHash.update(e),this.oHash.digestInto(e),this.destroy()}digest(){let e=new Uint8Array(this.oHash.outputLen);return this.digestInto(e),e}_cloneInto(e){e||(e=Object.create(Object.getPrototypeOf(this),{}));let{oHash:t,iHash:r,finished:n,destroyed:i,blockLen:s,outputLen:o}=this;return e=e,e.finished=n,e.destroyed=i,e.blockLen=s,e.outputLen=o,e.oHash=t._cloneInto(e.oHash),e.iHash=r._cloneInto(e.iHash),e}clone(){return this._cloneInto()}destroy(){this.destroyed=!0,this.oHash.destroy(),this.iHash.destroy()}},gD=(e,t,r)=>new mD(e,t).update(r).digest();gD.create=(e,t)=>new mD(e,t);i_=class{constructor(e,t,r,n){ge(this,"blockLen"),ge(this,"outputLen"),ge(this,"padOffset"),ge(this,"isLE"),ge(this,"buffer"),ge(this,"view"),ge(this,"finished",!1),ge(this,"length",0),ge(this,"pos",0),ge(this,"destroyed",!1),this.blockLen=e,this.outputLen=t,this.padOffset=r,this.isLE=n,this.buffer=new Uint8Array(e),this.view=gw(this.buffer)}update(e){Yf(this),Jf(e);let{view:t,buffer:r,blockLen:n}=this,i=e.length;for(let s=0;s<i;){let o=Math.min(n-this.pos,i-s);if(o===n){let a=gw(e);for(;n<=i-s;s+=n)this.process(a,s);continue}r.set(e.subarray(s,s+o),this.pos),this.pos+=o,s+=o,this.pos===n&&(this.process(t,0),this.pos=0)}return this.length+=e.length,this.roundClean(),this}digestInto(e){Yf(this),$ee(e,this),this.finished=!0;let{buffer:t,view:r,blockLen:n,isLE:i}=this,{pos:s}=this;t[s++]=128,Zo(this.buffer.subarray(s)),this.padOffset>n-s&&(this.process(r,0),s=0);for(let d=s;d<n;d++)t[d]=0;r.setBigUint64(n-8,BigInt(this.length*8),i),this.process(r,0);let o=gw(e),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen must be aligned to 32bit");let l=a/4,u=this.get();if(l>u.length)throw new Error("_sha2: outputLen bigger than state");for(let d=0;d<l;d++)o.setUint32(4*d,u[d],i)}digest(){let{buffer:e,outputLen:t}=this;this.digestInto(e);let r=e.slice(0,t);return this.destroy(),r}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());let{blockLen:t,buffer:r,length:n,finished:i,destroyed:s,pos:o}=this;return e.destroyed=s,e.finished=i,e.length=n,e.pos=o,n%t&&e.buffer.set(r),e}clone(){return this._cloneInto()}},zo=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),Cn=Uint32Array.from([1779033703,4089235720,3144134277,2227873595,1013904242,4271175723,2773480762,1595750129,1359893119,2917565137,2600822924,725511199,528734635,4215389547,1541459225,327033209]),Ad=Uint32Array.from([1732584193,4023233417,2562383102,271733878,3285377520]),Ko=new Uint32Array(80),Uee=class extends i_{constructor(){super(64,20,8,!1),ge(this,"A",Ad[0]|0),ge(this,"B",Ad[1]|0),ge(this,"C",Ad[2]|0),ge(this,"D",Ad[3]|0),ge(this,"E",Ad[4]|0)}get(){let{A:e,B:t,C:r,D:n,E:i}=this;return[e,t,r,n,i]}set(e,t,r,n,i){this.A=e|0,this.B=t|0,this.C=r|0,this.D=n|0,this.E=i|0}process(e,t){for(let a=0;a<16;a++,t+=4)Ko[a]=e.getUint32(t,!1);for(let a=16;a<80;a++)Ko[a]=yw(Ko[a-3]^Ko[a-8]^Ko[a-14]^Ko[a-16],1);let{A:r,B:n,C:i,D:s,E:o}=this;for(let a=0;a<80;a++){let l,u;a<20?(l=yD(n,i,s),u=1518500249):a<40?(l=n^i^s,u=1859775393):a<60?(l=bD(n,i,s),u=2400959708):(l=n^i^s,u=3395469782);let d=yw(r,5)+l+o+u+Ko[a]|0;o=s,s=i,i=yw(n,30),n=r,r=d}r=r+this.A|0,n=n+this.B|0,i=i+this.C|0,s=s+this.D|0,o=o+this.E|0,this.set(r,n,i,s,o)}roundClean(){Zo(Ko)}destroy(){this.set(0,0,0,0,0),Zo(this.buffer)}},Hee=n_(()=>new Uee),Ff=BigInt(4294967295),rN=BigInt(32);nN=(e,t,r)=>e>>>r,iN=(e,t,r)=>e<<32-r|t>>>r,wc=(e,t,r)=>e>>>r|t<<32-r,_c=(e,t,r)=>e<<32-r|t>>>r,Bf=(e,t,r)=>e<<64-r|t>>>r-32,$f=(e,t,r)=>e>>>r-32|t<<64-r;Wee=(e,t,r)=>(e>>>0)+(t>>>0)+(r>>>0),Vee=(e,t,r,n)=>t+r+n+(e/2**32|0)|0,zee=(e,t,r,n)=>(e>>>0)+(t>>>0)+(r>>>0)+(n>>>0),Kee=(e,t,r,n,i)=>t+r+n+i+(e/2**32|0)|0,Jee=(e,t,r,n,i)=>(e>>>0)+(t>>>0)+(r>>>0)+(n>>>0)+(i>>>0),Yee=(e,t,r,n,i,s)=>t+r+n+i+s+(e/2**32|0)|0,Xee=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),Jo=new Uint32Array(64),Zee=class extends i_{constructor(e){super(64,e,8,!1)}get(){let{A:e,B:t,C:r,D:n,E:i,F:s,G:o,H:a}=this;return[e,t,r,n,i,s,o,a]}set(e,t,r,n,i,s,o,a){this.A=e|0,this.B=t|0,this.C=r|0,this.D=n|0,this.E=i|0,this.F=s|0,this.G=o|0,this.H=a|0}process(e,t){for(let d=0;d<16;d++,t+=4)Jo[d]=e.getUint32(t,!1);for(let d=16;d<64;d++){let p=Jo[d-15],h=Jo[d-2],m=vs(p,7)^vs(p,18)^p>>>3,y=vs(h,17)^vs(h,19)^h>>>10;Jo[d]=y+Jo[d-7]+m+Jo[d-16]|0}let{A:r,B:n,C:i,D:s,E:o,F:a,G:l,H:u}=this;for(let d=0;d<64;d++){let p=vs(o,6)^vs(o,11)^vs(o,25),h=u+p+yD(o,a,l)+Xee[d]+Jo[d]|0,m=(vs(r,2)^vs(r,13)^vs(r,22))+bD(r,n,i)|0;u=l,l=a,a=o,o=s+h|0,s=i,i=n,n=r,r=h+m|0}r=r+this.A|0,n=n+this.B|0,i=i+this.C|0,s=s+this.D|0,o=o+this.E|0,a=a+this.F|0,l=l+this.G|0,u=u+this.H|0,this.set(r,n,i,s,o,a,l,u)}roundClean(){Zo(Jo)}destroy(){this.set(0,0,0,0,0,0,0,0),Zo(this.buffer)}},Qee=class extends Zee{constructor(){super(32),ge(this,"A",zo[0]|0),ge(this,"B",zo[1]|0),ge(this,"C",zo[2]|0),ge(this,"D",zo[3]|0),ge(this,"E",zo[4]|0),ge(this,"F",zo[5]|0),ge(this,"G",zo[6]|0),ge(this,"H",zo[7]|0)}},wD=Gee(["0x428a2f98d728ae22","0x7137449123ef65cd","0xb5c0fbcfec4d3b2f","0xe9b5dba58189dbbc","0x3956c25bf348b538","0x59f111f1b605d019","0x923f82a4af194f9b","0xab1c5ed5da6d8118","0xd807aa98a3030242","0x12835b0145706fbe","0x243185be4ee4b28c","0x550c7dc3d5ffb4e2","0x72be5d74f27b896f","0x80deb1fe3b1696b1","0x9bdc06a725c71235","0xc19bf174cf692694","0xe49b69c19ef14ad2","0xefbe4786384f25e3","0x0fc19dc68b8cd5b5","0x240ca1cc77ac9c65","0x2de92c6f592b0275","0x4a7484aa6ea6e483","0x5cb0a9dcbd41fbd4","0x76f988da831153b5","0x983e5152ee66dfab","0xa831c66d2db43210","0xb00327c898fb213f","0xbf597fc7beef0ee4","0xc6e00bf33da88fc2","0xd5a79147930aa725","0x06ca6351e003826f","0x142929670a0e6e70","0x27b70a8546d22ffc","0x2e1b21385c26c926","0x4d2c6dfc5ac42aed","0x53380d139d95b3df","0x650a73548baf63de","0x766a0abb3c77b2a8","0x81c2c92e47edaee6","0x92722c851482353b","0xa2bfe8a14cf10364","0xa81a664bbc423001","0xc24b8b70d0f89791","0xc76c51a30654be30","0xd192e819d6ef5218","0xd69906245565a910","0xf40e35855771202a","0x106aa07032bbd1b8","0x19a4c116b8d2d0c8","0x1e376c085141ab53","0x2748774cdf8eeb99","0x34b0bcb5e19b48a8","0x391c0cb3c5c95a63","0x4ed8aa4ae3418acb","0x5b9cca4f7763e373","0x682e6ff3d6b2b8a3","0x748f82ee5defb2fc","0x78a5636f43172f60","0x84c87814a1f0ab72","0x8cc702081a6439ec","0x90befffa23631e28","0xa4506cebde82bde9","0xbef9a3f7b2c67915","0xc67178f2e372532b","0xca273eceea26619c","0xd186b8c721c0c207","0xeada7dd6cde0eb1e","0xf57d4f7fee6ed178","0x06f067aa72176fba","0x0a637dc5a2c898a6","0x113f9804bef90dae","0x1b710b35131c471b","0x28db77f523047d84","0x32caab7b40c72493","0x3c9ebe0a15c9bebc","0x431d67c49c100d4c","0x4cc5d4becb3e42b6","0x597f299cfc657e2a","0x5fcb6fab3ad6faec","0x6c44198c4a475817"].map(e=>BigInt(e))),ete=wD[0],tte=wD[1],Yo=new Uint32Array(80),Xo=new Uint32Array(80),rte=class extends i_{constructor(e){super(128,e,16,!1)}get(){let{Ah:e,Al:t,Bh:r,Bl:n,Ch:i,Cl:s,Dh:o,Dl:a,Eh:l,El:u,Fh:d,Fl:p,Gh:h,Gl:m,Hh:y,Hl:b}=this;return[e,t,r,n,i,s,o,a,l,u,d,p,h,m,y,b]}set(e,t,r,n,i,s,o,a,l,u,d,p,h,m,y,b){this.Ah=e|0,this.Al=t|0,this.Bh=r|0,this.Bl=n|0,this.Ch=i|0,this.Cl=s|0,this.Dh=o|0,this.Dl=a|0,this.Eh=l|0,this.El=u|0,this.Fh=d|0,this.Fl=p|0,this.Gh=h|0,this.Gl=m|0,this.Hh=y|0,this.Hl=b|0}process(e,t){for(let x=0;x<16;x++,t+=4)Yo[x]=e.getUint32(t),Xo[x]=e.getUint32(t+=4);for(let x=16;x<80;x++){let C=Yo[x-15]|0,R=Xo[x-15]|0,k=wc(C,R,1)^wc(C,R,8)^nN(C,R,7),T=_c(C,R,1)^_c(C,R,8)^iN(C,R,7),D=Yo[x-2]|0,O=Xo[x-2]|0,I=wc(D,O,19)^Bf(D,O,61)^nN(D,O,6),L=_c(D,O,19)^$f(D,O,61)^iN(D,O,6),F=zee(T,L,Xo[x-7],Xo[x-16]),U=Kee(F,k,I,Yo[x-7],Yo[x-16]);Yo[x]=U|0,Xo[x]=F|0}let{Ah:r,Al:n,Bh:i,Bl:s,Ch:o,Cl:a,Dh:l,Dl:u,Eh:d,El:p,Fh:h,Fl:m,Gh:y,Gl:b,Hh:w,Hl:E}=this;for(let x=0;x<80;x++){let C=wc(d,p,14)^wc(d,p,18)^Bf(d,p,41),R=_c(d,p,14)^_c(d,p,18)^$f(d,p,41),k=d&h^~d&y,T=p&m^~p&b,D=Jee(E,R,T,tte[x],Xo[x]),O=Yee(D,w,C,k,ete[x],Yo[x]),I=D|0,L=wc(r,n,28)^Bf(r,n,34)^Bf(r,n,39),F=_c(r,n,28)^$f(r,n,34)^$f(r,n,39),U=r&i^r&o^i&o,z=n&s^n&a^s&a;w=y|0,E=b|0,y=h|0,b=m|0,h=d|0,m=p|0,{h:d,l:p}=so(l|0,u|0,O|0,I|0),l=o|0,u=a|0,o=i|0,a=s|0,i=r|0,s=n|0;let K=Wee(I,F,z);r=Vee(K,O,L,U),n=K|0}({h:r,l:n}=so(this.Ah|0,this.Al|0,r|0,n|0)),{h:i,l:s}=so(this.Bh|0,this.Bl|0,i|0,s|0),{h:o,l:a}=so(this.Ch|0,this.Cl|0,o|0,a|0),{h:l,l:u}=so(this.Dh|0,this.Dl|0,l|0,u|0),{h:d,l:p}=so(this.Eh|0,this.El|0,d|0,p|0),{h,l:m}=so(this.Fh|0,this.Fl|0,h|0,m|0),{h:y,l:b}=so(this.Gh|0,this.Gl|0,y|0,b|0),{h:w,l:E}=so(this.Hh|0,this.Hl|0,w|0,E|0),this.set(r,n,i,s,o,a,l,u,d,p,h,m,y,b,w,E)}roundClean(){Zo(Yo,Xo)}destroy(){Zo(this.buffer),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}},nte=class extends rte{constructor(){super(64),ge(this,"Ah",Cn[0]|0),ge(this,"Al",Cn[1]|0),ge(this,"Bh",Cn[2]|0),ge(this,"Bl",Cn[3]|0),ge(this,"Ch",Cn[4]|0),ge(this,"Cl",Cn[5]|0),ge(this,"Dh",Cn[6]|0),ge(this,"Dl",Cn[7]|0),ge(this,"Eh",Cn[8]|0),ge(this,"El",Cn[9]|0),ge(this,"Fh",Cn[10]|0),ge(this,"Fl",Cn[11]|0),ge(this,"Gh",Cn[12]|0),ge(this,"Gl",Cn[13]|0),ge(this,"Hh",Cn[14]|0),ge(this,"Hl",Cn[15]|0)}},ite=n_(()=>new Qee,fD(1)),ste=n_(()=>new nte,fD(3)),ote=class{constructor(){ge(this,"name","noble")}hmac(e,t,r){return gD(e==="sha1"?Hee:e==="sha256"?ite:ste,t,r)}randomBytes(e){return jee(e)}constantTimeEqual(e,t){return vee(e,t)}},ate=Object.freeze(new ote);dte=t_({MIN_SECRET_BYTES:1});_D=class{constructor(e){this.context=e,this.testDataFileNames=[],this.extensionEnabled=!1}setTestDataDownloader(e,t){this.testDataDownloader=e,this.testDataFileNames=t??[]}setupPageTracking(e){this.tabManager=new WQ(e)}async switchTab(e){if(!this.tabManager)throw new Error("Tab manager not initialized");return await this.tabManager.switchToPage(e)}async closeTab(e){if(!this.tabManager)throw new Error("Tab manager not initialized");await this.tabManager.closePage(e)}getCurrentPage(){return this.tabManager?this.tabManager.getCurrentPage():null}validatePage(e){let t=this.getCurrentPage();if(t&&t!==e&&!t.isClosed())return te.info(`[validatePage] Page changed, switching to ${t.url()}`),t;if(e.isClosed()){let r=e.context().pages().filter(n=>!n.isClosed());if(r.length>0){let n=r[r.length-1];return te.info(`[validatePage] Page closed, switching to ${n.url()}`),n}te.error("[validatePage] No valid pages found")}return e}replaceVariables(e){return Wg(e,this.context.variableStore.getAll())}getTestDataFileNames(){return this.testDataFileNames}getTestDataFilePath(e){let t=this.context.testDataDir||process.cwd();return Cd.join(t,e)}async downloadTestDataFiles(e){if(e.length===0){te.debug("[AgentServices] No file paths provided for download");return}let t=this.context.testDataDir||process.cwd(),r=e.filter(n=>{let i=Cd.basename(n),s=Cd.join(t,i),o=eD.existsSync(s);return o&&te.debug(`[AgentServices] File already exists locally: ${i}`),!o});if(r.length===0){te.debug("[AgentServices] All files exist locally, no download needed");return}if(!this.testDataDownloader){te.debug("[AgentServices] No test data downloader configured, assuming files are pre-populated");return}te.info(`[AgentServices] Downloading ${r.length} test data files: ${r.join(", ")}`),await this.testDataDownloader(r,t)}async waitForDownloadComplete(e,t){return zQ(e,this.context,t)}getRecentDownloadedFilePath(){return this.context.downloadStatus?this.context.downloadStatus.status!=="completed"?(te.debug(`Download is ${this.context.downloadStatus.status}, not completed`),null):this.context.downloadStatus.filePath?(te.info(`Retrieved recent download path: ${this.context.downloadStatus.filePath}`),this.context.downloadStatus.filePath):(te.warn("Download completed but file path is missing"),null):(te.debug("No download found"),null)}addSensitive(e,t){this.context.variableStore.set(e,t,!0)}saveVariable(e,t){let r=e.startsWith("$")?e.slice(1):e;this.context.variableStore.set(r,t),te.debug(`Saved variable: ${r} = ${JSON.stringify(t)}`),this.context.agentNote=`A new value is saved to the variable "${r}".`}addNote(e){!e||e.trim()===""||(this.context.agentNote?this.context.agentNote+=`
|
|
4799
|
+
\f\u200B`,wordwrap:80},mQ=(e,t,r)=>[...e,...t],VN=(e,t,r)=>[...t],gQ=(e,t,r)=>e.some(n=>typeof n=="object")?mQ(e,t):VN(e,t);SQ=class{getMailgunConfig(){let e=xn().env||{};if(e.MAILGUN_API_KEY)return{apiKey:e.MAILGUN_API_KEY,domain:e.MAILGUN_DOMAIN||""}}async execute(e,t,r){let n=t.action_data;if(!n)throw new Error("Action data not found");let i=this.getMailgunConfig();if(!i)throw new Error("Mailgun configuration not provided. Please configure MAILGUN_API_KEY and MAILGUN_DOMAIN in SDK config.");let s=n.kwargs,o=r.getModel?.()||"gemini-2.5-pro",a=await EQ(i,{model:o,forward_email:s.forward_email,extraction_type:s.extraction_type,prompt:s.prompt,filters:{from_email:s.filter_from_email,to_email:s.filter_to_email,subject:s.filter_subject,body_contains:s.filter_body_contains},timeout:s.timeout});if(a.status==="success"&&a.data){let l=a.result_variable?.replace(/^\$/,"")||zN(s.extraction_type);r.variableStore.set(l,a.data),te.info(`[extract_email_content] Extracted and saved to ${l}`)}else throw new Error(a.message||"Failed to extract email content")}transpile(e){let t=e.action_data?.kwargs||{};return['await agent.execAction("extract_email_content", page, {',` action_data: { kwargs: ${JSON.stringify(t)} },`,"});"]}},AQ=io.object({forward_email:io.string().describe("Email address where emails are forwarded to (Mailgun inbox)"),extraction_type:io.enum(["verification_code","activation_link","custom"]).describe("Type of content to extract: verification_code for OTP codes, activation_link for magic links, custom for custom prompts"),prompt:io.string().optional().describe("Custom extraction prompt (required when extraction_type is custom)"),filter_from_email:io.string().optional().describe("Filter emails by sender address"),filter_to_email:io.string().optional().describe("Filter emails by recipient address"),filter_subject:io.string().optional().describe("Filter emails by subject (partial match)"),filter_body_contains:io.string().optional().describe("Filter emails by body content (partial match)"),timeout:io.number().optional().describe("Timeout in seconds for polling (default: 60)")});Lf=null;IQ=[Uw(Er),Hw(Er),qw(Er),Gw(Er),Ww(Er),Vw(Er),zw(Er),Kw(Er),Yw(Er),Jw(Er)],PQ=Promise.all(IQ);RQ=class{constructor(e,t){this.registry=e,this.getContext=t}getToolDefinitions(){return this.registry.getTools().filter(e=>e.availability.mcp).map(e=>({name:e.name,description:e.description,inputSchema:hf(e.schema)}))}getToolDefinitionsFiltered(e){let t=new Set(e);return this.registry.getTools().filter(r=>t.has(r.name)&&r.availability.mcp).map(r=>({name:r.name,description:r.description,inputSchema:hf(r.schema)}))}async createServer(e="web-sdk-tools"){throw new Error("MCP server creation not yet implemented. Install and configure an MCP SDK like @modelcontextprotocol/sdk")}async executeTool(e,t){let r=await this.getContext(),n=await this.registry.execute(e,t,r);return{content:[{type:"text",text:n.success?n.message||"Tool executed successfully":n.error||"Tool execution failed"}]}}getToolCount(){return this.registry.size()}getToolNames(){return this.registry.getToolNames()}};Qw=class{constructor(e={}){e.testDir&&(this.testDir=e.testDir,this.videoBasePath=Sd.join(e.testDir,"videos"),this.statesBasePath=Sd.join(e.testDir,"states"),this.downloadsBasePath=Sd.join(e.testDir,"downloads"),Ka.mkdirSync(this.videoBasePath,{recursive:!0}),Ka.mkdirSync(this.statesBasePath,{recursive:!0}),Ka.mkdirSync(this.downloadsBasePath,{recursive:!0})),this.terminationTimeout=e.terminationTimeout??null,this.defaultHeadless=e.headless??!1,this.additionalArgs=e.additionalArgs??[]}async launchBrowser(e={}){let t=e.debugPort,r=e.headless??this.defaultHeadless,n=ax(e.deviceName),i=ox(e.deviceName),s=n===kl.Chromium,o=!!e.extensionPath;te.info(`[BrowserManager] Launching ${n} browser for device: ${e.deviceName||"default"}${t?` on port ${t}`:""}`);let a={headless:r};if(s){o&&r&&(te.warn("[BrowserManager] Extension requested in headless mode; forcing headed mode to load extension."),r=!1,a.headless=!1);let k=[];(e.enableCamera||e.enableMicrophone)&&(k.push("--use-fake-device-for-media-stream","--use-fake-ui-for-media-stream"),e.enableMicrophone&&e.fakeAudioCapturePath&&(k.push(`--use-file-for-fake-audio-capture=${e.fakeAudioCapturePath}`),te.info(`[BrowserManager] Using fake audio capture file: ${e.fakeAudioCapturePath}`)));let T=o&&e.extensionPath?[`--disable-extensions-except=${e.extensionPath}`,`--load-extension=${e.extensionPath}`]:[];a.args=[...xv(t,e.disableSecurity??!0,r),...k,...T,...this.additionalArgs],i&&(a.channel=i,te.debug(`[BrowserManager] Launching browser with channel: ${i}`))}let l=$p(e.deviceName),u=sx(e.deviceName),d={acceptDownloads:!0,...l,timezoneId:e.timezoneId||"America/Los_Angeles",locale:e.locale||"en-US"};e.viewport&&(d.viewport=e.viewport,d.screen=e.viewport),e.isMobile!==void 0&&(d.isMobile=e.isMobile),e.hasTouch!==void 0&&(d.hasTouch=e.hasTouch),e.userAgent&&(d.userAgent=e.userAgent),e.colorScheme&&(d.colorScheme=e.colorScheme),e.geolocation&&(d.geolocation=e.geolocation,d.permissions=[...d.permissions||[],"geolocation"]);let p=o&&s?e.localStorageStatePath:void 0;e.localStorageStatePath&&!p&&(d.storageState=e.localStorageStatePath),e.recordVideo&&this.videoBasePath&&(d.recordVideo={dir:this.videoBasePath,size:{width:u.width,height:u.height}}),e.proxy&&(d.proxy=e.proxy),e.extraHTTPHeaders&&Object.keys(e.extraHTTPHeaders).length>0&&(d.extraHTTPHeaders=e.extraHTTPHeaders);let h,m,y,b=!1;if(s&&(o||e.userDataDir)){if(e.userDataDir)y=e.userDataDir;else{let T=this.testDir||Ka.mkdtempSync(Sd.join(MQ.tmpdir(),"shiplight-"));y=Sd.join(T,`ext-profile-${Date.now()}`),Ka.mkdirSync(y,{recursive:!0}),b=!0}let k={...a,...d};m=await YO.launchPersistentContext(y,k),p&&(await $Q(m,p),te.info(`[BrowserManager] Loaded storage state into persistent context from ${p}`)),h=m.browser(),te.info(`[BrowserManager] Launched persistent context${e.extensionPath?` for extension at ${e.extensionPath}`:` with profile at ${y}`}`)}else{switch(n){case kl.Firefox:h=await FQ.launch(a);break;case kl.Webkit:h=await BQ.launch(a);break;case kl.Chromium:default:h=await YO.launch(a);break}m=await h.newContext(d)}if(m.addInitScript(Tp),s){let k=["clipboard-read","clipboard-write"];e.enableCamera&&k.push("camera"),e.enableMicrophone&&k.push("microphone");try{await m.grantPermissions(k),te.info(`[BrowserManager] Granted permissions: ${k.join(", ")}`)}catch(T){te.warn("[BrowserManager] Failed to grant permissions:",T)}}else(e.enableCamera||e.enableMicrophone)&&te.warn("[BrowserManager] Camera/microphone enabled but browser is not Chromium; ignoring.");if(e.cookies&&e.cookies.length>0){let k=(Date.now()+31536e6)/1e3,T=e.cookies.map(D=>({...D,expires:k}));await m.addCookies(T),te.info(`[BrowserManager] Added ${e.cookies.length} cookies to browser context with expires=${k}`)}let w=e.viewport,E=w?{width:w.width,height:w.height+Bp}:ix(e.deviceName);if(te.info(`[BrowserManager] windowSize=${JSON.stringify(E)}`),s){let k=async T=>{try{await Dg(T,E.width,E.height),w&&await T.setViewportSize(w)}catch(D){te.warn("[BrowserManager] Failed to set window bounds via CDP:",D)}};for(let T of m.pages())await k(T);m.on("page",k)}let x="";if(s&&t!==void 0)try{x=await Ng(t)}catch(k){te.warn("[BrowserManager] Failed to get CDP WebSocket URL:",k)}let C=null;x&&(C=await JN({cdpUrl:x,label:`agent ${e.deviceName??n}`,pid:process.pid}),C&&te.info(`[BrowserManager] Registered browser with dev-box registry id=${C}`));let R={debugPort:t,browser:h,context:m,startTime:new Date,timeout:null,browserWsUrl:x,downloadsBasePath:this.downloadsBasePath,browserType:n,userDataDir:y,isTempUserDataDir:b,registryId:C};if(this.terminationTimeout!==null){let k=setTimeout(()=>{te.info(`[BrowserManager] Browser auto-terminated after ${this.terminationTimeout}ms`),this.terminateBrowser(R).catch(T=>te.error("[BrowserManager] Error terminating browser:",T))},this.terminationTimeout);R.timeout=k}return R}async terminateBrowser(e){if(e.timeout&&clearTimeout(e.timeout),await YN(e.registryId??null),await e.context.close(),await e.browser.close(),e.isTempUserDataDir&&e.userDataDir)try{Ka.rmSync(e.userDataDir,{recursive:!0,force:!0})}catch(t){te.warn("[BrowserManager] Failed to clean up temp user data dir:",e.userDataDir,t)}}getVideoBasePath(){return this.videoBasePath}getStatesBasePath(){return this.statesBasePath}getDownloadsBasePath(){return this.downloadsBasePath}};QN=e=>{if(!e||e===Sa)return"desktop";let t=mu(e);return t&&t.isMobile?"mobile":"desktop"},GQ=(e=>(e.Desktop="desktop",e.Mobile="mobile",e))(GQ||{}),WQ=class{constructor(e){this.currentPage=null,this.currentIndex=-1,this.context=e,this.initialize()}initialize(){this.context.on("page",async t=>{await this.handleNewPage(t)});let e=this.context.pages();e.length>0&&(this.currentPage=e[0],this.currentIndex=0);for(let t of e)this.setupPageListeners(t)}async handleNewPage(e){try{this.setupPageListeners(e);let t=this.context.pages().indexOf(e);await this.setCurrentPage(e,t)}catch{}}setupPageListeners(e){e.on("close",async()=>{await this.handlePageClose(e)})}async handlePageClose(e){try{if(this.currentPage===e){let t=this.context.pages(),r=t.slice().reverse().find(n=>!n.isClosed());r&&await this.setCurrentPage(r,t.indexOf(r))}}catch{}}async setCurrentPage(e,t){let r=this.currentPage!==e;this.currentPage=e,this.currentIndex=t,r&&await e.bringToFront()}async switchToPage(e){let t=this.context.pages();if(e<0||e>=t.length)throw new Error(`Invalid page index: ${e}. Available pages: 0-${t.length-1}`);let r=t[e];if(r.isClosed())throw new Error(`Page at index ${e} is closed`);return await this.setCurrentPage(r,e),r}async closePage(e){let t=this.context.pages();if(e<0||e>=t.length)throw new Error(`Invalid page index: ${e}. Available pages: 0-${t.length-1}`);let r=t[e];if(r.isClosed())throw new Error(`Page at index ${e} is already closed`);await r.close()}getCurrentPage(){return this.currentPage}getCurrentIndex(){return this.currentIndex}getAllPages(){return this.context.pages()}getPageCount(){return this.context.pages().length}};el=class extends Error{constructor(e,t){super(e,t),this.name="OTPError"}},tD=class extends el{constructor(e){super(e),this.name="SecretError"}},JQ=class extends tD{constructor(e,t){super(`Secret must be at least ${e} bytes (${e*8} bits), got ${t} bytes`),this.name="SecretTooShortError"}},YQ=class extends tD{constructor(e,t){super(`Secret must not exceed ${e} bytes, got ${t} bytes`),this.name="SecretTooLongError"}},e_=class extends el{constructor(e){super(e),this.name="CounterError"}},XQ=class extends e_{constructor(){super("Counter must be non-negative"),this.name="CounterNegativeError"}},XO=class extends e_{constructor(){super("Counter exceeds maximum safe integer value"),this.name="CounterOverflowError"}},ZQ=class extends e_{constructor(){super("Counter must be a finite integer"),this.name="CounterNotIntegerError"}},rD=class extends el{constructor(e){super(e),this.name="TimeError"}},QQ=class extends rD{constructor(){super("Time must be non-negative"),this.name="TimeNegativeError"}},eee=class extends rD{constructor(){super("Time must be a finite number"),this.name="TimeNotFiniteError"}},nD=class extends el{constructor(e){super(e),this.name="PeriodError"}},tee=class extends nD{constructor(e){super(`Period must be at least ${e} second(s)`),this.name="PeriodTooSmallError"}},ree=class extends nD{constructor(e){super(`Period must not exceed ${e} seconds`),this.name="PeriodTooLargeError"}},iD=class extends el{constructor(e,t){super(e,t),this.name="CryptoError"}},Mf=class extends iD{constructor(e,t){super(`HMAC computation failed: ${e}`,t),this.name="HMACError"}},nee=class extends iD{constructor(e,t){super(`Random byte generation failed: ${e}`,t),this.name="RandomBytesError"}},sD=class extends el{constructor(e){super(e),this.name="PluginError"}},iee=class extends sD{constructor(){super("Crypto plugin is required."),this.name="CryptoPluginMissingError"}},see=class extends sD{constructor(){super("Base32 plugin is required."),this.name="Base32PluginMissingError"}},Za=class extends el{constructor(e){super(e),this.name="ConfigurationError"}},oee=class extends Za{constructor(){super("Secret is required. Use generateSecret() to create one, or provide via { secret: 'YOUR_BASE32_SECRET' }"),this.name="SecretMissingError"}},aee=new TextEncoder,cge=new TextDecoder,lee=16,cee=64,uee=1,dee=3600,pee=Number.MAX_SAFE_INTEGER,hee=99,oD=Symbol("otplib.guardrails.override");kd=Object.freeze({MIN_SECRET_BYTES:lee,MAX_SECRET_BYTES:cee,MIN_PERIOD:uee,MAX_PERIOD:dee,MAX_COUNTER:pee,MAX_WINDOW:hee,[oD]:!1});Eee=class{constructor(e){this.crypto=e}get plugin(){return this.crypto}async hmac(e,t,r){try{let n=this.crypto.hmac(e,t,r);return n instanceof Promise?await n:n}catch(n){let i=n instanceof Error?n.message:String(n);throw new Mf(i,{cause:n})}}hmacSync(e,t,r){try{let n=this.crypto.hmac(e,t,r);if(n instanceof Promise)throw new Mf("Crypto plugin does not support synchronous HMAC operations");return n}catch(n){if(n instanceof Mf)throw n;let i=n instanceof Error?n.message:String(n);throw new Mf(i,{cause:n})}}randomBytes(e){try{return this.crypto.randomBytes(e)}catch(t){let r=t instanceof Error?t.message:String(t);throw new nee(r,{cause:t})}}};hD=(e,t)=>t===0?e:hD(t,e%t),Kf=(e,t)=>e+(t-hD(e,t)),mw=(()=>{let e=[];for(let t=0;t<40;t++)e.push(2**t);return e})();eN=Pee(Ree(5),Oee("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"),Dee(5),Nee("")),Lee=class{constructor(){ge(this,"name","scure")}encode(e,t={}){let{padding:r=!1}=t,n=eN.encode(e);return r?n:n.replace(/=+$/,"")}decode(e){try{let t=e.toUpperCase(),r=t.padEnd(Math.ceil(t.length/8)*8,"=");return eN.decode(r)}catch(t){throw t instanceof Error?new Error(`Invalid Base32 string: ${t.message}`):new Error("Invalid Base32 string")}}},Mee=Object.freeze(new Lee);fD=e=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,e])}),mD=class{constructor(e,t){if(ge(this,"oHash"),ge(this,"iHash"),ge(this,"blockLen"),ge(this,"outputLen"),ge(this,"finished",!1),ge(this,"destroyed",!1),Bee(e),Jf(t,void 0,"key"),this.iHash=e.create(),typeof this.iHash.update!="function")throw new Error("Expected instance of class which extends utils.Hash");this.blockLen=this.iHash.blockLen,this.outputLen=this.iHash.outputLen;let r=this.blockLen,n=new Uint8Array(r);n.set(t.length>r?e.create().update(t).digest():t);for(let i=0;i<n.length;i++)n[i]^=54;this.iHash.update(n),this.oHash=e.create();for(let i=0;i<n.length;i++)n[i]^=106;this.oHash.update(n),Zo(n)}update(e){return Yf(this),this.iHash.update(e),this}digestInto(e){Yf(this),Jf(e,this.outputLen,"output"),this.finished=!0,this.iHash.digestInto(e),this.oHash.update(e),this.oHash.digestInto(e),this.destroy()}digest(){let e=new Uint8Array(this.oHash.outputLen);return this.digestInto(e),e}_cloneInto(e){e||(e=Object.create(Object.getPrototypeOf(this),{}));let{oHash:t,iHash:r,finished:n,destroyed:i,blockLen:s,outputLen:o}=this;return e=e,e.finished=n,e.destroyed=i,e.blockLen=s,e.outputLen=o,e.oHash=t._cloneInto(e.oHash),e.iHash=r._cloneInto(e.iHash),e}clone(){return this._cloneInto()}destroy(){this.destroyed=!0,this.oHash.destroy(),this.iHash.destroy()}},gD=(e,t,r)=>new mD(e,t).update(r).digest();gD.create=(e,t)=>new mD(e,t);i_=class{constructor(e,t,r,n){ge(this,"blockLen"),ge(this,"outputLen"),ge(this,"padOffset"),ge(this,"isLE"),ge(this,"buffer"),ge(this,"view"),ge(this,"finished",!1),ge(this,"length",0),ge(this,"pos",0),ge(this,"destroyed",!1),this.blockLen=e,this.outputLen=t,this.padOffset=r,this.isLE=n,this.buffer=new Uint8Array(e),this.view=gw(this.buffer)}update(e){Yf(this),Jf(e);let{view:t,buffer:r,blockLen:n}=this,i=e.length;for(let s=0;s<i;){let o=Math.min(n-this.pos,i-s);if(o===n){let a=gw(e);for(;n<=i-s;s+=n)this.process(a,s);continue}r.set(e.subarray(s,s+o),this.pos),this.pos+=o,s+=o,this.pos===n&&(this.process(t,0),this.pos=0)}return this.length+=e.length,this.roundClean(),this}digestInto(e){Yf(this),$ee(e,this),this.finished=!0;let{buffer:t,view:r,blockLen:n,isLE:i}=this,{pos:s}=this;t[s++]=128,Zo(this.buffer.subarray(s)),this.padOffset>n-s&&(this.process(r,0),s=0);for(let d=s;d<n;d++)t[d]=0;r.setBigUint64(n-8,BigInt(this.length*8),i),this.process(r,0);let o=gw(e),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen must be aligned to 32bit");let l=a/4,u=this.get();if(l>u.length)throw new Error("_sha2: outputLen bigger than state");for(let d=0;d<l;d++)o.setUint32(4*d,u[d],i)}digest(){let{buffer:e,outputLen:t}=this;this.digestInto(e);let r=e.slice(0,t);return this.destroy(),r}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());let{blockLen:t,buffer:r,length:n,finished:i,destroyed:s,pos:o}=this;return e.destroyed=s,e.finished=i,e.length=n,e.pos=o,n%t&&e.buffer.set(r),e}clone(){return this._cloneInto()}},zo=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),Cn=Uint32Array.from([1779033703,4089235720,3144134277,2227873595,1013904242,4271175723,2773480762,1595750129,1359893119,2917565137,2600822924,725511199,528734635,4215389547,1541459225,327033209]),Ad=Uint32Array.from([1732584193,4023233417,2562383102,271733878,3285377520]),Ko=new Uint32Array(80),Uee=class extends i_{constructor(){super(64,20,8,!1),ge(this,"A",Ad[0]|0),ge(this,"B",Ad[1]|0),ge(this,"C",Ad[2]|0),ge(this,"D",Ad[3]|0),ge(this,"E",Ad[4]|0)}get(){let{A:e,B:t,C:r,D:n,E:i}=this;return[e,t,r,n,i]}set(e,t,r,n,i){this.A=e|0,this.B=t|0,this.C=r|0,this.D=n|0,this.E=i|0}process(e,t){for(let a=0;a<16;a++,t+=4)Ko[a]=e.getUint32(t,!1);for(let a=16;a<80;a++)Ko[a]=yw(Ko[a-3]^Ko[a-8]^Ko[a-14]^Ko[a-16],1);let{A:r,B:n,C:i,D:s,E:o}=this;for(let a=0;a<80;a++){let l,u;a<20?(l=yD(n,i,s),u=1518500249):a<40?(l=n^i^s,u=1859775393):a<60?(l=bD(n,i,s),u=2400959708):(l=n^i^s,u=3395469782);let d=yw(r,5)+l+o+u+Ko[a]|0;o=s,s=i,i=yw(n,30),n=r,r=d}r=r+this.A|0,n=n+this.B|0,i=i+this.C|0,s=s+this.D|0,o=o+this.E|0,this.set(r,n,i,s,o)}roundClean(){Zo(Ko)}destroy(){this.set(0,0,0,0,0),Zo(this.buffer)}},Hee=n_(()=>new Uee),Ff=BigInt(4294967295),rN=BigInt(32);nN=(e,t,r)=>e>>>r,iN=(e,t,r)=>e<<32-r|t>>>r,wc=(e,t,r)=>e>>>r|t<<32-r,_c=(e,t,r)=>e<<32-r|t>>>r,Bf=(e,t,r)=>e<<64-r|t>>>r-32,$f=(e,t,r)=>e>>>r-32|t<<64-r;Wee=(e,t,r)=>(e>>>0)+(t>>>0)+(r>>>0),Vee=(e,t,r,n)=>t+r+n+(e/2**32|0)|0,zee=(e,t,r,n)=>(e>>>0)+(t>>>0)+(r>>>0)+(n>>>0),Kee=(e,t,r,n,i)=>t+r+n+i+(e/2**32|0)|0,Jee=(e,t,r,n,i)=>(e>>>0)+(t>>>0)+(r>>>0)+(n>>>0)+(i>>>0),Yee=(e,t,r,n,i,s)=>t+r+n+i+s+(e/2**32|0)|0,Xee=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),Jo=new Uint32Array(64),Zee=class extends i_{constructor(e){super(64,e,8,!1)}get(){let{A:e,B:t,C:r,D:n,E:i,F:s,G:o,H:a}=this;return[e,t,r,n,i,s,o,a]}set(e,t,r,n,i,s,o,a){this.A=e|0,this.B=t|0,this.C=r|0,this.D=n|0,this.E=i|0,this.F=s|0,this.G=o|0,this.H=a|0}process(e,t){for(let d=0;d<16;d++,t+=4)Jo[d]=e.getUint32(t,!1);for(let d=16;d<64;d++){let p=Jo[d-15],h=Jo[d-2],m=vs(p,7)^vs(p,18)^p>>>3,y=vs(h,17)^vs(h,19)^h>>>10;Jo[d]=y+Jo[d-7]+m+Jo[d-16]|0}let{A:r,B:n,C:i,D:s,E:o,F:a,G:l,H:u}=this;for(let d=0;d<64;d++){let p=vs(o,6)^vs(o,11)^vs(o,25),h=u+p+yD(o,a,l)+Xee[d]+Jo[d]|0,m=(vs(r,2)^vs(r,13)^vs(r,22))+bD(r,n,i)|0;u=l,l=a,a=o,o=s+h|0,s=i,i=n,n=r,r=h+m|0}r=r+this.A|0,n=n+this.B|0,i=i+this.C|0,s=s+this.D|0,o=o+this.E|0,a=a+this.F|0,l=l+this.G|0,u=u+this.H|0,this.set(r,n,i,s,o,a,l,u)}roundClean(){Zo(Jo)}destroy(){this.set(0,0,0,0,0,0,0,0),Zo(this.buffer)}},Qee=class extends Zee{constructor(){super(32),ge(this,"A",zo[0]|0),ge(this,"B",zo[1]|0),ge(this,"C",zo[2]|0),ge(this,"D",zo[3]|0),ge(this,"E",zo[4]|0),ge(this,"F",zo[5]|0),ge(this,"G",zo[6]|0),ge(this,"H",zo[7]|0)}},wD=Gee(["0x428a2f98d728ae22","0x7137449123ef65cd","0xb5c0fbcfec4d3b2f","0xe9b5dba58189dbbc","0x3956c25bf348b538","0x59f111f1b605d019","0x923f82a4af194f9b","0xab1c5ed5da6d8118","0xd807aa98a3030242","0x12835b0145706fbe","0x243185be4ee4b28c","0x550c7dc3d5ffb4e2","0x72be5d74f27b896f","0x80deb1fe3b1696b1","0x9bdc06a725c71235","0xc19bf174cf692694","0xe49b69c19ef14ad2","0xefbe4786384f25e3","0x0fc19dc68b8cd5b5","0x240ca1cc77ac9c65","0x2de92c6f592b0275","0x4a7484aa6ea6e483","0x5cb0a9dcbd41fbd4","0x76f988da831153b5","0x983e5152ee66dfab","0xa831c66d2db43210","0xb00327c898fb213f","0xbf597fc7beef0ee4","0xc6e00bf33da88fc2","0xd5a79147930aa725","0x06ca6351e003826f","0x142929670a0e6e70","0x27b70a8546d22ffc","0x2e1b21385c26c926","0x4d2c6dfc5ac42aed","0x53380d139d95b3df","0x650a73548baf63de","0x766a0abb3c77b2a8","0x81c2c92e47edaee6","0x92722c851482353b","0xa2bfe8a14cf10364","0xa81a664bbc423001","0xc24b8b70d0f89791","0xc76c51a30654be30","0xd192e819d6ef5218","0xd69906245565a910","0xf40e35855771202a","0x106aa07032bbd1b8","0x19a4c116b8d2d0c8","0x1e376c085141ab53","0x2748774cdf8eeb99","0x34b0bcb5e19b48a8","0x391c0cb3c5c95a63","0x4ed8aa4ae3418acb","0x5b9cca4f7763e373","0x682e6ff3d6b2b8a3","0x748f82ee5defb2fc","0x78a5636f43172f60","0x84c87814a1f0ab72","0x8cc702081a6439ec","0x90befffa23631e28","0xa4506cebde82bde9","0xbef9a3f7b2c67915","0xc67178f2e372532b","0xca273eceea26619c","0xd186b8c721c0c207","0xeada7dd6cde0eb1e","0xf57d4f7fee6ed178","0x06f067aa72176fba","0x0a637dc5a2c898a6","0x113f9804bef90dae","0x1b710b35131c471b","0x28db77f523047d84","0x32caab7b40c72493","0x3c9ebe0a15c9bebc","0x431d67c49c100d4c","0x4cc5d4becb3e42b6","0x597f299cfc657e2a","0x5fcb6fab3ad6faec","0x6c44198c4a475817"].map(e=>BigInt(e))),ete=wD[0],tte=wD[1],Yo=new Uint32Array(80),Xo=new Uint32Array(80),rte=class extends i_{constructor(e){super(128,e,16,!1)}get(){let{Ah:e,Al:t,Bh:r,Bl:n,Ch:i,Cl:s,Dh:o,Dl:a,Eh:l,El:u,Fh:d,Fl:p,Gh:h,Gl:m,Hh:y,Hl:b}=this;return[e,t,r,n,i,s,o,a,l,u,d,p,h,m,y,b]}set(e,t,r,n,i,s,o,a,l,u,d,p,h,m,y,b){this.Ah=e|0,this.Al=t|0,this.Bh=r|0,this.Bl=n|0,this.Ch=i|0,this.Cl=s|0,this.Dh=o|0,this.Dl=a|0,this.Eh=l|0,this.El=u|0,this.Fh=d|0,this.Fl=p|0,this.Gh=h|0,this.Gl=m|0,this.Hh=y|0,this.Hl=b|0}process(e,t){for(let x=0;x<16;x++,t+=4)Yo[x]=e.getUint32(t),Xo[x]=e.getUint32(t+=4);for(let x=16;x<80;x++){let C=Yo[x-15]|0,R=Xo[x-15]|0,k=wc(C,R,1)^wc(C,R,8)^nN(C,R,7),T=_c(C,R,1)^_c(C,R,8)^iN(C,R,7),D=Yo[x-2]|0,O=Xo[x-2]|0,I=wc(D,O,19)^Bf(D,O,61)^nN(D,O,6),L=_c(D,O,19)^$f(D,O,61)^iN(D,O,6),F=zee(T,L,Xo[x-7],Xo[x-16]),U=Kee(F,k,I,Yo[x-7],Yo[x-16]);Yo[x]=U|0,Xo[x]=F|0}let{Ah:r,Al:n,Bh:i,Bl:s,Ch:o,Cl:a,Dh:l,Dl:u,Eh:d,El:p,Fh:h,Fl:m,Gh:y,Gl:b,Hh:w,Hl:E}=this;for(let x=0;x<80;x++){let C=wc(d,p,14)^wc(d,p,18)^Bf(d,p,41),R=_c(d,p,14)^_c(d,p,18)^$f(d,p,41),k=d&h^~d&y,T=p&m^~p&b,D=Jee(E,R,T,tte[x],Xo[x]),O=Yee(D,w,C,k,ete[x],Yo[x]),I=D|0,L=wc(r,n,28)^Bf(r,n,34)^Bf(r,n,39),F=_c(r,n,28)^$f(r,n,34)^$f(r,n,39),U=r&i^r&o^i&o,z=n&s^n&a^s&a;w=y|0,E=b|0,y=h|0,b=m|0,h=d|0,m=p|0,{h:d,l:p}=so(l|0,u|0,O|0,I|0),l=o|0,u=a|0,o=i|0,a=s|0,i=r|0,s=n|0;let K=Wee(I,F,z);r=Vee(K,O,L,U),n=K|0}({h:r,l:n}=so(this.Ah|0,this.Al|0,r|0,n|0)),{h:i,l:s}=so(this.Bh|0,this.Bl|0,i|0,s|0),{h:o,l:a}=so(this.Ch|0,this.Cl|0,o|0,a|0),{h:l,l:u}=so(this.Dh|0,this.Dl|0,l|0,u|0),{h:d,l:p}=so(this.Eh|0,this.El|0,d|0,p|0),{h,l:m}=so(this.Fh|0,this.Fl|0,h|0,m|0),{h:y,l:b}=so(this.Gh|0,this.Gl|0,y|0,b|0),{h:w,l:E}=so(this.Hh|0,this.Hl|0,w|0,E|0),this.set(r,n,i,s,o,a,l,u,d,p,h,m,y,b,w,E)}roundClean(){Zo(Yo,Xo)}destroy(){Zo(this.buffer),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}},nte=class extends rte{constructor(){super(64),ge(this,"Ah",Cn[0]|0),ge(this,"Al",Cn[1]|0),ge(this,"Bh",Cn[2]|0),ge(this,"Bl",Cn[3]|0),ge(this,"Ch",Cn[4]|0),ge(this,"Cl",Cn[5]|0),ge(this,"Dh",Cn[6]|0),ge(this,"Dl",Cn[7]|0),ge(this,"Eh",Cn[8]|0),ge(this,"El",Cn[9]|0),ge(this,"Fh",Cn[10]|0),ge(this,"Fl",Cn[11]|0),ge(this,"Gh",Cn[12]|0),ge(this,"Gl",Cn[13]|0),ge(this,"Hh",Cn[14]|0),ge(this,"Hl",Cn[15]|0)}},ite=n_(()=>new Qee,fD(1)),ste=n_(()=>new nte,fD(3)),ote=class{constructor(){ge(this,"name","noble")}hmac(e,t,r){return gD(e==="sha1"?Hee:e==="sha256"?ite:ste,t,r)}randomBytes(e){return jee(e)}constantTimeEqual(e,t){return vee(e,t)}},ate=Object.freeze(new ote);dte=t_({MIN_SECRET_BYTES:1});_D=class{constructor(e){this.context=e,this.testDataFileNames=[],this.extensionEnabled=!1}setTestDataDownloader(e,t){this.testDataDownloader=e,this.testDataFileNames=t??[]}setupPageTracking(e){this.tabManager=new WQ(e)}async switchTab(e){if(!this.tabManager)throw new Error("Tab manager not initialized");return await this.tabManager.switchToPage(e)}async closeTab(e){if(!this.tabManager)throw new Error("Tab manager not initialized");await this.tabManager.closePage(e)}getCurrentPage(){return this.tabManager?this.tabManager.getCurrentPage():null}validatePage(e){let t=this.getCurrentPage();if(t&&t!==e&&!t.isClosed())return te.info(`[validatePage] Page changed, switching to ${t.url()}`),t;if(e.isClosed()){let r=e.context().pages().filter(n=>!n.isClosed());if(r.length>0){let n=r[r.length-1];return te.info(`[validatePage] Page closed, switching to ${n.url()}`),n}te.error("[validatePage] No valid pages found")}return e}replaceVariables(e){return Wg(e,this.context.variableStore.getAll())}getTestDataFileNames(){return this.testDataFileNames}getTestDataFilePath(e){let t=this.context.testDataDir||process.cwd();return Cd.join(t,e)}async downloadTestDataFiles(e){if(e.length===0){te.debug("[AgentServices] No file paths provided for download");return}let t=this.context.testDataDir||process.cwd(),r=e.filter(n=>{let i=Cd.basename(n),s=Cd.join(t,i),o=eD.existsSync(s);return o&&te.debug(`[AgentServices] File already exists locally: ${i}`),!o});if(r.length===0){te.debug("[AgentServices] All files exist locally, no download needed");return}if(!this.testDataDownloader){te.debug("[AgentServices] No test data downloader configured, assuming files are pre-populated");return}te.info(`[AgentServices] Downloading ${r.length} test data files: ${r.join(", ")}`),await this.testDataDownloader(r,t)}async waitForDownloadComplete(e,t){return zQ(e,this.context,t)}getRecentDownloadedFilePath(){return this.context.downloadStatus?this.context.downloadStatus.status!=="completed"?(te.debug(`Download is ${this.context.downloadStatus.status}, not completed`),null):this.context.downloadStatus.filePath?(te.info(`Retrieved recent download path: ${this.context.downloadStatus.filePath}`),this.context.downloadStatus.filePath):(te.warn("Download completed but file path is missing"),null):(te.debug("No download found"),null)}addSensitive(e,t){this.context.variableStore.set(e,t,!0)}saveVariable(e,t){let r=e.startsWith("$")?e.slice(1):e;this.context.variableStore.set(r,t),te.debug(`Saved variable: ${r} = ${JSON.stringify(t)}`),this.context.agentNote=`A new value is saved to the variable "${r}".`}addNote(e){!e||e.trim()===""||(this.context.agentNote?this.context.agentNote+=`
|
|
4800
4800
|
${e.trim()}`:this.context.agentNote=e.trim())}readVariable(e){let t=e.startsWith("$")?e.slice(1):e,r=this.context.variableStore.get(t);return te.debug(`Read variable: ${t} = ${JSON.stringify(r)}`),r}async generate2faCode(e){try{let t=ute({secret:e,guardrails:dte});return te.info(`Generated 2FA code: ${t}`),t}catch(t){throw te.error(`Failed to generate 2FA code: ${t.message}`),new Error(`Failed to generate 2FA code: ${t.message}`)}}async getDOMText(e){return await e.evaluate(()=>document.body.innerText)}async waitUntilStable(e,t){return Co(e,t)}setPage(e){this.context.setPage?(te.info("[AgentServices] Calling setPage callback"),this.context.setPage(e)):te.debug("[AgentServices] setPage callback not configured")}getModel(){if(!this.context.model)throw new Error("No LLM model configured. An LLM model is required for AI-powered actions (login, verify, ai_extract, ai_wait_until, etc.). Set GOOGLE_API_KEY or ANTHROPIC_API_KEY in your MCP server configuration.");return this.context.model}getComputerUseModel(){return this.context.computer_use_model}get variableStore(){return this.context.variableStore}getDownloadDir(){return this.context.downloadDir}getActionSettings(){return this.context.organizationSettings?.action_code_conversion_settings||{}}getInteractiveClassNames(){return this.context.organizationSettings?.agent_settings?.interactive_class_names||[]}getIframeFallbackDomains(){return this.context.organizationSettings?.agent_settings?.iframe_fallback_domains||[]}isUseCleanScreenshotForAssertion(){return this.context.organizationSettings?.use_clean_screenshot_for_assertion??!0}isKnowledgeImagesEnabled(){return this.context.organizationSettings?.agent_settings?.enable_knowledge_images||!1}isSlicedScreenshotsEnabled(){return this.context.organizationSettings?.agent_settings?.use_sliced_screenshots||!1}isResizeSlicedScreenshotsEnabled(){return this.context.organizationSettings?.agent_settings?.resize_sliced_screenshots||!1}isAccessibilityTreeEnabled(){return this.context.organizationSettings?.agent_settings?.use_accessibility_tree||!1}isActionIntentFilteringEnabled(){return this.context.organizationSettings?.agent_settings?.use_action_intent_filtering||!1}isDomTreeTsEnabled(){let e=process.env.USE_DOM_TREE_TS;return e!==void 0?e==="true"||e==="1":this.context.organizationSettings?.agent_settings?.use_dom_tree_ts||!1}setExtensionEnabled(e){this.extensionEnabled=e}getDomServiceOptions(){return{useDomTreeTs:this.isDomTreeTsEnabled(),domTreeRoot:this.extensionEnabled?"document":"body"}}setKnowledgeRetriever(e){this.knowledgeRetriever=e}hasKnowledgeRetriever(){return this.knowledgeRetriever!==void 0}async retrieveKnowledges(e,t,r,n){if(!this.knowledgeRetriever)return te.debug("[AgentServices] No knowledge retriever configured"),[];try{let i=await this.knowledgeRetriever(e,t,r,n);return te.debug(`[AgentServices] Retrieved ${i.length} knowledges for statement`),i}catch(i){return te.warn(`[AgentServices] Failed to retrieve knowledges: ${i.message}`),[]}}},vD=(e=>(e.Started="started",e.Action="action",e.Completion="completion",e.Error="error",e.Aborted="aborted",e.Keepalive="keepalive",e))(vD||{}),xD=class extends Error{constructor(e){super(e),this.name="AgentTaskFailedError",this.details=e}},hte=1;mte=3,gte=40;tl=class{constructor(e){this.context=e,this._newActionEntities=new Map,this.agentServices=new _D(e),this.agentServices.agent=this,this.context.tokenUsages||(this.context.tokenUsages=[])}getNewActionEntities(){return this._newActionEntities}getAgentNote(){return this.context.agentNote||void 0}async getActionHandler(){if(!this._actionHandler){let{default:e}=await Promise.resolve().then(()=>(Zl(),Xl));this._actionHandler=new e}return this._actionHandler}async execAction(e,t,r){let n=(await this.getActionHandler()).getAction(e);if(!n)throw new Error(`Unknown action: ${e}`);await n.execute(t,r,this.agentServices)}async dismissModalIfPresent(e,t){try{let r=await this.execute(e,`TASK: Check if there is an INTRUSIVE POPUP blocking the page, and dismiss it if present.
|
|
4801
4801
|
|
|
4802
4802
|
ONLY dismiss intrusive popups such as:
|
|
@@ -4849,7 +4849,8 @@ ${a}`);let l=this.agentServices.knowledgeRetriever,u=!1;this.agentServices.hasKn
|
|
|
4849
4849
|
75% { opacity: 1; transform: scale(1.0); }
|
|
4850
4850
|
100% { opacity: 0; transform: scale(0.9); }
|
|
4851
4851
|
}
|
|
4852
|
-
`});import{chromium as Nte}from"playwright";function Dte(e){return e.replace(/\/$/,"")}async function tm(e){let t=Dte(e);return Ts?.cdpUrl===t?(te.info("[RelayCache] Reusing cached Browser connection"),Ts.browser):kc?(te.info("[RelayCache] Waiting for in-progress connection..."),await kc):(kc=(async()=>{let n;for(let i=0;i<3;i++)try{te.info(`[RelayCache] Connecting to CDP (attempt ${i+1})...`);let o=await Nte.connectOverCDP(t,{timeout:6e4});te.info("[RelayCache] Connected to CDP successfully");let a=()=>{Ts?.browser===o&&(te.info("[RelayCache] Browser disconnected, clearing cache"),Ts=null)};return Ts={browser:o,cdpUrl:t,onDisconnected:a},o.on("disconnected",a),te.info("[RelayCache] Cached Browser connection for future reuse"),o}catch(s){n=s;let o=250+i*250;te.warn(`[RelayCache] Connection attempt ${i+1} failed, retrying in ${o}ms...`),await new Promise(a=>setTimeout(a,o))}throw te.error("[RelayCache] All connection attempts failed:",n),n instanceof Error?n:new Error("CDP connect failed")})().finally(()=>{kc=null}),await kc)}function AD(){if(!Ts){te.info("[RelayCache] No cached connection to disconnect");return}let e=Ts;Ts=null,kc=null,e.onDisconnected&&typeof e.browser.off=="function"&&e.browser.off("disconnected",e.onDisconnected),te.info("[RelayCache] Force disconnecting Browser"),e.browser.close().catch(()=>{})}function TD(){return{hasCached:Ts!==null,cdpUrl:Ts?.cdpUrl}}var Ts,kc,rm=mt(()=>{"use strict";Yn();Ts=null,kc=null});function Ic(){return!!process.env.SHIPLIGHT_PERF_PROFILING}var nm=mt(()=>{"use strict"});import{z as ze}from"zod";var CD,o_,kD,Pc,Dd,ID,PD,In,OD,im,Qo,a_=mt(()=>{"use strict";CD=ze.enum(["JS_CODE","AI_MODE"]),o_=ze.object({type:CD,expression:ze.string()}),kD=ze.enum(["DRAFT","STEP","ACTION","IF_ELSE","WHILE_LOOP"]),Pc=ze.object({uid:ze.string(),type:kD,comment:ze.string().optional()}),Dd=ze.object({action_data:ze.object({action_name:ze.string(),kwargs:ze.record(ze.any()).optional(),args:ze.array(ze.any()).optional()}),action_description:ze.string().optional(),url:ze.string().optional(),xpath:ze.string().nullable().optional(),locator:ze.string().nullable().optional(),css_selector:ze.string().nullable().optional(),unique_selector:ze.string().nullable().optional(),element_index:ze.number().nullable().optional(),frame_path:ze.array(ze.any()).optional(),artifacts:ze.record(ze.any()).optional(),feedback:ze.string().optional(),original_browser_use_action:ze.any().optional()}).passthrough(),ID=Pc.extend({type:ze.literal("DRAFT"),description:ze.string()}),PD=Pc.extend({type:ze.literal("ACTION"),description:ze.string(),action_entity:Dd.optional(),locator:ze.string().optional(),use_pure_vision:ze.boolean().optional()}),In=ze.lazy(()=>ze.union([ID,PD,Pc.extend({type:ze.literal("STEP"),description:ze.string().optional().default(""),statements:ze.array(In),reference_id:ze.number().optional(),template_path:ze.string().optional(),template_params:ze.record(ze.string()).optional()}),Pc.extend({type:ze.literal("IF_ELSE"),description:ze.string().optional(),condition:o_,then:ze.array(In),else:ze.array(In).optional()}),Pc.extend({type:ze.literal("WHILE_LOOP"),description:ze.string().optional(),condition:o_,body:ze.array(In),timeout_ms:ze.number().optional()})])),OD=ze.object({name:ze.string(),statements:ze.array(In),teardown:ze.array(In).optional(),skip:ze.union([ze.boolean(),ze.string()]).optional(),timeout:ze.number().optional(),fail:ze.union([ze.boolean(),ze.string()]).optional(),only:ze.boolean().optional(),slow:ze.boolean().optional()}),im=ze.object({tests:ze.array(OD).min(1),beforeAll:ze.array(In).optional(),afterAll:ze.array(In).optional(),beforeEach:ze.array(In).optional(),afterEach:ze.array(In).optional()}),Qo=ze.object({comment:ze.string().optional(),version:ze.string().optional(),goal:ze.string().optional(),url:ze.string().optional(),baseURL:ze.string().optional(),final_feedback:ze.string().optional(),completed:ze.boolean().optional(),success:ze.boolean().optional(),statements:ze.array(In).optional(),teardown:ze.array(In).optional(),last_modified_at:ze.string().optional(),testGroup:im.optional()}).refine(e=>e.testGroup!==void 0?e.goal===void 0&&(e.statements===void 0||e.statements.length===0):e.goal!==void 0,{message:"TestFlow must have either goal/statements (single test) or testGroup (suite), not both"})});import{stringify as Rte,parse as LD,parseAllDocuments as Mye,parseDocument as Lte,Document as Mte,isMap as Nc,isSeq as ts}from"yaml";import{v4 as es}from"uuid";function sm(e,t){let r={...t?.test_case_id!==void 0?{test_case_id:t.test_case_id}:{},...t?.name?{name:t.name}:{},goal:e.goal??"",url:e.url,base_url:e.baseURL,...t?.timeout!==void 0?{timeout:t.timeout}:{},...t?.settings&&Object.keys(t.settings).length>0?{settings:t.settings}:{},statements:(e.statements??[]).map(Ei)};return e.final_feedback&&(r.final_feedback=e.final_feedback),e.teardown&&e.teardown.length>0&&(r.teardown=e.teardown.map(Ei)),r}function rl(e,t){if(e.testGroup)return FD(e,t);let r=sm(e,t),n=new Mte(r);return e.comment&&(n.commentBefore=e.comment),ND(n,e.statements??[]),e.teardown&&ND(n,e.teardown,"teardown"),n.toString(MD)}function ND(e,t,r="statements"){let n=e.contents;if(!n||!Nc(n))return;let i=n.get(r,!0);ts(i)&&Rd(i,t)}function Rd(e,t){for(let r=0;r<Math.min(e.items.length,t.length);r++){let n=t[r],i=e.items[r];if(r>0&&(i.spaceBefore=!0),n.comment&&(r===0?e.commentBefore=n.comment:i.commentBefore=n.comment),Nc(i)){let s=i;if(n.type==="STEP"){let o=s.get("statements",!0);ts(o)&&Rd(o,n.statements)}else if(n.type==="IF_ELSE"){let o=s.get("THEN",!0);ts(o)&&Rd(o,n.then);let a=s.get("ELSE",!0);ts(a)&&n.else&&Rd(a,n.else)}else if(n.type==="WHILE_LOOP"){let o=s.get("DO",!0);ts(o)&&Rd(o,n.body)}}}}function FD(e,t){let r=e.testGroup;if(!r)throw new Error("suiteToYaml requires a TestFlow with testGroup");let n={};t?.test_case_id!==void 0&&(n.test_case_id=t.test_case_id),t?.name&&(n.name=t.name),t?.tags&&t.tags.length>0&&(n.tags=t.tags),t?.use&&Object.keys(t.use).length>0&&(n.use=t.use),t?.settings&&Object.keys(t.settings).length>0&&(n.settings=t.settings);let i={};return e.baseURL&&(i.base_url=e.baseURL),r.beforeAll&&r.beforeAll.length>0&&(i.beforeAll=r.beforeAll.map(Ei)),r.beforeEach&&r.beforeEach.length>0&&(i.beforeEach=r.beforeEach.map(Ei)),r.afterEach&&r.afterEach.length>0&&(i.afterEach=r.afterEach.map(Ei)),r.afterAll&&r.afterAll.length>0&&(i.afterAll=r.afterAll.map(Ei)),i.tests=r.tests.map(s=>{let o={name:s.name};return s.skip!==void 0&&(o.skip=s.skip),s.timeout!==void 0&&(o.timeout=s.timeout),s.fail!==void 0&&(o.fail=s.fail),s.only!==void 0&&(o.only=s.only),s.slow!==void 0&&(o.slow=s.slow),o.statements=s.statements.map(Ei),s.teardown&&s.teardown.length>0&&(o.teardown=s.teardown.map(Ei)),o}),n.suite=i,Rte(n,MD)}function Ei(e){switch(e.type){case"DRAFT":return Fte(e);case"ACTION":return Bte(e);case"STEP":return $te(e);case"IF_ELSE":return jte(e);case"WHILE_LOOP":return Ute(e)}}function Fte(e){return{intent:e.description}}function Bte(e){let t=e.action_entity?.action_data?.action_name??e.action_entity?.action?.action_name,r=e.action_entity?.action_data?.kwargs??e.action_entity?.action?.kwargs;if(t==="verify"){let a=r?.statement;if(typeof a=="string"&&!e.action_entity?.locator&&!e.action_entity?.xpath){let l=r?.code;return typeof l=="string"?{VERIFY:a,js:l}:{VERIFY:a}}}if(t==="go_to_url"){let a=r?.url;if(typeof a=="string"&&!e.action_entity?.locator&&!e.action_entity?.xpath){let l={URL:a};return r?.new_tab===!0&&(l.new_tab=!0),typeof r?.timeout_seconds=="number"&&(l.timeout_seconds=r.timeout_seconds),l}}if(t==="js_action"){let a=r?.code;if(typeof a=="string"&&e.description)return{intent:e.description,js:a}}if(t==="ai_wait_until"){let a=r?.condition;if(typeof a=="string"){let l={WAIT_UNTIL:a};return typeof r?.timeout_seconds=="number"&&r.timeout_seconds!==60&&(l.timeout_seconds=r.timeout_seconds),l}}if(t==="wait"){let a=r?.seconds,u={WAIT:e.description||`Wait ${a}s`};return typeof a=="number"&&(u.seconds=a),u}if(t==="js_code"){let a=r?.code;if(typeof a=="string"&&!e.action_entity?.locator&&!e.action_entity?.xpath)return{CODE:a}}if(!e.action_entity)return{intent:e.description};let n=e.action_entity.action_data??e.action_entity.action;if(!n)return{intent:e.description};let i={intent:e.description,action:n.action_name},s=e.locator??e.action_entity.locator;s&&(i.locator=s);let o=e.action_entity.xpath;if(o&&(i.xpath=o),e.use_pure_vision&&(i.use_pure_vision=!0),n.kwargs&&Object.keys(n.kwargs).length>0)for(let[a,l]of Object.entries(n.kwargs))i[a]=l;return n.args&&n.args.length>0&&(i.args=n.args),i}function $te(e){if(e.template_path){let r={template:e.template_path};return e.template_params&&Object.keys(e.template_params).length>0&&(r.params=e.template_params),r}let t={STEP:e.description,statements:e.statements.map(Ei)};return e.reference_id!==void 0&&(t.reference_id=e.reference_id),t}function jte(e){let t={IF:BD(e.condition),THEN:e.then.map(Ei)};return e.else&&e.else.length>0&&(t.ELSE=e.else.map(Ei)),t}function Ute(e){let t={WHILE:BD(e.condition),DO:e.body.map(Ei)};return e.timeout_ms!==void 0&&(t.timeout_ms=e.timeout_ms),t}function BD(e){return e.type==="JS_CODE"?`js:${e.expression}`:e.expression}function om(e){try{let t=LD(e);if(!t||typeof t!="object")return{};let r={};return typeof t.test_case_id=="number"&&Number.isFinite(t.test_case_id)&&(r.test_case_id=t.test_case_id),typeof t.template_id=="number"&&Number.isFinite(t.template_id)&&(r.template_id=t.template_id),typeof t.name=="string"&&t.name.trim()&&(r.name=t.name.trim()),typeof t.timeout=="number"&&Number.isFinite(t.timeout)&&(r.timeout=t.timeout),t.settings&&typeof t.settings=="object"&&!Array.isArray(t.settings)&&(r.settings=t.settings),r}catch{return{}}}function l_(e){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(l_);let t=e,r=Object.keys(t);if(r.length===1){let i=r[0];if(i.startsWith("{ ")&&i.endsWith(" }")&&t[i]===null)return`{{${i.slice(2,-2)}}}`}let n={};for(let[i,s]of Object.entries(t))n[i]=l_(s);return n}function $n(e){if(e.length>DD)throw new Error(`YAML input too large (${e.length} bytes, max ${DD})`);let t=l_(LD(e));if(!t||typeof t!="object")throw new Error("Invalid YAML: expected an object at root level");if(t.suite)return Hte(t);let r={version:"1.3.0",goal:t.goal,url:t.url,baseURL:t.base_url,statements:Si(t.statements??[])};t.final_feedback&&(r.final_feedback=t.final_feedback),t.teardown&&Array.isArray(t.teardown)&&(r.teardown=Si(t.teardown));let n=Qo.safeParse(r);if(!n.success)throw new Error(`Invalid TestFlow after YAML conversion: ${JSON.stringify(n.error.errors)}`);let i=n.data;return jD(e,i),i}function Hte(e){let t=e.suite;if(!t||typeof t!="object")throw new Error("Invalid suite: expected an object");let r=t.tests;if(!Array.isArray(r)||r.length===0)throw new Error('Suite must have a non-empty "tests" array');let i={tests:r.map(a=>{if(!a.name)throw new Error('Each test in a suite must have a "name" field');if(!Array.isArray(a.statements)||a.statements.length===0)throw new Error(`Suite test "${a.name}" must have a non-empty "statements" array`);let l={name:a.name,statements:Si(a.statements)};return Array.isArray(a.teardown)&&a.teardown.length>0&&(l.teardown=Si(a.teardown)),a.skip!==void 0&&(l.skip=a.skip),typeof a.timeout=="number"&&(l.timeout=a.timeout),a.fail!==void 0&&(l.fail=a.fail),a.only===!0&&(l.only=!0),a.slow===!0&&(l.slow=!0),l})};Array.isArray(t.beforeAll)&&t.beforeAll.length>0&&(i.beforeAll=Si(t.beforeAll)),Array.isArray(t.afterAll)&&t.afterAll.length>0&&(i.afterAll=Si(t.afterAll)),Array.isArray(t.beforeEach)&&t.beforeEach.length>0&&(i.beforeEach=Si(t.beforeEach)),Array.isArray(t.afterEach)&&t.afterEach.length>0&&(i.afterEach=Si(t.afterEach));let s=im.safeParse(i);if(!s.success)throw new Error(`Invalid TestGroup: ${JSON.stringify(s.error.errors)}`);return{version:"1.3.0",baseURL:t.base_url||void 0,testGroup:s.data}}function Si(e){if(!Array.isArray(e))throw new Error("Expected an array of statements");return e.map(qte)}function qte(e){if(typeof e=="string")throw new Error(`Plain string statements are not supported. Use an object with a "desc" key instead. Example: { "desc": "${e}" }`);if(typeof e!="object"||e===null)throw new Error(`Invalid statement: expected object, got ${typeof e}`);let t=e;if("IF"in t)return Gte(t);if("WHILE"in t)return Wte(t);if("STEP"in t)return Vte(t);if("VERIFY"in t){let r=t.VERIFY,n={statement:typeof r=="string"?r:String(r)};return typeof t.js=="string"&&(n.code=t.js),{uid:es(),type:"ACTION",description:String(r),action_entity:{action_description:String(r),action_data:{action_name:"verify",kwargs:n}}}}if("URL"in t){let r=t.URL,n=t.new_tab===!0?!0:void 0,i=typeof t.timeout_seconds=="number"?t.timeout_seconds:void 0,s={url:typeof r=="string"?r:String(r)};return n&&(s.new_tab=!0),i!==void 0&&(s.timeout_seconds=i),{uid:es(),type:"ACTION",description:`Navigate to ${r}`,action_entity:{action_description:`Navigate to ${r}`,action_data:{action_name:"go_to_url",kwargs:s}}}}if("WAIT_UNTIL"in t){let r=t.WAIT_UNTIL,n=typeof t.timeout_seconds=="number"?t.timeout_seconds:60;return{uid:es(),type:"ACTION",description:`Wait until: ${r}`,action_entity:{action_description:`Wait until: ${r}`,action_data:{action_name:"ai_wait_until",kwargs:{condition:typeof r=="string"?r:String(r),timeout_seconds:n}}}}}if("WAIT"in t){let r=t.WAIT,n=typeof t.seconds=="number"?t.seconds:3;return{uid:es(),type:"ACTION",description:typeof r=="string"?r:`Wait ${n}s`,action_entity:{action_description:typeof r=="string"?r:`Wait ${n}s`,action_data:{action_name:"wait",kwargs:{seconds:n}}}}}if("CODE"in t){let r=t.CODE;if(r==null)throw new Error('CODE statement has no code. Use "CODE: |" followed by indented code on the next line.');return{uid:es(),type:"ACTION",description:"Code block",action_entity:{action_description:"Code block",action_data:{action_name:"js_code",kwargs:{code:typeof r=="string"?r:String(r)}}}}}if("js"in t&&("intent"in t||"desc"in t)&&!("VERIFY"in t)&&t.action!=="verify"){let r=t.js,n=typeof t.intent=="string"?t.intent:typeof t.desc=="string"?t.desc:"";return{uid:es(),type:"ACTION",description:n,action_entity:{action_description:n,action_data:{action_name:"js_action",kwargs:{code:typeof r=="string"?r:String(r)}}}}}if("call"in t&&typeof t.call=="string"){let{call:r,...n}=t;return RD({...n,action:"function",functionName:r})}if("action"in t)return RD(t);if("intent"in t&&typeof t.intent=="string"||"desc"in t&&typeof t.desc=="string")return{uid:es(),type:"DRAFT",description:typeof t.intent=="string"?t.intent:t.desc};throw new Error(`Cannot infer statement type from object: ${JSON.stringify(t)}`)}function $D(e){if(typeof e!="string")throw new Error(`Condition must be a string, got ${typeof e}`);return e.startsWith("js:")?{type:"JS_CODE",expression:e.slice(3)}:{type:"AI_MODE",expression:e}}function Gte(e){let t=$D(e.IF),r=e.THEN;if(!Array.isArray(r))throw new Error("IF_ELSE requires a THEN array");let n={uid:es(),type:"IF_ELSE",condition:t,then:Si(r)};return"ELSE"in e&&Array.isArray(e.ELSE)&&(n.else=Si(e.ELSE)),n}function Wte(e){let t=$D(e.WHILE),r=e.DO;if(!Array.isArray(r))throw new Error("WHILE_LOOP requires a DO array");let n={uid:es(),type:"WHILE_LOOP",condition:t,body:Si(r)};return typeof e.timeout_ms=="number"&&(n.timeout_ms=e.timeout_ms),n}function Vte(e){let t=typeof e.STEP=="string"?e.STEP:"";if(!Array.isArray(e.statements))throw new Error("STEP requires a statements array");let r={uid:es(),type:"STEP",description:t,statements:Si(e.statements)};if(typeof e.reference_id=="number"&&(r.reference_id=e.reference_id),typeof e.template_path=="string"&&(r.template_path=e.template_path),e.template_params&&typeof e.template_params=="object"&&!Array.isArray(e.template_params)){let n=e.template_params,i={};for(let[s,o]of Object.entries(n))i[s]=String(o);r.template_params=i}return r}function RD(e){let t=typeof e.action=="string"?e.action:String(e.action),r=typeof e.intent=="string"?e.intent:typeof e.desc=="string"?e.desc:"",n=typeof e.locator=="string"?e.locator:void 0,i=typeof e.xpath=="string"?e.xpath:void 0,s=typeof e.use_pure_vision=="boolean"?e.use_pure_vision:void 0,o={};for(let[u,d]of Object.entries(e))zte.has(u)||(o[u]=d);t==="verify"&&typeof o.js=="string"&&(o.code=o.js,delete o.js);let a={action_description:r,action_data:{action_name:t,kwargs:Object.keys(o).length>0?o:{}}};n&&(a.locator=n),i&&(a.xpath=i);let l={uid:es(),type:"ACTION",description:r,action_entity:a};return s&&(l.use_pure_vision=!0),l}function jD(e,t){let r;try{r=Lte(e)}catch{return}let n=r.contents;if(!n||!Nc(n))return;if(r.commentBefore)t.comment=r.commentBefore;else{let l=n.items?.[0];l?.key&&l.key.commentBefore&&(t.comment=l.key.commentBefore)}let i=n,s=i.get("statements",!0);ts(s)&&t.statements&&Oc(s,t.statements);let o=i.get("teardown",!0);ts(o)&&t.teardown&&Oc(o,t.teardown)}function Oc(e,t){e.commentBefore&&t.length>0&&(t[0].comment=e.commentBefore);for(let r=0;r<Math.min(e.items.length,t.length);r++){let n=e.items[r];n.commentBefore&&!(r===0&&e.commentBefore)&&(t[r].comment=n.commentBefore);let i=t[r];if(i.type==="STEP"&&Nc(n)){let s=n.get("statements",!0);ts(s)&&Oc(s,i.statements)}else if(i.type==="IF_ELSE"&&Nc(n)){let s=n.get("THEN",!0);ts(s)&&Oc(s,i.then);let o=n.get("ELSE",!0);ts(o)&&i.else&&Oc(o,i.else)}else if(i.type==="WHILE_LOOP"&&Nc(n)){let s=n.get("DO",!0);ts(s)&&Oc(s,i.body)}}}var MD,DD,zte,am=mt(()=>{"use strict";a_();MD={lineWidth:120,defaultKeyType:"PLAIN",defaultStringType:"PLAIN"};DD=1024*1024;zte=new Set(["action","intent","desc","locator","xpath","use_pure_vision"])});import{parse as Uye,stringify as Hye}from"yaml";var UD=mt(()=>{"use strict";am()});var c_,ea,lm=mt(()=>{"use strict";c_=e=>{let t=[];switch(e.type){case"STEP":e.statements&&t.push({key:"statements",statements:e.statements});break;case"IF_ELSE":e.then&&t.push({key:"then",statements:e.then}),e.else&&t.push({key:"else",statements:e.else});break;case"WHILE_LOOP":e.body&&t.push({key:"body",statements:e.body});break}return t},ea=e=>{let t=[],r=n=>{for(let i of n){t.push(i);let s=c_(i);for(let o of s)r(o.statements)}};return r(e),t}});function cm(e){let t=0,r=0;for(let n of e)if(n.type==="DRAFT")r++;else if(n.type==="ACTION"){let i=n.action_entity?.action_data?.action_name??"";WD.has(i)||t++}return{action:t,draft:r}}function Jte(e){try{return new Function(`return async function() { ${e} }`),null}catch(t){return t.message}}function GD(e){try{return new Function(`return async function() { return (${e}) }`),null}catch(t){return t.message}}function Yte(e){let t=e.split(/\r?\n/).map(i=>i.trim()).filter(i=>i.length>0&&!i.startsWith("//")).length,r=e.match(/\bawait\b/g),n=r?r.length:0;return t<=HD&&n<=qD?null:`${t} non-blank line(s), ${n} await(s) \u2014 limits are ${HD} lines and ${qD} awaits. The js: field is a cache for one natural-language intent, not a place for multi-step logic. Break this into multiple statements \u2014 one VERIFY or intent+js per UI interaction or assertion \u2014 so each step is visible in the debugger and self-healable.`}function u_(e,t){let r=t?.coverageThreshold??Kte,n=[],i=[],s;try{s=$n(e)}catch(h){return{valid:!1,errors:[`Invalid YAML: ${h.message}`],warnings:[],stats:{total:0,action:0,draft:0,coverage:0}}}s.goal||n.push('Missing required field: "goal"'),s.statements?.length||n.push('Missing required field: "statements"');let o=[...ea(s.statements??[]),...s.teardown?ea(s.teardown):[]],{action:a,draft:l}=cm(o),u="Hint: in YAML double-quoted strings, backslashes are escape characters \u2014 use \\\\/ instead of \\/ for regex, or use single quotes.";for(let h of o){let m=h;if(m.reference_id!==void 0){let y=m.description||h.uid;n.push(`Unresolved cloud template reference on statement "${y}" (reference_id: ${m.reference_id}). Local YAML tests cannot use reference_id \u2014 inline the template statements or use the local "template:" key instead.`)}if(h.type==="ACTION"){let y=h,b=y.action_entity?.action_data?.action_name??"";if(b==="js_code"||b==="js_action"||b==="verify"||b==="ai_assert"){let w=y.action_entity?.action_data?.kwargs?.code;if(typeof w=="string"){let E=Jte(w);if(E){let x=y.description||b;n.push(`Invalid JS in "${x}": ${E}. ${u}`)}else if(b==="verify"||b==="js_action"){let x=Yte(w);if(x){let C=y.description||b;n.push(`JS cache for "${C}" is too complex: ${x}`)}}}}}if(h.type==="IF_ELSE"){let y=h;if(y.condition.type==="JS_CODE"){let b=GD(y.condition.expression);b&&n.push(`Invalid JS in IF condition "${y.condition.expression}": ${b}. ${u}`)}}if(h.type==="WHILE_LOOP"){let y=h;if(y.condition.type==="JS_CODE"){let b=GD(y.condition.expression);b&&n.push(`Invalid JS in WHILE condition "${y.condition.expression}": ${b}. ${u}`)}}}let d=a+l,p=d>0?Math.round(a/d*100):0;return d>0&&p/100<r&&i.push(`Low action coverage: ${a}/${d} statements (${p}%) are enriched with action/js. ${l} draft statement(s) still need enrichment. Use MCP tools (act, get_locators) to convert drafts to actions.`),{valid:n.length===0,errors:n,warnings:i,stats:{total:d,action:a,draft:l,coverage:p}}}var Kte,HD,qD,WD,VD=mt(()=>{"use strict";am();lm();Kte=.5,HD=5,qD=3,WD=new Set(["verify","ai_assert","done","go_to_url","ai_wait_until","wait","js_code"])});var zD=mt(()=>{"use strict";lm()});import{v4 as Xye}from"uuid";var KD=mt(()=>{"use strict"});var rs,Ld,JD=mt(()=>{"use strict";rs=(e=>(e.DRAFT="DRAFT",e.STEP="STEP",e.ACTION="ACTION",e.IF_ELSE="IF_ELSE",e.WHILE_LOOP="WHILE_LOOP",e))(rs||{}),Ld=18e4});var um=mt(()=>{"use strict"});var YD=mt(()=>{"use strict";um()});var XD,Zte,ZD,QD,Md,Qte,ere,eR=mt(()=>{"use strict";XD=112,Zte=1080-XD,ZD={"Blackberry PlayBook":{name:"Blackberry PlayBook",userAgent:"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/26.0 Safari/536.2+",screen:{width:600,height:1024},viewport:{width:600,height:1024},deviceScaleFactor:1,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"BlackBerry Z30":{name:"BlackBerry Z30",userAgent:"Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/26.0 Mobile Safari/537.10+",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy Note 3":{name:"Galaxy Note 3",userAgent:"Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy Note II":{name:"Galaxy Note II",userAgent:"Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy S III":{name:"Galaxy S III",userAgent:"Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy S5":{name:"Galaxy S5",userAgent:"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S8":{name:"Galaxy S8",userAgent:"Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:740},viewport:{width:360,height:740},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S9+":{name:"Galaxy S9+",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:320,height:658},viewport:{width:320,height:658},deviceScaleFactor:4.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S24":{name:"Galaxy S24",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-S921U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:780},viewport:{width:360,height:780},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy A55":{name:"Galaxy A55",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:480,height:1040},viewport:{width:480,height:1040},deviceScaleFactor:2.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy Tab S4":{name:"Galaxy Tab S4",userAgent:"Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:712,height:1138},viewport:{width:712,height:1138},deviceScaleFactor:2.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy Tab S9":{name:"Galaxy Tab S9",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-X710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:640,height:1024},viewport:{width:640,height:1024},deviceScaleFactor:2.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"iPad (gen 5)":{name:"iPad (gen 5)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 6)":{name:"iPad (gen 6)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 7)":{name:"iPad (gen 7)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:810,height:1080},viewport:{width:810,height:1080},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 11)":{name:"iPad (gen 11)",userAgent:"Mozilla/5.0 (iPad; CPU OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/19E241 Safari/604.1",screen:{width:656,height:944},viewport:{width:656,height:944},deviceScaleFactor:2.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad Mini":{name:"iPad Mini",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad Pro 11":{name:"iPad Pro 11",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:834,height:1194},viewport:{width:834,height:1194},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 6":{name:"iPhone 6",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 6 Plus":{name:"iPhone 6 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 7":{name:"iPhone 7",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 7 Plus":{name:"iPhone 7 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 8":{name:"iPhone 8",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 8 Plus":{name:"iPhone 8 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone SE":{name:"iPhone SE",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/26.0 Mobile/14E304 Safari/602.1",screen:{width:320,height:568},viewport:{width:320,height:568},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone SE (3rd gen)":{name:"iPhone SE (3rd gen)",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/26.0 Mobile/19E241 Safari/602.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone X":{name:"iPhone X",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:812},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone XR":{name:"iPhone XR",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:896},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11":{name:"iPhone 11",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:715},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11 Pro":{name:"iPhone 11 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:635},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11 Pro Max":{name:"iPhone 11 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:715},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12":{name:"iPhone 12",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Pro":{name:"iPhone 12 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Pro Max":{name:"iPhone 12 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Mini":{name:"iPhone 12 Mini",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:629},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13":{name:"iPhone 13",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Pro":{name:"iPhone 13 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Pro Max":{name:"iPhone 13 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Mini":{name:"iPhone 13 Mini",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:629},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14":{name:"iPhone 14",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Plus":{name:"iPhone 14 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Pro":{name:"iPhone 14 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:660},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Pro Max":{name:"iPhone 14 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:740},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15":{name:"iPhone 15",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:659},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Plus":{name:"iPhone 15 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:739},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Pro":{name:"iPhone 15 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:659},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Pro Max":{name:"iPhone 15 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:739},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Kindle Fire HDX":{name:"Kindle Fire HDX",userAgent:"Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true",screen:{width:800,height:1280},viewport:{width:800,height:1280},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"LG Optimus L70":{name:"LG Optimus L70",userAgent:"Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:384,height:640},viewport:{width:384,height:640},deviceScaleFactor:1.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Microsoft Lumia 550":{name:"Microsoft Lumia 550",userAgent:"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36 Edge/14.14263",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Microsoft Lumia 950":{name:"Microsoft Lumia 950",userAgent:"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36 Edge/14.14263",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:4,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 10":{name:"Nexus 10",userAgent:"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:800,height:1280},viewport:{width:800,height:1280},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 4":{name:"Nexus 4",userAgent:"Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:384,height:640},viewport:{width:384,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 5":{name:"Nexus 5",userAgent:"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 5X":{name:"Nexus 5X",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 6":{name:"Nexus 6",userAgent:"Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 6P":{name:"Nexus 6P",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 7":{name:"Nexus 7",userAgent:"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:600,height:960},viewport:{width:600,height:960},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nokia Lumia 520":{name:"Nokia Lumia 520",userAgent:"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)",screen:{width:320,height:533},viewport:{width:320,height:533},deviceScaleFactor:1.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nokia N9":{name:"Nokia N9",userAgent:"Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13",screen:{width:480,height:854},viewport:{width:480,height:854},deviceScaleFactor:1,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Pixel 2":{name:"Pixel 2",userAgent:"Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:411,height:731},viewport:{width:411,height:731},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 2 XL":{name:"Pixel 2 XL",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:411,height:823},viewport:{width:411,height:823},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 3":{name:"Pixel 3",userAgent:"Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:393,height:786},viewport:{width:393,height:786},deviceScaleFactor:2.75,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 4":{name:"Pixel 4",userAgent:"Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:353,height:745},viewport:{width:353,height:745},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 4a (5G)":{name:"Pixel 4a (5G)",userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:892},viewport:{width:412,height:765},deviceScaleFactor:2.63,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 5":{name:"Pixel 5",userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:393,height:851},viewport:{width:393,height:727},deviceScaleFactor:2.75,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 7":{name:"Pixel 7",userAgent:"Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:915},viewport:{width:412,height:839},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Moto G4":{name:"Moto G4",userAgent:"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Desktop Chrome HiDPI":{name:"Desktop Chrome HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Edge HiDPI":{name:"Desktop Edge HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Firefox HiDPI":{name:"Desktop Firefox HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0.1) Gecko/20100101 Firefox/142.0.1",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"firefox"},"Desktop Safari":{name:"Desktop Safari",userAgent:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"webkit"},"Desktop Chrome":{name:"Desktop Chrome",displayName:"Playwright Chromium",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Chrome Medium Resolution":{name:"Desktop Chrome Medium Resolution",displayName:"Playwright Chromium",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Chrome (Branded)":{name:"Desktop Chrome (Branded)",displayName:"Google Chrome",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"chrome"},"Desktop Chrome Medium Resolution (Branded)":{name:"Desktop Chrome Medium Resolution (Branded)",displayName:"Google Chrome",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"chrome"},"Desktop Edge":{name:"Desktop Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1920,height:1080},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Edge (Branded)":{name:"Desktop Edge (Branded)",displayName:"Microsoft Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"msedge"},"Desktop Edge Medium Resolution (Branded)":{name:"Desktop Edge Medium Resolution (Branded)",displayName:"Microsoft Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"msedge"},"Desktop Firefox":{name:"Desktop Firefox",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0.1) Gecko/20100101 Firefox/142.0.1",screen:{width:1920,height:1080},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"firefox"}},QD={desktop:["Desktop Chrome","Desktop Chrome Medium Resolution","Desktop Chrome (Branded)","Desktop Chrome Medium Resolution (Branded)","Desktop Edge (Branded)","Desktop Edge Medium Resolution (Branded)","Desktop Safari"],mobile:["iPhone 15 Pro Max","iPhone 15 Pro","iPhone 15 Plus","iPhone 15","iPhone 14 Pro Max","iPhone 14 Pro","iPhone 14 Plus","iPhone 14","iPhone 13 Pro Max","iPhone 13 Pro","iPhone 13","iPhone 13 Mini","iPhone 12 Pro Max","iPhone 12 Pro","iPhone 12","iPhone 12 Mini","iPhone 11 Pro Max","iPhone 11 Pro","iPhone 11","iPhone XR","iPhone X","iPhone SE (3rd gen)","iPhone SE","iPhone 8 Plus","iPhone 8","iPhone 7 Plus","iPhone 7","iPhone 6 Plus","iPhone 6","Galaxy S24","Galaxy A55","Galaxy S9+","Galaxy S8","Galaxy S5","Galaxy Note 3","Galaxy Note II","Galaxy S III","Pixel 7","Pixel 5","Pixel 4a (5G)","Pixel 4","Pixel 3","Pixel 2 XL","Pixel 2","Nexus 6P","Nexus 6","Nexus 5X","Nexus 5","Nexus 4","Moto G4","LG Optimus L70","Microsoft Lumia 950","Microsoft Lumia 550","Nokia Lumia 520","Nokia N9","BlackBerry Z30"]},Md=(e,t=!1)=>{let r=["chromium"];return t&&r.push("webkit"),QD[e].map(n=>ZD[n]).filter(n=>n.defaultBrowserType&&r.includes(n.defaultBrowserType))},Qte={desktop:{label:"Desktop",type:"desktop",devices:Md("desktop")},mobile:{label:"Mobile Web",type:"mobile",devices:Md("mobile")}},ere={desktop:{label:"Desktop",type:"desktop",devices:Md("desktop",!0)},mobile:{label:"Mobile Web",type:"mobile",devices:Md("mobile",!0)}}});var tR=mt(()=>{"use strict"});var rR=mt(()=>{"use strict"});var nR=mt(()=>{"use strict"});var iR=mt(()=>{"use strict"});var Fd,oR=mt(()=>{"use strict";Fd=class sR{data={};sensitive=new Set;get(t){return this.data[t]}set(t,r,n=!1){this.data[t]=r,n?this.sensitive.add(t):this.sensitive.has(t)&&this.sensitive.delete(t)}getAll(){return{...this.data}}isSensitive(t){return this.sensitive.has(t)}getAllSensitiveKeys(){return new Set(this.sensitive)}delete(t){return this.sensitive.delete(t),delete this.data[t]}clear(){this.data={},this.sensitive.clear()}has(t){return t in this.data}get size(){return Object.keys(this.data).length}merge(t){for(let[r,n]of Object.entries(t.getAll()))this.set(r,n,t.isSensitive(r))}toJSON(){return{data:{...this.data},sensitiveKeys:Array.from(this.sensitive)}}static fromJSON(t){let r=new sR;if(t.data){let n=new Set(t.sensitiveKeys||[]);for(let[i,s]of Object.entries(t.data))r.set(i,s,n.has(i))}return r}}});var aR=mt(()=>{"use strict"});var lR=mt(()=>{"use strict"});var cR=mt(()=>{"use strict";um()});var ns=mt(()=>{"use strict";UD();VD();am();a_();zD();KD();lm();JD();YD();eR();tR();rR();nR();iR();oR();aR();lR();cR();um()});var uR={};Li(uR,{connectBrowser:()=>tm,forceDisconnect:()=>AD,getCacheStatus:()=>TD});var dR=mt(()=>{"use strict";rm()});import qt from"fs";import nre from"net";import ire from"os";import Bt from"path";import mR from"crypto";import are from"axios";import lre from"node:http";import Bd,{WebSocketServer as pR}from"ws";import Dc from"node:fs";import hR from"node:path";import ure from"node:os";async function sre(e){return new Promise(t=>{let r=nre.createServer();r.once("error",()=>t(!1)),r.once("listening",()=>r.close(()=>t(!0))),r.listen(e,"127.0.0.1")})}function ore(){let t=new Date().toISOString().replace(/T/,"-").replace(/:/g,"-").replace(/\..+/,""),r=mR.randomBytes(2).toString("hex");return`${t}-${r}`}var gR,dm,un,cre,yR,ai,dre,fR,pre,hre,bR,wR=mt(()=>{"use strict";rm();nm();Yn();ns();gR=class{sessions=new Map;browserManager=null;baseDebugPort=9222;runDir;onBeforeAction;constructor(e={}){this.runDir=e.runDir||Bt.join(ire.homedir(),".shiplight/inspect"),this.onBeforeAction=e.onBeforeAction,qt.mkdirSync(this.runDir,{recursive:!0})}async findAvailablePort(){for(let e=this.baseDebugPort;e<this.baseDebugPort+100;e++)if(await sre(e))return e;throw new Error(`No available debug ports found in range ${this.baseDebugPort}\u2013${this.baseDebugPort+99}`)}ensureBrowserManager(){this.browserManager||(this.browserManager=new Qw({testDir:this.runDir}))}async createSession(e){this.ensureBrowserManager();let t=ore(),r=await this.findAvailablePort(),n=e.browserOptions||{},i,s;if(n.pathToExtension&&!qt.existsSync(n.pathToExtension))throw new Error(`Extension directory not found: ${n.pathToExtension}`);try{i=await this.browserManager.launchBrowser({debugPort:r,viewport:n.viewport,isMobile:n.isMobile,hasTouch:n.hasTouch,userAgent:n.userAgent,colorScheme:n.colorScheme,timezoneId:n.timezoneId,geolocation:n.geolocation,headless:n.headless,disableSecurity:n.disableSecurity,recordVideo:n.recordEvidence,locale:n.locale,proxy:n.proxy,localStorageStatePath:n.storageStatePath,extensionPath:n.pathToExtension,userDataDir:n.userDataDir});let o=i.context.pages();s=o.find(l=>!l.url().startsWith("chrome-extension://"))??o[0]??await i.context.newPage(),e.startingUrl&&e.startingUrl!=="about:blank"&&await s.goto(e.startingUrl,{waitUntil:"domcontentloaded"});let a=await this.createSessionData(t,s,i.context,e.webAgentConfig,e.maxActions,i);return a.recordEvidence=n.recordEvidence??!1,n.recordEvidence&&await i.context.tracing.start({screenshots:!0,snapshots:!0,sources:!1}),this.sessions.set(t,a),{sessionId:t,url:s.url()}}catch(o){throw s&&await s.close().catch(()=>{}),i&&this.browserManager&&await this.browserManager.terminateBrowser(i).catch(()=>{}),te.info("[SessionManager.createSession] Failed:",o),o}}async createSessionWithPage(e,t={}){let r=this.generateSessionId(),n=t.runDir||this.runDir;n!==this.runDir&&qt.mkdirSync(n,{recursive:!0});let i=await this.createSessionData(r,e,e.context(),t.webAgentConfig,t.maxActions,void 0);return this.sessions.set(r,i),{sessionId:r}}async createRelaySession(e){let t=this.generateSessionId();try{let n=(await tm(e)).contexts()[0];if(!n)throw new Error("No browser context available after CDP connection");let s=n.pages()[0]||null,o=new Fd,a=Nd({variableStore:o,executionHistory:[],testDataDir:Bt.join(this.runDir,"files")}),l=new tl(a);l.agentServices.setupPageTracking(n);let u={sessionId:t,sessionType:"relay",page:s,webAgent:l,agentContext:a,variableStore:o,consoleLogs:[],networkLogs:[],actionLog:[],createdAt:new Date,lastAccessedAt:new Date,abortController:new AbortController,totalActions:0,relayConnection:{cdpUrl:e,connectedAt:new Date}};return this.sessions.set(t,u),{sessionId:t}}catch(r){throw te.error("[createRelaySession] FAILED:",r),r}}generateSessionId(){let e=new Date,t=e.toISOString().slice(0,10),r=e.toTimeString().slice(0,8).replace(/:/g,"-"),n=Math.random().toString(36).substring(2,6);return`${t}_${r}_${n}`}async createSessionData(e,t,r,n,i,s){let o=[];t.on("console",p=>{o.push({type:p.type(),text:p.text(),timestamp:Date.now()})});let a=[];t.on("response",p=>{a.push({url:p.url(),method:p.request().method(),status:p.status(),timestamp:Date.now()})});let l=n?.variableStore??new Fd,u=Nd({model:n?.model,variableStore:l,executionHistory:[],testDataDir:n?.testDataDir||Bt.join(this.runDir,"files"),downloadDir:n?.downloadDir,organizationId:n?.organizationId,organizationSettings:n?.organizationSettings}),d=new tl(u);return d.agentServices.setupPageTracking(r),n?.testDataDownloader&&d.agentServices.setTestDataDownloader(n.testDataDownloader,n.testDataFileNames),n?.knowledgeRetriever&&d.agentServices.setKnowledgeRetriever(n.knowledgeRetriever),{sessionId:e,sessionType:"playwright",browserInstance:s,page:t,webAgent:d,agentContext:u,variableStore:l,consoleLogs:o,networkLogs:a,createdAt:new Date,lastAccessedAt:new Date,actionLog:[],abortController:new AbortController,maxActions:i,totalActions:0}}async closeSession(e){let t=this.sessions.get(e);if(!t)return{};if(t.sessionType==="relay")return{};t.page.removeAllListeners("console"),t.page.removeAllListeners("response");let r=null;try{r=t.recordEvidence&&t.browserInstance?t.page.video():null}catch{}let n;if(t.recordEvidence&&t.browserInstance)try{n=Bt.join(this.runDir,"traces",`${e}.zip`),qt.mkdirSync(Bt.dirname(n),{recursive:!0}),await t.browserInstance.context.tracing.stop({path:n}),qt.existsSync(n)||(te.warn("[SessionManager.closeSession] Trace file not created at expected path:",n),n=void 0),t.tracePath=n}catch(a){te.warn("[SessionManager.closeSession] Failed to stop trace:",a),n=void 0}t.browserInstance&&this.browserManager&&await this.browserManager.terminateBrowser(t.browserInstance),await this.persistReportSnapshot(e,t,{logPrefix:"[SessionManager.closeSession]"}),this.sessions.delete(e);let i;if(r)try{i=await r.path()??void 0}catch(a){te.info("[SessionManager.closeSession] Failed to retrieve video path:",a)}let s=Bt.join(this.runDir,e,"report-data.json"),o=qt.existsSync(s);return{...i?{videoPath:i}:{},...n?{tracePath:n}:{},...o?{reportDataPath:s}:{},reportDataSaved:o}}async closeAllSessions(){let e=Array.from(this.sessions.keys());for(let t of e)await this.closeSession(t)}getSessionCount(){return this.sessions.size}async forceDisconnectRelay(){let{forceDisconnect:e}=await Promise.resolve().then(()=>(dR(),uR));e()}getSession(e){let t=this.sessions.get(e);return t?(t.lastAccessedAt=new Date,{sessionId:t.sessionId,sessionType:t.sessionType==="relay"?"relay":"browser",createdAt:t.createdAt,lastAccessedAt:t.lastAccessedAt,currentUrl:this.getPageForSession(t).url(),relayConnection:t.relayConnection}):null}getAllSessions(){return Array.from(this.sessions.values()).map(e=>({sessionId:e.sessionId,sessionType:e.sessionType==="relay"?"relay":"browser",createdAt:e.createdAt,lastAccessedAt:e.lastAccessedAt,currentUrl:this.getPageForSession(e).url(),relayConnection:e.relayConnection}))}getSessionData(e){return this.sessions.get(e)||null}getDebugPort(e){return this.sessions.get(e)?.browserInstance?.debugPort}getPage(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);return this.getPageForSession(t)}getPageForSession(e){let t=e.webAgent.agentServices.getCurrentPage();if(t&&!t.isClosed())return t;if(e.page)return e.webAgent.agentServices.validatePage(e.page);throw new Error("No pages available in this session. Attach a tab via the Chrome extension first.")}getWebAgent(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);return t.webAgent}getVariableStore(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);return t.variableStore}async getCurrentUrl(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);return this.getPageForSession(t).url()}async navigate(e,t){let r=this.sessions.get(e);if(!r)throw new Error(`Session ${e} not found`);await this.getPageForSession(r).goto(t,{waitUntil:"domcontentloaded"})}async loginWithTestAccount(e,t){let r=this.sessions.get(e);if(!r)throw new Error(`Session ${e} not found`);if(!t.loginConfig||!t.username||!t.password)return!1;try{let n=this.getPageForSession(r),i=t.loginConfig.account?.type,s={site_url:n.url(),account:{type:i,username:t.username,password:t.password,two_factor_auth_config:t.loginConfig.account?.two_factor_auth_config},additional_prompt:t.loginConfig.additional_prompt,verification_hint:t.loginConfig.verification_hint,num_verification_exprs:0};return(await r.webAgent.loginPage(n,s)).success}catch(n){return te.info("Login failed:",n),!1}}async getPageInfo(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);let r=this.getPageForSession(t);return{url:r.url(),title:await r.title()}}getSessionInfo(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);let r=t.sessionType==="relay"?"relay":"browser";return{sessionId:t.sessionId,sessionType:r,relayConnection:t.relayConnection}}async getExtendedPageInfo(e){let[t,r,n,i,s,o,a]=await Promise.all([Promise.resolve(e.url()),e.title(),e.evaluate(()=>window.scrollY),e.evaluate(()=>window.innerHeight),e.evaluate(()=>window.innerWidth),e.evaluate(()=>document.documentElement.scrollHeight),e.evaluate(()=>document.documentElement.scrollWidth)]),l=Math.floor(n),u=Math.floor(Math.max(0,o-(n+i)));return{url:t,title:r,viewportWidth:Math.floor(s),viewportHeight:Math.floor(i),pageWidth:Math.floor(a),pageHeight:Math.floor(o),scrollY:Math.floor(n),pixelsAbove:l,pixelsBelow:u}}async inspectPage(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);let r=Bt.join(this.runDir,e);qt.mkdirSync(r,{recursive:!0});let n=Date.now(),i=this.getPageForSession(t),s=new ni,{domState:o,screenshot:a}=await s.getClickableElementsWithScreenshot(i),l=o.elementTree.clickableElementsToString(),u=await this.getExtendedPageInfo(i),d=Bt.join(r,`screenshot-${n}.png`);qt.writeFileSync(d,a),t.domState=o;let p=await this.buildRichDomText(l,u,t),h=Bt.join(r,`dom-${n}.txt`);return qt.writeFileSync(h,p),{screenshotPath:d,domText:p,domFilePath:h,currentUrl:i.url()}}async getDom(e,t=!0){let r=Ic(),n=r?performance.now():0,i=this.sessions.get(e);if(!i)throw new Error(`Session ${e} not found`);let s=Bt.join(this.runDir,e);qt.mkdirSync(s,{recursive:!0});let o=Date.now(),a=this.getPageForSession(i),l,u=r?performance.now():0;t&&(l=await a.screenshot({type:"png",fullPage:!1}));let d=r?performance.now()-u:0,p=1e4,h=r?performance.now():0,m=(async()=>{let K=new ni;return t?await K.getClickableElementsWithScreenshot(a):{domState:await K.getClickableElements(a,{highlightElements:!1}),screenshot:void 0}})(),y,b=new Promise((K,W)=>{y=setTimeout(()=>{let pe=a.url();W(new Error(`inspect_page timed out after ${p/1e3}s. Page: ${pe} \u2014 The page may be unresponsive or blocking CDP commands. Try navigating to a simpler page or reloading.`))},p)}),{domState:w,screenshot:E}=await Promise.race([m,b]);clearTimeout(y);let x=w.elementTree.clickableElementsToString(),C=r?performance.now()-h:0,R=r?performance.now():0,k=await this.getExtendedPageInfo(a),T=r?performance.now()-R:0;i.domState=w;let D=r?performance.now():0,O;E&&(O=Bt.join(s,`screenshot-${o}.png`),qt.writeFileSync(O,E));let I=await this.buildRichDomText(x,k,i),L=Bt.join(s,`dom-${o}.txt`);qt.writeFileSync(L,I);let F=r?performance.now()-D:0,U=a.url();if(t){let K="";try{K=await a.title()}catch{}this.savePageCacheArtifacts(U,K,I,l,E,w,a).catch(W=>{te.warn("[SessionManager] Failed to save page cache artifacts:",W)})}let z=r?performance.now()-n:0;return{domText:I,domFilePath:L,screenshotPath:O,currentUrl:U,...r&&{duration_ms:Math.round(z),timing:{screenshot_ms:Math.round(d),dom_extraction_ms:Math.round(C),page_info_ms:Math.round(T),file_write_ms:Math.round(F)}}}}async buildRichDomText(e,t,r){let n=t.pixelsAbove>0,i=t.pixelsBelow>0,s=t.viewportHeight>0?t.pixelsAbove/t.viewportHeight:0,o=t.viewportHeight>0?t.pixelsBelow/t.viewportHeight:0,a=t.viewportHeight>0?t.pageHeight/t.viewportHeight:0,l=t.pageHeight>t.viewportHeight?t.scrollY/Math.max(t.pageHeight-t.viewportHeight,1):0,u=`Page info: ${t.viewportWidth}x${t.viewportHeight}px viewport, ${t.pageWidth}x${t.pageHeight}px total page size, ${s.toFixed(1)} pages above, ${o.toFixed(1)} pages below, ${a.toFixed(1)} total pages, at ${Math.round(l*100)}% of page`,p=r.page.context().pages(),h=this.getPageForSession(r),m="";for(let b=0;b<p.length;b++){let w=p[b],E=w.url(),x=await w.title().catch(()=>""),C=w===h?" (current)":"";m+=`Tab ${b}: ${E} - ${x.slice(0,30)}${C}
|
|
4852
|
+
`});import{chromium as Nte}from"playwright";function Dte(e){return e.replace(/\/$/,"")}async function tm(e){let t=Dte(e);return Ts?.cdpUrl===t?(te.info("[RelayCache] Reusing cached Browser connection"),Ts.browser):kc?(te.info("[RelayCache] Waiting for in-progress connection..."),await kc):(kc=(async()=>{let n;for(let i=0;i<3;i++)try{te.info(`[RelayCache] Connecting to CDP (attempt ${i+1})...`);let o=await Nte.connectOverCDP(t,{timeout:6e4});te.info("[RelayCache] Connected to CDP successfully");let a=()=>{Ts?.browser===o&&(te.info("[RelayCache] Browser disconnected, clearing cache"),Ts=null)};return Ts={browser:o,cdpUrl:t,onDisconnected:a},o.on("disconnected",a),te.info("[RelayCache] Cached Browser connection for future reuse"),o}catch(s){n=s;let o=250+i*250;te.warn(`[RelayCache] Connection attempt ${i+1} failed, retrying in ${o}ms...`),await new Promise(a=>setTimeout(a,o))}throw te.error("[RelayCache] All connection attempts failed:",n),n instanceof Error?n:new Error("CDP connect failed")})().finally(()=>{kc=null}),await kc)}function AD(){if(!Ts){te.info("[RelayCache] No cached connection to disconnect");return}let e=Ts;Ts=null,kc=null,e.onDisconnected&&typeof e.browser.off=="function"&&e.browser.off("disconnected",e.onDisconnected),te.info("[RelayCache] Force disconnecting Browser"),e.browser.close().catch(()=>{})}function TD(){return{hasCached:Ts!==null,cdpUrl:Ts?.cdpUrl}}var Ts,kc,rm=mt(()=>{"use strict";Yn();Ts=null,kc=null});function Ic(){return!!process.env.SHIPLIGHT_PERF_PROFILING}var nm=mt(()=>{"use strict"});var CD=mt(()=>{"use strict"});var kD=mt(()=>{"use strict"});var ID=mt(()=>{"use strict"});var PD=mt(()=>{"use strict"});var im=mt(()=>{"use strict"});var OD=mt(()=>{"use strict";im()});var ND,Lte,DD,RD,Dd,Mte,Fte,LD=mt(()=>{"use strict";ND=112,Lte=1080-ND,DD={"Blackberry PlayBook":{name:"Blackberry PlayBook",userAgent:"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/26.0 Safari/536.2+",screen:{width:600,height:1024},viewport:{width:600,height:1024},deviceScaleFactor:1,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"BlackBerry Z30":{name:"BlackBerry Z30",userAgent:"Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/26.0 Mobile Safari/537.10+",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy Note 3":{name:"Galaxy Note 3",userAgent:"Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy Note II":{name:"Galaxy Note II",userAgent:"Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy S III":{name:"Galaxy S III",userAgent:"Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/26.0 Mobile Safari/534.30",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Galaxy S5":{name:"Galaxy S5",userAgent:"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S8":{name:"Galaxy S8",userAgent:"Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:740},viewport:{width:360,height:740},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S9+":{name:"Galaxy S9+",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:320,height:658},viewport:{width:320,height:658},deviceScaleFactor:4.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy S24":{name:"Galaxy S24",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-S921U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:780},viewport:{width:360,height:780},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy A55":{name:"Galaxy A55",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:480,height:1040},viewport:{width:480,height:1040},deviceScaleFactor:2.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy Tab S4":{name:"Galaxy Tab S4",userAgent:"Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:712,height:1138},viewport:{width:712,height:1138},deviceScaleFactor:2.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Galaxy Tab S9":{name:"Galaxy Tab S9",userAgent:"Mozilla/5.0 (Linux; Android 14; SM-X710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:640,height:1024},viewport:{width:640,height:1024},deviceScaleFactor:2.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"iPad (gen 5)":{name:"iPad (gen 5)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 6)":{name:"iPad (gen 6)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 7)":{name:"iPad (gen 7)",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:810,height:1080},viewport:{width:810,height:1080},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad (gen 11)":{name:"iPad (gen 11)",userAgent:"Mozilla/5.0 (iPad; CPU OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/19E241 Safari/604.1",screen:{width:656,height:944},viewport:{width:656,height:944},deviceScaleFactor:2.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad Mini":{name:"iPad Mini",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:768,height:1024},viewport:{width:768,height:1024},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPad Pro 11":{name:"iPad Pro 11",userAgent:"Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:834,height:1194},viewport:{width:834,height:1194},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 6":{name:"iPhone 6",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 6 Plus":{name:"iPhone 6 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 7":{name:"iPhone 7",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 7 Plus":{name:"iPhone 7 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 8":{name:"iPhone 8",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 8 Plus":{name:"iPhone 8 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:414,height:736},viewport:{width:414,height:736},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone SE":{name:"iPhone SE",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/26.0 Mobile/14E304 Safari/602.1",screen:{width:320,height:568},viewport:{width:320,height:568},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone SE (3rd gen)":{name:"iPhone SE (3rd gen)",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/26.0 Mobile/19E241 Safari/602.1",screen:{width:375,height:667},viewport:{width:375,height:667},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone X":{name:"iPhone X",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/26.0 Mobile/15A372 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:812},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone XR":{name:"iPhone XR",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:896},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11":{name:"iPhone 11",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:715},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11 Pro":{name:"iPhone 11 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:635},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 11 Pro Max":{name:"iPhone 11 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:414,height:896},viewport:{width:414,height:715},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12":{name:"iPhone 12",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Pro":{name:"iPhone 12 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Pro Max":{name:"iPhone 12 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 12 Mini":{name:"iPhone 12 Mini",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:629},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13":{name:"iPhone 13",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Pro":{name:"iPhone 13 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Pro Max":{name:"iPhone 13 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 13 Mini":{name:"iPhone 13 Mini",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:375,height:812},viewport:{width:375,height:629},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14":{name:"iPhone 14",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:390,height:844},viewport:{width:390,height:664},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Plus":{name:"iPhone 14 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:428,height:926},viewport:{width:428,height:746},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Pro":{name:"iPhone 14 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:660},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 14 Pro Max":{name:"iPhone 14 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:740},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15":{name:"iPhone 15",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:659},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Plus":{name:"iPhone 15 Plus",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:739},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Pro":{name:"iPhone 15 Pro",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:393,height:852},viewport:{width:393,height:659},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"iPhone 15 Pro Max":{name:"iPhone 15 Pro Max",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",screen:{width:430,height:932},viewport:{width:430,height:739},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Kindle Fire HDX":{name:"Kindle Fire HDX",userAgent:"Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true",screen:{width:800,height:1280},viewport:{width:800,height:1280},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"LG Optimus L70":{name:"LG Optimus L70",userAgent:"Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:384,height:640},viewport:{width:384,height:640},deviceScaleFactor:1.25,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Microsoft Lumia 550":{name:"Microsoft Lumia 550",userAgent:"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36 Edge/14.14263",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Microsoft Lumia 950":{name:"Microsoft Lumia 950",userAgent:"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36 Edge/14.14263",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:4,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 10":{name:"Nexus 10",userAgent:"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:800,height:1280},viewport:{width:800,height:1280},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 4":{name:"Nexus 4",userAgent:"Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:384,height:640},viewport:{width:384,height:640},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 5":{name:"Nexus 5",userAgent:"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 5X":{name:"Nexus 5X",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 6":{name:"Nexus 6",userAgent:"Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 6P":{name:"Nexus 6P",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:732},viewport:{width:412,height:732},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nexus 7":{name:"Nexus 7",userAgent:"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:600,height:960},viewport:{width:600,height:960},deviceScaleFactor:2,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nokia Lumia 520":{name:"Nokia Lumia 520",userAgent:"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)",screen:{width:320,height:533},viewport:{width:320,height:533},deviceScaleFactor:1.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Nokia N9":{name:"Nokia N9",userAgent:"Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13",screen:{width:480,height:854},viewport:{width:480,height:854},deviceScaleFactor:1,isMobile:!0,hasTouch:!0,defaultBrowserType:"webkit"},"Pixel 2":{name:"Pixel 2",userAgent:"Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:411,height:731},viewport:{width:411,height:731},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 2 XL":{name:"Pixel 2 XL",userAgent:"Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:411,height:823},viewport:{width:411,height:823},deviceScaleFactor:3.5,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 3":{name:"Pixel 3",userAgent:"Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:393,height:786},viewport:{width:393,height:786},deviceScaleFactor:2.75,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 4":{name:"Pixel 4",userAgent:"Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:353,height:745},viewport:{width:353,height:745},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 4a (5G)":{name:"Pixel 4a (5G)",userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:892},viewport:{width:412,height:765},deviceScaleFactor:2.63,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 5":{name:"Pixel 5",userAgent:"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:393,height:851},viewport:{width:393,height:727},deviceScaleFactor:2.75,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Pixel 7":{name:"Pixel 7",userAgent:"Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:412,height:915},viewport:{width:412,height:839},deviceScaleFactor:2.625,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Moto G4":{name:"Moto G4",userAgent:"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Mobile Safari/537.36",screen:{width:360,height:640},viewport:{width:360,height:640},deviceScaleFactor:3,isMobile:!0,hasTouch:!0,defaultBrowserType:"chromium"},"Desktop Chrome HiDPI":{name:"Desktop Chrome HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Edge HiDPI":{name:"Desktop Edge HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Firefox HiDPI":{name:"Desktop Firefox HiDPI",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0.1) Gecko/20100101 Firefox/142.0.1",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"firefox"},"Desktop Safari":{name:"Desktop Safari",userAgent:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15",screen:{width:1792,height:1120},viewport:{width:1280,height:720},deviceScaleFactor:2,isMobile:!1,hasTouch:!1,defaultBrowserType:"webkit"},"Desktop Chrome":{name:"Desktop Chrome",displayName:"Playwright Chromium",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Chrome Medium Resolution":{name:"Desktop Chrome Medium Resolution",displayName:"Playwright Chromium",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Chrome (Branded)":{name:"Desktop Chrome (Branded)",displayName:"Google Chrome",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"chrome"},"Desktop Chrome Medium Resolution (Branded)":{name:"Desktop Chrome Medium Resolution (Branded)",displayName:"Google Chrome",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"chrome"},"Desktop Edge":{name:"Desktop Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1920,height:1080},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium"},"Desktop Edge (Branded)":{name:"Desktop Edge (Branded)",displayName:"Microsoft Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1920,height:1080},viewport:{width:1920,height:1080},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"msedge"},"Desktop Edge Medium Resolution (Branded)":{name:"Desktop Edge Medium Resolution (Branded)",displayName:"Microsoft Edge",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.7390.16 Safari/537.36 Edg/141.0.7390.16",screen:{width:1280,height:720},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"chromium",channel:"msedge"},"Desktop Firefox":{name:"Desktop Firefox",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0.1) Gecko/20100101 Firefox/142.0.1",screen:{width:1920,height:1080},viewport:{width:1280,height:720},deviceScaleFactor:1,isMobile:!1,hasTouch:!1,defaultBrowserType:"firefox"}},RD={desktop:["Desktop Chrome","Desktop Chrome Medium Resolution","Desktop Chrome (Branded)","Desktop Chrome Medium Resolution (Branded)","Desktop Edge (Branded)","Desktop Edge Medium Resolution (Branded)","Desktop Safari"],mobile:["iPhone 15 Pro Max","iPhone 15 Pro","iPhone 15 Plus","iPhone 15","iPhone 14 Pro Max","iPhone 14 Pro","iPhone 14 Plus","iPhone 14","iPhone 13 Pro Max","iPhone 13 Pro","iPhone 13","iPhone 13 Mini","iPhone 12 Pro Max","iPhone 12 Pro","iPhone 12","iPhone 12 Mini","iPhone 11 Pro Max","iPhone 11 Pro","iPhone 11","iPhone XR","iPhone X","iPhone SE (3rd gen)","iPhone SE","iPhone 8 Plus","iPhone 8","iPhone 7 Plus","iPhone 7","iPhone 6 Plus","iPhone 6","Galaxy S24","Galaxy A55","Galaxy S9+","Galaxy S8","Galaxy S5","Galaxy Note 3","Galaxy Note II","Galaxy S III","Pixel 7","Pixel 5","Pixel 4a (5G)","Pixel 4","Pixel 3","Pixel 2 XL","Pixel 2","Nexus 6P","Nexus 6","Nexus 5X","Nexus 5","Nexus 4","Moto G4","LG Optimus L70","Microsoft Lumia 950","Microsoft Lumia 550","Nokia Lumia 520","Nokia N9","BlackBerry Z30"]},Dd=(e,t=!1)=>{let r=["chromium"];return t&&r.push("webkit"),RD[e].map(n=>DD[n]).filter(n=>n.defaultBrowserType&&r.includes(n.defaultBrowserType))},Mte={desktop:{label:"Desktop",type:"desktop",devices:Dd("desktop")},mobile:{label:"Mobile Web",type:"mobile",devices:Dd("mobile")}},Fte={desktop:{label:"Desktop",type:"desktop",devices:Dd("desktop",!0)},mobile:{label:"Mobile Web",type:"mobile",devices:Dd("mobile",!0)}}});import{v4 as Uye}from"uuid";var MD=mt(()=>{"use strict"});import{z as ze}from"zod";var FD,o_,BD,Pc,Rd,$D,jD,In,UD,sm,Qo,a_=mt(()=>{"use strict";FD=ze.enum(["JS_CODE","AI_MODE"]),o_=ze.object({type:FD,expression:ze.string()}),BD=ze.enum(["DRAFT","STEP","ACTION","IF_ELSE","WHILE_LOOP"]),Pc=ze.object({uid:ze.string(),type:BD,comment:ze.string().optional()}),Rd=ze.object({action_data:ze.object({action_name:ze.string(),kwargs:ze.record(ze.any()).optional(),args:ze.array(ze.any()).optional()}),action_description:ze.string().optional(),url:ze.string().optional(),xpath:ze.string().nullable().optional(),locator:ze.string().nullable().optional(),css_selector:ze.string().nullable().optional(),unique_selector:ze.string().nullable().optional(),element_index:ze.number().nullable().optional(),frame_path:ze.array(ze.any()).optional(),artifacts:ze.record(ze.any()).optional(),feedback:ze.string().optional(),original_browser_use_action:ze.any().optional()}).passthrough(),$D=Pc.extend({type:ze.literal("DRAFT"),description:ze.string()}),jD=Pc.extend({type:ze.literal("ACTION"),description:ze.string(),action_entity:Rd.optional(),locator:ze.string().optional(),use_pure_vision:ze.boolean().optional()}),In=ze.lazy(()=>ze.union([$D,jD,Pc.extend({type:ze.literal("STEP"),description:ze.string().optional().default(""),statements:ze.array(In),reference_id:ze.number().optional(),template_path:ze.string().optional(),template_params:ze.record(ze.string()).optional()}),Pc.extend({type:ze.literal("IF_ELSE"),description:ze.string().optional(),condition:o_,then:ze.array(In),else:ze.array(In).optional()}),Pc.extend({type:ze.literal("WHILE_LOOP"),description:ze.string().optional(),condition:o_,body:ze.array(In),timeout_ms:ze.number().optional()})])),UD=ze.object({name:ze.string(),statements:ze.array(In),teardown:ze.array(In).optional(),skip:ze.union([ze.boolean(),ze.string()]).optional(),timeout:ze.number().optional(),fail:ze.union([ze.boolean(),ze.string()]).optional(),only:ze.boolean().optional(),slow:ze.boolean().optional()}),sm=ze.object({tests:ze.array(UD).min(1),beforeAll:ze.array(In).optional(),afterAll:ze.array(In).optional(),beforeEach:ze.array(In).optional(),afterEach:ze.array(In).optional()}),Qo=ze.object({comment:ze.string().optional(),version:ze.string().optional(),goal:ze.string().optional(),url:ze.string().optional(),baseURL:ze.string().optional(),final_feedback:ze.string().optional(),completed:ze.boolean().optional(),success:ze.boolean().optional(),statements:ze.array(In).optional(),teardown:ze.array(In).optional(),last_modified_at:ze.string().optional(),testGroup:sm.optional()}).refine(e=>e.testGroup!==void 0?e.goal===void 0&&(e.statements===void 0||e.statements.length===0):e.goal!==void 0,{message:"TestFlow must have either goal/statements (single test) or testGroup (suite), not both"})});import{stringify as Bte,parse as WD,parseAllDocuments as zye,parseDocument as $te,Document as jte,isMap as Nc,isSeq as ts}from"yaml";import{v4 as es}from"uuid";function om(e,t){let r={...t?.test_case_id!==void 0?{test_case_id:t.test_case_id}:{},...t?.name?{name:t.name}:{},goal:e.goal??"",url:e.url,base_url:e.baseURL,...t?.timeout!==void 0?{timeout:t.timeout}:{},...t?.settings&&Object.keys(t.settings).length>0?{settings:t.settings}:{},statements:(e.statements??[]).map(Ei)};return e.final_feedback&&(r.final_feedback=e.final_feedback),e.teardown&&e.teardown.length>0&&(r.teardown=e.teardown.map(Ei)),r}function rl(e,t){if(e.testGroup)return zD(e,t);let r=om(e,t),n=new jte(r);return e.comment&&(n.commentBefore=e.comment),HD(n,e.statements??[]),e.teardown&&HD(n,e.teardown,"teardown"),n.toString(VD)}function HD(e,t,r="statements"){let n=e.contents;if(!n||!Nc(n))return;let i=n.get(r,!0);ts(i)&&Ld(i,t)}function Ld(e,t){for(let r=0;r<Math.min(e.items.length,t.length);r++){let n=t[r],i=e.items[r];if(r>0&&(i.spaceBefore=!0),n.comment&&(r===0?e.commentBefore=n.comment:i.commentBefore=n.comment),Nc(i)){let s=i;if(n.type==="STEP"){let o=s.get("statements",!0);ts(o)&&Ld(o,n.statements)}else if(n.type==="IF_ELSE"){let o=s.get("THEN",!0);ts(o)&&Ld(o,n.then);let a=s.get("ELSE",!0);ts(a)&&n.else&&Ld(a,n.else)}else if(n.type==="WHILE_LOOP"){let o=s.get("DO",!0);ts(o)&&Ld(o,n.body)}}}}function zD(e,t){let r=e.testGroup;if(!r)throw new Error("suiteToYaml requires a TestFlow with testGroup");let n={};t?.test_case_id!==void 0&&(n.test_case_id=t.test_case_id),t?.name&&(n.name=t.name),t?.tags&&t.tags.length>0&&(n.tags=t.tags),t?.use&&Object.keys(t.use).length>0&&(n.use=t.use),t?.settings&&Object.keys(t.settings).length>0&&(n.settings=t.settings);let i={};return e.baseURL&&(i.base_url=e.baseURL),r.beforeAll&&r.beforeAll.length>0&&(i.beforeAll=r.beforeAll.map(Ei)),r.beforeEach&&r.beforeEach.length>0&&(i.beforeEach=r.beforeEach.map(Ei)),r.afterEach&&r.afterEach.length>0&&(i.afterEach=r.afterEach.map(Ei)),r.afterAll&&r.afterAll.length>0&&(i.afterAll=r.afterAll.map(Ei)),i.tests=r.tests.map(s=>{let o={name:s.name};return s.skip!==void 0&&(o.skip=s.skip),s.timeout!==void 0&&(o.timeout=s.timeout),s.fail!==void 0&&(o.fail=s.fail),s.only!==void 0&&(o.only=s.only),s.slow!==void 0&&(o.slow=s.slow),o.statements=s.statements.map(Ei),s.teardown&&s.teardown.length>0&&(o.teardown=s.teardown.map(Ei)),o}),n.suite=i,Bte(n,VD)}function Ei(e){switch(e.type){case"DRAFT":return Ute(e);case"ACTION":return Hte(e);case"STEP":return qte(e);case"IF_ELSE":return Gte(e);case"WHILE_LOOP":return Wte(e)}}function Ute(e){return{intent:e.description}}function Hte(e){let t=e.action_entity?.action_data?.action_name??e.action_entity?.action?.action_name,r=e.action_entity?.action_data?.kwargs??e.action_entity?.action?.kwargs;if(t==="verify"){let a=r?.statement;if(typeof a=="string"&&!e.action_entity?.locator&&!e.action_entity?.xpath){let l=r?.code;return typeof l=="string"?{VERIFY:a,js:l}:{VERIFY:a}}}if(t==="go_to_url"){let a=r?.url;if(typeof a=="string"&&!e.action_entity?.locator&&!e.action_entity?.xpath){let l={URL:a};return r?.new_tab===!0&&(l.new_tab=!0),typeof r?.timeout_seconds=="number"&&(l.timeout_seconds=r.timeout_seconds),l}}if(t==="js_action"){let a=r?.code;if(typeof a=="string"&&e.description)return{intent:e.description,js:a}}if(t==="ai_wait_until"){let a=r?.condition;if(typeof a=="string"){let l={WAIT_UNTIL:a};return typeof r?.timeout_seconds=="number"&&r.timeout_seconds!==60&&(l.timeout_seconds=r.timeout_seconds),l}}if(t==="wait"){let a=r?.seconds,u={WAIT:e.description||`Wait ${a}s`};return typeof a=="number"&&(u.seconds=a),u}if(t==="js_code"){let a=r?.code;if(typeof a=="string"&&!e.action_entity?.locator&&!e.action_entity?.xpath)return{CODE:a}}if(!e.action_entity)return{intent:e.description};let n=e.action_entity.action_data??e.action_entity.action;if(!n)return{intent:e.description};let i={intent:e.description,action:n.action_name},s=e.locator??e.action_entity.locator;s&&(i.locator=s);let o=e.action_entity.xpath;if(o&&(i.xpath=o),e.use_pure_vision&&(i.use_pure_vision=!0),n.kwargs&&Object.keys(n.kwargs).length>0)for(let[a,l]of Object.entries(n.kwargs))i[a]=l;return n.args&&n.args.length>0&&(i.args=n.args),i}function qte(e){if(e.template_path){let r={template:e.template_path};return e.template_params&&Object.keys(e.template_params).length>0&&(r.params=e.template_params),r}let t={STEP:e.description,statements:e.statements.map(Ei)};return e.reference_id!==void 0&&(t.reference_id=e.reference_id),t}function Gte(e){let t={IF:KD(e.condition),THEN:e.then.map(Ei)};return e.else&&e.else.length>0&&(t.ELSE=e.else.map(Ei)),t}function Wte(e){let t={WHILE:KD(e.condition),DO:e.body.map(Ei)};return e.timeout_ms!==void 0&&(t.timeout_ms=e.timeout_ms),t}function KD(e){return e.type==="JS_CODE"?`js:${e.expression}`:e.expression}function am(e){try{let t=WD(e);if(!t||typeof t!="object")return{};let r={};return typeof t.test_case_id=="number"&&Number.isFinite(t.test_case_id)&&(r.test_case_id=t.test_case_id),typeof t.template_id=="number"&&Number.isFinite(t.template_id)&&(r.template_id=t.template_id),typeof t.name=="string"&&t.name.trim()&&(r.name=t.name.trim()),typeof t.timeout=="number"&&Number.isFinite(t.timeout)&&(r.timeout=t.timeout),t.settings&&typeof t.settings=="object"&&!Array.isArray(t.settings)&&(r.settings=t.settings),r}catch{return{}}}function l_(e){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(l_);let t=e,r=Object.keys(t);if(r.length===1){let i=r[0];if(i.startsWith("{ ")&&i.endsWith(" }")&&t[i]===null)return`{{${i.slice(2,-2)}}}`}let n={};for(let[i,s]of Object.entries(t))n[i]=l_(s);return n}function $n(e){if(e.length>qD)throw new Error(`YAML input too large (${e.length} bytes, max ${qD})`);let t=l_(WD(e));if(!t||typeof t!="object")throw new Error("Invalid YAML: expected an object at root level");if(t.suite)return Vte(t);let r={version:"1.3.0",goal:t.goal,url:t.url,baseURL:t.base_url,statements:Si(t.statements??[])};t.final_feedback&&(r.final_feedback=t.final_feedback),t.teardown&&Array.isArray(t.teardown)&&(r.teardown=Si(t.teardown));let n=Qo.safeParse(r);if(!n.success)throw new Error(`Invalid TestFlow after YAML conversion: ${JSON.stringify(n.error.errors)}`);let i=n.data;return YD(e,i),i}function Vte(e){let t=e.suite;if(!t||typeof t!="object")throw new Error("Invalid suite: expected an object");let r=t.tests;if(!Array.isArray(r)||r.length===0)throw new Error('Suite must have a non-empty "tests" array');let i={tests:r.map(a=>{if(!a.name)throw new Error('Each test in a suite must have a "name" field');if(!Array.isArray(a.statements)||a.statements.length===0)throw new Error(`Suite test "${a.name}" must have a non-empty "statements" array`);let l={name:a.name,statements:Si(a.statements)};return Array.isArray(a.teardown)&&a.teardown.length>0&&(l.teardown=Si(a.teardown)),a.skip!==void 0&&(l.skip=a.skip),typeof a.timeout=="number"&&(l.timeout=a.timeout),a.fail!==void 0&&(l.fail=a.fail),a.only===!0&&(l.only=!0),a.slow===!0&&(l.slow=!0),l})};Array.isArray(t.beforeAll)&&t.beforeAll.length>0&&(i.beforeAll=Si(t.beforeAll)),Array.isArray(t.afterAll)&&t.afterAll.length>0&&(i.afterAll=Si(t.afterAll)),Array.isArray(t.beforeEach)&&t.beforeEach.length>0&&(i.beforeEach=Si(t.beforeEach)),Array.isArray(t.afterEach)&&t.afterEach.length>0&&(i.afterEach=Si(t.afterEach));let s=sm.safeParse(i);if(!s.success)throw new Error(`Invalid TestGroup: ${JSON.stringify(s.error.errors)}`);return{version:"1.3.0",baseURL:t.base_url||void 0,testGroup:s.data}}function Si(e){if(!Array.isArray(e))throw new Error("Expected an array of statements");return e.map(zte)}function zte(e){if(typeof e=="string")throw new Error(`Plain string statements are not supported. Use an object with a "desc" key instead. Example: { "desc": "${e}" }`);if(typeof e!="object"||e===null)throw new Error(`Invalid statement: expected object, got ${typeof e}`);let t=e;if("IF"in t)return Kte(t);if("WHILE"in t)return Jte(t);if("STEP"in t)return Yte(t);if("VERIFY"in t){let r=t.VERIFY,n={statement:typeof r=="string"?r:String(r)};return typeof t.js=="string"&&(n.code=t.js),{uid:es(),type:"ACTION",description:String(r),action_entity:{action_description:String(r),action_data:{action_name:"verify",kwargs:n}}}}if("URL"in t){let r=t.URL,n=t.new_tab===!0?!0:void 0,i=typeof t.timeout_seconds=="number"?t.timeout_seconds:void 0,s={url:typeof r=="string"?r:String(r)};return n&&(s.new_tab=!0),i!==void 0&&(s.timeout_seconds=i),{uid:es(),type:"ACTION",description:`Navigate to ${r}`,action_entity:{action_description:`Navigate to ${r}`,action_data:{action_name:"go_to_url",kwargs:s}}}}if("WAIT_UNTIL"in t){let r=t.WAIT_UNTIL,n=typeof t.timeout_seconds=="number"?t.timeout_seconds:60;return{uid:es(),type:"ACTION",description:`Wait until: ${r}`,action_entity:{action_description:`Wait until: ${r}`,action_data:{action_name:"ai_wait_until",kwargs:{condition:typeof r=="string"?r:String(r),timeout_seconds:n}}}}}if("WAIT"in t){let r=t.WAIT,n=typeof t.seconds=="number"?t.seconds:3;return{uid:es(),type:"ACTION",description:typeof r=="string"?r:`Wait ${n}s`,action_entity:{action_description:typeof r=="string"?r:`Wait ${n}s`,action_data:{action_name:"wait",kwargs:{seconds:n}}}}}if("CODE"in t){let r=t.CODE;if(r==null)throw new Error('CODE statement has no code. Use "CODE: |" followed by indented code on the next line.');return{uid:es(),type:"ACTION",description:"Code block",action_entity:{action_description:"Code block",action_data:{action_name:"js_code",kwargs:{code:typeof r=="string"?r:String(r)}}}}}if("js"in t&&("intent"in t||"desc"in t)&&!("VERIFY"in t)&&t.action!=="verify"){let r=t.js,n=typeof t.intent=="string"?t.intent:typeof t.desc=="string"?t.desc:"";return{uid:es(),type:"ACTION",description:n,action_entity:{action_description:n,action_data:{action_name:"js_action",kwargs:{code:typeof r=="string"?r:String(r)}}}}}if("call"in t&&typeof t.call=="string"){let{call:r,...n}=t;return GD({...n,action:"function",functionName:r})}if("action"in t)return GD(t);if("intent"in t&&typeof t.intent=="string"||"desc"in t&&typeof t.desc=="string")return{uid:es(),type:"DRAFT",description:typeof t.intent=="string"?t.intent:t.desc};throw new Error(`Cannot infer statement type from object: ${JSON.stringify(t)}`)}function JD(e){if(typeof e!="string")throw new Error(`Condition must be a string, got ${typeof e}`);return e.startsWith("js:")?{type:"JS_CODE",expression:e.slice(3)}:{type:"AI_MODE",expression:e}}function Kte(e){let t=JD(e.IF),r=e.THEN;if(!Array.isArray(r))throw new Error("IF_ELSE requires a THEN array");let n={uid:es(),type:"IF_ELSE",condition:t,then:Si(r)};return"ELSE"in e&&Array.isArray(e.ELSE)&&(n.else=Si(e.ELSE)),n}function Jte(e){let t=JD(e.WHILE),r=e.DO;if(!Array.isArray(r))throw new Error("WHILE_LOOP requires a DO array");let n={uid:es(),type:"WHILE_LOOP",condition:t,body:Si(r)};return typeof e.timeout_ms=="number"&&(n.timeout_ms=e.timeout_ms),n}function Yte(e){let t=typeof e.STEP=="string"?e.STEP:"";if(!Array.isArray(e.statements))throw new Error("STEP requires a statements array");let r={uid:es(),type:"STEP",description:t,statements:Si(e.statements)};if(typeof e.reference_id=="number"&&(r.reference_id=e.reference_id),typeof e.template_path=="string"&&(r.template_path=e.template_path),e.template_params&&typeof e.template_params=="object"&&!Array.isArray(e.template_params)){let n=e.template_params,i={};for(let[s,o]of Object.entries(n))i[s]=String(o);r.template_params=i}return r}function GD(e){let t=typeof e.action=="string"?e.action:String(e.action),r=typeof e.intent=="string"?e.intent:typeof e.desc=="string"?e.desc:"",n=typeof e.locator=="string"?e.locator:void 0,i=typeof e.xpath=="string"?e.xpath:void 0,s=typeof e.use_pure_vision=="boolean"?e.use_pure_vision:void 0,o={};for(let[u,d]of Object.entries(e))Xte.has(u)||(o[u]=d);t==="verify"&&typeof o.js=="string"&&(o.code=o.js,delete o.js);let a={action_description:r,action_data:{action_name:t,kwargs:Object.keys(o).length>0?o:{}}};n&&(a.locator=n),i&&(a.xpath=i);let l={uid:es(),type:"ACTION",description:r,action_entity:a};return s&&(l.use_pure_vision=!0),l}function YD(e,t){let r;try{r=$te(e)}catch{return}let n=r.contents;if(!n||!Nc(n))return;if(r.commentBefore)t.comment=r.commentBefore;else{let l=n.items?.[0];l?.key&&l.key.commentBefore&&(t.comment=l.key.commentBefore)}let i=n,s=i.get("statements",!0);ts(s)&&t.statements&&Oc(s,t.statements);let o=i.get("teardown",!0);ts(o)&&t.teardown&&Oc(o,t.teardown)}function Oc(e,t){e.commentBefore&&t.length>0&&(t[0].comment=e.commentBefore);for(let r=0;r<Math.min(e.items.length,t.length);r++){let n=e.items[r];n.commentBefore&&!(r===0&&e.commentBefore)&&(t[r].comment=n.commentBefore);let i=t[r];if(i.type==="STEP"&&Nc(n)){let s=n.get("statements",!0);ts(s)&&Oc(s,i.statements)}else if(i.type==="IF_ELSE"&&Nc(n)){let s=n.get("THEN",!0);ts(s)&&Oc(s,i.then);let o=n.get("ELSE",!0);ts(o)&&i.else&&Oc(o,i.else)}else if(i.type==="WHILE_LOOP"&&Nc(n)){let s=n.get("DO",!0);ts(s)&&Oc(s,i.body)}}}var VD,qD,Xte,lm=mt(()=>{"use strict";a_();VD={lineWidth:120,defaultKeyType:"PLAIN",defaultStringType:"PLAIN"};qD=1024*1024;Xte=new Set(["action","intent","desc","locator","xpath","use_pure_vision"])});import{parse as Zye,stringify as Qye}from"yaml";var XD=mt(()=>{"use strict";lm()});var c_,ea,cm=mt(()=>{"use strict";c_=e=>{let t=[];switch(e.type){case"STEP":e.statements&&t.push({key:"statements",statements:e.statements});break;case"IF_ELSE":e.then&&t.push({key:"then",statements:e.then}),e.else&&t.push({key:"else",statements:e.else});break;case"WHILE_LOOP":e.body&&t.push({key:"body",statements:e.body});break}return t},ea=e=>{let t=[],r=n=>{for(let i of n){t.push(i);let s=c_(i);for(let o of s)r(o.statements)}};return r(e),t}});function um(e){let t=0,r=0;for(let n of e)if(n.type==="DRAFT")r++;else if(n.type==="ACTION"){let i=n.action_entity?.action_data?.action_name??"";tR.has(i)||t++}return{action:t,draft:r}}function Qte(e){try{return new Function(`return async function() { ${e} }`),null}catch(t){return t.message}}function eR(e){try{return new Function(`return async function() { return (${e}) }`),null}catch(t){return t.message}}function ere(e){let t=e.split(/\r?\n/).map(s=>s.trim()).filter(s=>s.length>0&&!s.startsWith("//")),r=t.length,n=t.join(`
|
|
4853
|
+
`).match(/\bawait\b/g),i=n?n.length:0;return r<=ZD&&i<=QD?null:`${r} non-blank line(s), ${i} await(s) \u2014 limits are ${ZD} lines and ${QD} awaits. The js: field is a cache for one natural-language intent, not a place for multi-step logic. Break this into multiple statements \u2014 one VERIFY or intent+js per UI interaction or assertion \u2014 so each step is visible in the debugger and self-healable.`}function u_(e,t){let r=t?.coverageThreshold??Zte,n=[],i=[],s;try{s=$n(e)}catch(h){return{valid:!1,errors:[`Invalid YAML: ${h.message}`],warnings:[],stats:{total:0,action:0,draft:0,coverage:0}}}s.goal||n.push('Missing required field: "goal"'),s.statements?.length||n.push('Missing required field: "statements"');let o=[...ea(s.statements??[]),...s.teardown?ea(s.teardown):[]],{action:a,draft:l}=um(o),u="Hint: in YAML double-quoted strings, backslashes are escape characters \u2014 use \\\\/ instead of \\/ for regex, or use single quotes.";for(let h of o){let m=h;if(m.reference_id!==void 0){let y=m.description||h.uid;n.push(`Unresolved cloud template reference on statement "${y}" (reference_id: ${m.reference_id}). Local YAML tests cannot use reference_id \u2014 inline the template statements or use the local "template:" key instead.`)}if(h.type==="ACTION"){let y=h,b=y.action_entity?.action_data?.action_name??"";if(b==="js_code"||b==="js_action"||b==="verify"||b==="ai_assert"){let w=y.action_entity?.action_data?.kwargs?.code;if(typeof w=="string"){let E=Qte(w);if(E){let x=y.description||b;n.push(`Invalid JS in "${x}": ${E}. ${u}`)}else if(b==="verify"||b==="js_action"){let x=ere(w);if(x){let C=y.description||b;n.push(`JS cache for "${C}" is too complex: ${x}`)}}}}}if(h.type==="IF_ELSE"){let y=h;if(y.condition.type==="JS_CODE"){let b=eR(y.condition.expression);b&&n.push(`Invalid JS in IF condition "${y.condition.expression}": ${b}. ${u}`)}}if(h.type==="WHILE_LOOP"){let y=h;if(y.condition.type==="JS_CODE"){let b=eR(y.condition.expression);b&&n.push(`Invalid JS in WHILE condition "${y.condition.expression}": ${b}. ${u}`)}}}let d=a+l,p=d>0?Math.round(a/d*100):0;return d>0&&p/100<r&&i.push(`Low action coverage: ${a}/${d} statements (${p}%) are enriched with action/js. ${l} draft statement(s) still need enrichment. Use MCP tools (act, get_locators) to convert drafts to actions.`),{valid:n.length===0,errors:n,warnings:i,stats:{total:d,action:a,draft:l,coverage:p}}}var Zte,ZD,QD,tR,rR=mt(()=>{"use strict";lm();cm();Zte=.5,ZD=5,QD=3,tR=new Set(["verify","ai_assert","done","go_to_url","ai_wait_until","wait","js_code"])});var nR=mt(()=>{"use strict";cm()});var rs,Md,iR=mt(()=>{"use strict";rs=(e=>(e.DRAFT="DRAFT",e.STEP="STEP",e.ACTION="ACTION",e.IF_ELSE="IF_ELSE",e.WHILE_LOOP="WHILE_LOOP",e))(rs||{}),Md=18e4});var Fd,oR=mt(()=>{"use strict";Fd=class sR{data={};sensitive=new Set;get(t){return this.data[t]}set(t,r,n=!1){this.data[t]=r,n?this.sensitive.add(t):this.sensitive.has(t)&&this.sensitive.delete(t)}getAll(){return{...this.data}}isSensitive(t){return this.sensitive.has(t)}getAllSensitiveKeys(){return new Set(this.sensitive)}delete(t){return this.sensitive.delete(t),delete this.data[t]}clear(){this.data={},this.sensitive.clear()}has(t){return t in this.data}get size(){return Object.keys(this.data).length}merge(t){for(let[r,n]of Object.entries(t.getAll()))this.set(r,n,t.isSensitive(r))}toJSON(){return{data:{...this.data},sensitiveKeys:Array.from(this.sensitive)}}static fromJSON(t){let r=new sR;if(t.data){let n=new Set(t.sensitiveKeys||[]);for(let[i,s]of Object.entries(t.data))r.set(i,s,n.has(i))}return r}}});var aR=mt(()=>{"use strict"});var lR=mt(()=>{"use strict"});var cR=mt(()=>{"use strict";im()});var ns=mt(()=>{"use strict";CD();kD();ID();PD();OD();LD();MD();XD();rR();lm();a_();nR();cm();iR();oR();aR();lR();cR();im()});var uR={};Li(uR,{connectBrowser:()=>tm,forceDisconnect:()=>AD,getCacheStatus:()=>TD});var dR=mt(()=>{"use strict";rm()});import qt from"fs";import nre from"net";import ire from"os";import Bt from"path";import mR from"crypto";import are from"axios";import lre from"node:http";import Bd,{WebSocketServer as pR}from"ws";import Dc from"node:fs";import hR from"node:path";import ure from"node:os";async function sre(e){return new Promise(t=>{let r=nre.createServer();r.once("error",()=>t(!1)),r.once("listening",()=>r.close(()=>t(!0))),r.listen(e,"127.0.0.1")})}function ore(){let t=new Date().toISOString().replace(/T/,"-").replace(/:/g,"-").replace(/\..+/,""),r=mR.randomBytes(2).toString("hex");return`${t}-${r}`}var gR,dm,un,cre,yR,ai,dre,fR,pre,hre,bR,wR=mt(()=>{"use strict";rm();nm();Yn();ns();gR=class{sessions=new Map;browserManager=null;baseDebugPort=9222;runDir;onBeforeAction;constructor(e={}){this.runDir=e.runDir||Bt.join(ire.homedir(),".shiplight/inspect"),this.onBeforeAction=e.onBeforeAction,qt.mkdirSync(this.runDir,{recursive:!0})}async findAvailablePort(){for(let e=this.baseDebugPort;e<this.baseDebugPort+100;e++)if(await sre(e))return e;throw new Error(`No available debug ports found in range ${this.baseDebugPort}\u2013${this.baseDebugPort+99}`)}ensureBrowserManager(){this.browserManager||(this.browserManager=new Qw({testDir:this.runDir}))}async createSession(e){this.ensureBrowserManager();let t=ore(),r=await this.findAvailablePort(),n=e.browserOptions||{},i,s;if(n.pathToExtension&&!qt.existsSync(n.pathToExtension))throw new Error(`Extension directory not found: ${n.pathToExtension}`);try{i=await this.browserManager.launchBrowser({debugPort:r,viewport:n.viewport,isMobile:n.isMobile,hasTouch:n.hasTouch,userAgent:n.userAgent,colorScheme:n.colorScheme,timezoneId:n.timezoneId,geolocation:n.geolocation,headless:n.headless,disableSecurity:n.disableSecurity,recordVideo:n.recordEvidence,locale:n.locale,proxy:n.proxy,localStorageStatePath:n.storageStatePath,extensionPath:n.pathToExtension,userDataDir:n.userDataDir});let o=i.context.pages();s=o.find(l=>!l.url().startsWith("chrome-extension://"))??o[0]??await i.context.newPage(),e.startingUrl&&e.startingUrl!=="about:blank"&&await s.goto(e.startingUrl,{waitUntil:"domcontentloaded"});let a=await this.createSessionData(t,s,i.context,e.webAgentConfig,e.maxActions,i);return a.recordEvidence=n.recordEvidence??!1,n.recordEvidence&&await i.context.tracing.start({screenshots:!0,snapshots:!0,sources:!1}),this.sessions.set(t,a),{sessionId:t,url:s.url()}}catch(o){throw s&&await s.close().catch(()=>{}),i&&this.browserManager&&await this.browserManager.terminateBrowser(i).catch(()=>{}),te.info("[SessionManager.createSession] Failed:",o),o}}async createSessionWithPage(e,t={}){let r=this.generateSessionId(),n=t.runDir||this.runDir;n!==this.runDir&&qt.mkdirSync(n,{recursive:!0});let i=await this.createSessionData(r,e,e.context(),t.webAgentConfig,t.maxActions,void 0);return this.sessions.set(r,i),{sessionId:r}}async createRelaySession(e){let t=this.generateSessionId();try{let n=(await tm(e)).contexts()[0];if(!n)throw new Error("No browser context available after CDP connection");let s=n.pages()[0]||null,o=new Fd,a=Nd({variableStore:o,executionHistory:[],testDataDir:Bt.join(this.runDir,"files")}),l=new tl(a);l.agentServices.setupPageTracking(n);let u={sessionId:t,sessionType:"relay",page:s,webAgent:l,agentContext:a,variableStore:o,consoleLogs:[],networkLogs:[],actionLog:[],createdAt:new Date,lastAccessedAt:new Date,abortController:new AbortController,totalActions:0,relayConnection:{cdpUrl:e,connectedAt:new Date}};return this.sessions.set(t,u),{sessionId:t}}catch(r){throw te.error("[createRelaySession] FAILED:",r),r}}generateSessionId(){let e=new Date,t=e.toISOString().slice(0,10),r=e.toTimeString().slice(0,8).replace(/:/g,"-"),n=Math.random().toString(36).substring(2,6);return`${t}_${r}_${n}`}async createSessionData(e,t,r,n,i,s){let o=[];t.on("console",p=>{o.push({type:p.type(),text:p.text(),timestamp:Date.now()})});let a=[];t.on("response",p=>{a.push({url:p.url(),method:p.request().method(),status:p.status(),timestamp:Date.now()})});let l=n?.variableStore??new Fd,u=Nd({model:n?.model,variableStore:l,executionHistory:[],testDataDir:n?.testDataDir||Bt.join(this.runDir,"files"),downloadDir:n?.downloadDir,organizationId:n?.organizationId,organizationSettings:n?.organizationSettings}),d=new tl(u);return d.agentServices.setupPageTracking(r),n?.testDataDownloader&&d.agentServices.setTestDataDownloader(n.testDataDownloader,n.testDataFileNames),n?.knowledgeRetriever&&d.agentServices.setKnowledgeRetriever(n.knowledgeRetriever),{sessionId:e,sessionType:"playwright",browserInstance:s,page:t,webAgent:d,agentContext:u,variableStore:l,consoleLogs:o,networkLogs:a,createdAt:new Date,lastAccessedAt:new Date,actionLog:[],abortController:new AbortController,maxActions:i,totalActions:0}}async closeSession(e){let t=this.sessions.get(e);if(!t)return{};if(t.sessionType==="relay")return{};t.page.removeAllListeners("console"),t.page.removeAllListeners("response");let r=null;try{r=t.recordEvidence&&t.browserInstance?t.page.video():null}catch{}let n;if(t.recordEvidence&&t.browserInstance)try{n=Bt.join(this.runDir,"traces",`${e}.zip`),qt.mkdirSync(Bt.dirname(n),{recursive:!0}),await t.browserInstance.context.tracing.stop({path:n}),qt.existsSync(n)||(te.warn("[SessionManager.closeSession] Trace file not created at expected path:",n),n=void 0),t.tracePath=n}catch(a){te.warn("[SessionManager.closeSession] Failed to stop trace:",a),n=void 0}t.browserInstance&&this.browserManager&&await this.browserManager.terminateBrowser(t.browserInstance),await this.persistReportSnapshot(e,t,{logPrefix:"[SessionManager.closeSession]"}),this.sessions.delete(e);let i;if(r)try{i=await r.path()??void 0}catch(a){te.info("[SessionManager.closeSession] Failed to retrieve video path:",a)}let s=Bt.join(this.runDir,e,"report-data.json"),o=qt.existsSync(s);return{...i?{videoPath:i}:{},...n?{tracePath:n}:{},...o?{reportDataPath:s}:{},reportDataSaved:o}}async closeAllSessions(){let e=Array.from(this.sessions.keys());for(let t of e)await this.closeSession(t)}getSessionCount(){return this.sessions.size}async forceDisconnectRelay(){let{forceDisconnect:e}=await Promise.resolve().then(()=>(dR(),uR));e()}getSession(e){let t=this.sessions.get(e);return t?(t.lastAccessedAt=new Date,{sessionId:t.sessionId,sessionType:t.sessionType==="relay"?"relay":"browser",createdAt:t.createdAt,lastAccessedAt:t.lastAccessedAt,currentUrl:this.getPageForSession(t).url(),relayConnection:t.relayConnection}):null}getAllSessions(){return Array.from(this.sessions.values()).map(e=>({sessionId:e.sessionId,sessionType:e.sessionType==="relay"?"relay":"browser",createdAt:e.createdAt,lastAccessedAt:e.lastAccessedAt,currentUrl:this.getPageForSession(e).url(),relayConnection:e.relayConnection}))}getSessionData(e){return this.sessions.get(e)||null}getDebugPort(e){return this.sessions.get(e)?.browserInstance?.debugPort}getPage(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);return this.getPageForSession(t)}getPageForSession(e){let t=e.webAgent.agentServices.getCurrentPage();if(t&&!t.isClosed())return t;if(e.page)return e.webAgent.agentServices.validatePage(e.page);throw new Error("No pages available in this session. Attach a tab via the Chrome extension first.")}getWebAgent(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);return t.webAgent}getVariableStore(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);return t.variableStore}async getCurrentUrl(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);return this.getPageForSession(t).url()}async navigate(e,t){let r=this.sessions.get(e);if(!r)throw new Error(`Session ${e} not found`);await this.getPageForSession(r).goto(t,{waitUntil:"domcontentloaded"})}async loginWithTestAccount(e,t){let r=this.sessions.get(e);if(!r)throw new Error(`Session ${e} not found`);if(!t.loginConfig||!t.username||!t.password)return!1;try{let n=this.getPageForSession(r),i=t.loginConfig.account?.type,s={site_url:n.url(),account:{type:i,username:t.username,password:t.password,two_factor_auth_config:t.loginConfig.account?.two_factor_auth_config},additional_prompt:t.loginConfig.additional_prompt,verification_hint:t.loginConfig.verification_hint,num_verification_exprs:0};return(await r.webAgent.loginPage(n,s)).success}catch(n){return te.info("Login failed:",n),!1}}async getPageInfo(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);let r=this.getPageForSession(t);return{url:r.url(),title:await r.title()}}getSessionInfo(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);let r=t.sessionType==="relay"?"relay":"browser";return{sessionId:t.sessionId,sessionType:r,relayConnection:t.relayConnection}}async getExtendedPageInfo(e){let[t,r,n,i,s,o,a]=await Promise.all([Promise.resolve(e.url()),e.title(),e.evaluate(()=>window.scrollY),e.evaluate(()=>window.innerHeight),e.evaluate(()=>window.innerWidth),e.evaluate(()=>document.documentElement.scrollHeight),e.evaluate(()=>document.documentElement.scrollWidth)]),l=Math.floor(n),u=Math.floor(Math.max(0,o-(n+i)));return{url:t,title:r,viewportWidth:Math.floor(s),viewportHeight:Math.floor(i),pageWidth:Math.floor(a),pageHeight:Math.floor(o),scrollY:Math.floor(n),pixelsAbove:l,pixelsBelow:u}}async inspectPage(e){let t=this.sessions.get(e);if(!t)throw new Error(`Session ${e} not found`);let r=Bt.join(this.runDir,e);qt.mkdirSync(r,{recursive:!0});let n=Date.now(),i=this.getPageForSession(t),s=new ni,{domState:o,screenshot:a}=await s.getClickableElementsWithScreenshot(i),l=o.elementTree.clickableElementsToString(),u=await this.getExtendedPageInfo(i),d=Bt.join(r,`screenshot-${n}.png`);qt.writeFileSync(d,a),t.domState=o;let p=await this.buildRichDomText(l,u,t),h=Bt.join(r,`dom-${n}.txt`);return qt.writeFileSync(h,p),{screenshotPath:d,domText:p,domFilePath:h,currentUrl:i.url()}}async getDom(e,t=!0){let r=Ic(),n=r?performance.now():0,i=this.sessions.get(e);if(!i)throw new Error(`Session ${e} not found`);let s=Bt.join(this.runDir,e);qt.mkdirSync(s,{recursive:!0});let o=Date.now(),a=this.getPageForSession(i),l,u=r?performance.now():0;t&&(l=await a.screenshot({type:"png",fullPage:!1}));let d=r?performance.now()-u:0,p=1e4,h=r?performance.now():0,m=(async()=>{let K=new ni;return t?await K.getClickableElementsWithScreenshot(a):{domState:await K.getClickableElements(a,{highlightElements:!1}),screenshot:void 0}})(),y,b=new Promise((K,W)=>{y=setTimeout(()=>{let pe=a.url();W(new Error(`inspect_page timed out after ${p/1e3}s. Page: ${pe} \u2014 The page may be unresponsive or blocking CDP commands. Try navigating to a simpler page or reloading.`))},p)}),{domState:w,screenshot:E}=await Promise.race([m,b]);clearTimeout(y);let x=w.elementTree.clickableElementsToString(),C=r?performance.now()-h:0,R=r?performance.now():0,k=await this.getExtendedPageInfo(a),T=r?performance.now()-R:0;i.domState=w;let D=r?performance.now():0,O;E&&(O=Bt.join(s,`screenshot-${o}.png`),qt.writeFileSync(O,E));let I=await this.buildRichDomText(x,k,i),L=Bt.join(s,`dom-${o}.txt`);qt.writeFileSync(L,I);let F=r?performance.now()-D:0,U=a.url();if(t){let K="";try{K=await a.title()}catch{}this.savePageCacheArtifacts(U,K,I,l,E,w,a).catch(W=>{te.warn("[SessionManager] Failed to save page cache artifacts:",W)})}let z=r?performance.now()-n:0;return{domText:I,domFilePath:L,screenshotPath:O,currentUrl:U,...r&&{duration_ms:Math.round(z),timing:{screenshot_ms:Math.round(d),dom_extraction_ms:Math.round(C),page_info_ms:Math.round(T),file_write_ms:Math.round(F)}}}}async buildRichDomText(e,t,r){let n=t.pixelsAbove>0,i=t.pixelsBelow>0,s=t.viewportHeight>0?t.pixelsAbove/t.viewportHeight:0,o=t.viewportHeight>0?t.pixelsBelow/t.viewportHeight:0,a=t.viewportHeight>0?t.pageHeight/t.viewportHeight:0,l=t.pageHeight>t.viewportHeight?t.scrollY/Math.max(t.pageHeight-t.viewportHeight,1):0,u=`Page info: ${t.viewportWidth}x${t.viewportHeight}px viewport, ${t.pageWidth}x${t.pageHeight}px total page size, ${s.toFixed(1)} pages above, ${o.toFixed(1)} pages below, ${a.toFixed(1)} total pages, at ${Math.round(l*100)}% of page`,p=r.page.context().pages(),h=this.getPageForSession(r),m="";for(let b=0;b<p.length;b++){let w=p[b],E=w.url(),x=await w.title().catch(()=>""),C=w===h?" (current)":"";m+=`Tab ${b}: ${E} - ${x.slice(0,30)}${C}
|
|
4853
4854
|
`}e!==""?(n?e=`... ${t.pixelsAbove} pixels above (${s.toFixed(1)} pages) ...
|
|
4854
4855
|
${e}`:e=`[Start of page]
|
|
4855
4856
|
${e}`,i?e=`${e}
|
|
@@ -6613,8 +6614,8 @@ statements:
|
|
|
6613
6614
|
|
|
6614
6615
|
- VERIFY: The browser lands on the docs site
|
|
6615
6616
|
js: "await expect(page).toHaveURL(/docs\\\\.shiplight\\\\.ai/)"
|
|
6616
|
-
`});var SR=xp(dn=>{"use strict";Object.defineProperty(dn,"__esModule",{value:!0});dn.testEnvironmentConfigFromEntity=ER;dn.testAccountGroupFromEntity=Ore;dn.testCaseFromEntity=Nre;dn.testSuiteFromEntity=Dre;dn.testRunFromEntity=Rre;dn.testCaseResultFromEntity=Lre;dn.environmentFromEntity=Mre;dn.testAccountFromEntity=Fre;dn.testRunOptionsToEntity=Bre;dn.testFolderFromEntity=$re;dn.createFolderOptionsToEntity=jre;dn.createTestCaseOptionsToEntity=Ure;dn.reusableStepFromEntity=Hre;dn.createReusableStepOptionsToEntity=qre;dn.updateReusableStepOptionsToEntity=Gre;dn.createEnvironmentOptionsToEntity=Wre;function ER(e){return{environmentId:e.environment_id,testAccountGroupId:e.test_account_group_id,testAccountGroup:e.test_account_group?{type:e.test_account_group.type,accountIds:e.test_account_group.account_ids}:void 0,path:e.path,hooks:e.hooks}}function Ore(e){return{id:e.id,type:e.type,accountIds:e.account_ids}}function Nre(e){return{id:e.id,title:e.title,description:e.description,labels:e.labels,folderId:e.folder_id,createdAt:e.created_at,updatedAt:e.updated_at,version:e.version,testFlow:e.test_flow,actionSteps:e.action_steps,codeS3Path:e.code_s3_path,suiteId:e.suite_id,status:e.status,testAccountIds:e.test_account_ids,testDataIds:e.test_data_ids,environmentConfigs:e.environment_configs?.map(ER),disableAutoLogin:e.disable_auto_login,deviceName:e.device_name,timeoutMinutes:e.timeout_minutes,settings:e.settings,actionEntities:e.action_entities}}function Dre(e){return{id:e.id,title:e.title,name:e.name,description:e.description,testCount:e.test_count,createdAt:e.created_at,updatedAt:e.updated_at}}function Rre(e){return{id:e.id,status:e.status,result:e.result,trigger:e.trigger,startTime:e.start_time,endTime:e.end_time,durationMs:e.duration_ms,totalTestCaseCount:e.total_test_case_count,passedTestCaseCount:e.passed_test_case_count,failedTestCaseCount:e.failed_test_case_count,skippedTestCaseCount:e.skipped_test_case_count,notExecutedCount:e.not_executed_count,testCaseResultIds:e.test_case_result_ids}}function Lre(e){return{id:e.id,testCaseId:e.test_case_id,testCaseName:e.test_case_name,result:e.result,durationMs:e.duration_ms,error:e.error}}function Mre(e){return{id:e.id,name:e.name,url:e.url,description:e.description}}function Fre(e){return{id:e.id,username:e.username,password:e.password,environmentId:e.environment_id,description:e.description}}function Bre(e){return{test_case_ids:e.testCaseIds,test_suite_ids:e.testSuiteIds,environment_id:e.environmentId,environment_url:e.environmentUrl,test_context:e.testContext,test_account_id:e.testAccountId}}function $re(e){return{id:e.id,name:e.name,description:e.description,parentId:e.parent_id,depth:e.depth,pathIds:e.path_ids,createdAt:e.created_at,updatedAt:e.updated_at,createdBy:e.created_by,updatedBy:e.updated_by}}function jre(e){return{name:e.name,description:e.description,parentId:e.parentId}}function Ure(e){return{title:e.title,description:e.description,folder_id:e.folderId,labels:e.labels,test_flow:e.testFlow,environment_configs:e.environmentConfigs?.map(t=>({environment_id:t.environmentId,test_account_group:t.testAccountGroup?{type:t.testAccountGroup.type,account_ids:t.testAccountGroup.accountIds}:void 0,path:t.path,hooks:t.hooks}))}}function Hre(e){return{id:e.id,name:e.name,description:e.description,statements:e.statements,createdAt:e.created_at,updatedAt:e.updated_at,updatedBy:e.updated_by,usageCount:e.usage_count}}function qre(e){return{name:e.name,description:e.description,statements:e.statements}}function Gre(e){let t={};return e.name!==void 0&&(t.name=e.name),e.description!==void 0&&(t.description=e.description),e.statements!==void 0&&(t.statements=e.statements),t}function Wre(e){return{name:e.name,url:e.url,description:e.description}}});var TR=xp(Ai=>{"use strict";var Vre=Ai&&Ai.__createBinding||(Object.create?function(e,t,r,n){n===void 0&&(n=r);var i=Object.getOwnPropertyDescriptor(t,r);(!i||("get"in i?!t.__esModule:i.writable||i.configurable))&&(i={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,i)}:function(e,t,r,n){n===void 0&&(n=r),e[n]=t[r]}),zre=Ai&&Ai.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),Kre=Ai&&Ai.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(r){var n=[];for(var i in r)Object.prototype.hasOwnProperty.call(r,i)&&(n[n.length]=i);return n},e(t)};return function(t){if(t&&t.__esModule)return t;var r={};if(t!=null)for(var n=e(t),i=0;i<n.length;i++)n[i]!=="default"&&Vre(r,t,n[i]);return zre(r,t),r}}(),Jre=Ai&&Ai.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ai,"__esModule",{value:!0});Ai.ShiplightClient=void 0;var AR=Jre(bv("axios")),Yre=Kre(bv("cli-progress")),Ar=SR(),g_=class{constructor(t,r="https://api.shiplight.ai"){this.baseUrl=r.replace(/\/$/,""),this.axios=AR.default.create({baseURL:this.baseUrl,headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}})}async triggerTestRun(t){let r=(0,Ar.testRunOptionsToEntity)(t),{test_case_ids:n,test_suite_ids:i,environment_id:s,environment_url:o,test_context:a,test_account_id:l}=r;if(!n?.length&&!i?.length)throw new Error("Must specify either test_case_ids or test_suite_ids");let u,d;if(i?.length===1&&!n?.length?(u=`/v1/test-run/test-suite/${i[0]}`,d={trigger:"API",test_context:a||{}}):n?.length===1&&!i?.length?(u=`/v1/test-run/test-case/${n[0]}`,d={trigger:"API",test_context:a||{}}):(u="/v1/test-run",d={test_case_ids:n||[],test_suite_ids:i||[],trigger:"API"},a&&(d.test_context=a)),s){let p={id:s};o&&(p.url=o),d.environment=p}l&&(d.testAccountGroup={type:"Specific",accountIds:[l]});try{let p=await this.axios.post(u,d);return(0,Ar.testRunFromEntity)(p.data)}catch(p){this.handleError(p)}}async getTestRunStatus(t){try{let r=await this.axios.get(`/v1/test-runs/${t}`);return(0,Ar.testRunFromEntity)(r.data)}catch(r){this.handleError(r)}}async waitForTestRun(t,r={}){let{timeout:n=600,pollInterval:i=10,showProgress:s=!1}=r,o=Date.now(),a=null,l=0,u=!0;for(;Date.now()-o<n*1e3;){u||await this.sleep(i*1e3),u=!1;let d=await this.getTestRunStatus(t);if(s){let m=d.totalTestCaseCount||0,y=(d.passedTestCaseCount||0)+(d.failedTestCaseCount||0);m>0&&(a?y>l&&(a.update(y),l=y):(a=new Yre.SingleBar({format:`Test Run ${t} |{bar}| {percentage}% | {value}/{total} tests | ETA: {eta}s`,barCompleteChar:"\u2588",barIncompleteChar:"\u2591",hideCursor:!0}),a.start(m,y),l=y))}let p=d.status,h=d.result;if(p==="Finished"||h==="Passed"||h==="Failed"||h==="Skipped")return a&&(a.update(a.getTotal()),a.stop()),d}throw a&&a.stop(),new Error(`Test run ${t} did not complete within ${n} seconds`)}async getTestCaseResults(t){let n=(await this.getTestRunStatus(t)).testCaseResultIds||[],i=[];for(let s of n)try{let o=await this.axios.get(`/v1/test-runs/${t}/test-case-results/${s}`);i.push((0,Ar.testCaseResultFromEntity)(o.data))}catch{console.warn(`Warning: Could not fetch test case result ${s}`)}return i}async getEnvironments(){try{return(await this.axios.get("/v1/environments")).data.map(Ar.environmentFromEntity)}catch(t){this.handleError(t)}}async createEnvironment(t){try{let r=(0,Ar.createEnvironmentOptionsToEntity)(t),n=await this.axios.post("/v1/environments",r);return(0,Ar.environmentFromEntity)(n.data.data||n.data)}catch(r){this.handleError(r)}}async getTestAccounts(t){try{let r=t?{environmentId:t}:{};return(await this.axios.get("/v1/test-accounts",{params:r})).data.map(Ar.testAccountFromEntity)}catch(r){this.handleError(r)}}async getTestSuites(){try{return(await this.axios.get("/v1/test-suites")).data.map(Ar.testSuiteFromEntity)}catch(t){this.handleError(t)}}async getTestSuiteDetails(t){try{let n=(await this.axios.get(`/v1/test-suites/${t}`)).data;return{suite:(0,Ar.testSuiteFromEntity)(n.suite),testCases:n.testCases.map(Ar.testCaseFromEntity)}}catch(r){this.handleError(r)}}async getTestCases(){try{let t=await this.axios.get("/v1/test-cases"),r=t.data.data||t.data||[];return Array.isArray(r)?r.map(Ar.testCaseFromEntity):[]}catch(t){this.handleError(t)}}async getTestCase(t){try{let r=await this.axios.get(`/v1/test-cases/${t}`);return(0,Ar.testCaseFromEntity)(r.data)}catch(r){this.handleError(r)}}async getTestCasesInFolder(t,r=!0){try{let n=r?{folderIdRecursive:t}:{folderId:t},i=await this.axios.get("/v1/test-cases",{params:n}),s=i.data.data||i.data||[];return Array.isArray(s)?s.map(Ar.testCaseFromEntity):[]}catch(n){this.handleError(n)}}async getFolders(){try{let t=await this.axios.get("/v1/test-folders/all"),r=t.data.data||t.data||[];return Array.isArray(r)?r.map(Ar.testFolderFromEntity):[]}catch(t){this.handleError(t)}}async getFolderByName(t,r){try{let i=(await this.getFolders()).filter(s=>s.name.toLowerCase()===t.toLowerCase());return r!==void 0?i.find(o=>o.parentId===r)||null:i.length>0?i[0]:null}catch(n){this.handleError(n)}}async createFolder(t){try{let r=(0,Ar.createFolderOptionsToEntity)(t),n=await this.axios.post("/v1/test-folders",r);return(0,Ar.testFolderFromEntity)(n.data.data||n.data)}catch(r){this.handleError(r)}}async createTestCase(t){try{let r=(0,Ar.createTestCaseOptionsToEntity)(t),n=await this.axios.post("/v1/test-cases",r);return(0,Ar.testCaseFromEntity)(n.data.data||n.data)}catch(r){this.handleError(r)}}async getReusableSteps(){try{let t=await this.axios.get("/v1/reusable-steps"),r=t.data.data||t.data||[];return Array.isArray(r)?r.map(Ar.reusableStepFromEntity):[]}catch(t){this.handleError(t)}}async getReusableStepById(t){try{let r=await this.axios.get(`/v1/reusable-steps/${t}`);return(0,Ar.reusableStepFromEntity)(r.data.data||r.data)}catch(r){this.handleError(r)}}async createReusableStep(t){try{let r={reusableStepEntity:(0,Ar.createReusableStepOptionsToEntity)(t)},n=await this.axios.post("/v1/reusable-steps",r);return(0,Ar.reusableStepFromEntity)(n.data.data||n.data)}catch(r){this.handleError(r)}}async updateReusableStep(t,r){try{let n=(0,Ar.updateReusableStepOptionsToEntity)(r),i=await this.axios.put(`/v1/reusable-steps/${t}`,n);return(0,Ar.reusableStepFromEntity)(i.data.data||i.data)}catch(n){this.handleError(n)}}async deleteReusableStep(t){try{await this.axios.delete(`/v1/reusable-steps/${t}`)}catch(r){this.handleError(r)}}async getTestFunctions(t){try{let r=t?{statuses:t.join(",")}:{},n=await this.axios.get("/v1/functions",{params:r}),i={};return n.data.forEach(s=>{s.code&&(i[s.name]=s.code)}),i}catch(r){this.handleError(r)}}async createLocalRun(t){try{return(await this.axios.post("/v1/local-runs",t)).data}catch(r){this.handleError(r)}}async completeLocalRun(t){try{return(await this.axios.put(`/v1/local-runs/${t.testRunId}/complete`,t)).data}catch(r){this.handleError(r)}}sleep(t){return new Promise(r=>setTimeout(r,t))}handleError(t){if(AR.default.isAxiosError(t)){let r=t;throw r.response?new Error(`API request failed: ${r.response.status} - ${JSON.stringify(r.response.data)}`):r.request?new Error("API request failed: No response received"):new Error(`API request failed: ${r.message}`)}throw t}};Ai.ShiplightClient=g_});var PR=xp(ra=>{"use strict";Object.defineProperty(ra,"__esModule",{value:!0});ra.TestResult=ra.TestRunTrigger=ra.TestRunStatus=void 0;var CR;(function(e){e.PENDING="Pending",e.RUNNING="Running",e.COMPLETED="Completed",e.FAILED="Failed",e.CANCELLED="Cancelled"})(CR||(ra.TestRunStatus=CR={}));var kR;(function(e){e.MANUAL="manual",e.SCHEDULED="scheduled",e.API="api",e.CI_CD="ci_cd",e.WEBHOOK="webhook"})(kR||(ra.TestRunTrigger=kR={}));var IR;(function(e){e.PASSED="passed",e.FAILED="failed",e.SKIPPED="skipped",e.ERROR="error"})(IR||(ra.TestResult=IR={}))});var OR=xp(Ti=>{"use strict";Object.defineProperty(Ti,"__esModule",{value:!0});Ti.version=Ti.TestResult=Ti.TestRunTrigger=Ti.TestRunStatus=Ti.ShiplightClient=void 0;var Xre=TR();Object.defineProperty(Ti,"ShiplightClient",{enumerable:!0,get:function(){return Xre.ShiplightClient}});var y_=PR();Object.defineProperty(Ti,"TestRunStatus",{enumerable:!0,get:function(){return y_.TestRunStatus}});Object.defineProperty(Ti,"TestRunTrigger",{enumerable:!0,get:function(){return y_.TestRunTrigger}});Object.defineProperty(Ti,"TestResult",{enumerable:!0,get:function(){return y_.TestResult}});Ti.version="1.0.0"});import Wwe from"fs-extra";import zwe from"chalk";import Jwe from"ora";import Xwe from"ora";import Qwe from"chalk";import t_e,{AbortError as r_e}from"p-retry";import o_e from"fs-extra";import d_e from"chalk";import h_e from"fs-extra";import m_e from"ora";import*as w_ from"path";import{fileURLToPath as sne}from"url";function na(e,t,r,n="main"){let i=[];for(let s=0;s<e.length;s++){let o=e[s],a=`${n}.${s}`,l=Qre(o,t,a,r);l.length>0&&(i.push(...l),s<e.length-1&&i.push(""))}return i}function Qre(e,t,r,n){let i=" ".repeat(t);switch(e.type){case"DRAFT":return ene(e,t,r);case"ACTION":return tne(e,t,r,n);case"STEP":return rne(e,t,r,n);case"IF_ELSE":return nne(e,t,r,n);case"WHILE_LOOP":return ine(e,t,r,n);default:return[`${i}// Unknown statement type: ${e.type}`]}}function ene(e,t,r){let n=" ".repeat(t),i=e.description?.trim()||"";return new Zs().transpileUncachedAction(i,r,!1,!0,e.uid).map(a=>`${n}${a}`)}function tne(e,t,r,n){let i=" ".repeat(t),s=e.description,o=e.uid,l=n.actionEntityStore?.entries[e.uid]?.action_entity??e.action_entity;if(!l)return new Zs().transpileUncachedAction(s||"",r,!!e.use_pure_vision).map(y=>`${i}${y}`);let u=e.locator?{...l,locator:e.locator}:l;return s&&s!==u.action_description&&(u={...u,action_description:s},u.action_data?.action_name==="verify"&&u.action_data?.kwargs?.statement&&(u={...u,action_data:{...u.action_data,kwargs:{...u.action_data.kwargs,statement:s}}})),new Zs().transpile(u,r,o).map(h=>`${i}${h}`)}function rne(e,t,r,n){let i=" ".repeat(t),s=[];if(e.reference_id){let o=n.reusableGroups.get(e.reference_id);if(o&&o.statements){e.description&&e.description.trim()&&s.push(`${i}// Step: ${_m(e.description)}`);let a=na(o.statements,t,n,r);s.push(...a)}}else{e.description&&e.description.trim()&&s.push(`${i}// Step: ${_m(e.description)}`);let o=na(e.statements,t,n,r);s.push(...o)}return s}function nne(e,t,r,n){let i=" ".repeat(t),s=[];if(s.push(`${i}// ${r}: Conditional check`),e.condition.type==="JS_CODE")s.push(`${i}if (${e.condition.expression}) {`);else{s.push(`${i}// AI Condition: ${_m(e.condition.expression)}`);let a=JSON.stringify(e.condition.expression);s.push(`${i}if (await agent.evaluate(page, ${a}, "${r}")) {`)}let o=na(e.then,t+1,n,`${r}.then`);if(s.push(...o),e.else&&e.else.length>0){s.push(`${i}} else {`);let a=na(e.else,t+1,n,`${r}.else`);s.push(...a)}return s.push(`${i}}`),s}function ine(e,t,r,n){let i=" ".repeat(t),s=[];s.push(`${i}// ${r}: Loop`);let o=e.timeout_ms??Ld,a=o/1e3,l=e.timeout_ms?`While loop exceeded timeout of ${a}s`:`While loop exceeded default timeout of ${a}s`,u=`loop_${r.replace(/\./g,"_")}`;if(s.push(`${i}const ${u}_start = Date.now();`),s.push(`${i}const ${u}_timeout = ${o};`),s.push(`${i}const ${u}_check = () => {`),s.push(`${i} if (Date.now() - ${u}_start > ${u}_timeout) {`),s.push(`${i} throw new Error('${l}');`),s.push(`${i} }`),s.push(`${i} return true;`),s.push(`${i}};`),e.condition.type==="JS_CODE")s.push(`${i}while (${u}_check() && (${e.condition.expression})) {`);else{s.push(`${i}// AI Loop Condition: ${_m(e.condition.expression)}`);let p=JSON.stringify(e.condition.expression);s.push(`${i}while (${u}_check() && await agent.evaluate(page, ${p}, "${r}")) {`)}let d=na(e.body,t+1,n,`${r}.body`);return s.push(...d),s.push(`${i}}`),s}function b_(e){return e.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function _m(e){return e.replace(/\r\n/g," ").replace(/\n/g," ").replace(/\r/g," ").trim()}function NR(e,t){let r=$n(e);return ane(r,t)}function ane(e,t){let r=[];r.push(...lne()),r.push(""),e.baseURL&&(r.push(`test.use({ baseURL: '${b_(e.baseURL)}' });`),r.push(""));let n=t?.testName||e.goal||"Generated test";r.push(`test('${b_(n)}', async ({ page }) => {`),r.push(" // Configure SDK with API keys from environment"),r.push(" configureSdk({"),r.push(" env: {"),r.push(" GOOGLE_API_KEY: process.env.GOOGLE_API_KEY,"),r.push(" ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,"),r.push(" },"),r.push(" });"),r.push(""),r.push(" // Create agent"),r.push(" const variableStore = new VariableStore();"),r.push(" const agent = new WebAgent(createAgentContext({"),r.push(" model: process.env.SHIPLIGHT_MODEL || 'gemini-2.5-pro',"),r.push(" variableStore,"),r.push(" }));"),r.push("");let i=t?.startingUrl||e.url;i&&(r.push(" // Navigate to the specified URL"),r.push(` const targetUrl = process.env.PLAYWRIGHT_STARTING_URL || '${b_(i)}';`),r.push(" if (targetUrl) {"),r.push(" await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });"),r.push(" }"),r.push(""));let s={testName:t?.testName,reusableGroups:new Map,startingUrl:t?.startingUrl};if(e.teardown&&e.teardown.length>0){if(r.push(" try {"),e.statements&&e.statements.length>0){r.push(" // Test steps");let l=na(e.statements,2,s);r.push(...l)}r.push(" } finally {"),r.push(" // Teardown");let a=na(e.teardown,2,s,"teardown");r.push(...a),r.push(" }")}else if(e.statements&&e.statements.length>0){r.push(" // Test steps");let a=na(e.statements,1,s);r.push(...a)}return r.push("});"),r.join(`
|
|
6617
|
-
`)}function lne(){return["import { test, expect } from '@playwright/test';","import { WebAgent, createAgentContext, configureSdk } from 'shiplightai';","import { VariableStore } from 'shiplightai';"]}var Zre,one,y_e,DR=mt(()=>{"use strict";Zre=eM(OR(),1);ns();Yn();ns();ns();Yn();ns();one=sne(import.meta.url),y_e=w_.dirname(one)});import{stringify as cne}from"yaml";import{createHash as Cne}from"crypto";import{parse as kne,stringify as qR}from"yaml";import{readFileSync as Ine,existsSync as Pne}from"fs";import{resolve as v_,dirname as One}from"path";import{parse as FR,stringify as Nne}from"yaml";import{readFileSync as jne,writeFileSync as Une,mkdirSync as Hne}from"fs";import{dirname as qne}from"path";function co(e){return e.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function Xr(e){return e.replace(/\r\n/g," ").replace(/\n/g," ").replace(/\r/g," ").trim()}function une(e){let t=e.frame_path;return!t||t.length===0?"page":`page.frameLocator('${t[0]}')`}function dne(e){let t=e.xpath;return typeof t=="string"&&t.trim()?!t.startsWith("xpath=")&&!t.startsWith("/")&&!t.startsWith("//")?`xpath=//${t}`:t.startsWith("xpath=")?t:`xpath=${t}`:null}function xm(e){let t=une(e),r=e.locator;if(typeof r=="string"&&r.trim())return r=r.trim(),r.endsWith("first()")?`${t}.${r}`:`${t}.${r}.first()`;let n=dne(e);if(n){let i=JSON.stringify(n);return`${t}.locator(${i}).first()`}return null}function RR(e){let t=e.action_data?.action_name;return!t||(t==="verify"||t==="ai_assert"||t==="assert")&&e.action_data?.kwargs?.code?!1:pne.includes(t)}function fne(e){let t=e.action_data?.action_name;return!t||(t==="verify"||t==="ai_assert"||t==="assert")&&e.action_data?.kwargs?.code?!1:!hne.includes(t)}function xt(e,t){jn.set(e,t)}function mne(e){return jn.get(e)}function il(e,t,r=[]){let n=[...r];return t.locator?n.push(`locator: ${JSON.stringify(t.locator)}`):t.xpath&&n.push(`xpath: ${JSON.stringify(t.xpath)}`),t.frame_path&&t.frame_path.length>0&&n.push(`frame_path: ${JSON.stringify(t.frame_path)}`),n.length===0?[`await agent.execAction("${e}", page, {});`]:[`await agent.execAction("${e}", page, {`,...n.map(i=>` ${i},`),"});"]}function LR(e){let t=e.functionName;if(!t)return null;let r=Array.isArray(e.args)?e.args.map(String):[];if(r.length===0)return`await ${t}()`;let n=["page","testContext","request","agent"],i=["undefined","null","true","false"],s=r.map(o=>n.includes(o)||i.includes(o)||/^-?\d+(\.\d+)?$/.test(o)?o:o.startsWith("$")?`agent.agentServices.readVariable('${o.substring(1)}')`:`"${o}"`);return`await ${t}(${s.join(", ")})`}function Cs(e,t,r,n="main"){let i=[];for(let s=0;s<e.length;s++){let o=e[s],a=`${n}.${s}`,l=gne(o,t,a,r);l.length>0&&(i.push(...l),s<e.length-1&&i.push(""))}return i}function gne(e,t,r,n){let i=" ".repeat(t);switch(e.type){case"DRAFT":return yne(e,t,r,n);case"ACTION":return bne(e,t,r,n);case"STEP":return wne(e,t,r,n);case"IF_ELSE":return _ne(e,t,r,n);case"WHILE_LOOP":return vne(e,t,r,n);default:return[`${i}// Unknown statement type: ${e.type}`]}}function yne(e,t,r,n){let i=" ".repeat(t),s=e.description?.trim()||"";if(!s)return[`${i}// ${r}: Skipping - no description`];if(n.noAgent)return[`${i}// ${r}: ${Xr(s)}`,`${i}// DRAFT: ${Xr(s)} (requires agent - skipped in hook)`];let o=JSON.stringify(s);return[`${i}// ${r}: ${Xr(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.run(page, ${o}, '${r}');`]}function bne(e,t,r,n){let i=" ".repeat(t),s=e.description,o=e.uid,l=n.actionEntityStore?.entries[e.uid]?.action_entity??e.action_entity;if(!l){if(!s)return[`${i}// ${r}: Skipping - no description`];if(n.noAgent)return[`${i}// ${r}: ${Xr(s)}`,`${i}// DRAFT: ${Xr(s)} (requires agent - skipped in hook)`];let C=JSON.stringify(s),R=!!e.use_pure_vision;return[`${i}// ${r}: ${Xr(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.execute(page, ${C}, '${r}', ${R});`]}let u=e.locator?{...l,locator:e.locator}:l;s&&s!==u.action_description&&(u={...u,action_description:s});let d=u.action_data?.action_name||"",p=u.action_description||"",h=mne(d);if(!h)return[`${i}// ${r}: Unknown action: ${d}`];let m={imports:n.imports},y=h(u,r,m);if(n.noAgent){if(RR(u))return[`${i}// ${r}: ${Xr(p)}`,`${i}// AI action: ${Xr(p)} (requires agent - skipped in hook)`];let C=xne(u,d,i,r);return C||[`${i}// ${r}: ${Xr(p)}`,...y.map(R=>`${i}${R}`)]}if(RR(u))return[`${i}// ${r}: ${Xr(p)}`,`${i}page = agent.agentServices.validatePage(page);`,...y.map(C=>`${i}${C}`)];let b=JSON.stringify(p),w=y.map(C=>`${i} ${C}`),E=fne(u),x=o?`'${o}'`:"undefined";return[`${i}// ${r}: ${Xr(p)}`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.step(page, async () => {`,...w,`${i}}, ${b}, '${r}', ${x}, ${E});`]}function wne(e,t,r,n){let i=" ".repeat(t),s=[];e.description&&e.description.trim()&&s.push(`${i}// Step: ${Xr(e.description)}`);let o=Cs(e.statements,t,n,r);return s.push(...o),s}function _ne(e,t,r,n){let i=" ".repeat(t),s=[];if(s.push(`${i}// ${r}: Conditional check`),e.condition.type==="JS_CODE")s.push(`${i}if (${e.condition.expression}) {`);else{s.push(`${i}// AI Condition: ${Xr(e.condition.expression)}`);let a=JSON.stringify(e.condition.expression);s.push(`${i}if (await agent.evaluate(page, ${a}, "${r}")) {`)}let o=Cs(e.then,t+1,n,`${r}.then`);if(s.push(...o),e.else&&e.else.length>0){s.push(`${i}} else {`);let a=Cs(e.else,t+1,n,`${r}.else`);s.push(...a)}return s.push(`${i}}`),s}function vne(e,t,r,n){let i=" ".repeat(t),s=[];s.push(`${i}// ${r}: Loop`);let o=e.timeout_ms??
|
|
6617
|
+
`});var SR=xp(dn=>{"use strict";Object.defineProperty(dn,"__esModule",{value:!0});dn.testEnvironmentConfigFromEntity=ER;dn.testAccountGroupFromEntity=Ore;dn.testCaseFromEntity=Nre;dn.testSuiteFromEntity=Dre;dn.testRunFromEntity=Rre;dn.testCaseResultFromEntity=Lre;dn.environmentFromEntity=Mre;dn.testAccountFromEntity=Fre;dn.testRunOptionsToEntity=Bre;dn.testFolderFromEntity=$re;dn.createFolderOptionsToEntity=jre;dn.createTestCaseOptionsToEntity=Ure;dn.reusableStepFromEntity=Hre;dn.createReusableStepOptionsToEntity=qre;dn.updateReusableStepOptionsToEntity=Gre;dn.createEnvironmentOptionsToEntity=Wre;function ER(e){return{environmentId:e.environment_id,testAccountGroupId:e.test_account_group_id,testAccountGroup:e.test_account_group?{type:e.test_account_group.type,accountIds:e.test_account_group.account_ids}:void 0,path:e.path,hooks:e.hooks}}function Ore(e){return{id:e.id,type:e.type,accountIds:e.account_ids}}function Nre(e){return{id:e.id,title:e.title,description:e.description,labels:e.labels,folderId:e.folder_id,createdAt:e.created_at,updatedAt:e.updated_at,version:e.version,testFlow:e.test_flow,actionSteps:e.action_steps,codeS3Path:e.code_s3_path,suiteId:e.suite_id,status:e.status,testAccountIds:e.test_account_ids,testDataIds:e.test_data_ids,environmentConfigs:e.environment_configs?.map(ER),disableAutoLogin:e.disable_auto_login,deviceName:e.device_name,timeoutMinutes:e.timeout_minutes,settings:e.settings,actionEntities:e.action_entities}}function Dre(e){return{id:e.id,title:e.title,name:e.name,description:e.description,testCount:e.test_count,createdAt:e.created_at,updatedAt:e.updated_at}}function Rre(e){return{id:e.id,status:e.status,result:e.result,trigger:e.trigger,startTime:e.start_time,endTime:e.end_time,durationMs:e.duration_ms,totalTestCaseCount:e.total_test_case_count,passedTestCaseCount:e.passed_test_case_count,failedTestCaseCount:e.failed_test_case_count,skippedTestCaseCount:e.skipped_test_case_count,notExecutedCount:e.not_executed_count,testCaseResultIds:e.test_case_result_ids}}function Lre(e){return{id:e.id,testCaseId:e.test_case_id,testCaseName:e.test_case_name,result:e.result,durationMs:e.duration_ms,error:e.error}}function Mre(e){return{id:e.id,name:e.name,url:e.url,description:e.description}}function Fre(e){return{id:e.id,username:e.username,password:e.password,environmentId:e.environment_id,description:e.description}}function Bre(e){return{test_case_ids:e.testCaseIds,test_suite_ids:e.testSuiteIds,environment_id:e.environmentId,environment_url:e.environmentUrl,test_context:e.testContext,test_account_id:e.testAccountId}}function $re(e){return{id:e.id,name:e.name,description:e.description,parentId:e.parent_id,depth:e.depth,pathIds:e.path_ids,createdAt:e.created_at,updatedAt:e.updated_at,createdBy:e.created_by,updatedBy:e.updated_by}}function jre(e){return{name:e.name,description:e.description,parentId:e.parentId}}function Ure(e){return{title:e.title,description:e.description,folder_id:e.folderId,labels:e.labels,test_flow:e.testFlow,environment_configs:e.environmentConfigs?.map(t=>({environment_id:t.environmentId,test_account_group:t.testAccountGroup?{type:t.testAccountGroup.type,account_ids:t.testAccountGroup.accountIds}:void 0,path:t.path,hooks:t.hooks}))}}function Hre(e){return{id:e.id,name:e.name,description:e.description,statements:e.statements,createdAt:e.created_at,updatedAt:e.updated_at,updatedBy:e.updated_by,usageCount:e.usage_count}}function qre(e){return{name:e.name,description:e.description,statements:e.statements}}function Gre(e){let t={};return e.name!==void 0&&(t.name=e.name),e.description!==void 0&&(t.description=e.description),e.statements!==void 0&&(t.statements=e.statements),t}function Wre(e){return{name:e.name,url:e.url,description:e.description}}});var TR=xp(Ai=>{"use strict";var Vre=Ai&&Ai.__createBinding||(Object.create?function(e,t,r,n){n===void 0&&(n=r);var i=Object.getOwnPropertyDescriptor(t,r);(!i||("get"in i?!t.__esModule:i.writable||i.configurable))&&(i={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,i)}:function(e,t,r,n){n===void 0&&(n=r),e[n]=t[r]}),zre=Ai&&Ai.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),Kre=Ai&&Ai.__importStar||function(){var e=function(t){return e=Object.getOwnPropertyNames||function(r){var n=[];for(var i in r)Object.prototype.hasOwnProperty.call(r,i)&&(n[n.length]=i);return n},e(t)};return function(t){if(t&&t.__esModule)return t;var r={};if(t!=null)for(var n=e(t),i=0;i<n.length;i++)n[i]!=="default"&&Vre(r,t,n[i]);return zre(r,t),r}}(),Jre=Ai&&Ai.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ai,"__esModule",{value:!0});Ai.ShiplightClient=void 0;var AR=Jre(bv("axios")),Yre=Kre(bv("cli-progress")),Ar=SR(),g_=class{constructor(t,r="https://api.shiplight.ai"){this.baseUrl=r.replace(/\/$/,""),this.axios=AR.default.create({baseURL:this.baseUrl,headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}})}async triggerTestRun(t){let r=(0,Ar.testRunOptionsToEntity)(t),{test_case_ids:n,test_suite_ids:i,environment_id:s,environment_url:o,test_context:a,test_account_id:l}=r;if(!n?.length&&!i?.length)throw new Error("Must specify either test_case_ids or test_suite_ids");let u,d;if(i?.length===1&&!n?.length?(u=`/v1/test-run/test-suite/${i[0]}`,d={trigger:"API",test_context:a||{}}):n?.length===1&&!i?.length?(u=`/v1/test-run/test-case/${n[0]}`,d={trigger:"API",test_context:a||{}}):(u="/v1/test-run",d={test_case_ids:n||[],test_suite_ids:i||[],trigger:"API"},a&&(d.test_context=a)),s){let p={id:s};o&&(p.url=o),d.environment=p}l&&(d.testAccountGroup={type:"Specific",accountIds:[l]});try{let p=await this.axios.post(u,d);return(0,Ar.testRunFromEntity)(p.data)}catch(p){this.handleError(p)}}async getTestRunStatus(t){try{let r=await this.axios.get(`/v1/test-runs/${t}`);return(0,Ar.testRunFromEntity)(r.data)}catch(r){this.handleError(r)}}async waitForTestRun(t,r={}){let{timeout:n=600,pollInterval:i=10,showProgress:s=!1}=r,o=Date.now(),a=null,l=0,u=!0;for(;Date.now()-o<n*1e3;){u||await this.sleep(i*1e3),u=!1;let d=await this.getTestRunStatus(t);if(s){let m=d.totalTestCaseCount||0,y=(d.passedTestCaseCount||0)+(d.failedTestCaseCount||0);m>0&&(a?y>l&&(a.update(y),l=y):(a=new Yre.SingleBar({format:`Test Run ${t} |{bar}| {percentage}% | {value}/{total} tests | ETA: {eta}s`,barCompleteChar:"\u2588",barIncompleteChar:"\u2591",hideCursor:!0}),a.start(m,y),l=y))}let p=d.status,h=d.result;if(p==="Finished"||h==="Passed"||h==="Failed"||h==="Skipped")return a&&(a.update(a.getTotal()),a.stop()),d}throw a&&a.stop(),new Error(`Test run ${t} did not complete within ${n} seconds`)}async getTestCaseResults(t){let n=(await this.getTestRunStatus(t)).testCaseResultIds||[],i=[];for(let s of n)try{let o=await this.axios.get(`/v1/test-runs/${t}/test-case-results/${s}`);i.push((0,Ar.testCaseResultFromEntity)(o.data))}catch{console.warn(`Warning: Could not fetch test case result ${s}`)}return i}async getEnvironments(){try{return(await this.axios.get("/v1/environments")).data.map(Ar.environmentFromEntity)}catch(t){this.handleError(t)}}async createEnvironment(t){try{let r=(0,Ar.createEnvironmentOptionsToEntity)(t),n=await this.axios.post("/v1/environments",r);return(0,Ar.environmentFromEntity)(n.data.data||n.data)}catch(r){this.handleError(r)}}async getTestAccounts(t){try{let r=t?{environmentId:t}:{};return(await this.axios.get("/v1/test-accounts",{params:r})).data.map(Ar.testAccountFromEntity)}catch(r){this.handleError(r)}}async getTestSuites(){try{return(await this.axios.get("/v1/test-suites")).data.map(Ar.testSuiteFromEntity)}catch(t){this.handleError(t)}}async getTestSuiteDetails(t){try{let n=(await this.axios.get(`/v1/test-suites/${t}`)).data;return{suite:(0,Ar.testSuiteFromEntity)(n.suite),testCases:n.testCases.map(Ar.testCaseFromEntity)}}catch(r){this.handleError(r)}}async getTestCases(){try{let t=await this.axios.get("/v1/test-cases"),r=t.data.data||t.data||[];return Array.isArray(r)?r.map(Ar.testCaseFromEntity):[]}catch(t){this.handleError(t)}}async getTestCase(t){try{let r=await this.axios.get(`/v1/test-cases/${t}`);return(0,Ar.testCaseFromEntity)(r.data)}catch(r){this.handleError(r)}}async getTestCasesInFolder(t,r=!0){try{let n=r?{folderIdRecursive:t}:{folderId:t},i=await this.axios.get("/v1/test-cases",{params:n}),s=i.data.data||i.data||[];return Array.isArray(s)?s.map(Ar.testCaseFromEntity):[]}catch(n){this.handleError(n)}}async getFolders(){try{let t=await this.axios.get("/v1/test-folders/all"),r=t.data.data||t.data||[];return Array.isArray(r)?r.map(Ar.testFolderFromEntity):[]}catch(t){this.handleError(t)}}async getFolderByName(t,r){try{let i=(await this.getFolders()).filter(s=>s.name.toLowerCase()===t.toLowerCase());return r!==void 0?i.find(o=>o.parentId===r)||null:i.length>0?i[0]:null}catch(n){this.handleError(n)}}async createFolder(t){try{let r=(0,Ar.createFolderOptionsToEntity)(t),n=await this.axios.post("/v1/test-folders",r);return(0,Ar.testFolderFromEntity)(n.data.data||n.data)}catch(r){this.handleError(r)}}async createTestCase(t){try{let r=(0,Ar.createTestCaseOptionsToEntity)(t),n=await this.axios.post("/v1/test-cases",r);return(0,Ar.testCaseFromEntity)(n.data.data||n.data)}catch(r){this.handleError(r)}}async getReusableSteps(){try{let t=await this.axios.get("/v1/reusable-steps"),r=t.data.data||t.data||[];return Array.isArray(r)?r.map(Ar.reusableStepFromEntity):[]}catch(t){this.handleError(t)}}async getReusableStepById(t){try{let r=await this.axios.get(`/v1/reusable-steps/${t}`);return(0,Ar.reusableStepFromEntity)(r.data.data||r.data)}catch(r){this.handleError(r)}}async createReusableStep(t){try{let r={reusableStepEntity:(0,Ar.createReusableStepOptionsToEntity)(t)},n=await this.axios.post("/v1/reusable-steps",r);return(0,Ar.reusableStepFromEntity)(n.data.data||n.data)}catch(r){this.handleError(r)}}async updateReusableStep(t,r){try{let n=(0,Ar.updateReusableStepOptionsToEntity)(r),i=await this.axios.put(`/v1/reusable-steps/${t}`,n);return(0,Ar.reusableStepFromEntity)(i.data.data||i.data)}catch(n){this.handleError(n)}}async deleteReusableStep(t){try{await this.axios.delete(`/v1/reusable-steps/${t}`)}catch(r){this.handleError(r)}}async getTestFunctions(t){try{let r=t?{statuses:t.join(",")}:{},n=await this.axios.get("/v1/functions",{params:r}),i={};return n.data.forEach(s=>{s.code&&(i[s.name]=s.code)}),i}catch(r){this.handleError(r)}}async createLocalRun(t){try{return(await this.axios.post("/v1/local-runs",t)).data}catch(r){this.handleError(r)}}async completeLocalRun(t){try{return(await this.axios.put(`/v1/local-runs/${t.testRunId}/complete`,t)).data}catch(r){this.handleError(r)}}sleep(t){return new Promise(r=>setTimeout(r,t))}handleError(t){if(AR.default.isAxiosError(t)){let r=t;throw r.response?new Error(`API request failed: ${r.response.status} - ${JSON.stringify(r.response.data)}`):r.request?new Error("API request failed: No response received"):new Error(`API request failed: ${r.message}`)}throw t}};Ai.ShiplightClient=g_});var PR=xp(ra=>{"use strict";Object.defineProperty(ra,"__esModule",{value:!0});ra.TestResult=ra.TestRunTrigger=ra.TestRunStatus=void 0;var CR;(function(e){e.PENDING="Pending",e.RUNNING="Running",e.COMPLETED="Completed",e.FAILED="Failed",e.CANCELLED="Cancelled"})(CR||(ra.TestRunStatus=CR={}));var kR;(function(e){e.MANUAL="manual",e.SCHEDULED="scheduled",e.API="api",e.CI_CD="ci_cd",e.WEBHOOK="webhook"})(kR||(ra.TestRunTrigger=kR={}));var IR;(function(e){e.PASSED="passed",e.FAILED="failed",e.SKIPPED="skipped",e.ERROR="error"})(IR||(ra.TestResult=IR={}))});var OR=xp(Ti=>{"use strict";Object.defineProperty(Ti,"__esModule",{value:!0});Ti.version=Ti.TestResult=Ti.TestRunTrigger=Ti.TestRunStatus=Ti.ShiplightClient=void 0;var Xre=TR();Object.defineProperty(Ti,"ShiplightClient",{enumerable:!0,get:function(){return Xre.ShiplightClient}});var y_=PR();Object.defineProperty(Ti,"TestRunStatus",{enumerable:!0,get:function(){return y_.TestRunStatus}});Object.defineProperty(Ti,"TestRunTrigger",{enumerable:!0,get:function(){return y_.TestRunTrigger}});Object.defineProperty(Ti,"TestResult",{enumerable:!0,get:function(){return y_.TestResult}});Ti.version="1.0.0"});import Wwe from"fs-extra";import zwe from"chalk";import Jwe from"ora";import Xwe from"ora";import Qwe from"chalk";import t_e,{AbortError as r_e}from"p-retry";import o_e from"fs-extra";import d_e from"chalk";import h_e from"fs-extra";import m_e from"ora";import*as w_ from"path";import{fileURLToPath as sne}from"url";function na(e,t,r,n="main"){let i=[];for(let s=0;s<e.length;s++){let o=e[s],a=`${n}.${s}`,l=Qre(o,t,a,r);l.length>0&&(i.push(...l),s<e.length-1&&i.push(""))}return i}function Qre(e,t,r,n){let i=" ".repeat(t);switch(e.type){case"DRAFT":return ene(e,t,r);case"ACTION":return tne(e,t,r,n);case"STEP":return rne(e,t,r,n);case"IF_ELSE":return nne(e,t,r,n);case"WHILE_LOOP":return ine(e,t,r,n);default:return[`${i}// Unknown statement type: ${e.type}`]}}function ene(e,t,r){let n=" ".repeat(t),i=e.description?.trim()||"";return new Zs().transpileUncachedAction(i,r,!1,!0,e.uid).map(a=>`${n}${a}`)}function tne(e,t,r,n){let i=" ".repeat(t),s=e.description,o=e.uid,l=n.actionEntityStore?.entries[e.uid]?.action_entity??e.action_entity;if(!l)return new Zs().transpileUncachedAction(s||"",r,!!e.use_pure_vision).map(y=>`${i}${y}`);let u=e.locator?{...l,locator:e.locator}:l;return s&&s!==u.action_description&&(u={...u,action_description:s},u.action_data?.action_name==="verify"&&u.action_data?.kwargs?.statement&&(u={...u,action_data:{...u.action_data,kwargs:{...u.action_data.kwargs,statement:s}}})),new Zs().transpile(u,r,o).map(h=>`${i}${h}`)}function rne(e,t,r,n){let i=" ".repeat(t),s=[];if(e.reference_id){let o=n.reusableGroups.get(e.reference_id);if(o&&o.statements){e.description&&e.description.trim()&&s.push(`${i}// Step: ${_m(e.description)}`);let a=na(o.statements,t,n,r);s.push(...a)}}else{e.description&&e.description.trim()&&s.push(`${i}// Step: ${_m(e.description)}`);let o=na(e.statements,t,n,r);s.push(...o)}return s}function nne(e,t,r,n){let i=" ".repeat(t),s=[];if(s.push(`${i}// ${r}: Conditional check`),e.condition.type==="JS_CODE")s.push(`${i}if (${e.condition.expression}) {`);else{s.push(`${i}// AI Condition: ${_m(e.condition.expression)}`);let a=JSON.stringify(e.condition.expression);s.push(`${i}if (await agent.evaluate(page, ${a}, "${r}")) {`)}let o=na(e.then,t+1,n,`${r}.then`);if(s.push(...o),e.else&&e.else.length>0){s.push(`${i}} else {`);let a=na(e.else,t+1,n,`${r}.else`);s.push(...a)}return s.push(`${i}}`),s}function ine(e,t,r,n){let i=" ".repeat(t),s=[];s.push(`${i}// ${r}: Loop`);let o=e.timeout_ms??Md,a=o/1e3,l=e.timeout_ms?`While loop exceeded timeout of ${a}s`:`While loop exceeded default timeout of ${a}s`,u=`loop_${r.replace(/\./g,"_")}`;if(s.push(`${i}const ${u}_start = Date.now();`),s.push(`${i}const ${u}_timeout = ${o};`),s.push(`${i}const ${u}_check = () => {`),s.push(`${i} if (Date.now() - ${u}_start > ${u}_timeout) {`),s.push(`${i} throw new Error('${l}');`),s.push(`${i} }`),s.push(`${i} return true;`),s.push(`${i}};`),e.condition.type==="JS_CODE")s.push(`${i}while (${u}_check() && (${e.condition.expression})) {`);else{s.push(`${i}// AI Loop Condition: ${_m(e.condition.expression)}`);let p=JSON.stringify(e.condition.expression);s.push(`${i}while (${u}_check() && await agent.evaluate(page, ${p}, "${r}")) {`)}let d=na(e.body,t+1,n,`${r}.body`);return s.push(...d),s.push(`${i}}`),s}function b_(e){return e.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function _m(e){return e.replace(/\r\n/g," ").replace(/\n/g," ").replace(/\r/g," ").trim()}function NR(e,t){let r=$n(e);return ane(r,t)}function ane(e,t){let r=[];r.push(...lne()),r.push(""),e.baseURL&&(r.push(`test.use({ baseURL: '${b_(e.baseURL)}' });`),r.push(""));let n=t?.testName||e.goal||"Generated test";r.push(`test('${b_(n)}', async ({ page }) => {`),r.push(" // Configure SDK with API keys from environment"),r.push(" configureSdk({"),r.push(" env: {"),r.push(" GOOGLE_API_KEY: process.env.GOOGLE_API_KEY,"),r.push(" ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,"),r.push(" },"),r.push(" });"),r.push(""),r.push(" // Create agent"),r.push(" const variableStore = new VariableStore();"),r.push(" const agent = new WebAgent(createAgentContext({"),r.push(" model: process.env.SHIPLIGHT_MODEL || 'gemini-2.5-pro',"),r.push(" variableStore,"),r.push(" }));"),r.push("");let i=t?.startingUrl||e.url;i&&(r.push(" // Navigate to the specified URL"),r.push(` const targetUrl = process.env.PLAYWRIGHT_STARTING_URL || '${b_(i)}';`),r.push(" if (targetUrl) {"),r.push(" await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });"),r.push(" }"),r.push(""));let s={testName:t?.testName,reusableGroups:new Map,startingUrl:t?.startingUrl};if(e.teardown&&e.teardown.length>0){if(r.push(" try {"),e.statements&&e.statements.length>0){r.push(" // Test steps");let l=na(e.statements,2,s);r.push(...l)}r.push(" } finally {"),r.push(" // Teardown");let a=na(e.teardown,2,s,"teardown");r.push(...a),r.push(" }")}else if(e.statements&&e.statements.length>0){r.push(" // Test steps");let a=na(e.statements,1,s);r.push(...a)}return r.push("});"),r.join(`
|
|
6618
|
+
`)}function lne(){return["import { test, expect } from '@playwright/test';","import { WebAgent, createAgentContext, configureSdk } from 'shiplightai';","import { VariableStore } from 'shiplightai';"]}var Zre,one,y_e,DR=mt(()=>{"use strict";Zre=eM(OR(),1);ns();Yn();ns();ns();Yn();ns();one=sne(import.meta.url),y_e=w_.dirname(one)});import{stringify as cne}from"yaml";import{createHash as Cne}from"crypto";import{parse as kne,stringify as qR}from"yaml";import{readFileSync as Ine,existsSync as Pne}from"fs";import{resolve as v_,dirname as One}from"path";import{parse as FR,stringify as Nne}from"yaml";import{readFileSync as jne,writeFileSync as Une,mkdirSync as Hne}from"fs";import{dirname as qne}from"path";function co(e){return e.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function Xr(e){return e.replace(/\r\n/g," ").replace(/\n/g," ").replace(/\r/g," ").trim()}function une(e){let t=e.frame_path;return!t||t.length===0?"page":`page.frameLocator('${t[0]}')`}function dne(e){let t=e.xpath;return typeof t=="string"&&t.trim()?!t.startsWith("xpath=")&&!t.startsWith("/")&&!t.startsWith("//")?`xpath=//${t}`:t.startsWith("xpath=")?t:`xpath=${t}`:null}function xm(e){let t=une(e),r=e.locator;if(typeof r=="string"&&r.trim())return r=r.trim(),r.endsWith("first()")?`${t}.${r}`:`${t}.${r}.first()`;let n=dne(e);if(n){let i=JSON.stringify(n);return`${t}.locator(${i}).first()`}return null}function RR(e){let t=e.action_data?.action_name;return!t||(t==="verify"||t==="ai_assert"||t==="assert")&&e.action_data?.kwargs?.code?!1:pne.includes(t)}function fne(e){let t=e.action_data?.action_name;return!t||(t==="verify"||t==="ai_assert"||t==="assert")&&e.action_data?.kwargs?.code?!1:!hne.includes(t)}function xt(e,t){jn.set(e,t)}function mne(e){return jn.get(e)}function il(e,t,r=[]){let n=[...r];return t.locator?n.push(`locator: ${JSON.stringify(t.locator)}`):t.xpath&&n.push(`xpath: ${JSON.stringify(t.xpath)}`),t.frame_path&&t.frame_path.length>0&&n.push(`frame_path: ${JSON.stringify(t.frame_path)}`),n.length===0?[`await agent.execAction("${e}", page, {});`]:[`await agent.execAction("${e}", page, {`,...n.map(i=>` ${i},`),"});"]}function LR(e){let t=e.functionName;if(!t)return null;let r=Array.isArray(e.args)?e.args.map(String):[];if(r.length===0)return`await ${t}()`;let n=["page","testContext","request","agent"],i=["undefined","null","true","false"],s=r.map(o=>n.includes(o)||i.includes(o)||/^-?\d+(\.\d+)?$/.test(o)?o:o.startsWith("$")?`agent.agentServices.readVariable('${o.substring(1)}')`:`"${o}"`);return`await ${t}(${s.join(", ")})`}function Cs(e,t,r,n="main"){let i=[];for(let s=0;s<e.length;s++){let o=e[s],a=`${n}.${s}`,l=gne(o,t,a,r);l.length>0&&(i.push(...l),s<e.length-1&&i.push(""))}return i}function gne(e,t,r,n){let i=" ".repeat(t);switch(e.type){case"DRAFT":return yne(e,t,r,n);case"ACTION":return bne(e,t,r,n);case"STEP":return wne(e,t,r,n);case"IF_ELSE":return _ne(e,t,r,n);case"WHILE_LOOP":return vne(e,t,r,n);default:return[`${i}// Unknown statement type: ${e.type}`]}}function yne(e,t,r,n){let i=" ".repeat(t),s=e.description?.trim()||"";if(!s)return[`${i}// ${r}: Skipping - no description`];if(n.noAgent)return[`${i}// ${r}: ${Xr(s)}`,`${i}// DRAFT: ${Xr(s)} (requires agent - skipped in hook)`];let o=JSON.stringify(s);return[`${i}// ${r}: ${Xr(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.run(page, ${o}, '${r}');`]}function bne(e,t,r,n){let i=" ".repeat(t),s=e.description,o=e.uid,l=n.actionEntityStore?.entries[e.uid]?.action_entity??e.action_entity;if(!l){if(!s)return[`${i}// ${r}: Skipping - no description`];if(n.noAgent)return[`${i}// ${r}: ${Xr(s)}`,`${i}// DRAFT: ${Xr(s)} (requires agent - skipped in hook)`];let C=JSON.stringify(s),R=!!e.use_pure_vision;return[`${i}// ${r}: ${Xr(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.execute(page, ${C}, '${r}', ${R});`]}let u=e.locator?{...l,locator:e.locator}:l;s&&s!==u.action_description&&(u={...u,action_description:s});let d=u.action_data?.action_name||"",p=u.action_description||"",h=mne(d);if(!h)return[`${i}// ${r}: Unknown action: ${d}`];let m={imports:n.imports},y=h(u,r,m);if(n.noAgent){if(RR(u))return[`${i}// ${r}: ${Xr(p)}`,`${i}// AI action: ${Xr(p)} (requires agent - skipped in hook)`];let C=xne(u,d,i,r);return C||[`${i}// ${r}: ${Xr(p)}`,...y.map(R=>`${i}${R}`)]}if(RR(u))return[`${i}// ${r}: ${Xr(p)}`,`${i}page = agent.agentServices.validatePage(page);`,...y.map(C=>`${i}${C}`)];let b=JSON.stringify(p),w=y.map(C=>`${i} ${C}`),E=fne(u),x=o?`'${o}'`:"undefined";return[`${i}// ${r}: ${Xr(p)}`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.step(page, async () => {`,...w,`${i}}, ${b}, '${r}', ${x}, ${E});`]}function wne(e,t,r,n){let i=" ".repeat(t),s=[];e.description&&e.description.trim()&&s.push(`${i}// Step: ${Xr(e.description)}`);let o=Cs(e.statements,t,n,r);return s.push(...o),s}function _ne(e,t,r,n){let i=" ".repeat(t),s=[];if(s.push(`${i}// ${r}: Conditional check`),e.condition.type==="JS_CODE")s.push(`${i}if (${e.condition.expression}) {`);else{s.push(`${i}// AI Condition: ${Xr(e.condition.expression)}`);let a=JSON.stringify(e.condition.expression);s.push(`${i}if (await agent.evaluate(page, ${a}, "${r}")) {`)}let o=Cs(e.then,t+1,n,`${r}.then`);if(s.push(...o),e.else&&e.else.length>0){s.push(`${i}} else {`);let a=Cs(e.else,t+1,n,`${r}.else`);s.push(...a)}return s.push(`${i}}`),s}function vne(e,t,r,n){let i=" ".repeat(t),s=[];s.push(`${i}// ${r}: Loop`);let o=e.timeout_ms??Md,a=o/1e3,l=e.timeout_ms?`While loop exceeded timeout of ${a}s`:`While loop exceeded default timeout of ${a}s`,u=`loop_${r.replace(/\./g,"_")}`;if(s.push(`${i}const ${u}_start = Date.now();`),s.push(`${i}const ${u}_timeout = ${o};`),s.push(`${i}const ${u}_check = () => {`),s.push(`${i} if (Date.now() - ${u}_start > ${u}_timeout) {`),s.push(`${i} throw new Error('${l}');`),s.push(`${i} }`),s.push(`${i} return true;`),s.push(`${i}};`),e.condition.type==="JS_CODE")s.push(`${i}while (${u}_check() && (${e.condition.expression})) {`);else{s.push(`${i}// AI Loop Condition: ${Xr(e.condition.expression)}`);let p=JSON.stringify(e.condition.expression);s.push(`${i}while (${u}_check() && await agent.evaluate(page, ${p}, "${r}")) {`)}let d=Cs(e.body,t+1,n,`${r}.body`);return s.push(...d),s.push(`${i}}`),s}function xne(e,t,r,n){let i=e.action_description||"",s=e.action_data?.kwargs||{},o=s.timeout_ms??x_;switch(t){case"go_to_url":case"open_tab":{let a=s.url||"";return[`${r}// ${n}: ${Xr(i)}`,`${r}await page.goto(${JSON.stringify(a)}, { waitUntil: 'domcontentloaded' });`]}case"go_back":return[`${r}// ${n}: ${Xr(i)}`,`${r}await page.goBack();`];case"go_forward":return[`${r}// ${n}: ${Xr(i)}`,`${r}await page.goForward();`];case"input_text":{let a=s.text||"",l=xm(e);return l?[`${r}// ${n}: ${Xr(i)}`,`${r}await ${l}.fill(${JSON.stringify(a)}, { timeout: ${o} });`]:null}case"select_dropdown_option":{let a=s.text||s.label||"",l=xm(e);return l?[`${r}// ${n}: ${Xr(i)}`,`${r}await ${l}.selectOption({ label: ${JSON.stringify(a)} }, { timeout: ${o} });`]:null}default:return null}}function Ene(e,t){let r=[],n=t?.version||"unknown";r.push(`// @generated by shiplightai v${n}`),r.push(...UR()),r.push(""),t?.use&&Object.keys(t.use).length>0&&(r.push(`test.use(${JSON.stringify(t.use,null,2)});`),r.push(""));let i=new Set,s={imports:i,actionEntityStore:t?.actionEntityStore};t?.beforeEach&&t.beforeEach.length>0&&(r.push(...MR("beforeEach",t.beforeEach,s)),r.push(""));let o=t?.timeout||t?.skip!==void 0||t?.fail!==void 0||t?.only||t?.slow?{timeout:t.timeout,skip:t.skip,fail:t.fail,only:t.only,slow:t.slow}:void 0;if(t?.parameters&&t.parameters.length>0){let a=t?.testName||e.goal||"Generated test",l=__(t?.tags);for(let u of t.parameters){let d=jR(e,u.values);r.push(...Sm(d,`${l}${co(a)} [${co(u.name)}]`,s,0,o)),r.push("")}}else{let a=t?.testName||e.goal||"Generated test",l=__(t?.tags);r.push(...Sm(e,`${l}${co(a)}`,s,0,o))}return t?.afterEach&&t.afterEach.length>0&&(r.push(""),r.push(...MR("afterEach",t.afterEach,s))),HR(r,i),r.join(`
|
|
6618
6619
|
`)}function Sne(e,t){let r=[],n=t?.version||"unknown";r.push(`// @generated by shiplightai v${n}`),r.push(...UR()),r.push(""),t?.use&&Object.keys(t.use).length>0&&(r.push(`test.use(${JSON.stringify(t.use,null,2)});`),r.push(""));let i=new Set,s={imports:i,actionEntityStore:t?.actionEntityStore},o=t?.testName||"Test Suite",a=__(t?.tags);r.push(`test.describe.serial('${a}${co(o)}', () => {`),e.beforeAll&&e.beforeAll.length>0&&(r.push(...vm("beforeAll",e.beforeAll,s,1)),r.push("")),e.beforeEach&&e.beforeEach.length>0&&(r.push(...vm("beforeEach",e.beforeEach,s,1)),r.push(""));for(let u=0;u<e.tests.length;u++){let d=e.tests[u],p=d.timeout||d.skip!==void 0||d.fail!==void 0||d.only||d.slow?{timeout:d.timeout,skip:d.skip,fail:d.fail,only:d.only,slow:d.slow}:void 0;if(d.parameters&&d.parameters.length>0)for(let h of d.parameters){let m=jR(d.testFlow,h.values);r.push(...Sm(m,`${co(d.name)} [${co(h.name)}]`,s,1,p)),r.push("")}else r.push(...Sm(d.testFlow,co(d.name),s,1,p)),(u<e.tests.length-1||e.afterEach||e.afterAll)&&r.push("")}return e.afterEach&&e.afterEach.length>0&&(r.push(...vm("afterEach",e.afterEach,s,1)),r.push("")),e.afterAll&&e.afterAll.length>0&&r.push(...vm("afterAll",e.afterAll,s,1)),r.push("});"),HR(r,i),r.join(`
|
|
6619
6620
|
`)}function __(e){return e&&e.length>0?e.map(t=>`@${t}`).join(" ")+" ":""}function Em(e){let t=new Set;function r(n){for(let i of n)switch(i.type){case rs.ACTION:{let o=i.action_entity?.action_data?.kwargs;if(o?.args&&Array.isArray(o.args))for(let a of o.args)typeof a=="string"&&Ane.includes(a)&&t.add(a);break}case rs.STEP:r(i.statements);break;case rs.IF_ELSE:{let s=i;r(s.then),s.else&&r(s.else);break}case rs.WHILE_LOOP:r(i.body);break}}return r(e),t}function Tne(e){let t=Em(e.statements??[]);if(e.teardown)for(let r of Em(e.teardown))t.add(r);return t}function E_(e){return`{ ${["page","agent",...Array.from(e).sort()].join(", ")} }`}function Sm(e,t,r,n=0,i){let s=" ".repeat(n),o=[],a=Tne(e),l=E_(a),u=i?.only?"test.only":"test";o.push(`${s}${u}('${t}', async (${l}) => {`),i?.skip===!0?o.push(`${s} test.skip();`):typeof i?.skip=="string"&&o.push(`${s} test.skip(true, '${co(i.skip)}');`),i?.fail===!0?o.push(`${s} test.fail();`):typeof i?.fail=="string"&&o.push(`${s} test.fail(true, '${co(i.fail)}');`),i?.slow&&o.push(`${s} test.slow();`),i?.timeout&&o.push(`${s} test.setTimeout(${i.timeout});`);let d=e.teardown&&e.teardown.length>0,p=n+1;if(d){if(o.push(`${s} try {`),e.statements&&e.statements.length>0){o.push(`${s} // Test steps`);let m=Cs(e.statements,p+1,r);o.push(...m)}o.push(`${s} } finally {`),o.push(`${s} // Teardown`);let h=Cs(e.teardown,p+1,r,"teardown");o.push(...h),o.push(`${s} }`)}else if(e.statements&&e.statements.length>0){o.push(`${s} // Test steps`);let h=Cs(e.statements,p,r);o.push(...h)}return o.push(`${s}});`),o}function MR(e,t,r){let n=[],i=$R(t),s=Em(i),o=E_(s);return n.push(`test.${e}(async (${o}) => {`),n.push(...Cs(i,1,r,e)),n.push("});"),n}function vm(e,t,r,n){let i=" ".repeat(n),s=[],o=$R(t);if(e==="beforeAll"||e==="afterAll"){let l={...r,noAgent:!0};s.push(`${i}test.${e}(async ({ browser }, workerInfo) => {`),s.push(`${i} const page = await browser.newPage({ baseURL: workerInfo.project.use.baseURL });`),s.push(...Cs(o,n+1,l,e)),s.push(`${i} await page.close();`),s.push(`${i}});`)}else{let l=Em(o),u=E_(l);s.push(`${i}test.${e}(async (${u}) => {`),s.push(...Cs(o,n+1,r,e)),s.push(`${i}});`)}return s}function $R(e){let r=cne({goal:"_hook",statements:e});return $n(r).statements??[]}function jR(e,t){let r=rl(e);for(let[n,i]of Object.entries(t))r=r.split(`<<${n}>>`).join(String(i));return $n(r)}function UR(){return["import { test, expect } from 'shiplightai/fixture';"]}function HR(e,t){if(t.size>0){let r=0;for(let i=0;i<e.length;i++)e[i].startsWith("import ")&&(r=i+1);let n=Array.from(t);e.splice(r,0,...n)}}function GR(e,t,r){let n={expandingPaths:new Set([v_(t)]),depth:0,referencedPaths:new Set,basePath:r},i={...e};Array.isArray(i.statements)&&(i.statements=ia(i.statements,t,n)),Array.isArray(i.teardown)&&(i.teardown=ia(i.teardown,t,n));for(let s of["beforeAll","afterAll","beforeEach","afterEach"])Array.isArray(i[s])&&(i[s]=ia(i[s],t,n));return{doc:i,referencedTemplatePaths:Array.from(n.referencedPaths)}}function ia(e,t,r){let n=[];for(let i of e)if(Dne(i)){let s=Rne(i,t,r);n.push(s)}else n.push(Lne(i,t,r));return n}function Dne(e){return typeof e=="object"&&e!==null&&typeof e.template=="string"}function Rne(e,t,r){if(r.depth>=BR)throw new Error(`Template expansion exceeded maximum depth of ${BR}. Check for deeply nested or circular template references.`);let n=v_(One(t),e.template),i=!Pne(n)&&r.basePath?v_(r.basePath,e.template):n;if(r.expandingPaths.has(i))throw new Error(`Circular template reference detected: ${i} is already being expanded. Stack: ${Array.from(r.expandingPaths).join(" \u2192 ")} \u2192 ${i}`);r.referencedPaths.add(i);let s;try{s=Ine(i,"utf-8")}catch(y){throw new Error(`Failed to read template file: ${i} (referenced from ${t}): ${y.message}`)}let o=FR(s);if(!o||typeof o!="object")throw new Error(`Invalid template file: ${i} \u2014 expected a YAML object`);let a=o.params||[],l=e.params||{};for(let y of a)if(!(y in l))throw new Error(`Template ${e.template} requires param "${y}" but it was not provided. Required params: [${a.join(", ")}]`);let u=o.statements;if(!Array.isArray(u))throw new Error(`Template ${e.template} must have a "statements" array`);if(Object.keys(l).length>0){let b=Nne(u);for(let[w,E]of Object.entries(l))b=b.split(`<<${w}>>`).join(String(E));u=FR(b)}let d={expandingPaths:new Set([...r.expandingPaths,i]),depth:r.depth+1,referencedPaths:r.referencedPaths},p=ia(u,i,d),m={STEP:o.name||e.template.replace(/\.yaml$/,"").split("/").pop()||e.template,template_path:e.template,statements:p};return Object.keys(l).length>0&&(m.template_params=l),m}function Lne(e,t,r){if(typeof e!="object"||e===null)return e;let n={...e};return Array.isArray(n.statements)&&(n.statements=ia(n.statements,t,r)),Array.isArray(n.THEN)&&(n.THEN=ia(n.THEN,t,r)),Array.isArray(n.ELSE)&&(n.ELSE=ia(n.ELSE,t,r)),Array.isArray(n.DO)&&(n.DO=ia(n.DO,t,r)),n}function Mne(e,t,r){let n=kne(e),i=n?.name,s=n?.tags,o=n?.use;if(n&&(n.name!==void 0||n.tags!==void 0||n.use!==void 0)&&(delete n.name,delete n.tags,delete n.use),n?.suite){if(n.goal||n.statements)throw new S_('YAML file cannot have both "suite" and top-level "goal"/"statements". Use either suite format or single-test format.');return Bne(n,i,s,o,t,r)}return Fne(n,i,s,o,t,r)}function Fne(e,t,r,n,i,s){let o=e?.beforeEach,a=e?.afterEach,l=WR(e?.parameters),u=e?.timeout,d=e?.skip,p=e?.fail,h=e?.only,m=e?.slow,y=e?.settings,b=n;if(y){let C={};y.auto_dismiss_modal!==void 0&&(C.autoDismissModal=!!y.auto_dismiss_modal),y.browser_timezone!==void 0&&y.browser_timezone!==null&&(C.timezoneId=String(y.browser_timezone)),y.browser_language!==void 0&&y.browser_language!==null&&(C.locale=String(y.browser_language)),y.extra_http_headers!==void 0&&y.extra_http_headers!==null&&typeof y.extra_http_headers=="object"&&(C.extraHTTPHeaders=y.extra_http_headers),Object.keys(C).length>0&&(b={...b,...C})}if(e&&(delete e.beforeEach,delete e.afterEach,delete e.parameters,delete e.timeout,delete e.skip,delete e.fail,delete e.only,delete e.slow,delete e.settings),e?.url)throw new S_(`The "url" field is not supported in local YAML tests. Use "base_url: ${e.url}" and add "- URL: /" as the first statement instead.`);e&&!e.goal&&t&&(e.goal=t);let w=[];if(i&&e&&typeof e=="object"){let C=GR(e,i,s);e=C.doc,w=C.referencedTemplatePaths}let E=qR(e),x=$n(E);return i&&(Rc(x.statements??[],i,"main"),x.teardown&&Rc(x.teardown,i,"teardown")),{testFlow:x,name:t,tags:r,use:b,beforeEach:o,afterEach:a,parameters:l,timeout:u,skip:d,fail:p,only:h,slow:m,referencedTemplatePaths:w}}function Bne(e,t,r,n,i,s){let o=e.suite;if(!Array.isArray(o.tests)||o.tests.length===0)throw new Error('Suite must have a non-empty "tests" array.');let a=o.beforeAll,l=o.afterAll,u=o.beforeEach,d=o.afterEach,p=[],h=o.tests.map(b=>{if(!b.name)throw new Error('Each test in a suite must have a "name" field.');if(!Array.isArray(b.statements)||b.statements.length===0)throw new Error(`Suite test "${b.name}" must have a non-empty "statements" array.`);let w={goal:b.name,statements:b.statements};b.teardown&&(w.teardown=b.teardown);let E=[],x=w;if(i&&typeof w=="object"){let T=GR(w,i,s);x=T.doc,E=T.referencedTemplatePaths,p.push(...E)}let C=qR(x),R=$n(C),k=WR(b.parameters);return{testFlow:R,name:b.name,tags:Array.isArray(b.tags)?b.tags:void 0,parameters:k,timeout:b.timeout,skip:b.skip,fail:b.fail,only:b.only,slow:b.slow}}),m=o.base_url,y=m?{...n,baseURL:m}:n;return{suite:{beforeAll:a,afterAll:l,beforeEach:u,afterEach:d,tests:h},name:t,tags:r,use:y,referencedTemplatePaths:p}}function WR(e){if(!(!Array.isArray(e)||e.length===0))return e.map((t,r)=>{if(!t.name)throw new Error(`Parameter set at index ${r} must have a "name" field.`);if(!t.values||typeof t.values!="object")throw new Error(`Parameter set "${t.name}" must have a "values" object.`);return{name:t.name,values:t.values}})}function Rc(e,t,r){for(let n=0;n<e.length;n++){let i=e[n],s=`${r}.${n}`,o=i.description||"";if(i.uid=$ne(t,s,o),i.type===rs.STEP)Rc(i.statements,t,s);else if(i.type===rs.IF_ELSE){let a=i;Rc(a.then,t,`${s}.then`),a.else&&Rc(a.else,t,`${s}.else`)}else i.type===rs.WHILE_LOOP&&Rc(i.body,t,`${s}.body`)}}function $ne(e,t,r){let n=Cne("sha256").update(`${e}:${t}:${r}`).digest("hex");return`${n.slice(0,8)}-${n.slice(8,12)}-${n.slice(12,16)}-${n.slice(16,20)}-${n.slice(20,32)}`}function VR(e,t){let r;try{r=jne(e,"utf-8")}catch(n){return{valid:!1,errors:[`Failed to read file: ${n.message}`],warnings:[]}}return Gne(r,e,t)}function Gne(e,t,r){let n=/\btemplate:\s/.test(e),i=/^suite:/m.test(e),s=n||i?null:u_(e);if(s&&!s.valid)return{valid:!1,errors:s.errors,warnings:[],stats:s.stats};let o,a,l=[];try{let u=r?.parsed??Mne(e,t);l=u.referencedTemplatePaths;let d={version:r?.version,actionEntityStore:r?.actionEntityStore},p=u.testFlow?.baseURL?{...u.use,baseURL:u.testFlow.baseURL}:u.use;u.suite?o=Sne(u.suite,{...d,testName:u.name,tags:u.tags,use:u.use}):o=Ene(u.testFlow,{...d,testName:u.name,tags:u.tags,use:p,beforeEach:u.beforeEach,afterEach:u.afterEach,parameters:u.parameters,timeout:u.timeout,skip:u.skip,fail:u.fail,only:u.only,slow:u.slow});let h=o.split(`
|
|
6620
6621
|
`).filter(m=>!m.startsWith("import ")).join(`
|
|
@@ -6682,8 +6683,8 @@ Returns:
|
|
|
6682
6683
|
|
|
6683
6684
|
Returns locator, xpath, frame path, tag name, and text for each element.
|
|
6684
6685
|
Use this to collect locator data for building test flows without interacting
|
|
6685
|
-
with the page. Pass multiple indices in a single call to save round-trips.`};Am=null,Tm=null;XR=class Bc{constructor(t){this.backend=t}static navigateTool={...P_,inputSchema:ol(Om,{$refStrategy:"none"})};async navigate(t){let r=Om.parse(t),n=await O_(this.backend,r);return JSON.stringify(n)}static get actTool(){return V_()}async act(t){let r=N_.parse(t),n=await R_(this.backend,r);return JSON.stringify(n)}static updateVariablesTool={...L_,inputSchema:ol(Nm,{$refStrategy:"none"})};async updateVariables(t){let r=Nm.parse(t),n=M_(this.backend,r);return JSON.stringify(n)}static clearExecutionHistoryTool={...F_,inputSchema:ol(Dm,{$refStrategy:"none"})};async clearExecutionHistory(t){let r=Dm.parse(t),n=B_(this.backend,r);return JSON.stringify(n)}static getPageInfoTool={...$_,inputSchema:ol(Rm,{$refStrategy:"none"})};async getPageInfo(t){let r=Rm.parse(t),n=await j_(this.backend,r);return JSON.stringify(n)}static inspectPageTool={...U_,inputSchema:ol(Lm,{$refStrategy:"none"})};async inspectPage(t){let r=Lm.parse(t),n=await H_(this.backend,r);return JSON.stringify(n)}static getLocatorsTool={...q_,inputSchema:ol(Mm,{$refStrategy:"none"})};async getLocators(t){let r=Mm.parse(t),n=await G_(this.backend,r);return JSON.stringify(n)}static get toolDefinitions(){return[Bc.navigateTool,Bc.getPageInfoTool,Bc.inspectPageTool,Bc.actTool,Bc.getLocatorsTool]}},ZR=class Im{constructor(t){this.backend=t}static getConsoleLogsTool={name:"get_browser_console_logs",description:"Get console logs from the browser (errors, warnings, etc.)",inputSchema:Cm(ur.object({session_id:ur.string().describe("Browser session ID"),since_timestamp:ur.number().optional().describe("Only return logs after this timestamp"),log_types:ur.array(ur.string()).optional().describe("Filter by log types (e.g., ['error', 'warning'])")}),{$refStrategy:"none"})};async getConsoleLogs(t){let{session_id:r,since_timestamp:n,log_types:i}=ur.object({session_id:ur.string(),since_timestamp:ur.number().optional(),log_types:ur.array(ur.string()).optional()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);let o=this.backend.getConsoleLogs(r,{sinceTimestamp:n,logTypes:i});return JSON.stringify({session_id:r,log_count:o.length,logs:o.slice(-100)})}static getNetworkLogsTool={name:"get_browser_network_logs",description:"Get network request logs from the browser",inputSchema:Cm(ur.object({session_id:ur.string().describe("Browser session ID"),since_timestamp:ur.number().optional().describe("Only return logs after this timestamp"),status_filter:ur.enum(["errors","success"]).optional().describe("Filter by HTTP status (errors: 4xx/5xx, success: 2xx)")}),{$refStrategy:"none"})};async getNetworkLogs(t){let{session_id:r,since_timestamp:n,status_filter:i}=ur.object({session_id:ur.string(),since_timestamp:ur.number().optional(),status_filter:ur.enum(["errors","success"]).optional()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);let o=this.backend.getNetworkLogs(r,{sinceTimestamp:n,statusFilter:i});return JSON.stringify({session_id:r,log_count:o.length,logs:o.slice(-100)})}static clearLogsTool={name:"clear_logs",description:"Clear console and network logs for a session",inputSchema:Cm(ur.object({session_id:ur.string().describe("Browser session ID")}),{$refStrategy:"none"})};async clearLogs(t){let{session_id:r}=ur.object({session_id:ur.string()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);return this.backend.clearLogs(r),JSON.stringify({session_id:r,message:"Logs cleared successfully"})}static getLocalArtifactTool={name:"get_local_artifact",description:"Get a local artifact file (screenshot, DOM snapshot, etc.) from a live browser session. Only accepts local file paths, NOT S3 URIs. For test run artifacts, use get_step_artifacts instead.",inputSchema:Cm(ur.object({path:ur.string().describe("Artifact file path from previous tool output"),return_format:ur.enum(["base64","text"]).optional().describe("Return format (auto-detected if not specified)")}),{$refStrategy:"none"})};async getLocalArtifact(t){let{path:r}=ur.object({path:ur.string(),return_format:ur.enum(["base64","text"]).optional()}).parse(t),n=await this.backend.getLocalArtifact(r);return JSON.stringify({path:r,format:n.format,size:n.size,data:n.data})}static toolDefinitions=[Im.getConsoleLogsTool,Im.getNetworkLogsTool,Im.clearLogsTool]};QR=class al{constructor(t){this.apiClient=t}requireApi(t){if(!this.apiClient)throw new Error(jc(t));return this.apiClient}static listEnvironmentsTool={name:"list_environments",description:"List all testing environments (staging, production, etc.)",inputSchema:Mc(tr.object({}),{$refStrategy:"none"})};async listEnvironments(t){let n=await this.requireApi("list_environments").listEnvironments();return JSON.stringify({environments:n.map(i=>({id:i.id,name:i.name,url:i.url}))})}static listTestAccountsTool={name:"list_test_accounts",description:"List test accounts for a specific environment. Requires either environment_id or environment_url.",inputSchema:Mc(tr.object({environment_id:tr.number().optional().describe("Environment ID to filter by"),environment_url:tr.string().optional().describe("Environment URL to filter by (alternative to environment_id)")}),{$refStrategy:"none"})};async listTestAccounts(t){let r=this.requireApi("list_test_accounts"),{environment_id:n,environment_url:i}=tr.object({environment_id:tr.number().optional(),environment_url:tr.string().optional()}).parse(t),s=await r.listTestAccounts(n,i);return JSON.stringify({test_accounts:s.map(o=>({id:o.id,name:o.name,username:o.username,environment_id:o.environmentId||o.environment_id}))})}static getTestAccountTool={name:"get_test_account",description:"Get a specific test account by ID",inputSchema:Mc(tr.object({test_account_id:tr.number().describe("Test account ID")}),{$refStrategy:"none"})};async getTestAccount(t){let r=this.requireApi("get_test_account"),{test_account_id:n}=tr.object({test_account_id:tr.number()}).parse(t),i=await r.getTestAccount(n);return JSON.stringify({test_account:i})}static listFoldersTool={name:"list_folders",description:"List test case folders",inputSchema:Mc(tr.object({parent_id:tr.number().nullable().optional().describe("Parent folder ID, null for root"),search:tr.string().optional().describe("Search query")}),{$refStrategy:"none"})};async listFolders(t){let r=this.requireApi("list_folders"),{parent_id:n,search:i}=tr.object({parent_id:tr.number().nullable().optional(),search:tr.string().optional()}).parse(t),s=await r.listFolders(n,i);return JSON.stringify({folders:s.map(o=>({id:o.id,name:o.name,parent_id:o.parentId||o.parent_id,path:o.pathIds}))})}static createFolderTool={name:"create_folder",description:"Create a new test case folder",inputSchema:Mc(tr.object({name:tr.string().describe("Folder name"),description:tr.string().optional().describe("Folder description"),parent_id:tr.number().nullable().optional().describe("Parent folder ID")}),{$refStrategy:"none"})};async createFolder(t){let r=this.requireApi("create_folder"),{name:n,description:i,parent_id:s}=tr.object({name:tr.string(),description:tr.string().optional(),parent_id:tr.number().nullable().optional()}).parse(t),o=await r.createFolder({name:n,description:i,parentId:s});return JSON.stringify({folder_id:o.id,message:"Folder created successfully"})}static getFolderTool={name:"get_folder",description:"Get folder details with full hierarchical path",inputSchema:Mc(tr.object({folder_id:tr.number().describe("Folder ID")}),{$refStrategy:"none"})};async getFolder(t){let r=this.requireApi("get_folder"),{folder_id:n}=tr.object({folder_id:tr.number()}).parse(t),i=await r.getFolder(n);return JSON.stringify({folder:i})}static toolDefinitions=[al.listEnvironmentsTool,al.listTestAccountsTool,al.getTestAccountTool,al.listFoldersTool,al.createFolderTool,al.getFolderTool]};qd=class uo{constructor(t){this.apiClient=t}requireApi(t){if(!this.apiClient)throw new Error(jc(t));return this.apiClient}parseFlowInput(t){return typeof t=="string"?Qo.parse($n(t)):Qo.parse(t)}readTextFile(t,r){try{return Fm(t,"utf-8")}catch(n){let i=n instanceof Error?n.message:String(n);throw new Error(`Failed to read ${r} file at ${t}: ${i}`)}}extractFunctionCodeFromFile(t,r){let n=this.readTextFile(t,`function "${r}"`),i=Zr.createSourceFile(t,n,Zr.ScriptTarget.Latest,!0,Zr.ScriptKind.TS),s=u=>n.slice(u.getStart(i),u.getEnd()),o=(u,d,p)=>{let h=u.map(y=>s(y)).join(", ");return`${p?"async ":""}(${h}) => ${s(d)}`},a=null,l=u=>{if(!Zr.isVariableStatement(u))return!1;for(let d of u.declarationList.declarations)if(!(!Zr.isIdentifier(d.name)||d.name.text!==r||!d.initializer)){if(Zr.isArrowFunction(d.initializer))return a=s(d.initializer),!0;if(Zr.isFunctionExpression(d.initializer))return a=o(d.initializer.parameters,d.initializer.body,d.initializer.modifiers?.some(p=>p.kind===Zr.SyntaxKind.AsyncKeyword)??!1),!0}return!1};for(let u of i.statements){if(Zr.isFunctionDeclaration(u)&&u.name?.text===r&&u.body){a=o(u.parameters,u.body,u.modifiers?.some(d=>d.kind===Zr.SyntaxKind.AsyncKeyword)??!1);break}if(l(u))break;Zr.isExportDeclaration(u)||Zr.isExportAssignment(u)}if(!a)throw new Error(`Could not find function "${r}" in ${t}`);return a}stripTypeAnnotations(t){let r=`const __fn = ${t};`,n;try{n=Zr.transpileModule(r,{compilerOptions:{target:Zr.ScriptTarget.ES2020,module:Zr.ModuleKind.ESNext}}).outputText}catch(s){throw new Error(`Failed to strip TypeScript types from function code: ${s.message}`)}let i=Zr.createSourceFile("__fn.ts",n,Zr.ScriptTarget.ES2020,!0);for(let s of i.statements)if(Zr.isVariableStatement(s)&&s.declarationList.declarations.length===1){let o=s.declarationList.declarations[0];if(Zr.isIdentifier(o.name)&&o.name.text==="__fn"&&o.initializer)return n.slice(o.initializer.getStart(i),o.initializer.getEnd()).trim()}throw new Error("Failed to strip TypeScript types: could not locate function expression in transpiler output")}static createTestCaseTool={name:"create_test_case",description:"Create a test case from a flow (test flow JSON object or YAML string). IMPORTANT: Read 'shiplight://schemas/testflow-json-v1.2.0' for the required flow format. Accepts a test flow as JSON object or YAML string. Include action_entity with locator/xpath on ACTION statements when available - this speeds up test execution.",inputSchema:ks(Le.object({flow:Le.union([Le.string(),Le.any()]).describe("Test flow as JSON object or YAML string"),folder_id:Le.number().optional().describe("Folder ID"),name:Le.string().optional().describe("Test case name"),environment_id:Le.number().optional().describe("Environment ID for test execution"),test_account_id:Le.number().optional().describe("Optional test account ID for login")}),{$refStrategy:"none"})};async createTestCase(t){let r=this.requireApi("create_test_case"),{flow:n,folder_id:i,name:s,environment_id:o,test_account_id:a}=Le.object({flow:Le.any(),folder_id:Le.number().optional(),name:Le.string().optional(),environment_id:Le.number().optional(),test_account_id:Le.number().optional()}).parse(t),l;try{l=this.parseFlowInput(n)}catch(b){throw b instanceof Le.ZodError?new Error(`Invalid TestFlow schema: ${JSON.stringify(b.errors)}`):b}let u={...l,version:l.testGroup?"1.3.0":"1.2.0",statements:this.regenerateUids(l.statements??[]),teardown:l.teardown?this.regenerateUids(l.teardown):void 0,testGroup:l.testGroup?this.regenerateGroupUids(l.testGroup):void 0},d=l.url||l.baseURL,p=o;if(p===void 0&&d)try{let b=await r.listEnvironments(),w=Xne(d,b);w&&(p=w.id)}catch{}let h;p!==void 0&&(h=[{environment_id:p,test_account_group:a?{type:"Specific",account_ids:[a]}:{type:"None",account_ids:[]},path:""}]);let m=await r.createTestCase({title:s||l.goal||"Untitled",testFlow:u,folderId:i,environmentConfigs:h}),y=this.computeFlowStats(l.statements??[],l.teardown);return JSON.stringify({...m,environment_id:p??null,test_account_id:a??null,yaml:rl(l,{test_case_id:m.test_case_id}),flow_stats:y})}static updateTestCaseTool={name:"update_test_case",description:"Update a test case from a flow (test flow JSON object or YAML string). IMPORTANT: Read 'shiplight://schemas/testflow-json-v1.2.0' for the required flow format. Accepts a test flow as JSON object or YAML string. Include action_entity with locator/xpath on ACTION statements when available - this speeds up test execution.",inputSchema:ks(Le.object({test_case_id:Le.number().describe("Test case ID"),flow:Le.union([Le.string(),Le.any()]).describe("Test flow as JSON object or YAML string"),title:Le.string().optional().describe("New title"),environment_id:Le.number().optional().describe("Environment ID to set/update"),test_account_id:Le.number().optional().describe("Test account ID to associate")}),{$refStrategy:"none"})};async updateTestCase(t){let r=this.requireApi("update_test_case"),{test_case_id:n,flow:i,title:s,environment_id:o,test_account_id:a}=Le.object({test_case_id:Le.number(),flow:Le.any(),title:Le.string().optional(),environment_id:Le.number().optional(),test_account_id:Le.number().optional()}).parse(t),l;try{l=this.parseFlowInput(i)}catch(m){throw m instanceof Le.ZodError?new Error(`Invalid TestFlow schema: ${JSON.stringify(m.errors)}`):m}let u={...l,version:l.testGroup?"1.3.0":"1.2.0",statements:this.regenerateUids(l.statements??[]),teardown:l.teardown?this.regenerateUids(l.teardown):void 0,testGroup:l.testGroup?this.regenerateGroupUids(l.testGroup):void 0},d;o!==void 0&&(d=[{environment_id:o,test_account_group:a?{type:"Specific",account_ids:[a]}:{type:"None",account_ids:[]}}]);let p=await r.updateTestCase(n,{title:s||l.goal||"Untitled",testFlow:u,environmentConfigs:d}),h=this.computeFlowStats(l.statements??[],l.teardown);return JSON.stringify({...p,flow_stats:h})}static getTestCaseTool={name:"get_test_case",description:"Get a test case by ID. Use output_format 'yaml' to get the flow as a YAML string.",inputSchema:ks(Le.object({test_case_id:Le.number().describe("Test case ID"),output_format:Le.enum(["json","yaml"]).optional().describe("Output format for the test flow (default: json)")}),{$refStrategy:"none"})};async getTestCase(t){let r=this.requireApi("get_test_case"),{test_case_id:n,output_format:i}=Le.object({test_case_id:Le.number(),output_format:Le.enum(["json","yaml"]).optional()}).parse(t),s=await r.getTestCase(n);if(i==="yaml"&&s.test_flow){let o=rl(s.test_flow,{test_case_id:s.id});return JSON.stringify({test_case:{id:s.id,title:s.title,folder_id:s.folder_id},yaml:o})}return JSON.stringify({test_case:s})}static runTestCaseTool={name:"run_test_case",description:"Trigger cloud execution of a test case. Returns a test_run_id that can be used with get_test_run_details to poll for completion and results.",inputSchema:ks(Le.object({test_case_id:Le.number().describe("Test case ID to run"),environment_id:Le.number().optional().describe("Environment ID to run against (uses test case default if not specified)")}),{$refStrategy:"none"})};async runTestCase(t){let r=this.requireApi("run_test_case"),{test_case_id:n,environment_id:i}=Le.object({test_case_id:Le.number(),environment_id:Le.number().optional()}).parse(t),s=await r.runTestCase(n,i);return JSON.stringify({test_run_id:s.id,status:s.status,result:s.result,test_case_result_ids:s.test_case_result_ids,message:`Test run ${s.id} triggered. Use get_test_run_details(${s.id}) to check status and results.`})}static saveTestCaseTool={name:"save_test_case",description:"Save a test case from YAML \u2014 automatically creates or updates based on embedded test_case_id metadata. Prefer file_path over yaml to avoid reading and passing file content (saves tokens). If the YAML contains a test_case_id field, updates that test case; otherwise creates a new one. Returns YAML with test_case_id embedded so you can write it back to the local file for future updates. If the YAML contains 'template:' file references, file_path auto-resolves them (or provide base_path explicitly).",inputSchema:ks(Le.object({file_path:Le.string().optional().describe("Path to a YAML test file on disk (alternative to yaml \u2014 avoids passing file content as a string)"),yaml:Le.string().optional().describe("YAML test flow string (not needed if file_path is provided)"),folder_id:Le.number().optional().describe("Folder ID (only used on create)"),name:Le.string().optional().describe("Test case name (defaults to flow goal)"),environment_id:Le.number().optional().describe("Environment ID for test execution"),test_account_id:Le.number().optional().describe("Test account ID for login"),base_path:Le.string().optional().describe("Base directory for resolving template: file references (auto-derived from file_path if not specified)")}),{$refStrategy:"none"})};resolveLocalReferences(t,r){return Zne(t,r)}async saveTestCase(t){let{file_path:r,yaml:n,folder_id:i,name:s,environment_id:o,test_account_id:a,base_path:l}=Le.object({file_path:Le.string().optional(),yaml:Le.string().optional(),folder_id:Le.number().optional(),name:Le.string().optional(),environment_id:Le.number().optional(),test_account_id:Le.number().optional(),base_path:Le.string().optional()}).refine(y=>y.file_path||y.yaml,{message:"Either file_path or yaml must be provided"}).parse(t),u=r?this.readTextFile(r,"test case"):n,d=l??(r?eL(r):void 0),p=d?this.resolveLocalReferences(u,d):u,h=om(u),m=s||h.name;if(h.test_case_id!==void 0){let y=await this.updateTestCase({test_case_id:h.test_case_id,flow:p,title:m,environment_id:o,test_account_id:a}),b=JSON.parse(y),w=this.parseFlowInput(p);return JSON.stringify({...b,yaml:rl(w,{test_case_id:h.test_case_id})})}else return await this.createTestCase({flow:p,folder_id:i,name:m,environment_id:o,test_account_id:a})}computeFlowStats(t,r){let n=[...ea(t),...r?ea(r):[]],{action:i,draft:s}=cm(n),o=i+s,a=o>0?Math.round(i/o*100):0,l={total:o,draft_statements:s,enriched_statements:i,coverage:a};return s>0&&(l.hint=`${s} draft statement(s) (~10-15s each at runtime vs ~1s enriched). Consider converting drafts to actions with action/js.`),l}regenerateUids(t){return t.map(r=>{let n={...r,uid:Yne()};return r.type==="STEP"&&r.statements?n.statements=this.regenerateUids(r.statements):r.type==="IF_ELSE"?(r.then&&(n.then=this.regenerateUids(r.then)),r.else&&(n.else=this.regenerateUids(r.else))):r.type==="WHILE_LOOP"&&r.body&&(n.body=this.regenerateUids(r.body)),n})}regenerateGroupUids(t){let r=n=>n?this.regenerateUids(n):void 0;return{...t,tests:t.tests.map(n=>({...n,statements:this.regenerateUids(n.statements),teardown:n.teardown?this.regenerateUids(n.teardown):void 0})),beforeAll:r(t.beforeAll),afterAll:r(t.afterAll),beforeEach:r(t.beforeEach),afterEach:r(t.afterEach)}}static saveTemplateTool={name:"save_template",description:"Save a template (reusable step group) \u2014 automatically creates or updates based on template_id. Prefer file_path over yaml to avoid reading and passing file content (saves tokens). For partial updates, provide template_id with only the fields to change (e.g. name, description) \u2014 file_path/yaml not required. For create or full update, provide file_path or yaml with statements.",inputSchema:ks(Le.object({file_path:Le.string().optional().describe("Path to a YAML template file on disk (alternative to yaml \u2014 avoids passing file content as a string)"),yaml:Le.string().optional().describe("YAML template string with name, optional params, and statements (not needed if file_path is provided)"),template_id:Le.number().optional().describe("Template ID for updates (overrides embedded template_id)"),name:Le.string().optional().describe("Template name (overrides embedded name)"),description:Le.string().optional().describe("Template description")}),{$refStrategy:"none"})};async saveTemplate(t){let r=this.requireApi("save_template");if(!r.createReusableStep||!r.updateReusableStep)throw new Error("API client does not support reusable steps");let{file_path:n,yaml:i,template_id:s,name:o,description:a}=Le.object({file_path:Le.string().optional(),yaml:Le.string().optional(),template_id:Le.number().optional(),name:Le.string().optional(),description:Le.string().optional()}).parse(t),l=n||i;if(s&&!l){let E={};if(o!==void 0&&(E.name=o),a!==void 0&&(E.description=a),Object.keys(E).length===0)throw new Error("Partial update requires at least one field to change (name, description)");let x=await r.updateReusableStep(s,E);return JSON.stringify({success:!0,message:"Template updated successfully (partial)",template_id:x.id,name:x.name})}if(!l)throw new Error("Either file_path or yaml must be provided (or template_id for partial updates)");let u=n?this.readTextFile(n,"template"):i,d=om(u),p=s??d.template_id,h=o??d.name??"Untitled Template",m=u.includes("goal:")?u:`goal: "${h}"
|
|
6686
|
-
${u}`,y=$n(m),b=this.regenerateUids(y.statements??[]),w={name:h,description:a??y.goal??h,statements:b};if(p){let E=await r.updateReusableStep(p,w);return JSON.stringify({success:!0,message:"Template updated successfully",template_id:E.id,name:E.name,statement_count:E.statements?.length??0})}else{let E=await r.createReusableStep(w);return JSON.stringify({success:!0,message:"Template created successfully",template_id:E.id,name:E.name,statement_count:E.statements?.length??0})}}static saveFunctionTool={name:"save_function",description:"Save a test function to the cloud \u2014 automatically creates or updates based on function_id. Prefer file_path over code to avoid reading and passing file content (saves tokens). For partial updates, provide function_id with only the fields to change (e.g. name, description) \u2014 file_path/code not required. For create or full update, provide name and either file_path or code.",inputSchema:ks(Le.object({file_path:Le.string().optional().describe("Path to a TypeScript file on disk (alternative to code \u2014 avoids passing file content as a string)"),function_id:Le.number().optional().describe("Function ID for updates"),name:Le.string().optional().describe("Function name in snake_case (e.g. 'get_cart_count') \u2014 required for create"),code:Le.string().optional().describe("Function code body (not needed if file_path is provided)"),description:Le.string().optional().describe("Function description")}),{$refStrategy:"none"})};async saveFunction(t){let r=this.requireApi("save_function");if(!r.createTestFunction||!r.updateTestFunction)throw new Error("API client does not support test functions");let{file_path:n,function_id:i,name:s,code:o,description:a}=Le.object({file_path:Le.string().optional(),function_id:Le.number().optional(),name:Le.string().optional(),code:Le.string().optional(),description:Le.string().optional()}).parse(t),l=n||o;if(i!=null&&!l){let h={};if(s!==void 0&&(h.name=s),a!==void 0&&(h.description=a),Object.keys(h).length===0)throw new Error("Partial update requires at least one field to change (name, description)");let m=await r.updateTestFunction(i,h);return JSON.stringify({success:!0,message:"Function updated successfully (partial)",function_id:m.id,name:m.name})}if(!s)throw new Error("name is required for creating or fully updating a function");if(!l)throw new Error("Either file_path or code must be provided (or function_id for partial updates)");let u=n?this.extractFunctionCodeFromFile(n,s):o,d=this.stripTypeAnnotations(u),p={name:s,code:d,description:a};if(i!=null){let h=await r.updateTestFunction(i,p);return JSON.stringify({success:!0,message:"Function updated successfully",function_id:h.id,name:h.name})}else{let h=await r.createTestFunction(p);return JSON.stringify({success:!0,message:"Function created successfully",function_id:h.id,name:h.name})}}static saveTestAccountTool={name:"save_test_account",description:"Create or update a test account \u2014 automatically creates if no test_account_id is provided, updates otherwise. Optionally upload a local storageState file so the cloud runner can reuse saved browser sessions. loginConfig is built automatically from the provided credentials.",inputSchema:ks(Le.object({test_account_id:Le.number().optional().describe("Test account ID for updates"),environment_id:Le.number().describe("Environment ID"),username:Le.string().describe("Username / email"),password:Le.string().describe("Password"),account_type:Le.enum(["password","oauth2"]).optional().describe("Login type (default: password)"),oauth_provider:Le.string().optional().describe("OAuth provider name (required when account_type is oauth2)"),two_factor_auth:Le.object({type:Le.enum(["totp","sms","email"]).describe("2FA type"),data:Le.string().describe("Secret key for TOTP, phone number for SMS, etc.")}).optional().describe("Two-factor authentication configuration"),storage_state_path:Le.string().optional().describe("Path to a local storageState JSON file to upload to the cloud")}),{$refStrategy:"none"})};async saveTestAccount(t){let r=this.requireApi("save_test_account"),{test_account_id:n,environment_id:i,username:s,password:o,account_type:a,oauth_provider:l,two_factor_auth:u,storage_state_path:d}=Le.object({test_account_id:Le.number().optional(),environment_id:Le.number(),username:Le.string(),password:Le.string(),account_type:Le.enum(["password","oauth2"]).optional(),oauth_provider:Le.string().optional(),two_factor_auth:Le.object({type:Le.enum(["totp","sms","email"]),data:Le.string()}).optional(),storage_state_path:Le.string().optional()}).refine(b=>b.account_type!=="oauth2"||!!b.oauth_provider,{message:"oauth_provider is required when account_type is 'oauth2'",path:["oauth_provider"]}).parse(t),p=a??"password",h={account:{type:p,...p==="oauth2"&&l?{provider_name:l}:{},...u?{two_factor_auth_config:u}:{}}},m;n?(r.updateTestAccount&&await r.updateTestAccount(n,{username:s,password:o,environmentId:i,loginConfig:h}),m=n):m=(await r.createTestAccount({environmentId:i,username:s,password:o,loginConfig:h})).id;let y=null;if(d&&r.uploadStorageState){let b=Fm(k_(d),"utf-8"),w=JSON.parse(b);y=await r.uploadStorageState(m,w)}return JSON.stringify({success:!0,message:n?"Test account updated":"Test account created",test_account_id:m,...y?{storage_state:y}:{}})}static getTemplateTool={name:"get_template",description:"Get a template (reusable step group) by ID from the cloud. Returns the template as YAML with embedded template_id, ready to save as a local .yaml file.",inputSchema:ks(Le.object({template_id:Le.number().describe("Template ID")}),{$refStrategy:"none"})};async getTemplate(t){let r=this.requireApi("get_template");if(!r.getReusableStep)throw new Error("API client does not support reusable steps");let{template_id:n}=Le.object({template_id:Le.number()}).parse(t),i=await r.getReusableStep(n),s={template_id:i.id,name:i.name};i.description&&(s.description=i.description);let o={goal:i.name,url:"",statements:i.statements},a=sm(o);s.statements=a.statements;let l=I_(s,{lineWidth:120,defaultKeyType:"PLAIN",defaultStringType:"PLAIN"});return JSON.stringify({template_id:i.id,name:i.name,description:i.description,statement_count:i.statements?.length??0,yaml:l})}static getFunctionTool={name:"get_function",description:"Get a test function by ID from the cloud. Returns the function name, description, and code.",inputSchema:ks(Le.object({function_id:Le.number().describe("Function ID")}),{$refStrategy:"none"})};async getFunction(t){let r=this.requireApi("get_function");if(!r.getTestFunction)throw new Error("API client does not support test functions");let{function_id:n}=Le.object({function_id:Le.number()}).parse(t),i=await r.getTestFunction(n);return JSON.stringify({function_id:i.id,name:i.name,description:i.description,code:i.code})}static toolDefinitions=[uo.getTestCaseTool,uo.getTemplateTool,uo.getFunctionTool,uo.runTestCaseTool,uo.saveTestCaseTool,uo.saveTestAccountTool,uo.saveTemplateTool,uo.saveFunctionTool]};rie=3600*1e3,km=Pm.join(eie.tmpdir(),"shiplight-artifacts"),tL=class $c{constructor(t,r){this.apiClient=t,this.options=r||{}}options;requireApi(t){if(!this.apiClient)throw new Error(jc(t));return this.apiClient}getProxyUrl(t){if(!this.options.artifactProxyBaseUrl)return null;let r=t.match(/^s3:\/\/[^/]+\/(.+)$/);if(!r)return null;let n=r[1];return`${this.options.artifactProxyBaseUrl}/api/artifacts/${n}`}cleanupOldArtifacts(){try{if(!sl.existsSync(km))return;let t=Date.now(),r=sl.readdirSync(km,{withFileTypes:!0});for(let n of r){if(!n.isDirectory())continue;let i=Pm.join(km,n.name);try{let s=sl.statSync(i);t-s.mtimeMs>rie&&sl.rmSync(i,{recursive:!0,force:!0})}catch{}}}catch{}}static listTestRunsTool={name:"list_test_runs",description:"List test runs with optional filtering by test plan, trigger type, or result status",inputSchema:jd($t.object({test_plan_id:$t.number().optional().describe("Filter by test plan ID"),trigger:$t.string().optional().describe("Filter by trigger type (Manual, Scheduled, API, GITHUB_ACTION, Webhook, Automation)"),result:$t.string().optional().describe("Filter by result (Passed, Failed, Pending, Skipped, Queued)"),limit:$t.number().optional().describe("Maximum number of results (default 20)")}),{$refStrategy:"none"})};async listTestRuns(t){let r=this.requireApi("list_test_runs"),{test_plan_id:n,trigger:i,result:s,limit:o}=$t.object({test_plan_id:$t.number().optional(),trigger:$t.string().optional(),result:$t.string().optional(),limit:$t.number().optional()}).parse(t),a=await r.listTestRuns({testPlanId:n,trigger:i,result:s,limit:o??20});return JSON.stringify({test_runs:a.map(l=>({id:l.id,status:l.status,result:l.result,trigger:l.trigger,start_time:l.startTime||l.start_time,end_time:l.endTime||l.end_time,duration_ms:l.duration,total_test_case_count:l.totalTestCaseCount||l.total_test_case_count,passed_test_case_count:l.passedTestCaseCount||l.passed_test_case_count,failed_test_case_count:l.failedTestCaseCount||l.failed_test_case_count,skipped_test_case_count:l.skippedTestCaseCount||l.skipped_test_case_count,test_plan_id:l.testPlanId||l.test_plan_id})),count:a.length})}static getTestRunDetailsTool={name:"get_test_run_details",description:"Get detailed information about a test run including all test case results",inputSchema:jd($t.object({test_run_id:$t.number().describe("Test run ID")}),{$refStrategy:"none"})};async getTestRunDetails(t){let r=this.requireApi("get_test_run_details"),{test_run_id:n}=$t.object({test_run_id:$t.number()}).parse(t),i=await r.getTestRunDetails(n),s=i.testRun||i,o=i.testCaseResults||[];return JSON.stringify({test_run:{id:s.id,status:s.status,result:s.result,trigger:s.trigger,start_time:s.startTime||s.start_time,end_time:s.endTime||s.end_time,duration_ms:s.duration,total_test_case_count:s.totalTestCaseCount||s.total_test_case_count,passed_test_case_count:s.passedTestCaseCount||s.passed_test_case_count,failed_test_case_count:s.failedTestCaseCount||s.failed_test_case_count,skipped_test_case_count:s.skippedTestCaseCount||s.skipped_test_case_count,test_plan_id:s.testPlanId||s.test_plan_id},test_case_results:o.map(a=>({id:a.id,test_case_id:a.testCaseId||a.test_case_id,result:a.result,status:a.status,duration_ms:a.duration,environment_name:a.environmentName||a.environment_name,environment_url:a.environmentUrl||a.environment_url,error:a.error}))})}static getTestCaseResultTool={name:"get_test_case_result",description:"Get detailed test case result including status, duration, and error information",inputSchema:jd($t.object({test_case_result_id:$t.number().describe("Test case result ID"),include_report:$t.boolean().optional().describe("Include full report with step details (default false)")}),{$refStrategy:"none"})};async getTestCaseResult(t){let r=this.requireApi("get_test_case_result"),{test_case_result_id:n,include_report:i}=$t.object({test_case_result_id:$t.number(),include_report:$t.boolean().optional()}).parse(t),s=await r.getTestCaseResult(n),o=Array.isArray(s.report)?s.report[0]:s.report,a=o?.resultJson||{},l=Object.entries(a),u=l.length,d=null;for(let h=0;h<l.length;h++){let[,m]=l[h];if(m.status==="failed"||m.status==="failure"){d=h;break}}let p={id:s.id,test_case_id:s.testCaseId||s.test_case_id,test_run_id:s.testRunId||s.test_run_id,result:s.result,status:s.status,start_time:s.startTime||s.start_time,end_time:s.endTime||s.end_time,duration_ms:s.duration,environment_name:s.environmentName||s.environment_name,environment_id:s.environmentId||s.environment_id,environment_url:s.environmentUrl||s.environment_url,device:s.device,total_steps:u,failed_step_index:d,video_s3_uri:s.video,trace_s3_uri:s.trace,report_s3_uri:s.reportS3Uri||s.report_s3_uri};if(i){let h=s.reportS3Uri||s.report_s3_uri,m=null;if(h&&r.getS3FileContents)try{let b=await r.getS3FileContents(h);if(b){let w=JSON.parse(b);m=Array.isArray(w)?w[0]:w}}catch(b){console.error("Failed to fetch S3 report, falling back to DB report:",b)}let y=m||o;p.report={stdout:y?.stdout,stderr:y?.stderr,consoleLogs:y?.consoleLogs,flaky:y?.flaky,error:y?.error,step_results:y?.resultJson,video_s3_uri:y?.videoS3Uri,trace_s3_uri:y?.traceS3Uri,source_s3_uri:y?.sourceS3Uri}}return JSON.stringify(p)}static getTestCaseResultStepsTool={name:"get_test_case_result_steps",description:"Get step-by-step execution details for a range of steps. Use get_test_case_result first to find the failed_step_index, then request the range you need.",inputSchema:jd($t.object({test_case_result_id:$t.number().describe("Test case result ID"),from_step:$t.number().describe("Start step index (0-based, inclusive)"),to_step:$t.number().describe("End step index (0-based, inclusive)")}),{$refStrategy:"none"})};async getTestCaseResultSteps(t){let r=this.requireApi("get_test_case_result_steps"),{test_case_result_id:n,from_step:i,to_step:s}=$t.object({test_case_result_id:$t.number(),from_step:$t.number(),to_step:$t.number()}).parse(t),o=await r.getTestCaseResult(n),l=(Array.isArray(o.report)?o.report[0]:o.report)?.resultJson||{},u=Object.entries(l).map(([p,h])=>{let m=h.artifacts?.[0];return{step_id:p,description:h.description,status:h.status,message:h.message,start_time:h.startTime,duration_ms:h.duration,has_screenshot:!!(m?.screenshot_s3_path||h.screenshotS3Uri),has_messages:!!m?.messages_s3_path,has_response:!!m?.response_s3_path,has_system_prompt:!!m?.system_prompt_s3_path}}),d=u.slice(i,s+1);return JSON.stringify({test_case_result_id:n,total_steps:u.length,from_step:i,to_step:s,steps:d})}static getStepArtifactsTool={name:"get_step_artifacts",description:"Download all artifacts for a step to local files. Returns local file paths - client decides which to read.",inputSchema:jd($t.object({test_case_result_id:$t.number().describe("Test case result ID"),step_index:$t.number().describe("Step index (0-based)")}),{$refStrategy:"none"})};async getStepArtifacts(t){let r=this.requireApi("get_step_artifacts"),{test_case_result_id:n,step_index:i}=$t.object({test_case_result_id:$t.number(),step_index:$t.number()}).parse(t),s=await r.getTestCaseResult(n),a=(Array.isArray(s.report)?s.report[0]:s.report)?.resultJson||{},l=Object.values(a);if(i<0||i>=l.length)throw new Error(`Step index ${i} out of range (0-${l.length-1})`);let u=l[i],d=u.artifacts?.[0],p={},h=d?.screenshot_s3_path||u.screenshotS3Uri;h&&(p.screenshot={s3Uri:h,filename:`step_${i}_screenshot.png`}),d?.messages_s3_path&&(p.messages={s3Uri:d.messages_s3_path,filename:`step_${i}_messages.json`}),d?.response_s3_path&&(p.response={s3Uri:d.response_s3_path,filename:`step_${i}_response.txt`}),d?.system_prompt_s3_path&&(p.system_prompt={s3Uri:d.system_prompt_s3_path,filename:`step_${i}_system_prompt.txt`});let m=!!r.getS3FileContents,y=!!this.options.artifactProxyBaseUrl,b=!!r.getArtifactPresignedUrl;if(!m&&!y&&!b)return JSON.stringify({test_case_result_id:n,step_index:i,error:"Artifact download not supported by this API client",s3_uris:Object.fromEntries(Object.entries(p).map(([C,{s3Uri:R}])=>[C,R]))});this.cleanupOldArtifacts();let w=Pm.join(km,`tcr-${n}`);sl.existsSync(w)||sl.mkdirSync(w,{recursive:!0});let E={},x=!!r.downloadArtifact;return await Promise.all(Object.entries(p).map(async([C,{s3Uri:R,filename:k}])=>{try{let T=null;if(!T&&m){let O=await r.getS3FileContents(R);O&&(T=O)}if(!T&&y&&x){let O=this.getProxyUrl(R);O&&(T=await r.downloadArtifact(O))}if(!T&&b){let O=await r.getArtifactPresignedUrl(R);if(O){let I=await tie.get(O,{responseType:"arraybuffer"});T=Buffer.from(I.data)}}if(!T){E[C]=null;return}let D=Pm.join(w,k);sl.writeFileSync(D,T),E[C]=D}catch(T){console.error(`Failed to download ${C} artifact:`,T),E[C]=null}})),JSON.stringify({test_case_result_id:n,step_index:i,screenshot_path:E.screenshot,messages_path:E.messages,response_path:E.response,system_prompt_path:E.system_prompt})}static toolDefinitions=[$c.listTestRunsTool,$c.getTestRunDetailsTool,$c.getTestCaseResultTool,$c.getTestCaseResultStepsTool,$c.getStepArtifactsTool]};nL=class Hd{sessionManager;apiClient;constructor(t,r){this.sessionManager=t??null,this.apiClient=r??null}requireApi(t){if(!this.apiClient)throw new Error(jc(t));return this.apiClient}static scaffoldProjectTool={name:"scaffold_project",description:"Scaffold a ready-to-run local test project with Playwright and shiplightai. Generates package.json, playwright.config.ts, .gitignore, and .env.example. IMPORTANT: You MUST call this tool before writing any .test.yaml files \u2014 it sets up the project structure required to run them. After scaffolding, the user runs: npm install && npx playwright install chromium && npx shiplight test",inputSchema:Ud(at.object({project_path:at.string().describe("Absolute path where the project should be created")}),{$refStrategy:"none"})};async scaffoldProject(t){let{project_path:r}=at.object({project_path:at.string()}).parse(t),n=wm({projectPath:r});return JSON.stringify({success:!0,project_path:n.projectPath,files_created:n.filesCreated,next_steps:["Copy .env.example to .env and set at least one AI model API key (GOOGLE_API_KEY or ANTHROPIC_API_KEY). Optionally set SHIPLIGHT_API_TOKEN if you have a Shiplight account.","Run: npm install","Run: npx playwright install chromium","Write .test.yaml files into the project directory (or any subdirectory)","Run: npx shiplight test"],do_this_now:"You MUST now: (1) Run 'npm install' in the project directory to install shiplightai and @playwright/test, (2) Run 'npx playwright install chromium' to download the Chromium browser, (3) Read resource 'shiplight://yaml-test-spec-v1.3.0' to learn the YAML test format before writing any .test.yaml files."})}static exportYamlToTestTool={name:"export_yaml_to_test",description:"Convert a YAML test flow into a standalone Playwright .test.ts file. The generated test uses shiplightai with an inline agent \u2014 no cloud runner needed. Use scaffold_project first to scaffold the project, then export tests into the project directory.",inputSchema:Ud(at.object({yaml:at.string().describe("YAML test flow string"),output_path:at.string().describe("Absolute path for the output .test.ts file (e.g., /path/to/project/tests/login.test.ts)"),test_name:at.string().optional().describe("Override the test name (defaults to the flow's goal)"),starting_url:at.string().optional().describe("Override the starting URL from the test flow")}),{$refStrategy:"none"})};async exportYamlToTest(t){let{yaml:r,output_path:n,test_name:i,starting_url:s}=at.object({yaml:at.string(),output_path:at.string(),test_name:at.string().optional(),starting_url:at.string().optional()}).parse(t),o=NR(r,{testName:i,startingUrl:s}),a=fo.dirname(n);return Cr.mkdirSync(a,{recursive:!0}),Cr.writeFileSync(n,o),JSON.stringify({success:!0,output_path:n,size_bytes:Buffer.byteLength(o,"utf8")})}static validateTestYamlTool={name:"validate_yaml_test",description:"Validate and transpile a YAML test file on disk. Reads the .test.yaml file, validates syntax and action coverage (enriched vs draft statements), parses suites/hooks/params/templates, transpiles to a .yaml.spec.ts Playwright test file, and validates the generated TypeScript syntax. Use your Write tool to save the .test.yaml file first, then call this tool to validate and compile it. IMPORTANT: Before writing tests, you MUST first walk through the test flow in a browser session using `act` to perform each action and `get_locators` to capture element locators, then embed the locator/xpath data into your YAML statements. Tests with too many draft statements (bare intent: without action/js) will be rejected.",inputSchema:Ud(at.object({file_path:at.string().describe("Absolute path to the YAML test file to validate (e.g., /path/to/tests/login.test.yaml)")}),{$refStrategy:"none"})};async validateTestYaml(t){let{file_path:r}=at.object({file_path:at.string()}).parse(t),n=VR(r,{version:"mcp"});return n.valid?n.warnings.length>0&&n.stats?JSON.stringify({valid:!1,file_path:r,errors:[`Insufficient action coverage: ${n.stats.action}/${n.stats.total} statements (${n.stats.coverage}%) are enriched with action/js. ${n.stats.draft} draft(s) still need enrichment. At least 50% required.`],stats:n.stats,guidance:"Before writing tests, walk through the flow in a browser session: (1) Use `new_session` to open a browser, (2) Use `inspect_page` + `act` to perform each action and capture locators from the response, (3) Use `get_locators` for additional element info, (4) Embed the locator/xpath data into your YAML statements, (5) Then call validate_yaml_test again after updating the file."}):JSON.stringify({valid:!0,file_path:r,spec_file:n.specFile,stats:n.stats,warnings:[],errors:[]}):JSON.stringify({valid:!1,file_path:r,errors:n.errors,stats:n.stats})}static generateHtmlReportTool={name:"generate_html_report",description:"Generate a self-contained HTML session report. Can be called while the session is live OR after close_session. Embeds per-step screenshots, an optional video player, and a Playwright trace viewer link. The session must have been started with record_evidence: true. Pass local_video_path (returned by close_session) to embed the video. Pass local_trace_path (returned by close_session) to include trace info for later upload. Pass trace_url if the trace has already been uploaded (shows an interactive viewer link). Pass summary to describe what was tested. Pass checks \u2014 a list of acceptance criteria derived from what you were asked to build \u2014 each with a pass/fail result and the step indices that prove it (step indices are 1-based: first action = step 1). The agent should fill these in itself based on the task and steps taken; no user input required. Pass highlight_steps to feature specific screenshots in a Summary section at the top. Returns the file path of the written report.",inputSchema:Ud(at.object({session_id:at.string().describe("The session ID \u2014 works for live sessions and closed sessions"),title:at.string().optional().describe("Optional report title (e.g. 'Todo App \u2014 Install MCP button')"),summary:at.string().optional().describe("Text summary of what the agent tested and the outcome \u2014 shown prominently at the top of the report. Example: 'Verified that the Install MCP button appears on the dashboard and opens the install dialog correctly. All 3 checks passed.'"),checks:at.array(at.object({description:at.string().describe("One acceptance criterion, e.g. 'Tasks persist after page reload'"),passed:at.boolean().describe("Whether this criterion passed"),step_indices:at.array(at.number()).optional().describe("Step indices whose screenshots are evidence for this check. Use the step_index returned directly by inspect_page and act \u2014 no manual counting needed. 1-based: first action = step 1."),note:at.string().optional().describe("Optional detail \u2014 e.g. what failed, or a caveat")})).optional().describe("Acceptance criteria checklist derived from the feature you were asked to build and verify. Fill these in yourself based on the task and what you verified \u2014 the user does not need to provide them. Each check maps to one or more step screenshots as evidence. Step indices are 1-based (first action = step 1). Example: [{ description: 'User can add a task', passed: true, step_indices: [2] }, { description: 'Task persists after reload', passed: true, step_indices: [8] }]"),highlight_steps:at.array(at.number()).optional().describe("Step indices to feature as key screenshots (fallback if checks is not provided). Step indices are 1-based (first action = step 1). If omitted and no checks given, auto-selects first, last, and failed steps."),local_video_path:at.string().optional().describe("Local .webm file path returned by close_session. Embeds the video directly in the report."),video_url:at.string().optional().describe("Public URL of the .webm recording (alternative to local_video_path for uploaded videos)"),local_trace_path:at.string().optional().describe("Local .zip trace path returned by close_session. Stored in the report for local reference; pass trace_url instead to render the 'Open Trace Viewer' button."),trace_url:at.string().optional().describe("Public URL of the Playwright trace .zip (after uploading). Renders an 'Open Trace Viewer' button."),output_path:at.string().optional().describe("Where to write the file (default: /tmp/report.html)")}),{$refStrategy:"none"})};async generateHtmlReport(t){let{session_id:r,title:n,summary:i,checks:s,highlight_steps:o,local_video_path:a,video_url:l,local_trace_path:u,trace_url:d,output_path:p}=at.object({session_id:at.string(),title:at.string().optional(),summary:at.string().optional(),checks:at.array(at.object({description:at.string(),passed:at.boolean(),step_indices:at.array(at.number()).optional(),note:at.string().optional()})).optional(),highlight_steps:at.array(at.number()).optional(),local_video_path:at.string().optional(),video_url:at.string().optional(),local_trace_path:at.string().optional(),trace_url:at.string().optional(),output_path:at.string().optional()}).parse(t);if(!this.sessionManager)throw new Error("No session manager available");if(this.sessionManager.hasSession(r))throw new Error(`Session "${r}" is still open. Call close_session first, then generate_html_report.`);let h=await nie(this.sessionManager.getRunDir(),r);if(!h.recordEvidence)throw new Error(`Session ${r} was not started with record_evidence: true. This must be enabled to generate a report.`);let m=p??fo.join(rL.tmpdir(),"report.html"),y=ye=>ye.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""),b=a&&Cr.existsSync(a)?encodeURI(`file://${a}`):l&&/^https?:\/\//i.test(l)?y(l):null,w=n??"Session Report",E=h.createdAt.toLocaleString("en-US",{month:"long",day:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit"}),{actionLog:x}=h,C=x.filter(ye=>ye.success).length,R=x.filter(ye=>!ye.success).length,T=((x.length>0?x[x.length-1].timestamp-x[0].timestamp:0)/1e3).toFixed(1),D=5*1024*1024,O=new Map;await Promise.all([...new Set(x.map(ye=>ye.screenshotPath).filter(ye=>!!ye))].map(async ye=>{try{if((await Cr.promises.stat(ye)).size>D)return;let Ie=await Cr.promises.readFile(ye);O.set(ye,`data:image/png;base64,${Ie.toString("base64")}`)}catch{}}));let I=ye=>ye?O.get(ye)??"":"",L=R===0,F=L?"verdict-pass":"verdict-fail",U=L?"\u2705 PASS":"\u274C FAIL",z=x.map(ye=>{let me=I(ye.screenshotPath),Ie=ye.actionName==="verify",ue=Ie?ye.success?"pass":"fail":"",Me=Ie?ye.success?"\u2705 pass":"\u274C fail":"",he=((x[0]?ye.timestamp-x[0].timestamp:0)/1e3).toFixed(2),Ee=me?`<img class="thumb" src="${me}" alt="Step ${ye.stepIndex} screenshot" data-description="${y(ye.description)}" onclick="openModal(event, this)" style="display:none">`:"",Ae=!ye.success&&ye.error?`<div class="step-error">${y(ye.error)}</div>`:"";return`
|
|
6686
|
+
with the page. Pass multiple indices in a single call to save round-trips.`};Am=null,Tm=null;XR=class Bc{constructor(t){this.backend=t}static navigateTool={...P_,inputSchema:ol(Om,{$refStrategy:"none"})};async navigate(t){let r=Om.parse(t),n=await O_(this.backend,r);return JSON.stringify(n)}static get actTool(){return V_()}async act(t){let r=N_.parse(t),n=await R_(this.backend,r);return JSON.stringify(n)}static updateVariablesTool={...L_,inputSchema:ol(Nm,{$refStrategy:"none"})};async updateVariables(t){let r=Nm.parse(t),n=M_(this.backend,r);return JSON.stringify(n)}static clearExecutionHistoryTool={...F_,inputSchema:ol(Dm,{$refStrategy:"none"})};async clearExecutionHistory(t){let r=Dm.parse(t),n=B_(this.backend,r);return JSON.stringify(n)}static getPageInfoTool={...$_,inputSchema:ol(Rm,{$refStrategy:"none"})};async getPageInfo(t){let r=Rm.parse(t),n=await j_(this.backend,r);return JSON.stringify(n)}static inspectPageTool={...U_,inputSchema:ol(Lm,{$refStrategy:"none"})};async inspectPage(t){let r=Lm.parse(t),n=await H_(this.backend,r);return JSON.stringify(n)}static getLocatorsTool={...q_,inputSchema:ol(Mm,{$refStrategy:"none"})};async getLocators(t){let r=Mm.parse(t),n=await G_(this.backend,r);return JSON.stringify(n)}static get toolDefinitions(){return[Bc.navigateTool,Bc.getPageInfoTool,Bc.inspectPageTool,Bc.actTool,Bc.getLocatorsTool]}},ZR=class Im{constructor(t){this.backend=t}static getConsoleLogsTool={name:"get_browser_console_logs",description:"Get console logs from the browser (errors, warnings, etc.)",inputSchema:Cm(ur.object({session_id:ur.string().describe("Browser session ID"),since_timestamp:ur.number().optional().describe("Only return logs after this timestamp"),log_types:ur.array(ur.string()).optional().describe("Filter by log types (e.g., ['error', 'warning'])")}),{$refStrategy:"none"})};async getConsoleLogs(t){let{session_id:r,since_timestamp:n,log_types:i}=ur.object({session_id:ur.string(),since_timestamp:ur.number().optional(),log_types:ur.array(ur.string()).optional()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);let o=this.backend.getConsoleLogs(r,{sinceTimestamp:n,logTypes:i});return JSON.stringify({session_id:r,log_count:o.length,logs:o.slice(-100)})}static getNetworkLogsTool={name:"get_browser_network_logs",description:"Get network request logs from the browser",inputSchema:Cm(ur.object({session_id:ur.string().describe("Browser session ID"),since_timestamp:ur.number().optional().describe("Only return logs after this timestamp"),status_filter:ur.enum(["errors","success"]).optional().describe("Filter by HTTP status (errors: 4xx/5xx, success: 2xx)")}),{$refStrategy:"none"})};async getNetworkLogs(t){let{session_id:r,since_timestamp:n,status_filter:i}=ur.object({session_id:ur.string(),since_timestamp:ur.number().optional(),status_filter:ur.enum(["errors","success"]).optional()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);let o=this.backend.getNetworkLogs(r,{sinceTimestamp:n,statusFilter:i});return JSON.stringify({session_id:r,log_count:o.length,logs:o.slice(-100)})}static clearLogsTool={name:"clear_logs",description:"Clear console and network logs for a session",inputSchema:Cm(ur.object({session_id:ur.string().describe("Browser session ID")}),{$refStrategy:"none"})};async clearLogs(t){let{session_id:r}=ur.object({session_id:ur.string()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);return this.backend.clearLogs(r),JSON.stringify({session_id:r,message:"Logs cleared successfully"})}static getLocalArtifactTool={name:"get_local_artifact",description:"Get a local artifact file (screenshot, DOM snapshot, etc.) from a live browser session. Only accepts local file paths, NOT S3 URIs. For test run artifacts, use get_step_artifacts instead.",inputSchema:Cm(ur.object({path:ur.string().describe("Artifact file path from previous tool output"),return_format:ur.enum(["base64","text"]).optional().describe("Return format (auto-detected if not specified)")}),{$refStrategy:"none"})};async getLocalArtifact(t){let{path:r}=ur.object({path:ur.string(),return_format:ur.enum(["base64","text"]).optional()}).parse(t),n=await this.backend.getLocalArtifact(r);return JSON.stringify({path:r,format:n.format,size:n.size,data:n.data})}static toolDefinitions=[Im.getConsoleLogsTool,Im.getNetworkLogsTool,Im.clearLogsTool]};QR=class al{constructor(t){this.apiClient=t}requireApi(t){if(!this.apiClient)throw new Error(jc(t));return this.apiClient}static listEnvironmentsTool={name:"list_environments",description:"List all testing environments (staging, production, etc.)",inputSchema:Mc(tr.object({}),{$refStrategy:"none"})};async listEnvironments(t){let n=await this.requireApi("list_environments").listEnvironments();return JSON.stringify({environments:n.map(i=>({id:i.id,name:i.name,url:i.url}))})}static listTestAccountsTool={name:"list_test_accounts",description:"List test accounts for a specific environment. Requires either environment_id or environment_url.",inputSchema:Mc(tr.object({environment_id:tr.number().optional().describe("Environment ID to filter by"),environment_url:tr.string().optional().describe("Environment URL to filter by (alternative to environment_id)")}),{$refStrategy:"none"})};async listTestAccounts(t){let r=this.requireApi("list_test_accounts"),{environment_id:n,environment_url:i}=tr.object({environment_id:tr.number().optional(),environment_url:tr.string().optional()}).parse(t),s=await r.listTestAccounts(n,i);return JSON.stringify({test_accounts:s.map(o=>({id:o.id,name:o.name,username:o.username,environment_id:o.environmentId||o.environment_id}))})}static getTestAccountTool={name:"get_test_account",description:"Get a specific test account by ID",inputSchema:Mc(tr.object({test_account_id:tr.number().describe("Test account ID")}),{$refStrategy:"none"})};async getTestAccount(t){let r=this.requireApi("get_test_account"),{test_account_id:n}=tr.object({test_account_id:tr.number()}).parse(t),i=await r.getTestAccount(n);return JSON.stringify({test_account:i})}static listFoldersTool={name:"list_folders",description:"List test case folders",inputSchema:Mc(tr.object({parent_id:tr.number().nullable().optional().describe("Parent folder ID, null for root"),search:tr.string().optional().describe("Search query")}),{$refStrategy:"none"})};async listFolders(t){let r=this.requireApi("list_folders"),{parent_id:n,search:i}=tr.object({parent_id:tr.number().nullable().optional(),search:tr.string().optional()}).parse(t),s=await r.listFolders(n,i);return JSON.stringify({folders:s.map(o=>({id:o.id,name:o.name,parent_id:o.parentId||o.parent_id,path:o.pathIds}))})}static createFolderTool={name:"create_folder",description:"Create a new test case folder",inputSchema:Mc(tr.object({name:tr.string().describe("Folder name"),description:tr.string().optional().describe("Folder description"),parent_id:tr.number().nullable().optional().describe("Parent folder ID")}),{$refStrategy:"none"})};async createFolder(t){let r=this.requireApi("create_folder"),{name:n,description:i,parent_id:s}=tr.object({name:tr.string(),description:tr.string().optional(),parent_id:tr.number().nullable().optional()}).parse(t),o=await r.createFolder({name:n,description:i,parentId:s});return JSON.stringify({folder_id:o.id,message:"Folder created successfully"})}static getFolderTool={name:"get_folder",description:"Get folder details with full hierarchical path",inputSchema:Mc(tr.object({folder_id:tr.number().describe("Folder ID")}),{$refStrategy:"none"})};async getFolder(t){let r=this.requireApi("get_folder"),{folder_id:n}=tr.object({folder_id:tr.number()}).parse(t),i=await r.getFolder(n);return JSON.stringify({folder:i})}static toolDefinitions=[al.listEnvironmentsTool,al.listTestAccountsTool,al.getTestAccountTool,al.listFoldersTool,al.createFolderTool,al.getFolderTool]};qd=class uo{constructor(t){this.apiClient=t}requireApi(t){if(!this.apiClient)throw new Error(jc(t));return this.apiClient}parseFlowInput(t){return typeof t=="string"?Qo.parse($n(t)):Qo.parse(t)}readTextFile(t,r){try{return Fm(t,"utf-8")}catch(n){let i=n instanceof Error?n.message:String(n);throw new Error(`Failed to read ${r} file at ${t}: ${i}`)}}extractFunctionCodeFromFile(t,r){let n=this.readTextFile(t,`function "${r}"`),i=Zr.createSourceFile(t,n,Zr.ScriptTarget.Latest,!0,Zr.ScriptKind.TS),s=u=>n.slice(u.getStart(i),u.getEnd()),o=(u,d,p)=>{let h=u.map(y=>s(y)).join(", ");return`${p?"async ":""}(${h}) => ${s(d)}`},a=null,l=u=>{if(!Zr.isVariableStatement(u))return!1;for(let d of u.declarationList.declarations)if(!(!Zr.isIdentifier(d.name)||d.name.text!==r||!d.initializer)){if(Zr.isArrowFunction(d.initializer))return a=s(d.initializer),!0;if(Zr.isFunctionExpression(d.initializer))return a=o(d.initializer.parameters,d.initializer.body,d.initializer.modifiers?.some(p=>p.kind===Zr.SyntaxKind.AsyncKeyword)??!1),!0}return!1};for(let u of i.statements){if(Zr.isFunctionDeclaration(u)&&u.name?.text===r&&u.body){a=o(u.parameters,u.body,u.modifiers?.some(d=>d.kind===Zr.SyntaxKind.AsyncKeyword)??!1);break}if(l(u))break;Zr.isExportDeclaration(u)||Zr.isExportAssignment(u)}if(!a)throw new Error(`Could not find function "${r}" in ${t}`);return a}stripTypeAnnotations(t){let r=`const __fn = ${t};`,n;try{n=Zr.transpileModule(r,{compilerOptions:{target:Zr.ScriptTarget.ES2020,module:Zr.ModuleKind.ESNext}}).outputText}catch(s){throw new Error(`Failed to strip TypeScript types from function code: ${s.message}`)}let i=Zr.createSourceFile("__fn.ts",n,Zr.ScriptTarget.ES2020,!0);for(let s of i.statements)if(Zr.isVariableStatement(s)&&s.declarationList.declarations.length===1){let o=s.declarationList.declarations[0];if(Zr.isIdentifier(o.name)&&o.name.text==="__fn"&&o.initializer)return n.slice(o.initializer.getStart(i),o.initializer.getEnd()).trim()}throw new Error("Failed to strip TypeScript types: could not locate function expression in transpiler output")}static createTestCaseTool={name:"create_test_case",description:"Create a test case from a flow (test flow JSON object or YAML string). IMPORTANT: Read 'shiplight://schemas/testflow-json-v1.2.0' for the required flow format. Accepts a test flow as JSON object or YAML string. Include action_entity with locator/xpath on ACTION statements when available - this speeds up test execution.",inputSchema:ks(Le.object({flow:Le.union([Le.string(),Le.any()]).describe("Test flow as JSON object or YAML string"),folder_id:Le.number().optional().describe("Folder ID"),name:Le.string().optional().describe("Test case name"),environment_id:Le.number().optional().describe("Environment ID for test execution"),test_account_id:Le.number().optional().describe("Optional test account ID for login")}),{$refStrategy:"none"})};async createTestCase(t){let r=this.requireApi("create_test_case"),{flow:n,folder_id:i,name:s,environment_id:o,test_account_id:a}=Le.object({flow:Le.any(),folder_id:Le.number().optional(),name:Le.string().optional(),environment_id:Le.number().optional(),test_account_id:Le.number().optional()}).parse(t),l;try{l=this.parseFlowInput(n)}catch(b){throw b instanceof Le.ZodError?new Error(`Invalid TestFlow schema: ${JSON.stringify(b.errors)}`):b}let u={...l,version:l.testGroup?"1.3.0":"1.2.0",statements:this.regenerateUids(l.statements??[]),teardown:l.teardown?this.regenerateUids(l.teardown):void 0,testGroup:l.testGroup?this.regenerateGroupUids(l.testGroup):void 0},d=l.url||l.baseURL,p=o;if(p===void 0&&d)try{let b=await r.listEnvironments(),w=Xne(d,b);w&&(p=w.id)}catch{}let h;p!==void 0&&(h=[{environment_id:p,test_account_group:a?{type:"Specific",account_ids:[a]}:{type:"None",account_ids:[]},path:""}]);let m=await r.createTestCase({title:s||l.goal||"Untitled",testFlow:u,folderId:i,environmentConfigs:h}),y=this.computeFlowStats(l.statements??[],l.teardown);return JSON.stringify({...m,environment_id:p??null,test_account_id:a??null,yaml:rl(l,{test_case_id:m.test_case_id}),flow_stats:y})}static updateTestCaseTool={name:"update_test_case",description:"Update a test case from a flow (test flow JSON object or YAML string). IMPORTANT: Read 'shiplight://schemas/testflow-json-v1.2.0' for the required flow format. Accepts a test flow as JSON object or YAML string. Include action_entity with locator/xpath on ACTION statements when available - this speeds up test execution.",inputSchema:ks(Le.object({test_case_id:Le.number().describe("Test case ID"),flow:Le.union([Le.string(),Le.any()]).describe("Test flow as JSON object or YAML string"),title:Le.string().optional().describe("New title"),environment_id:Le.number().optional().describe("Environment ID to set/update"),test_account_id:Le.number().optional().describe("Test account ID to associate")}),{$refStrategy:"none"})};async updateTestCase(t){let r=this.requireApi("update_test_case"),{test_case_id:n,flow:i,title:s,environment_id:o,test_account_id:a}=Le.object({test_case_id:Le.number(),flow:Le.any(),title:Le.string().optional(),environment_id:Le.number().optional(),test_account_id:Le.number().optional()}).parse(t),l;try{l=this.parseFlowInput(i)}catch(m){throw m instanceof Le.ZodError?new Error(`Invalid TestFlow schema: ${JSON.stringify(m.errors)}`):m}let u={...l,version:l.testGroup?"1.3.0":"1.2.0",statements:this.regenerateUids(l.statements??[]),teardown:l.teardown?this.regenerateUids(l.teardown):void 0,testGroup:l.testGroup?this.regenerateGroupUids(l.testGroup):void 0},d;o!==void 0&&(d=[{environment_id:o,test_account_group:a?{type:"Specific",account_ids:[a]}:{type:"None",account_ids:[]}}]);let p=await r.updateTestCase(n,{title:s||l.goal||"Untitled",testFlow:u,environmentConfigs:d}),h=this.computeFlowStats(l.statements??[],l.teardown);return JSON.stringify({...p,flow_stats:h})}static getTestCaseTool={name:"get_test_case",description:"Get a test case by ID. Use output_format 'yaml' to get the flow as a YAML string.",inputSchema:ks(Le.object({test_case_id:Le.number().describe("Test case ID"),output_format:Le.enum(["json","yaml"]).optional().describe("Output format for the test flow (default: json)")}),{$refStrategy:"none"})};async getTestCase(t){let r=this.requireApi("get_test_case"),{test_case_id:n,output_format:i}=Le.object({test_case_id:Le.number(),output_format:Le.enum(["json","yaml"]).optional()}).parse(t),s=await r.getTestCase(n);if(i==="yaml"&&s.test_flow){let o=rl(s.test_flow,{test_case_id:s.id});return JSON.stringify({test_case:{id:s.id,title:s.title,folder_id:s.folder_id},yaml:o})}return JSON.stringify({test_case:s})}static runTestCaseTool={name:"run_test_case",description:"Trigger cloud execution of a test case. Returns a test_run_id that can be used with get_test_run_details to poll for completion and results.",inputSchema:ks(Le.object({test_case_id:Le.number().describe("Test case ID to run"),environment_id:Le.number().optional().describe("Environment ID to run against (uses test case default if not specified)")}),{$refStrategy:"none"})};async runTestCase(t){let r=this.requireApi("run_test_case"),{test_case_id:n,environment_id:i}=Le.object({test_case_id:Le.number(),environment_id:Le.number().optional()}).parse(t),s=await r.runTestCase(n,i);return JSON.stringify({test_run_id:s.id,status:s.status,result:s.result,test_case_result_ids:s.test_case_result_ids,message:`Test run ${s.id} triggered. Use get_test_run_details(${s.id}) to check status and results.`})}static saveTestCaseTool={name:"save_test_case",description:"Save a test case from YAML \u2014 automatically creates or updates based on embedded test_case_id metadata. Prefer file_path over yaml to avoid reading and passing file content (saves tokens). If the YAML contains a test_case_id field, updates that test case; otherwise creates a new one. Returns YAML with test_case_id embedded so you can write it back to the local file for future updates. If the YAML contains 'template:' file references, file_path auto-resolves them (or provide base_path explicitly).",inputSchema:ks(Le.object({file_path:Le.string().optional().describe("Path to a YAML test file on disk (alternative to yaml \u2014 avoids passing file content as a string)"),yaml:Le.string().optional().describe("YAML test flow string (not needed if file_path is provided)"),folder_id:Le.number().optional().describe("Folder ID (only used on create)"),name:Le.string().optional().describe("Test case name (defaults to flow goal)"),environment_id:Le.number().optional().describe("Environment ID for test execution"),test_account_id:Le.number().optional().describe("Test account ID for login"),base_path:Le.string().optional().describe("Base directory for resolving template: file references (auto-derived from file_path if not specified)")}),{$refStrategy:"none"})};resolveLocalReferences(t,r){return Zne(t,r)}async saveTestCase(t){let{file_path:r,yaml:n,folder_id:i,name:s,environment_id:o,test_account_id:a,base_path:l}=Le.object({file_path:Le.string().optional(),yaml:Le.string().optional(),folder_id:Le.number().optional(),name:Le.string().optional(),environment_id:Le.number().optional(),test_account_id:Le.number().optional(),base_path:Le.string().optional()}).refine(y=>y.file_path||y.yaml,{message:"Either file_path or yaml must be provided"}).parse(t),u=r?this.readTextFile(r,"test case"):n,d=l??(r?eL(r):void 0),p=d?this.resolveLocalReferences(u,d):u,h=am(u),m=s||h.name;if(h.test_case_id!==void 0){let y=await this.updateTestCase({test_case_id:h.test_case_id,flow:p,title:m,environment_id:o,test_account_id:a}),b=JSON.parse(y),w=this.parseFlowInput(p);return JSON.stringify({...b,yaml:rl(w,{test_case_id:h.test_case_id})})}else return await this.createTestCase({flow:p,folder_id:i,name:m,environment_id:o,test_account_id:a})}computeFlowStats(t,r){let n=[...ea(t),...r?ea(r):[]],{action:i,draft:s}=um(n),o=i+s,a=o>0?Math.round(i/o*100):0,l={total:o,draft_statements:s,enriched_statements:i,coverage:a};return s>0&&(l.hint=`${s} draft statement(s) (~10-15s each at runtime vs ~1s enriched). Consider converting drafts to actions with action/js.`),l}regenerateUids(t){return t.map(r=>{let n={...r,uid:Yne()};return r.type==="STEP"&&r.statements?n.statements=this.regenerateUids(r.statements):r.type==="IF_ELSE"?(r.then&&(n.then=this.regenerateUids(r.then)),r.else&&(n.else=this.regenerateUids(r.else))):r.type==="WHILE_LOOP"&&r.body&&(n.body=this.regenerateUids(r.body)),n})}regenerateGroupUids(t){let r=n=>n?this.regenerateUids(n):void 0;return{...t,tests:t.tests.map(n=>({...n,statements:this.regenerateUids(n.statements),teardown:n.teardown?this.regenerateUids(n.teardown):void 0})),beforeAll:r(t.beforeAll),afterAll:r(t.afterAll),beforeEach:r(t.beforeEach),afterEach:r(t.afterEach)}}static saveTemplateTool={name:"save_template",description:"Save a template (reusable step group) \u2014 automatically creates or updates based on template_id. Prefer file_path over yaml to avoid reading and passing file content (saves tokens). For partial updates, provide template_id with only the fields to change (e.g. name, description) \u2014 file_path/yaml not required. For create or full update, provide file_path or yaml with statements.",inputSchema:ks(Le.object({file_path:Le.string().optional().describe("Path to a YAML template file on disk (alternative to yaml \u2014 avoids passing file content as a string)"),yaml:Le.string().optional().describe("YAML template string with name, optional params, and statements (not needed if file_path is provided)"),template_id:Le.number().optional().describe("Template ID for updates (overrides embedded template_id)"),name:Le.string().optional().describe("Template name (overrides embedded name)"),description:Le.string().optional().describe("Template description")}),{$refStrategy:"none"})};async saveTemplate(t){let r=this.requireApi("save_template");if(!r.createReusableStep||!r.updateReusableStep)throw new Error("API client does not support reusable steps");let{file_path:n,yaml:i,template_id:s,name:o,description:a}=Le.object({file_path:Le.string().optional(),yaml:Le.string().optional(),template_id:Le.number().optional(),name:Le.string().optional(),description:Le.string().optional()}).parse(t),l=n||i;if(s&&!l){let E={};if(o!==void 0&&(E.name=o),a!==void 0&&(E.description=a),Object.keys(E).length===0)throw new Error("Partial update requires at least one field to change (name, description)");let x=await r.updateReusableStep(s,E);return JSON.stringify({success:!0,message:"Template updated successfully (partial)",template_id:x.id,name:x.name})}if(!l)throw new Error("Either file_path or yaml must be provided (or template_id for partial updates)");let u=n?this.readTextFile(n,"template"):i,d=am(u),p=s??d.template_id,h=o??d.name??"Untitled Template",m=u.includes("goal:")?u:`goal: "${h}"
|
|
6687
|
+
${u}`,y=$n(m),b=this.regenerateUids(y.statements??[]),w={name:h,description:a??y.goal??h,statements:b};if(p){let E=await r.updateReusableStep(p,w);return JSON.stringify({success:!0,message:"Template updated successfully",template_id:E.id,name:E.name,statement_count:E.statements?.length??0})}else{let E=await r.createReusableStep(w);return JSON.stringify({success:!0,message:"Template created successfully",template_id:E.id,name:E.name,statement_count:E.statements?.length??0})}}static saveFunctionTool={name:"save_function",description:"Save a test function to the cloud \u2014 automatically creates or updates based on function_id. Prefer file_path over code to avoid reading and passing file content (saves tokens). For partial updates, provide function_id with only the fields to change (e.g. name, description) \u2014 file_path/code not required. For create or full update, provide name and either file_path or code.",inputSchema:ks(Le.object({file_path:Le.string().optional().describe("Path to a TypeScript file on disk (alternative to code \u2014 avoids passing file content as a string)"),function_id:Le.number().optional().describe("Function ID for updates"),name:Le.string().optional().describe("Function name in snake_case (e.g. 'get_cart_count') \u2014 required for create"),code:Le.string().optional().describe("Function code body (not needed if file_path is provided)"),description:Le.string().optional().describe("Function description")}),{$refStrategy:"none"})};async saveFunction(t){let r=this.requireApi("save_function");if(!r.createTestFunction||!r.updateTestFunction)throw new Error("API client does not support test functions");let{file_path:n,function_id:i,name:s,code:o,description:a}=Le.object({file_path:Le.string().optional(),function_id:Le.number().optional(),name:Le.string().optional(),code:Le.string().optional(),description:Le.string().optional()}).parse(t),l=n||o;if(i!=null&&!l){let h={};if(s!==void 0&&(h.name=s),a!==void 0&&(h.description=a),Object.keys(h).length===0)throw new Error("Partial update requires at least one field to change (name, description)");let m=await r.updateTestFunction(i,h);return JSON.stringify({success:!0,message:"Function updated successfully (partial)",function_id:m.id,name:m.name})}if(!s)throw new Error("name is required for creating or fully updating a function");if(!l)throw new Error("Either file_path or code must be provided (or function_id for partial updates)");let u=n?this.extractFunctionCodeFromFile(n,s):o,d=this.stripTypeAnnotations(u),p={name:s,code:d,description:a};if(i!=null){let h=await r.updateTestFunction(i,p);return JSON.stringify({success:!0,message:"Function updated successfully",function_id:h.id,name:h.name})}else{let h=await r.createTestFunction(p);return JSON.stringify({success:!0,message:"Function created successfully",function_id:h.id,name:h.name})}}static saveTestAccountTool={name:"save_test_account",description:"Create or update a test account \u2014 automatically creates if no test_account_id is provided, updates otherwise. Optionally upload a local storageState file so the cloud runner can reuse saved browser sessions. loginConfig is built automatically from the provided credentials.",inputSchema:ks(Le.object({test_account_id:Le.number().optional().describe("Test account ID for updates"),environment_id:Le.number().describe("Environment ID"),username:Le.string().describe("Username / email"),password:Le.string().describe("Password"),account_type:Le.enum(["password","oauth2"]).optional().describe("Login type (default: password)"),oauth_provider:Le.string().optional().describe("OAuth provider name (required when account_type is oauth2)"),two_factor_auth:Le.object({type:Le.enum(["totp","sms","email"]).describe("2FA type"),data:Le.string().describe("Secret key for TOTP, phone number for SMS, etc.")}).optional().describe("Two-factor authentication configuration"),storage_state_path:Le.string().optional().describe("Path to a local storageState JSON file to upload to the cloud")}),{$refStrategy:"none"})};async saveTestAccount(t){let r=this.requireApi("save_test_account"),{test_account_id:n,environment_id:i,username:s,password:o,account_type:a,oauth_provider:l,two_factor_auth:u,storage_state_path:d}=Le.object({test_account_id:Le.number().optional(),environment_id:Le.number(),username:Le.string(),password:Le.string(),account_type:Le.enum(["password","oauth2"]).optional(),oauth_provider:Le.string().optional(),two_factor_auth:Le.object({type:Le.enum(["totp","sms","email"]),data:Le.string()}).optional(),storage_state_path:Le.string().optional()}).refine(b=>b.account_type!=="oauth2"||!!b.oauth_provider,{message:"oauth_provider is required when account_type is 'oauth2'",path:["oauth_provider"]}).parse(t),p=a??"password",h={account:{type:p,...p==="oauth2"&&l?{provider_name:l}:{},...u?{two_factor_auth_config:u}:{}}},m;n?(r.updateTestAccount&&await r.updateTestAccount(n,{username:s,password:o,environmentId:i,loginConfig:h}),m=n):m=(await r.createTestAccount({environmentId:i,username:s,password:o,loginConfig:h})).id;let y=null;if(d&&r.uploadStorageState){let b=Fm(k_(d),"utf-8"),w=JSON.parse(b);y=await r.uploadStorageState(m,w)}return JSON.stringify({success:!0,message:n?"Test account updated":"Test account created",test_account_id:m,...y?{storage_state:y}:{}})}static getTemplateTool={name:"get_template",description:"Get a template (reusable step group) by ID from the cloud. Returns the template as YAML with embedded template_id, ready to save as a local .yaml file.",inputSchema:ks(Le.object({template_id:Le.number().describe("Template ID")}),{$refStrategy:"none"})};async getTemplate(t){let r=this.requireApi("get_template");if(!r.getReusableStep)throw new Error("API client does not support reusable steps");let{template_id:n}=Le.object({template_id:Le.number()}).parse(t),i=await r.getReusableStep(n),s={template_id:i.id,name:i.name};i.description&&(s.description=i.description);let o={goal:i.name,url:"",statements:i.statements},a=om(o);s.statements=a.statements;let l=I_(s,{lineWidth:120,defaultKeyType:"PLAIN",defaultStringType:"PLAIN"});return JSON.stringify({template_id:i.id,name:i.name,description:i.description,statement_count:i.statements?.length??0,yaml:l})}static getFunctionTool={name:"get_function",description:"Get a test function by ID from the cloud. Returns the function name, description, and code.",inputSchema:ks(Le.object({function_id:Le.number().describe("Function ID")}),{$refStrategy:"none"})};async getFunction(t){let r=this.requireApi("get_function");if(!r.getTestFunction)throw new Error("API client does not support test functions");let{function_id:n}=Le.object({function_id:Le.number()}).parse(t),i=await r.getTestFunction(n);return JSON.stringify({function_id:i.id,name:i.name,description:i.description,code:i.code})}static toolDefinitions=[uo.getTestCaseTool,uo.getTemplateTool,uo.getFunctionTool,uo.runTestCaseTool,uo.saveTestCaseTool,uo.saveTestAccountTool,uo.saveTemplateTool,uo.saveFunctionTool]};rie=3600*1e3,km=Pm.join(eie.tmpdir(),"shiplight-artifacts"),tL=class $c{constructor(t,r){this.apiClient=t,this.options=r||{}}options;requireApi(t){if(!this.apiClient)throw new Error(jc(t));return this.apiClient}getProxyUrl(t){if(!this.options.artifactProxyBaseUrl)return null;let r=t.match(/^s3:\/\/[^/]+\/(.+)$/);if(!r)return null;let n=r[1];return`${this.options.artifactProxyBaseUrl}/api/artifacts/${n}`}cleanupOldArtifacts(){try{if(!sl.existsSync(km))return;let t=Date.now(),r=sl.readdirSync(km,{withFileTypes:!0});for(let n of r){if(!n.isDirectory())continue;let i=Pm.join(km,n.name);try{let s=sl.statSync(i);t-s.mtimeMs>rie&&sl.rmSync(i,{recursive:!0,force:!0})}catch{}}}catch{}}static listTestRunsTool={name:"list_test_runs",description:"List test runs with optional filtering by test plan, trigger type, or result status",inputSchema:jd($t.object({test_plan_id:$t.number().optional().describe("Filter by test plan ID"),trigger:$t.string().optional().describe("Filter by trigger type (Manual, Scheduled, API, GITHUB_ACTION, Webhook, Automation)"),result:$t.string().optional().describe("Filter by result (Passed, Failed, Pending, Skipped, Queued)"),limit:$t.number().optional().describe("Maximum number of results (default 20)")}),{$refStrategy:"none"})};async listTestRuns(t){let r=this.requireApi("list_test_runs"),{test_plan_id:n,trigger:i,result:s,limit:o}=$t.object({test_plan_id:$t.number().optional(),trigger:$t.string().optional(),result:$t.string().optional(),limit:$t.number().optional()}).parse(t),a=await r.listTestRuns({testPlanId:n,trigger:i,result:s,limit:o??20});return JSON.stringify({test_runs:a.map(l=>({id:l.id,status:l.status,result:l.result,trigger:l.trigger,start_time:l.startTime||l.start_time,end_time:l.endTime||l.end_time,duration_ms:l.duration,total_test_case_count:l.totalTestCaseCount||l.total_test_case_count,passed_test_case_count:l.passedTestCaseCount||l.passed_test_case_count,failed_test_case_count:l.failedTestCaseCount||l.failed_test_case_count,skipped_test_case_count:l.skippedTestCaseCount||l.skipped_test_case_count,test_plan_id:l.testPlanId||l.test_plan_id})),count:a.length})}static getTestRunDetailsTool={name:"get_test_run_details",description:"Get detailed information about a test run including all test case results",inputSchema:jd($t.object({test_run_id:$t.number().describe("Test run ID")}),{$refStrategy:"none"})};async getTestRunDetails(t){let r=this.requireApi("get_test_run_details"),{test_run_id:n}=$t.object({test_run_id:$t.number()}).parse(t),i=await r.getTestRunDetails(n),s=i.testRun||i,o=i.testCaseResults||[];return JSON.stringify({test_run:{id:s.id,status:s.status,result:s.result,trigger:s.trigger,start_time:s.startTime||s.start_time,end_time:s.endTime||s.end_time,duration_ms:s.duration,total_test_case_count:s.totalTestCaseCount||s.total_test_case_count,passed_test_case_count:s.passedTestCaseCount||s.passed_test_case_count,failed_test_case_count:s.failedTestCaseCount||s.failed_test_case_count,skipped_test_case_count:s.skippedTestCaseCount||s.skipped_test_case_count,test_plan_id:s.testPlanId||s.test_plan_id},test_case_results:o.map(a=>({id:a.id,test_case_id:a.testCaseId||a.test_case_id,result:a.result,status:a.status,duration_ms:a.duration,environment_name:a.environmentName||a.environment_name,environment_url:a.environmentUrl||a.environment_url,error:a.error}))})}static getTestCaseResultTool={name:"get_test_case_result",description:"Get detailed test case result including status, duration, and error information",inputSchema:jd($t.object({test_case_result_id:$t.number().describe("Test case result ID"),include_report:$t.boolean().optional().describe("Include full report with step details (default false)")}),{$refStrategy:"none"})};async getTestCaseResult(t){let r=this.requireApi("get_test_case_result"),{test_case_result_id:n,include_report:i}=$t.object({test_case_result_id:$t.number(),include_report:$t.boolean().optional()}).parse(t),s=await r.getTestCaseResult(n),o=Array.isArray(s.report)?s.report[0]:s.report,a=o?.resultJson||{},l=Object.entries(a),u=l.length,d=null;for(let h=0;h<l.length;h++){let[,m]=l[h];if(m.status==="failed"||m.status==="failure"){d=h;break}}let p={id:s.id,test_case_id:s.testCaseId||s.test_case_id,test_run_id:s.testRunId||s.test_run_id,result:s.result,status:s.status,start_time:s.startTime||s.start_time,end_time:s.endTime||s.end_time,duration_ms:s.duration,environment_name:s.environmentName||s.environment_name,environment_id:s.environmentId||s.environment_id,environment_url:s.environmentUrl||s.environment_url,device:s.device,total_steps:u,failed_step_index:d,video_s3_uri:s.video,trace_s3_uri:s.trace,report_s3_uri:s.reportS3Uri||s.report_s3_uri};if(i){let h=s.reportS3Uri||s.report_s3_uri,m=null;if(h&&r.getS3FileContents)try{let b=await r.getS3FileContents(h);if(b){let w=JSON.parse(b);m=Array.isArray(w)?w[0]:w}}catch(b){console.error("Failed to fetch S3 report, falling back to DB report:",b)}let y=m||o;p.report={stdout:y?.stdout,stderr:y?.stderr,consoleLogs:y?.consoleLogs,flaky:y?.flaky,error:y?.error,step_results:y?.resultJson,video_s3_uri:y?.videoS3Uri,trace_s3_uri:y?.traceS3Uri,source_s3_uri:y?.sourceS3Uri}}return JSON.stringify(p)}static getTestCaseResultStepsTool={name:"get_test_case_result_steps",description:"Get step-by-step execution details for a range of steps. Use get_test_case_result first to find the failed_step_index, then request the range you need.",inputSchema:jd($t.object({test_case_result_id:$t.number().describe("Test case result ID"),from_step:$t.number().describe("Start step index (0-based, inclusive)"),to_step:$t.number().describe("End step index (0-based, inclusive)")}),{$refStrategy:"none"})};async getTestCaseResultSteps(t){let r=this.requireApi("get_test_case_result_steps"),{test_case_result_id:n,from_step:i,to_step:s}=$t.object({test_case_result_id:$t.number(),from_step:$t.number(),to_step:$t.number()}).parse(t),o=await r.getTestCaseResult(n),l=(Array.isArray(o.report)?o.report[0]:o.report)?.resultJson||{},u=Object.entries(l).map(([p,h])=>{let m=h.artifacts?.[0];return{step_id:p,description:h.description,status:h.status,message:h.message,start_time:h.startTime,duration_ms:h.duration,has_screenshot:!!(m?.screenshot_s3_path||h.screenshotS3Uri),has_messages:!!m?.messages_s3_path,has_response:!!m?.response_s3_path,has_system_prompt:!!m?.system_prompt_s3_path}}),d=u.slice(i,s+1);return JSON.stringify({test_case_result_id:n,total_steps:u.length,from_step:i,to_step:s,steps:d})}static getStepArtifactsTool={name:"get_step_artifacts",description:"Download all artifacts for a step to local files. Returns local file paths - client decides which to read.",inputSchema:jd($t.object({test_case_result_id:$t.number().describe("Test case result ID"),step_index:$t.number().describe("Step index (0-based)")}),{$refStrategy:"none"})};async getStepArtifacts(t){let r=this.requireApi("get_step_artifacts"),{test_case_result_id:n,step_index:i}=$t.object({test_case_result_id:$t.number(),step_index:$t.number()}).parse(t),s=await r.getTestCaseResult(n),a=(Array.isArray(s.report)?s.report[0]:s.report)?.resultJson||{},l=Object.values(a);if(i<0||i>=l.length)throw new Error(`Step index ${i} out of range (0-${l.length-1})`);let u=l[i],d=u.artifacts?.[0],p={},h=d?.screenshot_s3_path||u.screenshotS3Uri;h&&(p.screenshot={s3Uri:h,filename:`step_${i}_screenshot.png`}),d?.messages_s3_path&&(p.messages={s3Uri:d.messages_s3_path,filename:`step_${i}_messages.json`}),d?.response_s3_path&&(p.response={s3Uri:d.response_s3_path,filename:`step_${i}_response.txt`}),d?.system_prompt_s3_path&&(p.system_prompt={s3Uri:d.system_prompt_s3_path,filename:`step_${i}_system_prompt.txt`});let m=!!r.getS3FileContents,y=!!this.options.artifactProxyBaseUrl,b=!!r.getArtifactPresignedUrl;if(!m&&!y&&!b)return JSON.stringify({test_case_result_id:n,step_index:i,error:"Artifact download not supported by this API client",s3_uris:Object.fromEntries(Object.entries(p).map(([C,{s3Uri:R}])=>[C,R]))});this.cleanupOldArtifacts();let w=Pm.join(km,`tcr-${n}`);sl.existsSync(w)||sl.mkdirSync(w,{recursive:!0});let E={},x=!!r.downloadArtifact;return await Promise.all(Object.entries(p).map(async([C,{s3Uri:R,filename:k}])=>{try{let T=null;if(!T&&m){let O=await r.getS3FileContents(R);O&&(T=O)}if(!T&&y&&x){let O=this.getProxyUrl(R);O&&(T=await r.downloadArtifact(O))}if(!T&&b){let O=await r.getArtifactPresignedUrl(R);if(O){let I=await tie.get(O,{responseType:"arraybuffer"});T=Buffer.from(I.data)}}if(!T){E[C]=null;return}let D=Pm.join(w,k);sl.writeFileSync(D,T),E[C]=D}catch(T){console.error(`Failed to download ${C} artifact:`,T),E[C]=null}})),JSON.stringify({test_case_result_id:n,step_index:i,screenshot_path:E.screenshot,messages_path:E.messages,response_path:E.response,system_prompt_path:E.system_prompt})}static toolDefinitions=[$c.listTestRunsTool,$c.getTestRunDetailsTool,$c.getTestCaseResultTool,$c.getTestCaseResultStepsTool,$c.getStepArtifactsTool]};nL=class Hd{sessionManager;apiClient;constructor(t,r){this.sessionManager=t??null,this.apiClient=r??null}requireApi(t){if(!this.apiClient)throw new Error(jc(t));return this.apiClient}static scaffoldProjectTool={name:"scaffold_project",description:"Scaffold a ready-to-run local test project with Playwright and shiplightai. Generates package.json, playwright.config.ts, .gitignore, and .env.example. IMPORTANT: You MUST call this tool before writing any .test.yaml files \u2014 it sets up the project structure required to run them. After scaffolding, the user runs: npm install && npx playwright install chromium && npx shiplight test",inputSchema:Ud(at.object({project_path:at.string().describe("Absolute path where the project should be created")}),{$refStrategy:"none"})};async scaffoldProject(t){let{project_path:r}=at.object({project_path:at.string()}).parse(t),n=wm({projectPath:r});return JSON.stringify({success:!0,project_path:n.projectPath,files_created:n.filesCreated,next_steps:["Copy .env.example to .env and set at least one AI model API key (GOOGLE_API_KEY or ANTHROPIC_API_KEY). Optionally set SHIPLIGHT_API_TOKEN if you have a Shiplight account.","Run: npm install","Run: npx playwright install chromium","Write .test.yaml files into the project directory (or any subdirectory)","Run: npx shiplight test"],do_this_now:"You MUST now: (1) Run 'npm install' in the project directory to install shiplightai and @playwright/test, (2) Run 'npx playwright install chromium' to download the Chromium browser, (3) Read resource 'shiplight://yaml-test-spec-v1.3.0' to learn the YAML test format before writing any .test.yaml files."})}static exportYamlToTestTool={name:"export_yaml_to_test",description:"Convert a YAML test flow into a standalone Playwright .test.ts file. The generated test uses shiplightai with an inline agent \u2014 no cloud runner needed. Use scaffold_project first to scaffold the project, then export tests into the project directory.",inputSchema:Ud(at.object({yaml:at.string().describe("YAML test flow string"),output_path:at.string().describe("Absolute path for the output .test.ts file (e.g., /path/to/project/tests/login.test.ts)"),test_name:at.string().optional().describe("Override the test name (defaults to the flow's goal)"),starting_url:at.string().optional().describe("Override the starting URL from the test flow")}),{$refStrategy:"none"})};async exportYamlToTest(t){let{yaml:r,output_path:n,test_name:i,starting_url:s}=at.object({yaml:at.string(),output_path:at.string(),test_name:at.string().optional(),starting_url:at.string().optional()}).parse(t),o=NR(r,{testName:i,startingUrl:s}),a=fo.dirname(n);return Cr.mkdirSync(a,{recursive:!0}),Cr.writeFileSync(n,o),JSON.stringify({success:!0,output_path:n,size_bytes:Buffer.byteLength(o,"utf8")})}static validateTestYamlTool={name:"validate_yaml_test",description:"Validate and transpile a YAML test file on disk. Reads the .test.yaml file, validates syntax and action coverage (enriched vs draft statements), parses suites/hooks/params/templates, transpiles to a .yaml.spec.ts Playwright test file, and validates the generated TypeScript syntax. Use your Write tool to save the .test.yaml file first, then call this tool to validate and compile it. IMPORTANT: Before writing tests, you MUST first walk through the test flow in a browser session using `act` to perform each action and `get_locators` to capture element locators, then embed the locator/xpath data into your YAML statements. Tests with too many draft statements (bare intent: without action/js) will be rejected.",inputSchema:Ud(at.object({file_path:at.string().describe("Absolute path to the YAML test file to validate (e.g., /path/to/tests/login.test.yaml)")}),{$refStrategy:"none"})};async validateTestYaml(t){let{file_path:r}=at.object({file_path:at.string()}).parse(t),n=VR(r,{version:"mcp"});return n.valid?n.warnings.length>0&&n.stats?JSON.stringify({valid:!1,file_path:r,errors:[`Insufficient action coverage: ${n.stats.action}/${n.stats.total} statements (${n.stats.coverage}%) are enriched with action/js. ${n.stats.draft} draft(s) still need enrichment. At least 50% required.`],stats:n.stats,guidance:"Before writing tests, walk through the flow in a browser session: (1) Use `new_session` to open a browser, (2) Use `inspect_page` + `act` to perform each action and capture locators from the response, (3) Use `get_locators` for additional element info, (4) Embed the locator/xpath data into your YAML statements, (5) Then call validate_yaml_test again after updating the file."}):JSON.stringify({valid:!0,file_path:r,spec_file:n.specFile,stats:n.stats,warnings:[],errors:[]}):JSON.stringify({valid:!1,file_path:r,errors:n.errors,stats:n.stats})}static generateHtmlReportTool={name:"generate_html_report",description:"Generate a self-contained HTML session report. Can be called while the session is live OR after close_session. Embeds per-step screenshots, an optional video player, and a Playwright trace viewer link. The session must have been started with record_evidence: true. Pass local_video_path (returned by close_session) to embed the video. Pass local_trace_path (returned by close_session) to include trace info for later upload. Pass trace_url if the trace has already been uploaded (shows an interactive viewer link). Pass summary to describe what was tested. Pass checks \u2014 a list of acceptance criteria derived from what you were asked to build \u2014 each with a pass/fail result and the step indices that prove it (step indices are 1-based: first action = step 1). The agent should fill these in itself based on the task and steps taken; no user input required. Pass highlight_steps to feature specific screenshots in a Summary section at the top. Returns the file path of the written report.",inputSchema:Ud(at.object({session_id:at.string().describe("The session ID \u2014 works for live sessions and closed sessions"),title:at.string().optional().describe("Optional report title (e.g. 'Todo App \u2014 Install MCP button')"),summary:at.string().optional().describe("Text summary of what the agent tested and the outcome \u2014 shown prominently at the top of the report. Example: 'Verified that the Install MCP button appears on the dashboard and opens the install dialog correctly. All 3 checks passed.'"),checks:at.array(at.object({description:at.string().describe("One acceptance criterion, e.g. 'Tasks persist after page reload'"),passed:at.boolean().describe("Whether this criterion passed"),step_indices:at.array(at.number()).optional().describe("Step indices whose screenshots are evidence for this check. Use the step_index returned directly by inspect_page and act \u2014 no manual counting needed. 1-based: first action = step 1."),note:at.string().optional().describe("Optional detail \u2014 e.g. what failed, or a caveat")})).optional().describe("Acceptance criteria checklist derived from the feature you were asked to build and verify. Fill these in yourself based on the task and what you verified \u2014 the user does not need to provide them. Each check maps to one or more step screenshots as evidence. Step indices are 1-based (first action = step 1). Example: [{ description: 'User can add a task', passed: true, step_indices: [2] }, { description: 'Task persists after reload', passed: true, step_indices: [8] }]"),highlight_steps:at.array(at.number()).optional().describe("Step indices to feature as key screenshots (fallback if checks is not provided). Step indices are 1-based (first action = step 1). If omitted and no checks given, auto-selects first, last, and failed steps."),local_video_path:at.string().optional().describe("Local .webm file path returned by close_session. Embeds the video directly in the report."),video_url:at.string().optional().describe("Public URL of the .webm recording (alternative to local_video_path for uploaded videos)"),local_trace_path:at.string().optional().describe("Local .zip trace path returned by close_session. Stored in the report for local reference; pass trace_url instead to render the 'Open Trace Viewer' button."),trace_url:at.string().optional().describe("Public URL of the Playwright trace .zip (after uploading). Renders an 'Open Trace Viewer' button."),output_path:at.string().optional().describe("Where to write the file (default: /tmp/report.html)")}),{$refStrategy:"none"})};async generateHtmlReport(t){let{session_id:r,title:n,summary:i,checks:s,highlight_steps:o,local_video_path:a,video_url:l,local_trace_path:u,trace_url:d,output_path:p}=at.object({session_id:at.string(),title:at.string().optional(),summary:at.string().optional(),checks:at.array(at.object({description:at.string(),passed:at.boolean(),step_indices:at.array(at.number()).optional(),note:at.string().optional()})).optional(),highlight_steps:at.array(at.number()).optional(),local_video_path:at.string().optional(),video_url:at.string().optional(),local_trace_path:at.string().optional(),trace_url:at.string().optional(),output_path:at.string().optional()}).parse(t);if(!this.sessionManager)throw new Error("No session manager available");if(this.sessionManager.hasSession(r))throw new Error(`Session "${r}" is still open. Call close_session first, then generate_html_report.`);let h=await nie(this.sessionManager.getRunDir(),r);if(!h.recordEvidence)throw new Error(`Session ${r} was not started with record_evidence: true. This must be enabled to generate a report.`);let m=p??fo.join(rL.tmpdir(),"report.html"),y=ye=>ye.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""),b=a&&Cr.existsSync(a)?encodeURI(`file://${a}`):l&&/^https?:\/\//i.test(l)?y(l):null,w=n??"Session Report",E=h.createdAt.toLocaleString("en-US",{month:"long",day:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit"}),{actionLog:x}=h,C=x.filter(ye=>ye.success).length,R=x.filter(ye=>!ye.success).length,T=((x.length>0?x[x.length-1].timestamp-x[0].timestamp:0)/1e3).toFixed(1),D=5*1024*1024,O=new Map;await Promise.all([...new Set(x.map(ye=>ye.screenshotPath).filter(ye=>!!ye))].map(async ye=>{try{if((await Cr.promises.stat(ye)).size>D)return;let Ie=await Cr.promises.readFile(ye);O.set(ye,`data:image/png;base64,${Ie.toString("base64")}`)}catch{}}));let I=ye=>ye?O.get(ye)??"":"",L=R===0,F=L?"verdict-pass":"verdict-fail",U=L?"\u2705 PASS":"\u274C FAIL",z=x.map(ye=>{let me=I(ye.screenshotPath),Ie=ye.actionName==="verify",ue=Ie?ye.success?"pass":"fail":"",Me=Ie?ye.success?"\u2705 pass":"\u274C fail":"",he=((x[0]?ye.timestamp-x[0].timestamp:0)/1e3).toFixed(2),Ee=me?`<img class="thumb" src="${me}" alt="Step ${ye.stepIndex} screenshot" data-description="${y(ye.description)}" onclick="openModal(event, this)" style="display:none">`:"",Ae=!ye.success&&ye.error?`<div class="step-error">${y(ye.error)}</div>`:"";return`
|
|
6687
6688
|
<div class="step-wrapper" ${me?'onclick="collapseWrapper(event, this)"':""}>
|
|
6688
6689
|
${Ee}
|
|
6689
6690
|
<div class="step-card ${ue}" ${me?'onclick="toggleStepImg(this)"':""}>
|
|
@@ -6936,13 +6937,13 @@ ${i?`
|
|
|
6936
6937
|
});
|
|
6937
6938
|
</script>
|
|
6938
6939
|
</body>
|
|
6939
|
-
</html>`,le=fo.dirname(m);return await Cr.promises.mkdir(le,{recursive:!0}),await Cr.promises.writeFile(m,fe,"utf8"),JSON.stringify({success:!0,file_path:m})}static uploadReportTool={name:"upload_html_report",description:"Upload a generated HTML report to Shiplight cloud for sharing. Optionally includes video recording and Playwright trace. Returns a permanent shareable URL. Requires SHIPLIGHT_API_TOKEN. Call this after generate_html_report to get a link you can attach to PRs or share with the team. Note: the local report HTML file is modified in-place to replace local file paths with cloud URLs.",inputSchema:Ud(at.object({report_path:at.string().describe("Path to the HTML report file (returned by generate_html_report)"),local_video_path:at.string().optional().describe("Path to the .webm video recording (returned by close_session)"),local_trace_path:at.string().optional().describe("Path to the .zip trace file (returned by close_session)")}),{$refStrategy:"none"})};async uploadReport(t){let{report_path:r,local_video_path:n,local_trace_path:i}=at.object({report_path:at.string(),local_video_path:at.string().optional(),local_trace_path:at.string().optional()}).parse(t),s=this.requireApi("upload_html_report");if(!s.getReportUploadUrls)throw new Error("Report upload is not supported by this API client");if(!Cr.existsSync(r))throw new Error(`Report file not found: ${r}`);let o=n&&Cr.existsSync(n),a=i&&Cr.existsSync(i),l=await s.getReportUploadUrls({videoFilename:o?fo.basename(n):void 0,traceFilename:a?fo.basename(i):void 0,reportFilename:"report.html"}),u=300*1e3,d=[];o&&l.video&&d.push(T_.put(l.video.uploadUrl,Cr.createReadStream(n),{headers:{"Content-Type":"video/webm","Content-Length":Cr.statSync(n).size},maxBodyLength:1/0,maxContentLength:1/0,timeout:u}).then(()=>{te.info("[upload_html_report] Video uploaded")}).catch(h=>{throw new Error(`Failed to upload video: ${h.message}`)})),a&&l.trace&&d.push(T_.put(l.trace.uploadUrl,Cr.createReadStream(i),{headers:{"Content-Type":"application/zip","Content-Length":Cr.statSync(i).size},maxBodyLength:1/0,maxContentLength:1/0,timeout:u}).then(()=>{te.info("[upload_html_report] Trace uploaded")}).catch(h=>{throw new Error(`Failed to upload trace: ${h.message}`)})),await Promise.all(d);let p=await Cr.promises.readFile(r,"utf8");if(o&&l.video){let h=p.replace(/src="file:\/\/[^"]*\.webm"/g,`src="${l.video.url}"`);h===p&&te.warn("[upload_html_report] No file:// video src found in report HTML to patch"),p=h}if(a&&l.trace){let h=encodeURIComponent(l.trace.url),m='<p class="no-trace">Trace will be available after uploading.</p>';p.includes(m)||te.warn("[upload_html_report] No trace placeholder found in report HTML to patch"),p=p.replace(m,`<a class="trace-btn" href="https://trace.playwright.dev/?trace=${h}" target="_blank" rel="noopener noreferrer">Open Trace Viewer \u2192</a>`)}return await Cr.promises.writeFile(r,p,"utf8"),await T_.put(l.report.uploadUrl,Buffer.from(p,"utf8"),{headers:{"Content-Type":"text/html"},maxBodyLength:1/0,maxContentLength:1/0,timeout:u}).catch(h=>{throw new Error(`Failed to upload report: ${h.message}`)}),te.info("[upload_html_report] Report uploaded"),JSON.stringify({success:!0,report_url:l.report.url,video_url:l.video?.url??null,trace_url:l.trace?.url??null})}static toolDefinitions=[Hd.scaffoldProjectTool,Hd.validateTestYamlTool,Hd.generateHtmlReportTool];static cloudToolDefinitions=[Hd.uploadReportTool]}});var sL={};Li(sL,{ACT_SUPPORTED_ACTIONS:()=>nl,ActionEntitySchema:()=>
|
|
6940
|
+
</html>`,le=fo.dirname(m);return await Cr.promises.mkdir(le,{recursive:!0}),await Cr.promises.writeFile(m,fe,"utf8"),JSON.stringify({success:!0,file_path:m})}static uploadReportTool={name:"upload_html_report",description:"Upload a generated HTML report to Shiplight cloud for sharing. Optionally includes video recording and Playwright trace. Returns a permanent shareable URL. Requires SHIPLIGHT_API_TOKEN. Call this after generate_html_report to get a link you can attach to PRs or share with the team. Note: the local report HTML file is modified in-place to replace local file paths with cloud URLs.",inputSchema:Ud(at.object({report_path:at.string().describe("Path to the HTML report file (returned by generate_html_report)"),local_video_path:at.string().optional().describe("Path to the .webm video recording (returned by close_session)"),local_trace_path:at.string().optional().describe("Path to the .zip trace file (returned by close_session)")}),{$refStrategy:"none"})};async uploadReport(t){let{report_path:r,local_video_path:n,local_trace_path:i}=at.object({report_path:at.string(),local_video_path:at.string().optional(),local_trace_path:at.string().optional()}).parse(t),s=this.requireApi("upload_html_report");if(!s.getReportUploadUrls)throw new Error("Report upload is not supported by this API client");if(!Cr.existsSync(r))throw new Error(`Report file not found: ${r}`);let o=n&&Cr.existsSync(n),a=i&&Cr.existsSync(i),l=await s.getReportUploadUrls({videoFilename:o?fo.basename(n):void 0,traceFilename:a?fo.basename(i):void 0,reportFilename:"report.html"}),u=300*1e3,d=[];o&&l.video&&d.push(T_.put(l.video.uploadUrl,Cr.createReadStream(n),{headers:{"Content-Type":"video/webm","Content-Length":Cr.statSync(n).size},maxBodyLength:1/0,maxContentLength:1/0,timeout:u}).then(()=>{te.info("[upload_html_report] Video uploaded")}).catch(h=>{throw new Error(`Failed to upload video: ${h.message}`)})),a&&l.trace&&d.push(T_.put(l.trace.uploadUrl,Cr.createReadStream(i),{headers:{"Content-Type":"application/zip","Content-Length":Cr.statSync(i).size},maxBodyLength:1/0,maxContentLength:1/0,timeout:u}).then(()=>{te.info("[upload_html_report] Trace uploaded")}).catch(h=>{throw new Error(`Failed to upload trace: ${h.message}`)})),await Promise.all(d);let p=await Cr.promises.readFile(r,"utf8");if(o&&l.video){let h=p.replace(/src="file:\/\/[^"]*\.webm"/g,`src="${l.video.url}"`);h===p&&te.warn("[upload_html_report] No file:// video src found in report HTML to patch"),p=h}if(a&&l.trace){let h=encodeURIComponent(l.trace.url),m='<p class="no-trace">Trace will be available after uploading.</p>';p.includes(m)||te.warn("[upload_html_report] No trace placeholder found in report HTML to patch"),p=p.replace(m,`<a class="trace-btn" href="https://trace.playwright.dev/?trace=${h}" target="_blank" rel="noopener noreferrer">Open Trace Viewer \u2192</a>`)}return await Cr.promises.writeFile(r,p,"utf8"),await T_.put(l.report.uploadUrl,Buffer.from(p,"utf8"),{headers:{"Content-Type":"text/html"},maxBodyLength:1/0,maxContentLength:1/0,timeout:u}).catch(h=>{throw new Error(`Failed to upload report: ${h.message}`)}),te.info("[upload_html_report] Report uploaded"),JSON.stringify({success:!0,report_url:l.report.url,video_url:l.video?.url??null,trace_url:l.trace?.url??null})}static toolDefinitions=[Hd.scaffoldProjectTool,Hd.validateTestYamlTool,Hd.generateHtmlReportTool];static cloudToolDefinitions=[Hd.uploadReportTool]}});var sL={};Li(sL,{ACT_SUPPORTED_ACTIONS:()=>nl,ActionEntitySchema:()=>Rd,BrowserTools:()=>XR,DataTools:()=>QR,DebugTools:()=>ZR,ExtensionRelayServer:()=>yR,LocalTestTools:()=>nL,PROMPTS:()=>pm,RESOURCES:()=>d_,RelayElectionCoordinator:()=>bR,RelayTools:()=>YR,SessionManager:()=>gR,SessionTools:()=>JR,StatementSchema:()=>In,TestCaseTools:()=>qd,TestFlowSchema:()=>Qo,TestResultTools:()=>tL,TokenApiClient:()=>dm,ToolRegistry:()=>mm,WebAgent:()=>tl,actHandler:()=>R_,actSchema:()=>N_,clearExecutionHistoryHandler:()=>B_,clearExecutionHistorySchema:()=>Dm,clearExecutionHistoryToolMeta:()=>F_,getActSchema:()=>W_,getActToolDefinition:()=>V_,getActToolMeta:()=>D_,getActionEntitySchemaResource:()=>f_,getLocatorsHandler:()=>G_,getLocatorsSchema:()=>Mm,getLocatorsToolMeta:()=>q_,getPageInfoHandler:()=>j_,getPageInfoSchema:()=>Rm,getPageInfoToolMeta:()=>$_,getPrompt:()=>hm,getResource:()=>bm,getTestFlowJsonSchemaResource:()=>p_,getTestFlowYamlSchemaResource:()=>h_,inspectPageHandler:()=>H_,inspectPageSchema:()=>Lm,inspectPageToolMeta:()=>U_,listPrompts:()=>fm,listResources:()=>ym,missingApiTokenError:()=>jc,navigateHandler:()=>O_,navigateSchema:()=>Om,navigateToolMeta:()=>P_,scaffoldProject:()=>wm,updateVariablesHandler:()=>M_,updateVariablesSchema:()=>Nm,updateVariablesToolMeta:()=>L_});var z_=mt(()=>{"use strict";wR();rm();_R();vR();xR();iL();m_();nm();gm()});var K_,iie,mo,J_=mt(()=>{"use strict";K_=class e{static _instance;_logLevel;constructor(){switch(process.env.LOG_LEVEL?.toUpperCase()){case"ERROR":this._logLevel=1;break;case"WARN":this._logLevel=2;break;case"INFO":this._logLevel=3;break;case"DEBUG":this._logLevel=4;break;default:this._logLevel=3}}static getInstance(){return e._instance||(e._instance=new e),e._instance}setLevel(t){this._logLevel=t}debug(...t){this._logLevel>=4&&console.error("[DEBUG]",...t)}info(...t){this._logLevel>=3&&console.error("[INFO]",...t)}warn(...t){this._logLevel>=2&&console.error("[WARN]",...t)}error(...t){this._logLevel>=1&&console.error("[ERROR]",...t)}log(...t){this.info(...t)}},iie=K_.getInstance(),mo=iie});import{createHash as sie}from"node:crypto";import{hostname as oie,userInfo as aie,platform as aL,arch as lie}from"node:os";import{PostHog as cie}from"posthog-node";function hie(){return pie?null:(Y_||(Y_=new cie(uie,{host:die,flushAt:1,flushInterval:3e4})),Y_)}function fie(){let e=`${oie()}:${aie().username}:${aL()}:${lie()}`;return sie("sha256").update(e).digest("hex")}function lL(e,t){let r=hie();if(r){oL||(mo.info("Anonymous usage telemetry enabled. Set SHIPLIGHT_TELEMETRY=0 to disable."),oL=!0);try{r.capture({distinctId:fie(),event:"mcp_new_session",properties:{product:"mcp-server",version:e,platform:aL(),nodeVersion:process.version,cloudMode:t,$geoip_disable:!0,$ip:null}}),r.flush().catch(()=>{})}catch{}}}var uie,die,pie,Y_,oL,cL=mt(()=>{"use strict";J_();uie="phc_5Va2dHamGwJWX9qZqyRka5Lann5ATsg3LL4uyU63qin",die="https://us.i.posthog.com",pie=process.env.SHIPLIGHT_TELEMETRY==="0"||process.env.DO_NOT_TRACK==="1",Y_=null,oL=!1});var hL={};Li(hL,{startServer:()=>Aie});import{Server as mie}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as gie}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as yie,ListToolsRequestSchema as bie,ListResourcesRequestSchema as wie,ReadResourceRequestSchema as _ie,ListPromptsRequestSchema as vie,GetPromptRequestSchema as xie,ErrorCode as X_,McpError as Z_}from"@modelcontextprotocol/sdk/types.js";import dL from"axios";import Eie from"dotenv";function Uc(e){return typeof e=="object"&&e!==null&&"code"in e&&e.code==="EPIPE"}function Hc(){uL||(uL=!0,process.exit(0))}function Bm(e){if(!process.stderr.destroyed){if(process.stderr.errored){Uc(process.stderr.errored)&&Hc();return}try{process.stderr.write(e)}catch(t){Uc(t)&&Hc()}}}function $m(e){if(e instanceof Error)return e.stack||`${e.name}: ${e.message}`;if(typeof e=="object"&&e!==null)try{return JSON.stringify(e)}catch{return String(e)}return String(e)}async function Q_(){let{SessionTools:e,RelayTools:t,BrowserTools:r,DebugTools:n,LocalTestTools:i,SessionManager:s,ExtensionRelayServer:o,RelayElectionCoordinator:a}=await Promise.resolve().then(()=>(z_(),sL));return{SessionTools:e,RelayTools:t,BrowserTools:r,DebugTools:n,LocalTestTools:i,SessionManager:s,ExtensionRelayServer:o,RelayElectionCoordinator:a}}function pL(){return process.env[Sie]||null}async function Aie(){let e=process.argv.includes("--debug"),t=process.env.SHIPLIGHT_RELAY_PORT&&parseInt(process.env.SHIPLIGHT_RELAY_PORT,10)||null;await new ev(e,t).run()}var uL,tv,Sie,ev,fL=mt(()=>{"use strict";SD();z_();Yn();J_();cL();process.env.PWDEBUG="console";uL=!1;process.stdout.on("error",e=>{if(Uc(e)){Hc();return}Bm(`[MCP] stdout error: ${$m(e)}
|
|
6940
6941
|
`)});process.stderr.on("error",e=>{Uc(e)&&Hc()});tv=(...e)=>{Bm(`${e.map($m).join(" ")}
|
|
6941
6942
|
`)};console.log=tv;console.info=tv;console.debug=tv;process.on("uncaughtException",e=>{if(Uc(e)){Hc();return}Bm(`[MCP] Uncaught exception (non-fatal):
|
|
6942
6943
|
${$m(e)}
|
|
6943
6944
|
`)});process.on("unhandledRejection",e=>{if(Uc(e)){Hc();return}Bm(`[MCP] Unhandled rejection (non-fatal):
|
|
6944
6945
|
${$m(e)}
|
|
6945
|
-
`)});Eie.config({override:!1});Sie="SHIPLIGHT_API_TOKEN";ev=class{constructor(t=!1,r=null){this.debugMode=t;this.relayPort=r;Ep({stderrOnly:!0});let n=process.env.SHIPLIGHT_API_URL||"https://api.shiplight.ai";this.server=new mie({name:"shiplight-mcp",version:"1.0.0"},{capabilities:{tools:{},resources:{},prompts:{}}}),this.registry=new mm;let i=pL();if(this.apiClient=i?new dm({apiBaseUrl:n,getApiToken:()=>pL()}):null,this.apiClient){let s=new qd(this.apiClient);this.testCaseTools=s,this.registry.registerTools(qd,s,["getTestCase","getTemplate","getFunction","saveTestCase","saveTestAccount","saveTemplate","saveFunction"])}}server;registry;sessionBackend=null;apiClient;sessionTools=null;browserTools=null;debugTools=null;testCaseTools=null;localTestTools=null;relayTools=null;relayServer=null;relayCoordinator=null;async initBrowserTools(){let t=process.env.TERMINATION_TIMEOUT?parseInt(process.env.TERMINATION_TIMEOUT,10):null,{SessionTools:r,BrowserTools:n,DebugTools:i,LocalTestTools:s,SessionManager:o}=await Q_();this.sessionBackend=new o({terminationTimeout:t,onBeforeAction:process.env.SHIPLIGHT_ACTION_INDICATORS==="1"?ED:void 0}),this.sessionTools=new r(this.sessionBackend,this.apiClient),this.browserTools=new n(this.sessionBackend),this.debugTools=new i(this.sessionBackend),this.localTestTools=new s(this.sessionBackend,this.apiClient);let{RelayTools:a}=await Q_();this.relayTools=new a(this.sessionBackend),this.registry.registerAll(r,this.sessionTools).registerAll(n,this.browserTools).registerAll(i,this.debugTools).registerAll(s,this.localTestTools).registerAll(a,this.relayTools),this.apiClient&&this.registry.registerAll({toolDefinitions:s.cloudToolDefinitions},this.localTestTools)}async startRelayServer(){if(this.relayPort===null)return!1;let t=this.relayPort,{RelayTools:r,ExtensionRelayServer:n,RelayElectionCoordinator:i}=await Q_();if(!this.sessionBackend||!this.relayTools)return mo.error("[MCP] Cannot start relay server: session backend not initialized"),!1;let s=`ws://127.0.0.1:${t}/cdp`,o=new i({port:t,onPromoted:async()=>{this.relayServer=new n,await this.relayServer.start(t),this.relayTools.setRelayServer(this.relayServer),this.debugMode&&this.registry.registerAll({toolDefinitions:r.debugToolDefinitions},this.relayTools),mo.info(`[MCP] Promoted to relay master on port ${t}`)},onDemoted:async()=>{this.relayServer&&(await this.relayServer.stop(),this.relayServer=null),this.relayTools.setRemoteRelayUrl(s),mo.info("[MCP] Demoted from relay master")}});return this.relayCoordinator=o,await o.start()==="master"?mo.info(`[MCP] Relay master on port ${t}`):(this.relayTools.setRemoteRelayUrl(o.getCdpUrl()),mo.info(`[MCP] Relay follower, master on port ${t}`)),!0}setupHandlers(){let{tools:t,handleToolCall:r}=this.registry.build();this.server.setRequestHandler(bie,async()=>({tools:t})),this.server.setRequestHandler(yie,async n=>{try{let{name:i,arguments:s}=n.params,o=await r(i,s);return i==="new_session"&&lL("0.1.
|
|
6946
|
+
`)});Eie.config({override:!1});Sie="SHIPLIGHT_API_TOKEN";ev=class{constructor(t=!1,r=null){this.debugMode=t;this.relayPort=r;Ep({stderrOnly:!0});let n=process.env.SHIPLIGHT_API_URL||"https://api.shiplight.ai";this.server=new mie({name:"shiplight-mcp",version:"1.0.0"},{capabilities:{tools:{},resources:{},prompts:{}}}),this.registry=new mm;let i=pL();if(this.apiClient=i?new dm({apiBaseUrl:n,getApiToken:()=>pL()}):null,this.apiClient){let s=new qd(this.apiClient);this.testCaseTools=s,this.registry.registerTools(qd,s,["getTestCase","getTemplate","getFunction","saveTestCase","saveTestAccount","saveTemplate","saveFunction"])}}server;registry;sessionBackend=null;apiClient;sessionTools=null;browserTools=null;debugTools=null;testCaseTools=null;localTestTools=null;relayTools=null;relayServer=null;relayCoordinator=null;async initBrowserTools(){let t=process.env.TERMINATION_TIMEOUT?parseInt(process.env.TERMINATION_TIMEOUT,10):null,{SessionTools:r,BrowserTools:n,DebugTools:i,LocalTestTools:s,SessionManager:o}=await Q_();this.sessionBackend=new o({terminationTimeout:t,onBeforeAction:process.env.SHIPLIGHT_ACTION_INDICATORS==="1"?ED:void 0}),this.sessionTools=new r(this.sessionBackend,this.apiClient),this.browserTools=new n(this.sessionBackend),this.debugTools=new i(this.sessionBackend),this.localTestTools=new s(this.sessionBackend,this.apiClient);let{RelayTools:a}=await Q_();this.relayTools=new a(this.sessionBackend),this.registry.registerAll(r,this.sessionTools).registerAll(n,this.browserTools).registerAll(i,this.debugTools).registerAll(s,this.localTestTools).registerAll(a,this.relayTools),this.apiClient&&this.registry.registerAll({toolDefinitions:s.cloudToolDefinitions},this.localTestTools)}async startRelayServer(){if(this.relayPort===null)return!1;let t=this.relayPort,{RelayTools:r,ExtensionRelayServer:n,RelayElectionCoordinator:i}=await Q_();if(!this.sessionBackend||!this.relayTools)return mo.error("[MCP] Cannot start relay server: session backend not initialized"),!1;let s=`ws://127.0.0.1:${t}/cdp`,o=new i({port:t,onPromoted:async()=>{this.relayServer=new n,await this.relayServer.start(t),this.relayTools.setRelayServer(this.relayServer),this.debugMode&&this.registry.registerAll({toolDefinitions:r.debugToolDefinitions},this.relayTools),mo.info(`[MCP] Promoted to relay master on port ${t}`)},onDemoted:async()=>{this.relayServer&&(await this.relayServer.stop(),this.relayServer=null),this.relayTools.setRemoteRelayUrl(s),mo.info("[MCP] Demoted from relay master")}});return this.relayCoordinator=o,await o.start()==="master"?mo.info(`[MCP] Relay master on port ${t}`):(this.relayTools.setRemoteRelayUrl(o.getCdpUrl()),mo.info(`[MCP] Relay follower, master on port ${t}`)),!0}setupHandlers(){let{tools:t,handleToolCall:r}=this.registry.build();this.server.setRequestHandler(bie,async()=>({tools:t})),this.server.setRequestHandler(yie,async n=>{try{let{name:i,arguments:s}=n.params,o=await r(i,s);return i==="new_session"&&lL("0.1.71",!!this.apiClient),{content:[{type:"text",text:o}]}}catch(i){let s=i instanceof Error?i.message:String(i);if(dL.isAxiosError(i)){let o=i.config?.url,a=i.config?.baseURL,l=i.response?.status;s=`${i.code||"AxiosError"}: ${i.message}`,(a||o)&&(s+=` (${a||""}${o||""})`),l&&(s+=` [${l}]`),console.error(`[MCP] API error: ${s}`)}throw dL.isAxiosError(i)&&i.response?.status===401&&(s="Authentication required. Contact info@shiplight.ai to get access to cloud services and advanced features."),new Z_(X_.InternalError,s)}}),this.server.setRequestHandler(wie,async()=>({resources:ym()})),this.server.setRequestHandler(_ie,async n=>{let{uri:i}=n.params,s=await bm(i);if(!s)throw new Z_(X_.InvalidRequest,`Unknown resource: ${i}`);return{contents:[{uri:i,mimeType:"text/markdown",text:s}]}}),this.server.setRequestHandler(vie,async()=>({prompts:fm().map(i=>({name:i.name,description:i.description}))})),this.server.setRequestHandler(xie,async n=>{let{name:i}=n.params,s=hm(i);if(!s)throw new Z_(X_.InvalidRequest,`Unknown prompt: ${i}`);return{messages:[{role:"user",content:{type:"text",text:s}}]}})}async run(){await this.initBrowserTools(),await this.startRelayServer(),this.setupHandlers();let t=new gie;await this.server.connect(t),mo.info("Shiplight MCP Server running on stdio")}}});var jm="0.1.71",mL=process.argv[2];if(process.argv.includes("--version")||process.argv.includes("-v")||mL==="version"){let e=jm==="unknown"||process.argv[1]?.includes("/monots");process.stdout.write(`shiplight-mcp ${e?`${jm}-local`:jm}
|
|
6946
6947
|
`),process.exit(0)}if(process.argv.includes("--chrome-extension-path")){let e=new URL("../chrome-extension",import.meta.url).pathname;process.stdout.write(e+`
|
|
6947
6948
|
`),process.exit(0)}(process.argv.includes("--help")||process.argv.includes("-h")||mL==="help")&&(process.stdout.write(`shiplight-mcp ${jm}
|
|
6948
6949
|
|