momentic 2.4.0 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.js CHANGED
@@ -46,7 +46,7 @@ globstar while`,e,u,t,m,h),this.matchOne(e.slice(u),t.slice(m),n))return this.de
46
46
  First test path: ${u}
47
47
 
48
48
  Second test path: ${o}`)}t.tests[p.id]={type:Ae.TEST,name:p.name,id:p.id,description:p.description??void 0,labels:p.labels,...d};return}catch(p){n.warn(`Skipping file '${o}' because it is missing Momentic test metadata: ${p}`);return}case Ae.MODULE:try{let p=At.parse(a);t.modules[p.moduleId]={type:Ae.MODULE,name:p.name,id:p.moduleId,description:p.description??void 0,...d};let u=d.fileName.replace(".module.yaml","");!HS&&Ne(p.name)!==u&&n.warn(`The module with ID ${p.moduleId} has a name (${p.name}) that does not match its file name (${u}). We recommend renaming the module or the file to be consistent to avoid confusion and issues with module resolution.`);return}catch(p){n.warn(`Skipping file '${o}' because it is missing Momentic module metadata: ${p}`);return}default:n.warn(`Unsupported file type ${l}, skipping...`);return}}var Zo="momentic.config.yaml",jS="momentic.workspace.yaml",dP=ue.object({projects:ue.string().array().describe("list of glob patterns to find project (momentic.config.yaml) files")}),pP=ue.union([ue.string(),ue.object({fromFile:ue.string(),json:ue.boolean().optional()})]),uP=ue.object({name:$d,baseUrl:ue.string(),envFile:ue.string().optional().describe("path to a file on disk to read environment variables from. can be relative to project root or absolute."),envVariables:ue.record(ue.string(),pP).optional(),inheritFromShell:ue.boolean().optional().describe("inherit all environment variables from the shell - might be noisy"),browser:Mr.optional()}),mP=ue.object({postSave:ue.string().optional()}),hP=ue.object({name:$d,include:ue.string().array().optional().describe("list of glob patterns that match momentic files (optional)"),exclude:ue.string().array().optional().describe("opposite of include, takes precedence over include"),goldenFileDir:ue.string().optional(),reporterDir:ue.string().optional(),outputDir:ue.string().optional(),retries:ue.number().optional().describe("number of retries per test"),parallel:ue.number().optional().describe("degree of parallelism"),environments:ue.array(uP).optional(),gitMainBranch:ue.string().optional(),gitProtectedBranches:ue.string().array().optional(),ai:sd.extend({aiPageFiltering:ue.boolean().optional().describe("rag v2 flag")}).optional(),browser:Mr.extend({autoExpandIframes:ue.boolean().optional(),disableSecondaryCacheResolution:ue.boolean().optional(),showZeroOpacityElements:ue.boolean().optional(),globalLocatorRedirect:ue.boolean().optional(),visualActions:ue.boolean().optional()}).optional(),advanced:Xh.optional(),hooks:mP.optional()});function WS(r,e){let t;try{t=sP(r,"utf-8")}catch(o){y.warn(`Could not read possible Momentic ${e} file at ${r}: ${o}`);return}let n;try{if(n=GS.parse(t),typeof n!="object"||n===null)throw new Error(`The ${e} file should parse as a map with key-value pairs, but is type ${typeof n} instead`)}catch(o){y.warn(`Possible Momentic ${e} file at ${r} does not parse as valid YAML: ${o}`);return}return n}function Vd(r){let e=WS(r,"project configuration");if(e!==void 0)try{return hP.parse(e)}catch(t){y.warn(`Possible Momentic project configuration file at ${r} does not adhere to the required schema: ${t}`);return}}function gP(r){let e=WS(r,"workspace configuration");if(e!==void 0)try{return dP.parse(e)}catch(t){y.warn(`Possible Momentic workspace configuration file at ${r} does not adhere to the required schema: ${t}`);return}}function fP(){let r=[],e=Wd(),t=eo.parse(e).root,n=15,o=0;for(;o<n;){o++;let i=eo.basename(e);if(Is.includes(i))return y.warn(`Stopping search for Momentic projects since the current directory name (${i}) is likely a system artifact folder.`),r;for(let a of lP(e))if(a.endsWith(Zo)){let s=eo.join(e,a),l=Vd(s);l&&r.push({configFilePath:s,config:l,rootDir:$S(s)})}if(r.length)return r;if(e=eo.dirname(e),e===t)break}return r}function nn(r={}){let{configFilePath:e,nameFilter:t}=r,n=qd(e);if(t&&(n=n.filter(o=>o.config.name===t)),n.length>1)throw new Error(`Multiple valid projects were found in the same directory. Please use the '-c / --config' flag to disambiguate:
49
- ${n.map(o=>o.configFilePath)}`);if(n.length===0)throw new Error("No valid Momentic project file available.");return y.debug(`Found valid project configuration at ${n[0].configFilePath}`),n[0]}function SP(r){let e=gP(r);if(!e||!e.projects||!e.projects.length)return;let t=e.projects.map(i=>(i.endsWith("/")||(i+="/"),`${i}*${Zo}`)),n=Xo(t,{absolute:!1,cwd:Wd(),dotRelative:!1,maxDepth:Gd,nodir:!0}),o=[];for(let i of n){let a=eo.join(Wd(),i),s=Vd(a);s&&o.push({configFilePath:a,config:s,rootDir:$S(a)})}return o}function qd(r){if(r){r=eo.resolve(r);let t=Vd(r);return t||(console.error(`No valid Momentic project file found at ${r}.`),process.exit(1)),[{config:t,configFilePath:r,rootDir:eo.dirname(r)}]}if(aP(jS)){let t=SP(jS);if(t)return t}return fP()}function Qo(r,e){let t=GS.stringify(r);cP(e,t)}import ei from"fs";import Kd from"path";import{z as Yd}from"zod";var VS="golden/visual-diff",qS="reports",KS="test-results";var yP=Yd.object({width:Yd.number(),height:Yd.number()}),ti=class{defaultGoldenScreenshotDir;regenerateGoldenFiles;constructor(e,t){let n=Kd.join(e.rootDir,e.config.goldenFileDir??VS);this.defaultGoldenScreenshotDir=n,this.regenerateGoldenFiles=t}async prepareGoldenScreenshotForComparison(e,t,n){if(t.screenshot?.data?.startsWith("https://")){let a=await fetch(t.screenshot.data);return{buffer:Buffer.from(await a.arrayBuffer()),width:t.screenshot.width,height:t.screenshot.height}}let o=t.screenshot?.data;o||(o=Kd.join(this.defaultGoldenScreenshotDir,`${t.id}.jpg`));let i=`${o}.metadata.json`;if(this.regenerateGoldenFiles)return ei.mkdirSync(Kd.dirname(o),{recursive:!0}),ei.writeFileSync(o,n.buffer),ei.writeFileSync(i,JSON.stringify({width:n.width,height:n.height})),{buffer:Buffer.from(n.buffer),width:n.width,height:n.height};if(ei.existsSync(o)){let a=ei.readFileSync(o),s=yP.parse(JSON.parse(ei.readFileSync(i,"utf-8")));return{buffer:a,width:s.width,height:s.height}}else throw new R("UserConfigurationError",`Cannot execute visual diff without a saved baseline screenshot at ${o}`)}};var ni=class{flags;constructor(e){this.flags={auto_expand_iframes:e.browser?.autoExpandIframes??!1,rag_v2:e.ai?.aiPageFiltering??!1,faker_constant_seed:e.advanced?.fakerConstantSeed??!1,disable_secondary_cache_resolution:e.browser?.disableSecondaryCacheResolution??!1,show_zero_opacity_elements:e.browser?.showZeroOpacityElements??!1,global_locator_redirect:e.browser?.globalLocatorRedirect??!1,visual_actions:e.browser?.visualActions??!1,mini_model_initial_assertion:!1,mini_model_initial_locator:!1,show_test_plans:!1,icon_knowledge_base:!1,disable_clickhouse_caches:!1,disable_clickhouse_last_updated_endpoint:!1}}isBooleanFlagEnabled(e){return this.flags[e]}getAllFlags(){return{...this.flags}}getFlagPayload(e){}async refresh(){}};import bP from"simple-git";var ve=bP();function ll(r){if(r.startsWith("git@")){let e=r.split(":");if(e.length===2){let t=e[1].replace(".git","").split("/");if(t.length===2){let n=t[0],o=t[1];return`${n}/${o}`}}}else if(r.startsWith("http")||r.startsWith("https")){let t=new URL(r).pathname.split("/").filter(Boolean);if(t.length>=2){let n=t[0],o=t[1].replace(".git","");return`${n}/${o}`}}}async function xe(r,e){try{return(await e).trim()}catch(t){r.error({err:t},"Failed to run git command");return}}function wP(){if(process.env.GITHUB_ACTION)return"GithubActions";if(process.env.GITLAB_CI)return"GitlabCI";if(process.env.CIRCLECI)return"CircleCI";if(process.env.BUILDKITE)return"Buildkite";if(process.env["System.CollectionUri"]?.includes("azure"))return"AzureDevOps"}async function vP(r){let[e,t,n,o]=await Promise.all([xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.listRemote(["--get-url","origin"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]);return{gitCommitSha:process.env.GITHUB_SHA,gitCommitShaShort:process.env.GITHUB_SHA?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.GITHUB_HEAD_REF||process.env.GITHUB_REF_NAME,gitOriginUrl:t,gitCommitMessage:n,gitCommitAuthorName:o,githubRepository:process.env.GITHUB_REPOSITORY,pipelineId:`${process.env.GITHUB_RUN_ID}:${process.env.GITHUB_RUN_ATTEMPT}`}}async function xP(r){let[e,t,n]=await Promise.all([xe(r,ve.listRemote(["--get-url","origin"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]);return{gitCommitSha:process.env.CI_COMMIT_SHA,gitCommitShaShort:process.env.CI_COMMIT_SHORT_SHA,gitCommitTimestamp:process.env.CI_COMMIT_TIMESTAMP?new Date(process.env.CI_COMMIT_TIMESTAMP):void 0,gitBranchName:process.env.CI_COMMIT_BRANCH||process.env.CI_COMMIT_REF_NAME,gitOriginUrl:e,gitCommitMessage:t,gitCommitAuthorName:n,gitlabProjectPath:process.env.CI_SERVER_HOST,pipelineId:`${process.env.CI_PIPELINE_ID}:${process.env.CI_JOB_ID}`}}async function TP(r){let[e,t,n,o]=await Promise.all([xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.listRemote(["--get-url","origin"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]),i=t?.includes("github.com"),a=t?.includes("gitlab.com"),s=t?ll(t):void 0;return{gitCommitSha:process.env.CIRCLE_SHA1,gitCommitShaShort:process.env.CIRCLE_SHA1?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.CIRCLE_BRANCH,gitOriginUrl:process.env.CIRCLE_REPOSITORY_URL,gitCommitMessage:n,gitCommitAuthorName:o,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env.CIRCLE_WORKFLOW_ID}:${process.env.CIRCLE_WORKFLOW_JOB_ID}`}}async function EP(r){let[e,t,n]=await Promise.all([xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]),o=process.env.BUILDKITE_REPO,i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?ll(o):void 0;return{gitCommitSha:process.env.BUILDKITE_COMMIT,gitCommitShaShort:process.env.BUILDKITE_COMMIT?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.BUILDKITE_BRANCH,gitOriginUrl:o,gitCommitMessage:t,gitCommitAuthorName:n,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env.BUILDKITE_PIPELINE_ID}:${process.env.BUILDKITE_BUILD_ID}:${process.env.BUILDKITE_JOB_ID}`}}async function CP(r){let[e,t,n]=await Promise.all([xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]),o=process.env["Build.Repository.Uri"],i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?ll(o):void 0;return{gitCommitSha:process.env["Build.SourceVersion"],gitCommitShaShort:process.env["Build.SourceVersion"]?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env["Build.SourceBranchName"],gitOriginUrl:o,gitCommitMessage:t,gitCommitAuthorName:n,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env["System.JobId"]}:${process.env["System.JobAttempt"]}`}}async function RP(r,e){let[t,n,o,i,a,s,l,c]=await Promise.all([xe(r,ve.revparse(["HEAD"])),xe(r,ve.revparse(["--short","HEAD"])),xe(r,ve.revparse(["--abbrev-ref","HEAD"])),xe(r,ve.listRemote(["--get-url","origin"])),xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"])),e?xe(r,ve.raw(["merge-base","--fork-point",e])):Promise.resolve(void 0)]),d=c?await xe(r,ve.show(["--no-patch","--format=%ci",c])):void 0,p=i?.includes("github.com"),u=i?.includes("gitlab.com"),m=i?ll(i):void 0;return{gitCommitSha:t,gitCommitShaShort:n,gitBranchName:o,gitOriginUrl:i,gitCommitTimestamp:a?new Date(a):void 0,gitCommitMessage:s,gitCommitAuthorName:l,lastCommitOnMainSha:c,lastCommitOnMainTimestamp:d?new Date(d):void 0,githubRepository:p?m:void 0,gitlabProjectPath:u?m:void 0,pipelineId:void 0}}async function AP(r){let e=r.config.gitProtectedBranches??[];return r.config.gitMainBranch&&e.push(r.config.gitMainBranch),{gitMainBranch:r.config.gitMainBranch,gitProtectedBranches:e}}async function IP(r,e){let t=wP();if(!t)return RP(r,e);switch(t){case"GithubActions":return vP(r);case"GitlabCI":return xP(r);case"CircleCI":return TP(r);case"Buildkite":return EP(r);case"AzureDevOps":return CP(r)}}async function PP(r,e,t){if(t.lastCommitOnMainSha&&t.lastCommitOnMainTimestamp)return{};if(t.gitlabProjectPath){if(!t.gitMainBranch||!t.gitCommitSha)return{};try{let n=await e.getMergeBaseCommitFromGitlab(t.gitlabProjectPath,t.gitMainBranch,t.gitCommitSha);return{lastCommitOnMainSha:n.sha,lastCommitOnMainTimestamp:n.committer.date}}catch(n){return r.warn({err:n},"Failed to get remote metadata from Gitlab"),{}}}if(t.githubRepository){if(!t.gitMainBranch||!t.gitCommitSha)return{};try{let[n,o]=t.githubRepository.split("/"),i=await e.getMergeBaseCommitFromGithub(n,o,t.gitMainBranch,t.gitCommitSha);return{lastCommitOnMainSha:i.sha,lastCommitOnMainTimestamp:i.committer.date}}catch(n){return r.warn({err:n},"Failed to get remote metadata from Github"),{}}}return{}}async function ri(r,e,t){let n=await AP(t),o=await IP(r,n.gitMainBranch),i={...n,...o},a=await PP(r,e,i);return{...n,...o,...a}}import BN from"http";import{z as Zd}from"zod";var j="v1",Aa="2.4.0";var hr=class extends Error{constructor(e){super(e),this.name="TimeoutError"}};var YS=r=>{let e=r.reason===void 0?new DOMException("This operation was aborted.","AbortError"):r.reason;return e instanceof Error?e:new DOMException(e,"AbortError")};async function D(r,e){let{milliseconds:t,fallback:n,message:o,customTimers:i={setTimeout,clearTimeout}}=e,a,s;return new Promise((l,c)=>{if(typeof t!="number"||Math.sign(t)!==1)throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${t}\``);if(e.signal){let{signal:p}=e;p.aborted&&c(YS(p)),s=()=>{c(YS(p))},p.addEventListener("abort",s)}if(t===Number.POSITIVE_INFINITY){r.then(l,c);return}let d=new hr;a=i.setTimeout.call(void 0,()=>{if(n){try{l(n())}catch(p){c(p)}return}"cancel"in r&&typeof r.cancel=="function"&&r.cancel(),o instanceof Error?c(o):(d.message=o??`Promise timed out after ${t} milliseconds`,c(d))},t),(async()=>{try{l(await r)}catch(p){c(p)}})()}).catch(l=>{throw l}).finally(()=>{a!==void 0&&i.clearTimeout.call(void 0,a),s!==void 0&&e.signal&&e.signal.removeEventListener("abort",s)})}var cl=class{limit;windowMs;userActions;constructor(e,t){this.limit=e,this.windowMs=t,this.userActions=new Map}_cleanup(e,t="DEFAULT_USER"){let n=Date.now(),o=`${t}:${e}`;if(this.userActions.has(o)){let a=this.userActions.get(o)?.filter(s=>n-s<=this.windowMs)??[];a.length>0?this.userActions.set(o,a):this.userActions.delete(o)}}increment(e,t="DEFAULT_USER"){let n=Date.now(),o=`${t}:${e}`;this._cleanup(t,e),this.userActions.has(o)||this.userActions.set(o,[]);let i=this.userActions.get(o);return i.length>=this.limit?!0:(i.push(n),!1)}};var Jd=["ability","able","aboard","about","above","accept","accident","according","account","accurate","acres","across","act","action","active","activity","actual","actually","add","addition","additional","adjective","adult","adventure","advice","affect","afraid","after","afternoon","again","against","age","ago","agree","ahead","aid","air","airplane","alike","alive","all","allow","almost","alone","along","aloud","alphabet","already","also","although","am","among","amount","ancient","angle","angry","animal","announced","another","answer","ants","any","anybody","anyone","anything","anyway","anywhere","apart","apartment","appearance","apple","applied","appropriate","are","area","arm","army","around","arrange","arrangement","arrive","arrow","art","article","as","aside","ask","asleep","at","ate","atmosphere","atom","atomic","attached","attack","attempt","attention","audience","author","automobile","available","average","avoid","aware","away","baby","back","bad","badly","bag","balance","ball","balloon","band","bank","bar","bare","bark","barn","base","baseball","basic","basis","basket","bat","battle","be","bean","bear","beat","beautiful","beauty","became","because","become","becoming","bee","been","before","began","beginning","begun","behavior","behind","being","believed","bell","belong","below","belt","bend","beneath","bent","beside","best","bet","better","between","beyond","bicycle","bigger","biggest","bill","birds","birth","birthday","bit","bite","black","blank","blanket","blew","blind","block","blood","blow","blue","board","boat","body","bone","book","border","born","both","bottle","bottom","bound","bow","bowl","box","boy","brain","branch","brass","brave","bread","break","breakfast","breath","breathe","breathing","breeze","brick","bridge","brief","bright","bring","broad","broke","broken","brother","brought","brown","brush","buffalo","build","building","built","buried","burn","burst","bus","bush","business","busy","but","butter","buy","by","cabin","cage","cake","call","calm","came","camera","camp","can","canal","cannot","cap","capital","captain","captured","car","carbon","card","care","careful","carefully","carried","carry","case","cast","castle","cat","catch","cattle","caught","cause","cave","cell","cent","center","central","century","certain","certainly","chain","chair","chamber","chance","change","changing","chapter","character","characteristic","charge","chart","check","cheese","chemical","chest","chicken","chief","child","children","choice","choose","chose","chosen","church","circle","circus","citizen","city","class","classroom","claws","clay","clean","clear","clearly","climate","climb","clock","close","closely","closer","cloth","clothes","clothing","cloud","club","coach","coal","coast","coat","coffee","cold","collect","college","colony","color","column","combination","combine","come","comfortable","coming","command","common","community","company","compare","compass","complete","completely","complex","composed","composition","compound","concerned","condition","congress","connected","consider","consist","consonant","constantly","construction","contain","continent","continued","contrast","control","conversation","cook","cookies","cool","copper","copy","corn","corner","correct","correctly","cost","cotton","could","count","country","couple","courage","course","court","cover","cow","cowboy","crack","cream","create","creature","crew","crop","cross","crowd","cry","cup","curious","current","curve","customs","cut","cutting","daily","damage","dance","danger","dangerous","dark","darkness","date","daughter","dawn","day","dead","deal","dear","death","decide","declared","deep","deeply","deer","definition","degree","depend","depth","describe","desert","design","desk","detail","determine","develop","development","diagram","diameter","did","die","differ","difference","different","difficult","difficulty","dig","dinner","direct","direction","directly","dirt","dirty","disappear","discover","discovery","discuss","discussion","disease","dish","distance","distant","divide","division","do","doctor","does","dog","doing","doll","dollar","done","donkey","door","dot","double","doubt","down","dozen","draw","drawn","dream","dress","drew","dried","drink","drive","driven","driver","driving","drop","dropped","drove","dry","duck","due","dug","dull","during","dust","duty","each","eager","ear","earlier","early","earn","earth","easier","easily","east","easy","eat","eaten","edge","education","effect","effort","egg","eight","either","electric","electricity","element","elephant","eleven","else","empty","end","enemy","energy","engine","engineer","enjoy","enough","enter","entire","entirely","environment","equal","equally","equator","equipment","escape","especially","essential","establish","even","evening","event","eventually","ever","every","everybody","everyone","everything","everywhere","evidence","exact","exactly","examine","example","excellent","except","exchange","excited","excitement","exciting","exclaimed","exercise","exist","expect","experience","experiment","explain","explanation","explore","express","expression","extra","eye","face","facing","fact","factor","factory","failed","fair","fairly","fall","fallen","familiar","family","famous","far","farm","farmer","farther","fast","fastened","faster","fat","father","favorite","fear","feathers","feature","fed","feed","feel","feet","fell","fellow","felt","fence","few","fewer","field","fierce","fifteen","fifth","fifty","fight","fighting","figure","fill","film","final","finally","find","fine","finest","finger","finish","fire","fireplace","firm","first","fish","five","fix","flag","flame","flat","flew","flies","flight","floating","floor","flow","flower","fly","fog","folks","follow","food","foot","football","for","force","foreign","forest","forget","forgot","forgotten","form","former","fort","forth","forty","forward","fought","found","four","fourth","fox","frame","free","freedom","frequently","fresh","friend","friendly","frighten","frog","from","front","frozen","fruit","fuel","full","fully","fun","function","funny","fur","furniture","further","future","gain","game","garage","garden","gas","gasoline","gate","gather","gave","general","generally","gentle","gently","get","getting","giant","gift","girl","give","given","giving","glad","glass","globe","go","goes","gold","golden","gone","good","goose","got","government","grabbed","grade","gradually","grain","grandfather","grandmother","graph","grass","gravity","gray","great","greater","greatest","greatly","green","grew","ground","group","grow","grown","growth","guard","guess","guide","gulf","gun","habit","had","hair","half","halfway","hall","hand","handle","handsome","hang","happen","happened","happily","happy","harbor","hard","harder","hardly","has","hat","have","having","hay","he","headed","heading","health","heard","hearing","heart","heat","heavy","height","held","hello","help","helpful","her","herd","here","herself","hidden","hide","high","higher","highest","highway","hill","him","himself","his","history","hit","hold","hole","hollow","home","honor","hope","horn","horse","hospital","hot","hour","house","how","however","huge","human","hundred","hung","hungry","hunt","hunter","hurried","hurry","hurt","husband","ice","idea","identity","if","ill","image","imagine","immediately","importance","important","impossible","improve","in","inch","include","including","income","increase","indeed","independent","indicate","individual","industrial","industry","influence","information","inside","instance","instant","instead","instrument","interest","interior","into","introduced","invented","involved","iron","is","island","it","its","itself","jack","jar","jet","job","join","joined","journey","joy","judge","jump","jungle","just","keep","kept","key","kids","kill","kind","kitchen","knew","knife","know","knowledge","known","label","labor","lack","lady","laid","lake","lamp","land","language","large","larger","largest","last","late","later","laugh","law","lay","layers","lead","leader","leaf","learn","least","leather","leave","leaving","led","left","leg","length","lesson","let","letter","level","library","lie","life","lift","light","like","likely","limited","line","lion","lips","liquid","list","listen","little","live","living","load","local","locate","location","log","lonely","long","longer","look","loose","lose","loss","lost","lot","loud","love","lovely","low","lower","luck","lucky","lunch","lungs","lying","machine","machinery","mad","made","magic","magnet","mail","main","mainly","major","make","making","man","managed","manner","manufacturing","many","map","mark","market","married","mass","massage","master","material","mathematics","matter","may","maybe","me","meal","mean","means","meant","measure","meat","medicine","meet","melted","member","memory","men","mental","merely","met","metal","method","mice","middle","might","mighty","mile","military","milk","mill","mind","mine","minerals","minute","mirror","missing","mission","mistake","mix","mixture","model","modern","molecular","moment","money","monkey","month","mood","moon","more","morning","most","mostly","mother","motion","motor","mountain","mouse","mouth","move","movement","movie","moving","mud","muscle","music","musical","must","my","myself","mysterious","nails","name","nation","national","native","natural","naturally","nature","near","nearby","nearer","nearest","nearly","necessary","neck","needed","needle","needs","negative","neighbor","neighborhood","nervous","nest","never","new","news","newspaper","next","nice","night","nine","no","nobody","nodded","noise","none","noon","nor","north","nose","not","note","noted","nothing","notice","noun","now","number","numeral","nuts","object","observe","obtain","occasionally","occur","ocean","of","off","offer","office","officer","official","oil","old","older","oldest","on","once","one","only","onto","open","operation","opinion","opportunity","opposite","or","orange","orbit","order","ordinary","organization","organized","origin","original","other","ought","our","ourselves","out","outer","outline","outside","over","own","owner","oxygen","pack","package","page","paid","pain","paint","pair","palace","pale","pan","paper","paragraph","parallel","parent","park","part","particles","particular","particularly","partly","parts","party","pass","passage","past","path","pattern","pay","peace","pen","pencil","people","per","percent","perfect","perfectly","perhaps","period","person","personal","pet","phrase","physical","piano","pick","picture","pictured","pie","piece","pig","pile","pilot","pine","pink","pipe","pitch","place","plain","plan","plane","planet","planned","planning","plant","plastic","plate","plates","play","pleasant","please","pleasure","plenty","plural","plus","pocket","poem","poet","poetry","point","pole","police","policeman","political","pond","pony","pool","poor","popular","population","porch","port","position","positive","possible","possibly","post","pot","potatoes","pound","pour","powder","power","powerful","practical","practice","prepare","present","president","press","pressure","pretty","prevent","previous","price","pride","primitive","principal","principle","printed","private","prize","probably","problem","process","produce","product","production","program","progress","promised","proper","properly","property","protection","proud","prove","provide","public","pull","pupil","pure","purple","purpose","push","put","putting","quarter","queen","question","quick","quickly","quiet","quietly","quite","rabbit","race","radio","railroad","rain","raise","ran","ranch","range","rapidly","rate","rather","raw","rays","reach","read","reader","ready","real","realize","rear","reason","recall","receive","recent","recently","recognize","record","red","refer","refused","region","regular","related","relationship","religious","remain","remarkable","remember","remove","repeat","replace","replied","report","represent","require","research","respect","rest","result","return","review","rhyme","rhythm","rice","rich","ride","riding","right","ring","rise","rising","river","road","roar","rock","rocket","rocky","rod","roll","roof","room","root","rope","rose","rough","round","route","row","rubbed","rubber","rule","ruler","run","running","rush","sad","saddle","safe","safety","said","sail","sale","salmon","salt","same","sand","sang","sat","satellites","satisfied","save","saved","saw","say","scale","scared","scene","school","science","scientific","scientist","score","screen","sea","search","season","seat","second","secret","section","see","seed","seeing","seems","seen","seldom","select","selection","sell","send","sense","sent","sentence","separate","series","serious","serve","service","sets","setting","settle","settlers","seven","several","shade","shadow","shake","shaking","shall","shallow","shape","share","sharp","she","sheep","sheet","shelf","shells","shelter","shine","shinning","ship","shirt","shoe","shoot","shop","shore","short","shorter","shot","should","shoulder","shout","show","shown","shut","sick","sides","sight","sign","signal","silence","silent","silk","silly","silver","similar","simple","simplest","simply","since","sing","single","sink","sister","sit","sitting","situation","six","size","skill","skin","sky","slabs","slave","sleep","slept","slide","slight","slightly","slip","slipped","slope","slow","slowly","small","smaller","smallest","smell","smile","smoke","smooth","snake","snow","so","soap","social","society","soft","softly","soil","solar","sold","soldier","solid","solution","solve","some","somebody","somehow","someone","something","sometime","somewhere","son","song","soon","sort","sound","source","south","southern","space","speak","special","species","specific","speech","speed","spell","spend","spent","spider","spin","spirit","spite","split","spoken","sport","spread","spring","square","stage","stairs","stand","standard","star","stared","start","state","statement","station","stay","steady","steam","steel","steep","stems","step","stepped","stick","stiff","still","stock","stomach","stone","stood","stop","stopped","store","storm","story","stove","straight","strange","stranger","straw","stream","street","strength","stretch","strike","string","strip","strong","stronger","struck","structure","struggle","stuck","student","studied","studying","subject","substance","success","successful","such","sudden","suddenly","sugar","suggest","suit","sum","summer","sun","sunlight","supper","supply","support","suppose","sure","surface","surprise","surrounded","swam","sweet","swept","swim","swimming","swing","swung","syllable","symbol","system","table","tail","take","taken","tales","talk","tall","tank","tape","task","taste","taught","tax","tea","teach","teacher","team","tears","teeth","telephone","television","tell","temperature","ten","tent","term","terrible","test","than","thank","that","thee","them","themselves","then","theory","there","therefore","these","they","thick","thin","thing","think","third","thirty","this","those","thou","though","thought","thousand","thread","three","threw","throat","through","throughout","throw","thrown","thumb","thus","thy","tide","tie","tight","tightly","till","time","tin","tiny","tip","tired","title","to","tobacco","today","together","told","tomorrow","tone","tongue","tonight","too","took","tool","top","topic","torn","total","touch","toward","tower","town","toy","trace","track","trade","traffic","trail","train","transportation","trap","travel","treated","tree","triangle","tribe","trick","tried","trip","troops","tropical","trouble","truck","trunk","truth","try","tube","tune","turn","twelve","twenty","twice","two","type","typical","uncle","under","underline","understanding","unhappy","union","unit","universe","unknown","unless","until","unusual","up","upon","upper","upward","us","use","useful","using","usual","usually","valley","valuable","value","vapor","variety","various","vast","vegetable","verb","vertical","very","vessels","victory","view","village","visit","visitor","voice","volume","vote","vowel","voyage","wagon","wait","walk","wall","want","war","warm","warn","was","wash","waste","watch","water","wave","way","we","weak","wealth","wear","weather","week","weigh","weight","welcome","well","went","were","west","western","wet","whale","what","whatever","wheat","wheel","when","whenever","where","wherever","whether","which","while","whispered","whistle","white","who","whole","whom","whose","why","wide","widely","wife","wild","will","willing","win","wind","window","wing","winter","wire","wise","wish","with","within","without","wolf","women","won","wonder","wonderful","wood","wooden","wool","word","wore","work","worker","world","worried","worry","worse","worth","would","wrapped","write","writer","writing","written","wrong","wrote","yard","year","yellow","yes","yesterday","yet","you","young","younger","your","yourself","youth","zero","zebra","zipper","zoo","zulu"];function JS(r){return new Array(r).fill(0).map(()=>Jd[Math.floor(Math.random()*Jd.length)]).join("-")}var LP=9e4,OP=15e3,yn=class extends Error{status;rawError;constructor(e,t,n,o={}){super(n,o),this.status=e,this.rawError=t}};async function MP(r){return r.text().then(e=>{try{return JSON.parse(e).error}catch{return e}})}var Xd=class{baseUrl;logger;constructor(e){this.baseUrl=e.baseUrl,this.logger=e.logger}getHeaders(){let e={"Content-Type":"application/json"};return Aa&&(e[Zh]=Aa),e}async sendRequest(e,t,n=3,o=LP){let i=n,a,s={path:e,baseUrl:this.baseUrl,method:t.method};for(;n>0;)try{return n--,await this.sendSingleRequestHelper(e,t,o)}catch(l){if(a=l,l instanceof yn&&l.status>=400&&l.status<500)throw l;if(l instanceof Error&&l.name==="AbortError"&&(a=new hr),n===0)throw a;let c=1500,d=i-n,p=Math.min(c*Math.pow(2,d-1),OP);await new Promise(u=>setTimeout(u,p))}throw this.logger.warn({...s,err:a},"Got fatal error response from Momentic server"),a}async sendSingleRequestHelper(e,t,n){let o={path:e,baseUrl:this.baseUrl,method:t.method},i=new AbortController,a=setTimeout(()=>i.abort(),n),s=()=>i.abort();t.signal&&t.signal.addEventListener("abort",s);let l={...this.getHeaders(),...t.extraHeaders};try{let c=await fetch(`${this.baseUrl}${e}`,{method:t.method,body:t.body?JSON.stringify(t.body):void 0,headers:l,signal:i.signal});if(!c.ok){let p=await MP(c);throw new yn(c.status,p,`Request to ${e} failed with status ${c.status}: ${p}`)}let d;if(c.status===204)d={};else{let p=await c.text();try{d=JSON.parse(p)}catch{d=p}}return this.logger&&!t.noLog&&d&&this.logger.debug({result:d,status:c.status,...o},"Got response from Momentic server"),d}finally{clearTimeout(a),t.signal&&t.signal.removeEventListener("abort",s)}}},Nt=class extends Xd{apiKey;constructor(e){super(e),this.apiKey=e.apiKey}getHeaders(){return{...super.getHeaders(),Authorization:`Bearer ${this.apiKey}`}}};var lt=class extends Nt{constructor(e){super(e)}getAppUrl(){return this.baseUrl.replace(/\/\/api/,"//app")}async getAuthInfo(){let e=await this.sendRequest(`/${j}/auth/check`,{method:"GET",noLog:!0},10,5e3),{orgId:t,userId:n}=yg.parse(e);return{orgId:t,userId:n}}async bulkGetRunStatus(e){let t=await this.sendRequest(`/${j}/runs/status`,{method:"POST",body:e,noLog:!0},3,1e4);return hg.parse(t)}async getTestYAMLExport(e){let t=await this.sendRequest(`/${j}/tests/export`,{method:"POST",body:e},3,3e4);return cg.parse(t)}async updateStepCaches(e,t){await this.sendRequest(`/${j}/cache`,{method:"PATCH",body:e,extraHeaders:t},3,1e4)}async getStepCacheForTest(e,t){let n=await this.sendRequest(`/${j}/cache`,{method:"POST",body:e,extraHeaders:t},10,3e4);return dg.parse(n)}async queueTests(e){let t=await this.sendRequest(`/${j}/tests/queue`,{method:"POST",body:e},3,1e4);return lg.parse(t)}async uploadScreenshot(e){let t=await this.sendRequest(`/${j}/screenshots`,{method:"POST",body:e,noLog:!0},3,5e3);return Sg.parse(t)}async getAllEnvironments(){let e=await this.sendRequest(`/${j}/environments`,{method:"GET"},3,5e3);return bg.parse(e)}async acquireCacheLock(e,t){let n=await this.sendRequest(`/${j}/result-cache/lock`,{method:"POST",body:e,signal:t},3,3e4);return Rg.parse(n)}async releaseCacheLock(e){await this.sendRequest(`/${j}/result-cache/lock`,{method:"DELETE",body:{key:e}},3,5e3)}async deleteCacheResult(e){await this.sendRequest(`/${j}/result-cache/entry`,{method:"DELETE",body:e},3,5e3)}async setCacheResult(e){await this.sendRequest(`/${j}/result-cache/entry`,{method:"PATCH",body:e},3,5e3)}async getCacheResult(e){try{return await this.sendRequest(`/${j}/result-cache/entry`,{method:"POST",body:e},3,5e3)}catch(t){if(t instanceof Error&&t.message.includes("404"))return null;throw t}}async queueSuiteRuns(e){let t=await this.sendRequest(`/${j}/suites/queue`,{method:"POST",body:e},3,5e3);return wg.parse(t)}async bulkGetRunGroupStatus(e){let t={runGroupIds:e},n=await this.sendRequest(`/${j}/run-groups/status`,{method:"POST",body:t,noLog:!0},3,5e3);return Zm.array().parse(n)}async updateCacheLastUsedDate(e,t,n,o){try{await this.sendRequest(`/${j}/cache/last-used-at`,{method:"PATCH",body:{uniqueKeys:t,testId:e},noLog:!0,extraHeaders:o},3,7500)}catch(i){n.error({err:i},"Failed to update cache last used date")}}async uploadProposedSteps(e,t){try{await this.sendRequest(`/${j}/test-fragments/`,{method:"POST",body:e},3,1e4)}catch(n){t.error({err:n},"Failed to upload proposed steps")}}async uploadSnapshotScreenshot(e,t,n){try{await this.sendRequest(`/${j}/snapshots/${t}/screenshot`,{method:"POST",body:n,noLog:!0},3,1e4)}catch(o){e.error({err:o},"Failed to upload screenshot")}}async generateConsoleLogsForRunAttemptUploadUrl(e,t,n){let o=await this.sendRequest(`/${j}/runs/${t}/attempts/${n}/console-logs`,{method:"POST",noLog:!0},3,5e3);return na.parse(o)}async generateNetworkLogsForRunAttemptUploadUrl(e,t,n){let o=await this.sendRequest(`/${j}/runs/${t}/attempts/${n}/network-logs`,{method:"POST",noLog:!0},3,1e4);return na.parse(o)}async generateHtmlSnapshotUploadUrl(e,t){let n=await this.sendRequest(`/${j}/snapshots/${t}/html`,{method:"POST",noLog:!0},3,1e4);return na.parse(n)}async reportBillableEvents(e,t){try{await this.sendRequest(`/${j}/billing/events`,{method:"POST",body:t,noLog:!0},10,1e4)}catch(n){e.error({err:n},"Failed to report billable event")}}async fetchTestFragment(e){let t=await this.sendRequest(`/${j}/test-fragments/${e}`,{method:"GET",noLog:!0},3,1e4);return vg.parse(t)}async patchTestFragment(e,t){await this.sendRequest(`/${j}/test-fragments/${e}`,{method:"PATCH",body:t},3,1e4)}async getPastTestResults(e,t){let n=await this.sendRequest(`/${j}/results/tests/${e}`,{method:"POST",body:t},3,1e4);return xg.parse(n)}async generateTestResultsUploadUrl(){let e=await this.sendRequest(`/${j}/results/uploads`,{method:"POST",noLog:!0},3,1e4);return Tg.parse(e)}async startProcessingResultsUpload(e,t){let n=await this.sendRequest(`/${j}/results/uploads/${e}/process`,{method:"POST",noLog:!0,body:t},3,1e4);return Eg.parse(n)}async fetchIconKnowledgeBase(e,t){try{let n=await this.sendRequest(`/${j}/knowledge-base/icons`,{method:"GET",noLog:!0},3,5e3);return Mg.parse(n)}catch(n){return t.error({err:n},"Failed to fetch icon knowledge base"),null}}async saveNewIcons(e,t){try{await this.sendRequest(`/${j}/knowledge-base/icons`,{method:"POST",body:e,noLog:!0},3,5e3)}catch(n){t.error({err:n},"Failed to save new icons to icon knowledge base")}}async getMergeBaseCommitFromGithub(e,t,n,o){let i=new URLSearchParams;i.set("base",n),i.set("head",o);let a=await this.sendRequest(`/${j}/git/github/${e}/${t}/merge-base-commit?${i.toString()}`,{method:"GET",noLog:!0},3,1e4);return dd.parse(a)}async getMergeBaseCommitFromGitlab(e,t,n){let o=new URLSearchParams;o.set("base",t),o.set("head",n);let i=await this.sendRequest(`/${j}/git/gitlab/${e}/merge-base-commit?${o.toString()}`,{method:"GET",noLog:!0},3,5e3);return dd.parse(i)}async getAgentConfig(){let e=await this.sendRequest(`/${j}/web-agent/agent-config`,{method:"GET",noLog:!0},3,5e3);return Zd.record(Zd.string(),Zd.string()).parse(e)}};import{randomUUID as XS}from"crypto";var dl=class{apiClient;constructor(e){this.apiClient=e}async reportBillableEvent(e,t,n){try{return await this.apiClient.reportBillableEvents(e,[{event:t,timestamp:new Date().toISOString(),transactionId:n?.eventId??XS(),properties:Zc({},n)}])}catch(o){e.error({err:o},"Failed to report billable event")}}async reportCreditsUsed(e,t,n,o){if(n)try{return await this.apiClient.reportBillableEvents(e,[{event:"credits-used",timestamp:new Date().toISOString(),transactionId:o?.eventId??XS(),properties:Zc({creditsUsed:n,usedBy:t},o)}])}catch(i){e.error({err:i},"Failed to report credits used")}}};function oi(r,e,t){return fetch(r,{method:"PUT",body:t,headers:{"Content-Type":e}})}var pl=class{constructor(e){this.client=e}async storeConsoleLogsForRunAttempt(e,t,n,o){try{let i=JSON.stringify(o),{uploadUrl:a}=await this.client.generateConsoleLogsForRunAttemptUploadUrl(e,t,n),s=await oi(a,"application/json",i);if(!s.ok)throw new Error(`Failed to upload network logs: ${s.statusText}`)}catch(i){e.error({err:i},"Failed to upload console logs")}}async storeNetworkLogsForRunAttempt(e,t,n,o){let i=JSON.stringify(o);try{let{uploadUrl:a}=await this.client.generateNetworkLogsForRunAttemptUploadUrl(e,t,n),s=await oi(a,"application/json",i);if(!s.ok)throw new Error(`Failed to upload network logs: ${s.statusText}`)}catch(a){e.error({err:a},"Failed to upload network logs")}}async storeHtmlSnapshot(e,t,n){try{let{uploadUrl:o}=await this.client.generateHtmlSnapshotUploadUrl(e,t),i=await oi(o,"text/html",n);if(!i.ok)throw new Error(`Failed to upload network logs: ${i.statusText}`)}catch(o){e.error({err:o},"Failed to upload html snapshot")}}async storeScreenshot(e,t,n){try{await this.client.uploadSnapshotScreenshot(e,t,{screenshot:n.toString("base64")})}catch(o){e.error({err:o},"Failed to upload screenshot")}}async storeA11yTreeSnapshot(e,t,n){return Promise.resolve()}async getConsoleLogsForRunAttempt(e,t,n){}async getNetworkLogsForRunAttempt(e,t,n){}async getHtmlSnapshot(e,t){}async getA11yTreeSnapshot(e,t){}async getScreenshot(e,t){}};var ii=class{constructor(e,t){this.client=e;this.orgId=t}async acquireCacheLock(e,t){return this.client.acquireCacheLock(e,t)}async uploadScreenshot(e){return(await this.client.uploadScreenshot({screenshot:e.toString("base64")})).key}async releaseCacheLock(e){return this.client.releaseCacheLock(e)}async deleteCacheResult(e){return this.client.deleteCacheResult(e)}async setCacheResult(e){return this.client.setCacheResult(e)}async getCacheResult(e){return this.client.getCacheResult(e)}fetchIconKnowledgeBase(e,t){return this.client.fetchIconKnowledgeBase(e,t)}saveNewIcons(e,t,n){return this.client.saveNewIcons(t,n)}};import{Faker as NP,en as kP}from"@faker-js/faker";var ai="v1",gr=class{httpClient;fakerInstance;type="API_CLIENT";sms={send:this.sendSms.bind(this),fetchLatest:this.fetchLatestSms.bind(this)};email={send:this.sendEmail.bind(this),fetchLatest:this.fetchLatestEmail.bind(this),fetchAll:this.fetchAllEmails.bind(this)};ai={generate:this.sendAiGenerate.bind(this)};constructor(e){this.httpClient=e.httpClient,e.fakerSeed&&(this.fakerInstance=new NP({locale:kP}),this.fakerInstance.seed(e.fakerSeed))}async sendAiGenerate(e){let t=typeof e=="string"?{input:e}:e;return this.httpClient.sendRequest(`/${ai}/tools/ai/generate`,{method:"POST",body:t}).catch(n=>{throw n instanceof yn?new Error(n.rawError):new Error(`Failed to send AI generation: ${n.message}`)})}async sendSms(e){return this.httpClient.sendRequest(`/${ai}/tools/sms/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to send sms: ${t.message}`)})}async fetchLatestSms(e){return this.httpClient.sendRequest(`/${ai}/tools/sms/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):t})}async sendEmail(e){return this.httpClient.sendRequest(`/${ai}/tools/email/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to send email: ${t.message}`)})}async fetchAllEmails(e){return this.httpClient.sendRequest(`/${ai}/tools/email/fetchAll`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to fetch all emails: ${t.message}`)})}async fetchLatestEmail(e){return this.httpClient.sendRequest(`/${ai}/tools/email/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to fetch latest emails: ${t.message}`)})}};import{z as _P}from"zod";var si=class extends Nt{agentConfig;constructor(e,t){super(t),this.agentConfig=e}async rankChunksWithAi(e,t){let n={...e,loggerTags:t.loggerTags},o=await this.sendRequest(`/${j}/web-agent/recommend-chunks-ai`,{method:"POST",body:n,signal:t.abortSignal});return mh.parse(o)}async rankChunksWithRag(e,t){let n=await this.sendRequest(`/${j}/web-agent/recommend-chunks`,{method:"POST",body:{cliVersion:Aa,...e},signal:t.abortSignal});return uh.parse(n)}async getScreenshotFromS3(e){let t=await this.sendRequest(`/${j}/s3/visual-diff-screenshot`,{method:"POST",body:{url:e}});return _P.string().parse(t)}async getElementLocation(e,t){let n={...e,disableCache:t.disableCache,loggerTags:t.loggerTags,agentConfigVersion:this.agentConfig?.locator},o=await this.sendRequest(`/${j}/web-agent/locate-element`,{method:"POST",body:n,signal:t.abortSignal});return ag.parse(o)}async getAssertionResult(e,t){let n={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,attemptNumber:t.attemptNumber,loggerTags:t.loggerTags,agentConfigVersion:this.agentConfig?.locator},o=await this.sendRequest(`/${j}/web-agent/assertion`,{method:"POST",body:n,signal:t.abortSignal});return ld.parse(o)}async getLintStepResult(e,t){let n={...e,disableCache:!!t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${j}/web-agent/lint/step`,{method:"POST",body:n,signal:t.abortSignal});return ig.parse(o)}async getVisualAssertionResult(e,t){let n={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,loggerTags:t.loggerTags},o=await this.sendRequest(`/${j}/web-agent/visual-assertion`,{method:"POST",body:n,signal:t.abortSignal});return ld.parse(o)}async getAiActionCommand(e,t){let n=await this.sendRequest(`/${j}/web-agent/next-command-dynamic`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return og.parse(n)}async getMultiturnAiActionCommand(e,t){return await this.sendRequest(`/${j}/web-agent/ai-action/next-command`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal})}async getMultiturnAiActionEvaluation(e,t){let n=await this.sendRequest(`/${j}/web-agent/ai-action/evaluate`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return Rc.parse(n)}async getReverseMappedDescription(e,t){let n=await this.sendRequest(`/${j}/web-agent/reverse-mapped-description`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return sg.parse(n)}async getTextExtraction(e,t){let n={...e,disableCache:t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${j}/web-agent/text-extraction`,{method:"POST",body:n,signal:t.abortSignal});return Cc.parse(o)}async getTestResultClassification(e,t){let n=await this.sendRequest(`/${j}/web-agent/result-classification`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Uc.parse(n)}async getExtractedKeywords(e,t){let n=await this.sendRequest(`/${j}/web-agent/extract-keywords`,{method:"POST",body:{goal:e,disableCache:t.disableCache,context:e},signal:t.abortSignal});return ph.parse(n)}async getAutohealingProposal(e,t){let n=await this.sendRequest(`/${j}/web-agent/autoheal-section`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return em.parse(n)}async getFailureRecoveryProposal(e,t){let n=await this.sendRequest(`/${j}/web-agent/failure-recovery`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return tm.parse(n)}async getIframeRegex(e,t){let n=await this.sendRequest(`/${j}/web-agent/iframe-regex`,{method:"POST",body:e,signal:t.abortSignal});return _u.parse(n)}};var li=class extends Nt{generator;constructor(e,t){super(e),this.generator=t}async runTemplateMatching(e,t={}){let n=await this.sendRequest(`/${j}/web-agent/template-matching`,{method:"POST",body:e,signal:t?.signal});return Du.parse(n)}async constructIframeRegex(e,t={}){return this.generator.getIframeRegex(e,{abortSignal:t.signal})}};var ul=class{constructor(e){this.client=e}async uploadResultsArchive(e,t){let{uploadUrl:n,id:o}=await this.client.generateTestResultsUploadUrl(),i=await oi(n,"application/zip",t);if(!i.ok)throw new Error(`Failed to upload test results: ${await i.text()}`);let{runGroupId:a}=await this.client.startProcessingResultsUpload(o,{runGroupId:e});return a}};function ci({client:r,gitMetadata:e,alwaysSaveCache:t,noCache:n}){return n?new Ls:new Qd(r,e,t)}var Qd=class{constructor(e,{gitMainBranch:t,gitBranchName:n,gitProtectedBranches:o,gitCommitTimestamp:i,lastCommitOnMainSha:a,lastCommitOnMainTimestamp:s},l){this.client=e;this.cacheHeaders={},t&&(this.cacheHeaders[Qh]=t),n&&(this.cacheHeaders[eg]=n),i&&(this.cacheHeaders[tg]=i.toISOString()),a&&(this.cacheHeaders[ng]=a),s&&(this.cacheHeaders[rg]=s.toISOString()),l?this.writeCaches=!0:n?this.writeCaches=!o.includes(n):this.writeCaches=!0}cacheHeaders;writeCaches;async saveStepCacheEntries(e,t,n){if(!this.writeCaches){n.debug("Skipping cache storage because branch is protected");return}try{await this.client.updateStepCaches({entries:e,testId:t},this.cacheHeaders)}catch(o){n.error({err:o},"Failed to save step cache entries")}}async resolveStepCacheEntries(e){let t=await this.client.getStepCacheForTest({testId:e.testId,organizationId:e.organizationId,steps:e.steps,schemaVersion:e.schemaVersion},this.cacheHeaders);if(!this.writeCaches){e.logger.debug("Skipping cache last used at update because branch is protected");return}let{uniqueKeysHit:n}=Fo({steps:e.steps,stepCacheEntries:t,logger:e.logger});this.client.updateCacheLastUsedDate(e.testId,n,e.logger,this.cacheHeaders)}};import{Server as pN}from"socket.io";import{cloneDeep as DP}from"lodash-es";var FP={showOverlay:!1},ep=class{sessions=new Map;sessionCountByIp=new Map;getCurrentConnectionsByIp(e){return this.sessionCountByIp.get(e)??0}getCurrentSessionsByIp(){return Object.fromEntries(this.sessionCountByIp)}reserveCapacityByIp(e){e&&this.sessionCountByIp.set(e,(this.sessionCountByIp.get(e)??0)+1)}releaseCapacityByIp(e){e&&this.sessionCountByIp.set(e,Math.max(this.getCurrentConnectionsByIp(e)-1,0))}registerSession({controller:e,context:t,cleanup:n,clientIp:o,sessionId:i,browserbaseSessionId:a}){return this.sessions.set(i,{controller:e,context:t,cleanup:n,clientIp:o,browserbaseSessionId:a,browserBehavior:DP(FP)}),i}removeSession(e,t){(async()=>{let o=this.sessions.get(e);if(!o)return;this.releaseCapacityByIp(o.clientIp);let{controller:i}=o;try{i.setClosed(),await i.browser.cleanup()}catch(a){t.error({err:a},"Error cleaning up browser in global state manager")}try{await o.cleanup?.()}catch(a){t.error({err:a},"Error running cleanup function in global state manager")}this.sessions.delete(e)})()}getSession(e){return this.sessions.get(e)}},Q=new ep;function ZS(r,e,t){let n=Date.now(),o=Date.now(),i,a,s,l,c=!1,d=async(h,g)=>{if(!h.closed&&!h.isInPageLoad)try{let f=s;s=void 0;let S=h.url(),v=g.toEditorDisplayCopy();JSON.stringify(v)===JSON.stringify(i)&&S===l&&n>o||(r.emit("browserState",{logsPerPage:f?.logsPerPage,harPages:f?.harPages,harEntries:f?.harEntries,viewport:h.getViewport(),url:S,iframeSrcUrls:a??[],context:v,isInPageLoad:h.isInPageLoad}),n=Date.now()),l=S,i=v}catch(f){if(!r.connected)return;let S=f instanceof Error?f.message:`${f}`;if(S.includes("Frame was detached")||S.includes("Not attached to an active page")||S.includes("browser has been closed")||S.includes("UserInfrastructureError"))return;t.error({err:f,sessionId:e},"Error grabbing browser state")}},p=setInterval(()=>{let h=Q.getSession(e),g=h?.controller?.browser;if(!g||g.closed){t.debug("Clearing browser state socket cron due to the browser being closed"),clearInterval(p);return}d(g,h.context)},1e3),u=(h,g)=>!!(JSON.stringify(h)!==JSON.stringify(a)||g.logsPerPage.some(f=>f.length>0)||g.harPages&&Object.keys(g.harPages).length>0||g.harEntries&&Object.keys(g.harEntries).length>0),m=setInterval(async()=>{let g=Q.getSession(e)?.controller?.browser;if(!g||g.closed){clearInterval(m);return}else if(c)return;c=!0;try{let f=await g.getAllFrameUrls(),S=g.retrieveAndClearDebugData();u(f,S)&&(a=f,s=S,o=Date.now())}catch(f){t.warn({err:f},"Failed to fetch extended details")}finally{c=!1}},2500);return{timers:[p,m]}}var fr={};var UP=r=>()=>{let{sessionId:e}=r.metadata;fr[e]?.abort?.abort()},QS={event:"cancelApiTest",createHandler:UP};import{CookieJar as rL}from"tough-cookie";import{randomUUID as VP}from"crypto";import{faker as BP}from"@faker-js/faker";import zP from"assert";import HP from"axios";import jP from"moment";import*as $P from"otpauth";import GP from"pg";async function ey(r){let e;try{e=new URL(r.url).hostname}catch{}let t=[];return r.headers.getSetCookie()?.forEach(n=>{let o=xs(n,e);t.push(...o)}),t}var WP=Object.getPrototypeOf(async function(){}).constructor;async function ty(r,e,t){let n=e.code;e.options.fragment&&(n=`return ${e.code}`);let{env:o}=e.bindings,i=e.tools,a={},s=(f,S)=>{o[f]=S,a[f]=S},l={},c=(f,S)=>{o[f]=S,l[f]=S},d;n.includes("Octokit")&&(d=(await import("@octokit/rest")).Octokit);let p;n.includes("createAppAuth")&&(p=(await import("@octokit/auth-app")).createAppAuth);let u=async()=>await Promise.resolve(new WP("axios","moment","faker","assert","pg","Octokit","createAppAuth","OTPAuth","extractCookiesFromResponse","env","setVariable","setPersistentVariable","sendSms","waitForLatestSms","email","sms","ai",n)(HP,jP,i.fakerInstance??BP,zP,GP,d,p,$P,ey,o,s,c,S=>i.sms.send(S),S=>i.sms.fetchLatest(S),i.email,i.sms,i.ai)),m=!0,h,g;try{h=await D(u(),{milliseconds:e.options.timeoutMs,message:`Timeout of ${e.options.timeoutMs}ms exceeded for code execution`,signal:e.signal})}catch(f){t.error({err:f,env:o,evalCode:n},`[${r}] Error executing code: ${f}`),m=!1,f instanceof hr?g=`Timeout of ${e.options.timeoutMs}ms exceeded for code execution`:g=f instanceof Error?f.message:`${f}`}return{result:h,variableUpdates:a,persistentVariableUpdates:l,success:m,error:g}}async function ny({code:r,fragment:e,context:t,localTools:n,logger:o,signal:i,timeoutMs:a=ar}){let s=VP(),l=await ty(s,{code:r,options:{fragment:e,timeoutMs:a},bindings:t.toObjectCopy(),tools:n,signal:i},o);return y.debug(`[${s}] Got execution result: ${JSON.stringify(l)}`),l}import{createHmac as qP,randomUUID as KP}from"crypto";import YP from"fetch-retry";var JP=YP(global.fetch,{retries:3,retryOn:function(r,e,t){return!!(e!==null||t&&t.status>=500)},retryDelay:function(r){return Math.pow(2,r)*500}}),ry=process.env.GCP_JS_EVAL_FUNCTION_ENDPOINT,oy=process.env.MOMENTIC_LAMBDA_AUTH_SECRET;async function iy({orgId:r,code:e,fragment:t,context:n,timeoutMs:o=ar,retries:i=2,signal:a,logger:s}){if(!ry)throw new Error("GCP_JS_EVAL_FUNCTION_ENDPOINT environment variable not set");let l,c,d=0;if(!oy)throw new Error("Missing lambda auth secret.");let p=qP("sha256",oy).update(r).digest("hex");for(;d<=i;){d++,a?.throwIfAborted();let m={id:KP(),orgId:r,momenticLambdaAuthHash:p,code:e,fragment:t,state:n.toObjectCopy(),timeoutMs:o};try{if(l=await D(JP(ry,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(m)}),{milliseconds:o,message:`Timeout of ${o}ms exceeded for code execution`,signal:a}),!l)throw new Error("Got empty response from code evaluation server");if(!l.ok)throw new Error(`Code evaluation server returned error code ${l.status}`);c=void 0;break}catch(h){c=h}}if(c)throw s.error({err:c},"Failed to evaluate code remotely"),c;if(!l)throw new Error(`An unexpected code evaluation error occurred${c?`: ${c}`:""}`);let u;try{u=vh.parse(await l.json())}catch(m){throw new Error(`Code evaluation server returned invalid response: ${m}`)}if(u.error)throw new Error(`Code evaluation error: ${u.error}`);return u}async function Kn(r){let e;if(process.env.GCP_JS_EVAL_FUNCTION_ENDPOINT)e=await iy(r);else if(r.localTools)e=await ny({...r,localTools:r.localTools});else throw new Error("No code evaluation environment available");if(e.error){let t=`Failed to evaluate code:
49
+ ${n.map(o=>o.configFilePath)}`);if(n.length===0)throw new Error("No valid Momentic project file available.");return y.debug(`Found valid project configuration at ${n[0].configFilePath}`),n[0]}function SP(r){let e=gP(r);if(!e||!e.projects||!e.projects.length)return;let t=e.projects.map(i=>(i.endsWith("/")||(i+="/"),`${i}*${Zo}`)),n=Xo(t,{absolute:!1,cwd:Wd(),dotRelative:!1,maxDepth:Gd,nodir:!0}),o=[];for(let i of n){let a=eo.join(Wd(),i),s=Vd(a);s&&o.push({configFilePath:a,config:s,rootDir:$S(a)})}return o}function qd(r){if(r){r=eo.resolve(r);let t=Vd(r);return t||(console.error(`No valid Momentic project file found at ${r}.`),process.exit(1)),[{config:t,configFilePath:r,rootDir:eo.dirname(r)}]}if(aP(jS)){let t=SP(jS);if(t)return t}return fP()}function Qo(r,e){let t=GS.stringify(r);cP(e,t)}import ei from"fs";import Kd from"path";import{z as Yd}from"zod";var VS="golden/visual-diff",qS="reports",KS="test-results";var yP=Yd.object({width:Yd.number(),height:Yd.number()}),ti=class{defaultGoldenScreenshotDir;regenerateGoldenFiles;constructor(e,t){let n=Kd.join(e.rootDir,e.config.goldenFileDir??VS);this.defaultGoldenScreenshotDir=n,this.regenerateGoldenFiles=t}async prepareGoldenScreenshotForComparison(e,t,n){if(t.screenshot?.data?.startsWith("https://")){let a=await fetch(t.screenshot.data);return{buffer:Buffer.from(await a.arrayBuffer()),width:t.screenshot.width,height:t.screenshot.height}}let o=t.screenshot?.data;o||(o=Kd.join(this.defaultGoldenScreenshotDir,`${t.id}.jpg`));let i=`${o}.metadata.json`;if(this.regenerateGoldenFiles)return ei.mkdirSync(Kd.dirname(o),{recursive:!0}),ei.writeFileSync(o,n.buffer),ei.writeFileSync(i,JSON.stringify({width:n.width,height:n.height})),{buffer:Buffer.from(n.buffer),width:n.width,height:n.height};if(ei.existsSync(o)){let a=ei.readFileSync(o),s=yP.parse(JSON.parse(ei.readFileSync(i,"utf-8")));return{buffer:a,width:s.width,height:s.height}}else throw new R("UserConfigurationError",`Cannot execute visual diff without a saved baseline screenshot at ${o}`)}};var ni=class{flags;constructor(e){this.flags={auto_expand_iframes:e.browser?.autoExpandIframes??!1,rag_v2:e.ai?.aiPageFiltering??!1,faker_constant_seed:e.advanced?.fakerConstantSeed??!1,disable_secondary_cache_resolution:e.browser?.disableSecondaryCacheResolution??!1,show_zero_opacity_elements:e.browser?.showZeroOpacityElements??!1,global_locator_redirect:e.browser?.globalLocatorRedirect??!1,visual_actions:e.browser?.visualActions??!1,mini_model_initial_assertion:!1,mini_model_initial_locator:!1,show_test_plans:!1,icon_knowledge_base:!1,disable_clickhouse_caches:!1,disable_clickhouse_last_updated_endpoint:!1}}isBooleanFlagEnabled(e){return this.flags[e]}getAllFlags(){return{...this.flags}}getFlagPayload(e){}async refresh(){}};import bP from"simple-git";var ve=bP();function ll(r){if(r.startsWith("git@")){let e=r.split(":");if(e.length===2){let t=e[1].replace(".git","").split("/");if(t.length===2){let n=t[0],o=t[1];return`${n}/${o}`}}}else if(r.startsWith("http")||r.startsWith("https")){let t=new URL(r).pathname.split("/").filter(Boolean);if(t.length>=2){let n=t[0],o=t[1].replace(".git","");return`${n}/${o}`}}}async function xe(r,e){try{return(await e).trim()}catch(t){r.error({err:t},"Failed to run git command");return}}function wP(){if(process.env.GITHUB_ACTION)return"GithubActions";if(process.env.GITLAB_CI)return"GitlabCI";if(process.env.CIRCLECI)return"CircleCI";if(process.env.BUILDKITE)return"Buildkite";if(process.env["System.CollectionUri"]?.includes("azure"))return"AzureDevOps"}async function vP(r){let[e,t,n,o]=await Promise.all([xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.listRemote(["--get-url","origin"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]);return{gitCommitSha:process.env.GITHUB_SHA,gitCommitShaShort:process.env.GITHUB_SHA?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.GITHUB_HEAD_REF||process.env.GITHUB_REF_NAME,gitOriginUrl:t,gitCommitMessage:n,gitCommitAuthorName:o,githubRepository:process.env.GITHUB_REPOSITORY,pipelineId:`${process.env.GITHUB_RUN_ID}:${process.env.GITHUB_RUN_ATTEMPT}`}}async function xP(r){let[e,t,n]=await Promise.all([xe(r,ve.listRemote(["--get-url","origin"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]);return{gitCommitSha:process.env.CI_COMMIT_SHA,gitCommitShaShort:process.env.CI_COMMIT_SHORT_SHA,gitCommitTimestamp:process.env.CI_COMMIT_TIMESTAMP?new Date(process.env.CI_COMMIT_TIMESTAMP):void 0,gitBranchName:process.env.CI_COMMIT_BRANCH||process.env.CI_COMMIT_REF_NAME,gitOriginUrl:e,gitCommitMessage:t,gitCommitAuthorName:n,gitlabProjectPath:process.env.CI_SERVER_HOST,pipelineId:`${process.env.CI_PIPELINE_ID}:${process.env.CI_JOB_ID}`}}async function TP(r){let[e,t,n,o]=await Promise.all([xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.listRemote(["--get-url","origin"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]),i=t?.includes("github.com"),a=t?.includes("gitlab.com"),s=t?ll(t):void 0;return{gitCommitSha:process.env.CIRCLE_SHA1,gitCommitShaShort:process.env.CIRCLE_SHA1?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.CIRCLE_BRANCH,gitOriginUrl:process.env.CIRCLE_REPOSITORY_URL,gitCommitMessage:n,gitCommitAuthorName:o,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env.CIRCLE_WORKFLOW_ID}:${process.env.CIRCLE_WORKFLOW_JOB_ID}`}}async function EP(r){let[e,t,n]=await Promise.all([xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]),o=process.env.BUILDKITE_REPO,i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?ll(o):void 0;return{gitCommitSha:process.env.BUILDKITE_COMMIT,gitCommitShaShort:process.env.BUILDKITE_COMMIT?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env.BUILDKITE_BRANCH,gitOriginUrl:o,gitCommitMessage:t,gitCommitAuthorName:n,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env.BUILDKITE_PIPELINE_ID}:${process.env.BUILDKITE_BUILD_ID}:${process.env.BUILDKITE_JOB_ID}`}}async function CP(r){let[e,t,n]=await Promise.all([xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"]))]),o=process.env["Build.Repository.Uri"],i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?ll(o):void 0;return{gitCommitSha:process.env["Build.SourceVersion"],gitCommitShaShort:process.env["Build.SourceVersion"]?.slice(0,6),gitCommitTimestamp:e?new Date(e):void 0,gitBranchName:process.env["Build.SourceBranchName"],gitOriginUrl:o,gitCommitMessage:t,gitCommitAuthorName:n,githubRepository:i?s:void 0,gitlabProjectPath:a?s:void 0,pipelineId:`${process.env["System.JobId"]}:${process.env["System.JobAttempt"]}`}}async function RP(r,e){let[t,n,o,i,a,s,l,c]=await Promise.all([xe(r,ve.revparse(["HEAD"])),xe(r,ve.revparse(["--short","HEAD"])),xe(r,ve.revparse(["--abbrev-ref","HEAD"])),xe(r,ve.listRemote(["--get-url","origin"])),xe(r,ve.show(["--no-patch","--format=%ci"])),xe(r,ve.show(["-s","--pretty=%B"])),xe(r,ve.show(["-s","--pretty=%an"])),e?xe(r,ve.raw(["merge-base","--fork-point",e])):Promise.resolve(void 0)]),d=c?await xe(r,ve.show(["--no-patch","--format=%ci",c])):void 0,p=i?.includes("github.com"),u=i?.includes("gitlab.com"),m=i?ll(i):void 0;return{gitCommitSha:t,gitCommitShaShort:n,gitBranchName:o,gitOriginUrl:i,gitCommitTimestamp:a?new Date(a):void 0,gitCommitMessage:s,gitCommitAuthorName:l,lastCommitOnMainSha:c,lastCommitOnMainTimestamp:d?new Date(d):void 0,githubRepository:p?m:void 0,gitlabProjectPath:u?m:void 0,pipelineId:void 0}}async function AP(r){let e=r.config.gitProtectedBranches??[];return r.config.gitMainBranch&&e.push(r.config.gitMainBranch),{gitMainBranch:r.config.gitMainBranch,gitProtectedBranches:e}}async function IP(r,e){let t=wP();if(!t)return RP(r,e);switch(t){case"GithubActions":return vP(r);case"GitlabCI":return xP(r);case"CircleCI":return TP(r);case"Buildkite":return EP(r);case"AzureDevOps":return CP(r)}}async function PP(r,e,t){if(t.lastCommitOnMainSha&&t.lastCommitOnMainTimestamp)return{};if(t.gitlabProjectPath){if(!t.gitMainBranch||!t.gitCommitSha)return{};try{let n=await e.getMergeBaseCommitFromGitlab(t.gitlabProjectPath,t.gitMainBranch,t.gitCommitSha);return{lastCommitOnMainSha:n.sha,lastCommitOnMainTimestamp:n.committer.date}}catch(n){return r.warn({err:n},"Failed to get remote metadata from Gitlab"),{}}}if(t.githubRepository){if(!t.gitMainBranch||!t.gitCommitSha)return{};try{let[n,o]=t.githubRepository.split("/"),i=await e.getMergeBaseCommitFromGithub(n,o,t.gitMainBranch,t.gitCommitSha);return{lastCommitOnMainSha:i.sha,lastCommitOnMainTimestamp:i.committer.date}}catch(n){return r.warn({err:n},"Failed to get remote metadata from Github"),{}}}return{}}async function ri(r,e,t){let n=await AP(t),o=await IP(r,n.gitMainBranch),i={...n,...o},a=await PP(r,e,i);return{...n,...o,...a}}import BN from"http";import{z as Zd}from"zod";var j="v1",Aa="2.4.2";var hr=class extends Error{constructor(e){super(e),this.name="TimeoutError"}};var YS=r=>{let e=r.reason===void 0?new DOMException("This operation was aborted.","AbortError"):r.reason;return e instanceof Error?e:new DOMException(e,"AbortError")};async function D(r,e){let{milliseconds:t,fallback:n,message:o,customTimers:i={setTimeout,clearTimeout}}=e,a,s;return new Promise((l,c)=>{if(typeof t!="number"||Math.sign(t)!==1)throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${t}\``);if(e.signal){let{signal:p}=e;p.aborted&&c(YS(p)),s=()=>{c(YS(p))},p.addEventListener("abort",s)}if(t===Number.POSITIVE_INFINITY){r.then(l,c);return}let d=new hr;a=i.setTimeout.call(void 0,()=>{if(n){try{l(n())}catch(p){c(p)}return}"cancel"in r&&typeof r.cancel=="function"&&r.cancel(),o instanceof Error?c(o):(d.message=o??`Promise timed out after ${t} milliseconds`,c(d))},t),(async()=>{try{l(await r)}catch(p){c(p)}})()}).catch(l=>{throw l}).finally(()=>{a!==void 0&&i.clearTimeout.call(void 0,a),s!==void 0&&e.signal&&e.signal.removeEventListener("abort",s)})}var cl=class{limit;windowMs;userActions;constructor(e,t){this.limit=e,this.windowMs=t,this.userActions=new Map}_cleanup(e,t="DEFAULT_USER"){let n=Date.now(),o=`${t}:${e}`;if(this.userActions.has(o)){let a=this.userActions.get(o)?.filter(s=>n-s<=this.windowMs)??[];a.length>0?this.userActions.set(o,a):this.userActions.delete(o)}}increment(e,t="DEFAULT_USER"){let n=Date.now(),o=`${t}:${e}`;this._cleanup(t,e),this.userActions.has(o)||this.userActions.set(o,[]);let i=this.userActions.get(o);return i.length>=this.limit?!0:(i.push(n),!1)}};var Jd=["ability","able","aboard","about","above","accept","accident","according","account","accurate","acres","across","act","action","active","activity","actual","actually","add","addition","additional","adjective","adult","adventure","advice","affect","afraid","after","afternoon","again","against","age","ago","agree","ahead","aid","air","airplane","alike","alive","all","allow","almost","alone","along","aloud","alphabet","already","also","although","am","among","amount","ancient","angle","angry","animal","announced","another","answer","ants","any","anybody","anyone","anything","anyway","anywhere","apart","apartment","appearance","apple","applied","appropriate","are","area","arm","army","around","arrange","arrangement","arrive","arrow","art","article","as","aside","ask","asleep","at","ate","atmosphere","atom","atomic","attached","attack","attempt","attention","audience","author","automobile","available","average","avoid","aware","away","baby","back","bad","badly","bag","balance","ball","balloon","band","bank","bar","bare","bark","barn","base","baseball","basic","basis","basket","bat","battle","be","bean","bear","beat","beautiful","beauty","became","because","become","becoming","bee","been","before","began","beginning","begun","behavior","behind","being","believed","bell","belong","below","belt","bend","beneath","bent","beside","best","bet","better","between","beyond","bicycle","bigger","biggest","bill","birds","birth","birthday","bit","bite","black","blank","blanket","blew","blind","block","blood","blow","blue","board","boat","body","bone","book","border","born","both","bottle","bottom","bound","bow","bowl","box","boy","brain","branch","brass","brave","bread","break","breakfast","breath","breathe","breathing","breeze","brick","bridge","brief","bright","bring","broad","broke","broken","brother","brought","brown","brush","buffalo","build","building","built","buried","burn","burst","bus","bush","business","busy","but","butter","buy","by","cabin","cage","cake","call","calm","came","camera","camp","can","canal","cannot","cap","capital","captain","captured","car","carbon","card","care","careful","carefully","carried","carry","case","cast","castle","cat","catch","cattle","caught","cause","cave","cell","cent","center","central","century","certain","certainly","chain","chair","chamber","chance","change","changing","chapter","character","characteristic","charge","chart","check","cheese","chemical","chest","chicken","chief","child","children","choice","choose","chose","chosen","church","circle","circus","citizen","city","class","classroom","claws","clay","clean","clear","clearly","climate","climb","clock","close","closely","closer","cloth","clothes","clothing","cloud","club","coach","coal","coast","coat","coffee","cold","collect","college","colony","color","column","combination","combine","come","comfortable","coming","command","common","community","company","compare","compass","complete","completely","complex","composed","composition","compound","concerned","condition","congress","connected","consider","consist","consonant","constantly","construction","contain","continent","continued","contrast","control","conversation","cook","cookies","cool","copper","copy","corn","corner","correct","correctly","cost","cotton","could","count","country","couple","courage","course","court","cover","cow","cowboy","crack","cream","create","creature","crew","crop","cross","crowd","cry","cup","curious","current","curve","customs","cut","cutting","daily","damage","dance","danger","dangerous","dark","darkness","date","daughter","dawn","day","dead","deal","dear","death","decide","declared","deep","deeply","deer","definition","degree","depend","depth","describe","desert","design","desk","detail","determine","develop","development","diagram","diameter","did","die","differ","difference","different","difficult","difficulty","dig","dinner","direct","direction","directly","dirt","dirty","disappear","discover","discovery","discuss","discussion","disease","dish","distance","distant","divide","division","do","doctor","does","dog","doing","doll","dollar","done","donkey","door","dot","double","doubt","down","dozen","draw","drawn","dream","dress","drew","dried","drink","drive","driven","driver","driving","drop","dropped","drove","dry","duck","due","dug","dull","during","dust","duty","each","eager","ear","earlier","early","earn","earth","easier","easily","east","easy","eat","eaten","edge","education","effect","effort","egg","eight","either","electric","electricity","element","elephant","eleven","else","empty","end","enemy","energy","engine","engineer","enjoy","enough","enter","entire","entirely","environment","equal","equally","equator","equipment","escape","especially","essential","establish","even","evening","event","eventually","ever","every","everybody","everyone","everything","everywhere","evidence","exact","exactly","examine","example","excellent","except","exchange","excited","excitement","exciting","exclaimed","exercise","exist","expect","experience","experiment","explain","explanation","explore","express","expression","extra","eye","face","facing","fact","factor","factory","failed","fair","fairly","fall","fallen","familiar","family","famous","far","farm","farmer","farther","fast","fastened","faster","fat","father","favorite","fear","feathers","feature","fed","feed","feel","feet","fell","fellow","felt","fence","few","fewer","field","fierce","fifteen","fifth","fifty","fight","fighting","figure","fill","film","final","finally","find","fine","finest","finger","finish","fire","fireplace","firm","first","fish","five","fix","flag","flame","flat","flew","flies","flight","floating","floor","flow","flower","fly","fog","folks","follow","food","foot","football","for","force","foreign","forest","forget","forgot","forgotten","form","former","fort","forth","forty","forward","fought","found","four","fourth","fox","frame","free","freedom","frequently","fresh","friend","friendly","frighten","frog","from","front","frozen","fruit","fuel","full","fully","fun","function","funny","fur","furniture","further","future","gain","game","garage","garden","gas","gasoline","gate","gather","gave","general","generally","gentle","gently","get","getting","giant","gift","girl","give","given","giving","glad","glass","globe","go","goes","gold","golden","gone","good","goose","got","government","grabbed","grade","gradually","grain","grandfather","grandmother","graph","grass","gravity","gray","great","greater","greatest","greatly","green","grew","ground","group","grow","grown","growth","guard","guess","guide","gulf","gun","habit","had","hair","half","halfway","hall","hand","handle","handsome","hang","happen","happened","happily","happy","harbor","hard","harder","hardly","has","hat","have","having","hay","he","headed","heading","health","heard","hearing","heart","heat","heavy","height","held","hello","help","helpful","her","herd","here","herself","hidden","hide","high","higher","highest","highway","hill","him","himself","his","history","hit","hold","hole","hollow","home","honor","hope","horn","horse","hospital","hot","hour","house","how","however","huge","human","hundred","hung","hungry","hunt","hunter","hurried","hurry","hurt","husband","ice","idea","identity","if","ill","image","imagine","immediately","importance","important","impossible","improve","in","inch","include","including","income","increase","indeed","independent","indicate","individual","industrial","industry","influence","information","inside","instance","instant","instead","instrument","interest","interior","into","introduced","invented","involved","iron","is","island","it","its","itself","jack","jar","jet","job","join","joined","journey","joy","judge","jump","jungle","just","keep","kept","key","kids","kill","kind","kitchen","knew","knife","know","knowledge","known","label","labor","lack","lady","laid","lake","lamp","land","language","large","larger","largest","last","late","later","laugh","law","lay","layers","lead","leader","leaf","learn","least","leather","leave","leaving","led","left","leg","length","lesson","let","letter","level","library","lie","life","lift","light","like","likely","limited","line","lion","lips","liquid","list","listen","little","live","living","load","local","locate","location","log","lonely","long","longer","look","loose","lose","loss","lost","lot","loud","love","lovely","low","lower","luck","lucky","lunch","lungs","lying","machine","machinery","mad","made","magic","magnet","mail","main","mainly","major","make","making","man","managed","manner","manufacturing","many","map","mark","market","married","mass","massage","master","material","mathematics","matter","may","maybe","me","meal","mean","means","meant","measure","meat","medicine","meet","melted","member","memory","men","mental","merely","met","metal","method","mice","middle","might","mighty","mile","military","milk","mill","mind","mine","minerals","minute","mirror","missing","mission","mistake","mix","mixture","model","modern","molecular","moment","money","monkey","month","mood","moon","more","morning","most","mostly","mother","motion","motor","mountain","mouse","mouth","move","movement","movie","moving","mud","muscle","music","musical","must","my","myself","mysterious","nails","name","nation","national","native","natural","naturally","nature","near","nearby","nearer","nearest","nearly","necessary","neck","needed","needle","needs","negative","neighbor","neighborhood","nervous","nest","never","new","news","newspaper","next","nice","night","nine","no","nobody","nodded","noise","none","noon","nor","north","nose","not","note","noted","nothing","notice","noun","now","number","numeral","nuts","object","observe","obtain","occasionally","occur","ocean","of","off","offer","office","officer","official","oil","old","older","oldest","on","once","one","only","onto","open","operation","opinion","opportunity","opposite","or","orange","orbit","order","ordinary","organization","organized","origin","original","other","ought","our","ourselves","out","outer","outline","outside","over","own","owner","oxygen","pack","package","page","paid","pain","paint","pair","palace","pale","pan","paper","paragraph","parallel","parent","park","part","particles","particular","particularly","partly","parts","party","pass","passage","past","path","pattern","pay","peace","pen","pencil","people","per","percent","perfect","perfectly","perhaps","period","person","personal","pet","phrase","physical","piano","pick","picture","pictured","pie","piece","pig","pile","pilot","pine","pink","pipe","pitch","place","plain","plan","plane","planet","planned","planning","plant","plastic","plate","plates","play","pleasant","please","pleasure","plenty","plural","plus","pocket","poem","poet","poetry","point","pole","police","policeman","political","pond","pony","pool","poor","popular","population","porch","port","position","positive","possible","possibly","post","pot","potatoes","pound","pour","powder","power","powerful","practical","practice","prepare","present","president","press","pressure","pretty","prevent","previous","price","pride","primitive","principal","principle","printed","private","prize","probably","problem","process","produce","product","production","program","progress","promised","proper","properly","property","protection","proud","prove","provide","public","pull","pupil","pure","purple","purpose","push","put","putting","quarter","queen","question","quick","quickly","quiet","quietly","quite","rabbit","race","radio","railroad","rain","raise","ran","ranch","range","rapidly","rate","rather","raw","rays","reach","read","reader","ready","real","realize","rear","reason","recall","receive","recent","recently","recognize","record","red","refer","refused","region","regular","related","relationship","religious","remain","remarkable","remember","remove","repeat","replace","replied","report","represent","require","research","respect","rest","result","return","review","rhyme","rhythm","rice","rich","ride","riding","right","ring","rise","rising","river","road","roar","rock","rocket","rocky","rod","roll","roof","room","root","rope","rose","rough","round","route","row","rubbed","rubber","rule","ruler","run","running","rush","sad","saddle","safe","safety","said","sail","sale","salmon","salt","same","sand","sang","sat","satellites","satisfied","save","saved","saw","say","scale","scared","scene","school","science","scientific","scientist","score","screen","sea","search","season","seat","second","secret","section","see","seed","seeing","seems","seen","seldom","select","selection","sell","send","sense","sent","sentence","separate","series","serious","serve","service","sets","setting","settle","settlers","seven","several","shade","shadow","shake","shaking","shall","shallow","shape","share","sharp","she","sheep","sheet","shelf","shells","shelter","shine","shinning","ship","shirt","shoe","shoot","shop","shore","short","shorter","shot","should","shoulder","shout","show","shown","shut","sick","sides","sight","sign","signal","silence","silent","silk","silly","silver","similar","simple","simplest","simply","since","sing","single","sink","sister","sit","sitting","situation","six","size","skill","skin","sky","slabs","slave","sleep","slept","slide","slight","slightly","slip","slipped","slope","slow","slowly","small","smaller","smallest","smell","smile","smoke","smooth","snake","snow","so","soap","social","society","soft","softly","soil","solar","sold","soldier","solid","solution","solve","some","somebody","somehow","someone","something","sometime","somewhere","son","song","soon","sort","sound","source","south","southern","space","speak","special","species","specific","speech","speed","spell","spend","spent","spider","spin","spirit","spite","split","spoken","sport","spread","spring","square","stage","stairs","stand","standard","star","stared","start","state","statement","station","stay","steady","steam","steel","steep","stems","step","stepped","stick","stiff","still","stock","stomach","stone","stood","stop","stopped","store","storm","story","stove","straight","strange","stranger","straw","stream","street","strength","stretch","strike","string","strip","strong","stronger","struck","structure","struggle","stuck","student","studied","studying","subject","substance","success","successful","such","sudden","suddenly","sugar","suggest","suit","sum","summer","sun","sunlight","supper","supply","support","suppose","sure","surface","surprise","surrounded","swam","sweet","swept","swim","swimming","swing","swung","syllable","symbol","system","table","tail","take","taken","tales","talk","tall","tank","tape","task","taste","taught","tax","tea","teach","teacher","team","tears","teeth","telephone","television","tell","temperature","ten","tent","term","terrible","test","than","thank","that","thee","them","themselves","then","theory","there","therefore","these","they","thick","thin","thing","think","third","thirty","this","those","thou","though","thought","thousand","thread","three","threw","throat","through","throughout","throw","thrown","thumb","thus","thy","tide","tie","tight","tightly","till","time","tin","tiny","tip","tired","title","to","tobacco","today","together","told","tomorrow","tone","tongue","tonight","too","took","tool","top","topic","torn","total","touch","toward","tower","town","toy","trace","track","trade","traffic","trail","train","transportation","trap","travel","treated","tree","triangle","tribe","trick","tried","trip","troops","tropical","trouble","truck","trunk","truth","try","tube","tune","turn","twelve","twenty","twice","two","type","typical","uncle","under","underline","understanding","unhappy","union","unit","universe","unknown","unless","until","unusual","up","upon","upper","upward","us","use","useful","using","usual","usually","valley","valuable","value","vapor","variety","various","vast","vegetable","verb","vertical","very","vessels","victory","view","village","visit","visitor","voice","volume","vote","vowel","voyage","wagon","wait","walk","wall","want","war","warm","warn","was","wash","waste","watch","water","wave","way","we","weak","wealth","wear","weather","week","weigh","weight","welcome","well","went","were","west","western","wet","whale","what","whatever","wheat","wheel","when","whenever","where","wherever","whether","which","while","whispered","whistle","white","who","whole","whom","whose","why","wide","widely","wife","wild","will","willing","win","wind","window","wing","winter","wire","wise","wish","with","within","without","wolf","women","won","wonder","wonderful","wood","wooden","wool","word","wore","work","worker","world","worried","worry","worse","worth","would","wrapped","write","writer","writing","written","wrong","wrote","yard","year","yellow","yes","yesterday","yet","you","young","younger","your","yourself","youth","zero","zebra","zipper","zoo","zulu"];function JS(r){return new Array(r).fill(0).map(()=>Jd[Math.floor(Math.random()*Jd.length)]).join("-")}var LP=9e4,OP=15e3,yn=class extends Error{status;rawError;constructor(e,t,n,o={}){super(n,o),this.status=e,this.rawError=t}};async function MP(r){return r.text().then(e=>{try{return JSON.parse(e).error}catch{return e}})}var Xd=class{baseUrl;logger;constructor(e){this.baseUrl=e.baseUrl,this.logger=e.logger}getHeaders(){let e={"Content-Type":"application/json"};return Aa&&(e[Zh]=Aa),e}async sendRequest(e,t,n=3,o=LP){let i=n,a,s={path:e,baseUrl:this.baseUrl,method:t.method};for(;n>0;)try{return n--,await this.sendSingleRequestHelper(e,t,o)}catch(l){if(a=l,l instanceof yn&&l.status>=400&&l.status<500)throw l;if(l instanceof Error&&l.name==="AbortError"&&(a=new hr),n===0)throw a;let c=1500,d=i-n,p=Math.min(c*Math.pow(2,d-1),OP);await new Promise(u=>setTimeout(u,p))}throw this.logger.warn({...s,err:a},"Got fatal error response from Momentic server"),a}async sendSingleRequestHelper(e,t,n){let o={path:e,baseUrl:this.baseUrl,method:t.method},i=new AbortController,a=setTimeout(()=>i.abort(),n),s=()=>i.abort();t.signal&&t.signal.addEventListener("abort",s);let l={...this.getHeaders(),...t.extraHeaders};try{let c=await fetch(`${this.baseUrl}${e}`,{method:t.method,body:t.body?JSON.stringify(t.body):void 0,headers:l,signal:i.signal});if(!c.ok){let p=await MP(c);throw new yn(c.status,p,`Request to ${e} failed with status ${c.status}: ${p}`)}let d;if(c.status===204)d={};else{let p=await c.text();try{d=JSON.parse(p)}catch{d=p}}return this.logger&&!t.noLog&&d&&this.logger.debug({result:d,status:c.status,...o},"Got response from Momentic server"),d}finally{clearTimeout(a),t.signal&&t.signal.removeEventListener("abort",s)}}},Nt=class extends Xd{apiKey;constructor(e){super(e),this.apiKey=e.apiKey}getHeaders(){return{...super.getHeaders(),Authorization:`Bearer ${this.apiKey}`}}};var lt=class extends Nt{constructor(e){super(e)}getAppUrl(){return this.baseUrl.replace(/\/\/api/,"//app")}async getAuthInfo(){let e=await this.sendRequest(`/${j}/auth/check`,{method:"GET",noLog:!0},10,5e3),{orgId:t,userId:n}=yg.parse(e);return{orgId:t,userId:n}}async bulkGetRunStatus(e){let t=await this.sendRequest(`/${j}/runs/status`,{method:"POST",body:e,noLog:!0},3,1e4);return hg.parse(t)}async getTestYAMLExport(e){let t=await this.sendRequest(`/${j}/tests/export`,{method:"POST",body:e},3,3e4);return cg.parse(t)}async updateStepCaches(e,t){await this.sendRequest(`/${j}/cache`,{method:"PATCH",body:e,extraHeaders:t},3,1e4)}async getStepCacheForTest(e,t){let n=await this.sendRequest(`/${j}/cache`,{method:"POST",body:e,extraHeaders:t},10,3e4);return dg.parse(n)}async queueTests(e){let t=await this.sendRequest(`/${j}/tests/queue`,{method:"POST",body:e},3,1e4);return lg.parse(t)}async uploadScreenshot(e){let t=await this.sendRequest(`/${j}/screenshots`,{method:"POST",body:e,noLog:!0},3,5e3);return Sg.parse(t)}async getAllEnvironments(){let e=await this.sendRequest(`/${j}/environments`,{method:"GET"},3,5e3);return bg.parse(e)}async acquireCacheLock(e,t){let n=await this.sendRequest(`/${j}/result-cache/lock`,{method:"POST",body:e,signal:t},3,3e4);return Rg.parse(n)}async releaseCacheLock(e){await this.sendRequest(`/${j}/result-cache/lock`,{method:"DELETE",body:{key:e}},3,5e3)}async deleteCacheResult(e){await this.sendRequest(`/${j}/result-cache/entry`,{method:"DELETE",body:e},3,5e3)}async setCacheResult(e){await this.sendRequest(`/${j}/result-cache/entry`,{method:"PATCH",body:e},3,5e3)}async getCacheResult(e){try{return await this.sendRequest(`/${j}/result-cache/entry`,{method:"POST",body:e},3,5e3)}catch(t){if(t instanceof Error&&t.message.includes("404"))return null;throw t}}async queueSuiteRuns(e){let t=await this.sendRequest(`/${j}/suites/queue`,{method:"POST",body:e},3,5e3);return wg.parse(t)}async bulkGetRunGroupStatus(e){let t={runGroupIds:e},n=await this.sendRequest(`/${j}/run-groups/status`,{method:"POST",body:t,noLog:!0},3,5e3);return Zm.array().parse(n)}async updateCacheLastUsedDate(e,t,n,o){try{await this.sendRequest(`/${j}/cache/last-used-at`,{method:"PATCH",body:{uniqueKeys:t,testId:e},noLog:!0,extraHeaders:o},3,7500)}catch(i){n.error({err:i},"Failed to update cache last used date")}}async uploadProposedSteps(e,t){try{await this.sendRequest(`/${j}/test-fragments/`,{method:"POST",body:e},3,1e4)}catch(n){t.error({err:n},"Failed to upload proposed steps")}}async uploadSnapshotScreenshot(e,t,n){try{await this.sendRequest(`/${j}/snapshots/${t}/screenshot`,{method:"POST",body:n,noLog:!0},3,1e4)}catch(o){e.error({err:o},"Failed to upload screenshot")}}async generateConsoleLogsForRunAttemptUploadUrl(e,t,n){let o=await this.sendRequest(`/${j}/runs/${t}/attempts/${n}/console-logs`,{method:"POST",noLog:!0},3,5e3);return na.parse(o)}async generateNetworkLogsForRunAttemptUploadUrl(e,t,n){let o=await this.sendRequest(`/${j}/runs/${t}/attempts/${n}/network-logs`,{method:"POST",noLog:!0},3,1e4);return na.parse(o)}async generateHtmlSnapshotUploadUrl(e,t){let n=await this.sendRequest(`/${j}/snapshots/${t}/html`,{method:"POST",noLog:!0},3,1e4);return na.parse(n)}async reportBillableEvents(e,t){try{await this.sendRequest(`/${j}/billing/events`,{method:"POST",body:t,noLog:!0},10,1e4)}catch(n){e.error({err:n},"Failed to report billable event")}}async fetchTestFragment(e){let t=await this.sendRequest(`/${j}/test-fragments/${e}`,{method:"GET",noLog:!0},3,1e4);return vg.parse(t)}async patchTestFragment(e,t){await this.sendRequest(`/${j}/test-fragments/${e}`,{method:"PATCH",body:t},3,1e4)}async getPastTestResults(e,t){let n=await this.sendRequest(`/${j}/results/tests/${e}`,{method:"POST",body:t},3,1e4);return xg.parse(n)}async generateTestResultsUploadUrl(){let e=await this.sendRequest(`/${j}/results/uploads`,{method:"POST",noLog:!0},3,1e4);return Tg.parse(e)}async startProcessingResultsUpload(e,t){let n=await this.sendRequest(`/${j}/results/uploads/${e}/process`,{method:"POST",noLog:!0,body:t},3,1e4);return Eg.parse(n)}async fetchIconKnowledgeBase(e,t){try{let n=await this.sendRequest(`/${j}/knowledge-base/icons`,{method:"GET",noLog:!0},3,5e3);return Mg.parse(n)}catch(n){return t.error({err:n},"Failed to fetch icon knowledge base"),null}}async saveNewIcons(e,t){try{await this.sendRequest(`/${j}/knowledge-base/icons`,{method:"POST",body:e,noLog:!0},3,5e3)}catch(n){t.error({err:n},"Failed to save new icons to icon knowledge base")}}async getMergeBaseCommitFromGithub(e,t,n,o){let i=new URLSearchParams;i.set("base",n),i.set("head",o);let a=await this.sendRequest(`/${j}/git/github/${e}/${t}/merge-base-commit?${i.toString()}`,{method:"GET",noLog:!0},3,1e4);return dd.parse(a)}async getMergeBaseCommitFromGitlab(e,t,n){let o=new URLSearchParams;o.set("base",t),o.set("head",n);let i=await this.sendRequest(`/${j}/git/gitlab/${e}/merge-base-commit?${o.toString()}`,{method:"GET",noLog:!0},3,5e3);return dd.parse(i)}async getAgentConfig(){let e=await this.sendRequest(`/${j}/web-agent/agent-config`,{method:"GET",noLog:!0},3,5e3);return Zd.record(Zd.string(),Zd.string()).parse(e)}};import{randomUUID as XS}from"crypto";var dl=class{apiClient;constructor(e){this.apiClient=e}async reportBillableEvent(e,t,n){try{return await this.apiClient.reportBillableEvents(e,[{event:t,timestamp:new Date().toISOString(),transactionId:n?.eventId??XS(),properties:Zc({},n)}])}catch(o){e.error({err:o},"Failed to report billable event")}}async reportCreditsUsed(e,t,n,o){if(n)try{return await this.apiClient.reportBillableEvents(e,[{event:"credits-used",timestamp:new Date().toISOString(),transactionId:o?.eventId??XS(),properties:Zc({creditsUsed:n,usedBy:t},o)}])}catch(i){e.error({err:i},"Failed to report credits used")}}};function oi(r,e,t){return fetch(r,{method:"PUT",body:t,headers:{"Content-Type":e}})}var pl=class{constructor(e){this.client=e}async storeConsoleLogsForRunAttempt(e,t,n,o){try{let i=JSON.stringify(o),{uploadUrl:a}=await this.client.generateConsoleLogsForRunAttemptUploadUrl(e,t,n),s=await oi(a,"application/json",i);if(!s.ok)throw new Error(`Failed to upload network logs: ${s.statusText}`)}catch(i){e.error({err:i},"Failed to upload console logs")}}async storeNetworkLogsForRunAttempt(e,t,n,o){let i=JSON.stringify(o);try{let{uploadUrl:a}=await this.client.generateNetworkLogsForRunAttemptUploadUrl(e,t,n),s=await oi(a,"application/json",i);if(!s.ok)throw new Error(`Failed to upload network logs: ${s.statusText}`)}catch(a){e.error({err:a},"Failed to upload network logs")}}async storeHtmlSnapshot(e,t,n){try{let{uploadUrl:o}=await this.client.generateHtmlSnapshotUploadUrl(e,t),i=await oi(o,"text/html",n);if(!i.ok)throw new Error(`Failed to upload network logs: ${i.statusText}`)}catch(o){e.error({err:o},"Failed to upload html snapshot")}}async storeScreenshot(e,t,n){try{await this.client.uploadSnapshotScreenshot(e,t,{screenshot:n.toString("base64")})}catch(o){e.error({err:o},"Failed to upload screenshot")}}async storeA11yTreeSnapshot(e,t,n){return Promise.resolve()}async getConsoleLogsForRunAttempt(e,t,n){}async getNetworkLogsForRunAttempt(e,t,n){}async getHtmlSnapshot(e,t){}async getA11yTreeSnapshot(e,t){}async getScreenshot(e,t){}};var ii=class{constructor(e,t){this.client=e;this.orgId=t}async acquireCacheLock(e,t){return this.client.acquireCacheLock(e,t)}async uploadScreenshot(e){return(await this.client.uploadScreenshot({screenshot:e.toString("base64")})).key}async releaseCacheLock(e){return this.client.releaseCacheLock(e)}async deleteCacheResult(e){return this.client.deleteCacheResult(e)}async setCacheResult(e){return this.client.setCacheResult(e)}async getCacheResult(e){return this.client.getCacheResult(e)}fetchIconKnowledgeBase(e,t){return this.client.fetchIconKnowledgeBase(e,t)}saveNewIcons(e,t,n){return this.client.saveNewIcons(t,n)}};import{Faker as NP,en as kP}from"@faker-js/faker";var ai="v1",gr=class{httpClient;fakerInstance;type="API_CLIENT";sms={send:this.sendSms.bind(this),fetchLatest:this.fetchLatestSms.bind(this)};email={send:this.sendEmail.bind(this),fetchLatest:this.fetchLatestEmail.bind(this),fetchAll:this.fetchAllEmails.bind(this)};ai={generate:this.sendAiGenerate.bind(this)};constructor(e){this.httpClient=e.httpClient,e.fakerSeed&&(this.fakerInstance=new NP({locale:kP}),this.fakerInstance.seed(e.fakerSeed))}async sendAiGenerate(e){let t=typeof e=="string"?{input:e}:e;return this.httpClient.sendRequest(`/${ai}/tools/ai/generate`,{method:"POST",body:t}).catch(n=>{throw n instanceof yn?new Error(n.rawError):new Error(`Failed to send AI generation: ${n.message}`)})}async sendSms(e){return this.httpClient.sendRequest(`/${ai}/tools/sms/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to send sms: ${t.message}`)})}async fetchLatestSms(e){return this.httpClient.sendRequest(`/${ai}/tools/sms/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):t})}async sendEmail(e){return this.httpClient.sendRequest(`/${ai}/tools/email/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to send email: ${t.message}`)})}async fetchAllEmails(e){return this.httpClient.sendRequest(`/${ai}/tools/email/fetchAll`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to fetch all emails: ${t.message}`)})}async fetchLatestEmail(e){return this.httpClient.sendRequest(`/${ai}/tools/email/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof yn?new Error(t.rawError):new Error(`Failed to fetch latest emails: ${t.message}`)})}};import{z as _P}from"zod";var si=class extends Nt{agentConfig;constructor(e,t){super(t),this.agentConfig=e}async rankChunksWithAi(e,t){let n={...e,loggerTags:t.loggerTags},o=await this.sendRequest(`/${j}/web-agent/recommend-chunks-ai`,{method:"POST",body:n,signal:t.abortSignal});return mh.parse(o)}async rankChunksWithRag(e,t){let n=await this.sendRequest(`/${j}/web-agent/recommend-chunks`,{method:"POST",body:{cliVersion:Aa,...e},signal:t.abortSignal});return uh.parse(n)}async getScreenshotFromS3(e){let t=await this.sendRequest(`/${j}/s3/visual-diff-screenshot`,{method:"POST",body:{url:e}});return _P.string().parse(t)}async getElementLocation(e,t){let n={...e,disableCache:t.disableCache,loggerTags:t.loggerTags,agentConfigVersion:this.agentConfig?.locator},o=await this.sendRequest(`/${j}/web-agent/locate-element`,{method:"POST",body:n,signal:t.abortSignal});return ag.parse(o)}async getAssertionResult(e,t){let n={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,attemptNumber:t.attemptNumber,loggerTags:t.loggerTags,agentConfigVersion:this.agentConfig?.locator},o=await this.sendRequest(`/${j}/web-agent/assertion`,{method:"POST",body:n,signal:t.abortSignal});return ld.parse(o)}async getLintStepResult(e,t){let n={...e,disableCache:!!t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${j}/web-agent/lint/step`,{method:"POST",body:n,signal:t.abortSignal});return ig.parse(o)}async getVisualAssertionResult(e,t){let n={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,loggerTags:t.loggerTags},o=await this.sendRequest(`/${j}/web-agent/visual-assertion`,{method:"POST",body:n,signal:t.abortSignal});return ld.parse(o)}async getAiActionCommand(e,t){let n=await this.sendRequest(`/${j}/web-agent/next-command-dynamic`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return og.parse(n)}async getMultiturnAiActionCommand(e,t){return await this.sendRequest(`/${j}/web-agent/ai-action/next-command`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal})}async getMultiturnAiActionEvaluation(e,t){let n=await this.sendRequest(`/${j}/web-agent/ai-action/evaluate`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return Rc.parse(n)}async getReverseMappedDescription(e,t){let n=await this.sendRequest(`/${j}/web-agent/reverse-mapped-description`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return sg.parse(n)}async getTextExtraction(e,t){let n={...e,disableCache:t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${j}/web-agent/text-extraction`,{method:"POST",body:n,signal:t.abortSignal});return Cc.parse(o)}async getTestResultClassification(e,t){let n=await this.sendRequest(`/${j}/web-agent/result-classification`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Uc.parse(n)}async getExtractedKeywords(e,t){let n=await this.sendRequest(`/${j}/web-agent/extract-keywords`,{method:"POST",body:{goal:e,disableCache:t.disableCache,context:e},signal:t.abortSignal});return ph.parse(n)}async getAutohealingProposal(e,t){let n=await this.sendRequest(`/${j}/web-agent/autoheal-section`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return em.parse(n)}async getFailureRecoveryProposal(e,t){let n=await this.sendRequest(`/${j}/web-agent/failure-recovery`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return tm.parse(n)}async getIframeRegex(e,t){let n=await this.sendRequest(`/${j}/web-agent/iframe-regex`,{method:"POST",body:e,signal:t.abortSignal});return _u.parse(n)}};var li=class extends Nt{generator;constructor(e,t){super(e),this.generator=t}async runTemplateMatching(e,t={}){let n=await this.sendRequest(`/${j}/web-agent/template-matching`,{method:"POST",body:e,signal:t?.signal});return Du.parse(n)}async constructIframeRegex(e,t={}){return this.generator.getIframeRegex(e,{abortSignal:t.signal})}};var ul=class{constructor(e){this.client=e}async uploadResultsArchive(e,t){let{uploadUrl:n,id:o}=await this.client.generateTestResultsUploadUrl(),i=await oi(n,"application/zip",t);if(!i.ok)throw new Error(`Failed to upload test results: ${await i.text()}`);let{runGroupId:a}=await this.client.startProcessingResultsUpload(o,{runGroupId:e});return a}};function ci({client:r,gitMetadata:e,alwaysSaveCache:t,noCache:n}){return n?new Ls:new Qd(r,e,t)}var Qd=class{constructor(e,{gitMainBranch:t,gitBranchName:n,gitProtectedBranches:o,gitCommitTimestamp:i,lastCommitOnMainSha:a,lastCommitOnMainTimestamp:s},l){this.client=e;this.cacheHeaders={},t&&(this.cacheHeaders[Qh]=t),n&&(this.cacheHeaders[eg]=n),i&&(this.cacheHeaders[tg]=i.toISOString()),a&&(this.cacheHeaders[ng]=a),s&&(this.cacheHeaders[rg]=s.toISOString()),l?this.writeCaches=!0:n?this.writeCaches=!o.includes(n):this.writeCaches=!0}cacheHeaders;writeCaches;async saveStepCacheEntries(e,t,n){if(!this.writeCaches){n.debug("Skipping cache storage because branch is protected");return}try{await this.client.updateStepCaches({entries:e,testId:t},this.cacheHeaders)}catch(o){n.error({err:o},"Failed to save step cache entries")}}async resolveStepCacheEntries(e){let t=await this.client.getStepCacheForTest({testId:e.testId,organizationId:e.organizationId,steps:e.steps,schemaVersion:e.schemaVersion},this.cacheHeaders);if(!this.writeCaches){e.logger.debug("Skipping cache last used at update because branch is protected");return}let{uniqueKeysHit:n}=Fo({steps:e.steps,stepCacheEntries:t,logger:e.logger});this.client.updateCacheLastUsedDate(e.testId,n,e.logger,this.cacheHeaders)}};import{Server as pN}from"socket.io";import{cloneDeep as DP}from"lodash-es";var FP={showOverlay:!1},ep=class{sessions=new Map;sessionCountByIp=new Map;getCurrentConnectionsByIp(e){return this.sessionCountByIp.get(e)??0}getCurrentSessionsByIp(){return Object.fromEntries(this.sessionCountByIp)}reserveCapacityByIp(e){e&&this.sessionCountByIp.set(e,(this.sessionCountByIp.get(e)??0)+1)}releaseCapacityByIp(e){e&&this.sessionCountByIp.set(e,Math.max(this.getCurrentConnectionsByIp(e)-1,0))}registerSession({controller:e,context:t,cleanup:n,clientIp:o,sessionId:i,browserbaseSessionId:a}){return this.sessions.set(i,{controller:e,context:t,cleanup:n,clientIp:o,browserbaseSessionId:a,browserBehavior:DP(FP)}),i}removeSession(e,t){(async()=>{let o=this.sessions.get(e);if(!o)return;this.releaseCapacityByIp(o.clientIp);let{controller:i}=o;try{i.setClosed(),await i.browser.cleanup()}catch(a){t.error({err:a},"Error cleaning up browser in global state manager")}try{await o.cleanup?.()}catch(a){t.error({err:a},"Error running cleanup function in global state manager")}this.sessions.delete(e)})()}getSession(e){return this.sessions.get(e)}},Q=new ep;function ZS(r,e,t){let n=Date.now(),o=Date.now(),i,a,s,l,c=!1,d=async(h,g)=>{if(!h.closed&&!h.isInPageLoad)try{let f=s;s=void 0;let S=h.url(),v=g.toEditorDisplayCopy();JSON.stringify(v)===JSON.stringify(i)&&S===l&&n>o||(r.emit("browserState",{logsPerPage:f?.logsPerPage,harPages:f?.harPages,harEntries:f?.harEntries,viewport:h.getViewport(),url:S,iframeSrcUrls:a??[],context:v,isInPageLoad:h.isInPageLoad}),n=Date.now()),l=S,i=v}catch(f){if(!r.connected)return;let S=f instanceof Error?f.message:`${f}`;if(S.includes("Frame was detached")||S.includes("Not attached to an active page")||S.includes("browser has been closed")||S.includes("UserInfrastructureError"))return;t.error({err:f,sessionId:e},"Error grabbing browser state")}},p=setInterval(()=>{let h=Q.getSession(e),g=h?.controller?.browser;if(!g||g.closed){t.debug("Clearing browser state socket cron due to the browser being closed"),clearInterval(p);return}d(g,h.context)},1e3),u=(h,g)=>!!(JSON.stringify(h)!==JSON.stringify(a)||g.logsPerPage.some(f=>f.length>0)||g.harPages&&Object.keys(g.harPages).length>0||g.harEntries&&Object.keys(g.harEntries).length>0),m=setInterval(async()=>{let g=Q.getSession(e)?.controller?.browser;if(!g||g.closed){clearInterval(m);return}else if(c)return;c=!0;try{let f=await g.getAllFrameUrls(),S=g.retrieveAndClearDebugData();u(f,S)&&(a=f,s=S,o=Date.now())}catch(f){t.warn({err:f},"Failed to fetch extended details")}finally{c=!1}},2500);return{timers:[p,m]}}var fr={};var UP=r=>()=>{let{sessionId:e}=r.metadata;fr[e]?.abort?.abort()},QS={event:"cancelApiTest",createHandler:UP};import{CookieJar as rL}from"tough-cookie";import{randomUUID as VP}from"crypto";import{faker as BP}from"@faker-js/faker";import zP from"assert";import HP from"axios";import jP from"moment";import*as $P from"otpauth";import GP from"pg";async function ey(r){let e;try{e=new URL(r.url).hostname}catch{}let t=[];return r.headers.getSetCookie()?.forEach(n=>{let o=xs(n,e);t.push(...o)}),t}var WP=Object.getPrototypeOf(async function(){}).constructor;async function ty(r,e,t){let n=e.code;e.options.fragment&&(n=`return ${e.code}`);let{env:o}=e.bindings,i=e.tools,a={},s=(f,S)=>{o[f]=S,a[f]=S},l={},c=(f,S)=>{o[f]=S,l[f]=S},d;n.includes("Octokit")&&(d=(await import("@octokit/rest")).Octokit);let p;n.includes("createAppAuth")&&(p=(await import("@octokit/auth-app")).createAppAuth);let u=async()=>await Promise.resolve(new WP("axios","moment","faker","assert","pg","Octokit","createAppAuth","OTPAuth","extractCookiesFromResponse","env","setVariable","setPersistentVariable","sendSms","waitForLatestSms","email","sms","ai",n)(HP,jP,i.fakerInstance??BP,zP,GP,d,p,$P,ey,o,s,c,S=>i.sms.send(S),S=>i.sms.fetchLatest(S),i.email,i.sms,i.ai)),m=!0,h,g;try{h=await D(u(),{milliseconds:e.options.timeoutMs,message:`Timeout of ${e.options.timeoutMs}ms exceeded for code execution`,signal:e.signal})}catch(f){t.error({err:f,env:o,evalCode:n},`[${r}] Error executing code: ${f}`),m=!1,f instanceof hr?g=`Timeout of ${e.options.timeoutMs}ms exceeded for code execution`:g=f instanceof Error?f.message:`${f}`}return{result:h,variableUpdates:a,persistentVariableUpdates:l,success:m,error:g}}async function ny({code:r,fragment:e,context:t,localTools:n,logger:o,signal:i,timeoutMs:a=ar}){let s=VP(),l=await ty(s,{code:r,options:{fragment:e,timeoutMs:a},bindings:t.toObjectCopy(),tools:n,signal:i},o);return y.debug(`[${s}] Got execution result: ${JSON.stringify(l)}`),l}import{createHmac as qP,randomUUID as KP}from"crypto";import YP from"fetch-retry";var JP=YP(global.fetch,{retries:3,retryOn:function(r,e,t){return!!(e!==null||t&&t.status>=500)},retryDelay:function(r){return Math.pow(2,r)*500}}),ry=process.env.GCP_JS_EVAL_FUNCTION_ENDPOINT,oy=process.env.MOMENTIC_LAMBDA_AUTH_SECRET;async function iy({orgId:r,code:e,fragment:t,context:n,timeoutMs:o=ar,retries:i=2,signal:a,logger:s}){if(!ry)throw new Error("GCP_JS_EVAL_FUNCTION_ENDPOINT environment variable not set");let l,c,d=0;if(!oy)throw new Error("Missing lambda auth secret.");let p=qP("sha256",oy).update(r).digest("hex");for(;d<=i;){d++,a?.throwIfAborted();let m={id:KP(),orgId:r,momenticLambdaAuthHash:p,code:e,fragment:t,state:n.toObjectCopy(),timeoutMs:o};try{if(l=await D(JP(ry,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(m)}),{milliseconds:o,message:`Timeout of ${o}ms exceeded for code execution`,signal:a}),!l)throw new Error("Got empty response from code evaluation server");if(!l.ok)throw new Error(`Code evaluation server returned error code ${l.status}`);c=void 0;break}catch(h){c=h}}if(c)throw s.error({err:c},"Failed to evaluate code remotely"),c;if(!l)throw new Error(`An unexpected code evaluation error occurred${c?`: ${c}`:""}`);let u;try{u=vh.parse(await l.json())}catch(m){throw new Error(`Code evaluation server returned invalid response: ${m}`)}if(u.error)throw new Error(`Code evaluation error: ${u.error}`);return u}async function Kn(r){let e;if(process.env.GCP_JS_EVAL_FUNCTION_ENDPOINT)e=await iy(r);else if(r.localTools)e=await ny({...r,localTools:r.localTools});else throw new Error("No code evaluation environment available");if(e.error){let t=`Failed to evaluate code:
50
50
  ${e.error}
51
51
  Code received:
52
52
  ${r.code}`;throw r.logger.error({err:e.error,code:r.code,env:r.context.toObjectCopy()},t),new Error(t)}if(e.variableUpdates)for(let[t,n]of Object.entries(e.variableUpdates))r.context.setVariable(t,n);if(e.persistentVariableUpdates&&Object.keys(e.persistentVariableUpdates).length>0){await r.callbacks?.onPersistentVariableUpdates?.(e.persistentVariableUpdates);for(let[t,n]of Object.entries(e.persistentVariableUpdates))r.context.setVariable(t,n)}return e.result}import{set as XP}from"lodash-es";async function Ht(r){let{orgId:e,s:t,context:n,logger:o,signal:i,flagStore:a,retries:s=2,timeoutMs:l=ar,allowUndefined:c=!1}=r,d=/{{(.*?)}}/g,p=t.matchAll(d),u=t;for(let m of p){if(m.length<2)continue;let h=m[1].trim(),g;try{g=await Kn({orgId:e,code:h,fragment:!0,context:n,timeoutMs:l,logger:o,retries:s,localTools:r.localTools,signal:i,flagStore:a})}catch(S){throw o.error({err:S,value:t},"Error evaluating template string"),S}if(g===void 0&&!c)throw new R("UserConfigurationError",`Template fragment '${h}' evaluated to undefined. Please ensure that the variable name is spelled correctly and it is only referenced after being assigned a value.`);let f=typeof g=="string"?g:`${g}`;f=f.replaceAll(/\$/g,"$$$$"),u=u.replace(m[0],f)}return u}async function di(r){return ay(r)}async function ay({obj:r,bannedKeys:e,allowList:t,context:n,prefixPath:o=[],replacements:i=[],...a}){for(let s in r){if(e.includes(s))continue;let l=!1;if(t)if(t.includes(s))l=!0;else continue;let c=r[s],d=[...o,s];if(typeof c=="string"&&c.includes("{{")){let p=await Ht({s:c,context:n,...a});if(c===p)continue;i.push({path:d,original:c}),r[s]=p}else typeof c=="object"&&c!==null&&!Array.isArray(c)&&await ay({obj:c,bannedKeys:e,context:n,prefixPath:d,replacements:i,allowList:l?void 0:t,...a})}return i}function sy(r,e){for(let{path:t,original:n}of e)XP(r,t,n)}import ZP from"fetch-retry";var BX=process.env.MAILINATOR_API_KEY,zX=ZP(global.fetch,{retryOn:function(r,e,t){return r>3?!1:!!(e!==null||t&&t.status>=400)},retryDelay:function(r){return 500}});import eL from"fetch-cookie";import{cloneDeep as tL}from"lodash-es";var QP=3e4;async function ml({command:r,logger:e,baseUrl:t,fetchImplementation:n=fetch}){let o=r.timeout??QP/1e3,i=Object.fromEntries(Object.entries(r.headers||{}).filter(([m,h])=>m&&h)),a=new URLSearchParams;Object.entries(r.params||{}).filter(([m,h])=>m&&h).forEach(([m,h])=>{a.append(m,h)});let s=a.toString(),l;if(Uo(r.url)&&(l=r.url),t&&Bo(r.url,t)&&(l=new URL(r.url,t).toString()),!l)throw new R("ActionFailureError",`Invalid URL: ${r.url}`);e.debug({url:l,searchParams:s,headers:i,body:r.body,method:r.method},"Making HTTP request");let d=await D((async()=>{let m=s?`${l}?${s}`:l;try{return await n(m,{headers:i,method:r.method,body:r.body})}catch(h){throw e.error({err:h},"Failed to make HTTP request"),new Error(`Failed to make HTTP request: ${h}`)}})(),{milliseconds:o*1e3,fallback:()=>{throw new R("ActionFailureError",`Fetch request timed out after ${o} seconds`)}});if(!d.ok){let m;try{m=await d.text()}catch(h){m=`Failed to read response body: ${h}`}throw new R("ActionFailureError",`Fetch request failed with status ${d.status}: ${m}`)}let p={};d.headers.forEach((m,h)=>{p[h]=m});let u={status:d.status,headers:p};if(d.headers.get("content-type")?.includes("json"))try{u.json=await d.json()}catch{}else d.headers.get("content-type")?.includes("text")&&(u.text=await d.text());return u}async function ly(r){let{fixtures:e,inputs:t}=r,{context:n}=e,{orgId:o,step:i}=t,a=tL(i);await di({obj:a,orgId:o,bannedKeys:["code"],...e});let s=await nL(r);return a.envKey&&s.data&&n.setVariable(a.envKey,s.data),s}async function nL(r){let{fixtures:e,inputs:t}=r,{step:n,orgId:o,baseUrl:i}=t,{cookieJar:a}=e,s=new Date;switch(n.type){case"JAVASCRIPT":{let c=await Kn({code:n.code,orgId:o,fragment:!!n.fragment,timeoutMs:n.timeout?n.timeout*1e3:void 0,...e});try{JSON.stringify(c)}catch(d){return{...n,startedAt:s,finishedAt:new Date,status:"FAILED",message:`JavaScript return value is not serializable: ${d instanceof Error?d.message:`${d}`}`}}return{...n,startedAt:s,finishedAt:new Date,message:"JavaScript code executed successfully",status:"SUCCESS",data:c}}case"REQUEST":{let c=eL(fetch,a),d=await ml({command:n,logger:e.logger,baseUrl:i,fetchImplementation:c});return{...n,startedAt:s,finishedAt:new Date,status:"SUCCESS",message:"Request executed successfully",data:d}}default:return(c=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(n)}}async function cy(r){let{inputs:e,fixtures:t,callbacks:n}=r,{signal:o}=t,{steps:i,orgId:a,baseUrl:s}=e,{test:l,step:c}=n,d={startedAt:new Date,status:"RUNNING",results:[]},p=d.results,u=new rL,m={cookieJar:u,...t};for(let h of i){let g=new Date;c.onStarted?.(h.id);let f;try{o?.throwIfAborted(),f=await ly({inputs:{step:h,baseUrl:s,orgId:a},fixtures:m})}catch(S){o?.aborted?f={...h,startedAt:g,finishedAt:new Date,status:"CANCELLED",message:"Step cancelled by user."}:f={...h,startedAt:g,finishedAt:new Date,status:"FAILED",message:`Step failed: ${S instanceof Error?S.message:`${S}`}`}}if(p.push(f),c.onFinished?.({result:f,cookies:Es(u,new URL(s).hostname)}),l.updateAttemptProgress?.({results:p}),f.status!=="SUCCESS"){d.status=f.status==="CANCELLED"?"CANCELLED":"FAILED";break}}return d.status==="RUNNING"&&(d.status="PASSED"),d.finishedAt=new Date,l.onFinished?.(),d}async function dy(r){let{socket:e,storage:t}=r,n=r.socket.id,{testId:o}=e.handshake.query;if(typeof o!="string")throw new Error(`Received invalid test ID that does not parse as a string: ${o}`);let i=await t.getOrgId({type:"api-test",testId:o}),{baseUrl:a,envName:s,environmentVariables:l}=await tp({testId:o,orgId:i,logger:r.logger,storage:t,authorization:r.authorization}),c={type:"api-test",orgId:await r.storage.getOrgId({type:"api-test",testId:o}),testId:o,sessionId:n,latestContext:new It({baseUrl:a||"",currentUrl:a||"",variablesFromEnvironment:l,envName:s})};return fr[n]=c,c}async function tp({testId:r,orgId:e,logger:t,storage:n,authorization:o}){let i=await n.fetchApiTestMetadata(r,e,t);if(!i)throw new Error(`Failed to fetch API test metadata for test ID: ${r}`);let a;o?.type==="API_KEY"&&(a=new gr({httpClient:new Nt({...o,logger:t}),fakerSeed:void 0}));let s=i.envs?.find(p=>p.default),l;s&&(l=await n.fetchEnvironment(e,s.name,t));let c=i.baseUrl||l?.variables?.[Ge];if(!c)throw new Error("Base URL is empty in both API test options and the configured environment");let d={...l?.variables};return{baseUrl:c,envName:l?.name,environmentVariables:d,localCodeEvalTools:a}}var oL=r=>async(e,t)=>{let{steps:n}=e,{authorization:o,metadata:i,socket:a,storage:s,logger:l,flagStoreFactory:c}=r,{orgId:d,testId:p,sessionId:u}=i,m=l.child({testId:p,orgId:d,sessionId:u}),h=fr[u];if(!h)throw new Error(`No api testing session with id ${u} could be found. Please reconnect and try again.`);let g=new AbortController;h.abort=g;let f=h.latestContext,{localCodeEvalTools:S,baseUrl:v}=await tp({testId:p,orgId:d,logger:m,storage:s,authorization:o}),x={context:f,logger:m,localTools:S,signal:g.signal,flagStore:await c(d)},C=await cy({inputs:{steps:n,orgId:d,baseUrl:v},fixtures:x,callbacks:{test:{onFinished:()=>{a.emit("apiTestFinished")}},step:{onStarted:A=>{a.emit("apiStepStarted",A)},onFinished:A=>{a.emit("apiStepFinished",A)}}}});t({result:C})},py={event:"executeApiTest",createHandler:oL};var iL=({metadata:r,logger:e})=>{let{sessionId:t}=r;return async()=>{e.info({sessionId:t},"Cancel event received");let n=Q.getSession(t);if(!n)throw new Error("No active session found");try{n.controller.setClosed()}catch{}}},uy={event:"cancel",createHandler:iL};var aL=({metadata:r,logger:e})=>{let{sessionId:t}=r;return async(n,o)=>{let i=Q.getSession(t);if(!i)throw new Error("No active session found");i.controller.setOpen();let a=i.controller.browser;try{let l=(await a.getBrowserState({skipWait:!0})).serialize();e.debug({a11yTree:l},"Fetched a11y tree from the browser"),o({a11yTree:l})}catch(s){e.error({err:s},"Error fetching a11y tree from the browser"),o({err:s.message})}}},my={event:"fetchA11yTree",createHandler:aL};var sL=({metadata:r,logger:e})=>{let{sessionId:t}=r;return async(n,o)=>{let i=Q.getSession(t);if(!i)throw new Error("No active session found");i.controller.setOpen();let a=i.controller.browser;try{let s=await a.html();o({html:s})}catch(s){e.error({err:s},"Error fetching DOM from the browser"),s.name==="TimeoutError"?o({err:"Timed out fetching DOM tree. This page may be too large for Momentic to process."}):o({err:s.message})}}},hy={event:"fetchDom",createHandler:sL};var lL=({metadata:r,logger:e})=>{let{sessionId:t,type:n}=r;return o=>{e.info({sessionId:t,reason:o},`Disconnect event received (${o})`),n==="e2e"?Q.removeSession(t,e):n==="api-test"&&delete fr[t]}},gy={event:"disconnect",createHandler:lL};function rn(r){let{result:e,nestedResults:t}=r;if(!r.nestedResults.length)return;let{firstMetadata:n,lastMetadata:o}=cL(t);dL(e,n,o);let i=[...r.asyncTasks];r.asyncTasks.push((async()=>{try{await pL(i,e,n,o)}catch(a){r.logger.error({result:r.result,err:a},"Error hoisting scalar result metadata")}})())}function cL(r){let e=r[0],t;for(;;){switch(e.type){case"PRESET_ACTION":{t=e;break}case"CONDITIONAL":if(e.assertion){t=e;break}break;case"AI_ACTION_DYNAMIC":case"AI_ACTION":case"MODULE":case"SECTION":case"IFRAME":if(!e.results.length){t=e;break}e=e.results[e.results.length-1];break;default:return(a=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(e)}if(t)break}let n=r[r.length-1],o;for(;;){switch(n.type){case"PRESET_ACTION":{o=n;break}case"AI_ACTION_DYNAMIC":case"CONDITIONAL":case"AI_ACTION":case"MODULE":case"SECTION":case"IFRAME":if(!n.results.length){o=n;break}n=n.results[n.results.length-1];break;default:return(a=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(n)}if(o)break}return{firstMetadata:t,lastMetadata:o}}function dL(r,e,t){e&&(r.beforeUrl=e.beforeUrl),t&&(r.afterUrl=t.afterUrl,r.data=t.data,t.status!=="SUCCESS"&&(r.message=t.message))}async function pL(r,e,t,n){await Promise.allSettled(r),t&&(e.beforeSnapshot=t.beforeSnapshot),n&&(e.afterSnapshot=n.afterSnapshot)}import Ia from"os";import uL from"v8";var fy,Ln,mL=Ia.platform(),hL=Ia.cpus().map(r=>({model:r.model,speed:r.speed}));function Sy(r){let e=()=>{try{let t=!1,n=gL(),o=fL();n.freeMemory<1e6&&(t=!0);let i=uL.getHeapStatistics(),a=i.used_heap_size,s=i.heap_size_limit;a/s>.9&&(t=!0),t?r.warn({memory:n,cpu:o,heapStats:i},"Critical resource usage metrics detected"):r.debug({memory:n,cpu:o},"Got machine resource usage metrics")}catch{}};return e(),{interval:setInterval(e,1e4),cpuMetadata:hL,platform:mL}}function gL(){let r=Ia.totalmem(),e=Ia.freemem(),t=r-e;return{totalMemory:r,freeMemory:e,usedMemory:t}}function fL(){let r=Ia.cpus(),e=Date.now(),t={measurementTime:e,user:0,nice:0,sys:0,idle:0,irq:0,total:0};for(let o of r)t.user+=o.times.user,t.nice+=o.times.nice,t.sys+=o.times.sys,t.idle+=o.times.idle,t.irq+=o.times.irq;if(t.total=t.user+t.nice+t.sys+t.idle+t.irq,!Ln)return Ln=t,null;let n={user:t.user-Ln.user,nice:t.nice-Ln.nice,sys:t.sys-Ln.sys,idle:t.idle-Ln.idle,irq:t.irq-Ln.irq,total:t.total-Ln.total};return fy={measurementTime:e,intervalMs:e-Ln.measurementTime,user:n.user/n.total*100,nice:n.nice/n.total*100,sys:n.sys/n.total*100,idle:n.idle/n.total*100,irq:n.irq/n.total*100,total:100-n.idle/n.total*100},Ln=t,fy}import{hostname as vL}from"os";async function by(r){let{command:e,tracer:t,timeoutMs:n,targetingWrapper:o,disableCache:i,fixtures:a}=r,{logger:s,abortSignal:l}=a;if(e.target&&!rr(e.target))throw new Error("Element assertion with x/y is not supported yet");let c=e.assertion.type==="ELEMENT_EXISTENCE"&&e.assertion.negated&&(e.assertion.condition==="EXISTS"||e.assertion.condition==="VISIBLE"),d=Date.now(),p=0,u,m=500;for(;p<2||Date.now()-d<n;){p++,p>1&&await ne(m,l),l?.throwIfAborted();try{let{newTarget:h,elementInteractedDisplayString:g,result:f}=await o({ctx:a.ctx,tracer:t,command:e,target:e.target,cache:e.cache?.target,action:async S=>SL(S.locator,r),options:{disableCache:i,useSelector:!!e.useSelector,iframeUrl:e.iframeUrl,disableGlobalLocatorRedirect:!0,source:Or(e)}});if(u={success:f.success,data:f.data,err:f.err,newTarget:h,elementInteractedDisplayString:g},!f.success){u=f,m=Math.min(m*2,1e4);continue}return u}catch(h){if(l?.throwIfAborted(),c)return{success:!0,thoughts:`The element described does not exist on the page: ${h.message}`};if(s.warn({err:h},"Element assertion ended in error, retrying..."),!(h instanceof R)||h.reason!="ActionFailureError")throw h;u={success:!1,err:h}}}if(!u)throw new Error(`Failed to evaluate manual element assertion in ${n}ms.`);return u}async function SL(r,{command:e,fixtures:t}){let n=e.assertion;await t.browser.highlight(r);let o=!0,i,a;switch(n.type){case"ELEMENT_CONTENT":{let s=await r.textContent()??"";if(a={elementTextContent:ze(s,500,!0)},!yy(s,n.value,n.operation,!!n.negated)){let l=n.negated?lr[n.operation]:cr[n.operation];o=!1,i=new R("AssertionFailureError",`The content ${l} '${n.value}': ${s}`)}break}case"ELEMENT_ATTRIBUTE":{a={elementOuterHtml:ze(await r.evaluate(l=>l.cloneNode(!1).outerHTML),500,!0)};let s;try{s=await r.getAttribute(n.attr,{timeout:3e3})??""}catch(l){i=new R("AssertionFailureError",`The element does not have an attribute named ${n.attr}: ${l}`),o=!1;break}if(!yy(s,n.value,n.operation,!!n.negated)){let l=n.negated?lr[n.operation]:cr[n.operation];o=!1,n.operation==="EXISTS"?i=n.negated?new R("AssertionFailureError",`The attribute ${n.attr} ${l}: ${s}`):new R("AssertionFailureError",`The attribute ${n.attr} ${l}`):i=new R("AssertionFailureError",`The attribute ${n.attr} ${l} '${n.value}': ${s}`)}break}case"ELEMENT_EXISTENCE":{switch(n.condition){case"VISIBLE":{o=await r.evaluate(async(l,c)=>{let d=Date.now();for(;Date.now()-d<c;){let p=l.getBoundingClientRect();if(p.width>0&&p.height>0)return!0;await new Promise(u=>setTimeout(u,250))}return!1},En*1e3);break}case"EDITABLE":{o=await r.isEditable({timeout:En*1e3});break}case"EXISTS":{o=!0;break}case"ENABLED":{o=await r.isEnabled({timeout:En*1e3});break}default:return(l=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(n.condition)}if(o=n.negated?!o:o,!o){let s=n.negated?hd[n.condition]:gd[n.condition];i=new R("AssertionFailureError",`The element ${s}`)}break}}return{success:o,data:a,err:i}}function yy(r,e,t,n){let o;switch(t){case"CONTAINS":{o=r.includes(e);break}case"EQUALS":{o=r.trim()===e.trim();break}case"STARTS_WITH":{o=r.trim().startsWith(e);break}case"EXISTS":{o=r.trim().length>0;break}default:return(a=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(t)}return n?!o:o}import{Jimp as yL}from"jimp";async function Pa(r,e){let t=await r.screenshot(e),n=await yL.fromBuffer(t);return{buffer:t,width:Math.ceil(n.bitmap.width??0),height:Math.ceil(n.bitmap.height??0)}}import{Jimp as wy}from"jimp";import np from"jpeg-js";import bL from"pixelmatch";async function vy({ctx:r,tracer:e,command:t,disableCache:n,browser:o,targetingWrapper:i,logger:a,screenshotStorage:s}){if(t.target&&!rr(t.target))throw new Error("Visual Diff with x/y is not supported yet");await o.waitForDOMStability({logger:a});let l={clearHighlights:!0,hideCaret:!0},c;t.target?.elementDescriptor?c=(await i({ctx:r,tracer:e,command:t,target:t.target,cache:t.cache?.target??t.target?.a11yData,action:async U=>Pa(o,{locator:U.locator,...l}),options:{disableCache:!!n,useSelector:!!t.useSelector,iframeUrl:t.iframeUrl,disableGlobalLocatorRedirect:!0}})).result:c=await Pa(o,l);let d=await s.prepareGoldenScreenshotForComparison(a,t,c);if((c.height!==d.height||c.width!==d.width)&&a.debug({currHeight:c.height,currWidth:c.width,savedHeight:d.height,savedWidth:d.width},"Mismatched before and after visual diff screenshot sizes"),Math.abs(c.height-d.height)>10||Math.abs(c.width-d.width)>10){let $=`${c.width}x${c.height}`,U=`${d.width}x${d.height}`;return{fail:!0,thoughts:`Current screenshot (${$}) does not match saved screenshot dimensions (${U}) - did you change the size of the target or the viewport?`,beforeScreenshotOverride:d.buffer,afterScreenshotOverride:c.buffer,succeedImmediately:!1,urlAfterCommand:o.url()}}let p=await wy.fromBuffer(c.buffer),u={width:c.width,height:c.height},m=await wy.fromBuffer(d.buffer),h={width:d.width,height:d.height},g,f=u.width*u.height,S=h.width*h.height,v=Math.abs(u.height-h.height),x=Math.abs(u.width-h.width);if(f>S){let $=p.cover({w:h.width,h:h.height});c.buffer=await $.getBuffer("image/jpeg"),g="current",c.width=h.width,c.height=h.height}else if(S>f){let $=m.cover({w:u.width,h:u.height});d.buffer=await $.getBuffer("image/jpeg"),g="saved"}let b={data:Buffer.alloc(c.width*c.height*4),width:c.width,height:c.height},T=t.threshold??.1,A=bL(np.decode(d.buffer).data,np.decode(c.buffer).data,b.data,c.width,c.height,{threshold:T,diffColorAlt:[0,255,0]})/(c.width*c.height)*100,k=A>T*100,L=`Visual diff of ${A.toFixed(2)}% detected, which is ${k?"over":"under"} the threshold of ${T*100}%.`;if(g&&(L+=` The ${g} screenshot was cropped since it was taller by ${v} pixels and wider by ${x} pixels.`),k)throw new R("ActionFailureError",L);return{fail:k,thoughts:L,beforeScreenshotOverride:c.buffer,afterScreenshotOverride:np.encode(b,75).data,succeedImmediately:!1,urlAfterCommand:o.url()}}var wL=5e3;async function hl({timeout:r=En,...e}){let t=Date.now(),n=r*1e3,o=n+1e4,i,a=0,s=500;for(;a-t<n;){if(Date.now()-t>o){e.logger.warn("Exceeded max system timeout for page assertion, exiting...");break}e.signal.throwIfAborted();let l=Date.now();i=await xy(e),a=Date.now();let c=a-l;if(c>1e3&&e.logger.warn({pageAssertDuration:c},"Page assertion took longer than expected"),!i.success)await ne(s,e.signal),s=Math.min(Math.floor(s*1.5),wL);else return i}return i=await xy(e),i}async function xy({assertion:r,browser:e,flagStore:t}){switch(r.type){case"CONTENT":{let o,i=!1,a;try{let s;if(t.isBooleanFlagEnabled("auto_expand_iframes")){let l=await e.evaluateFunctionInAllFrames(Ty,{value:r.value,negated:!!r.negated,returnHtml:!1});i=r.negated?l.every(c=>c.evaluation):l.some(c=>c.evaluation),s=l.find(c=>c.pageHtml)?.pageHtml}else({evaluation:i,pageHtml:s}=await e.evaluateFunctionInPage(Ty,{value:r.value,negated:!!r.negated,returnHtml:!0},"checking page content"));if(!i){let l=r.negated?lr.CONTAINS:cr.CONTAINS;a=new R("AssertionFailureError",`The page ${l} '${r.value}'.`),o=s}}catch(s){a=new R("AssertionFailureError",`Failed to evaluate page content assertion: ${s instanceof Error?s.message:`${s}`}`)}return{success:i,err:a,data:i||!o?void 0:{pageContent:o}}}default:return(o=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(r.type)}}function Ty({value:r,negated:e,returnHtml:t}){let n=document.documentElement.outerHTML,o=n.includes(r)===!e;return n.length>1e4&&(n=n.slice(0,1e4)+"...TRUNCATED"),{evaluation:o,pageHtml:!o&&t?n:void 0}}var rp=async r=>{let{step:e,resolvedInputs:t}=r.moduleParams,{logger:n,context:o,storage:i,codeEvalTools:a,controller:s}=r.fixtures,l=s.browser,{orgId:c,runId:d}=r.inputs,p=s.executeAbortController.signal;Object.keys(t).length>0&&(o.setInputs(t),n.debug({inputs:t,moduleId:e.moduleId},"Set module inputs"));let u,m=!1,h,g;if(e.cacheConfig||e.defaultCacheAllInvocations){let f=e.cacheConfig?.cacheKey||e.defaultCacheKey||"",S=await Ht({orgId:c,s:f,context:o,logger:n,localTools:a,signal:p,flagStore:s.flagStore});g={orgId:c,cacheKeys:[S,...Object.entries(t).map(([x,b])=>`${x}:${b}`)]},n.debug({original:f,keyParams:g},"Module cache key params");let v=Date.now();for(;Date.now()-v<Jh;){p?.throwIfAborted();let x=await i.getCacheResult(g);if(x){n.debug({cacheResult:x},"Got result from module execution cache"),u=gl(e,t,"SUCCESS"),u.message="Used cached module result.",u.data=JSON.parse(x),m=!0;break}else n.debug({cacheKey:f,keyParams:g},"No cache result found, continuing with lock acquisition");let b=await i.acquireCacheLock({keyParams:g,clientMetadata:`hostName:${vL()};runId:${d}`},p);if(b.acquired){h=b.keyPrefix,n.info({cacheKeyPrefixIfLockAcquired:h,cacheKey:f,keyParams:g},"Acquired cache lock and proceeding with module execution");break}else n.debug({cacheKeyPrefixIfLockAcquired:h,cacheKey:f,keyParams:g},"Failed to acquire cache lock, retrying...");await ne(2500+Math.random()*1e4,p)}}try{if(!u)u=await xL(r);else if(e.autoAuth){let f=Ts.safeParse(u.data);if(!f.success)throw new R("UserConfigurationError",`Cached authentication module result is not a valid storage state: ${f.error.message}`);n.debug("Automatically loading auth state after cached module result"),await l.loadAuthState(f.data);let S=!1,v=e.advanced?.cacheInvalidation;if(v&&v.type==="PAGE_CHECK"){let x={type:"CONTENT",value:v.substring},b=await hl({timeout:En,assertion:x,browser:l,flagStore:s.flagStore,logger:n,signal:p});b.success?n.debug({invalResult:b},"Cached result still valid after page check, continuing..."):(n.info({invalResult:b},"Invalidating cached result due to page check failure"),S=!0)}if(g&&S)return await i.deleteCacheResult(g),rp(r)}}finally{try{h!==void 0&&!m&&u?.status==="SUCCESS"&&await TL({step:e,result:u,browser:s.browser,cacheKeyPrefix:h,logger:n,storage:i})}finally{h!==void 0&&await i.releaseCacheLock(h)}}return u},xL=async r=>{let{step:e,tracer:t}=r.moduleParams,n=gl(e,r.moduleParams.resolvedInputs,"SUCCESS"),o=await t.startSubSteps(),{status:i,results:a}=await Sr(r.work,()=>r.executeStepList({...r,listParams:{steps:e.steps,containerName:`module ('${e.name}')`,tracer:o}}));return n.results=a,n.status=i,n.finishedAt=new Date,rn({asyncTasks:r.work.asyncTasks,nestedResults:a,result:n,logger:r.fixtures.logger}),n};function gl(r,e,t){let n={};return Object.entries(e).forEach(([i,a])=>{n[i]=JSON.stringify(a)}),{type:"MODULE",id:r.id,moduleId:r.moduleId,moduleName:r.name,startedAt:new Date,cacheConfig:r.cacheConfig,inputs:n,results:[],finishedAt:new Date,status:t}}async function Ey({orgId:r,step:e,context:t,logger:n,flagStore:o,codeEvalTools:i,signal:a}){let s={};try{for(let l of e.parameters??[]){let c=e.inputs?.[l]??e.defaultParameters?.[l];if(!c){n.warn(`No value or default found for parameter '${l}' that is required by module '${e.name}'`);continue}s[l]=await Kn({orgId:r,code:c,fragment:!0,context:t,logger:n,localTools:i,signal:a,flagStore:o})}return s}catch(l){throw a?.throwIfAborted(),new R("UserConfigurationError",`Failed to evaluate module inputs: ${l}`)}}async function TL({step:r,result:e,browser:t,cacheKeyPrefix:n,logger:o,storage:i}){let a=r.cacheConfig?.cacheExpiryMs;(!a||a===Ag)&&(a=r.defaultCacheTtl??Ig);let s;r.autoAuth?s=JSON.stringify(await t.saveAuthState()):e.data!==void 0?s=JSON.stringify(e.data):s='""',o.debug({cacheKeyPrefix:n,ttlMs:a,truncatedCacheResultJson:ef(s)},"Setting module cache result"),await i.setCacheResult({result:s,keyPrefix:n,ttlMs:a})}async function yr(r,e,t){let n=new Date;try{return t.throwIfAborted(),await e()}catch(o){let i=new Date,a="FAILED",s;if(t.aborted||o instanceof DOMException&&o.name==="AbortError"?(s="Step aborted by user.",a="CANCELLED"):o instanceof R?s=`${o}`:s=`An unexpected error occurred: ${o.message}`,r.type==="RESOLVED_MODULE"){let l=gl(r,{},"FAILED");return l.message=s,l.startedAt=n,l.finishedAt=i,l}return{...zs(r),startedAt:n,finishedAt:i,status:a,data:null,message:s,results:[]}}}async function Sr(r,e){let t=!1;try{return r&&!r.state.failureRecoveryDisabled&&(r.state.failureRecoveryDisabled=!0,t=!0),await e()}finally{r&&t&&(r.state.failureRecoveryDisabled=void 0)}}import{randomUUID as Cy}from"crypto";import{cloneDeep as CL}from"lodash-es";function fl(r,e){r.state.healingDetails?r.state.healingDetails.push(e):r.state.healingDetails=[e]}var Sl=async r=>{let{step:e,tracer:t}=r.presetParams,{logger:n,controller:o,context:i,billingReporter:a}=r.fixtures,{collectDebugData:s}=r.options,{testMetadata:l,suiteMetadata:c}=r.inputs,d=e.command.type,p=n.child({commandType:d,stepId:e.id,commandId:e.command.id}),u=Qi(e.command);r.work.asyncTasks.push(a.reportCreditsUsed(p,d,u,{testId:l?.id,testName:l?.name,suiteId:c?.id,suiteName:c?.name}));let m=o.browser.url(),h=new Date,g,f=Cy(),S=Cy();if(s)try{g=await o.browser.screenshot({retries:1,clearHighlights:!0});let C=await o.browser.getRawCondensedHtml();t.attachBeforeHtmlSnapshot({logger:p,snapshotId:f,html:C}),r.work.asyncTasks.push(r.fixtures.debugDataStorage.storeHtmlSnapshot(p,f,C))}catch(C){p.debug({err:C},"Failed to take screenshot before step, likely because the page is still loading. This is non-fatal and does not affect the test.")}let v,x,b,T=bs();try{let C=await o.executePresetCommand(T,t,e.command,i,l?.advanced.disableAICaching??!1);C.beforeScreenshotOverride&&(g=C.beforeScreenshotOverride),b=C.afterScreenshotOverride;let{proposedStep:A}=RL({work:r.work,step:e,newTargets:C.newTargets,logger:p}),k=new Date,L=o.browser.url();x={beforeUrl:m,afterUrl:L,startedAt:h,finishedAt:k,viewport:o.browser.getViewport(),status:C.fail?"FAILED":"SUCCESS",elementInteracted:C.elementInteracted},v={...e,message:C.thoughts??AL(C.newTargets)??"Successfully executed preset action.",beforeUrl:m,afterUrl:L,finishedAt:k,startedAt:h,status:C.fail?"FAILED":"SUCCESS",data:C.data,results:[x],details:T.details,proposedStep:A},"assertion"in e.command&&(v.message=C.thoughts||"Assertion passed.")}catch(C){p.error({message:C.message,stack:C.stack},`Failed executing preset step ${jr(e.command)}`);let A=o.browser.url(),k=new Date,L=C instanceof Error?C.message:`${C}`;C instanceof R&&C.getLastScreenshotBuffer()&&(b=C.getLastScreenshotBuffer()),x={beforeUrl:m,afterUrl:A,startedAt:h,finishedAt:k,viewport:o.browser.getViewport(),status:C instanceof DOMException&&C.name==="AbortError"?"CANCELLED":"FAILED",message:L},v={...e,startedAt:h,finishedAt:k,beforeUrl:m,afterUrl:A,status:C instanceof DOMException&&C.name==="AbortError"?"CANCELLED":"FAILED",message:L,failureReason:C instanceof R?C.reason:void 0,results:[x],details:T.details}}if(s)try{b||(b=await o.browser.screenshot({retries:1}));let C=await o.browser.getRawCondensedHtml();t.attachAfterHtmlSnapshot({logger:p,snapshotId:S,html:C}),r.work.asyncTasks.push(r.fixtures.debugDataStorage.storeHtmlSnapshot(p,S,C))}catch(C){p.debug({err:C},"Failed store debug data after step, likely because the page is still loading. This is non-fatal and does not affect the test.")}return x.beforeSnapshot=f,v.beforeSnapshot=f,x.afterSnapshot=S,v.afterSnapshot=S,g&&(t.attachBeforeScreenshot({logger:p,snapshotId:f,screenshot:g}),r.work.asyncTasks.push(r.fixtures.debugDataStorage.storeScreenshot(p,f,g))),b&&(t.attachAfterScreenshot({logger:p,snapshotId:S,screenshot:b}),r.work.asyncTasks.push(r.fixtures.debugDataStorage.storeScreenshot(p,S,b))),v};function RL({work:r,step:e,newTargets:t,logger:n}){if(!t?.length)return{proposedStep:void 0};let o=e.command;qg(o,t,n);let i=t[0]?.description;if(i&&"target"in o&&o.target&&o.target.type==="description"){let a={...o,target:{...o.target,elementDescriptor:i}},s={...CL(e),command:a};return fl(r,{type:"DESCRIPTION_UPDATE",thoughts:`Updated element description after the original element could not be found on the page. New element location reasoning: ${t[0]?.thoughts}`}),{proposedStep:s}}return{proposedStep:void 0}}function AL(r){if(r?.length){if(r.length===1&&r[0]?.thoughts)return r[0].thoughts;if(r.length===2&&r.every(e=>e.thoughts))return`Located first element: ${r[0]?.thoughts}
@@ -3810,7 +3810,7 @@ ${a.stack}`),l.status(500).send("Internal Server Error")}),r){let a=rv.static(r,
3810
3810
  for /f "tokens=5" %a in ('netstat -ano ^| findstr :58888') do taskkill /PID %a /F
3811
3811
  `)}import t_ from"events";import ac from"fs";import n_ from"open";import ic from"path";import{fileURLToPath as r_}from"url";import ik from"diff-lines";import{gt as ak}from"semver";import{execSync as HN}from"child_process";import{platform as jN}from"os";function Zp(){return sv()?(y.dimmed("Setting device pixel ratio to 2 automatically since a Mac OS Retina screen was detected."),y.dimmed(`If you are using a low pixel-density monitor, you should manually set --pixel-ratio to 1 to avoid incorrect viewport calculations. Confirm your device's pixel-ratio at https://www.mydevice.io.
3812
3812
  `),2):(y.dimmed("Setting device pixel ratio to 1."),y.dimmed(`If you are using Momentic on a high-pixel density (HiDPI) monitor, relaunch with the --pixel-ratio option to avoid incorrect viewport calculations. Confirm your device's pixel-ratio at https://www.mydevice.io.
3813
- l.`),1)}function sv(){return jN()==="darwin"&&HN("system_profiler SPDisplaysDataType").toString().includes("Retina")}function Qp(r){sv()&&r===1&&(y.warn("If you are using Momentic on a Retina screen, relaunch with the --pixel-ratio option to avoid incorrect viewport calculations."),y.warn("Confirm your device's pixel-ratio at https://www.mydevice.io."))}import $N from"@actions/exec";import GN from"@actions/io";import WN from"quote";import VN from"string-argv";async function lv(r,e=!0){let t=VN(r),n=await GN.which(t[0],!0),o=t.slice(1),i=$N.exec(WN(n),o,{delay:100});if(e)return i}import{existsSync as qN,statSync as KN}from"fs";var vi=!!process.env.CI||!!process.env.GITHUB_ACTIONS||!!process.env.GITHUB_RUN_ID||!!process.env.GITLAB_CI||!!process.env.CI_COMMIT_SHA||!!process.env.JENKINS_URL||!!process.env.BUILD_NUMBER||!!process.env.JENKINS_HOME||!!process.env.CIRCLECI||!!process.env.CIRCLE_BUILD_NUM||!!process.env.TRAVIS||!!process.env.TRAVIS_BUILD_NUMBER||!!process.env.BITBUCKET_BUILD_NUMBER||!!process.env.BITBUCKET_COMMIT||!!process.env.CODEBUILD_BUILD_ID||!!process.env.TF_BUILD||!!process.env.BUILD_BUILDID||!!process.env.AGENT_ID||!!process.env.BUILDER_SA_EMAIL||!!process.env.HEROKU_TEST_RUN_ID||!!process.env.CI_NODE_INDEX||!!process.env.TEAMCITY_VERSION||!!process.env.BUILD_VCS_NUMBER||!!process.env.BUILDKITE||!!process.env.BUILDKITE_BUILD_NUMBER||!!process.env.APPVEYOR||!!process.env.APPVEYOR_BUILD_NUMBER||!!process.env.DRONE||!!process.env.DRONE_BUILD_NUMBER||!!process.env.SHIPPABLE||!!process.env.BUILD_URL||!!process.env.SEMAPHORE||!!process.env.SEMAPHORE_EXECUTABLE_UUID||!!process.env.WOODPECKER||!!process.env.CI_BUILD_NUMBER||!!process.env.WERCKER_MAIN_PIPELINE_STARTED||!!process.env.BUDDY_EXECUTION_ID;function cv(r){try{return qN(r)&&KN(r).isDirectory()}catch(e){return y.error({err:e},`Error reading path ${r} during directory existence check`),!1}}import YN from"csv-parser";import{createReadStream as JN}from"fs";function eu(r){return new Promise((e,t)=>{let n=[];JN(r).pipe(YN()).on("data",o=>n.push(o)).on("end",()=>e(n)).on("error",o=>t(o))})}import jl from"semver";import{z as $l}from"zod";var wn="2.4.0",XN="https://registry.npmjs.org/momentic",ZN=$l.object({versions:$l.record($l.string(),$l.unknown()).optional()});async function dv(r){try{await QN(r)}catch(e){y.warn({err:e},"Failed to check CLI version against NPM servers")}}async function QN(r){if(!wn){r.warn("Unable to check CLI version because CLI_VERSION is not set");return}let e;for(let n=0;n<2;n++)try{let o=await D(fetch(XN),{milliseconds:5e3});if(!o.ok)throw new Error(`Got error status code ${o.statusText}`);let i=await o.json();e=ZN.parse(i).versions;break}catch(o){r.warn({err:o},"Failed to fetch npm registry data")}if(!e){r.warn("Failed to fetch npm registry data. Skipping version check.");return}let t;for(let n of Object.keys(e))jl.valid(n)&&(!t||jl.gt(n,t))&&jl.gt(n,wn)&&jl.lt(n,"2.0.0")&&!n.includes("alpha")&&(t=n);t&&(y.warn(`Update available: v${wn} -> v${t}`),y.warn("This version may be missing critical fixes, features, and security updates."),y.warn(`Run "npx momentic@${t} -V" to update`))}import{existsSync as tk,mkdirSync as nk,statSync as rk}from"fs";import{dirname as ok}from"path";import uv from"readline/promises";import{hostname as ek}from"os";var ee=Fl({app:"cli",clientToken:"pub7eb923f18fb3f1d42ac5eba8c5ea13a5",hostname:ek(),disableConsoleLogs:!0}).child({version:"2.4.0"});var tu=!1,mv=(()=>{try{return rk("/.dockerenv"),!0}catch{return!1}})();async function ft(r,e){if(vi||tu||mv)return!0;ee.flush(),await new Promise(a=>setTimeout(a,500));let t=uv.createInterface({input:process.stdin,output:process.stdout}),n=r.split("."),o;if(n.length===1)o=r;else{let a=`${n.slice(0,n.length-1).join(".").trim()}.`;e?y.warn(a):y.log(a),o=n[n.length-1].trim()}let i=await t.question(`${o} ('y' for yes / n for no / 'A' to accept all) `);return t.close(),i==="A"?(tu=!0,setTimeout(()=>{tu=!1},3e3),!0):i.toLowerCase()==="y"}async function nu(r){let e=ok(r);return cv(e)?tk(r)?ft(`File '${pv(r)}' already exists. Overwrite existing content?`,!0):!0:await ft(`Directory '${pv(e)}' doesn't exist. Create it now?`,!0)?(nk(e,{recursive:!0}),!0):!1}function pv(r){return r.replace(/(\s+)/g,"\\$1")}async function hv(r,e){if(vi||mv)return e;let t=uv.createInterface({input:process.stdin,output:process.stdout}),n=await t.question(`${r} `);return t.close(),n.trim()||e}async function gv({test:r,fragment:e,entities:t,client:n,logger:o,yes:i}){ak(e.schemaVersion,_e)&&(y.error(`This version of the CLI does not support the schema version of the fragment (${e.schemaVersion}). Please update to the latest version of the CLI and retry this command.`),process.exit(1)),Vg(e.steps).forEach(g=>{t.modules[g]||(y.error(`The test patch contains a module with id ${g} that could not be found in the current project. This suggests that either this test patch or your local file system may be out of date.`),process.exit(1))}),e.createdAt.getTime()<Date.now()-7*24*60*60*1e3&&!i&&!await ft("The test patch you are applying is more than 7 days old. Are you sure you want to continue?",!0)&&process.exit(1);let s=r.lastModified.getTime();e.createdAt.getTime()+60*60*1e3<s&&!i&&!await ft("The test patch you are applying was created before the test was last updated. Are you sure you want to continue?",!0)&&process.exit(1);let l=Xr(r.fullFilePath,o,t),c=l.steps;if(!Array.isArray(c))throw new Error(`Test ${r.fullFilePath} is missing steps array`);let d,p;if(e.schemaVersion!==_e){let{steps:g,newVersion:f}=await oa({metadata:{id:e.id,schemaVersion:e.schemaVersion},steps:e.steps,logger:y});d=f,p=Ie.array().parse(g)}else p=Ie.array().parse(e.steps);let{stepsToSave:u,moduleUpdates:m}=await Zt({stepLists:{steps:p}});u.beforeSteps=l.beforeSteps??void 0,u.afterSteps=l.afterSteps??void 0;let h=ik(JSON.stringify(c,void 0,2),JSON.stringify(u,void 0,2),{n_surrounding:5});y.dimmed("=".repeat(30)),y.dimmed(h),y.dimmed("=".repeat(30)),y.dimmed(""),d&&y.warn(`If this patch is applied, your test will also be automatically upgraded to the latest schema version (${d}). Schema upgrades have no impact on functionality, although you may notice minor differences in the test YAML.`),!i&&!await ft("Do you want to apply this patch?")&&(y.dimmed("Cancelled."),process.exit(1)),Wn({relativeTestPath:r.relativePath,steps:u,schemaVersion:d??e.schemaVersion,project:t.project}),y.success("Patch applied successfully."),await n.patchTestFragment(e.id,{applied:!0,appliedAt:new Date})}import{randomUUID as po}from"crypto";import{z as Dv}from"zod";var jt=" ".repeat(6);import _v from"chalk";import{Argument as lo,Option as Oe}from"@commander-js/extra-typings";import{validateHeaderValue as sk}from"http";import{cpus as fv}from"os";import{parse as Cme}from"yaml";import{z as q}from"zod";var Gl=58888,ru=30*60*1e3,Jn=new Oe("--api-key <key>","API key for authentication. If not supplied, attempts to read the MOMENTIC_API_KEY env var."),Xn=new Oe("--server <server>","Momentic server to use. Leave unchanged unless using Momentic on-premise."),co=new Oe("-y, --yes","Skip all confirmation prompts.").env("CI"),ou=new Oe("-w, --wait","Wait for tests to finish running before exiting. Only applicable when running tests remotely").implies({remote:!0}),iu=new Oe("--wait-timeout <waitTimeout>",`The maximum number of seconds to wait for tests to complete. Only applicable when the --wait option is specified. Defaults to ${ru/1e3} seconds.`),Wl=new Oe("--custom-headers <customHeaders...>","Specify custom headers in the form HEADER=VALUE to be sent with each request during the test. Multiple entries can be provided."),yv=new Oe("--reporter <reporter>","Output report files in a standardized format to a local directory. See the --reporter-dir flag for information on the output directory.").choices(Object.values(Yi)),bv=new Oe("--reporter-dir <reporterDir>","Output directory to store report files. Relative paths are resolved relative to the project root, which is defined by the detected momentic.config.yaml. Defaults to 'reports' if unset."),au=new Oe("--output-dir <outputDir>","[Alpha] Output directory to store run artifacts such as screenshots, results, and logs. Relative paths are resolved relative to the project root, which is defined by the detected momentic.config.yaml. This directory will be cleared at the start of execution."),wv=new Oe("--upload-results","Upload test results to Momentic Cloud. By default, this option is disabled."),vv=new Oe("--include <includePatterns...>","Only include tests that match the provided regex patterns. Multiple patterns can be provided. The patterns will be matched against the test file paths and the pattern only needs to match a part of the path for the test to be included."),xv=new Oe("--exclude <excludePatterns...>","The inverted version of --include: a test that matches any of the provided exclusion patterns will be excluded from running."),su=new Oe("--pixel-ratio <pixelRatio>","Device pixel ratio of your screen or monitor. Mac OS Retina displays and machines marketed as 'HiDPI' should set this to 2. Visit https://www.mydevice.io/ to find your device's pixel ratio."),Tv=new Oe("--port <port>",`Port to run the app on. Defaults to ${Gl}.`),lu=new Oe("--input-csv <inputCsv>","Path to a CSV file on disk where each row represents a set of inputs that will be made available to all tests that are ran. The first line of the CSV must be the input names."),Vl=new Oe("--env <env>","Name of the environment to use when running tests."),ql=new Oe("--url-override <urlOverride>","Fully qualified url (e.g. https://www.google.com) to start all tests from. Overrides any default starting url set from the test or environment."),Ev=new Oe("--shard-index <shardIndex>","The index of the shard to run tests for. Defaults to 1.").default(1).argParser(r=>parseInt(r,10)),Fn=new Oe("-c, --config <configPath>","Absolute or relative path to a Momentic configuration file (*.momentic.config.yaml)"),cu=new Oe("-f, --filter <filter>","Run tests within the project that has a name equal to the filter provided. This option cannot be used together with file path or directory arguments, but substring matches are allowed."),Cv=new Oe("--shard-count <shardCount>","The number of shards that tests are being run on. Defaults to 1.").default(1).argParser(r=>parseInt(r,10)),Rv=new Oe("--fix","Attempt to fix any issues found. This option will write changes to your local file system."),du=new Oe("--save-cache","Always save updated step caches after successful test runs. By default, caches are not saved when running on the protected branches configured in the momentic.config.yaml.").env("CI"),pu=new Oe("--disable-cache","Disable caching of test results. This will cause all tests to be re-run every time."),Av=new lo("<tests...>",`One or more test paths to queue on Momentic Cloud.
3813
+ l.`),1)}function sv(){return jN()==="darwin"&&HN("system_profiler SPDisplaysDataType").toString().includes("Retina")}function Qp(r){sv()&&r===1&&(y.warn("If you are using Momentic on a Retina screen, relaunch with the --pixel-ratio option to avoid incorrect viewport calculations."),y.warn("Confirm your device's pixel-ratio at https://www.mydevice.io."))}import $N from"@actions/exec";import GN from"@actions/io";import WN from"quote";import VN from"string-argv";async function lv(r,e=!0){let t=VN(r),n=await GN.which(t[0],!0),o=t.slice(1),i=$N.exec(WN(n),o,{delay:100});if(e)return i}import{existsSync as qN,statSync as KN}from"fs";var vi=!!process.env.CI||!!process.env.GITHUB_ACTIONS||!!process.env.GITHUB_RUN_ID||!!process.env.GITLAB_CI||!!process.env.CI_COMMIT_SHA||!!process.env.JENKINS_URL||!!process.env.BUILD_NUMBER||!!process.env.JENKINS_HOME||!!process.env.CIRCLECI||!!process.env.CIRCLE_BUILD_NUM||!!process.env.TRAVIS||!!process.env.TRAVIS_BUILD_NUMBER||!!process.env.BITBUCKET_BUILD_NUMBER||!!process.env.BITBUCKET_COMMIT||!!process.env.CODEBUILD_BUILD_ID||!!process.env.TF_BUILD||!!process.env.BUILD_BUILDID||!!process.env.AGENT_ID||!!process.env.BUILDER_SA_EMAIL||!!process.env.HEROKU_TEST_RUN_ID||!!process.env.CI_NODE_INDEX||!!process.env.TEAMCITY_VERSION||!!process.env.BUILD_VCS_NUMBER||!!process.env.BUILDKITE||!!process.env.BUILDKITE_BUILD_NUMBER||!!process.env.APPVEYOR||!!process.env.APPVEYOR_BUILD_NUMBER||!!process.env.DRONE||!!process.env.DRONE_BUILD_NUMBER||!!process.env.SHIPPABLE||!!process.env.BUILD_URL||!!process.env.SEMAPHORE||!!process.env.SEMAPHORE_EXECUTABLE_UUID||!!process.env.WOODPECKER||!!process.env.CI_BUILD_NUMBER||!!process.env.WERCKER_MAIN_PIPELINE_STARTED||!!process.env.BUDDY_EXECUTION_ID;function cv(r){try{return qN(r)&&KN(r).isDirectory()}catch(e){return y.error({err:e},`Error reading path ${r} during directory existence check`),!1}}import YN from"csv-parser";import{createReadStream as JN}from"fs";function eu(r){return new Promise((e,t)=>{let n=[];JN(r).pipe(YN()).on("data",o=>n.push(o)).on("end",()=>e(n)).on("error",o=>t(o))})}import jl from"semver";import{z as $l}from"zod";var wn="2.4.2",XN="https://registry.npmjs.org/momentic",ZN=$l.object({versions:$l.record($l.string(),$l.unknown()).optional()});async function dv(r){try{await QN(r)}catch(e){y.warn({err:e},"Failed to check CLI version against NPM servers")}}async function QN(r){if(!wn){r.warn("Unable to check CLI version because CLI_VERSION is not set");return}let e;for(let n=0;n<2;n++)try{let o=await D(fetch(XN),{milliseconds:5e3});if(!o.ok)throw new Error(`Got error status code ${o.statusText}`);let i=await o.json();e=ZN.parse(i).versions;break}catch(o){r.warn({err:o},"Failed to fetch npm registry data")}if(!e){r.warn("Failed to fetch npm registry data. Skipping version check.");return}let t;for(let n of Object.keys(e))jl.valid(n)&&(!t||jl.gt(n,t))&&jl.gt(n,wn)&&jl.lt(n,"2.0.0")&&!n.includes("alpha")&&(t=n);t&&(y.warn(`Update available: v${wn} -> v${t}`),y.warn("This version may be missing critical fixes, features, and security updates."),y.warn(`Run "npx momentic@${t} -V" to update`))}import{existsSync as tk,mkdirSync as nk,statSync as rk}from"fs";import{dirname as ok}from"path";import uv from"readline/promises";import{hostname as ek}from"os";var ee=Fl({app:"cli",clientToken:"pub7eb923f18fb3f1d42ac5eba8c5ea13a5",hostname:ek(),disableConsoleLogs:!0}).child({version:"2.4.2"});var tu=!1,mv=(()=>{try{return rk("/.dockerenv"),!0}catch{return!1}})();async function ft(r,e){if(vi||tu||mv)return!0;ee.flush(),await new Promise(a=>setTimeout(a,500));let t=uv.createInterface({input:process.stdin,output:process.stdout}),n=r.split("."),o;if(n.length===1)o=r;else{let a=`${n.slice(0,n.length-1).join(".").trim()}.`;e?y.warn(a):y.log(a),o=n[n.length-1].trim()}let i=await t.question(`${o} ('y' for yes / n for no / 'A' to accept all) `);return t.close(),i==="A"?(tu=!0,setTimeout(()=>{tu=!1},3e3),!0):i.toLowerCase()==="y"}async function nu(r){let e=ok(r);return cv(e)?tk(r)?ft(`File '${pv(r)}' already exists. Overwrite existing content?`,!0):!0:await ft(`Directory '${pv(e)}' doesn't exist. Create it now?`,!0)?(nk(e,{recursive:!0}),!0):!1}function pv(r){return r.replace(/(\s+)/g,"\\$1")}async function hv(r,e){if(vi||mv)return e;let t=uv.createInterface({input:process.stdin,output:process.stdout}),n=await t.question(`${r} `);return t.close(),n.trim()||e}async function gv({test:r,fragment:e,entities:t,client:n,logger:o,yes:i}){ak(e.schemaVersion,_e)&&(y.error(`This version of the CLI does not support the schema version of the fragment (${e.schemaVersion}). Please update to the latest version of the CLI and retry this command.`),process.exit(1)),Vg(e.steps).forEach(g=>{t.modules[g]||(y.error(`The test patch contains a module with id ${g} that could not be found in the current project. This suggests that either this test patch or your local file system may be out of date.`),process.exit(1))}),e.createdAt.getTime()<Date.now()-7*24*60*60*1e3&&!i&&!await ft("The test patch you are applying is more than 7 days old. Are you sure you want to continue?",!0)&&process.exit(1);let s=r.lastModified.getTime();e.createdAt.getTime()+60*60*1e3<s&&!i&&!await ft("The test patch you are applying was created before the test was last updated. Are you sure you want to continue?",!0)&&process.exit(1);let l=Xr(r.fullFilePath,o,t),c=l.steps;if(!Array.isArray(c))throw new Error(`Test ${r.fullFilePath} is missing steps array`);let d,p;if(e.schemaVersion!==_e){let{steps:g,newVersion:f}=await oa({metadata:{id:e.id,schemaVersion:e.schemaVersion},steps:e.steps,logger:y});d=f,p=Ie.array().parse(g)}else p=Ie.array().parse(e.steps);let{stepsToSave:u,moduleUpdates:m}=await Zt({stepLists:{steps:p}});u.beforeSteps=l.beforeSteps??void 0,u.afterSteps=l.afterSteps??void 0;let h=ik(JSON.stringify(c,void 0,2),JSON.stringify(u,void 0,2),{n_surrounding:5});y.dimmed("=".repeat(30)),y.dimmed(h),y.dimmed("=".repeat(30)),y.dimmed(""),d&&y.warn(`If this patch is applied, your test will also be automatically upgraded to the latest schema version (${d}). Schema upgrades have no impact on functionality, although you may notice minor differences in the test YAML.`),!i&&!await ft("Do you want to apply this patch?")&&(y.dimmed("Cancelled."),process.exit(1)),Wn({relativeTestPath:r.relativePath,steps:u,schemaVersion:d??e.schemaVersion,project:t.project}),y.success("Patch applied successfully."),await n.patchTestFragment(e.id,{applied:!0,appliedAt:new Date})}import{randomUUID as po}from"crypto";import{z as Dv}from"zod";var jt=" ".repeat(6);import _v from"chalk";import{Argument as lo,Option as Oe}from"@commander-js/extra-typings";import{validateHeaderValue as sk}from"http";import{cpus as fv}from"os";import{parse as Cme}from"yaml";import{z as q}from"zod";var Gl=58888,ru=30*60*1e3,Jn=new Oe("--api-key <key>","API key for authentication. If not supplied, attempts to read the MOMENTIC_API_KEY env var."),Xn=new Oe("--server <server>","Momentic server to use. Leave unchanged unless using Momentic on-premise."),co=new Oe("-y, --yes","Skip all confirmation prompts.").env("CI"),ou=new Oe("-w, --wait","Wait for tests to finish running before exiting. Only applicable when running tests remotely").implies({remote:!0}),iu=new Oe("--wait-timeout <waitTimeout>",`The maximum number of seconds to wait for tests to complete. Only applicable when the --wait option is specified. Defaults to ${ru/1e3} seconds.`),Wl=new Oe("--custom-headers <customHeaders...>","Specify custom headers in the form HEADER=VALUE to be sent with each request during the test. Multiple entries can be provided."),yv=new Oe("--reporter <reporter>","Output report files in a standardized format to a local directory. See the --reporter-dir flag for information on the output directory.").choices(Object.values(Yi)),bv=new Oe("--reporter-dir <reporterDir>","Output directory to store report files. Relative paths are resolved relative to the project root, which is defined by the detected momentic.config.yaml. Defaults to 'reports' if unset."),au=new Oe("--output-dir <outputDir>","[Alpha] Output directory to store run artifacts such as screenshots, results, and logs. Relative paths are resolved relative to the project root, which is defined by the detected momentic.config.yaml. This directory will be cleared at the start of execution."),wv=new Oe("--upload-results","Upload test results to Momentic Cloud. By default, this option is disabled."),vv=new Oe("--include <includePatterns...>","Only include tests that match the provided regex patterns. Multiple patterns can be provided. The patterns will be matched against the test file paths and the pattern only needs to match a part of the path for the test to be included."),xv=new Oe("--exclude <excludePatterns...>","The inverted version of --include: a test that matches any of the provided exclusion patterns will be excluded from running."),su=new Oe("--pixel-ratio <pixelRatio>","Device pixel ratio of your screen or monitor. Mac OS Retina displays and machines marketed as 'HiDPI' should set this to 2. Visit https://www.mydevice.io/ to find your device's pixel ratio."),Tv=new Oe("--port <port>",`Port to run the app on. Defaults to ${Gl}.`),lu=new Oe("--input-csv <inputCsv>","Path to a CSV file on disk where each row represents a set of inputs that will be made available to all tests that are ran. The first line of the CSV must be the input names."),Vl=new Oe("--env <env>","Name of the environment to use when running tests."),ql=new Oe("--url-override <urlOverride>","Fully qualified url (e.g. https://www.google.com) to start all tests from. Overrides any default starting url set from the test or environment."),Ev=new Oe("--shard-index <shardIndex>","The index of the shard to run tests for. Defaults to 1.").default(1).argParser(r=>parseInt(r,10)),Fn=new Oe("-c, --config <configPath>","Absolute or relative path to a Momentic configuration file (*.momentic.config.yaml)"),cu=new Oe("-f, --filter <filter>","Run tests within the project that has a name equal to the filter provided. This option cannot be used together with file path or directory arguments, but substring matches are allowed."),Cv=new Oe("--shard-count <shardCount>","The number of shards that tests are being run on. Defaults to 1.").default(1).argParser(r=>parseInt(r,10)),Rv=new Oe("--fix","Attempt to fix any issues found. This option will write changes to your local file system."),du=new Oe("--save-cache","Always save updated step caches after successful test runs. By default, caches are not saved when running on the protected branches configured in the momentic.config.yaml.").env("CI"),pu=new Oe("--disable-cache","Disable caching of test results. This will cause all tests to be re-run every time."),Av=new lo("<tests...>",`One or more test paths to queue on Momentic Cloud.
3814
3814
 
3815
3815
  A test path is a lowercased version of your test name where spaces are replaced with dashes: 'npx momentic pull hello-world'.`),Iv=new lo("<tests...>",`One or more test paths to import from Momentic Cloud.
3816
3816
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "momentic",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "momentic",
9
- "version": "2.4.0",
9
+ "version": "2.4.2",
10
10
  "dependencies": {
11
11
  "@actions/exec": "^1.1.1",
12
12
  "@actions/io": "^1.1.3",
@@ -1657,18 +1657,18 @@
1657
1657
  }
1658
1658
  },
1659
1659
  "node_modules/@sentry/core": {
1660
- "version": "9.29.0",
1661
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.29.0.tgz",
1662
- "integrity": "sha512-wDyNe45PM+RCGtUn1tK7LzJ08ksv8i8KRUHrst7lsinEfRm83YH+wbWrPmwkVNEngUZvYkHwGLbNXM7xgFUuDQ==",
1660
+ "version": "9.30.0",
1661
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.30.0.tgz",
1662
+ "integrity": "sha512-JfEpeQ8a1qVJEb9DxpFTFy1J1gkNdlgKAPiqYGNnm4yQbnfl2Kb/iEo1if70FkiHc52H8fJwISEF90pzMm6lPg==",
1663
1663
  "license": "MIT",
1664
1664
  "engines": {
1665
1665
  "node": ">=18"
1666
1666
  }
1667
1667
  },
1668
1668
  "node_modules/@sentry/node": {
1669
- "version": "9.29.0",
1670
- "resolved": "https://registry.npmjs.org/@sentry/node/-/node-9.29.0.tgz",
1671
- "integrity": "sha512-oABipgC/fClRuvyMeK43rigv9F+OAaoR84UaMKB7aPXN6iz634wBRVsaoZAwiR3xLL+R7MafEPPA/s9XqlG7ag==",
1669
+ "version": "9.30.0",
1670
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-9.30.0.tgz",
1671
+ "integrity": "sha512-jHuSSKro2DUaccGcYSBbB8Rj0sG+LRh1iSWrJ+4c4Pj7tJFN9MbeMybC1buMSzAp+rwHUMZ3+ws0kgNVtsRJJg==",
1672
1672
  "license": "MIT",
1673
1673
  "dependencies": {
1674
1674
  "@opentelemetry/api": "^1.9.0",
@@ -1701,8 +1701,8 @@
1701
1701
  "@opentelemetry/sdk-trace-base": "^1.30.1",
1702
1702
  "@opentelemetry/semantic-conventions": "^1.34.0",
1703
1703
  "@prisma/instrumentation": "6.8.2",
1704
- "@sentry/core": "9.29.0",
1705
- "@sentry/opentelemetry": "9.29.0",
1704
+ "@sentry/core": "9.30.0",
1705
+ "@sentry/opentelemetry": "9.30.0",
1706
1706
  "import-in-the-middle": "^1.13.1",
1707
1707
  "minimatch": "^9.0.0"
1708
1708
  },
@@ -1711,12 +1711,12 @@
1711
1711
  }
1712
1712
  },
1713
1713
  "node_modules/@sentry/opentelemetry": {
1714
- "version": "9.29.0",
1715
- "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-9.29.0.tgz",
1716
- "integrity": "sha512-QTUmre8i5+832RjzQW+g8IQ3UmBe5fbQXGbCF5hQ0UNuHle9r3Z8UZcIff5W8tm5AXMxPqvptTnDEZUUXHgBiA==",
1714
+ "version": "9.30.0",
1715
+ "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-9.30.0.tgz",
1716
+ "integrity": "sha512-LhTmyGGLAP/LAxs/oXuPs0LC5Z80QSLL1oUoBRB5/+MitK7Huug6n8ZFjPTP3/6bT67XOVqILCdj8BwMlBeXhA==",
1717
1717
  "license": "MIT",
1718
1718
  "dependencies": {
1719
- "@sentry/core": "9.29.0"
1719
+ "@sentry/core": "9.30.0"
1720
1720
  },
1721
1721
  "engines": {
1722
1722
  "node": ">=18"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "momentic",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "bin": {
5
5
  "momentic": "./bin/cli.js"
6
6
  },