momentic-mobile 0.33.0 → 0.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.js CHANGED
@@ -24,7 +24,7 @@ ${this.decisions.map(e=>e.toString()).join(`
24
24
  `).slice(o).filter(Boolean).join(`
25
25
  `);return e.push({message:n,origin:a,type:t}),e}_log(e,t){r.write(this._buffer,e," ".repeat(this._groupDepth)+t,3)}debug(e,...t){this._log("debug",bc(e,...t))}error(e,...t){this._log("error",bc(e,...t))}info(e,...t){this._log("info",bc(e,...t))}log(e,...t){this._log("log",bc(e,...t))}warn(e,...t){this._log("warn",bc(e,...t))}getBuffer(){return this._buffer.length>0?this._buffer:void 0}};function gR(r){let e=globalThis.console,t=new Pd;globalThis.console=t;try{r()}finally{let o=t.getBuffer()?.map(i=>i.message).join(`
26
26
  `);process.stderr.write(`${o}
27
- `),globalThis.console=e}}var cs=" ".repeat(6);import F1 from"fetch-retry";import U1 from"os";import hR,{multistream as B1}from"pino";import z1 from"pino-pretty";import H1 from"pino-std-serializers";var us=new Map,G1=!0,fR="Log throttle exceeded",j1=100,W1=5e3,V1=F1(global.fetch,{retries:2,retryOn:function(r,e,t){return!!(e!==null||t&&t.status>=500)},retryDelay:function(r){return Math.pow(2,r)*500}}),mf=class r{consoleLogger;hostname;bindingAttributes;disableConsoleLogs;minLevelValue=20;logsInCurrentWindow=0;droppedLogsInWindow=!1;lastWindowStart=Date.now();site="https://ingest.us.signoz.cloud:443/logs/json";flushIntervalMs;maxBatchSize;buffer=[];flushTimer;constructor({bindings:e,hostname:t,disableConsoleLogs:n,flushIntervalMs:o,maxBatchSize:i}){this.hostname=t??U1.hostname(),this.disableConsoleLogs=n,this.bindingAttributes={...e,env:"production"},this.flushIntervalMs=o??5e3,this.maxBatchSize=i??10;let a={base:this.bindingAttributes,errorKey:"err",level:"debug"};this.consoleLogger=G1?hR(a):hR(a,B1([{stream:z1({colorize:!0})}]))}child(e){return new r({bindings:{...this.bindingAttributes,...e},hostname:this.hostname,disableConsoleLogs:this.disableConsoleLogs,flushIntervalMs:this.flushIntervalMs,maxBatchSize:this.maxBatchSize})}async flush(){await this.flushBuffer(),this.disableConsoleLogs||this.consoleLogger.flush()}scheduleFlush(){this.flushTimer||(this.flushTimer=setTimeout(()=>{this.flushTimer=void 0,this.flushBuffer()},this.flushIntervalMs))}async flushBuffer(){if(this.buffer.length===0)return;let e=this.buffer;this.buffer=[];try{let t=await V1(this.site,{method:"POST",headers:{"Content-Type":"application/json","signoz-access-token":"CumAaTMUcwjt05OddAmefKgshbhfRmWxzxih"},body:ji(e),signal:AbortSignal.timeout(5e3)});if(!t.ok)throw new Error(`Got error status (${t.statusText}) from SigNoz`)}catch{}}shouldAllowLog(e){if(e===fR)return!0;let t=Date.now();return t-this.lastWindowStart>W1&&(this.logsInCurrentWindow=0,this.droppedLogsInWindow&&this.log("error",void 0,fR),this.droppedLogsInWindow=!1,this.lastWindowStart=t),this.logsInCurrentWindow<j1?(this.logsInCurrentWindow++,!0):(this.droppedLogsInWindow=!0,!1)}log(e,t,n,...o){try{this.logHelper(e,t,n,...o)}catch(i){this.consoleLogger.warn(`Failed to log to Signoz: ${i}`)}}logHelper(e,t,n,...o){if(gc[e]<this.minLevelValue||!this.shouldAllowLog(n))return;typeof t=="string"&&!n&&(t={message:t}),typeof t=="object"&&t&&"err"in t&&t.err instanceof Error&&(t.err=H1.err(t.err));let i={...this.bindingAttributes,...t&&typeof t=="object"?t:{},...o.length>0?{args:o}:{}},a={host:this.hostname,env:this.bindingAttributes.env};this.disableConsoleLogs||this.consoleLogger[e](i,n,...o);let s={timestamp:Math.round(Date.now()*1e6),severity_text:e.toUpperCase(),resources:a,attributes:{},body:KA({message:n||"",...i})};this.buffer.push(s),this.buffer.length>=this.maxBatchSize?(this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=void 0),this.flushBuffer()):this.scheduleFlush()}setApp(e){let t=this.bindingAttributes.app;this.bindingAttributes.app=e,us.set("app",this),us.delete(t)}debug(e,t,...n){this.log("debug",e,t,...n)}info(e,t,...n){this.log("info",e,t,...n)}warn(e,t,...n){this.log("warn",e,t,...n)}error(e,t,...n){this.log("error",e,t,...n)}bindings(){return this.bindingAttributes}addBinding(e,t){this.bindingAttributes[e]=t}setMinLevel(e){typeof e=="number"?(this.minLevelValue=e,this.consoleLogger.level=YA[e]):(this.minLevelValue=gc[e],this.consoleLogger.level=e)}enableConsoleLogs(){this.disableConsoleLogs=!1}},ds=({app:r,hostname:e,disableConsoleLogs:t})=>(us.has(r)||us.set(r,new mf({bindings:{app:r},hostname:e,disableConsoleLogs:t})),us.get(r));async function SR(){await Promise.all([...us.values()].map(r=>r.flush()))}import{hostname as $1}from"os";var _r=ds({app:"cli",hostname:$1(),disableConsoleLogs:!0}).child({cliVersion:"0.33.0"});function pf(r){if(!r)return;r=r.toLowerCase();let e=vd.safeParse(r);if(e.success)return M.setMinLevel(e.data),e.data}function yR({results:r,startTime:e,entity:t,getDisplayLine:n,onFailed:o}){let i=r.filter(u=>u.status==="PASSED"&&u.quarantined),a=r.filter(u=>u.status==="PASSED"&&!u.quarantined),s=r.filter(u=>u.status==="FAILED"&&u.quarantined),c=r.filter(u=>u.status==="FAILED"&&!u.quarantined),l=r.filter(u=>u.status==="CANCELLED");return gR(()=>{if(c.forEach(u=>{M.log(""),o(u)}),c.length){M.log("");let u=c.length===1?"":"s";M.error(`${c.length} ${t}${u} failed:`),c.forEach(d=>{M.dimmed(n(d))})}if(l.length){M.log("");let u=l.length===1?"":"s";M.warn(`${l.length} ${t}${u} cancelled:`),l.forEach(d=>{M.dimmed(n(d))})}if(a.length){M.log("");let u=a.length===1?"":"s";M.success(`${a.length} ${t}${u} passed:`),a.forEach(d=>{M.dimmed(n(d))})}if(s.length){M.log("");let u=s.length===1?"":"s";M.warn(`${s.length} quarantined ${t}${u} failed:`),s.forEach(d=>{M.dimmed(n(d))})}if(i.length){M.log("");let u=i.length===1?"":"s";M.warn(`${i.length} quarantined ${t}${u} passed:`),i.forEach(d=>{M.dimmed(n(d))})}M.log(""),M.dimmed(`Total time: ${Math.round((Date.now()-e)/1e3)}s`)}),{quarantinedPassed:i.length,passed:a.length,quarantinedFailed:s.length,failed:c.length,cancelled:l.length}}var Ec=({status:r,testLogRef:e,getRunningTestsCount:t,getTotalTestsCount:n,additionalText:o})=>{r=r.toUpperCase();let i=r,a;r.includes("FAIL")?(i=ms.bgRed.white("FAIL"),a=3):r.includes("PASS")?(i=ms.bgGreen.white("PASS"),a=3):r.includes("START")?(i=ms.bgBlue.white("START"),a=2):r.includes("CANCEL")?(i=ms.bgRgb(191,68,11).white("CANCEL"),a=1):r.includes("RETRY")?(i=ms.bgRgb(191,68,11).white("RETRY"),a=2):r.includes("RUN")||r.includes("PROG")?(i=ms.bgMagenta.white("RUNNING"),a=0):(M.warn(`Unknown status tried to be logged in run test locally: ${r}`),a=0),q1||(i=`${i}`),M.log(`${i}${" ".repeat(a)} ${e} ${o?`${o} `:""}(${t()}/${n()})`)};import K1 from"fs";import{platform as Y1,tmpdir as X1}from"os";import J1 from"path";import{program as Z1}from"playwright-core/lib/cli/program";import{registry as Tc}from"playwright-core/lib/server";import bR from"proper-lockfile";var ER=J1.join(X1(),"momenticBrowserInstallation");var gf=["chrome","chromium","chrome-for-testing","ffmpeg"],Q1={Chromium:"chromium","Google Chrome":"chrome","Chrome for Testing":"chrome-for-testing"},TR={chrome:"chrome",chromium:"chromium","chrome-for-testing":"chromium-headless-shell",ffmpeg:"ffmpeg"};function vR(r){if(r==="Org Default")return!1;let e=TR[Q1[r]??""]??"",t=Tc.findExecutable(e);return!t||t.installType==="none"?!1:hf(t)}function hf(r){let e=r.executablePath();return K1.existsSync(e)}function eH(r,e){let t=TR[r];if(!t)throw new Error(`Requested install of unknown browser type ${r}`);let n=Tc.findExecutable(t);if(!n||n.installType==="none")throw new Error(`Requested install of unknown browser type ${r}`);if(!(!e&&hf(n)))return n}async function tH({browser:r,force:e}){let t=eH(r,e);if(!t){M.info(`Browser '${r}' is already installed, skipping...`);return}M.info(`Installing browser '${r}'...`);try{await Tc.installDeps([t],!1),await Tc.install([t],!1)}catch(n){if(n.message.includes("Lock file is already being held")){M.warn("Another process is installing Playwright browsers. Waiting for completion before proceeding..");let o=Tc.findExecutable(r),i=5*60*1e3,a=Date.now();for(;Date.now()-a<i&&!hf(o);)M.info("Waiting for browser to finish installing..."),await new Promise(s=>setTimeout(s,5e3))}else throw n}}async function rH(){if(Y1()==="win32"){M.info("Installing Windows dependencies for Playwright...");try{await Z1.parseAsync(["","","install","winldd"])}catch(r){M.warn(`Failed to install Windows dependencies: ${r}. Continuing with browser installation...`)}}}async function Id({rawBrowsers:r,force:e=!1,all:t=!1}){await rH();let n=t?gf:Array.from(new Set(r));try{await bR.lock(ER,{stale:1e3*60*5,update:1e3*60,realpath:!1,retries:{retries:30,factor:2,maxTimeout:15e3,minTimeout:500}})}catch(i){M.warn(`Failed to acquire lock to install browsers. Please ensure that any other process installing browsers completes within 5 minutes: ${i}. Continuing without installation...`);return}let o;try{for(let i of n)try{await tH({browser:i,force:e})}catch(a){o=a,M.error(`Failed to install the ${i} browser: ${a}`)}}finally{await bR.unlock(ER,{realpath:!1})}if(o)throw o}import{createServer as nH}from"http";async function zo(r,e,t=30){for(let n=0;n<t;n+=1){let o=r+n;if(await Od(o))return o}M.error(`Could not find an available port for ${e} starting from ${r} after ${t} attempts`),process.exit(1)}async function Od(r){return new Promise((e,t)=>{let n=nH();n.once("error",o=>{o.code==="EADDRINUSE"?e(!1):(M.warn({err:o},"Unexpected error checking for open ports, continuing..."),n.close(),e(!0))}),n.once("listening",()=>{n.close(()=>{e(!0)})}),n.listen(r)})}import Sye from"blocked-at";import bye from"why-is-node-running";function AR(r){let e=r?.shardIndex??1,t=r?.shardCount??1;if(e<1)throw new Error("Shard index must be greater than 0.");if(t<1)throw new Error("Shard count must be greater than 0.");if(e>t)throw new Error("Shard index cannot be greater than shard count")}function oH(r,e,t,n){if(t>r.length&&(M.warn(`Shard count ${t} is greater than the number of tests ${r.length}! Some workers won't have any tests to run.`),t=Math.max(t,r.length),e>t))return[];let o=Math.floor((e-1)*(r.length/t)),i=Math.floor(e*(r.length/t));return(n?[...r].sort((s,c)=>n(s).localeCompare(n(c))):[...r].sort()).filter((s,c)=>c>=o&&c<i)}function wR(r){let{items:e,shardIndex:t,shardCount:n,sortKey:o}=r;return n>1?oH(e,t,n,o):e}function ff({regenerateCache:r,saveCache:e,disableCache:t}){if(t){if(r)throw new Error("--disable-cache and --regenerate-cache cannot be used together.");if(e)throw new Error("--disable-cache and --save-cache cannot be used together.")}}function RR(r,e,t){return r instanceof Ti?(r.zodIssues.forEach(n=>{t.push({file:e,stepIndex:typeof n.path[0]=="number"?n.path[0]:void 0,field:n.path.slice(1).join(".")||n.path.join("."),issue:n.message})}),!0):!1}function Sf({parsingErrors:r,parsingErrorDetails:e,failedTestFilePaths:t,failedModuleFilePaths:n}){if(M.error(`
27
+ `),globalThis.console=e}}var cs=" ".repeat(6);import F1 from"fetch-retry";import U1 from"os";import hR,{multistream as B1}from"pino";import z1 from"pino-pretty";import H1 from"pino-std-serializers";var us=new Map,G1=!0,fR="Log throttle exceeded",j1=100,W1=5e3,V1=F1(global.fetch,{retries:2,retryOn:function(r,e,t){return!!(e!==null||t&&t.status>=500)},retryDelay:function(r){return Math.pow(2,r)*500}}),mf=class r{consoleLogger;hostname;bindingAttributes;disableConsoleLogs;minLevelValue=20;logsInCurrentWindow=0;droppedLogsInWindow=!1;lastWindowStart=Date.now();site="https://ingest.us.signoz.cloud:443/logs/json";flushIntervalMs;maxBatchSize;buffer=[];flushTimer;constructor({bindings:e,hostname:t,disableConsoleLogs:n,flushIntervalMs:o,maxBatchSize:i}){this.hostname=t??U1.hostname(),this.disableConsoleLogs=n,this.bindingAttributes={...e,env:"production"},this.flushIntervalMs=o??5e3,this.maxBatchSize=i??10;let a={base:this.bindingAttributes,errorKey:"err",level:"debug"};this.consoleLogger=G1?hR(a):hR(a,B1([{stream:z1({colorize:!0})}]))}child(e){return new r({bindings:{...this.bindingAttributes,...e},hostname:this.hostname,disableConsoleLogs:this.disableConsoleLogs,flushIntervalMs:this.flushIntervalMs,maxBatchSize:this.maxBatchSize})}async flush(){await this.flushBuffer(),this.disableConsoleLogs||this.consoleLogger.flush()}scheduleFlush(){this.flushTimer||(this.flushTimer=setTimeout(()=>{this.flushTimer=void 0,this.flushBuffer()},this.flushIntervalMs))}async flushBuffer(){if(this.buffer.length===0)return;let e=this.buffer;this.buffer=[];try{let t=await V1(this.site,{method:"POST",headers:{"Content-Type":"application/json","signoz-access-token":"CumAaTMUcwjt05OddAmefKgshbhfRmWxzxih"},body:ji(e),signal:AbortSignal.timeout(5e3)});if(!t.ok)throw new Error(`Got error status (${t.statusText}) from SigNoz`)}catch{}}shouldAllowLog(e){if(e===fR)return!0;let t=Date.now();return t-this.lastWindowStart>W1&&(this.logsInCurrentWindow=0,this.droppedLogsInWindow&&this.log("error",void 0,fR),this.droppedLogsInWindow=!1,this.lastWindowStart=t),this.logsInCurrentWindow<j1?(this.logsInCurrentWindow++,!0):(this.droppedLogsInWindow=!0,!1)}log(e,t,n,...o){try{this.logHelper(e,t,n,...o)}catch(i){this.consoleLogger.warn(`Failed to log to Signoz: ${i}`)}}logHelper(e,t,n,...o){if(gc[e]<this.minLevelValue||!this.shouldAllowLog(n))return;typeof t=="string"&&!n&&(t={message:t}),typeof t=="object"&&t&&"err"in t&&t.err instanceof Error&&(t.err=H1.err(t.err));let i={...this.bindingAttributes,...t&&typeof t=="object"?t:{},...o.length>0?{args:o}:{}},a={host:this.hostname,env:this.bindingAttributes.env};this.disableConsoleLogs||this.consoleLogger[e](i,n,...o);let s={timestamp:Math.round(Date.now()*1e6),severity_text:e.toUpperCase(),resources:a,attributes:{},body:KA({message:n||"",...i})};this.buffer.push(s),this.buffer.length>=this.maxBatchSize?(this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=void 0),this.flushBuffer()):this.scheduleFlush()}setApp(e){let t=this.bindingAttributes.app;this.bindingAttributes.app=e,us.set("app",this),us.delete(t)}debug(e,t,...n){this.log("debug",e,t,...n)}info(e,t,...n){this.log("info",e,t,...n)}warn(e,t,...n){this.log("warn",e,t,...n)}error(e,t,...n){this.log("error",e,t,...n)}bindings(){return this.bindingAttributes}addBinding(e,t){this.bindingAttributes[e]=t}setMinLevel(e){typeof e=="number"?(this.minLevelValue=e,this.consoleLogger.level=YA[e]):(this.minLevelValue=gc[e],this.consoleLogger.level=e)}enableConsoleLogs(){this.disableConsoleLogs=!1}},ds=({app:r,hostname:e,disableConsoleLogs:t})=>(us.has(r)||us.set(r,new mf({bindings:{app:r},hostname:e,disableConsoleLogs:t})),us.get(r));async function SR(){await Promise.all([...us.values()].map(r=>r.flush()))}import{hostname as $1}from"os";var _r=ds({app:"cli",hostname:$1(),disableConsoleLogs:!0}).child({cliVersion:"0.33.1"});function pf(r){if(!r)return;r=r.toLowerCase();let e=vd.safeParse(r);if(e.success)return M.setMinLevel(e.data),e.data}function yR({results:r,startTime:e,entity:t,getDisplayLine:n,onFailed:o}){let i=r.filter(u=>u.status==="PASSED"&&u.quarantined),a=r.filter(u=>u.status==="PASSED"&&!u.quarantined),s=r.filter(u=>u.status==="FAILED"&&u.quarantined),c=r.filter(u=>u.status==="FAILED"&&!u.quarantined),l=r.filter(u=>u.status==="CANCELLED");return gR(()=>{if(c.forEach(u=>{M.log(""),o(u)}),c.length){M.log("");let u=c.length===1?"":"s";M.error(`${c.length} ${t}${u} failed:`),c.forEach(d=>{M.dimmed(n(d))})}if(l.length){M.log("");let u=l.length===1?"":"s";M.warn(`${l.length} ${t}${u} cancelled:`),l.forEach(d=>{M.dimmed(n(d))})}if(a.length){M.log("");let u=a.length===1?"":"s";M.success(`${a.length} ${t}${u} passed:`),a.forEach(d=>{M.dimmed(n(d))})}if(s.length){M.log("");let u=s.length===1?"":"s";M.warn(`${s.length} quarantined ${t}${u} failed:`),s.forEach(d=>{M.dimmed(n(d))})}if(i.length){M.log("");let u=i.length===1?"":"s";M.warn(`${i.length} quarantined ${t}${u} passed:`),i.forEach(d=>{M.dimmed(n(d))})}M.log(""),M.dimmed(`Total time: ${Math.round((Date.now()-e)/1e3)}s`)}),{quarantinedPassed:i.length,passed:a.length,quarantinedFailed:s.length,failed:c.length,cancelled:l.length}}var Ec=({status:r,testLogRef:e,getRunningTestsCount:t,getTotalTestsCount:n,additionalText:o})=>{r=r.toUpperCase();let i=r,a;r.includes("FAIL")?(i=ms.bgRed.white("FAIL"),a=3):r.includes("PASS")?(i=ms.bgGreen.white("PASS"),a=3):r.includes("START")?(i=ms.bgBlue.white("START"),a=2):r.includes("CANCEL")?(i=ms.bgRgb(191,68,11).white("CANCEL"),a=1):r.includes("RETRY")?(i=ms.bgRgb(191,68,11).white("RETRY"),a=2):r.includes("RUN")||r.includes("PROG")?(i=ms.bgMagenta.white("RUNNING"),a=0):(M.warn(`Unknown status tried to be logged in run test locally: ${r}`),a=0),q1||(i=`${i}`),M.log(`${i}${" ".repeat(a)} ${e} ${o?`${o} `:""}(${t()}/${n()})`)};import K1 from"fs";import{platform as Y1,tmpdir as X1}from"os";import J1 from"path";import{program as Z1}from"playwright-core/lib/cli/program";import{registry as Tc}from"playwright-core/lib/server";import bR from"proper-lockfile";var ER=J1.join(X1(),"momenticBrowserInstallation");var gf=["chrome","chromium","chrome-for-testing","ffmpeg"],Q1={Chromium:"chromium","Google Chrome":"chrome","Chrome for Testing":"chrome-for-testing"},TR={chrome:"chrome",chromium:"chromium","chrome-for-testing":"chromium-headless-shell",ffmpeg:"ffmpeg"};function vR(r){if(r==="Org Default")return!1;let e=TR[Q1[r]??""]??"",t=Tc.findExecutable(e);return!t||t.installType==="none"?!1:hf(t)}function hf(r){let e=r.executablePath();return K1.existsSync(e)}function eH(r,e){let t=TR[r];if(!t)throw new Error(`Requested install of unknown browser type ${r}`);let n=Tc.findExecutable(t);if(!n||n.installType==="none")throw new Error(`Requested install of unknown browser type ${r}`);if(!(!e&&hf(n)))return n}async function tH({browser:r,force:e}){let t=eH(r,e);if(!t){M.info(`Browser '${r}' is already installed, skipping...`);return}M.info(`Installing browser '${r}'...`);try{await Tc.installDeps([t],!1),await Tc.install([t],!1)}catch(n){if(n.message.includes("Lock file is already being held")){M.warn("Another process is installing Playwright browsers. Waiting for completion before proceeding..");let o=Tc.findExecutable(r),i=5*60*1e3,a=Date.now();for(;Date.now()-a<i&&!hf(o);)M.info("Waiting for browser to finish installing..."),await new Promise(s=>setTimeout(s,5e3))}else throw n}}async function rH(){if(Y1()==="win32"){M.info("Installing Windows dependencies for Playwright...");try{await Z1.parseAsync(["","","install","winldd"])}catch(r){M.warn(`Failed to install Windows dependencies: ${r}. Continuing with browser installation...`)}}}async function Id({rawBrowsers:r,force:e=!1,all:t=!1}){await rH();let n=t?gf:Array.from(new Set(r));try{await bR.lock(ER,{stale:1e3*60*5,update:1e3*60,realpath:!1,retries:{retries:30,factor:2,maxTimeout:15e3,minTimeout:500}})}catch(i){M.warn(`Failed to acquire lock to install browsers. Please ensure that any other process installing browsers completes within 5 minutes: ${i}. Continuing without installation...`);return}let o;try{for(let i of n)try{await tH({browser:i,force:e})}catch(a){o=a,M.error(`Failed to install the ${i} browser: ${a}`)}}finally{await bR.unlock(ER,{realpath:!1})}if(o)throw o}import{createServer as nH}from"http";async function zo(r,e,t=30){for(let n=0;n<t;n+=1){let o=r+n;if(await Od(o))return o}M.error(`Could not find an available port for ${e} starting from ${r} after ${t} attempts`),process.exit(1)}async function Od(r){return new Promise((e,t)=>{let n=nH();n.once("error",o=>{o.code==="EADDRINUSE"?e(!1):(M.warn({err:o},"Unexpected error checking for open ports, continuing..."),n.close(),e(!0))}),n.once("listening",()=>{n.close(()=>{e(!0)})}),n.listen(r)})}import Sye from"blocked-at";import bye from"why-is-node-running";function AR(r){let e=r?.shardIndex??1,t=r?.shardCount??1;if(e<1)throw new Error("Shard index must be greater than 0.");if(t<1)throw new Error("Shard count must be greater than 0.");if(e>t)throw new Error("Shard index cannot be greater than shard count")}function oH(r,e,t,n){if(t>r.length&&(M.warn(`Shard count ${t} is greater than the number of tests ${r.length}! Some workers won't have any tests to run.`),t=Math.max(t,r.length),e>t))return[];let o=Math.floor((e-1)*(r.length/t)),i=Math.floor(e*(r.length/t));return(n?[...r].sort((s,c)=>n(s).localeCompare(n(c))):[...r].sort()).filter((s,c)=>c>=o&&c<i)}function wR(r){let{items:e,shardIndex:t,shardCount:n,sortKey:o}=r;return n>1?oH(e,t,n,o):e}function ff({regenerateCache:r,saveCache:e,disableCache:t}){if(t){if(r)throw new Error("--disable-cache and --regenerate-cache cannot be used together.");if(e)throw new Error("--disable-cache and --save-cache cannot be used together.")}}function RR(r,e,t){return r instanceof Ti?(r.zodIssues.forEach(n=>{t.push({file:e,stepIndex:typeof n.path[0]=="number"?n.path[0]:void 0,field:n.path.slice(1).join(".")||n.path.join("."),issue:n.message})}),!0):!1}function Sf({parsingErrors:r,parsingErrorDetails:e,failedTestFilePaths:t,failedModuleFilePaths:n}){if(M.error(`
28
28
  Found ${r} file(s) with validation errors that must be fixed manually:
29
29
  `),e.length>0){let o=new Map;e.forEach(i=>{let a=o.get(i.file)||[];a.push(i),o.set(i.file,a)}),o.forEach((i,a)=>{M.error(` ${a}`),i.forEach(({stepIndex:s,field:c,issue:l})=>{let u=s!==void 0?`Step ${s}`:"File",d=c?`, field "${c}"`:"";M.error(` ${u}${d}:`),M.error(` \u2192 ${l}`)})})}else t.size>0&&M.error(`Failed test files:
30
30
  ${[...t].map(o=>`${cs}- ${o}`).join(`
@@ -3269,7 +3269,7 @@ function addMd5Hash() {
3269
3269
  return cmn(c ^ (b | ~d), a, b, x, s, t);
3270
3270
  };
3271
3271
  var md51 = function(s) {
3272
- var txt = "", n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i;
3272
+ var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i;
3273
3273
  for (i = 64; i <= s.length; i += 64) {
3274
3274
  md5cycle(state, md5blk(s.substring(i - 64, i)));
3275
3275
  }
@@ -4571,9 +4571,9 @@ ${r}`;case"ELEMENT_CHECK":return`${YI}
4571
4571
  ${r}`;default:return r}}async function an({frameConfig:r,action:e,browser:t}){let n=t.getActiveFrameConfig();r?t.setActiveFrameConfig(r):n?.type==="auto"&&t.setActiveFrameConfig(void 0);try{return await e()}finally{t.setActiveFrameConfig(n)}}var D2=["NAVIGATE","NEW_TAB","TAB","REFRESH","WAIT_FOR_URL"];async function ZI({beforeUrl:r,beforePages:e,browser:t,command:n,logger:o}){if(D2.includes(n.type))return;let s=("cache"in n&&n.cache&&"target"in n.cache?n.cache.target:void 0)?.nodeOnlySerializedHtml?.includes("<a")??!1?300:3e3,c=Date.now(),l=0;for(;l===0||Date.now()-c<s;){await J(250),l++;let u=(await t.getOpenPages()).map(p=>p.url),d=t.url();if(u.length!==e.length)for(let p=u.length-1;p>=e.length;p--){let m=u[p];if(ta(m,o)&&m!==r&&m!==d){o.info({beforePages:e,afterPages:u,beforeUrl:r},"Auto-following new tab after preset action"),await t.switchToPage({type:"INDEX",index:String(p)});break}}}}async function jn(r,e={}){let t=await r.getBrowserState(e);return{serializedTree:t.serialize(e.serializationOpts),tree:t}}var QI=r=>!!r&&Ta(r),eO=r=>{let{cache:e,description:t,disableSecondaryCacheResolution:n,logger:o}=r,i=e,a=!1;return i&&n&&i.targetSource==="HEURISTIC_HEALED"&&(a=!0,i=void 0),i?.inputDescription&&!XI(t,i.inputDescription)&&(o.warn({old:i.inputDescription,new:t},"Target cache was generated with a different description, clearing it automatically"),a=!0,i=void 0),{cache:i,cacheBustedBeforeAction:a}};import{randomUUID as H2}from"crypto";var rO={minChunkTokenCount:500,acceptableChunkTokenCount:3e3,maxChunkTokenCount:8e3,maxLineLength:4e3},nO={minChunkTokenCount:5e3,acceptableChunkTokenCount:1e4,maxChunkTokenCount:3e4,maxLineLength:500},tO=/<(\S+) id="(\d+)".*?>/g,k2=/(<\/(\S+)>)|(<(\S+).*?\/>)/g,oO=["h1","h2","section","footer","nav","aside","form","label","dialog"],F2=[...oO,"span","div","h3"],U2=["table","select","form","ul","ol","menu","pre","code","dialog"],B2=["table","form","dialog","nav","section","ul","select"];function np(r){return z2(r)}function z2({logger:r,serializedTree:e,options:t}){let{minChunkTokenCount:n,acceptableChunkTokenCount:o,maxChunkTokenCount:i,maxLineLength:a}=t,s=[],c=e.split(`
4572
4572
  `),l=0,u=[],d=0,p=[],m=[],g=!1;for(;l<c.length;){g&&(s.push({ids:p,content:u.join(`
4573
4573
  `),tokenLength:d}),u=[],d=0,p=m.length?[m[m.length-1].id]:[],g=!1);let h=c[l],f=bn(h);d+=f,h.length>a&&(h=h.slice(0,a));let b=Array.from(h.matchAll(tO)).map(K=>K&&K.length>=3?{tagName:K[1],id:K[2]}:void 0).filter(K=>!!K),P=Array.from(h.matchAll(k2)).map(K=>K&&(K[2]||K[4])).filter(K=>!!K);P.reverse();let O=h.replace(/ id="[0-9]+"/g,"");u.push(O);for(let K of b)p.push(K.id),m.push(K);for(let K of P){let ge=m[m.length-1];ge&&ge.tagName===K&&m.pop()}let T=m.some(K=>U2.includes(K.tagName)),R=c[l+1]??"",D=bn(R),k=Array.from(R.matchAll(tO)).map(K=>K&&K.length>2?K[1]:void 0).filter(K=>!!K),F=k.some(K=>oO.includes(K)),ee=k.some(K=>F2.includes(K));d+D>=i&&(g=!0),d>=n&&(F&&!T||P.some(K=>B2.includes(K)))&&(g=!0),d>=o&&ee&&!T&&(g=!0),l++}return u.length&&s.push({ids:p,content:u.join(`
4574
- `),tokenLength:d}),s.forEach((h,f)=>{let y=h.ids[0],E=h.ids[h.ids.length-1];r.debug({tokenLength:h.tokenLength,minId:y,maxId:E},`Chunk for page filtering (index ${f+1}/${s.length})`)}),{chunks:s}}var G2=75e4,op=3e5;async function aa(r){let{options:e,fixtures:t,screenshot:n}=r,{aiPageFiltering:o}=e,{logger:i,generator:a,orgId:s,signal:c}=t,l=r.tree,u=r.serializedTree,d=bn(u);if(d>G2)try{let p=np({serializedTree:u,options:{minChunkTokenCount:1e4,maxChunkTokenCount:1e5,acceptableChunkTokenCount:5e4,maxLineLength:4e3},logger:i});l=await W2({...r,tokenLimit:op-1e4,chunks:p.chunks}),u=l.serialize();let m=bn(u);i.info({oldTokens:d,newTokens:m},"Filtered page using keywords"),d=m}catch(p){i.warn({err:p},"Error filtering page using keyword matching, using naive truncation"),l=l.pruneToSerializedCharLimit(op*Yo),u=l.serialize();let m=bn(u);i.info({oldTokens:d,newTokens:m},"Filtered page using naive truncation"),d=m}if(d>op)try{if(o){let p=np({serializedTree:u,options:nO,logger:i}),m=H2();l=await Y(j2({...r,chunks:p.chunks,callId:m}),{milliseconds:12e3,signal:c}),u=l.serialize();let g=bn(u);i.info({oldTokens:d,newTokens:g,langfuseCallId:m},"Filtered page using AI chunk ranking"),d=g}else{let p=np({serializedTree:u,options:rO,logger:i});l=await Y(V2({...r,chunkResult:p,tokenLimit:4e4}),{milliseconds:12e3,signal:c}),u=l.serialize();let m=bn(u);i.info({oldTokens:d,newTokens:m},"Filtered page using RAG"),d=m}}catch(p){i.warn({err:p},"Error filtering page using RAG/AI, using naive truncation"),l=l.pruneToSerializedCharLimit(op*Yo),u=l.serialize(),i.info("Filtered page using naive truncation")}return u}async function j2({type:r,callId:e,chunks:t,description:n,fixtures:o,tree:i}){let{generator:a,signal:s,logger:c}=o,l=await a.rankChunksWithAi({chunks:t,description:n,type:r,softTokenLimit:4e4,hardTokenLimit:8e4,callId:e},{abortSignal:s,logger:c,loggerTags:ye(c)}),u=[];return t.forEach((p,m)=>{l.indices.includes(m)&&(u=u.concat(p.ids))}),i.pruneUsingRelevantIds(new Set(u))}async function W2(r){let{description:e,fixtures:t,tree:n}=r,{generator:o,logger:i,signal:a}=t;if(!e.trim())throw new Error("Empty description passed to page filtering");let s=await o.getExtractedKeywords({goal:e},{logger:i,loggerTags:ye(i),abortSignal:a});i.info({keywordsResult:s},"Got keywords for page filtering");for(let c of s.keywords){let l=r.chunks.filter(m=>m.content.toLowerCase().includes(c.toLowerCase()));if(!l.length||l.reduce((m,g)=>m+g.tokenLength,0)>r.tokenLimit&&l.length>1)continue;let d=l.flatMap(m=>m.ids);return n.pruneUsingRelevantIds(new Set(d))}throw new Error("No keywords were unique enough for page filtering")}async function V2(r){let{description:e,fixtures:t,chunkResult:n,tokenLimit:o,tree:i}=r,{generator:a,logger:s,signal:c}=t,l=await a.rankChunksWithRag({description:e,chunks:n.chunks,tokenLimit:o},{abortSignal:c,logger:s,loggerTags:ye(s)});if(l.ids.length===0)throw new Error("RAG returned no important ids");return i.pruneUsingRelevantIds(new Set(l.ids.map(d=>`${d}`)))}async function Ny(r,e){if(!r.description)throw new w("UserConfigurationError","Cannot locate element with empty description");return an({action:async()=>$2(r,e),frameConfig:r.iframeUrl?{type:"url",url:r.iframeUrl}:void 0,browser:e.browser,logger:r.logger})}async function $2(r,e){let{disableCache:t,testContext:n,filterByViewport:o,skipWait:i,source:a,memory:s,aiPageFiltering:c,logger:l,allowNotActionableNodesOverride:u,skipSavingVisualAttributes:d}=r,{orgId:p,browser:m,localCodeEvalTools:g,generator:h,abortSignal:f}=e,y=r.description,E=Ds(),b=r.useMemory&&!t;n&&(y=await Yc({orgId:p,s:y,context:n,localTools:g,signal:f,logger:l})),a&&(y=JI(y,a));let{serializedTree:x,tree:P}=await E.startAsyncSpan("GET_PAGE_STATE",async()=>jn(m,{allowNotActionableNodesOverride:u,filterByViewport:o,abortSignal:f,skipWait:i,logger:l}),{}),O=await E.startAsyncSpan("GET_PAGE_SCREENSHOT",async()=>{let B,j=Date.now(),ue;for(;!B&&Date.now()-j<3e3;){f.throwIfAborted();try{B=await m.screenshot({clearHighlights:!0,respectActiveFrame:!0,retries:2})}catch(le){ue=le}}if(!B)throw new w("ActionFailureError",`Failed to take screenshot of page to locate element. The page may be unresponsive, or your machine might be severely resource constrained. Error: ${ue?.message}`);return B}),T=x,R=!1,I=`data:image/jpeg;base64,${O.toString("base64")}`;T=await aa({type:"locator",description:y,screenshot:I,serializedTree:x,options:{aiPageFiltering:c},tree:P,fixtures:{generator:h,signal:f,logger:l,orgId:p}}),T!==x&&(R=!0);let k=await E.startAsyncSpan("AI_LOCATOR_CALL",async B=>{let j=await h.getElementLocation({browserState:T,goal:y,screenshot:I,source:a,memory:b?s:void 0},{disableCache:t,abortSignal:f,loggerTags:ye(l),useMemory:b});return B.result=j,j});if(l.debug({usedRag:R,result:k},"Got locator result"),!(k.id>0))throw new wo(`Could not find any relevant element: ${k.thoughts}`,k.updatedMemory?{type:"GCS_TRACES",traces:k.updatedMemory}:void 0);let{resolution:ee,target:K,frameConfig:ge}=await E.startAsyncSpan("TARGET_RESOLUTION",async B=>{let j=await m.createTargetFromA11yId({id:k.id,requirements:k.requirements,additionalElements:k.additionalElements,description:y,targetSource:"AI",logger:l,skipSavingVisualAttributes:d});return B.result={serializedElement:j.target.nodeOnlySerializedHtml??"Unknown HTML element"},j});if(ee.a11yNode?.properties?.hidden&&ee.a11yNode?.properties?.hidden!=="false")throw new w("ActionFailureError",`Momentic's AI found a relevant element to interact with, but it is explicitly marked with an 'aria-hidden' attribute. Please remove this attribute or adjust the element description to locate a different element. Element chosen: ${ee.displayString}`);return b&&(k.updatedMemory?K.memory={type:"GCS_TRACES",traces:k.updatedMemory}:s&&(K.memory=s)),{thoughts:k.thoughts,target:K,resolution:ee,frameConfig:ge,screenshot:I}}var q2=15;async function ip({command:r,aiPageFiltering:e,logger:t,fixtures:n,useMemory:o,maxRetries:i=q2}){if(!r.assertion.trim())throw new w("ActionFailureError","Assertion command is missing the assertion content");let a=th.optional().catch(void 0).parse(r.source);r.source&&!a&&t.warn(`Invalid source ${r.source} for AI assertion, ignoring...`);let{browser:s}=n,c=r.timeout?r.timeout*1e3:s.smartWaitingTimeout,l=lP(c,i-1),u=0,d=Date.now(),p=d+c,m=d,g,h,f;try{await an({action:()=>s.clearHighlights(),frameConfig:r.iframeUrl?{type:"url",url:r.iframeUrl}:void 0,browser:s,logger:t})}catch(y){t.warn({err:y},"Failed to clear highlights before AI check, continuing...")}for(;u<i;){n.abortSignal.throwIfAborted();let y=Date.now();if(u>0){if(y>=p)break;let x=p-y,P=m-y,O=Math.min(P,x);O>0&&await J(O,n.abortSignal)}let E=Date.now();if(u>0&&E>=p)break;let b=!1;try{if(g=await an({action:async()=>{let P=await iO(s,t,n.abortSignal);return h&&h.serializedTree===P.serializedTree&&h.screenshotBuff.equals(P.screenshotBuff)?(b=!0,g):(h=P,aO({command:r,state:P,fixtures:n,useMemory:o,useConsensus:!1,highlightElementsOnFailure:!1,attemptNumber:u,aiPageFiltering:e,logger:t,source:a}))},frameConfig:r.iframeUrl?{type:"url",url:r.iframeUrl}:void 0,logger:t,browser:s}),g?.success){g?.updatedMemory&&Xc(r,g.updatedMemory,t);break}else throw g?.thoughts?new w("AssertionFailureError",g.thoughts):new w("InternalPlatformError","No thoughts were provided for AI assertion failure")}catch(x){n.abortSignal.throwIfAborted(),f=x instanceof Error?x:new Error(`${x}`),b?t.info(`AI check attempt ${u} failed (re-used previous result)`):t.info({err:x},`AI check assert attempt ${u} failed, retrying...`)}finally{u++,m=E+l}}if(!g?.success){let y=p-Date.now();y>0&&await J(y,n.abortSignal)}if(!g?.success)try{g=await an({action:async()=>aO({command:r,state:await iO(s,t,n.abortSignal),fixtures:n,useMemory:o,useConsensus:!0,highlightElementsOnFailure:!0,attemptNumber:u,aiPageFiltering:e,logger:t}),frameConfig:r.iframeUrl?{type:"url",url:r.iframeUrl}:void 0,logger:t,browser:s})}catch(y){n.abortSignal.throwIfAborted(),f=y instanceof Error?y:new Error(`${y}`)}finally{u++}if(g?.updatedMemory&&Xc(r,g.updatedMemory,t),!g?.success){let y=`AI check still failing after ${u} attempts.`;throw f&&(y+=` Latest result: ${f.message}`),new w("AssertionFailureError",y)}return{...g,succeedImmediately:!1,urlAfterCommand:s.url()}}async function iO(r,e,t){let[n,o]=await Promise.all([jn(r,{abortSignal:t,skipWait:!0,skipWaitForPageLoad:!0,logger:e}),r.screenshot({retries:1,respectActiveFrame:!0})]);return{...n,screenshotBuff:o}}async function aO({command:r,state:e,fixtures:t,useConsensus:n,useMemory:o,highlightElementsOnFailure:i,aiPageFiltering:a,attemptNumber:s,source:c,logger:l}){let{browser:u,generator:d,abortSignal:p}=t,m={type:"ASSERTION"},{serializedTree:g,tree:h}=e,f=e.screenshotBuff,y=f.toString("base64"),E=u.url(),b=r.contextChoice??"MULTIMODAL",x=g;b!=="VISION_ONLY"&&(x=await aa({type:"assertion",serializedTree:g,tree:h,description:r.assertion,screenshot:y,options:{aiPageFiltering:a},fixtures:{generator:d,signal:p,logger:l,orgId:t.orgId}}),x!==g&&(m.ragUsed=!0),m.pageState=x);let P={goal:r.assertion,url:E,memory:o?r.cache?.memory:void 0,browserState:x,screenshot:y,contextChoice:b,source:c},T=await(b==="VISION_ONLY"?(R,D)=>d.getVisualAssertionResult(R,D):(R,D)=>d.getAssertionResult(R,D))(P,{useConsensus:n,attemptNumber:s,useMemory:o,disableCache:!!r.disableCache,abortSignal:p,logger:l,loggerTags:ye(l)});return(T.result||i)&&T.relevantElements&&(m.relevantElementsSerialized=T.relevantElements.map(R=>u.getSerializedFormFromA11yId(R)).filter(R=>!!R),await K2(T.relevantElements,u,l)),{success:T.result,thoughts:T.thoughts,afterScreenshotOverride:f,updatedMemory:o?T.updatedMemory:void 0}}async function K2(r,e,t){let n=Date.now();for(let o of r){if(Date.now()-n>2e3){t.debug("Highlighting relevant elements took over 2s, aborting...");return}try{let i=new AbortController;await Y(e.highlightA11yId(o),{milliseconds:1e3,fallback:()=>{throw i.abort(),new Error("Timed out waiting for highlighting to complete")}})}catch(i){t.debug({err:i},"Failed to highlight relevant element after assertion, continuing...");return}}}var Y2=1e5,ap=class extends Error{constructor(){super("The page content exceeds the maximum token limit for AI smart waiting."),this.name="ExceededMaxAISmartWaitingTokensError"}};async function sO(r,e){let{logger:t}=r,{abortSignal:n,browser:o}=e,i=Date.now();try{await X2(i,r,e)}catch(a){if(a instanceof Error&&(a.name==="AbortError"||a.name==="TimeoutError")||n.aborted)return;a instanceof ap?t.warn("Skipping AI smart waiting due to excessive page size - falling back to naive waiting"):t.warn({err:a},"Unexpected error occurred during AI smart waiting");let s=o.smartWaitingTimeout-(Date.now()-i);s>0&&await J(s,n)}finally{t.debug({durationMs:Date.now()-i},"AI smart waiting complete")}}async function X2(r,e,t){let{abortSignal:n,browser:o}=t;if(o.smartWaitingTimeout<3e3){await J(o.smartWaitingTimeout,n);return}if(!e.description)throw new w("UserConfigurationError","Cannot locate element with empty description");await Y(J2(r,e,t),{milliseconds:o.smartWaitingTimeout})}async function J2(r,e,t){let{logger:n,iframeUrl:o}=e,{browser:i}=t;for(;Date.now()-r<i.smartWaitingTimeout;)if(await an({action:async()=>Z2(e,t),frameConfig:o?{type:"url",url:o}:void 0,browser:i,logger:n}))return}async function Z2(r,e){let{testContext:t,logger:n,filterByViewport:o,allowNotActionableNodesOverride:i}=r,{browser:a,abortSignal:s,localCodeEvalTools:c,orgId:l,generator:u}=e,d=r.description;t&&(d=await Yc({orgId:l,s:d,context:t,localTools:c,signal:s,logger:n}));let{serializedTree:p}=await jn(a,{allowNotActionableNodesOverride:i,filterByViewport:o,abortSignal:s,logger:n});if(bn(p)>Y2)throw new ap;s.throwIfAborted();let g;try{g=await a.screenshot({clearHighlights:!0,respectActiveFrame:!0,retries:2})}catch(E){throw new w("ActionFailureError",`Failed to take screenshot of page to perform smart waiting. The page may be unresponsive, or your machine might be severely resource constrained. Error: ${E instanceof Error?E.message:E}`)}let f=`data:image/jpeg;base64,${g.toString("base64")}`;s.throwIfAborted();let y=await u.getSmartWaitingDecision({browserState:p,description:d,screenshot:f},{abortSignal:s,loggerTags:ye(n)});return n.debug({result:y},"Got smart waiting result"),y.isPageReady}import{cloneDeep as cO}from"lodash-es";async function uO(r){let{command:e,timeoutMs:t,fixtures:n}=r,{abortSignal:o}=n,i=()=>Pu(e.cache)?e.cache:void 0,a=i(),s=cO(a),c=(h=!1)=>{if(a=i(),!!a)if(h){let f=SM(s,a);a.target=f.target,a.updatedAt=f.updatedAt}else{if(!s){a=void 0;return}a.target=s.target,a.updatedAt=s.updatedAt}},l=Date.now(),u=0,d,p=500,m=!1;for(;u<2||Date.now()-l<t;){u++,u>1&&await J(p,o),o?.throwIfAborted(),a=i();let{result:h,elementWasFound:f}=await lO({cacheToUse:a,params:r});if(d=h,m=f,h.success)break;c(),p=Math.min(p*2,1e4)}if(!d)throw new w("InternalPlatformError",`Failed to evaluate manual element assertion in ${t}ms.`);if(o?.throwIfAborted(),!d.success&&a?.target&&Ta(a.target)){let h=a?.target?.memory?{target:{id:-1,memory:a.target.memory}}:void 0,{result:f}=await lO({cacheToUse:h,params:r});d=f,d.success||c(!0)}let g=i();return d.success&&g?.target&&!m&&(g.target=LS(g.target),g.updatedAt=new Date),d}async function lO({cacheToUse:r,params:e}){let{command:t,disableCache:n,fixtures:o,tracer:i,targetingWrapper:a}=e,{logger:s}=o;if(t.target&&!vo(t.target))throw new Error("Element assertion with x/y is not supported yet");let c=Om(t.assertion),l,u=!1,d=cO(r);try{let{elementInteractedDisplayString:p,result:m,thoughts:g}=await a({ctx:o.ctx,tracer:i,command:t,target:t.target,cache:d?.target,action:async h=>Q2(h.locator,e),options:{...t,allowNotActionableNodesOverride:!0,disableCache:n,memory:d?.target?.memory,disableGlobalLocatorRedirect:!0,source:Ol(t),targetName:"target"}});return l={success:m.success,data:m.data,err:m.err,elementInteractedDisplayString:p,thoughts:g},u=!0,m.success||(s.warn({aiThoughts:g,elementString:p,err:m.err},"Element check found an element but failed"),l={...m,thoughts:g}),{result:l,elementWasFound:u}}catch(p){if(c)return l={success:!0,thoughts:`The element described does not exist on the page: ${p.message}`,err:void 0,data:void 0},{result:l,elementWasFound:u};if(!(p instanceof w)||p.reason!="ActionFailureError")throw p;return l={success:!1,err:p,data:void 0,thoughts:void 0},s.warn({err:p},"Element check did not find an element and failed"),{result:l,elementWasFound:u}}}async function Q2(r,{command:e,fixtures:t}){return await t.browser.highlight(r),await eK(r,e.assertion)}async function eK(r,e){let t=!0,n,o;switch(e.type){case"ELEMENT_CONTENT":{let a=await r.textContent()??"";if(o={elementTextContent:Vt(a,500,!0)},!Un(a,e.value,e.operation,{negated:!!e.negated,ignoreCase:!1})){let s=tn(e);t=!1,n=new w("AssertionFailureError",`The content ${s} '${e.value}': ${a}`)}break}case"ELEMENT_ATTRIBUTE":{o={elementOuterHtml:Vt(await r.evaluate(s=>s.cloneNode(!1).outerHTML),500,!0)};let a=null;try{a=await r.getAttribute(e.attr,{timeout:3e3})}catch(s){n=new w("AssertionFailureError",s instanceof Error?s.message:String(s)),t=!1;break}if(!Un(a,e.value,e.operation,{negated:!!e.negated,ignoreCase:!1})){let s=tn(e);t=!1,e.operation==="EXISTS"?n=new w("AssertionFailureError",`The attribute ${e.attr} ${s}`):n=new w("AssertionFailureError",`The attribute ${e.attr} ${s} '${e.value}': ${a}`)}break}case"ELEMENT_EXISTENCE":{switch(e.condition){case"VISIBLE":{t=await r.evaluate(async(s,c)=>{let l=Date.now();for(;Date.now()-l<c;){await new Promise(d=>setTimeout(d,250));let u=s.getBoundingClientRect();if(!(u.width===0||u.height===0)&&window.getComputedStyle(s).visibility!=="hidden"&&window.getComputedStyle(s).display!=="none")return!0}return!1},dr*1e3);break}case"EDITABLE":{t=await r.isEditable({timeout:dr*1e3});break}case"EXISTS":{t=!0;break}case"ENABLED":{t=await r.isEnabled({timeout:dr*1e3});break}case"FOCUSED":{t=await r.evaluate(s=>s===document.activeElement);break}default:return(s=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(e.condition)}if(t=e.negated?!t:t,!t){let a=tn(e);n=new w("AssertionFailureError",`The element ${a}`)}break}case"ELEMENT_NAME":{let a=await r.evaluate(s=>s.tagName);if(!Un(a,e.value,e.operation,{negated:!!e.negated,ignoreCase:!0})){let s=tn(e);t=!1,n=new w("AssertionFailureError",`The element tag name ${s} '${e.value}': ${a}`)}break}case"ELEMENT_STYLE":{let a=await r.evaluate((s,c)=>window.getComputedStyle(s).getPropertyValue(c),e.property);if(!Un(a,e.value,e.operation,{negated:!!e.negated,ignoreCase:!1})){let s=tn(e);t=!1,e.operation==="EXISTS"?n=new w("AssertionFailureError",`The style property ${e.property} ${s}`):n=new w("AssertionFailureError",`The style property ${e.property} ${s} '${e.value}': ${a}`)}break}default:return(a=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(e)}return{thoughts:void 0,success:t,data:o,err:n}}function dO(r){return r.type==="ELEMENT_EXISTENCE"&&r.negated&&r.condition==="EXISTS"}import{Jimp as tK}from"jimp";async function au(r,e){let t=await r.screenshot(e),n=await tK.fromBuffer(t);return{buffer:t,width:Math.ceil(n.bitmap.width??0),height:Math.ceil(n.bitmap.height??0)}}import{Jimp as mO}from"jimp";import Dy from"jpeg-js";import rK from"pixelmatch";async function pO({ctx:r,tracer:e,command:t,disableCache:n,browser:o,targetingWrapper:i,logger:a,screenshotStorage:s}){if(t.target&&!vo(t.target))throw new Error("Visual Diff with x/y is not supported yet");await o.waitForStability({logger:a});let c={clearHighlights:!0,hideCaret:!0},l;t.target?.elementDescriptor?l=(await i({ctx:r,tracer:e,command:t,target:t.target,cache:t.cache?.target,action:async k=>au(o,{locator:k.locator,...c}),options:{...t,disableCache:n,disableGlobalLocatorRedirect:!0,memory:t.cache?.target?.memory,targetName:"target"}})).result:l=await au(o,c);let u=await s.prepareGoldenScreenshotForComparison(a,t,l);if((l.height!==u.height||l.width!==u.width)&&a.warn({currHeight:l.height,currWidth:l.width,savedHeight:u.height,savedWidth:u.width},"Mismatched before and after visual diff screenshot sizes"),Math.abs(l.height-u.height)>10||Math.abs(l.width-u.width)>10){let I=`${l.width}x${l.height}`,k=`${u.width}x${u.height}`;return{fail:!0,thoughts:`Current screenshot (${I}) does not match saved screenshot dimensions (${k}) - did you change the size of the target or the viewport?`,beforeScreenshotOverride:u.buffer,afterScreenshotOverride:l.buffer,succeedImmediately:!1,urlAfterCommand:o.url()}}let d=await mO.fromBuffer(l.buffer),p={width:l.width,height:l.height},m=await mO.fromBuffer(u.buffer),g={width:u.width,height:u.height},h,f=p.width*p.height,y=g.width*g.height,E=Math.abs(p.height-g.height),b=Math.abs(p.width-g.width);if(f>y){let I=d.cover({w:g.width,h:g.height});l.buffer=await I.getBuffer("image/jpeg"),h="current",l.width=g.width,l.height=g.height}else if(y>f){let I=m.cover({w:p.width,h:p.height});u.buffer=await I.getBuffer("image/jpeg"),h="saved"}let x={data:Buffer.alloc(l.width*l.height*4),width:l.width,height:l.height},P=t.threshold??.1,T=rK(Dy.decode(u.buffer).data,Dy.decode(l.buffer).data,x.data,l.width,l.height,{threshold:P,diffColorAlt:[0,255,0]})/(l.width*l.height)*100,R=T>P*100,D=`Visual diff of ${T.toFixed(2)}% detected, which is ${R?"over":"under"} the threshold of ${P*100}%.`;if(h&&(D+=` The ${h} screenshot was cropped since it was taller by ${E} pixels and wider by ${b} pixels.`),R)throw new w("ActionFailureError",D);return{fail:R,thoughts:D,beforeScreenshotOverride:l.buffer,afterScreenshotOverride:Dy.encode(x,75).data,succeedImmediately:!1,urlAfterCommand:o.url()}}var nK=3e4;function oK(r){if(!r.body)return{};switch(r.body.type){case"json":return{content:r.body.content,contentType:"application/json"};case"form-urlencoded":{let e=new URLSearchParams;return Object.entries(r.body.content).forEach(([t,n])=>{e.append(t,n)}),{content:e.toString(),contentType:"application/x-www-form-urlencoded;charset=UTF-8"}}}}async function sp({command:r,logger:e,baseUrl:t,fetchImplementation:n=fetch}){let o=r.timeout??nK/1e3,i=Object.fromEntries(Object.entries(r.headers||{}).filter(([g,h])=>g&&h)),a=new URLSearchParams;Object.entries(r.params||{}).filter(([g,h])=>g&&h).forEach(([g,h])=>{a.append(g,h)});let s=a.toString(),c;if(Is(r.url)&&(c=r.url),t&&Os(r.url,t)&&(c=new URL(r.url,t).toString()),!c)throw new w("ActionFailureError",`Invalid URL: ${r.url}`);let l=c;e.info({url:l,searchParams:s,headers:i,body:r.body,method:r.method},"Making HTTP request");let d=await Y((async()=>{let g=s?`${l}?${s}`:l;try{let h=oK(r),f=new Headers(i);return h.contentType&&!f.has("Content-Type")&&f.set("Content-Type",h.contentType),await n(g,{headers:f,method:r.method,body:h.content})}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 w("ActionFailureError",`Fetch request timed out after ${o} seconds`)}});if(!d.ok){let g;try{g=await d.text()}catch(h){g=`Failed to read response body: ${h}`}throw new w("ActionFailureError",`Fetch request failed with status ${d.status}: ${g}`)}let p={};d.headers.forEach((g,h)=>{p[h]=g});let m={status:d.status,headers:p,request:{url:d.url,method:r.method,headers:i}};if(r.body?.type==="json"&&r.body.content)try{m.request.json=JSON.parse(r.body.content)}catch{}if(d.headers.get("content-type")?.includes("json"))try{m.json=await d.json()}catch{}else d.headers.get("content-type")?.includes("text")&&(m.text=await d.text());return m}var iK=5e3;async function hO({timeout:r=dr,...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 c=Date.now();i=await lp(e),a=Date.now();let l=a-c;if(l>1e3&&e.logger.warn({pageAssertDuration:l},"Page assertion took longer than expected"),!i.success)await J(s,e.signal),s=Math.min(Math.floor(s*1.5),iK);else return i}return i=await lp(e),i}async function lp({assertion:r,browser:e,autoExpandIframes:t}){switch(r.type){case"CONTENT":case"CONTENT":{let o,i=!1,a;try{let s;if(t){let c=await e.evaluateFunctionInAllFrames(gO,{value:r.value,negated:!!r.negated,returnHtml:!1});i=r.negated?c.every(l=>l.evaluation):c.some(l=>l.evaluation),s=c.find(l=>l.pageHtml)?.pageHtml}else({evaluation:i,pageHtml:s}=await e.evaluateFunctionInPage(gO,{value:r.value,negated:!!r.negated,returnHtml:!0},"checking page content"));if(!i){let c=r.negated?uo.CONTAINS:mo.CONTAINS;a=new w("AssertionFailureError",`The page ${c} '${r.value}'.`),o=s}}catch(s){a=new w("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)}}function gO({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 aK=3e4;async function fO({command:r,logger:e,baseUrl:t,fetchImplementation:n=fetch}){let o=r.timeout??aK/1e3,i=new AbortController,a=Object.fromEntries(Object.entries(r.headers||{}).filter(([d,p])=>d&&p));a["Content-Type"]="application/json";let s;if(Is(r.url)&&(s=r.url),t&&Os(r.url,t)&&(s=new URL(r.url,t).toString()),!s)throw new w("ActionFailureError",`Invalid URL: ${r.url}`);let l=await Y((async()=>{try{return await n(s,{headers:a,method:"POST",body:JSON.stringify({query:r.query,variables:r.variables?JSON.parse(r.variables):void 0}),signal:i.signal})}catch(d){e.error({err:d},"Failed to make HTTP request")}})(),{milliseconds:o*1e3});if(!l)throw new w("ActionFailureError",`GraphQL request timed out after ${o} seconds`);if(!l.ok){let d,p=await l.text();try{d=JSON.parse(p)}catch{throw new w("ActionFailureError",`GraphQL request failed with status ${l.status}: ${p}`)}throw d?.errors?.length&&d?.errors[0]?.message?new w("ActionFailureError",`GraphQL request failed with status ${l.status}: ${d.errors[0].message}`):new w("ActionFailureError",`GraphQL request failed with status ${l.status}: ${p}`)}let u={};return l.headers.forEach((d,p)=>{u[p]=d}),{status:l.status,headers:u,json:await l.json()}}var cp=class{orgId;options;storage;localCodeEvalTools;uploadedFileStorage;visualDiffScreenshotStorage;browser;generator;executeAbortController=new AbortController;logger;recordAbortController=null;registeredListeners={};recordedRequests={};constructor({browser:e,generator:t,logger:n,storage:o,orgId:i,localCodeEvalTools:a,uploadedFileStorage:s,visualDiffScreenshotStorage:c,options:l}){this.orgId=i,this.options=l,this.browser=e,this.browser.registerAbortSignal(this.executeAbortController.signal),this.storage=o,this.uploadedFileStorage=s,this.visualDiffScreenshotStorage=c,this.localCodeEvalTools=a,this.generator=t,this.logger=n}setOpen(){this.executeAbortController=new AbortController,this.browser.registerAbortSignal(this.executeAbortController.signal)}setClosed(){this.executeAbortController.abort()}throwIfClosed(){this.executeAbortController.signal.throwIfAborted()}get closed(){return this.executeAbortController.signal.aborted}async evaluateAiAction({goal:e,startingScreenshot:t,history:n,disableCache:o,langfuseSessionId:i,lastError:a,logger:s=this.logger}){let[c,l]=await Promise.all([jn(this.browser,{abortSignal:this.executeAbortController.signal,skipWait:!0,skipWaitForPageLoad:!0,logger:s}),this.browser.screenshot({retries:1,clearHighlights:!0})]),u=`data:image/jpeg;base64,${l.toString("base64")}`,d=await aa({type:"ai-action",description:e,screenshot:u,serializedTree:c.serializedTree,tree:c.tree,options:{aiPageFiltering:!!this.options?.aiPageFiltering},fixtures:{generator:this.generator,signal:this.executeAbortController.signal,logger:s,orgId:this.orgId}}),p={url:this.browser.url(),browserState:d,startingScreenshot:t,history:n,goal:e,screenshot:u,lastError:a};return await this.generator.getMultiturnAiActionEvaluation(p,{disableCache:o,abortSignal:this.executeAbortController.signal,loggerTags:{...ye(s)},langfuseSessionId:i})}async promptToCommand({goal:e,startingScreenshot:t,history:n,actionHint:o,disableCache:i,logger:a=this.logger,langfuseSessionId:s}){let c=this.browser.url(),[l,u]=await Promise.all([jn(this.browser,{abortSignal:this.executeAbortController.signal,skipWait:!0,skipWaitForPageLoad:!0,logger:a}),this.browser.screenshot({retries:1,clearHighlights:!0})]),d=`data:image/jpeg;base64,${u.toString("base64")}`,p=await aa({type:"ai-action",description:e,screenshot:d,serializedTree:l.serializedTree,tree:l.tree,options:{aiPageFiltering:!!this.options?.aiPageFiltering},fixtures:{generator:this.generator,signal:this.executeAbortController.signal,logger:a,orgId:this.orgId}}),m={url:c,browserState:p,startingScreenshot:t,history:n,goal:e,actionHint:o,screenshot:d};try{return await this.generator.getMultiturnAiActionCommand(m,{disableCache:i,abortSignal:this.executeAbortController.signal,loggerTags:{...ye(a)},langfuseSessionId:s})}catch(g){throw new w("InternalWebAgentError",`Error generating command: ${g instanceof Error?g.message:g}`,{errOptions:{cause:g}})}}async getBrowserState(e){return jn(this.browser,e)}async locateElement(e){return await Ny({...e,aiPageFiltering:!!this.options?.aiPageFiltering},this.getControllerFixtures())}async locateElementWithSelector(e,t){return an({action:async()=>{let n=await this.browser.resolveHardcodedCssSelector({ctx:null,selector:e,timeoutMs:2e3,logger:this.logger});return{thoughts:"Located element with selector",target:{id:-1,selector:e,targetSource:"USER_CSS_SELECTOR",targetUpdateTime:new Date().toUTCString()},resolution:n}},frameConfig:t?{type:"url",url:t}:void 0,browser:this.browser,logger:this.logger})}getControllerFixtures(e){return{ctx:e??null,browser:this.browser,generator:this.generator,logger:this.logger,orgId:this.orgId,storage:this.storage,localCodeEvalTools:this.localCodeEvalTools,abortSignal:this.executeAbortController.signal}}shouldUseMemory(){return this.options?.useMemory??(this.orgId==="org_01HMSCJQBCCG51M2ZF65YC5B8W"||this.orgId==="org_01HMJTX4GT1KG94KZRCT8MZ6YB")}async wrapMultiElementTargetingCommand({ctx:e,tracer:t,command:n,targetNames:o,descriptions:i,caches:a,action:s,options:c,retriesWithAI:l=1}){let u=[];for(let d=0;d<i.length;d++){let p=i[d],m=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:p,cache:a[d],action:async g=>g,options:{...c,targetName:o[d]}});u.push(m)}try{let d=await s(...u.map(g=>g.result)),p=g=>g==="fromTarget"?"From Target":g==="toTarget"?"To Target":"Target",m=u.map((g,h)=>g.thoughts?`${p(o[h])}: ${g.thoughts}`:void 0).filter(g=>!!g).join(" -------------- ")||void 0;return{result:d,elementInteractedDisplayStrings:u.map(g=>g.elementInteractedDisplayString),thoughts:m}}catch(d){if(this.throwIfClosed(),l>0)return this.logger.warn({err:d},"Failed to execute action with multiple cached targets, retrying with AI"),this.wrapMultiElementTargetingCommand({ctx:e,tracer:t,command:n,targetNames:o,descriptions:i,caches:i.map(()=>{}),action:s,options:c,retriesWithAI:l-1});throw new w("ActionFailureError",d.message,{errOptions:{cause:d}})}}async wrapHardcodedCssTargetingCommandHelper({ctx:e,target:t,action:n,options:o,command:i}){let a=this.logger.child({commandId:i.id}),{targetName:s}=o;if(t.type!=="description")throw new w("ActionFailureError","Cannot use selector with non-description target");let c,l=Date.now(),u=Date.now();for(;Date.now()-u<this.browser.smartWaitingTimeout;){l=Date.now();try{let d=await this.browser.resolveHardcodedCssSelector({ctx:e,selector:t.elementDescriptor,targetName:s,logger:a});return{result:await n({locator:d.locator,originalElementLocationResult:void 0,serverSideBoundingBox:null}),elementInteractedDisplayString:d.displayString}}catch(d){if(d.name==="AbortError")throw d;c=d,a.warn({err:d},"Failed to action on hardcoded css selector"),Date.now()-l<500&&await J(500)}}throw c}async resolveCachedTargetForAction(e){let{ctx:t,cache:n,options:o,logger:i}=e,a=Ds(),s=await a.startAsyncSpan("CACHE_RESOLUTION",async l=>{let u=await this.browser.resolveTarget(t,n,{allowNotActionableNodesOverride:o.allowNotActionableNodesOverride,logger:i,signal:this.executeAbortController.signal,...o.resolveTargetOptions});return l.attributes.targetDisplayString=u.displayString,u});(this.browser.userBrowserSettings.visualActions||this.browser.userBrowserSettings.globalLocatorRedirect!==!1)&&await a.startAsyncSpan("SCROLL_ELEMENT_INTO_VIEW",async()=>{await this.browser.scrollIntoViewIfNeeded(s.locator)});let c;return!o.disableGlobalLocatorRedirect&&this.browser.userBrowserSettings.globalLocatorRedirect!==!1&&(c=await a.startAsyncSpan("LOCATOR_REDIRECT",async()=>this.browser.performTargetRedirection(s,i))),c||(c={locator:s.locator,serverSideBoundingBox:await s.locator.boundingBox({timeout:ne}),originalElementLocationResult:s.originalElementLocationResult}),await s.revalidator?.(),{resolutionResult:s,finalTarget:c}}async wrapElementTargetingCommand(e){return await an({action:()=>this.wrapElementTargetingCommandHelper(e),frameConfig:e.options.iframeUrl?{type:"url",url:e.options.iframeUrl}:void 0,browser:this.browser,logger:this.logger})}async wrapElementTargetingCommandHelper(e){let{ctx:t,tracer:n,target:o,action:i,options:a,command:s,finalAttempt:c=!1,originalCache:l=e.cache}=e,{retriesWithAI:u=1}=e,{disableCache:d,useSelector:p,targetName:m,targetHealingInProgress:g,source:h}=a,f=Ds(),y=this.logger.child({commandId:s.id}),E=this.shouldUseMemory(),b=SO(e.cache);if((!b||d)&&!fg(o))throw new w("ActionFailureError","Cannot target element with no cached data or element descriptor");if(p)return this.wrapHardcodedCssTargetingCommandHelper(e);let x=!1;d&&(y.info("Cache explicitly disabled for this step"),x=!0,b=void 0);let P=eO({cache:b,description:o.elementDescriptor,disableSecondaryCacheResolution:!!this.browser.userBrowserSettings.disableSecondaryCacheResolution,logger:y});b=P.cache,x=x||P.cacheBustedBeforeAction;let O=!0;if(!QI(b)){O=!1,y.info({description:o.elementDescriptor,targetHealingInProgress:g,cacheBustedBeforeAction:x,memory:a.memory,useMemory:E},"Prompting AI for an updated element location"),(x||!l)&&await f.startAsyncSpan("SMART_WAITING",async()=>await sO({description:o.elementDescriptor,iframeUrl:a.iframeUrl,source:h,logger:y,allowNotActionableNodesOverride:a.allowNotActionableNodesOverride},this.getControllerFixtures(t))),u--;let T;try{T=await Ny({description:o.elementDescriptor,disableCache:!!a.disableCache,iframeUrl:a.iframeUrl,source:h,useMemory:E,memory:E?a.memory:void 0,aiPageFiltering:!!this.options?.aiPageFiltering,allowNotActionableNodesOverride:a.allowNotActionableNodesOverride,logger:y},this.getControllerFixtures(t))}catch(I){if(I instanceof wo&&I.updatedLocatorMemory){let k={id:-1,...l,memory:I.updatedLocatorMemory};Nm({cmd:s,key:m,newTarget:k,logger:y,updatedWithAI:!0})}throw new w("ActionFailureError",I.message)}T.frameConfig&&this.browser.setActiveFrameConfig(T.frameConfig);let R;!a.disableGlobalLocatorRedirect&&this.browser.userBrowserSettings.globalLocatorRedirect!==!1&&(R=await f.startAsyncSpan("LOCATOR_REDIRECT",async()=>this.browser.performTargetRedirection(T.resolution,y))),R||(R={locator:T.resolution.locator,serverSideBoundingBox:await T.resolution.locator.boundingBox({timeout:ne}),originalElementLocationResult:T.resolution.originalElementLocationResult});let D=await i(R);return Nm({cmd:s,key:m,newTarget:T.target,logger:y,updatedWithAI:!0}),g&&(n.recordTargetAutoHeal({healType:"AI"}),T.target.targetSource="AI_HEALED",T.target.targetUpdateTime=new Date().toUTCString(),T.target.targetUpdateLoggerTags=ye(y)),{result:D,elementInteractedDisplayString:T.resolution.displayString,thoughts:T.thoughts}}try{let{resolutionResult:T,finalTarget:R}=await this.resolveCachedTargetForAction({ctx:t,cache:b,options:a,logger:y}),D=await i(R);if(nt.increment("cache_target_resolution_v2",1,["outcome:hit","platform:web",`hasRequirements:${!!b.requirements}`,`hasAdditionalElements:${!!b.additionalElements}`,`orgId:${this.orgId}`,"cliVersion:0.33.0"]),Nm({cmd:s,key:m,newTarget:b,logger:y,updatedWithAI:!1}),O){let I=T.decisions.filter(k=>k.matched);if(I.length!==1)y.warn({decisions:T.decisions},"Expected exactly 1 matching method for element location, got more or less");else{let k=I[0].type;n.recordTargetAutoHeal({healType:k})}}return{result:D,elementInteractedDisplayString:T.displayString}}catch(T){if(this.throwIfClosed(),(T instanceof to||ET(T)||AT(T)||wT(T)||bT(T)||TT(T)||vT(T))&&!c)return this.wrapElementTargetingCommandHelper({ctx:t,tracer:n,command:s,target:o,action:i,cache:l,originalCache:l,retriesWithAI:u,finalAttempt:!0,options:a});if(T instanceof w)throw y.error({err:T},"Failed to execute command with target (fatal)"),T;if(u>0&&o){y.info({err:T},"Failed to execute action with cached target, retrying with AI"),nt.increment("cache_target_resolution_v2",1,["outcome:miss","platform:web",`hasRequirements:${!!b.requirements}`,`hasAdditionalElements:${!!b.additionalElements}`,`orgId:${this.orgId}`,"cliVersion:0.33.0",`missReason:${T instanceof gt?T.cacheMissReason:"unknown"}`]);let D;return b.memory&&uE(b.memory)&&(D=b.memory),this.wrapElementTargetingCommandHelper({ctx:t,tracer:n,command:s,target:o,cache:void 0,action:i,originalCache:l,retriesWithAI:u,finalAttempt:!0,options:{...a,memory:D,targetHealingInProgress:!0}})}throw new w("ActionFailureError",`Failed to execute interactive command: ${T instanceof Error?T.message:`${T}`}`,{errOptions:{cause:T}})}}async screenshotWithDimensions(e){return au(this.browser,e)}async executePresetCommand(e,t,n,o,i){this.options?.slowMoMs&&await J(this.options.slowMoMs);let a=await this.browser.getOpenPages(),s=this.browser.url(),c;try{c=await this.resolveCommandTemplateStrings(n,o)}catch(l){throw this.throwIfClosed(),new w("ActionFailureError",`Failed to substitute template strings in command: ${l.message}`,{errOptions:{cause:l}})}try{let l=await this.executePresetCommandHelper(e,t,n,o,i);return this.options?.autoFollowNewTabs&&await ZI({beforeUrl:s,command:n,beforePages:a.map(u=>u.url),browser:this.browser,logger:this.logger}),l}catch(l){throw l.name!=="AbortError"&&this.logger.error({err:l},"Error thrown in action controller"),l}finally{Ms(n,c)}}createCallbacksForBrowser(e){return{createIsolatedFolder:()=>oy(e)}}async resolveCommandTemplateStrings(e,t){return _s({obj:e,context:t,bannedKeys:["type","a11yData","thoughts","cache","code"],orgId:this.orgId,logger:this.logger,signal:this.executeAbortController.signal,localTools:this.localCodeEvalTools})}async executePresetCommandHelper(e,t,n,o,i){i=i||"disableCache"in n&&!!n.disableCache;let a=this.logger.child({commandId:n.id});switch(n.type){case"SUCCESS":let s=n.condition;return s?.assertion.trim()?ip({command:s,fixtures:this.getControllerFixtures(e),useMemory:this.shouldUseMemory(),aiPageFiltering:!!this.options?.aiPageFiltering,logger:a}):{succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"AI_ASSERTION":{if(!n.assertion.trim())throw new w("ActionFailureError","Missing assertion");if(n.timeout&&n.timeout>1800)throw new w("AssertionFailureError",`AI check timeout of ${n.timeout} exceeds the maximum allowed value of 30 minutes.`);return ip({command:n,fixtures:this.getControllerFixtures(e),useMemory:this.shouldUseMemory(),aiPageFiltering:!!this.options?.aiPageFiltering,logger:a})}case"AI_EXTRACT":{if(!n.goal.trim())throw new w("ActionFailureError","Cannot perform AI extraction without goal");if(n.schema){let h=nR(n.schema);if(h)throw new w("UserConfigurationError",h)}let m=await this.browser.getCondensedHtml(),g=await this.browser.screenshot({retries:2});try{let h=await this.generator.getTextExtraction({goal:n.goal,browserState:m,returnSchema:n.schema,screenshot:`data:image/jpeg;base64,${g.toString("base64")}`},{disableCache:i,abortSignal:this.executeAbortController.signal,loggerTags:ye(a)});if(h.result==="NOT_FOUND")throw new w("ActionFailureError","No relevant data found for extraction goal on this page");if(h.thoughts?.includes("MaxGenerationLengthExceededError"))throw new w("UserConfigurationError",h.thoughts);return{thoughts:h.thoughts||void 0,data:h.result,succeedImmediately:!1,urlAfterCommand:this.browser.url()}}catch(h){let f=h.message;throw f.includes("MaxGenerationLengthExceededError")?new w("UserConfigurationError","You tried to extract too much data. Please rephrase your query to limit the results returned or use a JavaScript step in the browser instead."):f.includes("AIProviderError")&&f.includes("time")?new w("AIProviderError","The AI provider responded with an error. This may be because you tried to extract too much data. Please limit extraction results to 2000 characters.",{errOptions:{cause:h}}):h}}case"NAVIGATE":if(!Is(n.url)&&!Os(n.url,this.browser.baseUrl))throw new w("ActionFailureError",`Invalid URL provided to navigate command: ${n.url}`);await this.browser.navigate({url:n.url,loadTimeoutMs:n.loadTimeout?n.loadTimeout*1e3:void 0});break;case"DIALOG":this.browser.registerDialogHandler(n.action);break;case"CAPTCHA":throw new w("UserConfigurationError","Captcha solving is no longer available on Momentic");case"GO_BACK":await this.browser.goBack();break;case"GO_FORWARD":await this.browser.goForward();break;case"SCROLL_LEFT":case"SCROLL_RIGHT":case"SCROLL_DOWN":case"SCROLL_UP":{let m,g;if(n.target&&An(n.target))await this.browser.hoverUsingVisualCoordinates(n.target.pixels);else if(n.target&&n.target.elementDescriptor.trim()){let{elementInteractedDisplayString:y,thoughts:E}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:n.target,cache:n.cache?.target,action:b=>this.browser.hover(b),options:{...n,targetName:"target",disableGlobalLocatorRedirect:!0,disableCache:i}});m=y,g=E}let h=this.browser.getViewport()?.height??Mo.height,f=this.browser.getViewport()?.width??Mo.width;switch(n.type){case"SCROLL_UP":await this.browser.scrollVertical(-(n.deltaY??h));break;case"SCROLL_DOWN":await this.browser.scrollVertical(n.deltaY??h);break;case"SCROLL_LEFT":await this.browser.scrollHorizontal(-(n.deltaX??f));break;case"SCROLL_RIGHT":await this.browser.scrollHorizontal(n.deltaX??f);break}return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m,thoughts:g}}case"WAIT_FOR_URL":{if(n.timeout&&n.timeout>1800)throw new w("UserConfigurationError",`Wait for URL timeout of ${n.timeout} exceeds the maximum allowed value of 30 minutes.`);let m=n.matcher;await this.browser.waitForUrl({beforeUrl:this.browser.url(),matcher:m},{timeout:n.timeout?n.timeout*1e3:void 0,negated:n.negated,caseInsensitive:n.caseInsensitive});break}case"WAIT":if(n.delay>1800)throw new w("UserConfigurationError",`Wait timeout of ${n.delay} seconds exceeds the maximum allowed value of 30 minutes`);let c=n.delay*1e3;await J(c,this.executeAbortController.signal);break;case"REFRESH":await this.browser.refresh({loadTimeoutMs:n.loadTimeout?n.loadTimeout*1e3:void 0});break;case"CLICK":{if(An(n.target)){await this.browser.clickUsingVisualCoordinates(n.target.pixels,n);break}let m=this.browser.url(),{elementInteractedDisplayString:g,result:h,thoughts:f}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,target:n.target,command:n,cache:n.cache?.target,action:E=>this.browser.click(E,this.createCallbacksForBrowser(this.orgId),n),options:{disableCache:i,targetName:"target",...n}}),y={urlAfterCommand:this.browser.url(),succeedImmediately:!1,elementInteracted:g,thoughts:f,data:h.downloadedFile?{downloadedFile:h.downloadedFile}:void 0};return Hm(m,y.urlAfterCommand)&&(y.succeedImmediately=!0,y.succeedImmediatelyReason="URL changed"),y}case"COPY":return await this.browser.copy(n.value),{succeedImmediately:!1,data:n.value,urlAfterCommand:this.browser.url()};case"PASTE":{await this.browser.paste();break}case"DRAG":{if(An(n.fromTarget)&&An(n.toTarget)){await this.browser.dragAndDropUsingVisualCoordinates(n.fromTarget.pixels,n.toTarget.pixels,{hoverDurationMs:n.hoverSeconds?n.hoverSeconds*1e3:void 0});break}if(An(n.fromTarget)||An(n.toTarget))throw new Error("Drag and drop targets must be both coordinates or both descriptions");let{elementInteractedDisplayStrings:m,thoughts:g}=await this.wrapMultiElementTargetingCommand({ctx:e,tracer:t,command:n,targetNames:["fromTarget","toTarget"],descriptions:[n.fromTarget,n.toTarget],caches:[n.cache?.fromTarget,n.cache?.toTarget],action:(h,f)=>this.browser.dragAndDrop(h,f,{hoverDurationMs:n.hoverSeconds?n.hoverSeconds*1e3:void 0,steps:n.steps}),options:{useSelector:!!n.useSelector,disableCache:i}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m[0],thoughts:g}}case"MOUSE_DRAG":{let m=parseInt(n.deltaX),g=parseInt(n.deltaY),h=n.steps??5;if(isNaN(m)||isNaN(g))throw new w("ActionFailureError",`Invalid pixel values passed to mouse drag command: (${n.deltaX}, ${n.deltaY})`);if(n.target&&An(n.target)){await this.browser.mouseDragUsingVisualCoordinates({deltaX:m,deltaY:g,steps:h,fromTarget:n.target.pixels});break}let f,y;if(n.target?.elementDescriptor){let{elementInteractedDisplayString:E,thoughts:b}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:n.target,cache:n.cache?.target,action:async x=>this.browser.mouseDrag(m,g,h,x.locator,{force:n.force}),options:{disableCache:i,targetName:"target",...n}});f=E,y=b}else await this.browser.mouseDrag(m,g,h,void 0,{force:n.force});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:f,thoughts:y}}case"SELECT_OPTION":{if(!vo(n.target))throw new Error("Select with x/y is not supported yet");let m=n.target.elementDescriptor,g=n.choice,{elementInteractedDisplayString:h,thoughts:f}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:{type:"description",elementDescriptor:m},cache:n.cache?.target,action:y=>this.browser.selectOption(y,g,n.force),options:{...n,targetName:"target",disableCache:i,source:Ol(n)}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:h,thoughts:f}}case"TAB":{let m={loadTimeoutMs:n.loadTimeout?n.loadTimeout*1e3:void 0,retry:!0};await this.browser.switchToPage(n.action,m);break}case"NEW_TAB":await this.browser.createNewTab(n.url,{loadTimeoutMs:n.loadTimeout?n.loadTimeout*1e3:void 0});break;case"COOKIE":if(!n.value)break;let l=await this.browser.setCookie(n.value);a.debug({results:l},"Set cookies");break;case"LOCAL_STORAGE":if(!n.value||!n.key)break;await this.browser.setLocalStorage(n.key,n.value);break;case"JAVASCRIPT":{let m;try{n.environment==="BROWSER"?(m=await this.browser.evaluateCodeInPage({code:n.code,fragment:n.fragment??!1,context:o.toObjectCopy(),timeoutMs:n.timeout?n.timeout*1e3:void 0}),a.info({result:m},"Executed JavaScript in browser")):m=await Fn({orgId:this.orgId,code:n.code,fragment:!!n.fragment,context:o,timeoutMs:n.timeout?n.timeout*1e3:void 0,logger:a,localTools:this.localCodeEvalTools,signal:this.executeAbortController.signal,callbacks:{onPersistentVariableUpdates:async g=>{if(!this.options?.scratchPadId){a.warn({updates:g},"Got persistent variable updates but scratch pad is not available");return}await this.storage.savePersistentVariables?.({scratchPadId:this.options?.scratchPadId,orgId:this.orgId,updates:g,logger:a})}}})}catch(g){throw this.throwIfClosed(),new w("ActionFailureError",g instanceof Error?g.message:`${g}`,{errOptions:{cause:g}})}try{JSON.stringify(m)}catch(g){throw new w("ActionFailureError",`Return value is not serializable: ${g instanceof Error?g.message:`${g}`}`,{errOptions:{cause:g}})}return{urlAfterCommand:this.browser.url(),succeedImmediately:!1,data:m}}case"TYPE":{if(n.target&&An(n.target)){await this.browser.clickUsingVisualCoordinates(n.target.pixels,n),await this.browser.type(n.value,{force:n.force,clearContent:n.clearContent,forceClearContent:n.forceClearContent,delay:n.delay,pressEnter:n.pressEnter},!0);break}let m=this.browser.url(),g,h,f=SO(n.target),y=this.browser.userBrowserSettings.globalLocatorRedirect===void 0||this.browser.userBrowserSettings.globalLocatorRedirect==="always";if(f){let{elementInteractedDisplayString:b,thoughts:x}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:f,cache:n.cache?.target,action:P=>this.browser.typeIntoTarget(n.value,P,{force:n.force,clearContent:n.clearContent,forceClearContent:n.forceClearContent,delay:n.delay,pressEnter:n.pressEnter,relativePosition:n.relativePosition}),options:{...n,targetName:"target",disableCache:i,disableGlobalLocatorRedirect:!y,source:Ol(n)}});g=b,h=x}else await this.browser.type(n.value,{force:n.force,clearContent:n.clearContent,forceClearContent:n.forceClearContent,delay:n.delay,pressEnter:n.pressEnter},!0);let E={urlAfterCommand:this.browser.url(),succeedImmediately:!1,elementInteracted:g,thoughts:h};return Hm(m,E.urlAfterCommand)&&(E.succeedImmediately=!0,E.succeedImmediatelyReason="URL changed"),E}case"HOVER":{if(An(n.target)){await this.browser.hoverUsingVisualCoordinates(n.target.pixels);break}let{elementInteractedDisplayString:m,thoughts:g}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:n.target,cache:n.cache?.target,action:h=>this.browser.hover(h),options:{...n,targetName:"target",disableCache:i}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m,thoughts:g}}case"FOCUS":{if(!vo(n.target))throw new Error("Focus with x/y is not supported yet");let{elementInteractedDisplayString:m,thoughts:g}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:n.target,cache:n.cache?.target,action:h=>this.browser.focus(h),options:{...n,targetName:"target",disableCache:i}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m,thoughts:g}}case"BLUR":{if(n.target&&!vo(n.target))throw new Error("Blur with x/y is not supported yet");if(!n.target||!n.target.elementDescriptor)return await this.browser.blur(null),{succeedImmediately:!1,urlAfterCommand:this.browser.url()};let{elementInteractedDisplayString:m,thoughts:g}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,target:n.target,command:n,cache:n.cache?.target,action:h=>this.browser.blur(h),options:{...n,targetName:"target",disableCache:i}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m,thoughts:g}}case"PRESS":let u=this.browser.url();await this.browser.press(n.value,{repeat:n.repeat,convertMeta:n.convertMeta??!0,delayMs:n.delayMs});let d={urlAfterCommand:this.browser.url(),succeedImmediately:!1};return Hm(u,d.urlAfterCommand)&&(d.succeedImmediately=!0,d.succeedImmediatelyReason="URL changed"),d;case"KEY_DOWN":return await this.browser.keyDown(n.value,{convertMeta:n.convertMeta??!0}),{urlAfterCommand:this.browser.url(),succeedImmediately:!1};case"KEY_UP":return await this.browser.keyUp(n.value,{convertMeta:n.convertMeta??!0}),{urlAfterCommand:this.browser.url(),succeedImmediately:!1};case"REQUEST":{let m=new lK,g=sK(fetch,m),h;try{h=new URL(n.url).hostname}catch{}let f=await sp({command:n,baseUrl:this.browser.baseUrl,logger:a,fetchImplementation:g});return{data:bl.parse({...f,cookies:ud(m,h)}),succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"GRAPHQL_REQUEST":return{data:await fO({command:n,baseUrl:this.browser.baseUrl,logger:a}),succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"VISUAL_DIFF":return pO({ctx:e,tracer:t,command:n,disableCache:i,browser:this.browser,logger:a,screenshotStorage:this.visualDiffScreenshotStorage,targetingWrapper:m=>this.wrapElementTargetingCommand(m)});case"FILE_UPLOAD":{let m,g;if(n.fileSource.type==="URL"?(g=n.fileSource.url,m=await _P({uri:n.fileSource.url,logger:a,orgId:this.orgId})):n.fileSource.type==="USER_FILE"&&(g=n.fileSource.name,m=await this.uploadedFileStorage?.getFileForUpload(n.fileSource.name,this.orgId)),!m)throw new w("UserConfigurationError",`Attempted to use non-existent file for upload step: ${g}`);await this.browser.setFileChooserHandler({...m,filename:n.filename});break}case"AUTH_SAVE":return{data:await this.browser.saveAuthState(),succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"AUTH_LOAD":{let m;if(!n.storageState.trim())m=void 0;else if(m=await Fn({orgId:this.orgId,code:n.storageState,fragment:!1,context:o,logger:a,localTools:this.localCodeEvalTools,signal:this.executeAbortController.signal}),typeof m!="object")throw new w("ActionFailureError",`Credentials must evaluate to an object (received ${typeof m} instead)`);let g;try{g=lA.optional().parse(m)}catch(h){throw new w("ActionFailureError",`Credentials provided do not follow the required format: ${h}`)}await this.browser.loadAuthState(g);break}case"ELEMENT_CHECK":{let m=(n.timeout??dr)*1e3,g=this.generator.getAgentConfig()?.assertion;if(dO(n.assertion)&&!n.useSelector&&n.target.type==="description"&&g&&g!=="v1"){let f={id:n.id,type:"AI_ASSERTION",assertion:`There is no element on the page closely matches the following description. If the description has single quotes, remember that requires an exact text substring match. Description: ${n.target.elementDescriptor}`,iframeUrl:n.iframeUrl,timeout:n.timeout,source:"NEGATED_CHECK",cache:n.cache&&"memory"in n.cache?{memory:n.cache?.memory}:void 0};try{let y=await ip({command:f,logger:a,aiPageFiltering:!!this.options?.aiPageFiltering,fixtures:this.getControllerFixtures(e),useMemory:this.shouldUseMemory()});return{succeedImmediately:!1,thoughts:`The element described does not exist on the page: ${y.thoughts}`,urlAfterCommand:this.browser.url(),afterScreenshotOverride:y.afterScreenshotOverride}}finally{f.cache?.memory&&Xc(n,f.cache?.memory.traces,a)}}let h=await uO({command:n,tracer:t,timeoutMs:m,targetingWrapper:f=>this.wrapElementTargetingCommand(f),fixtures:this.getControllerFixtures(e),disableCache:i});return{fail:!h.success,data:h.data,elementInteracted:h.elementInteractedDisplayString,thoughts:h.err?.message??h.thoughts??`Element assertion ${h.success?"succeeded":"failed"}.`,succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"PAGE_CHECK":{let m=await an({action:async()=>hO({assertion:n.assertion,browser:this.browser,logger:a,timeout:n.timeout,signal:this.executeAbortController.signal,autoExpandIframes:!!this.browser.userBrowserSettings.autoExpandIframes}),frameConfig:n.iframeUrl?{type:"url",url:n.iframeUrl}:void 0,browser:this.browser,logger:a});return{fail:!m.success,data:m.data,thoughts:m.success?"Page assertion passed.":m.err?.message??`Page assertion still failing after ${n.timeout} seconds.`,urlAfterCommand:this.browser.url(),succeedImmediately:!1}}case"REGISTER_REQUEST_LISTENER":{let m=new Qo(n.requestMatcher),g=this.browser.registerRequestListener(m);return this.registeredListeners[n.key]=g.then(async h=>await cy(h)).catch(h=>{a.error({err:h},"Failed to get request listener response")}),{succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"AWAIT_LISTENER":{let m=this.registeredListeners[n.key];if(!m)throw new w("ActionFailureError",`No listener registered with key: ${n.key}`);let g=n.timeout??10;return{data:await Y(m,{milliseconds:g*1e3,message:`Request listener timed out after ${g} seconds`}),succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"RECORD_REQUESTS":{let m=new Qo(n.requestMatcher);return this.recordedRequests[n.key]={},this.browser.registerRequestRecorder(n.key,{matches:g=>m.matches({url:g.request.url,method:g.request.method}),onRequestStart:(g,h)=>{this.recordedRequests[n.key][g]=qm(h)},onRequestComplete:(g,h)=>{this.recordedRequests[n.key]?.[g]&&(this.recordedRequests[n.key][g]=qm(h))}}),{succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"GET_RECORDED_REQUESTS":{let m=this.recordedRequests[n.key];if(!m)throw new w("ActionFailureError",`No recorder registered with key: ${n.key}`);return delete this.recordedRequests[n.key],{data:Object.values(m),succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"SET_HEADER":{let m;return n.requestMatcher&&(m=new Qo(n.requestMatcher)),this.browser.setHeader(n.name,n.value,m),{succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"MOCK_ROUTE":return{data:{key:this.browser.registerMock(n.key,new Qo(n.requestMatcher),async(g,h)=>{let f=await Fn({orgId:this.orgId,code:n.responseGenerator,fragment:!1,context:o,timeoutMs:void 0,logger:a,localTools:this.localCodeEvalTools,mock:{request:g,response:h},disallowVariableUpdates:!0,responseSerialization:"RESPONSE"}),y=OA.parse(f);return new Response(y.body,{status:y.status,headers:y.headers})},n.fetchOriginalResponse??!1)},succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"REMOVE_ROUTE_MOCK":return this.browser.removeMock(n.key),{succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"OFFLINE_MODE":return await this.browser.setOfflineMode(n.enable),{succeedImmediately:!1,urlAfterCommand:this.browser.url()};default:return(m=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(n)}return{succeedImmediately:!1,urlAfterCommand:this.browser.url()}}async getReverseMappedDescription({browserState:e,targetId:t,disableCache:n,screenshot:o}){return(await this.generator.getReverseMappedDescription({browserState:e,target:t,screenshot:o},{disableCache:n,abortSignal:this.executeAbortController.signal,loggerTags:ye(this.logger)})).phrase}async stopRecordMode(){this.recordAbortController?.abort(),await this.browser.clearAllCdpHighlights()}async startRecordMode({params:e,abortController:t,isClickToRecord:n}){this.recordAbortController=t;let o=new Qm({signal:t.signal,...e});return await this.browser.startRecording(this.recordAbortController.signal,o,n),o}async runSectionAutohealing(e){return this.generator.getAutohealingProposal(e,{disableCache:!0,abortSignal:this.executeAbortController.signal,loggerTags:ye(this.logger)})}async getFailureRecoveryPlan(e){return this.generator.getFailureRecoveryPlan(e,{disableCache:!0,abortSignal:this.executeAbortController.signal,loggerTags:ye(this.logger)})}};import{mkdirSync as IK}from"fs";import{tmpdir as OK}from"os";import xO from"path";import{diff as PK}from"deep-object-diff";import{cloneDeep as Fy}from"lodash-es";import vO from"fontoxpath";import cK from"@prettier/plugin-xml";import uK from"prettier";import{DOMParser as dK,XMLSerializer as mK}from"slimdom";var pK=new Set(["android.webkit.webview","com.facebook.react.views.webview.reactwebview","com.tencent.smtt.sdk.webview","com.tencent.smtt.sdk.x5webview","org.xwalk.core.xwalkview","com.uc.webview.export.webview"]);function gK(r){let e=r.toLowerCase();return e.endsWith("webview")||pK.has(e)}function su(r){return!!(gK(r.tagName)||r.getAttribute("package")==="com.android.chrome"&&r.getAttribute("content-desc")==="Web View"&&yO(r.tagName.toLowerCase()).startsWith("frame"))}function yO(r){let e=["android.widget.","android.view.","android.webkit.","android.app.","android.support.","androidx.","com.android.inputmethod."];for(let t of e)if(r.startsWith(t))return r.substring(t.length);return r}var hK=new Set(["index","package","a11y-important","screen-reader-focusabl"]),fK=new Set(["selected","checked","checkable","clickable","enabled","focusable","focused","long-clickable","password","scrollable","selected","showing-hint","context-clickable","multiline","text-entry-key","heading","dismissable","screen-reader-focusable","content-invalid","a11y-focused"]),SK=new Set(["text","hint"]),yK=new Set(["live-region","drawing-order"]),bK=new Set(["displayed","enabled"]);function EK(r,e){let t={};for(let[n,o]of Object.entries(e))hK.has(n)||n==="class"&&r===o||n==="focusable"&&o==="true"&&e.clickable==="true"||fK.has(n)&&o==="false"||SK.has(n)&&o===""||bK.has(n)&&o==="true"||yK.has(n)&&o==="0"||n!=="id"&&(t[n]=o);return t}function bO(r,e,t){let{prunedDocument:n,idToElement:o,prunedIdToElement:i,idCounter:a,opts:s}=r,c=a.value++;t.setAttribute("id",String(c));let l={};for(let p of e.attributes){let m=p.name,g=p.value;g!=null&&(l[m]=String(g))}let u=EK(e.tagName,l);for(let[p,m]of Object.entries(u))t.setAttribute(p,m);if(o.set(c,e),i.set(c,t),su(e)){let p=s?.injectedWebviewContent??"";if(s?.removeWebviewContent){for(;t.firstChild;)t.removeChild(t.firstChild);return}else if(!s?.disableMomenticAccessibilityTree&&p.trim().length>0){for(;t.firstChild;)t.removeChild(t.firstChild);p.trim().length>0&&t.appendChild(n.createCDATASection(`
4574
+ `),tokenLength:d}),s.forEach((h,f)=>{let y=h.ids[0],E=h.ids[h.ids.length-1];r.debug({tokenLength:h.tokenLength,minId:y,maxId:E},`Chunk for page filtering (index ${f+1}/${s.length})`)}),{chunks:s}}var G2=75e4,op=3e5;async function aa(r){let{options:e,fixtures:t,screenshot:n}=r,{aiPageFiltering:o}=e,{logger:i,generator:a,orgId:s,signal:c}=t,l=r.tree,u=r.serializedTree,d=bn(u);if(d>G2)try{let p=np({serializedTree:u,options:{minChunkTokenCount:1e4,maxChunkTokenCount:1e5,acceptableChunkTokenCount:5e4,maxLineLength:4e3},logger:i});l=await W2({...r,tokenLimit:op-1e4,chunks:p.chunks}),u=l.serialize();let m=bn(u);i.info({oldTokens:d,newTokens:m},"Filtered page using keywords"),d=m}catch(p){i.warn({err:p},"Error filtering page using keyword matching, using naive truncation"),l=l.pruneToSerializedCharLimit(op*Yo),u=l.serialize();let m=bn(u);i.info({oldTokens:d,newTokens:m},"Filtered page using naive truncation"),d=m}if(d>op)try{if(o){let p=np({serializedTree:u,options:nO,logger:i}),m=H2();l=await Y(j2({...r,chunks:p.chunks,callId:m}),{milliseconds:12e3,signal:c}),u=l.serialize();let g=bn(u);i.info({oldTokens:d,newTokens:g,langfuseCallId:m},"Filtered page using AI chunk ranking"),d=g}else{let p=np({serializedTree:u,options:rO,logger:i});l=await Y(V2({...r,chunkResult:p,tokenLimit:4e4}),{milliseconds:12e3,signal:c}),u=l.serialize();let m=bn(u);i.info({oldTokens:d,newTokens:m},"Filtered page using RAG"),d=m}}catch(p){i.warn({err:p},"Error filtering page using RAG/AI, using naive truncation"),l=l.pruneToSerializedCharLimit(op*Yo),u=l.serialize(),i.info("Filtered page using naive truncation")}return u}async function j2({type:r,callId:e,chunks:t,description:n,fixtures:o,tree:i}){let{generator:a,signal:s,logger:c}=o,l=await a.rankChunksWithAi({chunks:t,description:n,type:r,softTokenLimit:4e4,hardTokenLimit:8e4,callId:e},{abortSignal:s,logger:c,loggerTags:ye(c)}),u=[];return t.forEach((p,m)=>{l.indices.includes(m)&&(u=u.concat(p.ids))}),i.pruneUsingRelevantIds(new Set(u))}async function W2(r){let{description:e,fixtures:t,tree:n}=r,{generator:o,logger:i,signal:a}=t;if(!e.trim())throw new Error("Empty description passed to page filtering");let s=await o.getExtractedKeywords({goal:e},{logger:i,loggerTags:ye(i),abortSignal:a});i.info({keywordsResult:s},"Got keywords for page filtering");for(let c of s.keywords){let l=r.chunks.filter(m=>m.content.toLowerCase().includes(c.toLowerCase()));if(!l.length||l.reduce((m,g)=>m+g.tokenLength,0)>r.tokenLimit&&l.length>1)continue;let d=l.flatMap(m=>m.ids);return n.pruneUsingRelevantIds(new Set(d))}throw new Error("No keywords were unique enough for page filtering")}async function V2(r){let{description:e,fixtures:t,chunkResult:n,tokenLimit:o,tree:i}=r,{generator:a,logger:s,signal:c}=t,l=await a.rankChunksWithRag({description:e,chunks:n.chunks,tokenLimit:o},{abortSignal:c,logger:s,loggerTags:ye(s)});if(l.ids.length===0)throw new Error("RAG returned no important ids");return i.pruneUsingRelevantIds(new Set(l.ids.map(d=>`${d}`)))}async function Ny(r,e){if(!r.description)throw new w("UserConfigurationError","Cannot locate element with empty description");return an({action:async()=>$2(r,e),frameConfig:r.iframeUrl?{type:"url",url:r.iframeUrl}:void 0,browser:e.browser,logger:r.logger})}async function $2(r,e){let{disableCache:t,testContext:n,filterByViewport:o,skipWait:i,source:a,memory:s,aiPageFiltering:c,logger:l,allowNotActionableNodesOverride:u,skipSavingVisualAttributes:d}=r,{orgId:p,browser:m,localCodeEvalTools:g,generator:h,abortSignal:f}=e,y=r.description,E=Ds(),b=r.useMemory&&!t;n&&(y=await Yc({orgId:p,s:y,context:n,localTools:g,signal:f,logger:l})),a&&(y=JI(y,a));let{serializedTree:x,tree:P}=await E.startAsyncSpan("GET_PAGE_STATE",async()=>jn(m,{allowNotActionableNodesOverride:u,filterByViewport:o,abortSignal:f,skipWait:i,logger:l}),{}),O=await E.startAsyncSpan("GET_PAGE_SCREENSHOT",async()=>{let B,j=Date.now(),ue;for(;!B&&Date.now()-j<3e3;){f.throwIfAborted();try{B=await m.screenshot({clearHighlights:!0,respectActiveFrame:!0,retries:2})}catch(le){ue=le}}if(!B)throw new w("ActionFailureError",`Failed to take screenshot of page to locate element. The page may be unresponsive, or your machine might be severely resource constrained. Error: ${ue?.message}`);return B}),T=x,R=!1,I=`data:image/jpeg;base64,${O.toString("base64")}`;T=await aa({type:"locator",description:y,screenshot:I,serializedTree:x,options:{aiPageFiltering:c},tree:P,fixtures:{generator:h,signal:f,logger:l,orgId:p}}),T!==x&&(R=!0);let k=await E.startAsyncSpan("AI_LOCATOR_CALL",async B=>{let j=await h.getElementLocation({browserState:T,goal:y,screenshot:I,source:a,memory:b?s:void 0},{disableCache:t,abortSignal:f,loggerTags:ye(l),useMemory:b});return B.result=j,j});if(l.debug({usedRag:R,result:k},"Got locator result"),!(k.id>0))throw new wo(`Could not find any relevant element: ${k.thoughts}`,k.updatedMemory?{type:"GCS_TRACES",traces:k.updatedMemory}:void 0);let{resolution:ee,target:K,frameConfig:ge}=await E.startAsyncSpan("TARGET_RESOLUTION",async B=>{let j=await m.createTargetFromA11yId({id:k.id,requirements:k.requirements,additionalElements:k.additionalElements,description:y,targetSource:"AI",logger:l,skipSavingVisualAttributes:d});return B.result={serializedElement:j.target.nodeOnlySerializedHtml??"Unknown HTML element"},j});if(ee.a11yNode?.properties?.hidden&&ee.a11yNode?.properties?.hidden!=="false")throw new w("ActionFailureError",`Momentic's AI found a relevant element to interact with, but it is explicitly marked with an 'aria-hidden' attribute. Please remove this attribute or adjust the element description to locate a different element. Element chosen: ${ee.displayString}`);return b&&(k.updatedMemory?K.memory={type:"GCS_TRACES",traces:k.updatedMemory}:s&&(K.memory=s)),{thoughts:k.thoughts,target:K,resolution:ee,frameConfig:ge,screenshot:I}}var q2=15;async function ip({command:r,aiPageFiltering:e,logger:t,fixtures:n,useMemory:o,maxRetries:i=q2}){if(!r.assertion.trim())throw new w("ActionFailureError","Assertion command is missing the assertion content");let a=th.optional().catch(void 0).parse(r.source);r.source&&!a&&t.warn(`Invalid source ${r.source} for AI assertion, ignoring...`);let{browser:s}=n,c=r.timeout?r.timeout*1e3:s.smartWaitingTimeout,l=lP(c,i-1),u=0,d=Date.now(),p=d+c,m=d,g,h,f;try{await an({action:()=>s.clearHighlights(),frameConfig:r.iframeUrl?{type:"url",url:r.iframeUrl}:void 0,browser:s,logger:t})}catch(y){t.warn({err:y},"Failed to clear highlights before AI check, continuing...")}for(;u<i;){n.abortSignal.throwIfAborted();let y=Date.now();if(u>0){if(y>=p)break;let x=p-y,P=m-y,O=Math.min(P,x);O>0&&await J(O,n.abortSignal)}let E=Date.now();if(u>0&&E>=p)break;let b=!1;try{if(g=await an({action:async()=>{let P=await iO(s,t,n.abortSignal);return h&&h.serializedTree===P.serializedTree&&h.screenshotBuff.equals(P.screenshotBuff)?(b=!0,g):(h=P,aO({command:r,state:P,fixtures:n,useMemory:o,useConsensus:!1,highlightElementsOnFailure:!1,attemptNumber:u,aiPageFiltering:e,logger:t,source:a}))},frameConfig:r.iframeUrl?{type:"url",url:r.iframeUrl}:void 0,logger:t,browser:s}),g?.success){g?.updatedMemory&&Xc(r,g.updatedMemory,t);break}else throw g?.thoughts?new w("AssertionFailureError",g.thoughts):new w("InternalPlatformError","No thoughts were provided for AI assertion failure")}catch(x){n.abortSignal.throwIfAborted(),f=x instanceof Error?x:new Error(`${x}`),b?t.info(`AI check attempt ${u} failed (re-used previous result)`):t.info({err:x},`AI check assert attempt ${u} failed, retrying...`)}finally{u++,m=E+l}}if(!g?.success){let y=p-Date.now();y>0&&await J(y,n.abortSignal)}if(!g?.success)try{g=await an({action:async()=>aO({command:r,state:await iO(s,t,n.abortSignal),fixtures:n,useMemory:o,useConsensus:!0,highlightElementsOnFailure:!0,attemptNumber:u,aiPageFiltering:e,logger:t}),frameConfig:r.iframeUrl?{type:"url",url:r.iframeUrl}:void 0,logger:t,browser:s})}catch(y){n.abortSignal.throwIfAborted(),f=y instanceof Error?y:new Error(`${y}`)}finally{u++}if(g?.updatedMemory&&Xc(r,g.updatedMemory,t),!g?.success){let y=`AI check still failing after ${u} attempts.`;throw f&&(y+=` Latest result: ${f.message}`),new w("AssertionFailureError",y)}return{...g,succeedImmediately:!1,urlAfterCommand:s.url()}}async function iO(r,e,t){let[n,o]=await Promise.all([jn(r,{abortSignal:t,skipWait:!0,skipWaitForPageLoad:!0,logger:e}),r.screenshot({retries:1,respectActiveFrame:!0})]);return{...n,screenshotBuff:o}}async function aO({command:r,state:e,fixtures:t,useConsensus:n,useMemory:o,highlightElementsOnFailure:i,aiPageFiltering:a,attemptNumber:s,source:c,logger:l}){let{browser:u,generator:d,abortSignal:p}=t,m={type:"ASSERTION"},{serializedTree:g,tree:h}=e,f=e.screenshotBuff,y=f.toString("base64"),E=u.url(),b=r.contextChoice??"MULTIMODAL",x=g;b!=="VISION_ONLY"&&(x=await aa({type:"assertion",serializedTree:g,tree:h,description:r.assertion,screenshot:y,options:{aiPageFiltering:a},fixtures:{generator:d,signal:p,logger:l,orgId:t.orgId}}),x!==g&&(m.ragUsed=!0),m.pageState=x);let P={goal:r.assertion,url:E,memory:o?r.cache?.memory:void 0,browserState:x,screenshot:y,contextChoice:b,source:c},T=await(b==="VISION_ONLY"?(R,D)=>d.getVisualAssertionResult(R,D):(R,D)=>d.getAssertionResult(R,D))(P,{useConsensus:n,attemptNumber:s,useMemory:o,disableCache:!!r.disableCache,abortSignal:p,logger:l,loggerTags:ye(l)});return(T.result||i)&&T.relevantElements&&(m.relevantElementsSerialized=T.relevantElements.map(R=>u.getSerializedFormFromA11yId(R)).filter(R=>!!R),await K2(T.relevantElements,u,l)),{success:T.result,thoughts:T.thoughts,afterScreenshotOverride:f,updatedMemory:o?T.updatedMemory:void 0}}async function K2(r,e,t){let n=Date.now();for(let o of r){if(Date.now()-n>2e3){t.debug("Highlighting relevant elements took over 2s, aborting...");return}try{let i=new AbortController;await Y(e.highlightA11yId(o),{milliseconds:1e3,fallback:()=>{throw i.abort(),new Error("Timed out waiting for highlighting to complete")}})}catch(i){t.debug({err:i},"Failed to highlight relevant element after assertion, continuing...");return}}}var Y2=1e5,ap=class extends Error{constructor(){super("The page content exceeds the maximum token limit for AI smart waiting."),this.name="ExceededMaxAISmartWaitingTokensError"}};async function sO(r,e){let{logger:t}=r,{abortSignal:n,browser:o}=e,i=Date.now();try{await X2(i,r,e)}catch(a){if(a instanceof Error&&(a.name==="AbortError"||a.name==="TimeoutError")||n.aborted)return;a instanceof ap?t.warn("Skipping AI smart waiting due to excessive page size - falling back to naive waiting"):t.warn({err:a},"Unexpected error occurred during AI smart waiting");let s=o.smartWaitingTimeout-(Date.now()-i);s>0&&await J(s,n)}finally{t.debug({durationMs:Date.now()-i},"AI smart waiting complete")}}async function X2(r,e,t){let{abortSignal:n,browser:o}=t;if(o.smartWaitingTimeout<3e3){await J(o.smartWaitingTimeout,n);return}if(!e.description)throw new w("UserConfigurationError","Cannot locate element with empty description");await Y(J2(r,e,t),{milliseconds:o.smartWaitingTimeout})}async function J2(r,e,t){let{logger:n,iframeUrl:o}=e,{browser:i}=t;for(;Date.now()-r<i.smartWaitingTimeout;)if(await an({action:async()=>Z2(e,t),frameConfig:o?{type:"url",url:o}:void 0,browser:i,logger:n}))return}async function Z2(r,e){let{testContext:t,logger:n,filterByViewport:o,allowNotActionableNodesOverride:i}=r,{browser:a,abortSignal:s,localCodeEvalTools:c,orgId:l,generator:u}=e,d=r.description;t&&(d=await Yc({orgId:l,s:d,context:t,localTools:c,signal:s,logger:n}));let{serializedTree:p}=await jn(a,{allowNotActionableNodesOverride:i,filterByViewport:o,abortSignal:s,logger:n});if(bn(p)>Y2)throw new ap;s.throwIfAborted();let g;try{g=await a.screenshot({clearHighlights:!0,respectActiveFrame:!0,retries:2})}catch(E){throw new w("ActionFailureError",`Failed to take screenshot of page to perform smart waiting. The page may be unresponsive, or your machine might be severely resource constrained. Error: ${E instanceof Error?E.message:E}`)}let f=`data:image/jpeg;base64,${g.toString("base64")}`;s.throwIfAborted();let y=await u.getSmartWaitingDecision({browserState:p,description:d,screenshot:f},{abortSignal:s,loggerTags:ye(n)});return n.debug({result:y},"Got smart waiting result"),y.isPageReady}import{cloneDeep as cO}from"lodash-es";async function uO(r){let{command:e,timeoutMs:t,fixtures:n}=r,{abortSignal:o}=n,i=()=>Pu(e.cache)?e.cache:void 0,a=i(),s=cO(a),c=(h=!1)=>{if(a=i(),!!a)if(h){let f=SM(s,a);a.target=f.target,a.updatedAt=f.updatedAt}else{if(!s){a=void 0;return}a.target=s.target,a.updatedAt=s.updatedAt}},l=Date.now(),u=0,d,p=500,m=!1;for(;u<2||Date.now()-l<t;){u++,u>1&&await J(p,o),o?.throwIfAborted(),a=i();let{result:h,elementWasFound:f}=await lO({cacheToUse:a,params:r});if(d=h,m=f,h.success)break;c(),p=Math.min(p*2,1e4)}if(!d)throw new w("InternalPlatformError",`Failed to evaluate manual element assertion in ${t}ms.`);if(o?.throwIfAborted(),!d.success&&a?.target&&Ta(a.target)){let h=a?.target?.memory?{target:{id:-1,memory:a.target.memory}}:void 0,{result:f}=await lO({cacheToUse:h,params:r});d=f,d.success||c(!0)}let g=i();return d.success&&g?.target&&!m&&(g.target=LS(g.target),g.updatedAt=new Date),d}async function lO({cacheToUse:r,params:e}){let{command:t,disableCache:n,fixtures:o,tracer:i,targetingWrapper:a}=e,{logger:s}=o;if(t.target&&!vo(t.target))throw new Error("Element assertion with x/y is not supported yet");let c=Om(t.assertion),l,u=!1,d=cO(r);try{let{elementInteractedDisplayString:p,result:m,thoughts:g}=await a({ctx:o.ctx,tracer:i,command:t,target:t.target,cache:d?.target,action:async h=>Q2(h.locator,e),options:{...t,allowNotActionableNodesOverride:!0,disableCache:n,memory:d?.target?.memory,disableGlobalLocatorRedirect:!0,source:Ol(t),targetName:"target"}});return l={success:m.success,data:m.data,err:m.err,elementInteractedDisplayString:p,thoughts:g},u=!0,m.success||(s.warn({aiThoughts:g,elementString:p,err:m.err},"Element check found an element but failed"),l={...m,thoughts:g}),{result:l,elementWasFound:u}}catch(p){if(c)return l={success:!0,thoughts:`The element described does not exist on the page: ${p.message}`,err:void 0,data:void 0},{result:l,elementWasFound:u};if(!(p instanceof w)||p.reason!="ActionFailureError")throw p;return l={success:!1,err:p,data:void 0,thoughts:void 0},s.warn({err:p},"Element check did not find an element and failed"),{result:l,elementWasFound:u}}}async function Q2(r,{command:e,fixtures:t}){return await t.browser.highlight(r),await eK(r,e.assertion)}async function eK(r,e){let t=!0,n,o;switch(e.type){case"ELEMENT_CONTENT":{let a=await r.textContent()??"";if(o={elementTextContent:Vt(a,500,!0)},!Un(a,e.value,e.operation,{negated:!!e.negated,ignoreCase:!1})){let s=tn(e);t=!1,n=new w("AssertionFailureError",`The content ${s} '${e.value}': ${a}`)}break}case"ELEMENT_ATTRIBUTE":{o={elementOuterHtml:Vt(await r.evaluate(s=>s.cloneNode(!1).outerHTML),500,!0)};let a=null;try{a=await r.getAttribute(e.attr,{timeout:3e3})}catch(s){n=new w("AssertionFailureError",s instanceof Error?s.message:String(s)),t=!1;break}if(!Un(a,e.value,e.operation,{negated:!!e.negated,ignoreCase:!1})){let s=tn(e);t=!1,e.operation==="EXISTS"?n=new w("AssertionFailureError",`The attribute ${e.attr} ${s}`):n=new w("AssertionFailureError",`The attribute ${e.attr} ${s} '${e.value}': ${a}`)}break}case"ELEMENT_EXISTENCE":{switch(e.condition){case"VISIBLE":{t=await r.evaluate(async(s,c)=>{let l=Date.now();for(;Date.now()-l<c;){await new Promise(d=>setTimeout(d,250));let u=s.getBoundingClientRect();if(!(u.width===0||u.height===0)&&window.getComputedStyle(s).visibility!=="hidden"&&window.getComputedStyle(s).display!=="none")return!0}return!1},dr*1e3);break}case"EDITABLE":{t=await r.isEditable({timeout:dr*1e3});break}case"EXISTS":{t=!0;break}case"ENABLED":{t=await r.isEnabled({timeout:dr*1e3});break}case"FOCUSED":{t=await r.evaluate(s=>s===document.activeElement);break}default:return(s=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(e.condition)}if(t=e.negated?!t:t,!t){let a=tn(e);n=new w("AssertionFailureError",`The element ${a}`)}break}case"ELEMENT_NAME":{let a=await r.evaluate(s=>s.tagName);if(!Un(a,e.value,e.operation,{negated:!!e.negated,ignoreCase:!0})){let s=tn(e);t=!1,n=new w("AssertionFailureError",`The element tag name ${s} '${e.value}': ${a}`)}break}case"ELEMENT_STYLE":{let a=await r.evaluate((s,c)=>window.getComputedStyle(s).getPropertyValue(c),e.property);if(!Un(a,e.value,e.operation,{negated:!!e.negated,ignoreCase:!1})){let s=tn(e);t=!1,e.operation==="EXISTS"?n=new w("AssertionFailureError",`The style property ${e.property} ${s}`):n=new w("AssertionFailureError",`The style property ${e.property} ${s} '${e.value}': ${a}`)}break}default:return(a=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(e)}return{thoughts:void 0,success:t,data:o,err:n}}function dO(r){return r.type==="ELEMENT_EXISTENCE"&&r.negated&&r.condition==="EXISTS"}import{Jimp as tK}from"jimp";async function au(r,e){let t=await r.screenshot(e),n=await tK.fromBuffer(t);return{buffer:t,width:Math.ceil(n.bitmap.width??0),height:Math.ceil(n.bitmap.height??0)}}import{Jimp as mO}from"jimp";import Dy from"jpeg-js";import rK from"pixelmatch";async function pO({ctx:r,tracer:e,command:t,disableCache:n,browser:o,targetingWrapper:i,logger:a,screenshotStorage:s}){if(t.target&&!vo(t.target))throw new Error("Visual Diff with x/y is not supported yet");await o.waitForStability({logger:a});let c={clearHighlights:!0,hideCaret:!0},l;t.target?.elementDescriptor?l=(await i({ctx:r,tracer:e,command:t,target:t.target,cache:t.cache?.target,action:async k=>au(o,{locator:k.locator,...c}),options:{...t,disableCache:n,disableGlobalLocatorRedirect:!0,memory:t.cache?.target?.memory,targetName:"target"}})).result:l=await au(o,c);let u=await s.prepareGoldenScreenshotForComparison(a,t,l);if((l.height!==u.height||l.width!==u.width)&&a.warn({currHeight:l.height,currWidth:l.width,savedHeight:u.height,savedWidth:u.width},"Mismatched before and after visual diff screenshot sizes"),Math.abs(l.height-u.height)>10||Math.abs(l.width-u.width)>10){let I=`${l.width}x${l.height}`,k=`${u.width}x${u.height}`;return{fail:!0,thoughts:`Current screenshot (${I}) does not match saved screenshot dimensions (${k}) - did you change the size of the target or the viewport?`,beforeScreenshotOverride:u.buffer,afterScreenshotOverride:l.buffer,succeedImmediately:!1,urlAfterCommand:o.url()}}let d=await mO.fromBuffer(l.buffer),p={width:l.width,height:l.height},m=await mO.fromBuffer(u.buffer),g={width:u.width,height:u.height},h,f=p.width*p.height,y=g.width*g.height,E=Math.abs(p.height-g.height),b=Math.abs(p.width-g.width);if(f>y){let I=d.cover({w:g.width,h:g.height});l.buffer=await I.getBuffer("image/jpeg"),h="current",l.width=g.width,l.height=g.height}else if(y>f){let I=m.cover({w:p.width,h:p.height});u.buffer=await I.getBuffer("image/jpeg"),h="saved"}let x={data:Buffer.alloc(l.width*l.height*4),width:l.width,height:l.height},P=t.threshold??.1,T=rK(Dy.decode(u.buffer).data,Dy.decode(l.buffer).data,x.data,l.width,l.height,{threshold:P,diffColorAlt:[0,255,0]})/(l.width*l.height)*100,R=T>P*100,D=`Visual diff of ${T.toFixed(2)}% detected, which is ${R?"over":"under"} the threshold of ${P*100}%.`;if(h&&(D+=` The ${h} screenshot was cropped since it was taller by ${E} pixels and wider by ${b} pixels.`),R)throw new w("ActionFailureError",D);return{fail:R,thoughts:D,beforeScreenshotOverride:l.buffer,afterScreenshotOverride:Dy.encode(x,75).data,succeedImmediately:!1,urlAfterCommand:o.url()}}var nK=3e4;function oK(r){if(!r.body)return{};switch(r.body.type){case"json":return{content:r.body.content,contentType:"application/json"};case"form-urlencoded":{let e=new URLSearchParams;return Object.entries(r.body.content).forEach(([t,n])=>{e.append(t,n)}),{content:e.toString(),contentType:"application/x-www-form-urlencoded;charset=UTF-8"}}}}async function sp({command:r,logger:e,baseUrl:t,fetchImplementation:n=fetch}){let o=r.timeout??nK/1e3,i=Object.fromEntries(Object.entries(r.headers||{}).filter(([g,h])=>g&&h)),a=new URLSearchParams;Object.entries(r.params||{}).filter(([g,h])=>g&&h).forEach(([g,h])=>{a.append(g,h)});let s=a.toString(),c;if(Is(r.url)&&(c=r.url),t&&Os(r.url,t)&&(c=new URL(r.url,t).toString()),!c)throw new w("ActionFailureError",`Invalid URL: ${r.url}`);let l=c;e.info({url:l,searchParams:s,headers:i,body:r.body,method:r.method},"Making HTTP request");let d=await Y((async()=>{let g=s?`${l}?${s}`:l;try{let h=oK(r),f=new Headers(i);return h.contentType&&!f.has("Content-Type")&&f.set("Content-Type",h.contentType),await n(g,{headers:f,method:r.method,body:h.content})}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 w("ActionFailureError",`Fetch request timed out after ${o} seconds`)}});if(!d.ok){let g;try{g=await d.text()}catch(h){g=`Failed to read response body: ${h}`}throw new w("ActionFailureError",`Fetch request failed with status ${d.status}: ${g}`)}let p={};d.headers.forEach((g,h)=>{p[h]=g});let m={status:d.status,headers:p,request:{url:d.url,method:r.method,headers:i}};if(r.body?.type==="json"&&r.body.content)try{m.request.json=JSON.parse(r.body.content)}catch{}if(d.headers.get("content-type")?.includes("json"))try{m.json=await d.json()}catch{}else d.headers.get("content-type")?.includes("text")&&(m.text=await d.text());return m}var iK=5e3;async function hO({timeout:r=dr,...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 c=Date.now();i=await lp(e),a=Date.now();let l=a-c;if(l>1e3&&e.logger.warn({pageAssertDuration:l},"Page assertion took longer than expected"),!i.success)await J(s,e.signal),s=Math.min(Math.floor(s*1.5),iK);else return i}return i=await lp(e),i}async function lp({assertion:r,browser:e,autoExpandIframes:t}){switch(r.type){case"CONTENT":case"CONTENT":{let o,i=!1,a;try{let s;if(t){let c=await e.evaluateFunctionInAllFrames(gO,{value:r.value,negated:!!r.negated,returnHtml:!1});i=r.negated?c.every(l=>l.evaluation):c.some(l=>l.evaluation),s=c.find(l=>l.pageHtml)?.pageHtml}else({evaluation:i,pageHtml:s}=await e.evaluateFunctionInPage(gO,{value:r.value,negated:!!r.negated,returnHtml:!0},"checking page content"));if(!i){let c=r.negated?uo.CONTAINS:mo.CONTAINS;a=new w("AssertionFailureError",`The page ${c} '${r.value}'.`),o=s}}catch(s){a=new w("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)}}function gO({value:r,negated:e,returnHtml:t}){let n=document.body.innerHTML,o=n.includes(r)===!e;return n.length>1e4&&(n=n.slice(0,1e4)+"...TRUNCATED"),{evaluation:o,pageHtml:!o&&t?n:void 0}}var aK=3e4;async function fO({command:r,logger:e,baseUrl:t,fetchImplementation:n=fetch}){let o=r.timeout??aK/1e3,i=new AbortController,a=Object.fromEntries(Object.entries(r.headers||{}).filter(([d,p])=>d&&p));a["Content-Type"]="application/json";let s;if(Is(r.url)&&(s=r.url),t&&Os(r.url,t)&&(s=new URL(r.url,t).toString()),!s)throw new w("ActionFailureError",`Invalid URL: ${r.url}`);let l=await Y((async()=>{try{return await n(s,{headers:a,method:"POST",body:JSON.stringify({query:r.query,variables:r.variables?JSON.parse(r.variables):void 0}),signal:i.signal})}catch(d){e.error({err:d},"Failed to make HTTP request")}})(),{milliseconds:o*1e3});if(!l)throw new w("ActionFailureError",`GraphQL request timed out after ${o} seconds`);if(!l.ok){let d,p=await l.text();try{d=JSON.parse(p)}catch{throw new w("ActionFailureError",`GraphQL request failed with status ${l.status}: ${p}`)}throw d?.errors?.length&&d?.errors[0]?.message?new w("ActionFailureError",`GraphQL request failed with status ${l.status}: ${d.errors[0].message}`):new w("ActionFailureError",`GraphQL request failed with status ${l.status}: ${p}`)}let u={};return l.headers.forEach((d,p)=>{u[p]=d}),{status:l.status,headers:u,json:await l.json()}}var cp=class{orgId;options;storage;localCodeEvalTools;uploadedFileStorage;visualDiffScreenshotStorage;browser;generator;executeAbortController=new AbortController;logger;recordAbortController=null;registeredListeners={};recordedRequests={};constructor({browser:e,generator:t,logger:n,storage:o,orgId:i,localCodeEvalTools:a,uploadedFileStorage:s,visualDiffScreenshotStorage:c,options:l}){this.orgId=i,this.options=l,this.browser=e,this.browser.registerAbortSignal(this.executeAbortController.signal),this.storage=o,this.uploadedFileStorage=s,this.visualDiffScreenshotStorage=c,this.localCodeEvalTools=a,this.generator=t,this.logger=n}setOpen(){this.executeAbortController=new AbortController,this.browser.registerAbortSignal(this.executeAbortController.signal)}setClosed(){this.executeAbortController.abort()}throwIfClosed(){this.executeAbortController.signal.throwIfAborted()}get closed(){return this.executeAbortController.signal.aborted}async evaluateAiAction({goal:e,startingScreenshot:t,history:n,disableCache:o,langfuseSessionId:i,lastError:a,logger:s=this.logger}){let[c,l]=await Promise.all([jn(this.browser,{abortSignal:this.executeAbortController.signal,skipWait:!0,skipWaitForPageLoad:!0,logger:s}),this.browser.screenshot({retries:1,clearHighlights:!0})]),u=`data:image/jpeg;base64,${l.toString("base64")}`,d=await aa({type:"ai-action",description:e,screenshot:u,serializedTree:c.serializedTree,tree:c.tree,options:{aiPageFiltering:!!this.options?.aiPageFiltering},fixtures:{generator:this.generator,signal:this.executeAbortController.signal,logger:s,orgId:this.orgId}}),p={url:this.browser.url(),browserState:d,startingScreenshot:t,history:n,goal:e,screenshot:u,lastError:a};return await this.generator.getMultiturnAiActionEvaluation(p,{disableCache:o,abortSignal:this.executeAbortController.signal,loggerTags:{...ye(s)},langfuseSessionId:i})}async promptToCommand({goal:e,startingScreenshot:t,history:n,actionHint:o,disableCache:i,logger:a=this.logger,langfuseSessionId:s}){let c=this.browser.url(),[l,u]=await Promise.all([jn(this.browser,{abortSignal:this.executeAbortController.signal,skipWait:!0,skipWaitForPageLoad:!0,logger:a}),this.browser.screenshot({retries:1,clearHighlights:!0})]),d=`data:image/jpeg;base64,${u.toString("base64")}`,p=await aa({type:"ai-action",description:e,screenshot:d,serializedTree:l.serializedTree,tree:l.tree,options:{aiPageFiltering:!!this.options?.aiPageFiltering},fixtures:{generator:this.generator,signal:this.executeAbortController.signal,logger:a,orgId:this.orgId}}),m={url:c,browserState:p,startingScreenshot:t,history:n,goal:e,actionHint:o,screenshot:d};try{return await this.generator.getMultiturnAiActionCommand(m,{disableCache:i,abortSignal:this.executeAbortController.signal,loggerTags:{...ye(a)},langfuseSessionId:s})}catch(g){throw new w("InternalWebAgentError",`Error generating command: ${g instanceof Error?g.message:g}`,{errOptions:{cause:g}})}}async getBrowserState(e){return jn(this.browser,e)}async locateElement(e){return await Ny({...e,aiPageFiltering:!!this.options?.aiPageFiltering},this.getControllerFixtures())}async locateElementWithSelector(e,t){return an({action:async()=>{let n=await this.browser.resolveHardcodedCssSelector({ctx:null,selector:e,timeoutMs:2e3,logger:this.logger});return{thoughts:"Located element with selector",target:{id:-1,selector:e,targetSource:"USER_CSS_SELECTOR",targetUpdateTime:new Date().toUTCString()},resolution:n}},frameConfig:t?{type:"url",url:t}:void 0,browser:this.browser,logger:this.logger})}getControllerFixtures(e){return{ctx:e??null,browser:this.browser,generator:this.generator,logger:this.logger,orgId:this.orgId,storage:this.storage,localCodeEvalTools:this.localCodeEvalTools,abortSignal:this.executeAbortController.signal}}shouldUseMemory(){return this.options?.useMemory??(this.orgId==="org_01HMSCJQBCCG51M2ZF65YC5B8W"||this.orgId==="org_01HMJTX4GT1KG94KZRCT8MZ6YB")}async wrapMultiElementTargetingCommand({ctx:e,tracer:t,command:n,targetNames:o,descriptions:i,caches:a,action:s,options:c,retriesWithAI:l=1}){let u=[];for(let d=0;d<i.length;d++){let p=i[d],m=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:p,cache:a[d],action:async g=>g,options:{...c,targetName:o[d]}});u.push(m)}try{let d=await s(...u.map(g=>g.result)),p=g=>g==="fromTarget"?"From Target":g==="toTarget"?"To Target":"Target",m=u.map((g,h)=>g.thoughts?`${p(o[h])}: ${g.thoughts}`:void 0).filter(g=>!!g).join(" -------------- ")||void 0;return{result:d,elementInteractedDisplayStrings:u.map(g=>g.elementInteractedDisplayString),thoughts:m}}catch(d){if(this.throwIfClosed(),l>0)return this.logger.warn({err:d},"Failed to execute action with multiple cached targets, retrying with AI"),this.wrapMultiElementTargetingCommand({ctx:e,tracer:t,command:n,targetNames:o,descriptions:i,caches:i.map(()=>{}),action:s,options:c,retriesWithAI:l-1});throw new w("ActionFailureError",d.message,{errOptions:{cause:d}})}}async wrapHardcodedCssTargetingCommandHelper({ctx:e,target:t,action:n,options:o,command:i}){let a=this.logger.child({commandId:i.id}),{targetName:s}=o;if(t.type!=="description")throw new w("ActionFailureError","Cannot use selector with non-description target");let c,l=Date.now(),u=Date.now();for(;Date.now()-u<this.browser.smartWaitingTimeout;){l=Date.now();try{let d=await this.browser.resolveHardcodedCssSelector({ctx:e,selector:t.elementDescriptor,targetName:s,logger:a});return{result:await n({locator:d.locator,originalElementLocationResult:void 0,serverSideBoundingBox:null}),elementInteractedDisplayString:d.displayString}}catch(d){if(d.name==="AbortError")throw d;c=d,a.warn({err:d},"Failed to action on hardcoded css selector"),Date.now()-l<500&&await J(500)}}throw c}async resolveCachedTargetForAction(e){let{ctx:t,cache:n,options:o,logger:i}=e,a=Ds(),s=await a.startAsyncSpan("CACHE_RESOLUTION",async l=>{let u=await this.browser.resolveTarget(t,n,{allowNotActionableNodesOverride:o.allowNotActionableNodesOverride,logger:i,signal:this.executeAbortController.signal,...o.resolveTargetOptions});return l.attributes.targetDisplayString=u.displayString,u});(this.browser.userBrowserSettings.visualActions||this.browser.userBrowserSettings.globalLocatorRedirect!==!1)&&await a.startAsyncSpan("SCROLL_ELEMENT_INTO_VIEW",async()=>{await this.browser.scrollIntoViewIfNeeded(s.locator)});let c;return!o.disableGlobalLocatorRedirect&&this.browser.userBrowserSettings.globalLocatorRedirect!==!1&&(c=await a.startAsyncSpan("LOCATOR_REDIRECT",async()=>this.browser.performTargetRedirection(s,i))),c||(c={locator:s.locator,serverSideBoundingBox:await s.locator.boundingBox({timeout:ne}),originalElementLocationResult:s.originalElementLocationResult}),await s.revalidator?.(),{resolutionResult:s,finalTarget:c}}async wrapElementTargetingCommand(e){return await an({action:()=>this.wrapElementTargetingCommandHelper(e),frameConfig:e.options.iframeUrl?{type:"url",url:e.options.iframeUrl}:void 0,browser:this.browser,logger:this.logger})}async wrapElementTargetingCommandHelper(e){let{ctx:t,tracer:n,target:o,action:i,options:a,command:s,finalAttempt:c=!1,originalCache:l=e.cache}=e,{retriesWithAI:u=1}=e,{disableCache:d,useSelector:p,targetName:m,targetHealingInProgress:g,source:h}=a,f=Ds(),y=this.logger.child({commandId:s.id}),E=this.shouldUseMemory(),b=SO(e.cache);if((!b||d)&&!fg(o))throw new w("ActionFailureError","Cannot target element with no cached data or element descriptor");if(p)return this.wrapHardcodedCssTargetingCommandHelper(e);let x=!1;d&&(y.info("Cache explicitly disabled for this step"),x=!0,b=void 0);let P=eO({cache:b,description:o.elementDescriptor,disableSecondaryCacheResolution:!!this.browser.userBrowserSettings.disableSecondaryCacheResolution,logger:y});b=P.cache,x=x||P.cacheBustedBeforeAction;let O=!0;if(!QI(b)){O=!1,y.info({description:o.elementDescriptor,targetHealingInProgress:g,cacheBustedBeforeAction:x,memory:a.memory,useMemory:E},"Prompting AI for an updated element location"),(x||!l)&&await f.startAsyncSpan("SMART_WAITING",async()=>await sO({description:o.elementDescriptor,iframeUrl:a.iframeUrl,source:h,logger:y,allowNotActionableNodesOverride:a.allowNotActionableNodesOverride},this.getControllerFixtures(t))),u--;let T;try{T=await Ny({description:o.elementDescriptor,disableCache:!!a.disableCache,iframeUrl:a.iframeUrl,source:h,useMemory:E,memory:E?a.memory:void 0,aiPageFiltering:!!this.options?.aiPageFiltering,allowNotActionableNodesOverride:a.allowNotActionableNodesOverride,logger:y},this.getControllerFixtures(t))}catch(I){if(I instanceof wo&&I.updatedLocatorMemory){let k={id:-1,...l,memory:I.updatedLocatorMemory};Nm({cmd:s,key:m,newTarget:k,logger:y,updatedWithAI:!0})}throw new w("ActionFailureError",I.message)}T.frameConfig&&this.browser.setActiveFrameConfig(T.frameConfig);let R;!a.disableGlobalLocatorRedirect&&this.browser.userBrowserSettings.globalLocatorRedirect!==!1&&(R=await f.startAsyncSpan("LOCATOR_REDIRECT",async()=>this.browser.performTargetRedirection(T.resolution,y))),R||(R={locator:T.resolution.locator,serverSideBoundingBox:await T.resolution.locator.boundingBox({timeout:ne}),originalElementLocationResult:T.resolution.originalElementLocationResult});let D=await i(R);return Nm({cmd:s,key:m,newTarget:T.target,logger:y,updatedWithAI:!0}),g&&(n.recordTargetAutoHeal({healType:"AI"}),T.target.targetSource="AI_HEALED",T.target.targetUpdateTime=new Date().toUTCString(),T.target.targetUpdateLoggerTags=ye(y)),{result:D,elementInteractedDisplayString:T.resolution.displayString,thoughts:T.thoughts}}try{let{resolutionResult:T,finalTarget:R}=await this.resolveCachedTargetForAction({ctx:t,cache:b,options:a,logger:y}),D=await i(R);if(nt.increment("cache_target_resolution_v2",1,["outcome:hit","platform:web",`hasRequirements:${!!b.requirements}`,`hasAdditionalElements:${!!b.additionalElements}`,`orgId:${this.orgId}`,"cliVersion:0.33.1"]),Nm({cmd:s,key:m,newTarget:b,logger:y,updatedWithAI:!1}),O){let I=T.decisions.filter(k=>k.matched);if(I.length!==1)y.warn({decisions:T.decisions},"Expected exactly 1 matching method for element location, got more or less");else{let k=I[0].type;n.recordTargetAutoHeal({healType:k})}}return{result:D,elementInteractedDisplayString:T.displayString}}catch(T){if(this.throwIfClosed(),(T instanceof to||ET(T)||AT(T)||wT(T)||bT(T)||TT(T)||vT(T))&&!c)return this.wrapElementTargetingCommandHelper({ctx:t,tracer:n,command:s,target:o,action:i,cache:l,originalCache:l,retriesWithAI:u,finalAttempt:!0,options:a});if(T instanceof w)throw y.error({err:T},"Failed to execute command with target (fatal)"),T;if(u>0&&o){y.info({err:T},"Failed to execute action with cached target, retrying with AI"),nt.increment("cache_target_resolution_v2",1,["outcome:miss","platform:web",`hasRequirements:${!!b.requirements}`,`hasAdditionalElements:${!!b.additionalElements}`,`orgId:${this.orgId}`,"cliVersion:0.33.1",`missReason:${T instanceof gt?T.cacheMissReason:"unknown"}`]);let D;return b.memory&&uE(b.memory)&&(D=b.memory),this.wrapElementTargetingCommandHelper({ctx:t,tracer:n,command:s,target:o,cache:void 0,action:i,originalCache:l,retriesWithAI:u,finalAttempt:!0,options:{...a,memory:D,targetHealingInProgress:!0}})}throw new w("ActionFailureError",`Failed to execute interactive command: ${T instanceof Error?T.message:`${T}`}`,{errOptions:{cause:T}})}}async screenshotWithDimensions(e){return au(this.browser,e)}async executePresetCommand(e,t,n,o,i){this.options?.slowMoMs&&await J(this.options.slowMoMs);let a=await this.browser.getOpenPages(),s=this.browser.url(),c;try{c=await this.resolveCommandTemplateStrings(n,o)}catch(l){throw this.throwIfClosed(),new w("ActionFailureError",`Failed to substitute template strings in command: ${l.message}`,{errOptions:{cause:l}})}try{let l=await this.executePresetCommandHelper(e,t,n,o,i);return this.options?.autoFollowNewTabs&&await ZI({beforeUrl:s,command:n,beforePages:a.map(u=>u.url),browser:this.browser,logger:this.logger}),l}catch(l){throw l.name!=="AbortError"&&this.logger.error({err:l},"Error thrown in action controller"),l}finally{Ms(n,c)}}createCallbacksForBrowser(e){return{createIsolatedFolder:()=>oy(e)}}async resolveCommandTemplateStrings(e,t){return _s({obj:e,context:t,bannedKeys:["type","a11yData","thoughts","cache","code"],orgId:this.orgId,logger:this.logger,signal:this.executeAbortController.signal,localTools:this.localCodeEvalTools})}async executePresetCommandHelper(e,t,n,o,i){i=i||"disableCache"in n&&!!n.disableCache;let a=this.logger.child({commandId:n.id});switch(n.type){case"SUCCESS":let s=n.condition;return s?.assertion.trim()?ip({command:s,fixtures:this.getControllerFixtures(e),useMemory:this.shouldUseMemory(),aiPageFiltering:!!this.options?.aiPageFiltering,logger:a}):{succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"AI_ASSERTION":{if(!n.assertion.trim())throw new w("ActionFailureError","Missing assertion");if(n.timeout&&n.timeout>1800)throw new w("AssertionFailureError",`AI check timeout of ${n.timeout} exceeds the maximum allowed value of 30 minutes.`);return ip({command:n,fixtures:this.getControllerFixtures(e),useMemory:this.shouldUseMemory(),aiPageFiltering:!!this.options?.aiPageFiltering,logger:a})}case"AI_EXTRACT":{if(!n.goal.trim())throw new w("ActionFailureError","Cannot perform AI extraction without goal");if(n.schema){let h=nR(n.schema);if(h)throw new w("UserConfigurationError",h)}let m=await this.browser.getCondensedHtml(),g=await this.browser.screenshot({retries:2});try{let h=await this.generator.getTextExtraction({goal:n.goal,browserState:m,returnSchema:n.schema,screenshot:`data:image/jpeg;base64,${g.toString("base64")}`},{disableCache:i,abortSignal:this.executeAbortController.signal,loggerTags:ye(a)});if(h.result==="NOT_FOUND")throw new w("ActionFailureError","No relevant data found for extraction goal on this page");if(h.thoughts?.includes("MaxGenerationLengthExceededError"))throw new w("UserConfigurationError",h.thoughts);return{thoughts:h.thoughts||void 0,data:h.result,succeedImmediately:!1,urlAfterCommand:this.browser.url()}}catch(h){let f=h.message;throw f.includes("MaxGenerationLengthExceededError")?new w("UserConfigurationError","You tried to extract too much data. Please rephrase your query to limit the results returned or use a JavaScript step in the browser instead."):f.includes("AIProviderError")&&f.includes("time")?new w("AIProviderError","The AI provider responded with an error. This may be because you tried to extract too much data. Please limit extraction results to 2000 characters.",{errOptions:{cause:h}}):h}}case"NAVIGATE":if(!Is(n.url)&&!Os(n.url,this.browser.baseUrl))throw new w("ActionFailureError",`Invalid URL provided to navigate command: ${n.url}`);await this.browser.navigate({url:n.url,loadTimeoutMs:n.loadTimeout?n.loadTimeout*1e3:void 0});break;case"DIALOG":this.browser.registerDialogHandler(n.action);break;case"CAPTCHA":throw new w("UserConfigurationError","Captcha solving is no longer available on Momentic");case"GO_BACK":await this.browser.goBack();break;case"GO_FORWARD":await this.browser.goForward();break;case"SCROLL_LEFT":case"SCROLL_RIGHT":case"SCROLL_DOWN":case"SCROLL_UP":{let m,g;if(n.target&&An(n.target))await this.browser.hoverUsingVisualCoordinates(n.target.pixels);else if(n.target&&n.target.elementDescriptor.trim()){let{elementInteractedDisplayString:y,thoughts:E}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:n.target,cache:n.cache?.target,action:b=>this.browser.hover(b),options:{...n,targetName:"target",disableGlobalLocatorRedirect:!0,disableCache:i}});m=y,g=E}let h=this.browser.getViewport()?.height??Mo.height,f=this.browser.getViewport()?.width??Mo.width;switch(n.type){case"SCROLL_UP":await this.browser.scrollVertical(-(n.deltaY??h));break;case"SCROLL_DOWN":await this.browser.scrollVertical(n.deltaY??h);break;case"SCROLL_LEFT":await this.browser.scrollHorizontal(-(n.deltaX??f));break;case"SCROLL_RIGHT":await this.browser.scrollHorizontal(n.deltaX??f);break}return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m,thoughts:g}}case"WAIT_FOR_URL":{if(n.timeout&&n.timeout>1800)throw new w("UserConfigurationError",`Wait for URL timeout of ${n.timeout} exceeds the maximum allowed value of 30 minutes.`);let m=n.matcher;await this.browser.waitForUrl({beforeUrl:this.browser.url(),matcher:m},{timeout:n.timeout?n.timeout*1e3:void 0,negated:n.negated,caseInsensitive:n.caseInsensitive});break}case"WAIT":if(n.delay>1800)throw new w("UserConfigurationError",`Wait timeout of ${n.delay} seconds exceeds the maximum allowed value of 30 minutes`);let c=n.delay*1e3;await J(c,this.executeAbortController.signal);break;case"REFRESH":await this.browser.refresh({loadTimeoutMs:n.loadTimeout?n.loadTimeout*1e3:void 0});break;case"CLICK":{if(An(n.target)){await this.browser.clickUsingVisualCoordinates(n.target.pixels,n);break}let m=this.browser.url(),{elementInteractedDisplayString:g,result:h,thoughts:f}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,target:n.target,command:n,cache:n.cache?.target,action:E=>this.browser.click(E,this.createCallbacksForBrowser(this.orgId),n),options:{disableCache:i,targetName:"target",...n}}),y={urlAfterCommand:this.browser.url(),succeedImmediately:!1,elementInteracted:g,thoughts:f,data:h.downloadedFile?{downloadedFile:h.downloadedFile}:void 0};return Hm(m,y.urlAfterCommand)&&(y.succeedImmediately=!0,y.succeedImmediatelyReason="URL changed"),y}case"COPY":return await this.browser.copy(n.value),{succeedImmediately:!1,data:n.value,urlAfterCommand:this.browser.url()};case"PASTE":{await this.browser.paste();break}case"DRAG":{if(An(n.fromTarget)&&An(n.toTarget)){await this.browser.dragAndDropUsingVisualCoordinates(n.fromTarget.pixels,n.toTarget.pixels,{hoverDurationMs:n.hoverSeconds?n.hoverSeconds*1e3:void 0});break}if(An(n.fromTarget)||An(n.toTarget))throw new Error("Drag and drop targets must be both coordinates or both descriptions");let{elementInteractedDisplayStrings:m,thoughts:g}=await this.wrapMultiElementTargetingCommand({ctx:e,tracer:t,command:n,targetNames:["fromTarget","toTarget"],descriptions:[n.fromTarget,n.toTarget],caches:[n.cache?.fromTarget,n.cache?.toTarget],action:(h,f)=>this.browser.dragAndDrop(h,f,{hoverDurationMs:n.hoverSeconds?n.hoverSeconds*1e3:void 0,steps:n.steps}),options:{useSelector:!!n.useSelector,disableCache:i}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m[0],thoughts:g}}case"MOUSE_DRAG":{let m=parseInt(n.deltaX),g=parseInt(n.deltaY),h=n.steps??5;if(isNaN(m)||isNaN(g))throw new w("ActionFailureError",`Invalid pixel values passed to mouse drag command: (${n.deltaX}, ${n.deltaY})`);if(n.target&&An(n.target)){await this.browser.mouseDragUsingVisualCoordinates({deltaX:m,deltaY:g,steps:h,fromTarget:n.target.pixels});break}let f,y;if(n.target?.elementDescriptor){let{elementInteractedDisplayString:E,thoughts:b}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:n.target,cache:n.cache?.target,action:async x=>this.browser.mouseDrag(m,g,h,x.locator,{force:n.force}),options:{disableCache:i,targetName:"target",...n}});f=E,y=b}else await this.browser.mouseDrag(m,g,h,void 0,{force:n.force});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:f,thoughts:y}}case"SELECT_OPTION":{if(!vo(n.target))throw new Error("Select with x/y is not supported yet");let m=n.target.elementDescriptor,g=n.choice,{elementInteractedDisplayString:h,thoughts:f}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:{type:"description",elementDescriptor:m},cache:n.cache?.target,action:y=>this.browser.selectOption(y,g,n.force),options:{...n,targetName:"target",disableCache:i,source:Ol(n)}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:h,thoughts:f}}case"TAB":{let m={loadTimeoutMs:n.loadTimeout?n.loadTimeout*1e3:void 0,retry:!0};await this.browser.switchToPage(n.action,m);break}case"NEW_TAB":await this.browser.createNewTab(n.url,{loadTimeoutMs:n.loadTimeout?n.loadTimeout*1e3:void 0});break;case"COOKIE":if(!n.value)break;let l=await this.browser.setCookie(n.value);a.debug({results:l},"Set cookies");break;case"LOCAL_STORAGE":if(!n.value||!n.key)break;await this.browser.setLocalStorage(n.key,n.value);break;case"JAVASCRIPT":{let m;try{n.environment==="BROWSER"?(m=await this.browser.evaluateCodeInPage({code:n.code,fragment:n.fragment??!1,context:o.toObjectCopy(),timeoutMs:n.timeout?n.timeout*1e3:void 0}),a.info({result:m},"Executed JavaScript in browser")):m=await Fn({orgId:this.orgId,code:n.code,fragment:!!n.fragment,context:o,timeoutMs:n.timeout?n.timeout*1e3:void 0,logger:a,localTools:this.localCodeEvalTools,signal:this.executeAbortController.signal,callbacks:{onPersistentVariableUpdates:async g=>{if(!this.options?.scratchPadId){a.warn({updates:g},"Got persistent variable updates but scratch pad is not available");return}await this.storage.savePersistentVariables?.({scratchPadId:this.options?.scratchPadId,orgId:this.orgId,updates:g,logger:a})}}})}catch(g){throw this.throwIfClosed(),new w("ActionFailureError",g instanceof Error?g.message:`${g}`,{errOptions:{cause:g}})}try{JSON.stringify(m)}catch(g){throw new w("ActionFailureError",`Return value is not serializable: ${g instanceof Error?g.message:`${g}`}`,{errOptions:{cause:g}})}return{urlAfterCommand:this.browser.url(),succeedImmediately:!1,data:m}}case"TYPE":{if(n.target&&An(n.target)){await this.browser.clickUsingVisualCoordinates(n.target.pixels,n),await this.browser.type(n.value,{force:n.force,clearContent:n.clearContent,forceClearContent:n.forceClearContent,delay:n.delay,pressEnter:n.pressEnter},!0);break}let m=this.browser.url(),g,h,f=SO(n.target),y=this.browser.userBrowserSettings.globalLocatorRedirect===void 0||this.browser.userBrowserSettings.globalLocatorRedirect==="always";if(f){let{elementInteractedDisplayString:b,thoughts:x}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:f,cache:n.cache?.target,action:P=>this.browser.typeIntoTarget(n.value,P,{force:n.force,clearContent:n.clearContent,forceClearContent:n.forceClearContent,delay:n.delay,pressEnter:n.pressEnter,relativePosition:n.relativePosition}),options:{...n,targetName:"target",disableCache:i,disableGlobalLocatorRedirect:!y,source:Ol(n)}});g=b,h=x}else await this.browser.type(n.value,{force:n.force,clearContent:n.clearContent,forceClearContent:n.forceClearContent,delay:n.delay,pressEnter:n.pressEnter},!0);let E={urlAfterCommand:this.browser.url(),succeedImmediately:!1,elementInteracted:g,thoughts:h};return Hm(m,E.urlAfterCommand)&&(E.succeedImmediately=!0,E.succeedImmediatelyReason="URL changed"),E}case"HOVER":{if(An(n.target)){await this.browser.hoverUsingVisualCoordinates(n.target.pixels);break}let{elementInteractedDisplayString:m,thoughts:g}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:n.target,cache:n.cache?.target,action:h=>this.browser.hover(h),options:{...n,targetName:"target",disableCache:i}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m,thoughts:g}}case"FOCUS":{if(!vo(n.target))throw new Error("Focus with x/y is not supported yet");let{elementInteractedDisplayString:m,thoughts:g}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,command:n,target:n.target,cache:n.cache?.target,action:h=>this.browser.focus(h),options:{...n,targetName:"target",disableCache:i}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m,thoughts:g}}case"BLUR":{if(n.target&&!vo(n.target))throw new Error("Blur with x/y is not supported yet");if(!n.target||!n.target.elementDescriptor)return await this.browser.blur(null),{succeedImmediately:!1,urlAfterCommand:this.browser.url()};let{elementInteractedDisplayString:m,thoughts:g}=await this.wrapElementTargetingCommand({ctx:e,tracer:t,target:n.target,command:n,cache:n.cache?.target,action:h=>this.browser.blur(h),options:{...n,targetName:"target",disableCache:i}});return{succeedImmediately:!1,urlAfterCommand:this.browser.url(),elementInteracted:m,thoughts:g}}case"PRESS":let u=this.browser.url();await this.browser.press(n.value,{repeat:n.repeat,convertMeta:n.convertMeta??!0,delayMs:n.delayMs});let d={urlAfterCommand:this.browser.url(),succeedImmediately:!1};return Hm(u,d.urlAfterCommand)&&(d.succeedImmediately=!0,d.succeedImmediatelyReason="URL changed"),d;case"KEY_DOWN":return await this.browser.keyDown(n.value,{convertMeta:n.convertMeta??!0}),{urlAfterCommand:this.browser.url(),succeedImmediately:!1};case"KEY_UP":return await this.browser.keyUp(n.value,{convertMeta:n.convertMeta??!0}),{urlAfterCommand:this.browser.url(),succeedImmediately:!1};case"REQUEST":{let m=new lK,g=sK(fetch,m),h;try{h=new URL(n.url).hostname}catch{}let f=await sp({command:n,baseUrl:this.browser.baseUrl,logger:a,fetchImplementation:g});return{data:bl.parse({...f,cookies:ud(m,h)}),succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"GRAPHQL_REQUEST":return{data:await fO({command:n,baseUrl:this.browser.baseUrl,logger:a}),succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"VISUAL_DIFF":return pO({ctx:e,tracer:t,command:n,disableCache:i,browser:this.browser,logger:a,screenshotStorage:this.visualDiffScreenshotStorage,targetingWrapper:m=>this.wrapElementTargetingCommand(m)});case"FILE_UPLOAD":{let m,g;if(n.fileSource.type==="URL"?(g=n.fileSource.url,m=await _P({uri:n.fileSource.url,logger:a,orgId:this.orgId})):n.fileSource.type==="USER_FILE"&&(g=n.fileSource.name,m=await this.uploadedFileStorage?.getFileForUpload(n.fileSource.name,this.orgId)),!m)throw new w("UserConfigurationError",`Attempted to use non-existent file for upload step: ${g}`);await this.browser.setFileChooserHandler({...m,filename:n.filename});break}case"AUTH_SAVE":return{data:await this.browser.saveAuthState(),succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"AUTH_LOAD":{let m;if(!n.storageState.trim())m=void 0;else if(m=await Fn({orgId:this.orgId,code:n.storageState,fragment:!1,context:o,logger:a,localTools:this.localCodeEvalTools,signal:this.executeAbortController.signal}),typeof m!="object")throw new w("ActionFailureError",`Credentials must evaluate to an object (received ${typeof m} instead)`);let g;try{g=lA.optional().parse(m)}catch(h){throw new w("ActionFailureError",`Credentials provided do not follow the required format: ${h}`)}await this.browser.loadAuthState(g);break}case"ELEMENT_CHECK":{let m=(n.timeout??dr)*1e3,g=this.generator.getAgentConfig()?.assertion;if(dO(n.assertion)&&!n.useSelector&&n.target.type==="description"&&g&&g!=="v1"){let f={id:n.id,type:"AI_ASSERTION",assertion:`There is no element on the page closely matches the following description. If the description has single quotes, remember that requires an exact text substring match. Description: ${n.target.elementDescriptor}`,iframeUrl:n.iframeUrl,timeout:n.timeout,source:"NEGATED_CHECK",cache:n.cache&&"memory"in n.cache?{memory:n.cache?.memory}:void 0};try{let y=await ip({command:f,logger:a,aiPageFiltering:!!this.options?.aiPageFiltering,fixtures:this.getControllerFixtures(e),useMemory:this.shouldUseMemory()});return{succeedImmediately:!1,thoughts:`The element described does not exist on the page: ${y.thoughts}`,urlAfterCommand:this.browser.url(),afterScreenshotOverride:y.afterScreenshotOverride}}finally{f.cache?.memory&&Xc(n,f.cache?.memory.traces,a)}}let h=await uO({command:n,tracer:t,timeoutMs:m,targetingWrapper:f=>this.wrapElementTargetingCommand(f),fixtures:this.getControllerFixtures(e),disableCache:i});return{fail:!h.success,data:h.data,elementInteracted:h.elementInteractedDisplayString,thoughts:h.err?.message??h.thoughts??`Element assertion ${h.success?"succeeded":"failed"}.`,succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"PAGE_CHECK":{let m=await an({action:async()=>hO({assertion:n.assertion,browser:this.browser,logger:a,timeout:n.timeout,signal:this.executeAbortController.signal,autoExpandIframes:!!this.browser.userBrowserSettings.autoExpandIframes}),frameConfig:n.iframeUrl?{type:"url",url:n.iframeUrl}:void 0,browser:this.browser,logger:a});return{fail:!m.success,data:m.data,thoughts:m.success?"Page assertion passed.":m.err?.message??`Page assertion still failing after ${n.timeout} seconds.`,urlAfterCommand:this.browser.url(),succeedImmediately:!1}}case"REGISTER_REQUEST_LISTENER":{let m=new Qo(n.requestMatcher),g=this.browser.registerRequestListener(m);return this.registeredListeners[n.key]=g.then(async h=>await cy(h)).catch(h=>{a.error({err:h},"Failed to get request listener response")}),{succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"AWAIT_LISTENER":{let m=this.registeredListeners[n.key];if(!m)throw new w("ActionFailureError",`No listener registered with key: ${n.key}`);let g=n.timeout??10;return{data:await Y(m,{milliseconds:g*1e3,message:`Request listener timed out after ${g} seconds`}),succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"RECORD_REQUESTS":{let m=new Qo(n.requestMatcher);return this.recordedRequests[n.key]={},this.browser.registerRequestRecorder(n.key,{matches:g=>m.matches({url:g.request.url,method:g.request.method}),onRequestStart:(g,h)=>{this.recordedRequests[n.key][g]=qm(h)},onRequestComplete:(g,h)=>{this.recordedRequests[n.key]?.[g]&&(this.recordedRequests[n.key][g]=qm(h))}}),{succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"GET_RECORDED_REQUESTS":{let m=this.recordedRequests[n.key];if(!m)throw new w("ActionFailureError",`No recorder registered with key: ${n.key}`);return delete this.recordedRequests[n.key],{data:Object.values(m),succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"SET_HEADER":{let m;return n.requestMatcher&&(m=new Qo(n.requestMatcher)),this.browser.setHeader(n.name,n.value,m),{succeedImmediately:!1,urlAfterCommand:this.browser.url()}}case"MOCK_ROUTE":return{data:{key:this.browser.registerMock(n.key,new Qo(n.requestMatcher),async(g,h)=>{let f=await Fn({orgId:this.orgId,code:n.responseGenerator,fragment:!1,context:o,timeoutMs:void 0,logger:a,localTools:this.localCodeEvalTools,mock:{request:g,response:h},disallowVariableUpdates:!0,responseSerialization:"RESPONSE"}),y=OA.parse(f);return new Response(y.body,{status:y.status,headers:y.headers})},n.fetchOriginalResponse??!1)},succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"REMOVE_ROUTE_MOCK":return this.browser.removeMock(n.key),{succeedImmediately:!1,urlAfterCommand:this.browser.url()};case"OFFLINE_MODE":return await this.browser.setOfflineMode(n.enable),{succeedImmediately:!1,urlAfterCommand:this.browser.url()};default:return(m=>{throw"If Typescript complains about the line below, you missed a case or break in the switch above"})(n)}return{succeedImmediately:!1,urlAfterCommand:this.browser.url()}}async getReverseMappedDescription({browserState:e,targetId:t,disableCache:n,screenshot:o}){return(await this.generator.getReverseMappedDescription({browserState:e,target:t,screenshot:o},{disableCache:n,abortSignal:this.executeAbortController.signal,loggerTags:ye(this.logger)})).phrase}async stopRecordMode(){this.recordAbortController?.abort(),await this.browser.clearAllCdpHighlights()}async startRecordMode({params:e,abortController:t,isClickToRecord:n}){this.recordAbortController=t;let o=new Qm({signal:t.signal,...e});return await this.browser.startRecording(this.recordAbortController.signal,o,n),o}async runSectionAutohealing(e){return this.generator.getAutohealingProposal(e,{disableCache:!0,abortSignal:this.executeAbortController.signal,loggerTags:ye(this.logger)})}async getFailureRecoveryPlan(e){return this.generator.getFailureRecoveryPlan(e,{disableCache:!0,abortSignal:this.executeAbortController.signal,loggerTags:ye(this.logger)})}};import{mkdirSync as IK}from"fs";import{tmpdir as OK}from"os";import xO from"path";import{diff as PK}from"deep-object-diff";import{cloneDeep as Fy}from"lodash-es";import vO from"fontoxpath";import cK from"@prettier/plugin-xml";import uK from"prettier";import{DOMParser as dK,XMLSerializer as mK}from"slimdom";var pK=new Set(["android.webkit.webview","com.facebook.react.views.webview.reactwebview","com.tencent.smtt.sdk.webview","com.tencent.smtt.sdk.x5webview","org.xwalk.core.xwalkview","com.uc.webview.export.webview"]);function gK(r){let e=r.toLowerCase();return e.endsWith("webview")||pK.has(e)}function su(r){return!!(gK(r.tagName)||r.getAttribute("package")==="com.android.chrome"&&r.getAttribute("content-desc")==="Web View"&&yO(r.tagName.toLowerCase()).startsWith("frame"))}function yO(r){let e=["android.widget.","android.view.","android.webkit.","android.app.","android.support.","androidx.","com.android.inputmethod."];for(let t of e)if(r.startsWith(t))return r.substring(t.length);return r}var hK=new Set(["index","package","a11y-important","screen-reader-focusabl"]),fK=new Set(["selected","checked","checkable","clickable","enabled","focusable","focused","long-clickable","password","scrollable","selected","showing-hint","context-clickable","multiline","text-entry-key","heading","dismissable","screen-reader-focusable","content-invalid","a11y-focused"]),SK=new Set(["text","hint"]),yK=new Set(["live-region","drawing-order"]),bK=new Set(["displayed","enabled"]);function EK(r,e){let t={};for(let[n,o]of Object.entries(e))hK.has(n)||n==="class"&&r===o||n==="focusable"&&o==="true"&&e.clickable==="true"||fK.has(n)&&o==="false"||SK.has(n)&&o===""||bK.has(n)&&o==="true"||yK.has(n)&&o==="0"||n!=="id"&&(t[n]=o);return t}function bO(r,e,t){let{prunedDocument:n,idToElement:o,prunedIdToElement:i,idCounter:a,opts:s}=r,c=a.value++;t.setAttribute("id",String(c));let l={};for(let p of e.attributes){let m=p.name,g=p.value;g!=null&&(l[m]=String(g))}let u=EK(e.tagName,l);for(let[p,m]of Object.entries(u))t.setAttribute(p,m);if(o.set(c,e),i.set(c,t),su(e)){let p=s?.injectedWebviewContent??"";if(s?.removeWebviewContent){for(;t.firstChild;)t.removeChild(t.firstChild);return}else if(!s?.disableMomenticAccessibilityTree&&p.trim().length>0){for(;t.firstChild;)t.removeChild(t.firstChild);p.trim().length>0&&t.appendChild(n.createCDATASection(`
4575
4575
  ${p}
4576
- `));return}}let d=Array.from(e.childNodes??[]);for(let p of d){let m=p.nodeType;if(m===3){let g=p.nodeValue;g&&g.trim().length>0&&t.appendChild(n.createTextNode(g));continue}if(m===1){let g=p;if(!AK(g,s?.viewportBounds))continue;let h=n.createElement(yO(g.tagName));bO(r,g,h),t.appendChild(h)}}}function TK(r,e,t,n){let o=r.parseFromString("<hierarchy/>","text/xml"),i=new Map,a={prunedDocument:o,idToElement:t,prunedIdToElement:i,idCounter:{value:0},opts:n},s=o.documentElement;bO(a,e,s);let c=new mK().serializeToString(o);return{prunedDocument:o,prunedIdToElement:i,xml:c}}async function EO(r,e){let t=new dK,n=t.parseFromString(r,"text/xml"),o=new Map,i=n.documentElement;if(!i)throw new w("InternalWebAgentError","No root element found in XML");if(i.tagName!=="hierarchy")throw new w("InternalWebAgentError","No hierarchy element found in XML");let{prunedDocument:a,prunedIdToElement:s,xml:c}=TK(t,i,o,e);return{xml:await uK.format(c,{parser:"xml",plugins:[cK],printWidth:120,tabWidth:1,singleAttributePerLine:!1}),originalXml:r,document:n,idToElement:o,prunedDocument:a,prunedIdToElement:s}}function vK(r){let e=[],t=r;for(;t;){let n=t.tagName,o=t.parentElement,i=1;if(o){let a=Array.from(o.children).filter(s=>s.tagName===n);for(let s=0;s<a.length;s++)if(a[s]===t){i=s+1;break}}e.unshift(`${n}[${i}]`),t=o}return`/${e.join("/")}`}function up(r,e){let t=r.idToElement.get(e);if(t)return vK(t)}function ky(r,e){let t=r.idToElement.get(e);if(!t)return;let n=t.cloneNode(!0);for(let o of Array.from(n.children)){let i=o;for(let a of Array.from(i.children))i.removeChild(a)}return n.outerHTML}function sa(r){if(!r.hasAttribute("bounds"))return;let e=r.getAttribute("bounds");if(!e)return;let t=e.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/);if(t){let n=parseInt(t[1],10),o=parseInt(t[2],10),i=parseInt(t[3],10),a=parseInt(t[4],10);if(Number.isFinite(n)&&Number.isFinite(o)&&Number.isFinite(i)&&Number.isFinite(a))return[n,o,i,a]}}function AK(r,e){if(!e)return!0;let t=sa(r);if(!t||t.length<4)return!0;let n=t[0],o=t[1],i=t[2],a=t[3];return!(i<=e.left||n>=e.right||a<=e.top||o>=e.bottom)}function TO(r,e){if(r&&!(!e||e.length===0))return Object.fromEntries(e.map(t=>[t,r.getAttribute(t)]).filter(([,t])=>t!==null))}function AO({requirements:r,element:e}){let t;if((r?.positionSpecificity||r?.shapeSpecificity)&&(t=sa(e),!t))throw new w("ActionFailureError","Element to cache has no bounds or unexpected bounds format");return{requiredText:r?.textRequired?e.getAttribute("text")??void 0:void 0,requiredAttributes:TO(e,r?.attributesRequired),requiredBounds:r?.boundsRequired,position:r?.positionSpecificity?{x1:t[0],y1:t[1],x2:t[2],y2:t[3],tolerance:r?.positionSpecificity}:void 0,shape:r?.shapeSpecificity?{width:t[2]-t[0],height:t[3]-t[1],tolerance:r?.shapeSpecificity}:void 0}}function RO({aiResponse:r,description:e,emulatorState:t,memory:n,useMemory:o}){let i=t.graph.idToElement.get(r.id);if(!i)throw new w("InternalWebAgentError",`Could not find node with id: ${r.id}`);let a=sa(i);if(!a)throw new w("InternalWebAgentError",`Node ${r.id} has no bounding box: ${i.outerHTML}`);let s=up(t.graph,r.id)??"",c=ky(t.graph,r.id)??"",l=AO({requirements:r.requirements,element:i}),u=[];r.additionalElements&&(u=r.additionalElements.map(({id:p,requirements:m})=>{let g=t.graph.idToElement.get(p);if(!g)return;let h=up(t.graph,p);return h?{xPath:h,requirements:AO({requirements:m,element:g})}:void 0}).filter(p=>!!p));let d;if(su(i)&&r.inWebview!==!1?d={type:"WEBVIEW",resolvedDescription:e,xPath:s}:d={type:"NATIVE",bounds:a,resolvedDescription:e,xPath:s,elementOnlySerializedXml:c,requirements:l,requiredRelatedElements:u},o)if(r.updatedMemory){let p={type:"GCS_TRACES",traces:r.updatedMemory};d.memory=p}else n&&(d.memory=n);return{target:d,resolvedNode:i}}function CO(r){return r?.type==="WEBVIEW"?r.browserCache?.memory:void 0}var wK=.1,RK=.25;function dp(r,e,t,n){let o=Math.abs(e-t);switch(r){case"precise":return o<=n;case"narrow":return o<=Math.abs(e)*wK;case"broad":return o<=Math.abs(e)*RK;case"irrelevant":return!0}}function CK(r,e){let t=e.x2-e.x1,n=(e.x1+e.x2)/2,o=(r[0]+r[2])/2;if(!dp(e.tolerance,n,o,Math.min(1,t)))return!1;let i=e.y2-e.y1,a=(e.y1+e.y2)/2,s=(r[1]+r[3])/2;return dp(e.tolerance,a,s,Math.min(1,i))}function xK(r,e){return dp(e.tolerance,e.width,r[2]-r[0],Math.min(1,e.width))?dp(e.tolerance,e.height,r[3]-r[1],Math.min(1,e.height)):!1}var wO=(r,e,t)=>{if(!e)return;let{requiredAttributes:n,requiredText:o,requiredBounds:i,position:a,shape:s}=e;if(o!==void 0&&o.length>0){let c=Kc(r);if(c!==o)throw new gt(`Resolved element text mismatch: expected ${o}, got ${c}`)}if(n)for(let[c,l]of Object.entries(n)){let u=r.getAttribute(c)??void 0;if(u!==l)throw new gt(`Attribute ${c} mismatch: expected ${l}, got ${u}`)}if(i&&t&&!t.targetBounds.every((l,u)=>l===t.newElementBounds[u]))throw new gt(`Bounds changed from [${t.targetBounds.join(",")} ] to [${t.newElementBounds.join(",")} ]`);if(a&&t&&!CK(t.newElementBounds,a))throw new gt(`Position mismatch: expected ${JSON.stringify(a)}, got ${JSON.stringify(t.newElementBounds)}`);if(s&&t&&!xK(t.newElementBounds,s))throw new gt(`Shape mismatch: expected ${JSON.stringify(s)}, got ${JSON.stringify(t.newElementBounds)}`)};async function mp(r){let{target:e,domState:t}=r,{graph:n}=t,{document:o}=n,i=se();if(e.type==="WEBVIEW")return _K(e,r);if(!e.xPath)throw new w("ActionFailureError","Native element cache has no XPath");let a=vO.evaluateXPathToFirstNode(e.xPath,o,null,null);if(!a)throw new gt(`Could not resolve cached target via XPath: ${e.xPath}`);if(e.requiredRelatedElements){let p=e.requiredRelatedElements;i.startSection("Validate related elements are similar enough to past runs",()=>{for(let m of p){let g=vO.evaluateXPathToFirstNode(m.xPath,o);if(!g)throw new gt(`Required related element not found for XPath: ${m.xPath}`);wO(g,m.requirements)}})}let s=sa(a);if(!s)throw new gt("Resolved native element has no bounding box");if(!e.bounds)throw new gt("Native element cache has no bounds");wO(a,e.requirements,{targetBounds:e.bounds,newElementBounds:s});let c;for(let[p,m]of n.idToElement.entries())if(m===a){c=p;break}let l=e.elementOnlySerializedXml,u=e.xPath;return c!==void 0&&(l=ky(n,c)??l,u=up(n,c)??u),{resolvedTarget:{...e,resolvedNode:a,bounds:s,elementOnlySerializedXml:l,xPath:u}}}async function _K(r,e){let{stateManager:t,logger:n,signal:o}=e,i=se(),a=await t.getActiveWebview();if(!a||!a.browserController)throw n.error({webview:a?{...a,browserController:!!a.browserController}:void 0},"resolveTargetCacheInWebView: No browser controller attached"),new gt("No browser controller is attached to the requested webview");let s=a.browserController;if(!r.browserCache)throw n.error({target:r},"resolveTargetCacheInWebView: No browser target available on cache"),new gt("No browser target available on cache");let c=r.browserCache,{finalTarget:l}=await i.startAsyncSection("Resolve target in webview",()=>s.resolveCachedTargetForAction({ctx:null,cache:c,options:{disableGlobalLocatorRedirect:e.disableTargetRedirection,resolveTargetOptions:{logger:n,signal:o,skipWaitForPageLoad:!0,skipSavingVisualAttributes:!0}},logger:n}));return{resolvedTarget:{...r,controller:a.browserController,browserTarget:l}}}function la(r){let{command:e,cacheKey:t="cache",targetName:n="target",updatedCache:o}=r;Bi(e)&&(e[t]={...e[t],[n]:ja.parse(o)},r.updatedWithAI&&(e[t].updatedAt=new Date,e[t].updatedAtLoggerTags=ye(r.logger)))}function pp(r){if(r.type==="WEBVIEW")return{type:"WEBVIEW",resolvedDescription:r.resolvedDescription,xPath:r.xPath,browserCache:r.browserCache,memory:r.memory};let{resolvedNode:e,...t}=r;return{...t}}var Rt=class{driver;generator;stateManager;logger;fixtures;aborter;orgId;aiSettings;options;constructor(e){this.stateManager=e.stateManager,this.generator=e.generator,this.driver=e.driver,this.logger=e.logger,this.fixtures=e.fixtures,this.aborter=e.aborter,this.orgId=e.orgId,this.aiSettings=e.aiSettings,this.options=e.options}shouldUseMemoryForCommand(e){return this.aiSettings?.useMemory&&!e?.disableCache}async findElement({description:e,tracer:t,skipFetchingFullWebviewContent:n=!1,removeWebviewContent:o=!1,useMemory:i=!1,memory:a,webviewMemory:s,metadata:c}){let l=this.logger.child({...c}),u=await t.startAsyncSection("Get emulator state",async()=>{let f=await this.stateManager.getDomState({skipFetchingFullWebviewContent:n,removeWebviewContent:o}),y=await this.stateManager.getCurrentScreenshotPngString();return{emulatorState:f,screenshot:y}}),d;try{d=await t.startAsyncSpan("AI_LOCATOR_CALL",async f=>{let y=await this.generator.getAndroidElementLocation({description:e,screenXml:u.emulatorState.graph.xml,screenshot:u.screenshot,memory:i?a:void 0},{logger:l,loggerTags:ye(l),abortSignal:this.aborter.controller?.signal,useMemory:i,agentConfigVersion:this.aiSettings.agentConfig?.["android-locator"]});return f.result=y,y})}catch(f){throw this.throwIfAborted(),l.error({err:f},"Failed to locate element"),new w("InternalWebAgentError",`Failed to locate element: ${f instanceof Error?f.message:f}`,{errOptions:{cause:f}})}if(d.id===-1){let f=d.updatedMemory?{type:"GCS_TRACES",traces:d.updatedMemory}:void 0;return{success:!1,thoughts:d.thoughts??"No matching element found",updatedLocatorMemory:f}}let{target:p,resolvedNode:m}=RO({aiResponse:d,description:e,emulatorState:u.emulatorState,memory:a,useMemory:i});if(p.type==="NATIVE")return t.addSpan({type:"TARGET_RESOLUTION",startTime:Date.now(),endTime:Date.now(),result:{serializedElement:p.elementOnlySerializedXml??"Unknown element"},attributes:{},subSpans:[]}),{success:!0,resolvedTarget:{...p,resolvedNode:m},thoughts:d.thoughts};let{browserLocateResult:g,browserController:h}=await t.startWebviewTrace(async()=>{let f=await this.stateManager.getActiveWebview();if(!f||!f.browserController)throw new w("InternalWebAgentError","No browser controller is attached to the requested webview");return{browserLocateResult:await f.browserController.locateElement({description:e,disableCache:!1,useMemory:i,memory:i?s:void 0,logger:this.logger,skipWait:!0,skipSavingVisualAttributes:!0}),browserController:f.browserController}});return t.addSpan({type:"TARGET_RESOLUTION",startTime:Date.now(),endTime:Date.now(),result:{serializedElement:g.target.nodeOnlySerializedHtml??"Unknown HTML element in webview"},attributes:{},subSpans:[]}),{success:!0,resolvedTarget:{...p,controller:h,browserTarget:{...g.resolution,serverSideBoundingBox:await g.resolution.locator.boundingBox({timeout:5e3})},browserCache:g.target},thoughts:g.thoughts}}async targetingActionWithAILocator(e){let{action:t,command:n,description:o,tracer:i,cacheKey:a,targetName:s,cache:c,skipFetchingFullWebviewContent:l,removeWebviewContent:u,metadata:d}=e,p=await this.findElement({description:o,tracer:i,skipFetchingFullWebviewContent:l,removeWebviewContent:u,useMemory:this.shouldUseMemoryForCommand(n),memory:c?.memory,webviewMemory:CO(c),metadata:d});if(!p.success){if(p.updatedLocatorMemory&&c){let h={...c,memory:p.updatedLocatorMemory};la({command:n,cacheKey:a,targetName:s,updatedCache:h,updatedWithAI:!0,logger:this.logger})}throw new w("NoMatchingElementError",p.thoughts??"No matching element found")}let m=p.thoughts,g=await t(p.resolvedTarget);return la({command:n,cacheKey:a,targetName:s,updatedCache:p.resolvedTarget,updatedWithAI:!0,logger:this.logger}),{result:g,thoughts:m}}async wrapTargetingAction(e){let{action:t,description:n,command:o,cacheKey:i="cache",targetName:a="target",cacheIsInvalidAfterResolution:s,tracer:c,skipFetchingFullWebviewContent:l=!1,removeWebviewContent:u=!1,disableTargetRedirection:d=!1}=e,p,m={commandId:o.id};if(i==="cache"&&"cache"in o&&o.cache){let b=o.cache;a==="target"&&"target"in b?p=b.target:a==="fromTarget"&&"fromTarget"in b?p=b.fromTarget:a==="toTarget"&&"toTarget"in b&&(p=b.toTarget)}let g=!1,h=Fy(p);if(o.disableCache&&(this.logger.debug({command:o},"Cache explicitly disabled for command"),g=!0,h=void 0),s&&(g=!0,h=void 0),h&&h?.resolvedDescription!==n&&(this.logger.info({description:n,cacheDescription:h?.resolvedDescription},"Cache description mismatch, clearing it automatically"),g=!0,h=void 0),!h)return this.logger.info({description:n,cacheBustedBeforeAction:g},"Prompting AI for a new element location"),this.targetingActionWithAILocator({action:t,command:o,description:n,tracer:c,cacheKey:i,targetName:a,cache:p,skipFetchingFullWebviewContent:l,removeWebviewContent:u,metadata:m});let f=h.type==="NATIVE"?!!h.requirements:!!h.browserCache?.requirements,y=h.type==="NATIVE"?!!h.requiredRelatedElements?.length:!!h.browserCache?.additionalElements?.length,E;try{this.options?.emulator?.waitForStability&&await this.stateManager.waitForPageSourceStability({timeoutMs:3e3,signal:this.aborter.controller?.signal,reason:"Waiting for stability before cache resolution"});let{resolvedTarget:b,updatedCache:x}=await c.startAsyncSpan("CACHE_RESOLUTION",async O=>{let T=Date.now(),R;for(;Date.now()-T<3e3;){E=await this.stateManager.getDomState({skipFetchingFullWebviewContent:h?.type==="NATIVE"});let D;try{D=(await mp({target:h,domState:E,stateManager:this.stateManager,logger:this.logger,disableTargetRedirection:d})).resolvedTarget}catch(F){if(R=F,F instanceof gt){this.logger.warn({err:F},"Failed to resolve target cache, retrying");continue}throw this.logger.error({err:F},"Failed to resolve target cache"),F}let I=pp(D),k=PK(h,I);return k&&Object.keys(k).length>0&&this.logger.info({cacheDiffs:k},"Successfully resolved target with cache"),O.attributes.serializedElement=D.type==="WEBVIEW"?D.browserCache?.nodeOnlySerializedHtml??"Unknown HTML element in webview":D.elementOnlySerializedXml??"Unknown element",{resolvedTarget:D,updatedCache:I}}throw R}),P=await t(b);return la({command:o,cacheKey:i,targetName:a,updatedCache:x,updatedWithAI:!1,logger:this.logger}),nt.increment("cache_target_resolution_v2",1,["outcome:hit",`platform:mobile-${h.type.toLowerCase()}`,`hasRequirements:${f}`,`hasAdditionalElements:${y}`,`orgId:${this.orgId}`,"cliVersion:0.33.0"]),{result:P,thoughts:"Successfully executed preset action with cache"}}catch(b){if(this.throwIfAborted(),b instanceof w&&b.reason!=="InternalWebAgentError")throw this.logger.error({err:b},"Failed to execute action with target cache (fatal)"),b;return nt.increment("cache_target_resolution_v2",1,["outcome:miss",`platform:mobile-${h.type.toLowerCase()}`,`hasRequirements:${f}`,`hasAdditionalElements:${y}`,`orgId:${this.orgId}`,"cliVersion:0.33.0"]),this.logger.warn({err:b},"Failed to execute action with target cache, retrying with AI"),this.targetingActionWithAILocator({action:t,command:o,description:n,tracer:c,cacheKey:i,targetName:a,cache:h,skipFetchingFullWebviewContent:l,removeWebviewContent:u,metadata:m})}}constructPerformerParams(){return{stateManager:this.stateManager,generator:this.generator,driver:this.driver,logger:this.logger,fixtures:this.fixtures,aborter:this.aborter,orgId:this.orgId,aiSettings:this.aiSettings,options:this.options}}getBoundsFromNativeCache(e){if(!e.bounds)throw new w("ActionFailureError","Native element cache has no bounds");let[t,n,o,i]=e.bounds;if(t===void 0||n===void 0||o===void 0||i===void 0)throw new w("ActionFailureError",`Native element cache has incomplete bounds: [${e.bounds.join(", ")}]`);return{left:t,top:n,width:o-t,height:i-n}}calculateSwipeCoordinates({containerBounds:e,direction:t,desiredDelta:n,edgeMarginPercent:o=.1}){let i=e.left+e.width/2,a=e.top+e.height/2;if(t==="up"||t==="down"){let s=e.height*o,c=e.top+s,l=e.top+e.height-s,u=l-c,d=Math.min(Math.abs(n),u);return{startX:i,startY:t==="down"?l:c,actualDelta:d}}else{let s=e.width*o,c=e.left+s,l=e.left+e.width-s,u=l-c,d=Math.min(Math.abs(n),u);return{startX:t==="right"?l:c,startY:a,actualDelta:d}}}invertDirection(e){if(e==="up")return"down";if(e==="down")return"up";if(e==="left")return"right";if(e==="right")return"left";throw new Error(`Unreachable code: ${e}`)}async performRawSwipe({startX:e,startY:t,deltaPixels:n,direction:o,durationMs:i=300}){let a=Math.abs(n),s=e,c=t;o==="up"||o==="down"?c=o==="up"?t-a:t+a:s=o==="left"?e-a:e+a,await this.driver.performActions([{type:"pointer",id:"finger1",parameters:{pointerType:"touch"},actions:[{type:"pointerMove",duration:0,x:e,y:t},{type:"pointerDown",button:0},{type:"pause",duration:100},{type:"pointerMove",duration:i,x:s,y:c},{type:"pointerUp",button:0}]}]),await this.driver.releaseActions()}throwIfAborted(){this.aborter.controller?.signal.throwIfAborted()}get abortSignal(){return this.aborter.controller?.signal}get aiSettingsCopy(){return Fy(this.aiSettings)}get optionsCopy(){return Fy(this.options)}};function _O(r){return"iterations"in r}function LK(r){let e={relativePosition:r.relativePosition};if(r.iterations!==void 0&&(!Number.isInteger(r.iterations)||r.iterations<1))throw new Error("UserConfigurationError: iterations must be a positive integer");if(r.tapDelayMs!==void 0&&(!Number.isInteger(r.tapDelayMs)||r.tapDelayMs<0))throw new Error("UserConfigurationError: tapDelayMs must be >= 0");if(r.iterations&&r.iterations>1&&r.longPress)throw new Error("UserConfigurationError: Cannot specify both more than one tap iteration and long press at the same time");if(r.tapDelayMs!==void 0&&(!r.iterations||r.iterations<2))throw new Error("UserConfigurationError: tapDelayMs requires iterations >= 2");if(r.longPress){if(r.tapDelayMs!==void 0)throw new Error("UserConfigurationError: tapDelayMs cannot be used with longPress");return{...e,longPress:!0,longPressDurationMs:r.longPressDurationMs}}return r.iterations!==void 0?{...e,iterations:r.iterations,tapDelayMs:r.tapDelayMs}:e}var zs=class extends Rt{async tapOnNativeCoordinates(e){let t=e.x,n=e.y;if(this.logger.info({x:t,y:n},"Tap at coordinates"),"longPress"in e&&e.longPress)return await this.driver.executeScript("mobile: longClickGesture",[{x:t,y:n,duration:e.longPressDurationMs??2e3}]);if(_O(e)){let o=e.tapDelayMs??100;for(let i=0;i<e.iterations;i++)await this.driver.tap({x:t,y:n}),i<e.iterations-1&&await new Promise(a=>setTimeout(a,o));return}await this.driver.tap({x:t,y:n})}async tapOnNativeTarget(e,t){let[n,o,i,a]=e.bounds,s=i-n,c=a-o,l=t?.relativePosition?.x??s/2,u=t?.relativePosition?.y??c/2;l=Math.max(0,Math.min(l,s)),u=Math.max(0,Math.min(u,c));let d=n+l,p=o+u;return await this.tapOnNativeCoordinates({x:d,y:p,...t}),{x:d,y:p}}async tapOnWebviewTarget(e,t){let{controller:n}=e,o,i=1;return t&&_O(t)?(o=t.tapDelayMs,i=t.iterations):t&&"longPress"in t&&(o=t.longPressDurationMs),(await n.browser.click(e.browserTarget,{createIsolatedFolder:()=>{let s=Math.random().toString(36).substring(4),c=xO.join(OK(),"momentic","downloads"),l=xO.join(c,this.orgId,s);return IK(l,{recursive:!0}),l}},{delayMs:o,relativePosition:t?.relativePosition,iterations:i})).coordinates}async tapOnTarget({target:e,options:t}){return await se().startAsyncSpan("EMULATOR_INTERACTION",async o=>{o.attributes.options=t,"type"in e&&e.type==="NATIVE"?o.attributes.point=await this.tapOnNativeTarget(e,t):(o.withinWebview=!0,o.attributes.point=await this.tapOnWebviewTarget(e,t))},{name:"Tap on target"})}async executeTap({command:e}){let t=se(),n=LK(e);if(e.target.type==="coordinates"){let a=await this.driver.getWindowSize(),s=e.target.xPercent*a.width,c=e.target.yPercent*a.height;return await t.startAsyncSpan("EMULATOR_INTERACTION",async()=>{await this.tapOnNativeCoordinates({...n,x:s,y:c})},{name:`Tap at coordinates ${s}, ${c}`}),{success:!0,message:`Tapped at ${s}, ${c}`}}let o=e.target.description,{thoughts:i}=await this.wrapTargetingAction({command:e,tracer:t,action:a=>this.tapOnTarget({target:a,options:n}),description:o});return{success:!0,message:i}}};var ri=class extends Rt{async doPress({keycode:e,longPress:t}){await se().startAsyncSpan("EMULATOR_INTERACTION",async()=>this.driver.executeScript("mobile: pressKey",[{keycode:e,isLongPress:t}]),{name:"Send key events to emulator"})}};var ca=25,gp=class extends Rt{async doType(e){let t=se();if(!e.target){if(e.clearContent)throw new w("UserConfigurationError","Clearing content is only supported when a target is provided to the Type step");return await this.stateManager.waitForPageSourceStability({timeoutMs:2e3,signal:this.aborter.controller?.signal,reason:"Waiting for page to stabilize before typing"}),await this.sendKeys(e),{success:!0,message:"Successfully executed type action"}}if(e.target.type!=="description")throw new w("UserConfigurationError","x/y targets are not supported for the Type step");let{thoughts:n}=await this.wrapTargetingAction({command:e,tracer:t,action:async o=>{"type"in o&&o.type==="NATIVE"?await this.doNativeType(e,o):await this.doWebviewType(e,o)},description:e.target.description});return{success:!0,message:n}}async doWebviewType(e,t){await se().startAsyncSpan("EMULATOR_INTERACTION",async o=>{o.withinWebview=!0;let i={clearContent:e.clearContent,forceClearContent:e.forceClearContent,delay:e.keyPressDelayMs??ca};o.attributes.options=i;let{controller:a,browserTarget:s}=t;await a.browser.typeIntoTarget(e.text,s,i)},{name:"Typing within web view"})}async doNativeType(e,t){let n=new zs(this.constructPerformerParams());e.clearContent?(await n.tapOnNativeTarget(t,{longPress:!0}),await this.clearContent()):await n.tapOnNativeTarget(t),await this.stateManager.waitForPageSourceStability({timeoutMs:2e3,signal:this.aborter.controller?.signal,reason:"Waiting for keyboard to appear before typing"}),await this.sendKeys(e)}async sendKeys(e){let t=se(),n=e.keyPressDelayMs??ca;await t.startAsyncSection("Waiting for system keyboard to open",async(o,i)=>{let a=Date.now();for(;Date.now()-a<2e3;){this.throwIfAborted();let s=Date.now();if(await this.driver.isKeyboardShown())return;let c=Date.now()-s;c<500&&await new Promise(l=>setTimeout(l,500-c))}i.attributes.timedOut=!0}),n!==ca?await t.startAsyncSpan("EMULATOR_INTERACTION",async()=>{await this.driver.updateSettings({keyInjectionDelay:n}),await this.driver.keys(e.text),await this.driver.updateSettings({keyInjectionDelay:ca})},{name:`Typing with a ${n}ms delay`}):await t.startAsyncSpan("EMULATOR_INTERACTION",async()=>{await this.driver.keys(e.text)},{name:`Typing with a ${ca}ms delay`})}async clearContent(){let e=se();try{await e.startAsyncSection("Clearing any content from the focused field",()=>this.clearContentHelper())}catch(t){this.logger.warn({err:t},"Failed to find select all button, continuing...")}}async clearContentHelper(){let e=this.driver.$('//android.widget.LinearLayout[@content-desc="Select all" and @clickable="true"]');await e.waitForExist({timeout:750}),await e.click(),await new ri(this.constructPerformerParams()).doPress({keycode:67})}};import Dr from"zod";var MO=.8,ni=.2,NK=Dr.object({navigationBar:Dr.object({visible:Dr.boolean(),x:Dr.number(),y:Dr.number(),width:Dr.number(),height:Dr.number()}),statusBar:Dr.object({visible:Dr.boolean(),x:Dr.number(),y:Dr.number(),width:Dr.number(),height:Dr.number()})}),Hs=class extends Rt{async getHardcodedScrollableElementBounds(e,t){let n;switch(e.type){case"SCREEN":n=this.getInsetBoundsFromViewport(t);break;case"OPEN_APP":try{let o=NK.parse(await this.driver.executeScript("mobile: getSystemBars",[]));n=this.getInsetBoundsFromViewport(t),o.navigationBar.visible&&(n.height=Math.max(1,n.height-o.navigationBar.height)),o.statusBar.visible&&(n.top+=o.statusBar.height,n.height=Math.max(1,n.height-o.statusBar.height))}catch(o){this.logger.warn({err:o},"Failed to get system bars, using hardcoded bounds"),n=this.getInsetBoundsFromViewport(t)}break;case"OPEN_WEBVIEW":{let o=await this.stateManager.getActiveWebviewNodes();if(o.length===0&&(await this.stateManager.refreshWebviewsManually("get active webview nodes"),o=await this.stateManager.getActiveWebviewNodes()),o.length===0)throw new Error("No active webviews found");if(o.length>1){let a=o.map(s=>({id:s.id,ele:s.originalElement.outerHTML,bounds:s.bounds}));throw new Error(`Multiple active webviews found. Momentic currently only supports a single active webview at a time. Discovered nodes: ${JSON.stringify(a)}`)}let i=o[0]?.bounds;if(!i)throw new Error("No bounds found for active webview");n=this.getInsetBoundsFromBounds(i);break}default:{let o=e;throw new Error("If Typescript complains about the line above, you missed a switch case")}}return n}getInsetBoundsFromViewport(e){let t=Math.floor(e.width*ni),n=Math.floor(e.height*ni);return{left:e.x+t,top:e.y+n,width:Math.max(1,e.width-t*2),height:Math.max(1,e.height-n*2)}}getInsetBoundsFromBounds(e){let t=e[0],n=e[1],o=e[2],i=e[3],a=o-t,s=i-n,c=Math.floor(a*ni),l=Math.floor(s*ni);return{left:t+c,top:n+l,width:Math.max(1,a-c*2),height:Math.max(1,s-l*2)}}async executeSwipe(e){let t=se();if(e.scrollableElement.type==="CUSTOM_COORDINATES"){let{startX:o,startY:i,deltaPixels:a}=e.scrollableElement;return await t.startAsyncSpan("EMULATOR_INTERACTION",async s=>{s.attributes.startX=o,s.attributes.startY=i,s.attributes.deltaPixels=a,s.attributes.direction=e.direction,await this.performRawSwipe({startX:o,startY:i,deltaPixels:a,direction:e.direction,durationMs:e.durationMs})},{name:`Swipe ${e.direction} using raw coordinates`}),{success:!0,message:"Successfully executed swipe action"}}if(e.scrollableElement.type!=="CUSTOM"){let o=await this.driver.getWindowRect(),i=await this.getHardcodedScrollableElementBounds(e.scrollableElement,o);return await t.startAsyncSpan("EMULATOR_INTERACTION",async a=>{await this.swipeByAbsoluteCoordinates({span:a,direction:e.direction,percent:e.viewportPercent,durationMs:e.durationMs,containerBounds:i})},{name:`Swipe ${e.direction} in the entire ${e.scrollableElement.type.toLowerCase()}`}),{success:!0,message:"Successfully executed swipe action"}}let{thoughts:n}=await this.wrapTargetingAction({command:e,description:e.scrollableElement.target.description,action:async o=>se().startAsyncSpan("EMULATOR_INTERACTION",async a=>"type"in o&&o.type==="NATIVE"?this.scrollInNativeContainer({span:a,cmd:e,target:o}):(a.withinWebview=!0,this.swipeInWebview({span:a,cmd:e,target:o})),{name:`Swipe ${e.direction} in the specified container`}),tracer:t});return{success:!0,message:n}}async scrollInNativeContainer({span:e,cmd:t,target:n}){if(!n.bounds||n.bounds.length<4)throw new w("ActionFailureError","Native container cache has no bounds");let o=n.bounds,i=o[2]-o[0],a=o[3]-o[1],s=Math.floor(i*ni),c=Math.floor(a*ni);await this.swipeByAbsoluteCoordinates({span:e,direction:t.direction,percent:t.viewportPercent,durationMs:t.durationMs,containerBounds:{left:o[0]+s,top:o[1]+c,width:Math.max(1,i-s*2),height:Math.max(1,a-c*2)}})}async swipeInWebview({span:e,cmd:t,target:n}){let{controller:o,browserTarget:i}=n;if(!o.browser.getViewport())throw new Error("Failed to get viewport size from webview");let s=t.direction==="down"||t.direction==="up",c=await i.locator.boundingBox();if(!c)throw new Error("Failed to get bounds for webview container");let l=Math.floor(c.width*ni),u=Math.floor(c.height*ni),d=Math.max(1,c.width-l*2),p=Math.max(1,c.height-u*2),m={x:c.x+l+d/2,y:c.y+u+p/2},g=(s?p:d)*(t.viewportPercent??MO)*(s?t.direction==="down"?1:-1:t.direction==="right"?1:-1);e.attributes.startPoint=m,e.attributes.scrollPixelAmount=g,await o.browser.mouseDragUsingVisualCoordinates({deltaX:s?0:g,deltaY:s?g:0,steps:10,dragDurationMs:t.durationMs,fromTarget:m})}async swipeByAbsoluteCoordinates({span:e,direction:t,percent:n=MO,durationMs:o=500,containerBounds:i}){e.attributes.containerBounds=i;let a,s;t==="up"||t==="down"?(a=i.height*n,s=Math.floor(a/(o/1e3))):(a=i.width*n,s=Math.floor(a/(o/1e3))),e.attributes.pixelDelta=a,e.attributes.pixelsPerSecond=s,await this.driver.executeScript("mobile: swipeGesture",[{...i,direction:t,percent:n,speed:s}])}};var PO=5,IO=.8,DK=1,hp=class extends Hs{async executeScrollTo(e){let t=e.target.description,n=e.scrollStepPercent??IO,o=await this.tryUseCachedScrollPosition(e,t);return o||this.searchForElement(e,t,n)}async resolveContainer({scrollableElement:e,containerCache:t,aiMetadata:n}){let o=await this.driver.getWindowRect();if(e.type==="CUSTOM_COORDINATES")return{bounds:{left:0,top:0,width:o.width,height:o.height}};if(e.type!=="CUSTOM")return{bounds:await this.getHardcodedScrollableElementBounds(e,o)};let i=se(),a=e.target.description;if(t){let u=this.getBoundsFromNativeCache(t);return this.logger.info({bounds:u},"Got container bounds from native cache"),{bounds:u,cache:t}}let s=await this.findElement({description:a,tracer:i,metadata:n});if(!s.success)throw new w("NoMatchingElementError",s.thoughts??"No matching element found");let{resolvedTarget:c}=s;if(c.type!=="NATIVE")throw new Error(`ActionFailureError: Custom scroll container "${a}" resolved to a webview element. Custom containers must be native elements.`);let l=this.getBoundsFromNativeCache(c);return this.logger.info({bounds:l},"Got container bounds from AI"),{bounds:l,cache:c}}async tryUseCachedScrollPosition(e,t){let n=e.cache?.target;return n?n.type==="WEBVIEW"?this.tryUseWebviewCache(e,t):n.scrollDetails?this.tryUseNativeScrollCache(e,t,n):null:null}async tryUseWebviewCache(e,t){let n=se();try{let{thoughts:o}=await this.wrapTargetingAction({command:e,tracer:n,description:t,action:async i=>{if(i.type==="NATIVE")throw new Error("Expected WEBVIEW target but got NATIVE");await this.scrollWebviewTargetIntoView(i)}});return{success:!0,message:o}}catch(o){return this.logger.warn({err:o},"Failed to use webview cache, falling back to search"),null}}async tryUseNativeScrollCache(e,t,n){let o=n.scrollDetails,i=se(),a=e.scrollStepPercent??IO,s=o.scrollableElement.type==="CUSTOM"?o.scrollableElement.cache:void 0;await this.scrollByPixelDelta({pixelDelta:o.pixelDelta,scrollableElement:o.scrollableElement,containerCache:s,direction:o.direction,scrollStepPercent:a,aiMetadata:{commandId:e.id}});try{let l=await this.tryFindElement({cmd:e,description:t,tracer:i,scrollDetails:o,useAIIfCacheFails:!1});if(l)return l;this.logger.info("Element not found at cached position, undoing scroll")}catch(l){this.logger.warn({err:l},"Error finding element at cached position, will undo scroll")}let c=o.direction==="down"?"up":"down";return this.logger.info({pixelDelta:o.pixelDelta,originalDirection:o.direction,undoDirection:c,scrollableElementType:o.scrollableElement.type},"Undoing scroll"),await this.scrollByPixelDelta({pixelDelta:o.pixelDelta,scrollableElement:o.scrollableElement,containerCache:s,direction:c,scrollStepPercent:a,aiMetadata:{commandId:e.id}}),null}async tryFindElement({cmd:e,description:t,tracer:n,scrollDetails:o,useAIIfCacheFails:i=!0}){let a,s,c=e.cache?.target;if(c&&c.resolvedDescription===t&&!e.disableCache){let u=await this.stateManager.getDomState({skipFetchingFullWebviewContent:!0,removeWebviewContent:!0});try{let{resolvedTarget:d}=await mp({target:c,domState:u,stateManager:this.stateManager,logger:this.logger});a=d,s="Successfully resolved scroll to target with cache.",this.logger.info("Successfully resolved scroll to target from cache")}catch(d){this.logger.warn({err:d},"Failed to resolve target from cache")}}if(!a&&!i)return null;if(!a)try{let u=await this.findElement({description:t,tracer:n,metadata:{commandId:e.id}});if(!u.success)return null;a=u.resolvedTarget,s=u.thoughts}catch(u){if(u instanceof w&&u.reason==="NoMatchingElementError")return null;throw this.logger.warn({err:u},"Failed to find scroll-to target with AI"),u}return a.type==="WEBVIEW"?(await this.scrollWebviewTargetIntoView(a),la({command:e,updatedCache:pp(a),updatedWithAI:!0,logger:this.logger}),{success:!0,message:s}):(la({command:e,updatedCache:{...a,scrollDetails:o},updatedWithAI:!0,logger:this.logger}),{success:!0,message:s})}async searchForElement(e,t,n){let o=se(),i=await this.resolveContainer({scrollableElement:e.scrollableElement,aiMetadata:{commandId:e.id}});return this.scrollAndSearch(e,t,o,n,i)}async scrollAndSearch(e,t,n,o,i){let a=0,s=i.bounds,c=s.height*o,l=!0;for(let u=0;u<PO;u++){this.throwIfAborted();let d=this.buildScrollDetails(e,a,i.cache),p=await this.tryFindElement({cmd:e,description:t,tracer:n,scrollDetails:d});if(p)return p;if(!l)throw new Error(`ActionFailureError: Could not find element "${t}" after scrolling to the end`);this.logger.debug({attempt:u,cumulativePixelDelta:a},"Element not found, scrolling further");let m=kK(e.scrollableElement);l=await this.scrollByPage({direction:e.direction,containerBounds:s,scrollStepPercent:o,rawCoordinates:m}),a+=e.direction==="down"?c:-c}throw new Error(`ActionFailureError: Could not find element "${t}" after ${PO} scroll attempts`)}buildScrollDetails(e,t,n){return e.scrollableElement.type==="CUSTOM"?{pixelDelta:t,scrollableElement:{type:"CUSTOM",target:e.scrollableElement.target,cache:n},direction:e.direction}:e.scrollableElement.type==="CUSTOM_COORDINATES"?{pixelDelta:t,scrollableElement:e.scrollableElement,direction:e.direction}:{pixelDelta:t,scrollableElement:e.scrollableElement,direction:e.direction}}async scrollWebviewTargetIntoView(e){let{controller:t,browserTarget:n}=e;await t.browser.hover(n)}async scrollByPage({direction:e,containerBounds:t,scrollStepPercent:n,rawCoordinates:o}){return se().startAsyncSpan("EMULATOR_INTERACTION",async a=>(a.attributes.containerBounds=t,a.attributes.direction=e,this.executeScrollGesture({direction:e,containerBounds:t,scrollStepPercent:n,rawCoordinates:o})),{name:`Scroll ${e} by one page`})}async scrollByPixelDelta({pixelDelta:e,scrollableElement:t,containerCache:n,direction:o,scrollStepPercent:i,aiMetadata:a}){if(e===0)return;let s=se(),c,l,u;if(t.type==="CUSTOM_COORDINATES")c=t.startX,l=t.startY,u=t.deltaPixels;else{let m=(await this.resolveContainer({scrollableElement:t,containerCache:n,aiMetadata:a})).bounds,g=m.height*i,h=this.calculateSwipeCoordinates({containerBounds:m,direction:o,desiredDelta:g});c=h.startX,l=h.startY,u=h.actualDelta}let d=Math.ceil(Math.abs(e)/u);this.logger.debug({pixelDelta:e,direction:o,scrollableElementType:t.type,startX:c,startY:l,maxScrollPerStep:u,numScrolls:d},"scrollByPixelDelta calculated parameters"),await s.startAsyncSpan("EMULATOR_INTERACTION",async p=>{p.attributes.pixelDelta=e,p.attributes.numScrolls=d,p.attributes.maxScrollPerStep=u,p.attributes.startX=c,p.attributes.startY=l;let m=0;for(let g=0;g<d;g++){this.throwIfAborted();let h=Math.abs(e)-m,f=Math.min(u,h);await this.performRawSwipe({startX:c,startY:l,deltaPixels:f,direction:this.invertDirection(o)}),m+=f}},{name:`Scroll ${o} by ${e}px`})}async executeScrollGesture({direction:e,containerBounds:t,scrollStepPercent:n,diffThresholdPercent:o=DK,rawCoordinates:i}){let a=await this.stateManager.getRawScreenshotBase64(),s,c,l;if(i)s=i.startX,c=i.startY,l=i.deltaPixels;else{let m=t.height*n,g=this.calculateSwipeCoordinates({containerBounds:t,direction:e,desiredDelta:m});s=g.startX,c=g.startY,l=g.actualDelta}await this.performRawSwipe({startX:s,startY:c,deltaPixels:l,direction:this.invertDirection(e)});let u=await this.stateManager.getRawScreenshotBase64(),d=ps(a,u),p=d>o;return this.logger.debug({diffPercent:d,diffThresholdPercent:o,canScrollMore:p,direction:e,actualDelta:l,rawCoordinates:i},"Scroll gesture visual diff result"),p}};function kK(r){if(r.type==="CUSTOM_COORDINATES")return r}import{randomUUID as FK}from"crypto";import cu from"fs";import{tmpdir as UK}from"os";import Gs from"path";var fp=class extends Rt{async doInstallApk(e){return await this.installApkFromUri(e.uri),{success:!0,message:"Installed APK."}}async installApkFromUri(e){let t=await this.resolveUriToLocalApk(e);try{await this.stateManager.executeRawADBCommand(`install -r ${Gs.resolve(t.localPath)}`),this.logger.info({uri:e,localPath:t.localPath},"Installed APK on device")}finally{t.cleanup()}}async resolveUriToLocalApk(e){try{let t=new URL(e);if(t.protocol==="file:"){let n=t.href.slice(7),o;if(cu.existsSync(n))o=n;else if(cu.existsSync(Gs.join("/",n)))o=Gs.join("/",n);else throw new w("UserConfigurationError",`APK not found at path: ${n}`);return this.assertFileExists(o),{localPath:o,cleanup:()=>{}}}if(t.protocol==="http:"||t.protocol==="https:"){let n=await this.fetchWithTimeout(t);if(!n.ok)throw new w("UserInfrastructureError",`Failed to download APK from ${e} (status ${n.status})`);let o=await n.arrayBuffer(),i=Buffer.from(o),a=await this.writeBufferToTempFile(i,t.pathname);return{localPath:a,cleanup:()=>{try{cu.unlinkSync(a)}catch(s){this.logger.warn({err:s,path:a},"Failed to remove temporary APK file")}}}}throw new w("UserConfigurationError",`Unsupported URI scheme for APK installation: ${t.protocol}`)}catch(t){if(t instanceof TypeError){let n=Gs.resolve(e);return this.assertFileExists(n),{localPath:n,cleanup:()=>{}}}throw t}}assertFileExists(e){try{cu.accessSync(e)}catch{throw new w("UserConfigurationError",`APK not found at path: ${e}`)}}async fetchWithTimeout(e){let t=AbortSignal.timeout(9e4);return await fetch(e,{signal:t})}async writeBufferToTempFile(e,t){let n=Gs.extname(t)||".apk",o=Gs.join(UK(),`momentic-apk-${FK()}${n}`);return cu.writeFileSync(o,e),o}};import{existsSync as BK,readFileSync as zK}from"fs";import HK from"zod";var GK=HK.string().url();async function OO(r){if(GK.safeParse(r).success){let e=new AbortController,t=setTimeout(()=>e.abort(),1e4),n;try{n=await fetch(r,{signal:e.signal})}catch(i){throw new w("UserInfrastructureError",`Fetch failed or timed out for URL: ${r}`,{errOptions:{cause:i}})}finally{clearTimeout(t)}if(!n.ok)throw new w("UserInfrastructureError",`Failed to fetch file from URL: ${r}, status: ${n.status}`);let o=await n.arrayBuffer();return Buffer.from(o).toString("base64")}if(!BK(r))throw new w("UserInfrastructureError",`File does not exist at path: ${r}`);return zK(r).toString("base64")}var Sp=class extends Rt{async dragNative(e,t,n){let{left:o,top:i,width:a,height:s}=this.getBoundsFromNativeCache(e),{left:c,top:l,width:u,height:d}=this.getBoundsFromNativeCache(t),p=o+a/2,m=i+s/2,g=c+u/2,h=l+d/2,f=n?.hoverDuration??500,y=n?.dragDuration??1e3;await this.driver.performActions([{type:"pointer",id:"finger1",parameters:{pointerType:"touch"},actions:[{type:"pointerMove",duration:0,x:p,y:m},{type:"pointerDown",button:0},{type:"pause",duration:f},{type:"pointerMove",duration:y,x:g,y:h},{type:"pointerUp",button:0}]}]),await this.driver.releaseActions()}async dragWebview(e,t,n){let{controller:o}=e;if(e.controller!==t.controller)throw new w("UserConfigurationError","Cannot drag and drop between different webviews");let i=n?.dragDuration??1e3,a=n?.hoverDuration??1e3,s;n?.dragDuration&&(s=Math.max(1,Math.floor(i/200))),await o.browser.dragAndDrop(e.browserTarget,t.browserTarget,{hoverDurationMs:a,steps:s,dragDurationMs:i})}async executeDragAndDrop({command:e}){let t=se();if(e.fromTarget.type!=="description"||e.toTarget.type!=="description")throw new w("UserConfigurationError","Drag and drop only supports description targets for now");let n=e.fromTarget.description,{result:o,thoughts:i}=await this.wrapTargetingAction({command:e,tracer:t,description:n,cacheKey:"cache",targetName:"fromTarget",action:async l=>l}),a=e.toTarget.description,{result:s,thoughts:c}=await this.wrapTargetingAction({command:e,tracer:t,description:a,cacheKey:"cache",targetName:"toTarget",action:async l=>l});if(o.type!==s.type)throw new w("UserConfigurationError",`Drag and drop targets must be in the same context (both native or both webview). Found: From=${o.type}, To=${s.type}`);return await t.startAsyncSpan("EMULATOR_INTERACTION",async l=>{o.type==="NATIVE"&&s.type==="NATIVE"?await this.dragNative(o,s,{hoverDuration:e.hoverDuration,dragDuration:e.dragDuration}):o.type==="WEBVIEW"&&s.type==="WEBVIEW"&&(l.withinWebview=!0,await this.dragWebview(o,s,{hoverDuration:e.hoverDuration,dragDuration:e.dragDuration}))},{name:"Drag and drop"}),{success:!0,message:`${i}
4576
+ `));return}}let d=Array.from(e.childNodes??[]);for(let p of d){let m=p.nodeType;if(m===3){let g=p.nodeValue;g&&g.trim().length>0&&t.appendChild(n.createTextNode(g));continue}if(m===1){let g=p;if(!AK(g,s?.viewportBounds))continue;let h=n.createElement(yO(g.tagName));bO(r,g,h),t.appendChild(h)}}}function TK(r,e,t,n){let o=r.parseFromString("<hierarchy/>","text/xml"),i=new Map,a={prunedDocument:o,idToElement:t,prunedIdToElement:i,idCounter:{value:0},opts:n},s=o.documentElement;bO(a,e,s);let c=new mK().serializeToString(o);return{prunedDocument:o,prunedIdToElement:i,xml:c}}async function EO(r,e){let t=new dK,n=t.parseFromString(r,"text/xml"),o=new Map,i=n.documentElement;if(!i)throw new w("InternalWebAgentError","No root element found in XML");if(i.tagName!=="hierarchy")throw new w("InternalWebAgentError","No hierarchy element found in XML");let{prunedDocument:a,prunedIdToElement:s,xml:c}=TK(t,i,o,e);return{xml:await uK.format(c,{parser:"xml",plugins:[cK],printWidth:120,tabWidth:1,singleAttributePerLine:!1}),originalXml:r,document:n,idToElement:o,prunedDocument:a,prunedIdToElement:s}}function vK(r){let e=[],t=r;for(;t;){let n=t.tagName,o=t.parentElement,i=1;if(o){let a=Array.from(o.children).filter(s=>s.tagName===n);for(let s=0;s<a.length;s++)if(a[s]===t){i=s+1;break}}e.unshift(`${n}[${i}]`),t=o}return`/${e.join("/")}`}function up(r,e){let t=r.idToElement.get(e);if(t)return vK(t)}function ky(r,e){let t=r.idToElement.get(e);if(!t)return;let n=t.cloneNode(!0);for(let o of Array.from(n.children)){let i=o;for(let a of Array.from(i.children))i.removeChild(a)}return n.outerHTML}function sa(r){if(!r.hasAttribute("bounds"))return;let e=r.getAttribute("bounds");if(!e)return;let t=e.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/);if(t){let n=parseInt(t[1],10),o=parseInt(t[2],10),i=parseInt(t[3],10),a=parseInt(t[4],10);if(Number.isFinite(n)&&Number.isFinite(o)&&Number.isFinite(i)&&Number.isFinite(a))return[n,o,i,a]}}function AK(r,e){if(!e)return!0;let t=sa(r);if(!t||t.length<4)return!0;let n=t[0],o=t[1],i=t[2],a=t[3];return!(i<=e.left||n>=e.right||a<=e.top||o>=e.bottom)}function TO(r,e){if(r&&!(!e||e.length===0))return Object.fromEntries(e.map(t=>[t,r.getAttribute(t)]).filter(([,t])=>t!==null))}function AO({requirements:r,element:e}){let t;if((r?.positionSpecificity||r?.shapeSpecificity)&&(t=sa(e),!t))throw new w("ActionFailureError","Element to cache has no bounds or unexpected bounds format");return{requiredText:r?.textRequired?e.getAttribute("text")??void 0:void 0,requiredAttributes:TO(e,r?.attributesRequired),requiredBounds:r?.boundsRequired,position:r?.positionSpecificity?{x1:t[0],y1:t[1],x2:t[2],y2:t[3],tolerance:r?.positionSpecificity}:void 0,shape:r?.shapeSpecificity?{width:t[2]-t[0],height:t[3]-t[1],tolerance:r?.shapeSpecificity}:void 0}}function RO({aiResponse:r,description:e,emulatorState:t,memory:n,useMemory:o}){let i=t.graph.idToElement.get(r.id);if(!i)throw new w("InternalWebAgentError",`Could not find node with id: ${r.id}`);let a=sa(i);if(!a)throw new w("InternalWebAgentError",`Node ${r.id} has no bounding box: ${i.outerHTML}`);let s=up(t.graph,r.id)??"",c=ky(t.graph,r.id)??"",l=AO({requirements:r.requirements,element:i}),u=[];r.additionalElements&&(u=r.additionalElements.map(({id:p,requirements:m})=>{let g=t.graph.idToElement.get(p);if(!g)return;let h=up(t.graph,p);return h?{xPath:h,requirements:AO({requirements:m,element:g})}:void 0}).filter(p=>!!p));let d;if(su(i)&&r.inWebview!==!1?d={type:"WEBVIEW",resolvedDescription:e,xPath:s}:d={type:"NATIVE",bounds:a,resolvedDescription:e,xPath:s,elementOnlySerializedXml:c,requirements:l,requiredRelatedElements:u},o)if(r.updatedMemory){let p={type:"GCS_TRACES",traces:r.updatedMemory};d.memory=p}else n&&(d.memory=n);return{target:d,resolvedNode:i}}function CO(r){return r?.type==="WEBVIEW"?r.browserCache?.memory:void 0}var wK=.1,RK=.25;function dp(r,e,t,n){let o=Math.abs(e-t);switch(r){case"precise":return o<=n;case"narrow":return o<=Math.abs(e)*wK;case"broad":return o<=Math.abs(e)*RK;case"irrelevant":return!0}}function CK(r,e){let t=e.x2-e.x1,n=(e.x1+e.x2)/2,o=(r[0]+r[2])/2;if(!dp(e.tolerance,n,o,Math.min(1,t)))return!1;let i=e.y2-e.y1,a=(e.y1+e.y2)/2,s=(r[1]+r[3])/2;return dp(e.tolerance,a,s,Math.min(1,i))}function xK(r,e){return dp(e.tolerance,e.width,r[2]-r[0],Math.min(1,e.width))?dp(e.tolerance,e.height,r[3]-r[1],Math.min(1,e.height)):!1}var wO=(r,e,t)=>{if(!e)return;let{requiredAttributes:n,requiredText:o,requiredBounds:i,position:a,shape:s}=e;if(o!==void 0&&o.length>0){let c=Kc(r);if(c!==o)throw new gt(`Resolved element text mismatch: expected ${o}, got ${c}`)}if(n)for(let[c,l]of Object.entries(n)){let u=r.getAttribute(c)??void 0;if(u!==l)throw new gt(`Attribute ${c} mismatch: expected ${l}, got ${u}`)}if(i&&t&&!t.targetBounds.every((l,u)=>l===t.newElementBounds[u]))throw new gt(`Bounds changed from [${t.targetBounds.join(",")} ] to [${t.newElementBounds.join(",")} ]`);if(a&&t&&!CK(t.newElementBounds,a))throw new gt(`Position mismatch: expected ${JSON.stringify(a)}, got ${JSON.stringify(t.newElementBounds)}`);if(s&&t&&!xK(t.newElementBounds,s))throw new gt(`Shape mismatch: expected ${JSON.stringify(s)}, got ${JSON.stringify(t.newElementBounds)}`)};async function mp(r){let{target:e,domState:t}=r,{graph:n}=t,{document:o}=n,i=se();if(e.type==="WEBVIEW")return _K(e,r);if(!e.xPath)throw new w("ActionFailureError","Native element cache has no XPath");let a=vO.evaluateXPathToFirstNode(e.xPath,o,null,null);if(!a)throw new gt(`Could not resolve cached target via XPath: ${e.xPath}`);if(e.requiredRelatedElements){let p=e.requiredRelatedElements;i.startSection("Validate related elements are similar enough to past runs",()=>{for(let m of p){let g=vO.evaluateXPathToFirstNode(m.xPath,o);if(!g)throw new gt(`Required related element not found for XPath: ${m.xPath}`);wO(g,m.requirements)}})}let s=sa(a);if(!s)throw new gt("Resolved native element has no bounding box");if(!e.bounds)throw new gt("Native element cache has no bounds");wO(a,e.requirements,{targetBounds:e.bounds,newElementBounds:s});let c;for(let[p,m]of n.idToElement.entries())if(m===a){c=p;break}let l=e.elementOnlySerializedXml,u=e.xPath;return c!==void 0&&(l=ky(n,c)??l,u=up(n,c)??u),{resolvedTarget:{...e,resolvedNode:a,bounds:s,elementOnlySerializedXml:l,xPath:u}}}async function _K(r,e){let{stateManager:t,logger:n,signal:o}=e,i=se(),a=await t.getActiveWebview();if(!a||!a.browserController)throw n.error({webview:a?{...a,browserController:!!a.browserController}:void 0},"resolveTargetCacheInWebView: No browser controller attached"),new gt("No browser controller is attached to the requested webview");let s=a.browserController;if(!r.browserCache)throw n.error({target:r},"resolveTargetCacheInWebView: No browser target available on cache"),new gt("No browser target available on cache");let c=r.browserCache,{finalTarget:l}=await i.startAsyncSection("Resolve target in webview",()=>s.resolveCachedTargetForAction({ctx:null,cache:c,options:{disableGlobalLocatorRedirect:e.disableTargetRedirection,resolveTargetOptions:{logger:n,signal:o,skipWaitForPageLoad:!0,skipSavingVisualAttributes:!0}},logger:n}));return{resolvedTarget:{...r,controller:a.browserController,browserTarget:l}}}function la(r){let{command:e,cacheKey:t="cache",targetName:n="target",updatedCache:o}=r;Bi(e)&&(e[t]={...e[t],[n]:ja.parse(o)},r.updatedWithAI&&(e[t].updatedAt=new Date,e[t].updatedAtLoggerTags=ye(r.logger)))}function pp(r){if(r.type==="WEBVIEW")return{type:"WEBVIEW",resolvedDescription:r.resolvedDescription,xPath:r.xPath,browserCache:r.browserCache,memory:r.memory};let{resolvedNode:e,...t}=r;return{...t}}var Rt=class{driver;generator;stateManager;logger;fixtures;aborter;orgId;aiSettings;options;constructor(e){this.stateManager=e.stateManager,this.generator=e.generator,this.driver=e.driver,this.logger=e.logger,this.fixtures=e.fixtures,this.aborter=e.aborter,this.orgId=e.orgId,this.aiSettings=e.aiSettings,this.options=e.options}shouldUseMemoryForCommand(e){return this.aiSettings?.useMemory&&!e?.disableCache}async findElement({description:e,tracer:t,skipFetchingFullWebviewContent:n=!1,removeWebviewContent:o=!1,useMemory:i=!1,memory:a,webviewMemory:s,metadata:c}){let l=this.logger.child({...c}),u=await t.startAsyncSection("Get emulator state",async()=>{let f=await this.stateManager.getDomState({skipFetchingFullWebviewContent:n,removeWebviewContent:o}),y=await this.stateManager.getCurrentScreenshotPngString();return{emulatorState:f,screenshot:y}}),d;try{d=await t.startAsyncSpan("AI_LOCATOR_CALL",async f=>{let y=await this.generator.getAndroidElementLocation({description:e,screenXml:u.emulatorState.graph.xml,screenshot:u.screenshot,memory:i?a:void 0},{logger:l,loggerTags:ye(l),abortSignal:this.aborter.controller?.signal,useMemory:i,agentConfigVersion:this.aiSettings.agentConfig?.["android-locator"]});return f.result=y,y})}catch(f){throw this.throwIfAborted(),l.error({err:f},"Failed to locate element"),new w("InternalWebAgentError",`Failed to locate element: ${f instanceof Error?f.message:f}`,{errOptions:{cause:f}})}if(d.id===-1){let f=d.updatedMemory?{type:"GCS_TRACES",traces:d.updatedMemory}:void 0;return{success:!1,thoughts:d.thoughts??"No matching element found",updatedLocatorMemory:f}}let{target:p,resolvedNode:m}=RO({aiResponse:d,description:e,emulatorState:u.emulatorState,memory:a,useMemory:i});if(p.type==="NATIVE")return t.addSpan({type:"TARGET_RESOLUTION",startTime:Date.now(),endTime:Date.now(),result:{serializedElement:p.elementOnlySerializedXml??"Unknown element"},attributes:{},subSpans:[]}),{success:!0,resolvedTarget:{...p,resolvedNode:m},thoughts:d.thoughts};let{browserLocateResult:g,browserController:h}=await t.startWebviewTrace(async()=>{let f=await this.stateManager.getActiveWebview();if(!f||!f.browserController)throw new w("InternalWebAgentError","No browser controller is attached to the requested webview");return{browserLocateResult:await f.browserController.locateElement({description:e,disableCache:!1,useMemory:i,memory:i?s:void 0,logger:this.logger,skipWait:!0,skipSavingVisualAttributes:!0}),browserController:f.browserController}});return t.addSpan({type:"TARGET_RESOLUTION",startTime:Date.now(),endTime:Date.now(),result:{serializedElement:g.target.nodeOnlySerializedHtml??"Unknown HTML element in webview"},attributes:{},subSpans:[]}),{success:!0,resolvedTarget:{...p,controller:h,browserTarget:{...g.resolution,serverSideBoundingBox:await g.resolution.locator.boundingBox({timeout:5e3})},browserCache:g.target},thoughts:g.thoughts}}async targetingActionWithAILocator(e){let{action:t,command:n,description:o,tracer:i,cacheKey:a,targetName:s,cache:c,skipFetchingFullWebviewContent:l,removeWebviewContent:u,metadata:d}=e,p=await this.findElement({description:o,tracer:i,skipFetchingFullWebviewContent:l,removeWebviewContent:u,useMemory:this.shouldUseMemoryForCommand(n),memory:c?.memory,webviewMemory:CO(c),metadata:d});if(!p.success){if(p.updatedLocatorMemory&&c){let h={...c,memory:p.updatedLocatorMemory};la({command:n,cacheKey:a,targetName:s,updatedCache:h,updatedWithAI:!0,logger:this.logger})}throw new w("NoMatchingElementError",p.thoughts??"No matching element found")}let m=p.thoughts,g=await t(p.resolvedTarget);return la({command:n,cacheKey:a,targetName:s,updatedCache:p.resolvedTarget,updatedWithAI:!0,logger:this.logger}),{result:g,thoughts:m}}async wrapTargetingAction(e){let{action:t,description:n,command:o,cacheKey:i="cache",targetName:a="target",cacheIsInvalidAfterResolution:s,tracer:c,skipFetchingFullWebviewContent:l=!1,removeWebviewContent:u=!1,disableTargetRedirection:d=!1}=e,p,m={commandId:o.id};if(i==="cache"&&"cache"in o&&o.cache){let b=o.cache;a==="target"&&"target"in b?p=b.target:a==="fromTarget"&&"fromTarget"in b?p=b.fromTarget:a==="toTarget"&&"toTarget"in b&&(p=b.toTarget)}let g=!1,h=Fy(p);if(o.disableCache&&(this.logger.debug({command:o},"Cache explicitly disabled for command"),g=!0,h=void 0),s&&(g=!0,h=void 0),h&&h?.resolvedDescription!==n&&(this.logger.info({description:n,cacheDescription:h?.resolvedDescription},"Cache description mismatch, clearing it automatically"),g=!0,h=void 0),!h)return this.logger.info({description:n,cacheBustedBeforeAction:g},"Prompting AI for a new element location"),this.targetingActionWithAILocator({action:t,command:o,description:n,tracer:c,cacheKey:i,targetName:a,cache:p,skipFetchingFullWebviewContent:l,removeWebviewContent:u,metadata:m});let f=h.type==="NATIVE"?!!h.requirements:!!h.browserCache?.requirements,y=h.type==="NATIVE"?!!h.requiredRelatedElements?.length:!!h.browserCache?.additionalElements?.length,E;try{this.options?.emulator?.waitForStability&&await this.stateManager.waitForPageSourceStability({timeoutMs:3e3,signal:this.aborter.controller?.signal,reason:"Waiting for stability before cache resolution"});let{resolvedTarget:b,updatedCache:x}=await c.startAsyncSpan("CACHE_RESOLUTION",async O=>{let T=Date.now(),R;for(;Date.now()-T<3e3;){E=await this.stateManager.getDomState({skipFetchingFullWebviewContent:h?.type==="NATIVE"});let D;try{D=(await mp({target:h,domState:E,stateManager:this.stateManager,logger:this.logger,disableTargetRedirection:d})).resolvedTarget}catch(F){if(R=F,F instanceof gt){this.logger.warn({err:F},"Failed to resolve target cache, retrying");continue}throw this.logger.error({err:F},"Failed to resolve target cache"),F}let I=pp(D),k=PK(h,I);return k&&Object.keys(k).length>0&&this.logger.info({cacheDiffs:k},"Successfully resolved target with cache"),O.attributes.serializedElement=D.type==="WEBVIEW"?D.browserCache?.nodeOnlySerializedHtml??"Unknown HTML element in webview":D.elementOnlySerializedXml??"Unknown element",{resolvedTarget:D,updatedCache:I}}throw R}),P=await t(b);return la({command:o,cacheKey:i,targetName:a,updatedCache:x,updatedWithAI:!1,logger:this.logger}),nt.increment("cache_target_resolution_v2",1,["outcome:hit",`platform:mobile-${h.type.toLowerCase()}`,`hasRequirements:${f}`,`hasAdditionalElements:${y}`,`orgId:${this.orgId}`,"cliVersion:0.33.1"]),{result:P,thoughts:"Successfully executed preset action with cache"}}catch(b){if(this.throwIfAborted(),b instanceof w&&b.reason!=="InternalWebAgentError")throw this.logger.error({err:b},"Failed to execute action with target cache (fatal)"),b;return nt.increment("cache_target_resolution_v2",1,["outcome:miss",`platform:mobile-${h.type.toLowerCase()}`,`hasRequirements:${f}`,`hasAdditionalElements:${y}`,`orgId:${this.orgId}`,"cliVersion:0.33.1"]),this.logger.warn({err:b},"Failed to execute action with target cache, retrying with AI"),this.targetingActionWithAILocator({action:t,command:o,description:n,tracer:c,cacheKey:i,targetName:a,cache:h,skipFetchingFullWebviewContent:l,removeWebviewContent:u,metadata:m})}}constructPerformerParams(){return{stateManager:this.stateManager,generator:this.generator,driver:this.driver,logger:this.logger,fixtures:this.fixtures,aborter:this.aborter,orgId:this.orgId,aiSettings:this.aiSettings,options:this.options}}getBoundsFromNativeCache(e){if(!e.bounds)throw new w("ActionFailureError","Native element cache has no bounds");let[t,n,o,i]=e.bounds;if(t===void 0||n===void 0||o===void 0||i===void 0)throw new w("ActionFailureError",`Native element cache has incomplete bounds: [${e.bounds.join(", ")}]`);return{left:t,top:n,width:o-t,height:i-n}}calculateSwipeCoordinates({containerBounds:e,direction:t,desiredDelta:n,edgeMarginPercent:o=.1}){let i=e.left+e.width/2,a=e.top+e.height/2;if(t==="up"||t==="down"){let s=e.height*o,c=e.top+s,l=e.top+e.height-s,u=l-c,d=Math.min(Math.abs(n),u);return{startX:i,startY:t==="down"?l:c,actualDelta:d}}else{let s=e.width*o,c=e.left+s,l=e.left+e.width-s,u=l-c,d=Math.min(Math.abs(n),u);return{startX:t==="right"?l:c,startY:a,actualDelta:d}}}invertDirection(e){if(e==="up")return"down";if(e==="down")return"up";if(e==="left")return"right";if(e==="right")return"left";throw new Error(`Unreachable code: ${e}`)}async performRawSwipe({startX:e,startY:t,deltaPixels:n,direction:o,durationMs:i=300}){let a=Math.abs(n),s=e,c=t;o==="up"||o==="down"?c=o==="up"?t-a:t+a:s=o==="left"?e-a:e+a,await this.driver.performActions([{type:"pointer",id:"finger1",parameters:{pointerType:"touch"},actions:[{type:"pointerMove",duration:0,x:e,y:t},{type:"pointerDown",button:0},{type:"pause",duration:100},{type:"pointerMove",duration:i,x:s,y:c},{type:"pointerUp",button:0}]}]),await this.driver.releaseActions()}throwIfAborted(){this.aborter.controller?.signal.throwIfAborted()}get abortSignal(){return this.aborter.controller?.signal}get aiSettingsCopy(){return Fy(this.aiSettings)}get optionsCopy(){return Fy(this.options)}};function _O(r){return"iterations"in r}function LK(r){let e={relativePosition:r.relativePosition};if(r.iterations!==void 0&&(!Number.isInteger(r.iterations)||r.iterations<1))throw new Error("UserConfigurationError: iterations must be a positive integer");if(r.tapDelayMs!==void 0&&(!Number.isInteger(r.tapDelayMs)||r.tapDelayMs<0))throw new Error("UserConfigurationError: tapDelayMs must be >= 0");if(r.iterations&&r.iterations>1&&r.longPress)throw new Error("UserConfigurationError: Cannot specify both more than one tap iteration and long press at the same time");if(r.tapDelayMs!==void 0&&(!r.iterations||r.iterations<2))throw new Error("UserConfigurationError: tapDelayMs requires iterations >= 2");if(r.longPress){if(r.tapDelayMs!==void 0)throw new Error("UserConfigurationError: tapDelayMs cannot be used with longPress");return{...e,longPress:!0,longPressDurationMs:r.longPressDurationMs}}return r.iterations!==void 0?{...e,iterations:r.iterations,tapDelayMs:r.tapDelayMs}:e}var zs=class extends Rt{async tapOnNativeCoordinates(e){let t=e.x,n=e.y;if(this.logger.info({x:t,y:n},"Tap at coordinates"),"longPress"in e&&e.longPress)return await this.driver.executeScript("mobile: longClickGesture",[{x:t,y:n,duration:e.longPressDurationMs??2e3}]);if(_O(e)){let o=e.tapDelayMs??100;for(let i=0;i<e.iterations;i++)await this.driver.tap({x:t,y:n}),i<e.iterations-1&&await new Promise(a=>setTimeout(a,o));return}await this.driver.tap({x:t,y:n})}async tapOnNativeTarget(e,t){let[n,o,i,a]=e.bounds,s=i-n,c=a-o,l=t?.relativePosition?.x??s/2,u=t?.relativePosition?.y??c/2;l=Math.max(0,Math.min(l,s)),u=Math.max(0,Math.min(u,c));let d=n+l,p=o+u;return await this.tapOnNativeCoordinates({x:d,y:p,...t}),{x:d,y:p}}async tapOnWebviewTarget(e,t){let{controller:n}=e,o,i=1;return t&&_O(t)?(o=t.tapDelayMs,i=t.iterations):t&&"longPress"in t&&(o=t.longPressDurationMs),(await n.browser.click(e.browserTarget,{createIsolatedFolder:()=>{let s=Math.random().toString(36).substring(4),c=xO.join(OK(),"momentic","downloads"),l=xO.join(c,this.orgId,s);return IK(l,{recursive:!0}),l}},{delayMs:o,relativePosition:t?.relativePosition,iterations:i})).coordinates}async tapOnTarget({target:e,options:t}){return await se().startAsyncSpan("EMULATOR_INTERACTION",async o=>{o.attributes.options=t,"type"in e&&e.type==="NATIVE"?o.attributes.point=await this.tapOnNativeTarget(e,t):(o.withinWebview=!0,o.attributes.point=await this.tapOnWebviewTarget(e,t))},{name:"Tap on target"})}async executeTap({command:e}){let t=se(),n=LK(e);if(e.target.type==="coordinates"){let a=await this.driver.getWindowSize(),s=e.target.xPercent*a.width,c=e.target.yPercent*a.height;return await t.startAsyncSpan("EMULATOR_INTERACTION",async()=>{await this.tapOnNativeCoordinates({...n,x:s,y:c})},{name:`Tap at coordinates ${s}, ${c}`}),{success:!0,message:`Tapped at ${s}, ${c}`}}let o=e.target.description,{thoughts:i}=await this.wrapTargetingAction({command:e,tracer:t,action:a=>this.tapOnTarget({target:a,options:n}),description:o});return{success:!0,message:i}}};var ri=class extends Rt{async doPress({keycode:e,longPress:t}){await se().startAsyncSpan("EMULATOR_INTERACTION",async()=>this.driver.executeScript("mobile: pressKey",[{keycode:e,isLongPress:t}]),{name:"Send key events to emulator"})}};var ca=25,gp=class extends Rt{async doType(e){let t=se();if(!e.target){if(e.clearContent)throw new w("UserConfigurationError","Clearing content is only supported when a target is provided to the Type step");return await this.stateManager.waitForPageSourceStability({timeoutMs:2e3,signal:this.aborter.controller?.signal,reason:"Waiting for page to stabilize before typing"}),await this.sendKeys(e),{success:!0,message:"Successfully executed type action"}}if(e.target.type!=="description")throw new w("UserConfigurationError","x/y targets are not supported for the Type step");let{thoughts:n}=await this.wrapTargetingAction({command:e,tracer:t,action:async o=>{"type"in o&&o.type==="NATIVE"?await this.doNativeType(e,o):await this.doWebviewType(e,o)},description:e.target.description});return{success:!0,message:n}}async doWebviewType(e,t){await se().startAsyncSpan("EMULATOR_INTERACTION",async o=>{o.withinWebview=!0;let i={clearContent:e.clearContent,forceClearContent:e.forceClearContent,delay:e.keyPressDelayMs??ca};o.attributes.options=i;let{controller:a,browserTarget:s}=t;await a.browser.typeIntoTarget(e.text,s,i)},{name:"Typing within web view"})}async doNativeType(e,t){let n=new zs(this.constructPerformerParams());e.clearContent?(await n.tapOnNativeTarget(t,{longPress:!0}),await this.clearContent()):await n.tapOnNativeTarget(t),await this.stateManager.waitForPageSourceStability({timeoutMs:2e3,signal:this.aborter.controller?.signal,reason:"Waiting for keyboard to appear before typing"}),await this.sendKeys(e)}async sendKeys(e){let t=se(),n=e.keyPressDelayMs??ca;await t.startAsyncSection("Waiting for system keyboard to open",async(o,i)=>{let a=Date.now();for(;Date.now()-a<2e3;){this.throwIfAborted();let s=Date.now();if(await this.driver.isKeyboardShown())return;let c=Date.now()-s;c<500&&await new Promise(l=>setTimeout(l,500-c))}i.attributes.timedOut=!0}),n!==ca?await t.startAsyncSpan("EMULATOR_INTERACTION",async()=>{await this.driver.updateSettings({keyInjectionDelay:n}),await this.driver.keys(e.text),await this.driver.updateSettings({keyInjectionDelay:ca})},{name:`Typing with a ${n}ms delay`}):await t.startAsyncSpan("EMULATOR_INTERACTION",async()=>{await this.driver.keys(e.text)},{name:`Typing with a ${ca}ms delay`})}async clearContent(){let e=se();try{await e.startAsyncSection("Clearing any content from the focused field",()=>this.clearContentHelper())}catch(t){this.logger.warn({err:t},"Failed to find select all button, continuing...")}}async clearContentHelper(){let e=this.driver.$('//android.widget.LinearLayout[@content-desc="Select all" and @clickable="true"]');await e.waitForExist({timeout:750}),await e.click(),await new ri(this.constructPerformerParams()).doPress({keycode:67})}};import Dr from"zod";var MO=.8,ni=.2,NK=Dr.object({navigationBar:Dr.object({visible:Dr.boolean(),x:Dr.number(),y:Dr.number(),width:Dr.number(),height:Dr.number()}),statusBar:Dr.object({visible:Dr.boolean(),x:Dr.number(),y:Dr.number(),width:Dr.number(),height:Dr.number()})}),Hs=class extends Rt{async getHardcodedScrollableElementBounds(e,t){let n;switch(e.type){case"SCREEN":n=this.getInsetBoundsFromViewport(t);break;case"OPEN_APP":try{let o=NK.parse(await this.driver.executeScript("mobile: getSystemBars",[]));n=this.getInsetBoundsFromViewport(t),o.navigationBar.visible&&(n.height=Math.max(1,n.height-o.navigationBar.height)),o.statusBar.visible&&(n.top+=o.statusBar.height,n.height=Math.max(1,n.height-o.statusBar.height))}catch(o){this.logger.warn({err:o},"Failed to get system bars, using hardcoded bounds"),n=this.getInsetBoundsFromViewport(t)}break;case"OPEN_WEBVIEW":{let o=await this.stateManager.getActiveWebviewNodes();if(o.length===0&&(await this.stateManager.refreshWebviewsManually("get active webview nodes"),o=await this.stateManager.getActiveWebviewNodes()),o.length===0)throw new Error("No active webviews found");if(o.length>1){let a=o.map(s=>({id:s.id,ele:s.originalElement.outerHTML,bounds:s.bounds}));throw new Error(`Multiple active webviews found. Momentic currently only supports a single active webview at a time. Discovered nodes: ${JSON.stringify(a)}`)}let i=o[0]?.bounds;if(!i)throw new Error("No bounds found for active webview");n=this.getInsetBoundsFromBounds(i);break}default:{let o=e;throw new Error("If Typescript complains about the line above, you missed a switch case")}}return n}getInsetBoundsFromViewport(e){let t=Math.floor(e.width*ni),n=Math.floor(e.height*ni);return{left:e.x+t,top:e.y+n,width:Math.max(1,e.width-t*2),height:Math.max(1,e.height-n*2)}}getInsetBoundsFromBounds(e){let t=e[0],n=e[1],o=e[2],i=e[3],a=o-t,s=i-n,c=Math.floor(a*ni),l=Math.floor(s*ni);return{left:t+c,top:n+l,width:Math.max(1,a-c*2),height:Math.max(1,s-l*2)}}async executeSwipe(e){let t=se();if(e.scrollableElement.type==="CUSTOM_COORDINATES"){let{startX:o,startY:i,deltaPixels:a}=e.scrollableElement;return await t.startAsyncSpan("EMULATOR_INTERACTION",async s=>{s.attributes.startX=o,s.attributes.startY=i,s.attributes.deltaPixels=a,s.attributes.direction=e.direction,await this.performRawSwipe({startX:o,startY:i,deltaPixels:a,direction:e.direction,durationMs:e.durationMs})},{name:`Swipe ${e.direction} using raw coordinates`}),{success:!0,message:"Successfully executed swipe action"}}if(e.scrollableElement.type!=="CUSTOM"){let o=await this.driver.getWindowRect(),i=await this.getHardcodedScrollableElementBounds(e.scrollableElement,o);return await t.startAsyncSpan("EMULATOR_INTERACTION",async a=>{await this.swipeByAbsoluteCoordinates({span:a,direction:e.direction,percent:e.viewportPercent,durationMs:e.durationMs,containerBounds:i})},{name:`Swipe ${e.direction} in the entire ${e.scrollableElement.type.toLowerCase()}`}),{success:!0,message:"Successfully executed swipe action"}}let{thoughts:n}=await this.wrapTargetingAction({command:e,description:e.scrollableElement.target.description,action:async o=>se().startAsyncSpan("EMULATOR_INTERACTION",async a=>"type"in o&&o.type==="NATIVE"?this.scrollInNativeContainer({span:a,cmd:e,target:o}):(a.withinWebview=!0,this.swipeInWebview({span:a,cmd:e,target:o})),{name:`Swipe ${e.direction} in the specified container`}),tracer:t});return{success:!0,message:n}}async scrollInNativeContainer({span:e,cmd:t,target:n}){if(!n.bounds||n.bounds.length<4)throw new w("ActionFailureError","Native container cache has no bounds");let o=n.bounds,i=o[2]-o[0],a=o[3]-o[1],s=Math.floor(i*ni),c=Math.floor(a*ni);await this.swipeByAbsoluteCoordinates({span:e,direction:t.direction,percent:t.viewportPercent,durationMs:t.durationMs,containerBounds:{left:o[0]+s,top:o[1]+c,width:Math.max(1,i-s*2),height:Math.max(1,a-c*2)}})}async swipeInWebview({span:e,cmd:t,target:n}){let{controller:o,browserTarget:i}=n;if(!o.browser.getViewport())throw new Error("Failed to get viewport size from webview");let s=t.direction==="down"||t.direction==="up",c=await i.locator.boundingBox();if(!c)throw new Error("Failed to get bounds for webview container");let l=Math.floor(c.width*ni),u=Math.floor(c.height*ni),d=Math.max(1,c.width-l*2),p=Math.max(1,c.height-u*2),m={x:c.x+l+d/2,y:c.y+u+p/2},g=(s?p:d)*(t.viewportPercent??MO)*(s?t.direction==="down"?1:-1:t.direction==="right"?1:-1);e.attributes.startPoint=m,e.attributes.scrollPixelAmount=g,await o.browser.mouseDragUsingVisualCoordinates({deltaX:s?0:g,deltaY:s?g:0,steps:10,dragDurationMs:t.durationMs,fromTarget:m})}async swipeByAbsoluteCoordinates({span:e,direction:t,percent:n=MO,durationMs:o=500,containerBounds:i}){e.attributes.containerBounds=i;let a,s;t==="up"||t==="down"?(a=i.height*n,s=Math.floor(a/(o/1e3))):(a=i.width*n,s=Math.floor(a/(o/1e3))),e.attributes.pixelDelta=a,e.attributes.pixelsPerSecond=s,await this.driver.executeScript("mobile: swipeGesture",[{...i,direction:t,percent:n,speed:s}])}};var PO=5,IO=.8,DK=1,hp=class extends Hs{async executeScrollTo(e){let t=e.target.description,n=e.scrollStepPercent??IO,o=await this.tryUseCachedScrollPosition(e,t);return o||this.searchForElement(e,t,n)}async resolveContainer({scrollableElement:e,containerCache:t,aiMetadata:n}){let o=await this.driver.getWindowRect();if(e.type==="CUSTOM_COORDINATES")return{bounds:{left:0,top:0,width:o.width,height:o.height}};if(e.type!=="CUSTOM")return{bounds:await this.getHardcodedScrollableElementBounds(e,o)};let i=se(),a=e.target.description;if(t){let u=this.getBoundsFromNativeCache(t);return this.logger.info({bounds:u},"Got container bounds from native cache"),{bounds:u,cache:t}}let s=await this.findElement({description:a,tracer:i,metadata:n});if(!s.success)throw new w("NoMatchingElementError",s.thoughts??"No matching element found");let{resolvedTarget:c}=s;if(c.type!=="NATIVE")throw new Error(`ActionFailureError: Custom scroll container "${a}" resolved to a webview element. Custom containers must be native elements.`);let l=this.getBoundsFromNativeCache(c);return this.logger.info({bounds:l},"Got container bounds from AI"),{bounds:l,cache:c}}async tryUseCachedScrollPosition(e,t){let n=e.cache?.target;return n?n.type==="WEBVIEW"?this.tryUseWebviewCache(e,t):n.scrollDetails?this.tryUseNativeScrollCache(e,t,n):null:null}async tryUseWebviewCache(e,t){let n=se();try{let{thoughts:o}=await this.wrapTargetingAction({command:e,tracer:n,description:t,action:async i=>{if(i.type==="NATIVE")throw new Error("Expected WEBVIEW target but got NATIVE");await this.scrollWebviewTargetIntoView(i)}});return{success:!0,message:o}}catch(o){return this.logger.warn({err:o},"Failed to use webview cache, falling back to search"),null}}async tryUseNativeScrollCache(e,t,n){let o=n.scrollDetails,i=se(),a=e.scrollStepPercent??IO,s=o.scrollableElement.type==="CUSTOM"?o.scrollableElement.cache:void 0;await this.scrollByPixelDelta({pixelDelta:o.pixelDelta,scrollableElement:o.scrollableElement,containerCache:s,direction:o.direction,scrollStepPercent:a,aiMetadata:{commandId:e.id}});try{let l=await this.tryFindElement({cmd:e,description:t,tracer:i,scrollDetails:o,useAIIfCacheFails:!1});if(l)return l;this.logger.info("Element not found at cached position, undoing scroll")}catch(l){this.logger.warn({err:l},"Error finding element at cached position, will undo scroll")}let c=o.direction==="down"?"up":"down";return this.logger.info({pixelDelta:o.pixelDelta,originalDirection:o.direction,undoDirection:c,scrollableElementType:o.scrollableElement.type},"Undoing scroll"),await this.scrollByPixelDelta({pixelDelta:o.pixelDelta,scrollableElement:o.scrollableElement,containerCache:s,direction:c,scrollStepPercent:a,aiMetadata:{commandId:e.id}}),null}async tryFindElement({cmd:e,description:t,tracer:n,scrollDetails:o,useAIIfCacheFails:i=!0}){let a,s,c=e.cache?.target;if(c&&c.resolvedDescription===t&&!e.disableCache){let u=await this.stateManager.getDomState({skipFetchingFullWebviewContent:!0,removeWebviewContent:!0});try{let{resolvedTarget:d}=await mp({target:c,domState:u,stateManager:this.stateManager,logger:this.logger});a=d,s="Successfully resolved scroll to target with cache.",this.logger.info("Successfully resolved scroll to target from cache")}catch(d){this.logger.warn({err:d},"Failed to resolve target from cache")}}if(!a&&!i)return null;if(!a)try{let u=await this.findElement({description:t,tracer:n,metadata:{commandId:e.id}});if(!u.success)return null;a=u.resolvedTarget,s=u.thoughts}catch(u){if(u instanceof w&&u.reason==="NoMatchingElementError")return null;throw this.logger.warn({err:u},"Failed to find scroll-to target with AI"),u}return a.type==="WEBVIEW"?(await this.scrollWebviewTargetIntoView(a),la({command:e,updatedCache:pp(a),updatedWithAI:!0,logger:this.logger}),{success:!0,message:s}):(la({command:e,updatedCache:{...a,scrollDetails:o},updatedWithAI:!0,logger:this.logger}),{success:!0,message:s})}async searchForElement(e,t,n){let o=se(),i=await this.resolveContainer({scrollableElement:e.scrollableElement,aiMetadata:{commandId:e.id}});return this.scrollAndSearch(e,t,o,n,i)}async scrollAndSearch(e,t,n,o,i){let a=0,s=i.bounds,c=s.height*o,l=!0;for(let u=0;u<PO;u++){this.throwIfAborted();let d=this.buildScrollDetails(e,a,i.cache),p=await this.tryFindElement({cmd:e,description:t,tracer:n,scrollDetails:d});if(p)return p;if(!l)throw new Error(`ActionFailureError: Could not find element "${t}" after scrolling to the end`);this.logger.debug({attempt:u,cumulativePixelDelta:a},"Element not found, scrolling further");let m=kK(e.scrollableElement);l=await this.scrollByPage({direction:e.direction,containerBounds:s,scrollStepPercent:o,rawCoordinates:m}),a+=e.direction==="down"?c:-c}throw new Error(`ActionFailureError: Could not find element "${t}" after ${PO} scroll attempts`)}buildScrollDetails(e,t,n){return e.scrollableElement.type==="CUSTOM"?{pixelDelta:t,scrollableElement:{type:"CUSTOM",target:e.scrollableElement.target,cache:n},direction:e.direction}:e.scrollableElement.type==="CUSTOM_COORDINATES"?{pixelDelta:t,scrollableElement:e.scrollableElement,direction:e.direction}:{pixelDelta:t,scrollableElement:e.scrollableElement,direction:e.direction}}async scrollWebviewTargetIntoView(e){let{controller:t,browserTarget:n}=e;await t.browser.hover(n)}async scrollByPage({direction:e,containerBounds:t,scrollStepPercent:n,rawCoordinates:o}){return se().startAsyncSpan("EMULATOR_INTERACTION",async a=>(a.attributes.containerBounds=t,a.attributes.direction=e,this.executeScrollGesture({direction:e,containerBounds:t,scrollStepPercent:n,rawCoordinates:o})),{name:`Scroll ${e} by one page`})}async scrollByPixelDelta({pixelDelta:e,scrollableElement:t,containerCache:n,direction:o,scrollStepPercent:i,aiMetadata:a}){if(e===0)return;let s=se(),c,l,u;if(t.type==="CUSTOM_COORDINATES")c=t.startX,l=t.startY,u=t.deltaPixels;else{let m=(await this.resolveContainer({scrollableElement:t,containerCache:n,aiMetadata:a})).bounds,g=m.height*i,h=this.calculateSwipeCoordinates({containerBounds:m,direction:o,desiredDelta:g});c=h.startX,l=h.startY,u=h.actualDelta}let d=Math.ceil(Math.abs(e)/u);this.logger.debug({pixelDelta:e,direction:o,scrollableElementType:t.type,startX:c,startY:l,maxScrollPerStep:u,numScrolls:d},"scrollByPixelDelta calculated parameters"),await s.startAsyncSpan("EMULATOR_INTERACTION",async p=>{p.attributes.pixelDelta=e,p.attributes.numScrolls=d,p.attributes.maxScrollPerStep=u,p.attributes.startX=c,p.attributes.startY=l;let m=0;for(let g=0;g<d;g++){this.throwIfAborted();let h=Math.abs(e)-m,f=Math.min(u,h);await this.performRawSwipe({startX:c,startY:l,deltaPixels:f,direction:this.invertDirection(o)}),m+=f}},{name:`Scroll ${o} by ${e}px`})}async executeScrollGesture({direction:e,containerBounds:t,scrollStepPercent:n,diffThresholdPercent:o=DK,rawCoordinates:i}){let a=await this.stateManager.getRawScreenshotBase64(),s,c,l;if(i)s=i.startX,c=i.startY,l=i.deltaPixels;else{let m=t.height*n,g=this.calculateSwipeCoordinates({containerBounds:t,direction:e,desiredDelta:m});s=g.startX,c=g.startY,l=g.actualDelta}await this.performRawSwipe({startX:s,startY:c,deltaPixels:l,direction:this.invertDirection(e)});let u=await this.stateManager.getRawScreenshotBase64(),d=ps(a,u),p=d>o;return this.logger.debug({diffPercent:d,diffThresholdPercent:o,canScrollMore:p,direction:e,actualDelta:l,rawCoordinates:i},"Scroll gesture visual diff result"),p}};function kK(r){if(r.type==="CUSTOM_COORDINATES")return r}import{randomUUID as FK}from"crypto";import cu from"fs";import{tmpdir as UK}from"os";import Gs from"path";var fp=class extends Rt{async doInstallApk(e){return await this.installApkFromUri(e.uri),{success:!0,message:"Installed APK."}}async installApkFromUri(e){let t=await this.resolveUriToLocalApk(e);try{await this.stateManager.executeRawADBCommand(`install -r ${Gs.resolve(t.localPath)}`),this.logger.info({uri:e,localPath:t.localPath},"Installed APK on device")}finally{t.cleanup()}}async resolveUriToLocalApk(e){try{let t=new URL(e);if(t.protocol==="file:"){let n=t.href.slice(7),o;if(cu.existsSync(n))o=n;else if(cu.existsSync(Gs.join("/",n)))o=Gs.join("/",n);else throw new w("UserConfigurationError",`APK not found at path: ${n}`);return this.assertFileExists(o),{localPath:o,cleanup:()=>{}}}if(t.protocol==="http:"||t.protocol==="https:"){let n=await this.fetchWithTimeout(t);if(!n.ok)throw new w("UserInfrastructureError",`Failed to download APK from ${e} (status ${n.status})`);let o=await n.arrayBuffer(),i=Buffer.from(o),a=await this.writeBufferToTempFile(i,t.pathname);return{localPath:a,cleanup:()=>{try{cu.unlinkSync(a)}catch(s){this.logger.warn({err:s,path:a},"Failed to remove temporary APK file")}}}}throw new w("UserConfigurationError",`Unsupported URI scheme for APK installation: ${t.protocol}`)}catch(t){if(t instanceof TypeError){let n=Gs.resolve(e);return this.assertFileExists(n),{localPath:n,cleanup:()=>{}}}throw t}}assertFileExists(e){try{cu.accessSync(e)}catch{throw new w("UserConfigurationError",`APK not found at path: ${e}`)}}async fetchWithTimeout(e){let t=AbortSignal.timeout(9e4);return await fetch(e,{signal:t})}async writeBufferToTempFile(e,t){let n=Gs.extname(t)||".apk",o=Gs.join(UK(),`momentic-apk-${FK()}${n}`);return cu.writeFileSync(o,e),o}};import{existsSync as BK,readFileSync as zK}from"fs";import HK from"zod";var GK=HK.string().url();async function OO(r){if(GK.safeParse(r).success){let e=new AbortController,t=setTimeout(()=>e.abort(),1e4),n;try{n=await fetch(r,{signal:e.signal})}catch(i){throw new w("UserInfrastructureError",`Fetch failed or timed out for URL: ${r}`,{errOptions:{cause:i}})}finally{clearTimeout(t)}if(!n.ok)throw new w("UserInfrastructureError",`Failed to fetch file from URL: ${r}, status: ${n.status}`);let o=await n.arrayBuffer();return Buffer.from(o).toString("base64")}if(!BK(r))throw new w("UserInfrastructureError",`File does not exist at path: ${r}`);return zK(r).toString("base64")}var Sp=class extends Rt{async dragNative(e,t,n){let{left:o,top:i,width:a,height:s}=this.getBoundsFromNativeCache(e),{left:c,top:l,width:u,height:d}=this.getBoundsFromNativeCache(t),p=o+a/2,m=i+s/2,g=c+u/2,h=l+d/2,f=n?.hoverDuration??500,y=n?.dragDuration??1e3;await this.driver.performActions([{type:"pointer",id:"finger1",parameters:{pointerType:"touch"},actions:[{type:"pointerMove",duration:0,x:p,y:m},{type:"pointerDown",button:0},{type:"pause",duration:f},{type:"pointerMove",duration:y,x:g,y:h},{type:"pointerUp",button:0}]}]),await this.driver.releaseActions()}async dragWebview(e,t,n){let{controller:o}=e;if(e.controller!==t.controller)throw new w("UserConfigurationError","Cannot drag and drop between different webviews");let i=n?.dragDuration??1e3,a=n?.hoverDuration??1e3,s;n?.dragDuration&&(s=Math.max(1,Math.floor(i/200))),await o.browser.dragAndDrop(e.browserTarget,t.browserTarget,{hoverDurationMs:a,steps:s,dragDurationMs:i})}async executeDragAndDrop({command:e}){let t=se();if(e.fromTarget.type!=="description"||e.toTarget.type!=="description")throw new w("UserConfigurationError","Drag and drop only supports description targets for now");let n=e.fromTarget.description,{result:o,thoughts:i}=await this.wrapTargetingAction({command:e,tracer:t,description:n,cacheKey:"cache",targetName:"fromTarget",action:async l=>l}),a=e.toTarget.description,{result:s,thoughts:c}=await this.wrapTargetingAction({command:e,tracer:t,description:a,cacheKey:"cache",targetName:"toTarget",action:async l=>l});if(o.type!==s.type)throw new w("UserConfigurationError",`Drag and drop targets must be in the same context (both native or both webview). Found: From=${o.type}, To=${s.type}`);return await t.startAsyncSpan("EMULATOR_INTERACTION",async l=>{o.type==="NATIVE"&&s.type==="NATIVE"?await this.dragNative(o,s,{hoverDuration:e.hoverDuration,dragDuration:e.dragDuration}):o.type==="WEBVIEW"&&s.type==="WEBVIEW"&&(l.withinWebview=!0,await this.dragWebview(o,s,{hoverDuration:e.hoverDuration,dragDuration:e.dragDuration}))},{name:"Drag and drop"}),{success:!0,message:`${i}
4577
4577
  ${c}`}}};import{cloneDeep as LO}from"lodash-es";var yp=class{async getTextContent(e){return await e.textContent()??""}async getAttribute(e,t){return await e.getAttribute(t,{timeout:3e3})??""}async getTagName(e){return await e.evaluate(t=>t.tagName)}async isEditable(e){return await e.isEditable({timeout:dr*1e3})}async isEnabled(e){return await e.isEnabled({timeout:dr*1e3})}async isFocused(e){return await e.evaluate(t=>t===document.activeElement)}async getStyleProperty(e,t){return await e.evaluate((n,o)=>window.getComputedStyle(n).getPropertyValue(o),t)}},bp=class{async getTextContent(e){return Kc(e)}async getAttribute(e,t){return e.getAttribute(t)??""}async getTagName(e){return e.tagName}async isEditable(e){throw new Error("Cannot perform editable check on native element")}async isEnabled(e){return e.getAttribute("enabled")==="true"}async isFocused(e){return e.getAttribute("focused")==="true"}async getStyleProperty(e,t){throw new Error("Cannot perform computed style checks on native element")}};var jK=5e3,Ep=class extends Rt{async executeElementCheck(e){let t=Date.now(),n=(e.timeout??dr)*1e3,o=n+1e4,i,a=0,s=500,c=LO(e.cache);if(e.target.type!=="description")throw new w("UserConfigurationError","x/y targets are not supported for the Element Check step");for(;a-t<n;){if(Date.now()-t>o){this.logger.warn("Exceeded max system timeout for element check, exiting...");break}if(this.throwIfAborted(),i=await this.executeElementCheckHelper(e),a=Date.now(),!i.success)e.cache=c,c=LO(c),await J(s,this.abortSignal),s=Math.min(Math.floor(s*1.5),jK);else return i}let l=await this.executeElementCheckHelper(e,{cacheIsInvalidAfterResolution:!0});if(!l.success&&c&&e.cache){let u=Zc({logger:this.logger,originalTarget:Ui(c)?c.target:void 0,newTarget:e.cache.target});u&&Ps(c.target,u)&&(e.cache={target:u,updatedAt:e.cache.updatedAt})}return l}async executeElementCheckHelper(e,t){let n=se();if(e.target.type!=="description")throw new w("UserConfigurationError","x/y targets are not supported for the Element Check step");let o=Om(e.assertion);try{return(await this.wrapTargetingAction({...t??{},command:e,tracer:n,action:async a=>"type"in a&&a.type==="NATIVE"?await this.executeNativeElementCheck(e,a):await this.executeWebviewElementCheck(e,a),description:e.target.description,skipFetchingFullWebviewContent:!0,removeWebviewContent:!0,disableTargetRedirection:!0})).result}catch(i){return o&&(i instanceof w&&i.reason==="NoMatchingElementError"||i instanceof wo)?{success:!0}:{success:!1,message:`Failed to evaluate element content assertion: ${i instanceof Error?i.message:`${i}`}`}}}async executeNativeElementCheck(e,t){let n=se(),{assertion:o}=e,i=t.resolvedNode;return await n.startAsyncSpan("ELEMENT_ASSERTION",async a=>{let s=await this.executeElementAssertion({assertion:o,element:i,elementPropertyAccessors:new bp,span:a});return a.result=s,s},{name:"Native element check"})}async executeWebviewElementCheck(e,t){let n=se(),o=t.browserTarget.locator,i=e.assertion;return await n.startAsyncSpan("ELEMENT_ASSERTION",async a=>{await t.controller.browser.highlight(o);let s=await this.executeElementAssertion({assertion:i,element:o,elementPropertyAccessors:new yp,span:a});return a.result=s,s},{name:"Webview element check"})}async executeElementAssertion({assertion:e,element:t,elementPropertyAccessors:n,span:o}){switch(e.type){case"ELEMENT_CONTENT":{let i=await n.getTextContent(t)??"";return o.attributes.elementTextContent=Vt(i,500,!0),Un(i,e.value,e.operation,{negated:!!e.negated,ignoreCase:!1})?{success:!0}:{success:!1,message:`The content ${tn(e)} '${e.value}': ${i}`}}case"ELEMENT_ATTRIBUTE":{"evaluate"in t&&(o.attributes.elementOuterHtml=Vt(await t.evaluate(a=>a.cloneNode(!1).outerHTML),500,!0));let i;try{i=await n.getAttribute(t,e.attr)}catch{i=null}if(!Un(i,e.value,e.operation,{negated:!!e.negated,ignoreCase:!1})){let a=tn(e);return{success:!1,message:`The attribute ${e.attr} ${a}${e.operation==="EXISTS"?"":` '${e.value}': ${i}`}`}}return{success:!0}}case"ELEMENT_EXISTENCE":{let i=!1;switch(e.condition){case"EDITABLE":i=await n.isEditable(t);break;case"VISIBLE":case"EXISTS":i=!0;break;case"ENABLED":{i=await n.isEnabled(t);break}case"FOCUSED":i=await n.isFocused(t);break;default:throw e.condition,new Error("Unrecognized element condition type")}return i=e.negated?!i:i,i?{success:!0}:{success:!1,message:`The element ${tn(e)}`}}case"ELEMENT_NAME":{let i=await n.getTagName(t);return Un(i,e.value,e.operation,{negated:!!e.negated,ignoreCase:!0})?{success:!0}:{success:!1,message:`The element tag name ${tn(e)} '${e.value}': ${i}`}}case"ELEMENT_STYLE":{let i=await n.getStyleProperty(t,e.property);if(!Un(i,e.value,e.operation,{negated:!!e.negated,ignoreCase:!1})){let a=tn(e);return{success:!1,message:`The style property ${e.property} ${a}${e.operation==="EXISTS"?"":` '${e.value}': ${i}`}`}}return{success:!0}}default:throw new Error("Unrecognized element assertion type")}}};var WK=5e3,Tp=class extends Rt{async executeScreenCheck(e){let{timeout:t}=e,n=Date.now(),o=(t??dr)*1e3,i=o+1e4,a=0,s=500;for(;a-n<o;){if(Date.now()-n>i){this.logger.warn("Exceeded max system timeout for screen check, exiting...");break}this.throwIfAborted();let c=await this.executeScreenCheckHelper(e);if(a=Date.now(),!c.success)await J(s,this.abortSignal),s=Math.min(Math.floor(s*1.5),WK);else return c}return await this.executeScreenCheckHelper(e)}async executeScreenCheckHelper(e){return await se().startAsyncSection("Execute screen check",async(n,o)=>{let[i,a]=await Promise.all([this.executeNativeScreenCheckHelper({span:o,command:e}),this.executeWebviewScreenCheckHelper(e)]);return a?e.assertion.negated?i.success&&a.success?i:i.success?a:i:i.success?i:a:i})}async executeNativeScreenCheckHelper({span:e,command:t}){let{assertion:n}=t;switch(n.type){case"CONTENT":try{let o=(await this.stateManager.getDomState({skipFetchingFullWebviewContent:!0,removeWebviewContent:!0})).graph.document.documentElement?.outerHTML;if(!o)throw new Error("Failed to get screen HTML");let i=o.includes(n.value)===!n.negated;return o.length>1e4&&(o=o.slice(0,1e4)+"...TRUNCATED"),i?{success:!0}:(e.attributes.screenContent=o,{success:!1,message:`The screen ${MS(n)}.`})}catch(o){return{success:!1,message:`Failed to evaluate screen content assertion: ${o instanceof Error?o.message:`${o}`}`}}default:return n.type,{success:!1,message:`Unsupported screen check assertion type: ${n.type}`}}}async executeWebviewScreenCheckHelper(e){let t=await this.stateManager.getActiveWebview();if(!t||!t.browserController)return;let n=t.browserController.browser;return await lp({assertion:e.assertion,logger:this.logger,browser:n,autoExpandIframes:!!n.userBrowserSettings.autoExpandIframes})}};var vp=class extends Rt{async doUninstallApk(e){return await this.uninstallApkPackage(e.packageName),{success:!0,message:"Uninstalled APK."}}async uninstallApkPackage(e){let t=e.replace(/^package:/,""),n=await this.stateManager.executeRawADBCommand(`shell pm list packages | grep -E "^package:${t}$" || true`);if(!n||n.length===0)throw new w("UserConfigurationError",`Package ${t} not found`);if(n.split(`
4578
4578
  `).filter(i=>!!i).length>1)throw new w("UserConfigurationError",`Multiple packages found for ${t}`);try{await this.stateManager.executeRawADBCommand(`uninstall ${t}`)}catch(i){throw new w("UserInfrastructureError",`Failed to uninstall package ${t}: ${i}`)}}};import{createHash as $K}from"crypto";import{_android as qK,chromium as KK}from"playwright";import{z as St}from"zod";var NO=St.object({"Android-Package":St.string(),Browser:St.string(),"Protocol-Version":St.string(),"User-Agent":St.string(),"V8-Version":St.string(),"WebKit-Version":St.string(),webSocketDebuggerUrl:St.string()}),DO=St.object({description:St.string(),devtoolsFrontendUrl:St.string(),id:St.string(),title:St.string(),type:St.string(),url:St.string(),webSocketDebuggerUrl:St.string()}),kO=St.object({proc:St.string(),webview:St.string(),webviewName:St.string()}),FO=St.array(kO.extend({info:NO.optional(),pages:St.array(DO).optional()})),wYe=St.array(kO.extend({info:NO,pages:St.array(DO)}));var Ap=class r{driver;limbarClient;device;currentContext;logger;webviews=new Map;fixtures;orgId;options;aborter;constructor({driver:e,context:t,limbarClient:n,logger:o,device:i,fixtures:a,orgId:s,options:c,aborter:l}){this.driver=e,this.limbarClient=n,this.device=i,this.currentContext=t,this.logger=o,this.fixtures=a,this.orgId=s,this.options=c,this.aborter=l;for(let u of["SIGINT","SIGTERM"])process.on(u,async()=>{await this.cleanupWebviews()})}static async init({driver:e,logger:t,fixtures:n,limbarClient:o,orgId:i,adbPort:a,options:s,aborter:c,playwrightDevice:l}){let u=await e.getContext(),d=typeof u=="string"?u:u.id,p;if(l)p=l;else{let g=(await qK.devices()).filter(h=>h._initializer?.serial?.endsWith(a.toString())||h._initializer?.serial?.endsWith((a-1).toString()));if(t.warn({devices:g.map(h=>({serial:h._initializer?.serial,model:h._initializer?.model}))},"No playwright device provided, using ADB to find device"),g.length===0)throw new w("UserInfrastructureError",`Momentic found no devices listening on port ${a} or ${a-1}. This can occur if Android Studio reuses existing emulators. Please run 'adb emu kill' and 'adb disconnect' and retry.`);if(g.length>1)throw new w("UserInfrastructureError",`Momentic found multiple devices on the ports ${a} or ${a-1}. This can occur if Android Studio reuses existing emulators. Please run 'adb emu kill' and 'adb disconnect' and retry.`);p=g[0]}let m=new r({driver:e,context:d,logger:t,device:p,fixtures:n,orgId:i,options:s,aborter:c,limbarClient:o});return m.startWebviewRefreshInterval(),m}async getContexts(){let e=await this.driver.getContexts({}),t=Array.from(this.webviews.values());return{contexts:e,webviews:t.map(n=>({contextId:n.contextId,packageName:n.packageName,active:n.active,hasPlaywright:!!n.browserController,lastSeen:n.lastSeen,socketName:n.socketName}))}}async getRawScreenshotBase64(e=2){let t=se(),n;for(let o=0;o<e;o++)try{return await t.startAsyncSpan("EMULATOR_READ_STATE",async()=>await this.driver.takeScreenshot(),{name:"Take screenshot",signal:this.aborter.controller?.signal,timeoutMs:2e3})}catch(i){if(n=i,this.logger.warn({err:i},"Failed to take screenshot"),o===e-1)throw i}throw new w("InternalWebAgentError",`Failed to take screenshot: ${n}`)}async getCurrentScreenshotPngString(){return`data:image/png;base64,${await this.getRawScreenshotBase64(1)}`}async waitForScreenshotStability({timeoutMs:e,signal:t,reason:n,tolerancePercent:o=1}){await se().startAsyncSpan("WAIT_FOR_SCREENSHOT_STABILITY",async i=>{i.attributes.reason=n;let a=Date.now(),s,c,l=!1;for(;Date.now()-a<e;){c&&c<500&&await J(500-c,t),t?.throwIfAborted();let u=Date.now();if(!s){s=await this.getRawScreenshotBase64(),c=u-a;continue}let d=await this.getRawScreenshotBase64();if(c=u-a,ps(s,d)<=o){l=!0;break}s=d}l||(i.attributes.timedOut=!0,this.logger.warn({purpose:n},"Timed out waiting for screenshot stability"))})}async waitForPageSourceStability({timeoutMs:e,signal:t,reason:n}){await se().startAsyncSpan("WAIT_FOR_PAGE_STABILITY",async o=>{o.attributes.reason=n;let i=Date.now(),a,s,c=!1;for(;Date.now()-i<e;){s&&s<250&&await J(250-s,t),t?.throwIfAborted();let l=Date.now(),u;try{u=await this.getPageSource()}catch(p){this.logger.warn({err:p},"Failed to get page source during stability wait"),s=Date.now()-l;continue}let d=$K("md5").update(u).digest("hex");if(s=Date.now()-l,a&&a===d){c=!0;break}a=d}c||(o.attributes.timedOut=!0,this.logger.warn({purpose:n},"Timed out waiting for page source stability"))})}async getCurrentPackage(){let e=await this.driver.execute("mobile: getCurrentPackage");return typeof e=="string"?e:void 0}async getActiveWebviewNodes(){let t=(await this.getDomState({skipFetchingFullWebviewContent:!0,removeWebviewContent:!0})).graph,n=[];for(let[o,i]of t.idToElement.entries())n.some(a=>a.id===o)||su(i)&&n.push({id:o,originalElement:i,bounds:sa(i)});return n}async getActiveWebviewContent(){let e=await this.getActiveWebview();if(!e||!e.browserController)return;this.throwIfAborted();let t=e.browserController;return(await se().startAsyncSpan("EMULATOR_READ_STATE",()=>t.getBrowserState({abortSignal:this.aborter.controller?.signal,skipWait:!0,skipWaitForPageLoad:!0,logger:this.logger,serializationOpts:{noId:!0}}),{name:"Get webview content",signal:this.aborter.controller?.signal})).serializedTree}async getDomState(e){return await se().startAsyncSection("Get emulator state XML",async()=>{let n;if(!e?.skipFetchingFullWebviewContent)try{n=await this.getActiveWebviewContent()}catch(c){this.logger.error({err:c},"Could not get webview info to get the nested DOM state")}this.throwIfAborted();let i=e?.filterOffscreenElements??!0?await this.getViewportBounds():void 0,a=await this.getPageSource();return{graph:await EO(a,{injectedWebviewContent:n,disableMomenticAccessibilityTree:this.options.disableMomenticAccessibilityTree,removeWebviewContent:e?.removeWebviewContent,viewportBounds:i}),context:this.currentContext}},{timeoutMs:15e3})}async getPageSource(){return await se().startAsyncSpan("EMULATOR_READ_STATE",()=>this.driver.getPageSource(),{name:"Get Android page source",signal:this.aborter.controller?.signal})}async getViewportBounds(){let e=await this.driver.getWindowRect();return{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height}}refreshPromise;refreshInterval;async refreshWebviewsManually(e){if(this.refreshPromise){await this.refreshPromise;return}clearInterval(this.refreshInterval),this.refreshPromise=this.doRefreshWebview(e).catch(t=>{this.logger.warn({err:t},"Error refreshing webviews, continuing...")}).finally(()=>{this.refreshPromise=void 0,this.startWebviewRefreshInterval()})}startWebviewRefreshInterval(){this.refreshInterval||(this.refreshInterval=setInterval(()=>{this.refreshPromise=this.doRefreshWebview("auto refresh").catch(e=>{this.logger.warn({err:e},"Error refreshing webviews, continuing...")}).finally(()=>{this.refreshPromise=void 0})},15e3))}async doRefreshWebview(e){this.logger.info({reason:e},"Refreshing webviews"),await this.getPageSource(),this.throwIfAborted();let t=await this.getCurrentPackage();if(t==="com.android.permissioncontroller")return;let n=await this.getDetailedContexts();if(!n){this.logger.warn("No context details, not proceeding with refreshing webviews");return}let o=Date.now(),i=new Set;for(let a of n){if(this.throwIfAborted(),a.webview==="NATIVE_APP")continue;let s=a.info["Android-Package"];if(t&&s!==t&&this.logger.warn({packageName:s,currentPkgName:t},"Ignoring webview not in the active package"),i.add(a.webview),!this.webviews.has(a.webview)||!this.webviews.get(a.webview)?.active){let c={contextId:a.webview,packageName:s,active:!1,lastSeen:o,socketName:a.proc.startsWith("@")?a.proc.substring(1):a.proc};this.logger.info({contextId:c.contextId,packageName:c.packageName,socketName:c.socketName},"New webview detected"),this.webviews.set(a.webview,c);let l;if(s==="com.android.chrome"?(this.logger.info({webviewInfo:c},`Connecting Playwright to Android Chrome: ${a.webview}`),l=await this.connectPlaywrightToChrome(c),this.logger.info(`Connected Playwright to Android Chrome: ${a.webview}`)):(this.logger.info({webviewInfo:c},`Connecting Playwright to webview: ${a.webview}`),l=await this.connectPlaywrightToWebview(s,c.socketName),l&&this.logger.info(`Connected Playwright to webview ${a.webview}`)),!l)continue;c.browserController=l,c.active=!0}}for(let[a,s]of this.webviews.entries())!i.has(a)&&s.active&&(this.logger.info(`Disconnecting dead webview ${a}`),this.disconnectPlaywrightFromWebview(s),s.active=!1);this.logger.info("Refreshed webviews")}async getActiveWebview(){await this.refreshPromise;let e=await this.driver.execute("mobile: getCurrentPackage"),t=async()=>{e!==void 0&&typeof e!="string"&&this.logger.warn({currentPkg:e},"Unexpected getCurrentPackage result"),this.logger.info({currentPkg:e,allWebviews:Array.from(this.webviews.values()).map(i=>({contextId:i.contextId,packageName:i.packageName,active:i.active}))},"getActiveWebview: filtering webviews");let o=[];for(let i of this.webviews.values())i.packageName===e&&i.active&&o.push(i);return this.logger.info(`getActiveWebview: found ${o.length} matching webviews`),o},n=await t();if(n.length===0&&(await se().startAsyncSection("Refresh webviews",async()=>{await this.refreshWebviewsManually("no matching webview during getActiveWebview")}),n=await t()),n.length>1)throw new w("UserInfrastructureError","Multiple active webviews in a single package is currently not supported");return n[0]}getDeviceSerial(){let e=this.driver.capabilities,t=n=>{if(!e||typeof e!="object")return;let o=e[n];return typeof o=="string"?o:void 0};return t("deviceUDID")||t("udid")||t("appium:udid")||t("appium:deviceUDID")}async executeRawADBCommand(e){let t=this.getDeviceSerial(),n=e.trim().split(/\s+/).filter(i=>i.length>0);this.logger.info({serial:t,cmdArgs:n},"Executing ADB command");let o=await kt(n,{serial:t,timeoutMs:15e3,throwOnError:!0});return this.logger.info({result:o},"ADB command result"),o}async cleanupWebviews(){this.refreshInterval&&(clearInterval(this.refreshInterval),this.refreshInterval=void 0);for(let[e,t]of this.webviews.entries())this.logger.info(`Disconnecting webview ${e}`),this.disconnectPlaywrightFromWebview(t),t.active=!1}async getDetailedContexts(){return await se().startAsyncSpan("EMULATOR_READ_STATE",async()=>{let t=await this.driver.execute("mobile: getContexts");this.aborter.controller?.signal.throwIfAborted();let n;try{n=FO.parse(t)}catch(o){throw new w("InternalWebAgentError",`Failed to parse contexts. Original error:
4579
4579
  ${o}
@@ -4583,7 +4583,7 @@ ${n.map(o=>o.configFilePath)}`);if(n.length===0)throw new Error("No valid Moment
4583
4583
  `)){let o=n.indexOf("=");if(o===-1)continue;let i=n.slice(0,o),a=n.slice(o+1).trim();t[i]=a}return t}async function DY(r,e,t){try{let o=t["github.user"]||void 0;if(o)return o}catch{}let n;try{if(e?.startsWith("http://")||e?.startsWith("https://"))n=new URL(e).host;else if(e?.startsWith("git@")){let o=e.indexOf("@"),i=e.indexOf(":",o+1);o!==-1&&i!==-1&&(n=e.slice(o+1,i))}}catch{}if(n=n?.toLowerCase(),!!n){try{if(e?.startsWith("git@")&&n?.includes("github")){let{stdout:o,stderr:i}=await YO("ssh",["-T","-o","BatchMode=yes",`git@${n}`],{timeout:5e3}),s=`${o??""}${i??""}`.trim().match(/Hi\s+([A-Za-z0-9_-]+)!/);if(s?.[1])return s[1]}}catch{}try{let o=n&&n!=="github.com"?["api","--hostname",n,"user","-q",".login"]:["api","user","-q",".login"],{stdout:i}=await YO("gh",o,{timeout:5e3}),a=i?.toString().trim();if(a)return a}catch{}}}async function kY(r,e,t){let n=e?.includes("github.com"),o=e?.includes("gitlab.com");try{if(n)return DY(r,e,t);if(o)return}catch{}}function xp(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 st(r,e){try{return(await e).trim()}catch(t){if(t instanceof Error&&t.message.includes("not a git repository"))return;r.error({err:t},"Failed to run git command");return}}function FY(){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";if(process.env.PROJECT_ID&&process.env.BUILD_ID)return"GCPCloudBuild";if(process.env.MOMENTIC_GIT_OVERRIDE)return"Custom"}async function UY(r){let[e,t,n]=await Promise.all([st(r,at.show(["--no-patch","--format=%ci"])),st(r,at.show(["-s","--pretty=%B"])),st(r,at.show(["-s","--pretty=%an"]))]),o=process.env.GITHUB_SERVER_URL&&process.env.GITHUB_REPOSITORY?`${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}`:void 0;return{ciProvider:"GithubActions",gitCommitSha:process.env.GITHUB_SHA,gitCommitShaShort:process.env.GITHUB_SHA?.slice(0,6),gitCommitTimestamp:e?fo(e):void 0,gitBranchName:process.env.GITHUB_HEAD_REF||process.env.GITHUB_REF_NAME,gitOriginUrl:o,gitCommitMessage:t,gitCommitAuthorName:n,githubRepository:process.env.GITHUB_REPOSITORY,pipelineId:process.env.GITHUB_RUN_ID}}async function BY(r){let[e,t,n]=await Promise.all([st(r,at.listRemote(["--get-url","origin"])),st(r,at.show(["-s","--pretty=%B"])),st(r,at.show(["-s","--pretty=%an"]))]);return{ciProvider:"GitlabCI",gitCommitSha:process.env.CI_COMMIT_SHA,gitCommitShaShort:process.env.CI_COMMIT_SHORT_SHA,gitCommitTimestamp:process.env.CI_COMMIT_TIMESTAMP?fo(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_PROJECT_PATH,pipelineId:`${process.env.CI_PIPELINE_ID}:${process.env.CI_JOB_ID}`}}async function zY(r){let[e,t,n,o]=await Promise.all([st(r,at.show(["--no-patch","--format=%ci"])),st(r,at.listRemote(["--get-url","origin"])),st(r,at.show(["-s","--pretty=%B"])),st(r,at.show(["-s","--pretty=%an"]))]),i=process.env.CIRCLE_REPOSITORY_URL??t,a=i?.includes("github.com"),s=i?.includes("gitlab.com"),c=i?xp(i):void 0;return{ciProvider:"CircleCI",gitCommitSha:process.env.CIRCLE_SHA1,gitCommitShaShort:process.env.CIRCLE_SHA1?.slice(0,6),gitCommitTimestamp:e?fo(e):void 0,gitBranchName:process.env.CIRCLE_BRANCH,gitOriginUrl:i,gitCommitMessage:n,gitCommitAuthorName:o,githubRepository:a?c:void 0,gitlabProjectPath:s?c:void 0,pipelineId:process.env.CIRCLE_PIPELINE_ID}}async function HY(r){let[e,t,n]=await Promise.all([st(r,at.show(["--no-patch","--format=%ci"])),st(r,at.show(["-s","--pretty=%B"])),st(r,at.show(["-s","--pretty=%an"]))]),o=process.env.BUILDKITE_REPO,i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?xp(o):void 0;return{ciProvider:"Buildkite",gitCommitSha:process.env.BUILDKITE_COMMIT,gitCommitShaShort:process.env.BUILDKITE_COMMIT?.slice(0,6),gitCommitTimestamp:e?fo(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 GY(r){let[e,t,n]=await Promise.all([st(r,at.show(["--no-patch","--format=%ci"])),st(r,at.show(["-s","--pretty=%B"])),st(r,at.show(["-s","--pretty=%an"]))]),o=process.env["Build.Repository.Uri"],i=o?.includes("github.com"),a=o?.includes("gitlab.com"),s=o?xp(o):void 0;return{ciProvider:"AzureDevOps",gitCommitSha:process.env["Build.SourceVersion"],gitCommitShaShort:process.env["Build.SourceVersion"]?.slice(0,6),gitCommitTimestamp:e?fo(e):void 0,gitBranchName:process.env["System.PullRequest.SourceBranch"]??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 jY(r,e){let[t,n,o,i,a,s,c,l,u]=await Promise.all([st(r,at.revparse(["HEAD"])),st(r,at.revparse(["--short","HEAD"])),st(r,at.revparse(["--abbrev-ref","HEAD"])),st(r,at.listRemote(["--get-url","origin"])),st(r,at.show(["--no-patch","--format=%ci"])),st(r,at.show(["-s","--pretty=%B"])),st(r,at.show(["-s","--pretty=%an"])),e?st(r,at.raw(["merge-base","--fork-point",e])):Promise.resolve(void 0),NY(r)]),d=l?await st(r,at.show(["--no-patch","--format=%ci",l])):void 0,p=i?.includes("github.com"),m=i?.includes("gitlab.com"),g=i?xp(i):void 0,h=u["user.email"]||void 0,f=u["user.name"]||void 0,y=u["user.username"]||void 0,E=await kY(r,i,u)??y??void 0;return{ciProvider:"none",gitCommitSha:t,gitCommitShaShort:n,gitBranchName:o,gitOriginUrl:i,gitCommitTimestamp:a?fo(a):void 0,gitCommitMessage:s,gitCommitAuthorName:c,gitLocalUsername:E,gitLocalEmail:h,gitLocalName:f,lastCommitOnMainSha:l,lastCommitOnMainTimestamp:d?fo(d):void 0,githubRepository:p?g:void 0,gitlabProjectPath:m?g:void 0,pipelineId:void 0}}async function WY(){let r=process.env._HEAD_REPO_URL;return{ciProvider:"GCPCloudBuild",gitCommitSha:process.env.COMMIT_SHA,gitCommitShaShort:process.env.COMMIT_SHA?.slice(0,6),gitBranchName:process.env.BRANCH_NAME,gitOriginUrl:r?process.env._HEAD_REPO_URL:void 0,gitCommitTimestamp:void 0,gitCommitMessage:void 0,gitCommitAuthorName:void 0,githubRepository:r?process.env.REPO_FULL_NAME:void 0,pipelineId:`${process.env.PROJECT_ID}:${process.env.BUILD_ID}`}}function VY(){return{ciProvider:"Custom",gitCommitSha:process.env.GIT_COMMIT_SHA,gitCommitShaShort:process.env.GIT_COMMIT_SHA_SHORT??process.env.GIT_COMMIT_SHA?.slice(0,6),gitCommitTimestamp:fo(process.env.GIT_COMMIT_TIMESTAMP),gitBranchName:process.env.GIT_BRANCH_NAME,gitOriginUrl:process.env.GIT_ORIGIN_URL,gitCommitAuthorName:process.env.GIT_COMMIT_AUTHOR_NAME,gitCommitMessage:process.env.GIT_COMMIT_MESSAGE,lastCommitOnMainSha:process.env.LAST_COMMIT_ON_MAIN_SHA,lastCommitOnMainTimestamp:fo(process.env.LAST_COMMIT_ON_MAIN_TIMESTAMP),mergedGitBranchName:process.env.MERGED_GIT_BRANCH_NAME,githubRepository:process.env.GITHUB_REPOSITORY,gitlabProjectPath:process.env.GITLAB_PROJECT_PATH,gitLocalUsername:process.env.GIT_USERNAME,gitLocalEmail:process.env.GIT_EMAIL,gitLocalName:process.env.GIT_NAME}}async function $Y(r){let e=[...r.config.gitProtectedBranches??[]];return r.config.gitMainBranch&&e.push(r.config.gitMainBranch),{gitMainBranch:r.config.gitMainBranch,gitProtectedBranches:e}}async function du(r,e){let t=FY();if(!t)return jY(r,e);switch(t){case"GithubActions":return UY(r);case"GitlabCI":return BY(r);case"CircleCI":return zY(r);case"Buildkite":return HY(r);case"AzureDevOps":return GY(r);case"GCPCloudBuild":return WY();case"Custom":return VY()}}async function qY(r,e,t,n){let o=n;if(!n.gitCommitSha)return o;if(n.gitMainBranch&&(!o.lastCommitOnMainSha||!o.lastCommitOnMainTimestamp))try{let i=await e.getMergeBaseCommitFromGitlab(t,n.gitMainBranch,n.gitCommitSha);o={...o,lastCommitOnMainSha:i.sha,lastCommitOnMainTimestamp:i.committer.date}}catch(i){r.warn({err:i},"Failed to get merge base commit from Gitlab")}if(!o.gitCommitTimestamp||!o.gitCommitAuthorName||!o.gitCommitMessage||!o.gitCommitAuthorName)try{let i=await e.getCommitFromGitlab(t,n.gitCommitSha);i&&(o={...o,gitCommitTimestamp:o.gitCommitTimestamp??i.committer.date,gitCommitAuthorName:o.gitCommitAuthorName??i.author.name,gitCommitMessage:o.gitCommitMessage??i.message})}catch(i){r.warn({err:i},"Failed to get commit from Gitlab")}if(n.gitBranchName&&n.gitBranchName===n.gitMainBranch&&!o.mergedGitBranchName)try{let i=await e.getMergedBranchFromGitlab(t,n.gitBranchName??"",n.gitCommitSha);i.mergedBranch&&(o={...o,mergedGitBranchName:i.mergedBranch})}catch(i){r.warn({err:i},"Failed to get merged branch from Gitlab")}return o}async function KY(r,e,t,n,o){let i=o;if(!o.gitCommitSha)return i;if(o.gitMainBranch&&(!i.lastCommitOnMainSha||!i.lastCommitOnMainTimestamp))try{let a=await e.getMergeBaseCommitFromGithub(t,n,o.gitMainBranch,o.gitCommitSha);i={...i,lastCommitOnMainSha:a.sha,lastCommitOnMainTimestamp:a.committer.date}}catch(a){r.warn({err:a},"Failed to get merge base commit from GitHub")}if(!i.gitCommitTimestamp||!i.gitCommitAuthorName||!i.gitCommitMessage||!i.gitCommitAuthorName)try{let a=await e.getCommitFromGithub(t,n,o.gitCommitSha);a&&(i={...i,gitCommitTimestamp:i.gitCommitTimestamp??a.committer.date,gitCommitAuthorName:i.gitCommitAuthorName??a.author.name,gitCommitMessage:i.gitCommitMessage??a.message})}catch(a){r.warn({err:a},"Failed to get commit from GitHub")}if(o.gitBranchName&&o.gitBranchName===o.gitMainBranch&&!i.mergedGitBranchName)try{let a=await e.getMergedBranchFromGithub(t,n,o.gitBranchName??"",o.gitCommitSha);a.mergedBranch&&(i={...i,mergedGitBranchName:a.mergedBranch})}catch(a){r.warn({err:a},"Failed to get merged branch from GitHub")}return i}async function YY(r,e,t){try{if(t.githubRepository){let[n,o]=t.githubRepository.split("/");return await KY(r,e,n,o,t)}else if(t.gitlabProjectPath)return await qY(r,e,t.gitlabProjectPath,t)}catch(n){r.warn({err:n},"Failed to get remote git metadata")}return t}async function sn(r,e,t){let n=await $Y(t),o=await du(r,n.gitMainBranch),i={...n,...o};(!i.lastCommitOnMainSha||!i.lastCommitOnMainTimestamp)&&i.gitBranchName===n.gitMainBranch&&(i.lastCommitOnMainSha=i.gitCommitSha,i.lastCommitOnMainTimestamp=i.gitCommitTimestamp);let a=await YY(r,e,i);return{...n,...o,...a}}import{diff as XO}from"deep-object-diff";import ii from"fs";import{cloneDeep as XY}from"lodash-es";import _p from"path";import{v4 as JY}from"uuid";import mu from"yaml";function JO(r,e){let t=`${gn(e)}.module.yaml`,n=_p.join(_p.dirname(r),t);if(ii.existsSync(n))throw new Error(`A conflicting file already exists at the following path: ${n}`);return ii.renameSync(r,n),n}function ZO({content:r,schemaVersion:e,momenticFiles:t,project:n,forceSaveOnNoDiffs:o}){let i=t.mobileModules[r.moduleId]?.fullFilePath,a=t.mobileModules[r.moduleId]?.name;if(!i||!ii.existsSync(i))throw new Error(`Tried to update mobile module ${r.moduleId} that could not be found on disk`);let s=ii.readFileSync(i,"utf-8"),c=mu.parse(s),l={...c,...r,schemaVersion:e},u=po({fileType:Xe.MOBILE_MODULE,...cc.parse(l),steps:Rr.array().parse(r.steps)}),d=!!r.name&&r.name!==a,p=XO(u,c);if(p&&Object.keys(p).length===0&&!o&&!d)return;let m=mu.stringify(u);ii.writeFileSync(i,m,"utf-8");let g;d&&(g=JO(i,r.name)),Wn(g||i,n.config)}function QO({moduleId:r,patch:e,momenticFiles:t,project:n,logger:o}){let i=t.mobileModules[r]?.fullFilePath;if(!i)throw new Error(`Tried to update mobile module ${r} that could not be found on disk`);let a=pu(i,o),s={...a,...e},c=po({fileType:Xe.MOBILE_MODULE,...pd.parse(s)}),l=XO(c,a);if(l&&Object.keys(l).length===0)return;let u=mu.stringify(c);ii.writeFileSync(i,u,"utf-8");let d;e.name&&(d=JO(i,e.name)),Wn(d||i,n.config)}async function eL({name:r,description:e,enabled:t,steps:n,folder:o,project:i}){let a=gn(r),s=_p.join(o,`${a}.module.yaml`),c=JY(),{stepsToSave:l}=await Bn({platform:"ANDROID",steps:n}),u={schemaVersion:Co,moduleId:c,description:e,enabled:t},d={fileType:Xe.MOBILE_MODULE,...u,steps:l},p=mu.stringify(bA.parse(d));return ii.writeFileSync(s,p,"utf-8"),Wn(s,i.config),{moduleId:c,name:r,description:e||void 0,steps:n}}function pu(r,e){let t=ii.readFileSync(r,"utf-8"),n=mu.parse(t);try{return{...pd.parse(n),name:_p.basename(r,".module.yaml")}}catch(o){throw e.error({err:o,moduleFilePath:r,moduleContents:t},`${r} does not parse as a valid Momentic mobile module`),o}}async function jy(r,e,t,n){let o=pu(r.fullFilePath,t),{resolvedSteps:i}=await Jc({rawSteps:o.steps,resolvedModuleCache:n||{},onFetchModule:async s=>{let c=e.mobileModules[s]?.fullFilePath;if(!c)throw new Error(`Could not find mobile module with id ${s}`);return pu(c,t)},logger:t,metadata:{id:o.moduleId,schemaVersion:o.schemaVersion}}),a={...o,name:r.name,description:o.description||void 0,steps:i};return n&&(n[r.id]=XY(a)),a}async function tL(r,e){let t={};return await Promise.all(Object.values(r.mobileModules).map(async n=>{await jy(n,r,e,t)})),Array.from(Object.values(t))}import{randomUUID as ZY}from"crypto";import ln from"fs";import ai from"path";import $s from"yaml";import Vs from"zod";function rL({name:r,description:e="",steps:t=[],settings:n={},folder:o}){let a=`${gn(r)}.test.yaml`,s=ai.join(o,a);if(ln.existsSync(s))throw new Error(`A test named '${r}' already exists at path '${s}'. Choose a different name.`);let c={fileType:Xe.MOBILE_TEST,id:ZY(),description:e,schemaVersion:xo,platform:"ANDROID",settings:n,steps:t},l=$s.stringify(c);return ln.writeFileSync(s,l,"utf-8"),{fullPath:s,testId:c.id}}function Wy(r){if(!ln.existsSync(r))throw new Error(`Test file not found: ${r}`);let e=ln.readFileSync(r,"utf-8").replace(/\r\n|\r/g,`
4584
4584
  `),t=$s.parse(e);if(!t.steps||!Array.isArray(t.steps))throw new Error(`Test ${r} is missing steps`);return t}async function So(r,e,t){let n=Wy(r),o;try{o=No.parse(n)}catch(i){throw new Error(`Mobile test ${r} is missing metadata or has invalid metadata: ${i}`)}switch(o.platform){case"ANDROID":return QY(r,e,t);case"IOS":return e4(r,e,t)}}async function QY(r,e,t){let n=Wy(r),o;try{o=os.parse(n)}catch(s){throw new Error(`Mobile test ${r} is missing metadata or has invalid metadata: ${s}`)}let{resolvedStepLists:i}=await BS({rawStepLists:{steps:n.steps,beforeSteps:n.beforeSteps,afterSteps:n.afterSteps},logger:e,testMetadata:o,onFetchModule:async s=>{let c=t.mobileModules[s]?.fullFilePath;if(!c)throw new Error(`Mobile module ${s} not found`);return pu(c,e)}});return{...o,steps:i.steps}}async function e4(r,e,t){let n=Wy(r),o;try{o=is.parse(n)}catch(s){throw new Error(`Mobile test ${r} is missing metadata or has invalid metadata: ${s}`)}let{resolvedStepLists:i}=await US({rawStepLists:{steps:n.steps,beforeSteps:n.beforeSteps,afterSteps:n.afterSteps},logger:e,testMetadata:o,onFetchModule:async s=>{throw new Error("iOS modules are not yet supported")}});return{...o,steps:i.steps}}async function nL({filePath:r,steps:e,settings:t,labels:n,folder:o,project:i,momenticFiles:a,schemaVersion:s}){let c=ai.isAbsolute(r)?r:ai.join(o,r);if(!ln.existsSync(c))throw new Error(`Test file not found: ${c}`);let l=ln.readFileSync(c,"utf-8").replace(/\r\n|\r/g,`
4585
4585
  `),u=$s.parse(l),d=uc.extend({steps:Vs.record(Vs.string(),Vs.unknown()).array()}).parse({...u,schemaVersion:s});if(d.fileType!==Xe.MOBILE_TEST)throw new Error(`File at '${c}' is not a mobile test (fileType=${d.fileType}).`);let p;e&&(p=await Bn({platform:d.platform,steps:e}));let m={...d,...p?.stepsToSave!==void 0?{steps:p.stepsToSave}:{steps:d.steps},...n!==void 0?{labels:n}:{}};t&&(m.settings=t);let g=$s.stringify(m);for(let h of p?.moduleUpdates??[])ZO({content:h,schemaVersion:xo,momenticFiles:a,project:i});ln.writeFileSync(c,g,"utf-8"),Wn(c,i.config)}function oL(r,e,t){let n=ai.join(t.rootDir,r);if(!ln.existsSync(n))throw new Error(`Test not found at path '${r}' in project '${t.rootDir}'`);let o=ln.readFileSync(n,"utf-8").replace(/\r\n|\r/g,`
4586
- `),i=$s.parse(o),a=uc.extend({steps:Vs.record(Vs.string(),Vs.unknown()).array()}).parse(i),s=ai.basename(r,".test.yaml"),c,l;if(e.name&&e.name!==s){let p=`${gn(e.name)}.test.yaml`;if(c=ai.join(ai.dirname(r),p),l=ai.join(t.rootDir,c),ln.existsSync(l))throw new Error(`Test with name '${e.name}' already exists at path '${l}'`)}let u={...a,...e};if(delete u.name,u.fileType!==Xe.MOBILE_TEST)throw new Error(`File at '${n}' is not a mobile test (fileType=${u.fileType}).`);let d=$s.stringify(u);return ln.writeFileSync(n,d,"utf-8"),l&&l!==n?(ln.renameSync(n,l),Wn(l,t.config)):Wn(n,t.config),{newRelativeTestPath:c}}import{randomUUID as t4}from"crypto";import si from"fs";import qs from"path";var iL=new Set([".DS_Store","__MACOSX"]),aL={status:(r,e)=>{if(r.status===e.status)return r.status;if(r.status==="FAILED"||e.status==="FAILED")return"FAILED";if(r.status==="CANCELLED"||e.status==="CANCELLED")return"CANCELLED";if(r.status==="RETRYING"||e.status==="RETRYING")return"RETRYING";if(r.status==="RUNNING"||e.status==="RUNNING")return"RUNNING";if(r.status==="PENDING"||e.status==="PENDING")return"PENDING";throw new Error(`Invalid run status merge: ${r.status} and ${e.status}`)},startedAt:(r,e)=>r.startedAt<e.startedAt?r.startedAt:e.startedAt,updatedAt:(r,e)=>r.updatedAt>e.updatedAt?r.updatedAt:e.updatedAt,finishedAt:(r,e)=>!r.finishedAt||!e.finishedAt?new Date:r.finishedAt>e.finishedAt?r.finishedAt:e.finishedAt,gitCommitTimestamp:(r,e)=>{if(!(!r&&!e)){if(!r.gitCommitTimestamp||!e.gitCommitTimestamp||r.gitCommitTimestamp.getTime()!==e.gitCommitTimestamp.getTime())throw new Error(`Git commit timestamps must match to be merged: ${r.gitCommitTimestamp} and ${e.gitCommitTimestamp}`);return r.gitCommitTimestamp}},pipelineId:(r,e)=>r.pipelineId===e.pipelineId?r.pipelineId:!r.pipelineId&&e.pipelineId?e.pipelineId:!e.pipelineId&&r.pipelineId?r.pipelineId:r.startedAt<e.startedAt?e.pipelineId:r.pipelineId,labels:(r,e)=>{let t=new Set([...r.labels??[],...e.labels??[]]);return Array.from(t)}};function r4(r,e,t){if(aL[t]){let i=aL[t];return i(r,e)}let n=r[t],o=e[t];if(n!==o)throw new Error(`Metadata values for key "${t}" do not match: "${n}" vs "${o}"`);return n}var Vy=class extends Error{constructor(e,t){let n=`${e} contains invalid Momentic results: ${t}. Please ensure that the path points to a folder containing only valid results. If you passed \`--output-dir test-results/results-1\` to the \`run\` command, your results path for merging should be \`test-results\`.`;super(n),this.name="InvalidMomenticResultsPathError"}};function sL(r,e){try{let t=qs.join(e,"metadata.json");return ls.parse(JSON.parse(si.readFileSync(t,"utf-8")))}catch{throw new Vy(r,e)}}function lL(r,e,t){let n=t4(),o=r.child({runGroupId:n});si.rmSync(e,{recursive:!0,force:!0});let i=si.readdirSync(t).filter(c=>!iL.has(c)).map(c=>qs.join(t,c));if(i.length===0)throw new Error(`No run groups found in results path: ${t}`);si.mkdirSync(e,{recursive:!0});let a={...sL(t,i[0]),id:n};for(let c of i){let l=qs.join(c,"runs");if(!si.existsSync(l))continue;let u=sL(t,c);o.info({oldRunGroupId:u.id},"Merging run groups");for(let p in u){if(p==="id")continue;let m=p;a[m]=r4(a,u,m)}let d=si.readdirSync(l);for(let p of d){if(iL.has(p))continue;let m=qs.join(l,p),g=qs.join(e,"runs",p);si.cpSync(m,g,{recursive:!0})}}let s=qs.join(e,"metadata.json");si.writeFileSync(s,JSON.stringify(a,null,2))}import ZN from"adm-zip";import pb from"fs";import{z as VX}from"zod";var W="v1",$y="mobile-cli",pa="0.33.0";var n4=9e4,o4=3,i4=1500,a4=15e3,En=class extends Error{status;rawError;constructor(e,t,n,o={}){super(n,o),this.status=e,this.rawError=t}};async function s4(r){return r.text().then(e=>{try{return JSON.parse(e).error}catch{return e}})}var qy=class{baseUrl;logger;constructor(e){this.baseUrl=e.baseUrl,this.logger=e.logger}getHeaders(){let e={"Content-Type":"application/json"};return pa&&(e[Rd]=pa),$y&&(e[lw]=$y),e}async sendRequest(e,t){let{retries:n=o4,requestTimeoutMs:o=n4,initialRetryDelayMs:i=i4,maxRetryDelayMs:a=a4,onFailedRequest:s}=t,c=n,l=n,u,d={path:e,baseUrl:this.baseUrl,method:t.method};for(;c>0;)try{return c--,await this.sendSingleRequestHelper(e,t,o)}catch(p){u=p;try{s?.(u)}catch{}if(p instanceof En&&p.status>=400&&p.status<500)throw p;if(p instanceof Error&&p.name==="AbortError"&&(u=new Ho),c===0)throw u;let m=l-c,g=Math.min(i*Math.pow(2,m-1),a);await new Promise(h=>setTimeout(h,g))}throw this.logger.warn({...d,err:u},"Got fatal error response from Momentic server"),u}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,{once:!0});let c=Date.now(),l={...this.getHeaders(),...t.extraHeaders};try{let u=await fetch(`${this.baseUrl}${e}`,{method:t.method,body:t.body?JSON.stringify(t.body):void 0,headers:l,signal:i.signal});if(!u.ok){let m=await s4(u);throw new En(u.status,m,`Request to ${t.method} ${e} failed with status ${u.status}: ${m}`)}let d;if(u.status===204)d={};else if(t.responseType==="buffer"){let m=await u.arrayBuffer();d=Buffer.from(m)}else{let m=await u.text();try{d=JSON.parse(m)}catch{d=m}}this.logger&&t.logResponse===!0&&d&&this.logger.debug({result:d,status:u.status,durationMs:Date.now()-c,...o},"Got response from Momentic server");let p=t.responseHeadersObject;return p&&u.headers.forEach((m,g)=>{p[g.toLowerCase()]=m}),d}finally{clearTimeout(a),t.signal&&t.signal.removeEventListener("abort",s)}}},Vn=class extends qy{apiKey;mode;constructor(e){super(e),this.apiKey=e.apiKey,this.mode=e.mode}getHeaders(){return{...super.getHeaders(),Authorization:`Bearer ${this.apiKey}`,[sw]:this.mode??""}}};import{createAnthropic as WX}from"@ai-sdk/anthropic";var FL="vercel.ai.error",l4=Symbol.for(FL),cL,uL,lt=class UL extends(uL=Error,cL=l4,uL){constructor({name:e,message:t,cause:n}){super(t),this[cL]=!0,this.name=e,this.cause=n}static isInstance(e){return UL.hasMarker(e,FL)}static hasMarker(e,t){let n=Symbol.for(t);return e!=null&&typeof e=="object"&&n in e&&typeof e[n]=="boolean"&&e[n]===!0}},BL="AI_APICallError",zL=`vercel.ai.error.${BL}`,c4=Symbol.for(zL),dL,mL,ar=class extends(mL=lt,dL=c4,mL){constructor({message:r,url:e,requestBodyValues:t,statusCode:n,responseHeaders:o,responseBody:i,cause:a,isRetryable:s=n!=null&&(n===408||n===409||n===429||n>=500),data:c}){super({name:BL,message:r,cause:a}),this[dL]=!0,this.url=e,this.requestBodyValues=t,this.statusCode=n,this.responseHeaders=o,this.responseBody=i,this.isRetryable=s,this.data=c}static isInstance(r){return lt.hasMarker(r,zL)}},HL="AI_EmptyResponseBodyError",GL=`vercel.ai.error.${HL}`,u4=Symbol.for(GL),pL,gL,jL=class extends(gL=lt,pL=u4,gL){constructor({message:r="Empty response body"}={}){super({name:HL,message:r}),this[pL]=!0}static isInstance(r){return lt.hasMarker(r,GL)}};function WL(r){return r==null?"unknown error":typeof r=="string"?r:r instanceof Error?r.message:JSON.stringify(r)}var VL="AI_InvalidArgumentError",$L=`vercel.ai.error.${VL}`,d4=Symbol.for($L),hL,fL,Mp=class extends(fL=lt,hL=d4,fL){constructor({message:r,cause:e,argument:t}){super({name:VL,message:r,cause:e}),this[hL]=!0,this.argument=t}static isInstance(r){return lt.hasMarker(r,$L)}},qL="AI_InvalidPromptError",KL=`vercel.ai.error.${qL}`,m4=Symbol.for(KL),SL,yL,YL=class extends(yL=lt,SL=m4,yL){constructor({prompt:r,message:e,cause:t}){super({name:qL,message:`Invalid prompt: ${e}`,cause:t}),this[SL]=!0,this.prompt=r}static isInstance(r){return lt.hasMarker(r,KL)}},XL="AI_InvalidResponseDataError",JL=`vercel.ai.error.${XL}`,p4=Symbol.for(JL),bL,EL,Pp=class extends(EL=lt,bL=p4,EL){constructor({data:r,message:e=`Invalid response data: ${JSON.stringify(r)}.`}){super({name:XL,message:e}),this[bL]=!0,this.data=r}static isInstance(r){return lt.hasMarker(r,JL)}},ZL="AI_JSONParseError",QL=`vercel.ai.error.${ZL}`,g4=Symbol.for(QL),TL,vL,gu=class extends(vL=lt,TL=g4,vL){constructor({text:r,cause:e}){super({name:ZL,message:`JSON parsing failed: Text: ${r}.
4586
+ `),i=$s.parse(o),a=uc.extend({steps:Vs.record(Vs.string(),Vs.unknown()).array()}).parse(i),s=ai.basename(r,".test.yaml"),c,l;if(e.name&&e.name!==s){let p=`${gn(e.name)}.test.yaml`;if(c=ai.join(ai.dirname(r),p),l=ai.join(t.rootDir,c),ln.existsSync(l))throw new Error(`Test with name '${e.name}' already exists at path '${l}'`)}let u={...a,...e};if(delete u.name,u.fileType!==Xe.MOBILE_TEST)throw new Error(`File at '${n}' is not a mobile test (fileType=${u.fileType}).`);let d=$s.stringify(u);return ln.writeFileSync(n,d,"utf-8"),l&&l!==n?(ln.renameSync(n,l),Wn(l,t.config)):Wn(n,t.config),{newRelativeTestPath:c}}import{randomUUID as t4}from"crypto";import si from"fs";import qs from"path";var iL=new Set([".DS_Store","__MACOSX"]),aL={status:(r,e)=>{if(r.status===e.status)return r.status;if(r.status==="FAILED"||e.status==="FAILED")return"FAILED";if(r.status==="CANCELLED"||e.status==="CANCELLED")return"CANCELLED";if(r.status==="RETRYING"||e.status==="RETRYING")return"RETRYING";if(r.status==="RUNNING"||e.status==="RUNNING")return"RUNNING";if(r.status==="PENDING"||e.status==="PENDING")return"PENDING";throw new Error(`Invalid run status merge: ${r.status} and ${e.status}`)},startedAt:(r,e)=>r.startedAt<e.startedAt?r.startedAt:e.startedAt,updatedAt:(r,e)=>r.updatedAt>e.updatedAt?r.updatedAt:e.updatedAt,finishedAt:(r,e)=>!r.finishedAt||!e.finishedAt?new Date:r.finishedAt>e.finishedAt?r.finishedAt:e.finishedAt,gitCommitTimestamp:(r,e)=>{if(!(!r&&!e)){if(!r.gitCommitTimestamp||!e.gitCommitTimestamp||r.gitCommitTimestamp.getTime()!==e.gitCommitTimestamp.getTime())throw new Error(`Git commit timestamps must match to be merged: ${r.gitCommitTimestamp} and ${e.gitCommitTimestamp}`);return r.gitCommitTimestamp}},pipelineId:(r,e)=>r.pipelineId===e.pipelineId?r.pipelineId:!r.pipelineId&&e.pipelineId?e.pipelineId:!e.pipelineId&&r.pipelineId?r.pipelineId:r.startedAt<e.startedAt?e.pipelineId:r.pipelineId,labels:(r,e)=>{let t=new Set([...r.labels??[],...e.labels??[]]);return Array.from(t)}};function r4(r,e,t){if(aL[t]){let i=aL[t];return i(r,e)}let n=r[t],o=e[t];if(n!==o)throw new Error(`Metadata values for key "${t}" do not match: "${n}" vs "${o}"`);return n}var Vy=class extends Error{constructor(e,t){let n=`${e} contains invalid Momentic results: ${t}. Please ensure that the path points to a folder containing only valid results. If you passed \`--output-dir test-results/results-1\` to the \`run\` command, your results path for merging should be \`test-results\`.`;super(n),this.name="InvalidMomenticResultsPathError"}};function sL(r,e){try{let t=qs.join(e,"metadata.json");return ls.parse(JSON.parse(si.readFileSync(t,"utf-8")))}catch{throw new Vy(r,e)}}function lL(r,e,t){let n=t4(),o=r.child({runGroupId:n});si.rmSync(e,{recursive:!0,force:!0});let i=si.readdirSync(t).filter(c=>!iL.has(c)).map(c=>qs.join(t,c));if(i.length===0)throw new Error(`No run groups found in results path: ${t}`);si.mkdirSync(e,{recursive:!0});let a={...sL(t,i[0]),id:n};for(let c of i){let l=qs.join(c,"runs");if(!si.existsSync(l))continue;let u=sL(t,c);o.info({oldRunGroupId:u.id},"Merging run groups");for(let p in u){if(p==="id")continue;let m=p;a[m]=r4(a,u,m)}let d=si.readdirSync(l);for(let p of d){if(iL.has(p))continue;let m=qs.join(l,p),g=qs.join(e,"runs",p);si.cpSync(m,g,{recursive:!0})}}let s=qs.join(e,"metadata.json");si.writeFileSync(s,JSON.stringify(a,null,2))}import ZN from"adm-zip";import pb from"fs";import{z as VX}from"zod";var W="v1",$y="mobile-cli",pa="0.33.1";var n4=9e4,o4=3,i4=1500,a4=15e3,En=class extends Error{status;rawError;constructor(e,t,n,o={}){super(n,o),this.status=e,this.rawError=t}};async function s4(r){return r.text().then(e=>{try{return JSON.parse(e).error}catch{return e}})}var qy=class{baseUrl;logger;constructor(e){this.baseUrl=e.baseUrl,this.logger=e.logger}getHeaders(){let e={"Content-Type":"application/json"};return pa&&(e[Rd]=pa),$y&&(e[lw]=$y),e}async sendRequest(e,t){let{retries:n=o4,requestTimeoutMs:o=n4,initialRetryDelayMs:i=i4,maxRetryDelayMs:a=a4,onFailedRequest:s}=t,c=n,l=n,u,d={path:e,baseUrl:this.baseUrl,method:t.method};for(;c>0;)try{return c--,await this.sendSingleRequestHelper(e,t,o)}catch(p){u=p;try{s?.(u)}catch{}if(p instanceof En&&p.status>=400&&p.status<500)throw p;if(p instanceof Error&&p.name==="AbortError"&&(u=new Ho),c===0)throw u;let m=l-c,g=Math.min(i*Math.pow(2,m-1),a);await new Promise(h=>setTimeout(h,g))}throw this.logger.warn({...d,err:u},"Got fatal error response from Momentic server"),u}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,{once:!0});let c=Date.now(),l={...this.getHeaders(),...t.extraHeaders};try{let u=await fetch(`${this.baseUrl}${e}`,{method:t.method,body:t.body?JSON.stringify(t.body):void 0,headers:l,signal:i.signal});if(!u.ok){let m=await s4(u);throw new En(u.status,m,`Request to ${t.method} ${e} failed with status ${u.status}: ${m}`)}let d;if(u.status===204)d={};else if(t.responseType==="buffer"){let m=await u.arrayBuffer();d=Buffer.from(m)}else{let m=await u.text();try{d=JSON.parse(m)}catch{d=m}}this.logger&&t.logResponse===!0&&d&&this.logger.debug({result:d,status:u.status,durationMs:Date.now()-c,...o},"Got response from Momentic server");let p=t.responseHeadersObject;return p&&u.headers.forEach((m,g)=>{p[g.toLowerCase()]=m}),d}finally{clearTimeout(a),t.signal&&t.signal.removeEventListener("abort",s)}}},Vn=class extends qy{apiKey;mode;constructor(e){super(e),this.apiKey=e.apiKey,this.mode=e.mode}getHeaders(){return{...super.getHeaders(),Authorization:`Bearer ${this.apiKey}`,[sw]:this.mode??""}}};import{createAnthropic as WX}from"@ai-sdk/anthropic";var FL="vercel.ai.error",l4=Symbol.for(FL),cL,uL,lt=class UL extends(uL=Error,cL=l4,uL){constructor({name:e,message:t,cause:n}){super(t),this[cL]=!0,this.name=e,this.cause=n}static isInstance(e){return UL.hasMarker(e,FL)}static hasMarker(e,t){let n=Symbol.for(t);return e!=null&&typeof e=="object"&&n in e&&typeof e[n]=="boolean"&&e[n]===!0}},BL="AI_APICallError",zL=`vercel.ai.error.${BL}`,c4=Symbol.for(zL),dL,mL,ar=class extends(mL=lt,dL=c4,mL){constructor({message:r,url:e,requestBodyValues:t,statusCode:n,responseHeaders:o,responseBody:i,cause:a,isRetryable:s=n!=null&&(n===408||n===409||n===429||n>=500),data:c}){super({name:BL,message:r,cause:a}),this[dL]=!0,this.url=e,this.requestBodyValues=t,this.statusCode=n,this.responseHeaders=o,this.responseBody=i,this.isRetryable=s,this.data=c}static isInstance(r){return lt.hasMarker(r,zL)}},HL="AI_EmptyResponseBodyError",GL=`vercel.ai.error.${HL}`,u4=Symbol.for(GL),pL,gL,jL=class extends(gL=lt,pL=u4,gL){constructor({message:r="Empty response body"}={}){super({name:HL,message:r}),this[pL]=!0}static isInstance(r){return lt.hasMarker(r,GL)}};function WL(r){return r==null?"unknown error":typeof r=="string"?r:r instanceof Error?r.message:JSON.stringify(r)}var VL="AI_InvalidArgumentError",$L=`vercel.ai.error.${VL}`,d4=Symbol.for($L),hL,fL,Mp=class extends(fL=lt,hL=d4,fL){constructor({message:r,cause:e,argument:t}){super({name:VL,message:r,cause:e}),this[hL]=!0,this.argument=t}static isInstance(r){return lt.hasMarker(r,$L)}},qL="AI_InvalidPromptError",KL=`vercel.ai.error.${qL}`,m4=Symbol.for(KL),SL,yL,YL=class extends(yL=lt,SL=m4,yL){constructor({prompt:r,message:e,cause:t}){super({name:qL,message:`Invalid prompt: ${e}`,cause:t}),this[SL]=!0,this.prompt=r}static isInstance(r){return lt.hasMarker(r,KL)}},XL="AI_InvalidResponseDataError",JL=`vercel.ai.error.${XL}`,p4=Symbol.for(JL),bL,EL,Pp=class extends(EL=lt,bL=p4,EL){constructor({data:r,message:e=`Invalid response data: ${JSON.stringify(r)}.`}){super({name:XL,message:e}),this[bL]=!0,this.data=r}static isInstance(r){return lt.hasMarker(r,JL)}},ZL="AI_JSONParseError",QL=`vercel.ai.error.${ZL}`,g4=Symbol.for(QL),TL,vL,gu=class extends(vL=lt,TL=g4,vL){constructor({text:r,cause:e}){super({name:ZL,message:`JSON parsing failed: Text: ${r}.
4587
4587
  Error message: ${WL(e)}`,cause:e}),this[TL]=!0,this.text=r}static isInstance(r){return lt.hasMarker(r,QL)}},eN="AI_LoadAPIKeyError",tN=`vercel.ai.error.${eN}`,h4=Symbol.for(tN),AL,wL,hu=class extends(wL=lt,AL=h4,wL){constructor({message:r}){super({name:eN,message:r}),this[AL]=!0}static isInstance(r){return lt.hasMarker(r,tN)}},rN="AI_LoadSettingError",nN=`vercel.ai.error.${rN}`,f4=Symbol.for(nN),RL,CL,M3e=class extends(CL=lt,RL=f4,CL){constructor({message:r}){super({name:rN,message:r}),this[RL]=!0}static isInstance(r){return lt.hasMarker(r,nN)}},oN="AI_NoContentGeneratedError",iN=`vercel.ai.error.${oN}`,S4=Symbol.for(iN),xL,_L,P3e=class extends(_L=lt,xL=S4,_L){constructor({message:r="No content generated."}={}){super({name:oN,message:r}),this[xL]=!0}static isInstance(r){return lt.hasMarker(r,iN)}},aN="AI_NoSuchModelError",sN=`vercel.ai.error.${aN}`,y4=Symbol.for(sN),ML,PL,I3e=class extends(PL=lt,ML=y4,PL){constructor({errorName:r=aN,modelId:e,modelType:t,message:n=`No such ${t}: ${e}`}){super({name:r,message:n}),this[ML]=!0,this.modelId=e,this.modelType=t}static isInstance(r){return lt.hasMarker(r,sN)}},lN="AI_TooManyEmbeddingValuesForCallError",cN=`vercel.ai.error.${lN}`,b4=Symbol.for(cN),IL,OL,uN=class extends(OL=lt,IL=b4,OL){constructor(r){super({name:lN,message:`Too many values for a single embedding call. The ${r.provider} model "${r.modelId}" can only embed up to ${r.maxEmbeddingsPerCall} values per call, but ${r.values.length} values were provided.`}),this[IL]=!0,this.provider=r.provider,this.modelId=r.modelId,this.maxEmbeddingsPerCall=r.maxEmbeddingsPerCall,this.values=r.values}static isInstance(r){return lt.hasMarker(r,cN)}},dN="AI_TypeValidationError",mN=`vercel.ai.error.${dN}`,E4=Symbol.for(mN),LL,NL,li=class Ky extends(NL=lt,LL=E4,NL){constructor({value:e,cause:t}){super({name:dN,message:`Type validation failed: Value: ${JSON.stringify(e)}.
4588
4588
  Error message: ${WL(t)}`,cause:t}),this[LL]=!0,this.value=e}static isInstance(e){return lt.hasMarker(e,mN)}static wrap({value:e,cause:t}){return Ky.isInstance(t)&&t.value===e?t:new Ky({value:e,cause:t})}},pN="AI_UnsupportedFunctionalityError",gN=`vercel.ai.error.${pN}`,T4=Symbol.for(gN),DL,kL,Mr=class extends(kL=lt,DL=T4,kL){constructor({functionality:r,message:e=`'${r}' functionality not supported.`}){super({name:pN,message:e}),this[DL]=!0,this.functionality=r}static isInstance(r){return lt.hasMarker(r,gN)}};var Ip=class extends Error{constructor(e,t){super(e),this.name="ParseError",this.type=t.type,this.field=t.field,this.value=t.value,this.line=t.line}};function Yy(r){}function hN(r){if(typeof r=="function")throw new TypeError("`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?");let{onEvent:e=Yy,onError:t=Yy,onRetry:n=Yy,onComment:o}=r,i="",a=!0,s,c="",l="";function u(h){let f=a?h.replace(/^\xEF\xBB\xBF/,""):h,[y,E]=v4(`${i}${f}`);for(let b of y)d(b);i=E,a=!1}function d(h){if(h===""){m();return}if(h.startsWith(":")){o&&o(h.slice(h.startsWith(": ")?2:1));return}let f=h.indexOf(":");if(f!==-1){let y=h.slice(0,f),E=h[f+1]===" "?2:1,b=h.slice(f+E);p(y,b,h);return}p(h,"",h)}function p(h,f,y){switch(h){case"event":l=f;break;case"data":c=`${c}${f}
4589
4589
  `;break;case"id":s=f.includes("\0")?void 0:f;break;case"retry":/^\d+$/.test(f)?n(parseInt(f,10)):t(new Ip(`Invalid \`retry\` value: "${f}"`,{type:"invalid-retry",value:f,line:y}));break;default:t(new Ip(`Unknown field "${h.length>20?`${h.slice(0,20)}\u2026`:h}"`,{type:"unknown-field",field:h,value:f,line:y}));break}}function m(){c.length>0&&e({id:s,event:l||void 0,data:c.endsWith(`
@@ -4604,7 +4604,7 @@ ${a}
4604
4604
  `;break}case"tool":throw new Mr({functionality:"tool messages"});default:{let a=o;throw new Error(`Unsupported role: ${a}`)}}return n+=`${t}:
4605
4605
  `,{prompt:n,stopSequences:[`
4606
4606
  ${e}:`]}}function DN({id:r,model:e,created:t}){return{id:r??void 0,modelId:e??void 0,timestamp:t!=null?new Date(t*1e3):void 0}}function kN(r){switch(r){case"stop":return"stop";case"length":return"length";case"content_filter":return"content-filter";case"function_call":case"tool_calls":return"tool-calls";default:return"unknown"}}var H5=ot(()=>me(be.object({id:be.string().nullish(),created:be.number().nullish(),model:be.string().nullish(),choices:be.array(be.object({text:be.string(),finish_reason:be.string(),logprobs:be.object({tokens:be.array(be.string()),token_logprobs:be.array(be.number()),top_logprobs:be.array(be.record(be.string(),be.number())).nullish()}).nullish()})),usage:be.object({prompt_tokens:be.number(),completion_tokens:be.number(),total_tokens:be.number()}).nullish()}))),G5=ot(()=>me(be.union([be.object({id:be.string().nullish(),created:be.number().nullish(),model:be.string().nullish(),choices:be.array(be.object({text:be.string(),finish_reason:be.string().nullish(),index:be.number(),logprobs:be.object({tokens:be.array(be.string()),token_logprobs:be.array(be.number()),top_logprobs:be.array(be.record(be.string(),be.number())).nullish()}).nullish()})),usage:be.object({prompt_tokens:be.number(),completion_tokens:be.number(),total_tokens:be.number()}).nullish()}),lb]))),FN=ot(()=>me(qn.object({echo:qn.boolean().optional(),logitBias:qn.record(qn.string(),qn.number()).optional(),suffix:qn.string().optional(),user:qn.string().optional(),logprobs:qn.union([qn.boolean(),qn.number()]).optional()}))),j5=class{constructor(r,e){this.specificationVersion="v2",this.supportedUrls={},this.modelId=r,this.config=e}get providerOptionsName(){return this.config.provider.split(".")[0].trim()}get provider(){return this.config.provider}async getArgs({prompt:r,maxOutputTokens:e,temperature:t,topP:n,topK:o,frequencyPenalty:i,presencePenalty:a,stopSequences:s,responseFormat:c,tools:l,toolChoice:u,seed:d,providerOptions:p}){let m=[],g={...await Tr({provider:"openai",providerOptions:p,schema:FN}),...await Tr({provider:this.providerOptionsName,providerOptions:p,schema:FN})};o!=null&&m.push({type:"unsupported-setting",setting:"topK"}),l?.length&&m.push({type:"unsupported-setting",setting:"tools"}),u!=null&&m.push({type:"unsupported-setting",setting:"toolChoice"}),c!=null&&c.type!=="text"&&m.push({type:"unsupported-setting",setting:"responseFormat",details:"JSON response format is not supported."});let{prompt:h,stopSequences:f}=z5({prompt:r}),y=[...f??[],...s??[]];return{args:{model:this.modelId,echo:g.echo,logit_bias:g.logitBias,logprobs:g?.logprobs===!0?0:g?.logprobs===!1?void 0:g?.logprobs,suffix:g.suffix,user:g.user,max_tokens:e,temperature:t,top_p:n,frequency_penalty:i,presence_penalty:a,seed:d,prompt:h,stop:y.length>0?y:void 0},warnings:m}}async doGenerate(r){var e,t,n;let{args:o,warnings:i}=await this.getArgs(r),{responseHeaders:a,value:s,rawValue:c}=await vr({url:this.config.url({path:"/completions",modelId:this.modelId}),headers:Qt(this.config.headers(),r.headers),body:o,failedResponseHandler:Kn,successfulResponseHandler:un(H5),abortSignal:r.abortSignal,fetch:this.config.fetch}),l=s.choices[0],u={openai:{}};return l.logprobs!=null&&(u.openai.logprobs=l.logprobs),{content:[{type:"text",text:l.text}],usage:{inputTokens:(e=s.usage)==null?void 0:e.prompt_tokens,outputTokens:(t=s.usage)==null?void 0:t.completion_tokens,totalTokens:(n=s.usage)==null?void 0:n.total_tokens},finishReason:kN(l.finish_reason),request:{body:o},response:{...DN(s),headers:a,body:c},providerMetadata:u,warnings:i}}async doStream(r){let{args:e,warnings:t}=await this.getArgs(r),n={...e,stream:!0,stream_options:{include_usage:!0}},{responseHeaders:o,value:i}=await vr({url:this.config.url({path:"/completions",modelId:this.modelId}),headers:Qt(this.config.headers(),r.headers),body:n,failedResponseHandler:Kn,successfulResponseHandler:Ks(G5),abortSignal:r.abortSignal,fetch:this.config.fetch}),a="unknown",s={openai:{}},c={inputTokens:void 0,outputTokens:void 0,totalTokens:void 0},l=!0;return{stream:i.pipeThrough(new TransformStream({start(u){u.enqueue({type:"stream-start",warnings:t})},transform(u,d){if(r.includeRawChunks&&d.enqueue({type:"raw",rawValue:u.rawValue}),!u.success){a="error",d.enqueue({type:"error",error:u.error});return}let p=u.value;if("error"in p){a="error",d.enqueue({type:"error",error:p.error});return}l&&(l=!1,d.enqueue({type:"response-metadata",...DN(p)}),d.enqueue({type:"text-start",id:"0"})),p.usage!=null&&(c.inputTokens=p.usage.prompt_tokens,c.outputTokens=p.usage.completion_tokens,c.totalTokens=p.usage.total_tokens);let m=p.choices[0];m?.finish_reason!=null&&(a=kN(m.finish_reason)),m?.logprobs!=null&&(s.openai.logprobs=m.logprobs),m?.text!=null&&m.text.length>0&&d.enqueue({type:"text-delta",id:"0",delta:m.text})},flush(u){l||u.enqueue({type:"text-end",id:"0"}),u.enqueue({type:"finish",finishReason:a,providerMetadata:s,usage:c})}})),request:{body:n},response:{headers:o}}}},W5=ot(()=>me(ib.object({dimensions:ib.number().optional(),user:ib.string().optional()}))),V5=ot(()=>me(ga.object({data:ga.array(ga.object({embedding:ga.array(ga.number())})),usage:ga.object({prompt_tokens:ga.number()}).nullish()}))),$5=class{constructor(r,e){this.specificationVersion="v2",this.maxEmbeddingsPerCall=2048,this.supportsParallelCalls=!0,this.modelId=r,this.config=e}get provider(){return this.config.provider}async doEmbed({values:r,headers:e,abortSignal:t,providerOptions:n}){var o;if(r.length>this.maxEmbeddingsPerCall)throw new uN({provider:this.provider,modelId:this.modelId,maxEmbeddingsPerCall:this.maxEmbeddingsPerCall,values:r});let i=(o=await Tr({provider:"openai",providerOptions:n,schema:W5}))!=null?o:{},{responseHeaders:a,value:s,rawValue:c}=await vr({url:this.config.url({path:"/embeddings",modelId:this.modelId}),headers:Qt(this.config.headers(),e),body:{model:this.modelId,input:r,encoding_format:"float",dimensions:i.dimensions,user:i.user},failedResponseHandler:Kn,successfulResponseHandler:un(V5),abortSignal:t,fetch:this.config.fetch});return{embeddings:s.data.map(l=>l.embedding),usage:s.usage?{tokens:s.usage.prompt_tokens}:void 0,response:{headers:a,body:c}}}},q5=ot(()=>me(er.object({created:er.number().nullish(),data:er.array(er.object({b64_json:er.string(),revised_prompt:er.string().nullish()})),background:er.string().nullish(),output_format:er.string().nullish(),size:er.string().nullish(),quality:er.string().nullish(),usage:er.object({input_tokens:er.number().nullish(),output_tokens:er.number().nullish(),total_tokens:er.number().nullish(),input_tokens_details:er.object({image_tokens:er.number().nullish(),text_tokens:er.number().nullish()}).nullish()}).nullish()}))),K5={"dall-e-3":1,"dall-e-2":10,"gpt-image-1":10,"gpt-image-1-mini":10,"gpt-image-1.5":10},Y5=new Set(["gpt-image-1","gpt-image-1-mini","gpt-image-1.5"]),X5=class{constructor(r,e){this.modelId=r,this.config=e,this.specificationVersion="v2"}get maxImagesPerCall(){var r;return(r=K5[this.modelId])!=null?r:1}get provider(){return this.config.provider}async doGenerate({prompt:r,n:e,size:t,aspectRatio:n,seed:o,providerOptions:i,headers:a,abortSignal:s}){var c,l,u,d;let p=[];n!=null&&p.push({type:"unsupported-setting",setting:"aspectRatio",details:"This model does not support aspect ratio. Use `size` instead."}),o!=null&&p.push({type:"unsupported-setting",setting:"seed"});let m=(u=(l=(c=this.config._internal)==null?void 0:c.currentDate)==null?void 0:l.call(c))!=null?u:new Date,{value:g,responseHeaders:h}=await vr({url:this.config.url({path:"/images/generations",modelId:this.modelId}),headers:Qt(this.config.headers(),a),body:{model:this.modelId,prompt:r,n:e,size:t,...(d=i.openai)!=null?d:{},...Y5.has(this.modelId)?{}:{response_format:"b64_json"}},failedResponseHandler:Kn,successfulResponseHandler:un(q5),abortSignal:s,fetch:this.config.fetch});return{images:g.data.map(f=>f.b64_json),warnings:p,response:{timestamp:m,modelId:this.modelId,headers:h},providerMetadata:{openai:{images:g.data.map(f=>({...f.revised_prompt?{revisedPrompt:f.revised_prompt}:{},...g.created!=null?{created:g.created}:{},...g.size!=null?{size:g.size}:{},...g.quality!=null?{quality:g.quality}:{},...g.background!=null?{background:g.background}:{},...g.output_format!=null?{outputFormat:g.output_format}:{}}))}}}}},J5=Ct(()=>me(qt.object({code:qt.string().nullish(),containerId:qt.string()}))),Z5=Ct(()=>me(qt.object({outputs:qt.array(qt.discriminatedUnion("type",[qt.object({type:qt.literal("logs"),logs:qt.string()}),qt.object({type:qt.literal("image"),url:qt.string()})])).nullish()}))),Q5=Ct(()=>me(qt.object({container:qt.union([qt.string(),qt.object({fileIds:qt.array(qt.string()).optional()})]).optional()}))),eX=cn({id:"openai.code_interpreter",name:"code_interpreter",inputSchema:J5,outputSchema:Z5}),tX=(r={})=>eX(r),WN=ze.object({key:ze.string(),type:ze.enum(["eq","ne","gt","gte","lt","lte","in","nin"]),value:ze.union([ze.string(),ze.number(),ze.boolean(),ze.array(ze.string())])}),VN=ze.object({type:ze.enum(["and","or"]),filters:ze.array(ze.union([WN,ze.lazy(()=>VN)]))}),rX=Ct(()=>me(ze.object({vectorStoreIds:ze.array(ze.string()),maxNumResults:ze.number().optional(),ranking:ze.object({ranker:ze.string().optional(),scoreThreshold:ze.number().optional()}).optional(),filters:ze.union([WN,VN]).optional()}))),nX=Ct(()=>me(ze.object({queries:ze.array(ze.string()),results:ze.array(ze.object({attributes:ze.record(ze.string(),ze.unknown()),fileId:ze.string(),filename:ze.string(),score:ze.number(),text:ze.string()})).nullable()}))),oX=cn({id:"openai.file_search",name:"file_search",inputSchema:ze.object({}),outputSchema:nX}),iX=Ct(()=>me(sr.object({background:sr.enum(["auto","opaque","transparent"]).optional(),inputFidelity:sr.enum(["low","high"]).optional(),inputImageMask:sr.object({fileId:sr.string().optional(),imageUrl:sr.string().optional()}).optional(),model:sr.string().optional(),moderation:sr.enum(["auto"]).optional(),outputCompression:sr.number().int().min(0).max(100).optional(),outputFormat:sr.enum(["png","jpeg","webp"]).optional(),partialImages:sr.number().int().min(0).max(3).optional(),quality:sr.enum(["auto","low","medium","high"]).optional(),size:sr.enum(["1024x1024","1024x1536","1536x1024","auto"]).optional()}).strict())),aX=Ct(()=>me(sr.object({}))),sX=Ct(()=>me(sr.object({result:sr.string()}))),lX=cn({id:"openai.image_generation",name:"image_generation",inputSchema:aX,outputSchema:sX}),cX=(r={})=>lX(r),$N=Ct(()=>me(Ur.object({action:Ur.object({type:Ur.literal("exec"),command:Ur.array(Ur.string()),timeoutMs:Ur.number().optional(),user:Ur.string().optional(),workingDirectory:Ur.string().optional(),env:Ur.record(Ur.string(),Ur.string()).optional()})}))),qN=Ct(()=>me(Ur.object({output:Ur.string()}))),uX=cn({id:"openai.local_shell",name:"local_shell",inputSchema:$N,outputSchema:qN}),dX=Ct(()=>me(Ve.object({externalWebAccess:Ve.boolean().optional(),filters:Ve.object({allowedDomains:Ve.array(Ve.string()).optional()}).optional(),searchContextSize:Ve.enum(["low","medium","high"]).optional(),userLocation:Ve.object({type:Ve.literal("approximate"),country:Ve.string().optional(),city:Ve.string().optional(),region:Ve.string().optional(),timezone:Ve.string().optional()}).optional()}))),mX=Ct(()=>me(Ve.object({}))),pX=Ct(()=>me(Ve.object({action:Ve.discriminatedUnion("type",[Ve.object({type:Ve.literal("search"),query:Ve.string().optional()}),Ve.object({type:Ve.literal("openPage"),url:Ve.string().nullish()}),Ve.object({type:Ve.literal("findInPage"),url:Ve.string().nullish(),pattern:Ve.string().nullish()})]),sources:Ve.array(Ve.discriminatedUnion("type",[Ve.object({type:Ve.literal("url"),url:Ve.string()}),Ve.object({type:Ve.literal("api"),name:Ve.string()})])).optional()}))),gX=cn({id:"openai.web_search",name:"web_search",inputSchema:mX,outputSchema:pX}),hX=(r={})=>gX(r),fX=Ct(()=>me(Lt.object({searchContextSize:Lt.enum(["low","medium","high"]).optional(),userLocation:Lt.object({type:Lt.literal("approximate"),country:Lt.string().optional(),city:Lt.string().optional(),region:Lt.string().optional(),timezone:Lt.string().optional()}).optional()}))),SX=Ct(()=>me(Lt.object({}))),yX=Ct(()=>me(Lt.object({action:Lt.discriminatedUnion("type",[Lt.object({type:Lt.literal("search"),query:Lt.string().optional()}),Lt.object({type:Lt.literal("openPage"),url:Lt.string().nullish()}),Lt.object({type:Lt.literal("findInPage"),url:Lt.string().nullish(),pattern:Lt.string().nullish()})])}))),bX=cn({id:"openai.web_search_preview",name:"web_search_preview",inputSchema:SX,outputSchema:yX}),EX={codeInterpreter:tX,fileSearch:oX,imageGeneration:cX,localShell:uX,webSearchPreview:bX,webSearch:hX};function UN(r,e){return e?e.some(t=>r.startsWith(t)):!1}async function TX({prompt:r,systemMessageMode:e,fileIdPrefixes:t,store:n,hasLocalShellTool:o=!1}){var i,a,s,c;let l=[],u=[];for(let{role:d,content:p}of r)switch(d){case"system":{switch(e){case"system":{l.push({role:"system",content:p});break}case"developer":{l.push({role:"developer",content:p});break}case"remove":{u.push({type:"other",message:"system messages are removed for this model"});break}default:{let m=e;throw new Error(`Unsupported system message mode: ${m}`)}}break}case"user":{l.push({role:"user",content:p.map((m,g)=>{var h,f,y;switch(m.type){case"text":return{type:"input_text",text:m.text};case"file":if(m.mediaType.startsWith("image/")){let E=m.mediaType==="image/*"?"image/jpeg":m.mediaType;return{type:"input_image",...m.data instanceof URL?{image_url:m.data.toString()}:typeof m.data=="string"&&UN(m.data,t)?{file_id:m.data}:{image_url:`data:${E};base64,${ci(m.data)}`},detail:(f=(h=m.providerOptions)==null?void 0:h.openai)==null?void 0:f.imageDetail}}else{if(m.mediaType==="application/pdf")return m.data instanceof URL?{type:"input_file",file_url:m.data.toString()}:{type:"input_file",...typeof m.data=="string"&&UN(m.data,t)?{file_id:m.data}:{filename:(y=m.filename)!=null?y:`part-${g}.pdf`,file_data:`data:application/pdf;base64,${ci(m.data)}`}};throw new Mr({functionality:`file part media type ${m.mediaType}`})}}})});break}case"assistant":{let m={},g={};for(let h of p)switch(h.type){case"text":{let f=(a=(i=h.providerOptions)==null?void 0:i.openai)==null?void 0:a.itemId;if(n&&f!=null){l.push({type:"item_reference",id:f});break}l.push({role:"assistant",content:[{type:"output_text",text:h.text}],id:f});break}case"tool-call":{if(g[h.toolCallId]=h,h.providerExecuted)break;let f=(c=(s=h.providerOptions)==null?void 0:s.openai)==null?void 0:c.itemId;if(n&&f!=null){l.push({type:"item_reference",id:f});break}if(o&&h.toolName==="local_shell"){let y=await $n({value:h.input,schema:$N});l.push({type:"local_shell_call",call_id:h.toolCallId,id:f,action:{type:"exec",command:y.action.command,timeout_ms:y.action.timeoutMs,user:y.action.user,working_directory:y.action.workingDirectory,env:y.action.env}});break}l.push({type:"function_call",call_id:h.toolCallId,name:h.toolName,arguments:JSON.stringify(h.input),id:f});break}case"tool-result":{n?l.push({type:"item_reference",id:h.toolCallId}):u.push({type:"other",message:`Results for OpenAI tool ${h.toolName} are not sent to the API when store is false`});break}case"reasoning":{let f=await Tr({provider:"openai",providerOptions:h.providerOptions,schema:vX}),y=f?.itemId;if(y!=null){let E=m[y];if(n)E===void 0&&(l.push({type:"item_reference",id:y}),m[y]={type:"reasoning",id:y,summary:[]});else{let b=[];h.text.length>0?b.push({type:"summary_text",text:h.text}):E!==void 0&&u.push({type:"other",message:`Cannot append empty reasoning part to existing reasoning sequence. Skipping reasoning part: ${JSON.stringify(h)}.`}),E===void 0?(m[y]={type:"reasoning",id:y,encrypted_content:f?.reasoningEncryptedContent,summary:b},l.push(m[y])):(E.summary.push(...b),f?.reasoningEncryptedContent!=null&&(E.encrypted_content=f.reasoningEncryptedContent))}}else u.push({type:"other",message:`Non-OpenAI reasoning parts are not supported. Skipping reasoning part: ${JSON.stringify(h)}.`});break}}break}case"tool":{for(let m of p){let g=m.output;if(o&&m.toolName==="local_shell"&&g.type==="json"){let f=await $n({value:g.value,schema:qN});l.push({type:"local_shell_call_output",call_id:m.toolCallId,output:f.output});break}let h;switch(g.type){case"text":case"error-text":h=g.value;break;case"json":case"error-json":h=JSON.stringify(g.value);break;case"content":h=g.value.map(f=>{switch(f.type){case"text":return{type:"input_text",text:f.text};case"media":return f.mediaType.startsWith("image/")?{type:"input_image",image_url:`data:${f.mediaType};base64,${f.data}`}:{type:"input_file",filename:"data",file_data:`data:${f.mediaType};base64,${f.data}`}}});break}l.push({type:"function_call_output",call_id:m.toolCallId,output:h})}break}default:{let m=d;throw new Error(`Unsupported role: ${m}`)}}return{input:l,warnings:u}}var vX=ab.object({itemId:ab.string().nullish(),reasoningEncryptedContent:ab.string().nullish()});function BN({finishReason:r,hasFunctionCall:e}){switch(r){case void 0:case null:return e?"tool-calls":"stop";case"max_output_tokens":return"length";case"content_filter":return"content-filter";default:return e?"tool-calls":"unknown"}}var AX=ot(()=>me(S.union([S.object({type:S.literal("response.output_text.delta"),item_id:S.string(),delta:S.string(),logprobs:S.array(S.object({token:S.string(),logprob:S.number(),top_logprobs:S.array(S.object({token:S.string(),logprob:S.number()}))})).nullish()}),S.object({type:S.enum(["response.completed","response.incomplete"]),response:S.object({incomplete_details:S.object({reason:S.string()}).nullish(),usage:S.object({input_tokens:S.number(),input_tokens_details:S.object({cached_tokens:S.number().nullish()}).nullish(),output_tokens:S.number(),output_tokens_details:S.object({reasoning_tokens:S.number().nullish()}).nullish()}),service_tier:S.string().nullish()})}),S.object({type:S.literal("response.created"),response:S.object({id:S.string(),created_at:S.number(),model:S.string(),service_tier:S.string().nullish()})}),S.object({type:S.literal("response.output_item.added"),output_index:S.number(),item:S.discriminatedUnion("type",[S.object({type:S.literal("message"),id:S.string()}),S.object({type:S.literal("reasoning"),id:S.string(),encrypted_content:S.string().nullish()}),S.object({type:S.literal("function_call"),id:S.string(),call_id:S.string(),name:S.string(),arguments:S.string()}),S.object({type:S.literal("web_search_call"),id:S.string(),status:S.string()}),S.object({type:S.literal("computer_call"),id:S.string(),status:S.string()}),S.object({type:S.literal("file_search_call"),id:S.string()}),S.object({type:S.literal("image_generation_call"),id:S.string()}),S.object({type:S.literal("code_interpreter_call"),id:S.string(),container_id:S.string(),code:S.string().nullable(),outputs:S.array(S.discriminatedUnion("type",[S.object({type:S.literal("logs"),logs:S.string()}),S.object({type:S.literal("image"),url:S.string()})])).nullable(),status:S.string()})])}),S.object({type:S.literal("response.output_item.done"),output_index:S.number(),item:S.discriminatedUnion("type",[S.object({type:S.literal("message"),id:S.string()}),S.object({type:S.literal("reasoning"),id:S.string(),encrypted_content:S.string().nullish()}),S.object({type:S.literal("function_call"),id:S.string(),call_id:S.string(),name:S.string(),arguments:S.string(),status:S.literal("completed")}),S.object({type:S.literal("code_interpreter_call"),id:S.string(),code:S.string().nullable(),container_id:S.string(),outputs:S.array(S.discriminatedUnion("type",[S.object({type:S.literal("logs"),logs:S.string()}),S.object({type:S.literal("image"),url:S.string()})])).nullable()}),S.object({type:S.literal("image_generation_call"),id:S.string(),result:S.string()}),S.object({type:S.literal("web_search_call"),id:S.string(),status:S.string(),action:S.discriminatedUnion("type",[S.object({type:S.literal("search"),query:S.string().nullish(),sources:S.array(S.discriminatedUnion("type",[S.object({type:S.literal("url"),url:S.string()}),S.object({type:S.literal("api"),name:S.string()})])).nullish()}),S.object({type:S.literal("open_page"),url:S.string().nullish()}),S.object({type:S.literal("find_in_page"),url:S.string().nullish(),pattern:S.string().nullish()})])}),S.object({type:S.literal("file_search_call"),id:S.string(),queries:S.array(S.string()),results:S.array(S.object({attributes:S.record(S.string(),S.unknown()),file_id:S.string(),filename:S.string(),score:S.number(),text:S.string()})).nullish()}),S.object({type:S.literal("local_shell_call"),id:S.string(),call_id:S.string(),action:S.object({type:S.literal("exec"),command:S.array(S.string()),timeout_ms:S.number().optional(),user:S.string().optional(),working_directory:S.string().optional(),env:S.record(S.string(),S.string()).optional()})}),S.object({type:S.literal("computer_call"),id:S.string(),status:S.literal("completed")})])}),S.object({type:S.literal("response.function_call_arguments.delta"),item_id:S.string(),output_index:S.number(),delta:S.string()}),S.object({type:S.literal("response.image_generation_call.partial_image"),item_id:S.string(),output_index:S.number(),partial_image_b64:S.string()}),S.object({type:S.literal("response.code_interpreter_call_code.delta"),item_id:S.string(),output_index:S.number(),delta:S.string()}),S.object({type:S.literal("response.code_interpreter_call_code.done"),item_id:S.string(),output_index:S.number(),code:S.string()}),S.object({type:S.literal("response.output_text.annotation.added"),annotation:S.discriminatedUnion("type",[S.object({type:S.literal("url_citation"),start_index:S.number(),end_index:S.number(),url:S.string(),title:S.string()}),S.object({type:S.literal("file_citation"),file_id:S.string(),filename:S.string().nullish(),index:S.number().nullish(),start_index:S.number().nullish(),end_index:S.number().nullish(),quote:S.string().nullish()})])}),S.object({type:S.literal("response.reasoning_summary_part.added"),item_id:S.string(),summary_index:S.number()}),S.object({type:S.literal("response.reasoning_summary_text.delta"),item_id:S.string(),summary_index:S.number(),delta:S.string()}),S.object({type:S.literal("response.reasoning_summary_part.done"),item_id:S.string(),summary_index:S.number()}),S.object({type:S.literal("error"),sequence_number:S.number(),error:S.object({type:S.string(),code:S.string(),message:S.string(),param:S.string().nullish()})}),S.object({type:S.string()}).loose().transform(r=>({type:"unknown_chunk",message:r.type}))]))),wX=ot(()=>me(S.object({id:S.string().optional(),created_at:S.number().optional(),error:S.object({message:S.string(),type:S.string(),param:S.string().nullish(),code:S.string()}).nullish(),model:S.string().optional(),output:S.array(S.discriminatedUnion("type",[S.object({type:S.literal("message"),role:S.literal("assistant"),id:S.string(),content:S.array(S.object({type:S.literal("output_text"),text:S.string(),logprobs:S.array(S.object({token:S.string(),logprob:S.number(),top_logprobs:S.array(S.object({token:S.string(),logprob:S.number()}))})).nullish(),annotations:S.array(S.discriminatedUnion("type",[S.object({type:S.literal("url_citation"),start_index:S.number(),end_index:S.number(),url:S.string(),title:S.string()}),S.object({type:S.literal("file_citation"),file_id:S.string(),filename:S.string().nullish(),index:S.number().nullish(),start_index:S.number().nullish(),end_index:S.number().nullish(),quote:S.string().nullish()}),S.object({type:S.literal("container_file_citation"),container_id:S.string(),file_id:S.string(),filename:S.string().nullish(),start_index:S.number().nullish(),end_index:S.number().nullish(),index:S.number().nullish()}),S.object({type:S.literal("file_path"),file_id:S.string(),index:S.number().nullish()})]))}))}),S.object({type:S.literal("web_search_call"),id:S.string(),status:S.string(),action:S.discriminatedUnion("type",[S.object({type:S.literal("search"),query:S.string().nullish(),sources:S.array(S.discriminatedUnion("type",[S.object({type:S.literal("url"),url:S.string()}),S.object({type:S.literal("api"),name:S.string()})])).nullish()}),S.object({type:S.literal("open_page"),url:S.string().nullish()}),S.object({type:S.literal("find_in_page"),url:S.string().nullish(),pattern:S.string().nullish()})])}),S.object({type:S.literal("file_search_call"),id:S.string(),queries:S.array(S.string()),results:S.array(S.object({attributes:S.record(S.string(),S.union([S.string(),S.number(),S.boolean()])),file_id:S.string(),filename:S.string(),score:S.number(),text:S.string()})).nullish()}),S.object({type:S.literal("code_interpreter_call"),id:S.string(),code:S.string().nullable(),container_id:S.string(),outputs:S.array(S.discriminatedUnion("type",[S.object({type:S.literal("logs"),logs:S.string()}),S.object({type:S.literal("image"),url:S.string()})])).nullable()}),S.object({type:S.literal("image_generation_call"),id:S.string(),result:S.string()}),S.object({type:S.literal("local_shell_call"),id:S.string(),call_id:S.string(),action:S.object({type:S.literal("exec"),command:S.array(S.string()),timeout_ms:S.number().optional(),user:S.string().optional(),working_directory:S.string().optional(),env:S.record(S.string(),S.string()).optional()})}),S.object({type:S.literal("function_call"),call_id:S.string(),name:S.string(),arguments:S.string(),id:S.string()}),S.object({type:S.literal("computer_call"),id:S.string(),status:S.string().optional()}),S.object({type:S.literal("reasoning"),id:S.string(),encrypted_content:S.string().nullish(),summary:S.array(S.object({type:S.literal("summary_text"),text:S.string()}))})])).optional(),service_tier:S.string().nullish(),incomplete_details:S.object({reason:S.string()}).nullish(),usage:S.object({input_tokens:S.number(),input_tokens_details:S.object({cached_tokens:S.number().nullish()}).nullish(),output_tokens:S.number(),output_tokens_details:S.object({reasoning_tokens:S.number().nullish()}).nullish()}).optional()}))),KN=20,RX=["o1","o1-2024-12-17","o3","o3-2025-04-16","o3-deep-research","o3-deep-research-2025-06-26","o3-mini","o3-mini-2025-01-31","o4-mini","o4-mini-2025-04-16","o4-mini-deep-research","o4-mini-deep-research-2025-06-26","codex-mini-latest","computer-use-preview","gpt-5","gpt-5-2025-08-07","gpt-5-codex","gpt-5-mini","gpt-5-mini-2025-08-07","gpt-5-nano","gpt-5-nano-2025-08-07","gpt-5-pro","gpt-5-pro-2025-10-06","gpt-5.1","gpt-5.1-chat-latest","gpt-5.1-codex-mini","gpt-5.1-codex","gpt-5.1-codex-max","gpt-5.2","gpt-5.2-chat-latest","gpt-5.2-pro"],n6e=["gpt-4.1","gpt-4.1-2025-04-14","gpt-4.1-mini","gpt-4.1-mini-2025-04-14","gpt-4.1-nano","gpt-4.1-nano-2025-04-14","gpt-4o","gpt-4o-2024-05-13","gpt-4o-2024-08-06","gpt-4o-2024-11-20","gpt-4o-audio-preview","gpt-4o-audio-preview-2024-10-01","gpt-4o-audio-preview-2024-12-17","gpt-4o-search-preview","gpt-4o-search-preview-2025-03-11","gpt-4o-mini-search-preview","gpt-4o-mini-search-preview-2025-03-11","gpt-4o-mini","gpt-4o-mini-2024-07-18","gpt-4-turbo","gpt-4-turbo-2024-04-09","gpt-4-turbo-preview","gpt-4-0125-preview","gpt-4-1106-preview","gpt-4","gpt-4-0613","gpt-4.5-preview","gpt-4.5-preview-2025-02-27","gpt-3.5-turbo-0125","gpt-3.5-turbo","gpt-3.5-turbo-1106","chatgpt-4o-latest","gpt-5-chat-latest",...RX],CX=ot(()=>me(vt.object({conversation:vt.string().nullish(),include:vt.array(vt.enum(["reasoning.encrypted_content","file_search_call.results","message.output_text.logprobs"])).nullish(),instructions:vt.string().nullish(),logprobs:vt.union([vt.boolean(),vt.number().min(1).max(KN)]).optional(),maxToolCalls:vt.number().nullish(),metadata:vt.any().nullish(),parallelToolCalls:vt.boolean().nullish(),previousResponseId:vt.string().nullish(),promptCacheKey:vt.string().nullish(),promptCacheRetention:vt.enum(["in_memory","24h"]).nullish(),reasoningEffort:vt.string().nullish(),reasoningSummary:vt.string().nullish(),safetyIdentifier:vt.string().nullish(),serviceTier:vt.enum(["auto","flex","priority","default"]).nullish(),store:vt.boolean().nullish(),strictJsonSchema:vt.boolean().nullish(),textVerbosity:vt.enum(["low","medium","high"]).nullish(),truncation:vt.enum(["auto","disabled"]).nullish(),user:vt.string().nullish()})));async function xX({tools:r,toolChoice:e,strictJsonSchema:t}){r=r?.length?r:void 0;let n=[];if(r==null)return{tools:void 0,toolChoice:void 0,toolWarnings:n};let o=[];for(let a of r)switch(a.type){case"function":o.push({type:"function",name:a.name,description:a.description,parameters:a.inputSchema,strict:t});break;case"provider-defined":{switch(a.id){case"openai.file_search":{let s=await $n({value:a.args,schema:rX});o.push({type:"file_search",vector_store_ids:s.vectorStoreIds,max_num_results:s.maxNumResults,ranking_options:s.ranking?{ranker:s.ranking.ranker,score_threshold:s.ranking.scoreThreshold}:void 0,filters:s.filters});break}case"openai.local_shell":{o.push({type:"local_shell"});break}case"openai.web_search_preview":{let s=await $n({value:a.args,schema:fX});o.push({type:"web_search_preview",search_context_size:s.searchContextSize,user_location:s.userLocation});break}case"openai.web_search":{let s=await $n({value:a.args,schema:dX});o.push({type:"web_search",filters:s.filters!=null?{allowed_domains:s.filters.allowedDomains}:void 0,external_web_access:s.externalWebAccess,search_context_size:s.searchContextSize,user_location:s.userLocation});break}case"openai.code_interpreter":{let s=await $n({value:a.args,schema:Q5});o.push({type:"code_interpreter",container:s.container==null?{type:"auto",file_ids:void 0}:typeof s.container=="string"?s.container:{type:"auto",file_ids:s.container.fileIds}});break}case"openai.image_generation":{let s=await $n({value:a.args,schema:iX});o.push({type:"image_generation",background:s.background,input_fidelity:s.inputFidelity,input_image_mask:s.inputImageMask?{file_id:s.inputImageMask.fileId,image_url:s.inputImageMask.imageUrl}:void 0,model:s.model,size:s.size,quality:s.quality,moderation:s.moderation,output_format:s.outputFormat,output_compression:s.outputCompression});break}}break}default:n.push({type:"unsupported-tool",tool:a});break}if(e==null)return{tools:o,toolChoice:void 0,toolWarnings:n};let i=e.type;switch(i){case"auto":case"none":case"required":return{tools:o,toolChoice:i,toolWarnings:n};case"tool":return{tools:o,toolChoice:e.toolName==="code_interpreter"||e.toolName==="file_search"||e.toolName==="image_generation"||e.toolName==="web_search_preview"||e.toolName==="web_search"?{type:e.toolName}:{type:"function",name:e.toolName},toolWarnings:n};default:{let a=i;throw new Mr({functionality:`tool choice type: ${a}`})}}}var _X=class{constructor(r,e){this.specificationVersion="v2",this.supportedUrls={"image/*":[/^https?:\/\/.*$/],"application/pdf":[/^https?:\/\/.*$/]},this.modelId=r,this.config=e}get provider(){return this.config.provider}async getArgs({maxOutputTokens:r,temperature:e,stopSequences:t,topP:n,topK:o,presencePenalty:i,frequencyPenalty:a,seed:s,prompt:c,providerOptions:l,tools:u,toolChoice:d,responseFormat:p}){var m,g,h,f;let y=[],E=jN(this.modelId);o!=null&&y.push({type:"unsupported-setting",setting:"topK"}),s!=null&&y.push({type:"unsupported-setting",setting:"seed"}),i!=null&&y.push({type:"unsupported-setting",setting:"presencePenalty"}),a!=null&&y.push({type:"unsupported-setting",setting:"frequencyPenalty"}),t!=null&&y.push({type:"unsupported-setting",setting:"stopSequences"});let b=await Tr({provider:"openai",providerOptions:l,schema:CX});b?.conversation&&b?.previousResponseId&&y.push({type:"unsupported-setting",setting:"conversation",details:"conversation and previousResponseId cannot be used together"});let{input:x,warnings:P}=await TX({prompt:c,systemMessageMode:E.systemMessageMode,fileIdPrefixes:this.config.fileIdPrefixes,store:(m=b?.store)!=null?m:!0,hasLocalShellTool:D("openai.local_shell")});y.push(...P);let O=(g=b?.strictJsonSchema)!=null?g:!1,T=b?.include;function R(j){T==null?T=[j]:T.includes(j)||(T=[...T,j])}function D(j){return u?.find(ue=>ue.type==="provider-defined"&&ue.id===j)!=null}let I=typeof b?.logprobs=="number"?b?.logprobs:b?.logprobs===!0?KN:void 0;I&&R("message.output_text.logprobs");let k=(h=u?.find(j=>j.type==="provider-defined"&&(j.id==="openai.web_search"||j.id==="openai.web_search_preview")))==null?void 0:h.name;k&&R("web_search_call.action.sources"),D("openai.code_interpreter")&&R("code_interpreter_call.outputs");let F=b?.store;F===!1&&E.isReasoningModel&&R("reasoning.encrypted_content");let ee={model:this.modelId,input:x,temperature:e,top_p:n,max_output_tokens:r,...(p?.type==="json"||b?.textVerbosity)&&{text:{...p?.type==="json"&&{format:p.schema!=null?{type:"json_schema",strict:O,name:(f=p.name)!=null?f:"response",description:p.description,schema:p.schema}:{type:"json_object"}},...b?.textVerbosity&&{verbosity:b.textVerbosity}}},conversation:b?.conversation,max_tool_calls:b?.maxToolCalls,metadata:b?.metadata,parallel_tool_calls:b?.parallelToolCalls,previous_response_id:b?.previousResponseId,store:F,user:b?.user,instructions:b?.instructions,service_tier:b?.serviceTier,include:T,prompt_cache_key:b?.promptCacheKey,prompt_cache_retention:b?.promptCacheRetention,safety_identifier:b?.safetyIdentifier,top_logprobs:I,truncation:b?.truncation,...E.isReasoningModel&&(b?.reasoningEffort!=null||b?.reasoningSummary!=null)&&{reasoning:{...b?.reasoningEffort!=null&&{effort:b.reasoningEffort},...b?.reasoningSummary!=null&&{summary:b.reasoningSummary}}}};E.isReasoningModel?b?.reasoningEffort==="none"&&E.supportsNonReasoningParameters||(ee.temperature!=null&&(ee.temperature=void 0,y.push({type:"unsupported-setting",setting:"temperature",details:"temperature is not supported for reasoning models"})),ee.top_p!=null&&(ee.top_p=void 0,y.push({type:"unsupported-setting",setting:"topP",details:"topP is not supported for reasoning models"}))):(b?.reasoningEffort!=null&&y.push({type:"unsupported-setting",setting:"reasoningEffort",details:"reasoningEffort is not supported for non-reasoning models"}),b?.reasoningSummary!=null&&y.push({type:"unsupported-setting",setting:"reasoningSummary",details:"reasoningSummary is not supported for non-reasoning models"})),b?.serviceTier==="flex"&&!E.supportsFlexProcessing&&(y.push({type:"unsupported-setting",setting:"serviceTier",details:"flex processing is only available for o3, o4-mini, and gpt-5 models"}),delete ee.service_tier),b?.serviceTier==="priority"&&!E.supportsPriorityProcessing&&(y.push({type:"unsupported-setting",setting:"serviceTier",details:"priority processing is only available for supported models (gpt-4, gpt-5, gpt-5-mini, o3, o4-mini) and requires Enterprise access. gpt-5-nano is not supported"}),delete ee.service_tier);let{tools:K,toolChoice:ge,toolWarnings:B}=await xX({tools:u,toolChoice:d,strictJsonSchema:O});return{webSearchToolName:k,args:{...ee,tools:K,tool_choice:ge},warnings:[...y,...B],store:F}}async doGenerate(r){var e,t,n,o,i,a,s,c,l,u,d,p,m,g,h,f,y,E,b,x,P,O,T,R,D,I,k,F;let{args:ee,warnings:K,webSearchToolName:ge}=await this.getArgs(r),B=this.config.url({path:"/responses",modelId:this.modelId}),j=this.config.provider.replace(".responses",""),{responseHeaders:ue,value:le,rawValue:He}=await vr({url:B,headers:Qt(this.config.headers(),r.headers),body:ee,failedResponseHandler:Kn,successfulResponseHandler:un(wX),abortSignal:r.abortSignal,fetch:this.config.fetch});if(le.error)throw new ar({message:le.error.message,url:B,requestBodyValues:ee,statusCode:400,responseHeaders:ue,responseBody:He,isRetryable:!1});let ve=[],q=[],fe=!1;for(let C of le.output)switch(C.type){case"reasoning":{C.summary.length===0&&C.summary.push({type:"summary_text",text:""});for(let oe of C.summary)ve.push({type:"reasoning",text:oe.text,providerMetadata:{[j]:{itemId:C.id,reasoningEncryptedContent:(e=C.encrypted_content)!=null?e:null}}});break}case"image_generation_call":{ve.push({type:"tool-call",toolCallId:C.id,toolName:"image_generation",input:"{}",providerExecuted:!0}),ve.push({type:"tool-result",toolCallId:C.id,toolName:"image_generation",result:{result:C.result},providerExecuted:!0});break}case"local_shell_call":{ve.push({type:"tool-call",toolCallId:C.call_id,toolName:"local_shell",input:JSON.stringify({action:C.action}),providerMetadata:{[j]:{itemId:C.id}}});break}case"message":{for(let oe of C.content){(n=(t=r.providerOptions)==null?void 0:t.openai)!=null&&n.logprobs&&oe.logprobs&&q.push(oe.logprobs),ve.push({type:"text",text:oe.text,providerMetadata:{[j]:{itemId:C.id}}});for(let pe of oe.annotations)pe.type==="url_citation"?ve.push({type:"source",sourceType:"url",id:(a=(i=(o=this.config).generateId)==null?void 0:i.call(o))!=null?a:Fr(),url:pe.url,title:pe.title}):pe.type==="file_citation"?ve.push({type:"source",sourceType:"document",id:(l=(c=(s=this.config).generateId)==null?void 0:c.call(s))!=null?l:Fr(),mediaType:"text/plain",title:(d=(u=pe.quote)!=null?u:pe.filename)!=null?d:"Document",filename:(p=pe.filename)!=null?p:pe.file_id,...pe.file_id?{providerMetadata:{[j]:{fileId:pe.file_id}}}:{}}):pe.type==="container_file_citation"?ve.push({type:"source",sourceType:"document",id:(h=(g=(m=this.config).generateId)==null?void 0:g.call(m))!=null?h:Fr(),mediaType:"text/plain",title:(y=(f=pe.filename)!=null?f:pe.file_id)!=null?y:"Document",filename:(E=pe.filename)!=null?E:pe.file_id,providerMetadata:{[j]:{fileId:pe.file_id,containerId:pe.container_id,...pe.index!=null?{index:pe.index}:{}}}}):pe.type==="file_path"&&ve.push({type:"source",sourceType:"document",id:(P=(x=(b=this.config).generateId)==null?void 0:x.call(b))!=null?P:Fr(),mediaType:"application/octet-stream",title:pe.file_id,filename:pe.file_id,providerMetadata:{[j]:{fileId:pe.file_id,...pe.index!=null?{index:pe.index}:{}}}})}break}case"function_call":{fe=!0,ve.push({type:"tool-call",toolCallId:C.call_id,toolName:C.name,input:C.arguments,providerMetadata:{[j]:{itemId:C.id}}});break}case"web_search_call":{ve.push({type:"tool-call",toolCallId:C.id,toolName:ge??"web_search",input:JSON.stringify({}),providerExecuted:!0}),ve.push({type:"tool-result",toolCallId:C.id,toolName:ge??"web_search",result:HN(C.action),providerExecuted:!0});break}case"computer_call":{ve.push({type:"tool-call",toolCallId:C.id,toolName:"computer_use",input:"",providerExecuted:!0}),ve.push({type:"tool-result",toolCallId:C.id,toolName:"computer_use",result:{type:"computer_use_tool_result",status:C.status||"completed"},providerExecuted:!0});break}case"file_search_call":{ve.push({type:"tool-call",toolCallId:C.id,toolName:"file_search",input:"{}",providerExecuted:!0}),ve.push({type:"tool-result",toolCallId:C.id,toolName:"file_search",result:{queries:C.queries,results:(T=(O=C.results)==null?void 0:O.map(oe=>({attributes:oe.attributes,fileId:oe.file_id,filename:oe.filename,score:oe.score,text:oe.text})))!=null?T:null},providerExecuted:!0});break}case"code_interpreter_call":{ve.push({type:"tool-call",toolCallId:C.id,toolName:"code_interpreter",input:JSON.stringify({code:C.code,containerId:C.container_id}),providerExecuted:!0}),ve.push({type:"tool-result",toolCallId:C.id,toolName:"code_interpreter",result:{outputs:C.outputs},providerExecuted:!0});break}}let it={[j]:{...le.id!=null?{responseId:le.id}:{}}};q.length>0&&(it[j].logprobs=q),typeof le.service_tier=="string"&&(it[j].serviceTier=le.service_tier);let Ae=le.usage;return{content:ve,finishReason:BN({finishReason:(R=le.incomplete_details)==null?void 0:R.reason,hasFunctionCall:fe}),usage:{inputTokens:Ae.input_tokens,outputTokens:Ae.output_tokens,totalTokens:Ae.input_tokens+Ae.output_tokens,reasoningTokens:(I=(D=Ae.output_tokens_details)==null?void 0:D.reasoning_tokens)!=null?I:void 0,cachedInputTokens:(F=(k=Ae.input_tokens_details)==null?void 0:k.cached_tokens)!=null?F:void 0},request:{body:ee},response:{id:le.id,timestamp:new Date(le.created_at*1e3),modelId:le.model,headers:ue,body:He},providerMetadata:it,warnings:K}}async doStream(r){let{args:e,warnings:t,webSearchToolName:n,store:o}=await this.getArgs(r),{responseHeaders:i,value:a}=await vr({url:this.config.url({path:"/responses",modelId:this.modelId}),headers:Qt(this.config.headers(),r.headers),body:{...e,stream:!0},failedResponseHandler:Kn,successfulResponseHandler:Ks(AX),abortSignal:r.abortSignal,fetch:this.config.fetch}),s=this,c=this.config.provider.replace(".responses",""),l="unknown",u={inputTokens:void 0,outputTokens:void 0,totalTokens:void 0},d=[],p=null,m={},g=[],h=!1,f={},y;return{stream:a.pipeThrough(new TransformStream({start(E){E.enqueue({type:"stream-start",warnings:t})},transform(E,b){var x,P,O,T,R,D,I,k,F,ee,K,ge,B,j,ue,le,He,ve,q,fe,it,Ae;if(r.includeRawChunks&&b.enqueue({type:"raw",rawValue:E.rawValue}),!E.success){l="error",b.enqueue({type:"error",error:E.error});return}let C=E.value;if(zN(C))C.item.type==="function_call"?(m[C.output_index]={toolName:C.item.name,toolCallId:C.item.call_id},b.enqueue({type:"tool-input-start",id:C.item.call_id,toolName:C.item.name})):C.item.type==="web_search_call"?(m[C.output_index]={toolName:n??"web_search",toolCallId:C.item.id},b.enqueue({type:"tool-input-start",id:C.item.id,toolName:n??"web_search",providerExecuted:!0}),b.enqueue({type:"tool-input-end",id:C.item.id}),b.enqueue({type:"tool-call",toolCallId:C.item.id,toolName:n??"web_search",input:JSON.stringify({}),providerExecuted:!0})):C.item.type==="computer_call"?(m[C.output_index]={toolName:"computer_use",toolCallId:C.item.id},b.enqueue({type:"tool-input-start",id:C.item.id,toolName:"computer_use",providerExecuted:!0})):C.item.type==="code_interpreter_call"?(m[C.output_index]={toolName:"code_interpreter",toolCallId:C.item.id,codeInterpreter:{containerId:C.item.container_id}},b.enqueue({type:"tool-input-start",id:C.item.id,toolName:"code_interpreter",providerExecuted:!0}),b.enqueue({type:"tool-input-delta",id:C.item.id,delta:`{"containerId":"${C.item.container_id}","code":"`})):C.item.type==="file_search_call"?b.enqueue({type:"tool-call",toolCallId:C.item.id,toolName:"file_search",input:"{}",providerExecuted:!0}):C.item.type==="image_generation_call"?b.enqueue({type:"tool-call",toolCallId:C.item.id,toolName:"image_generation",input:"{}",providerExecuted:!0}):C.item.type==="message"?(g.splice(0,g.length),b.enqueue({type:"text-start",id:C.item.id,providerMetadata:{[c]:{itemId:C.item.id}}})):zN(C)&&C.item.type==="reasoning"&&(f[C.item.id]={encryptedContent:C.item.encrypted_content,summaryParts:{0:"active"}},b.enqueue({type:"reasoning-start",id:`${C.item.id}:0`,providerMetadata:{[c]:{itemId:C.item.id,reasoningEncryptedContent:(x=C.item.encrypted_content)!=null?x:null}}}));else if(PX(C)){if(C.item.type==="message")b.enqueue({type:"text-end",id:C.item.id,providerMetadata:{[c]:{itemId:C.item.id,...g.length>0&&{annotations:g}}}});else if(C.item.type==="function_call")m[C.output_index]=void 0,h=!0,b.enqueue({type:"tool-input-end",id:C.item.call_id}),b.enqueue({type:"tool-call",toolCallId:C.item.call_id,toolName:C.item.name,input:C.item.arguments,providerMetadata:{[c]:{itemId:C.item.id}}});else if(C.item.type==="web_search_call")m[C.output_index]=void 0,b.enqueue({type:"tool-result",toolCallId:C.item.id,toolName:n??"web_search",result:HN(C.item.action),providerExecuted:!0});else if(C.item.type==="computer_call")m[C.output_index]=void 0,b.enqueue({type:"tool-input-end",id:C.item.id}),b.enqueue({type:"tool-call",toolCallId:C.item.id,toolName:"computer_use",input:"",providerExecuted:!0}),b.enqueue({type:"tool-result",toolCallId:C.item.id,toolName:"computer_use",result:{type:"computer_use_tool_result",status:C.item.status||"completed"},providerExecuted:!0});else if(C.item.type==="file_search_call")m[C.output_index]=void 0,b.enqueue({type:"tool-result",toolCallId:C.item.id,toolName:"file_search",result:{queries:C.item.queries,results:(O=(P=C.item.results)==null?void 0:P.map(oe=>({attributes:oe.attributes,fileId:oe.file_id,filename:oe.filename,score:oe.score,text:oe.text})))!=null?O:null},providerExecuted:!0});else if(C.item.type==="code_interpreter_call")m[C.output_index]=void 0,b.enqueue({type:"tool-result",toolCallId:C.item.id,toolName:"code_interpreter",result:{outputs:C.item.outputs},providerExecuted:!0});else if(C.item.type==="image_generation_call")b.enqueue({type:"tool-result",toolCallId:C.item.id,toolName:"image_generation",result:{result:C.item.result},providerExecuted:!0});else if(C.item.type==="local_shell_call")m[C.output_index]=void 0,b.enqueue({type:"tool-call",toolCallId:C.item.call_id,toolName:"local_shell",input:JSON.stringify({action:{type:"exec",command:C.item.action.command,timeoutMs:C.item.action.timeout_ms,user:C.item.action.user,workingDirectory:C.item.action.working_directory,env:C.item.action.env}}),providerMetadata:{[c]:{itemId:C.item.id}}});else if(C.item.type==="reasoning"){let oe=f[C.item.id],pe=Object.entries(oe.summaryParts).filter(([Br,gi])=>gi==="active"||gi==="can-conclude").map(([Br])=>Br);for(let Br of pe)b.enqueue({type:"reasoning-end",id:`${C.item.id}:${Br}`,providerMetadata:{[c]:{itemId:C.item.id,reasoningEncryptedContent:(T=C.item.encrypted_content)!=null?T:null}}});delete f[C.item.id]}}else if(LX(C)){let oe=m[C.output_index];oe!=null&&b.enqueue({type:"tool-input-delta",id:oe.toolCallId,delta:C.delta})}else if(NX(C)){let oe=m[C.output_index];oe!=null&&b.enqueue({type:"tool-input-delta",id:oe.toolCallId,delta:JSON.stringify(C.delta).slice(1,-1)})}else if(DX(C)){let oe=m[C.output_index];oe!=null&&(b.enqueue({type:"tool-input-delta",id:oe.toolCallId,delta:'"}'}),b.enqueue({type:"tool-input-end",id:oe.toolCallId}),b.enqueue({type:"tool-call",toolCallId:oe.toolCallId,toolName:"code_interpreter",input:JSON.stringify({code:C.code,containerId:oe.codeInterpreter.containerId}),providerExecuted:!0}))}else if(OX(C))p=C.response.id,b.enqueue({type:"response-metadata",id:C.response.id,timestamp:new Date(C.response.created_at*1e3),modelId:C.response.model});else if(MX(C))b.enqueue({type:"text-delta",id:C.item_id,delta:C.delta}),(D=(R=r.providerOptions)==null?void 0:R.openai)!=null&&D.logprobs&&C.logprobs&&d.push(C.logprobs);else if(C.type==="response.reasoning_summary_part.added"){if(C.summary_index>0){let oe=f[C.item_id];oe.summaryParts[C.summary_index]="active";for(let pe of Object.keys(oe.summaryParts))oe.summaryParts[pe]==="can-conclude"&&(b.enqueue({type:"reasoning-end",id:`${C.item_id}:${pe}`,providerMetadata:{[c]:{itemId:C.item_id}}}),oe.summaryParts[pe]="concluded");b.enqueue({type:"reasoning-start",id:`${C.item_id}:${C.summary_index}`,providerMetadata:{[c]:{itemId:C.item_id,reasoningEncryptedContent:(k=(I=f[C.item_id])==null?void 0:I.encryptedContent)!=null?k:null}}})}}else C.type==="response.reasoning_summary_text.delta"?b.enqueue({type:"reasoning-delta",id:`${C.item_id}:${C.summary_index}`,delta:C.delta,providerMetadata:{[c]:{itemId:C.item_id}}}):C.type==="response.reasoning_summary_part.done"?o?(b.enqueue({type:"reasoning-end",id:`${C.item_id}:${C.summary_index}`,providerMetadata:{[c]:{itemId:C.item_id}}}),f[C.item_id].summaryParts[C.summary_index]="concluded"):f[C.item_id].summaryParts[C.summary_index]="can-conclude":IX(C)?(l=BN({finishReason:(F=C.response.incomplete_details)==null?void 0:F.reason,hasFunctionCall:h}),u.inputTokens=C.response.usage.input_tokens,u.outputTokens=C.response.usage.output_tokens,u.totalTokens=C.response.usage.input_tokens+C.response.usage.output_tokens,u.reasoningTokens=(K=(ee=C.response.usage.output_tokens_details)==null?void 0:ee.reasoning_tokens)!=null?K:void 0,u.cachedInputTokens=(B=(ge=C.response.usage.input_tokens_details)==null?void 0:ge.cached_tokens)!=null?B:void 0,typeof C.response.service_tier=="string"&&(y=C.response.service_tier)):kX(C)?(g.push(C.annotation),C.annotation.type==="url_citation"?b.enqueue({type:"source",sourceType:"url",id:(le=(ue=(j=s.config).generateId)==null?void 0:ue.call(j))!=null?le:Fr(),url:C.annotation.url,title:C.annotation.title}):C.annotation.type==="file_citation"&&b.enqueue({type:"source",sourceType:"document",id:(q=(ve=(He=s.config).generateId)==null?void 0:ve.call(He))!=null?q:Fr(),mediaType:"text/plain",title:(it=(fe=C.annotation.quote)!=null?fe:C.annotation.filename)!=null?it:"Document",filename:(Ae=C.annotation.filename)!=null?Ae:C.annotation.file_id,...C.annotation.file_id?{providerMetadata:{[c]:{fileId:C.annotation.file_id}}}:{}})):FX(C)&&b.enqueue({type:"error",error:C})},flush(E){let b={[c]:{responseId:p}};d.length>0&&(b[c].logprobs=d),y!==void 0&&(b[c].serviceTier=y),E.enqueue({type:"finish",finishReason:l,usage:u,providerMetadata:b})}})),request:{body:e},response:{headers:i}}}};function MX(r){return r.type==="response.output_text.delta"}function PX(r){return r.type==="response.output_item.done"}function IX(r){return r.type==="response.completed"||r.type==="response.incomplete"}function OX(r){return r.type==="response.created"}function LX(r){return r.type==="response.function_call_arguments.delta"}function NX(r){return r.type==="response.code_interpreter_call_code.delta"}function DX(r){return r.type==="response.code_interpreter_call_code.done"}function zN(r){return r.type==="response.output_item.added"}function kX(r){return r.type==="response.output_text.annotation.added"}function FX(r){return r.type==="error"}function HN(r){var e;switch(r.type){case"search":return{action:{type:"search",query:(e=r.query)!=null?e:void 0},...r.sources!=null&&{sources:r.sources}};case"open_page":return{action:{type:"openPage",url:r.url}};case"find_in_page":return{action:{type:"findInPage",url:r.url,pattern:r.pattern}}}}var UX=ot(()=>me(sb.object({instructions:sb.string().nullish(),speed:sb.number().min(.25).max(4).default(1).nullish()}))),BX=class{constructor(r,e){this.modelId=r,this.config=e,this.specificationVersion="v2"}get provider(){return this.config.provider}async getArgs({text:r,voice:e="alloy",outputFormat:t="mp3",speed:n,instructions:o,language:i,providerOptions:a}){let s=[],c=await Tr({provider:"openai",providerOptions:a,schema:UX}),l={model:this.modelId,input:r,voice:e,response_format:"mp3",speed:n,instructions:o};if(t&&(["mp3","opus","aac","flac","wav","pcm"].includes(t)?l.response_format=t:s.push({type:"unsupported-setting",setting:"outputFormat",details:`Unsupported output format: ${t}. Using mp3 instead.`})),c){let u={};for(let d in u){let p=u[d];p!==void 0&&(l[d]=p)}}return i&&s.push({type:"unsupported-setting",setting:"language",details:`OpenAI speech models do not support language selection. Language parameter "${i}" was ignored.`}),{requestBody:l,warnings:s}}async doGenerate(r){var e,t,n;let o=(n=(t=(e=this.config._internal)==null?void 0:e.currentDate)==null?void 0:t.call(e))!=null?n:new Date,{requestBody:i,warnings:a}=await this.getArgs(r),{value:s,responseHeaders:c,rawValue:l}=await vr({url:this.config.url({path:"/audio/speech",modelId:this.modelId}),headers:Qt(this.config.headers(),r.headers),body:i,failedResponseHandler:Kn,successfulResponseHandler:CN(),abortSignal:r.abortSignal,fetch:this.config.fetch});return{audio:s,warnings:a,request:{body:JSON.stringify(i)},response:{timestamp:o,modelId:this.modelId,headers:c,body:l}}}},zX=ot(()=>me(xt.object({text:xt.string(),language:xt.string().nullish(),duration:xt.number().nullish(),words:xt.array(xt.object({word:xt.string(),start:xt.number(),end:xt.number()})).nullish(),segments:xt.array(xt.object({id:xt.number(),seek:xt.number(),start:xt.number(),end:xt.number(),text:xt.string(),tokens:xt.array(xt.number()),temperature:xt.number(),avg_logprob:xt.number(),compression_ratio:xt.number(),no_speech_prob:xt.number()})).nullish()}))),HX=ot(()=>me(di.object({include:di.array(di.string()).optional(),language:di.string().optional(),prompt:di.string().optional(),temperature:di.number().min(0).max(1).default(0).optional(),timestampGranularities:di.array(di.enum(["word","segment"])).default(["segment"]).optional()}))),GN={afrikaans:"af",arabic:"ar",armenian:"hy",azerbaijani:"az",belarusian:"be",bosnian:"bs",bulgarian:"bg",catalan:"ca",chinese:"zh",croatian:"hr",czech:"cs",danish:"da",dutch:"nl",english:"en",estonian:"et",finnish:"fi",french:"fr",galician:"gl",german:"de",greek:"el",hebrew:"he",hindi:"hi",hungarian:"hu",icelandic:"is",indonesian:"id",italian:"it",japanese:"ja",kannada:"kn",kazakh:"kk",korean:"ko",latvian:"lv",lithuanian:"lt",macedonian:"mk",malay:"ms",marathi:"mr",maori:"mi",nepali:"ne",norwegian:"no",persian:"fa",polish:"pl",portuguese:"pt",romanian:"ro",russian:"ru",serbian:"sr",slovak:"sk",slovenian:"sl",spanish:"es",swahili:"sw",swedish:"sv",tagalog:"tl",tamil:"ta",thai:"th",turkish:"tr",ukrainian:"uk",urdu:"ur",vietnamese:"vi",welsh:"cy"},GX=class{constructor(r,e){this.modelId=r,this.config=e,this.specificationVersion="v2"}get provider(){return this.config.provider}async getArgs({audio:r,mediaType:e,providerOptions:t}){let n=[],o=await Tr({provider:"openai",providerOptions:t,schema:HX}),i=new FormData,a=r instanceof Uint8Array?new Blob([r]):new Blob([ON(r)]);i.append("model",this.modelId);let s=TN(e);if(i.append("file",new File([a],"audio",{type:e}),`audio.${s}`),o){let c={include:o.include,language:o.language,prompt:o.prompt,response_format:["gpt-4o-transcribe","gpt-4o-mini-transcribe"].includes(this.modelId)?"json":"verbose_json",temperature:o.temperature,timestamp_granularities:o.timestampGranularities};for(let[l,u]of Object.entries(c))if(u!=null)if(Array.isArray(u))for(let d of u)i.append(`${l}[]`,String(d));else i.append(l,String(u))}return{formData:i,warnings:n}}async doGenerate(r){var e,t,n,o,i,a,s,c;let l=(n=(t=(e=this.config._internal)==null?void 0:e.currentDate)==null?void 0:t.call(e))!=null?n:new Date,{formData:u,warnings:d}=await this.getArgs(r),{value:p,responseHeaders:m,rawValue:g}=await AN({url:this.config.url({path:"/audio/transcriptions",modelId:this.modelId}),headers:Qt(this.config.headers(),r.headers),formData:u,failedResponseHandler:Kn,successfulResponseHandler:un(zX),abortSignal:r.abortSignal,fetch:this.config.fetch}),h=p.language!=null&&p.language in GN?GN[p.language]:void 0;return{text:p.text,segments:(s=(a=(o=p.segments)==null?void 0:o.map(f=>({text:f.text,startSecond:f.start,endSecond:f.end})))!=null?a:(i=p.words)==null?void 0:i.map(f=>({text:f.word,startSecond:f.start,endSecond:f.end})))!=null?s:[],language:h,durationInSeconds:(c=p.duration)!=null?c:void 0,warnings:d,response:{timestamp:l,modelId:this.modelId,headers:m,body:g}}}},jX="2.0.89";function cb(r={}){var e,t;let n=(e=LN(EN({settingValue:r.baseURL,environmentVariableName:"OPENAI_BASE_URL"})))!=null?e:"https://api.openai.com/v1",o=(t=r.name)!=null?t:"openai",i=()=>eb({Authorization:`Bearer ${bN({apiKey:r.apiKey,environmentVariableName:"OPENAI_API_KEY",description:"OpenAI"})}`,"OpenAI-Organization":r.organization,"OpenAI-Project":r.project,...r.headers},`ai-sdk/openai/${jX}`),a=h=>new B5(h,{provider:`${o}.chat`,url:({path:f})=>`${n}${f}`,headers:i,fetch:r.fetch}),s=h=>new j5(h,{provider:`${o}.completion`,url:({path:f})=>`${n}${f}`,headers:i,fetch:r.fetch}),c=h=>new $5(h,{provider:`${o}.embedding`,url:({path:f})=>`${n}${f}`,headers:i,fetch:r.fetch}),l=h=>new X5(h,{provider:`${o}.image`,url:({path:f})=>`${n}${f}`,headers:i,fetch:r.fetch}),u=h=>new GX(h,{provider:`${o}.transcription`,url:({path:f})=>`${n}${f}`,headers:i,fetch:r.fetch}),d=h=>new BX(h,{provider:`${o}.speech`,url:({path:f})=>`${n}${f}`,headers:i,fetch:r.fetch}),p=h=>{if(new.target)throw new Error("The OpenAI model function cannot be called with the new keyword.");return m(h)},m=h=>new _X(h,{provider:`${o}.responses`,url:({path:f})=>`${n}${f}`,headers:i,fetch:r.fetch,fileIdPrefixes:["file-"]}),g=function(h){return p(h)};return g.languageModel=p,g.chat=a,g.completion=s,g.responses=m,g.embedding=c,g.textEmbedding=c,g.textEmbeddingModel=c,g.image=l,g.imageModel=l,g.transcription=u,g.transcriptionModel=u,g.speech=d,g.speechModel=d,g.tools=EX,g}var g6e=cb();function YN(r){let{apiKey:e,sessionId:t,extraHeaders:n,loggerTags:o}=r,i={Authorization:`Bearer ${e}`,[Rd]:pa??"",...t&&{[uw]:t},...n||{}};return o&&(i[cw]=JSON.stringify(o)),i}var Fp=r=>e=>{let t=YN(r);return WX({baseURL:`${r.baseUrl}/v1/llm/anthropic/${e}`,headers:t,apiKey:r.apiKey})(e)},XN=r=>e=>{let t=YN(r);return cb({baseURL:`${r.baseUrl}/v1/llm/openai/${e}`,headers:t,apiKey:r.apiKey})(e)};var ha=class extends Vn{agentConfig;constructor(e,t){let n={...Uv,...e};super(t),this.agentConfig=n}getAgentConfig(){return this.agentConfig}async rankChunksWithAi(e,t){let n={...e,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/web-agent/recommend-chunks-ai`,{method:"POST",body:n,signal:t.abortSignal});return Av.parse(o)}async rankChunksWithRag(e,t){let n=await this.sendRequest(`/${W}/web-agent/recommend-chunks`,{method:"POST",body:{cliVersion:pa,...e},signal:t.abortSignal});return vv.parse(n)}async getScreenshotFromS3(e){let t=await this.sendRequest(`/${W}/s3/visual-diff-screenshot`,{method:"POST",body:{url:e}});return VX.string().parse(t)}async getElementLocation(e,t){let n={...e,disableCache:t.disableCache,loggerTags:t.loggerTags,useMemory:t.useMemory,agentConfigVersion:this.agentConfig?.locator},o=await this.sendRequest(`/${W}/web-agent/locate-element`,{method:"POST",body:n,signal:t.abortSignal});return fw.parse(o)}async getAssertionResult(e,t){let n={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,attemptNumber:t.attemptNumber,loggerTags:t.loggerTags,useMemory:t.useMemory,agentConfigVersion:this.agentConfig?.assertion},o=await this.sendRequest(`/${W}/web-agent/assertion`,{method:"POST",body:n,signal:t.abortSignal});return tf.parse(o)}async getLintStepResult(e,t){let n={...e,disableCache:!!t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/web-agent/lint/step`,{method:"POST",body:n,signal:t.abortSignal});return hw.parse(o)}async getLintMcpCopilotMessageResult(e,t){let n={message:e.message,disableCache:!!t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/web-agent/lint/mcp-copilot`,{method:"POST",body:n,signal:t.abortSignal});return mw.parse(o)}async getMcpCopilotConversationEvaluation(e,t){let n={messagesAndToolCalls:e.messagesAndToolCalls,disableCache:!!t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/web-agent/mcp-copilot-conversation-evaluator`,{method:"POST",body:n,signal:t.abortSignal});return pw.parse(o)}async getMcpCopilotChatSummary(e,t){let n={messagesAndToolCalls:e.messagesAndToolCalls,disableCache:!!t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/web-agent/mcp-copilot-chat-summary`,{method:"POST",body:n,signal:t.abortSignal});return gw.parse(o)}async getVisualAssertionResult(e,t){let n={...e,disableCache:!!t.disableCache,useConsensus:!!t.useConsensus,attemptNumber:t.attemptNumber,loggerTags:t.loggerTags,useMemory:t.useMemory,agentConfigVersion:this.agentConfig?.["visual-assertion"]},o=await this.sendRequest(`/${W}/web-agent/visual-assertion`,{method:"POST",body:n,signal:t.abortSignal});return tf.parse(o)}async getAiActionCommand(e,t){let n=await this.sendRequest(`/${W}/web-agent/next-command-dynamic`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return dw.parse(n)}async getMultiturnAiActionCommand(e,t){return await this.sendRequest(`/${W}/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(`/${W}/web-agent/ai-action/evaluate`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return Hg.parse(n)}async getReverseMappedDescription(e,t){let n=await this.sendRequest(`/${W}/web-agent/reverse-mapped-description`,{method:"POST",body:{...e,disableCache:t.disableCache,loggerTags:t.loggerTags},signal:t.abortSignal});return Sw.parse(n)}async getTextExtraction(e,t){let n={...e,disableCache:t.disableCache,loggerTags:t.loggerTags,agentConfigVersion:this.agentConfig?.["text-extraction"]},o=await this.sendRequest(`/${W}/web-agent/text-extraction`,{method:"POST",body:n,signal:t.abortSignal});return zg.parse(o)}async getPageSummary(e,t){let n={...e,disableCache:t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/web-agent/page-summary`,{method:"POST",body:n,signal:t.abortSignal});return tv.parse(o)}async getSmartWaitingDecision(e,t){let n={...e,disableCache:t.disableCache,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/web-agent/smart-waiting`,{method:"POST",body:n,signal:t.abortSignal});return rv.parse(o)}async getTestResultClassification(e,t){let n=await this.sendRequest(`/${W}/web-agent/result-classification`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Pg.parse(n)}async getExtractedKeywords(e,t){let n=await this.sendRequest(`/${W}/web-agent/extract-keywords`,{method:"POST",body:e,signal:t.abortSignal});return Fv.parse(n)}async getAutohealingProposal(e,t){let n=await this.sendRequest(`/${W}/web-agent/autoheal-section`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return XT.parse(n)}async getFailureRecoveryProposal(e,t){let n=await this.sendRequest(`/${W}/web-agent/failure-recovery`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return QT.parse(n)}async getFailureRecoveryPlan(e,t){let n=await this.sendRequest(`/${W}/web-agent/failure-recovery-plan`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return ZT.parse(n)}async getIframeRegex(e,t){let n=await this.sendRequest(`/${W}/web-agent/iframe-regex`,{method:"POST",body:e,signal:t.abortSignal});return sE.parse(n)}getVercelAnthropicModelFactory(e){let{sessionId:t,logger:n}=e;return Fp({baseUrl:this.baseUrl,apiKey:this.apiKey,loggerTags:ye(n),sessionId:t})}getVercelOpenAIModelFactory(e){let{sessionId:t,logger:n}=e;return XN({baseUrl:this.baseUrl,apiKey:this.apiKey,loggerTags:ye(n),sessionId:t})}};import{z as ub}from"zod";var Pr=class extends Vn{constructor(e){super({...e,mode:void 0})}getAppUrl(){return yc(this.baseUrl)}async getAuthInfo(){let e=await this.sendRequest(`/${W}/auth/check`,{method:"GET",retries:10,requestTimeoutMs:5e3,onFailedRequest:t=>{M.warn(`API key check failed: ${t.message}`)}});return Pw.parse(e)}async bulkGetRunStatus(e){let t=await this.sendRequest(`/${W}/runs/status`,{method:"POST",body:e,retries:3,requestTimeoutMs:1e4});return Cw.parse(t)}async getTestYAMLExport(e){let t=await this.sendRequest(`/${W}/tests/export`,{method:"POST",body:e,retries:3,requestTimeoutMs:3e4});return bw.parse(t)}async updateStepCaches(e,t){await this.sendRequest(`/${W}/cache`,{method:"PATCH",body:e,extraHeaders:t,retries:3,requestTimeoutMs:1e4,initialRetryDelayMs:3e3})}async getStepCacheForTest(e,t){let n=await this.sendRequest(`/${W}/cache`,{method:"POST",body:e,extraHeaders:t,retries:10,requestTimeoutMs:3e4,initialRetryDelayMs:3e3});return Tw.parse(n)}async getWebStepCacheMemoryTraces(e){let t=await this.sendRequest(`/${W}/cache/traces`,{method:"POST",body:e,retries:10,requestTimeoutMs:3e4,initialRetryDelayMs:3e3});return rf.parse(t)}async getMobileStepCacheMemoryTraces(e){let t=await this.sendRequest(`/${W}/mobile-cache/traces`,{method:"POST",body:e,retries:10,requestTimeoutMs:3e4,initialRetryDelayMs:3e3});return rf.parse(t)}async updateMobileStepCaches(e,t){await this.sendRequest(`/${W}/mobile-cache`,{method:"PATCH",body:e,extraHeaders:t,retries:3,requestTimeoutMs:1e4,initialRetryDelayMs:3e3})}async getMobileStepCacheForTest(e,t){let n=await this.sendRequest(`/${W}/mobile-cache`,{method:"POST",body:e,extraHeaders:t,retries:10,requestTimeoutMs:3e4,initialRetryDelayMs:3e3});return vw.parse(n)}async queueTests(e){let t=await this.sendRequest(`/${W}/tests/queue`,{method:"POST",body:e,retries:3,requestTimeoutMs:1e4});return yw.parse(t)}async uploadScreenshot(e){let t=await this.sendRequest(`/${W}/screenshots`,{method:"POST",body:e,retries:3,requestTimeoutMs:5e3});return Mw.parse(t)}async uploadOnDemandScreenshot(e){return await this.sendRequest(`/${W}/on-demand-screenshots`,{method:"POST",body:e,retries:3,requestTimeoutMs:5e3}),{apiServerUrl:`${this.baseUrl}/${W}/on-demand-screenshots/${e.id}`}}async fetchOnDemandScreenshot(e){let t={};return{data:await this.sendRequest(`/${W}/on-demand-screenshots/${encodeURIComponent(e)}`,{method:"GET",retries:3,requestTimeoutMs:5e3,responseType:"buffer",responseHeadersObject:t}),contentType:t["content-type"]??"image/jpeg"}}async getAllEnvironments(){let e=await this.sendRequest(`/${W}/environments`,{method:"GET",retries:3,requestTimeoutMs:5e3});return Iw.parse(e)}async acquireCacheLock(e,t){let n=await this.sendRequest(`/${W}/result-cache/lock`,{method:"POST",body:e,signal:t,retries:3,requestTimeoutMs:3e4});return Yw.parse(n)}async releaseCacheLock(e){await this.sendRequest(`/${W}/result-cache/lock`,{method:"DELETE",body:{key:e},retries:3,requestTimeoutMs:5e3})}async deleteCacheResult(e){await this.sendRequest(`/${W}/result-cache/entry`,{method:"DELETE",body:e,retries:3,requestTimeoutMs:5e3})}async setCacheResult(e){await this.sendRequest(`/${W}/result-cache/entry`,{method:"PATCH",body:e,retries:3,requestTimeoutMs:5e3})}async getCacheResult(e){try{return await this.sendRequest(`/${W}/result-cache/entry`,{method:"POST",body:e,retries:3,requestTimeoutMs:5e3})}catch(t){if(t instanceof Error&&t.message.includes("404"))return null;throw t}}async queueSuiteRuns(e){let t=await this.sendRequest(`/${W}/suites/queue`,{method:"POST",body:e,retries:3,requestTimeoutMs:5e3});return Ow.parse(t)}async bulkGetRunGroupStatus(e){let t={runGroupIds:e},n=await this.sendRequest(`/${W}/run-groups/status`,{method:"POST",body:t,retries:3,requestTimeoutMs:5e3});return yv.array().parse(n)}async uploadProposedSteps(e,t){try{await this.sendRequest(`/${W}/test-fragments/`,{method:"POST",body:e,retries:3,requestTimeoutMs:1e4})}catch(n){t.error({err:n},"Failed to upload proposed steps")}}async reportBillableEvents(e,t){try{await this.sendRequest(`/${W}/billing/events`,{method:"POST",body:t,retries:10,requestTimeoutMs:1e4})}catch(n){e.error({err:n},"Failed to report billable event")}}async fetchTestFragment(e){let t=await this.sendRequest(`/${W}/test-fragments/${e}`,{method:"GET",retries:3,requestTimeoutMs:1e4});return Lw.parse(t)}async patchTestFragment(e,t){await this.sendRequest(`/${W}/test-fragments/${e}`,{method:"PATCH",body:t,retries:3,requestTimeoutMs:1e4})}async getPastTestResults(e,t){let n=await this.sendRequest(`/${W}/results/tests/${e}`,{method:"POST",body:t,retries:3,requestTimeoutMs:1e4});return Nw.parse(n)}async generateTestResultsUploadUrl(){let e=await this.sendRequest(`/${W}/results/uploads`,{method:"POST",retries:3,requestTimeoutMs:1e4});return Dw.parse(e)}async startProcessingResultsUpload(e,t){let n=await this.sendRequest(`/${W}/results/uploads/${e}/process`,{method:"POST",body:t,retries:3,requestTimeoutMs:1e4});return kw.parse(n)}async fetchIconKnowledgeBase(e){try{let t=await this.sendRequest(`/${W}/knowledge-base/icons`,{method:"GET",retries:3,requestTimeoutMs:5e3});return Zw.parse(t)}catch(t){return e.error({err:t},"Failed to fetch icon knowledge base"),null}}async saveNewIcons(e,t){try{await this.sendRequest(`/${W}/knowledge-base/icons`,{method:"POST",body:e,retries:3,requestTimeoutMs: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(`/${W}/git/github/${e}/${t}/merge-base-commit?${i.toString()}`,{method:"GET",retries:3,requestTimeoutMs:1e4});return Sc.parse(a)}async getCommitFromGithub(e,t,n){let o=await this.sendRequest(`/${W}/git/github/${e}/${t}/commits/${n}`,{method:"GET",retries:3,requestTimeoutMs:1e4});return Sc.parse(o)}async getMergedBranchFromGithub(e,t,n,o){let i=encodeURIComponent(n),a=await this.sendRequest(`/${W}/git/github/${e}/${t}/${i}/${o}/merged-branch`,{method:"GET",retries:3,requestTimeoutMs:1e4});return af.parse(a)}async getMergeBaseCommitFromGitlab(e,t,n){let o=new URLSearchParams;o.set("base",t),o.set("head",n);let i=encodeURIComponent(e),a=await this.sendRequest(`/${W}/git/gitlab/${i}/merge-base-commit?${o.toString()}`,{method:"GET",retries:3,requestTimeoutMs:5e3});return Sc.parse(a)}async getCommitFromGitlab(e,t){let n=encodeURIComponent(e),o=await this.sendRequest(`/${W}/git/gitlab/${n}/commits/${t}`,{method:"GET",retries:3,requestTimeoutMs:1e4});return Sc.parse(o)}async getMergedBranchFromGitlab(e,t,n){let o=encodeURIComponent(t),i=encodeURIComponent(e),a=await this.sendRequest(`/${W}/git/gitlab/${i}/${o}/${n}/merged-branch`,{method:"GET",retries:3,requestTimeoutMs:1e4});return af.parse(a)}async getAgentConfig(){let e=await this.sendRequest(`/${W}/web-agent/agent-config`,{method:"GET",retries:3,requestTimeoutMs:5e3});return ub.record(ub.string(),ub.string()).parse(e)}async getQuarantinedTests(){let e=await this.sendRequest(`/${W}/quarantine`,{method:"GET"});return Fw.parse(e)}async quarantineTest(e,t,n){await this.sendRequest(`/${W}/quarantine`,{method:"POST",body:{testId:e.id,testName:e.name,reason:t,...n??{}},retries:3,requestTimeoutMs:1e4})}async unquarantineTest(e,t,n){await this.sendRequest(`/${W}/quarantine/${e.id}`,{method:"DELETE",body:{testName:e.name,reason:t,...n??{}},retries:3,requestTimeoutMs:1e4})}async createAndroidEmulator(e){let t=await this.sendRequest(`/${W}/limbar/android`,{method:"POST",retries:3,body:e,requestTimeoutMs:9e4,initialRetryDelayMs:5e3,maxRetryDelayMs:15e3});return Uw.parse(t)}async extendAndroidEmulatorTtl(e){try{await this.sendRequest(`/${W}/limbar/android/${e}/keepalive`,{method:"POST",retries:3,requestTimeoutMs:15e3})}catch{}}async generateAndroidAssetUrls({channel:e,tag:t,md5:n}){let o={channel:e,tag:t,md5:n},i=await this.sendRequest(`/${W}/limbar/android/upload-url`,{method:"POST",retries:3,body:o,requestTimeoutMs:15e3,logResponse:!0});return zw.parse(i)}async deleteAndroidEmulator(e){await this.sendRequest(`/${W}/limbar/android/${e}`,{method:"DELETE",retries:3,requestTimeoutMs:3e4})}async getAndroidAssets(){let e=await this.sendRequest(`/${W}/limbar/assets`,{method:"GET",retries:3,requestTimeoutMs:1e4});return Hw.parse(e)}async getLimbarAssetDownloadUrl(e,t){let n=await this.sendRequest(`/${W}/limbar/assets/${e}/${t}/download-url`,{method:"GET",retries:2,requestTimeoutMs:3e4});return Gw.parse(n)}async deleteAndroidAsset(e,t){await this.sendRequest(`/${W}/limbar/assets/${e}/${t}`,{method:"DELETE",retries:3,requestTimeoutMs:1e4})}async createIosEmulator(e){let t=await this.sendRequest(`/${W}/limbar/ios`,{method:"POST",retries:3,body:e,requestTimeoutMs:9e4,initialRetryDelayMs:5e3,maxRetryDelayMs:15e3});return Bw.parse(t)}async extendIosEmulatorTtl(e){try{await this.sendRequest(`/${W}/limbar/ios/${e}/keepalive`,{method:"POST",retries:3,requestTimeoutMs:15e3})}catch{}}async deleteIosEmulator(e){await this.sendRequest(`/${W}/limbar/ios/${e}`,{method:"DELETE",retries:3,requestTimeoutMs:3e4})}async generateMobileLogcatUploadUrl(e){let t=await this.sendRequest(`/${W}/logcat/mobile/upload`,{method:"POST",body:e,retries:3,requestTimeoutMs:1e4});return IA.parse(t)}};async function db(r){let e=process.versions.node,t=parseInt(e.split(".")[0]);(isNaN(t)||t<18)&&(M.error(`Node.js version 20 or higher is required to run the CLI. Detected: ${process.versions.node}.`),process.exit(1)),M.debug(`Identified node version ${e}`);let n=await r.client.getAuthInfo();return M.debug("Got auth info from API"),n}var Up=class{apiClient;constructor(e){this.apiClient=e}async reportBillableEvents(e,t){await this.apiClient.reportBillableEvents(e,t)}};var Ys=class extends Vn{generator;constructor(e,t){super(e),this.generator=t}async runTemplateMatching(e,t={}){let n=await this.sendRequest(`/${W}/web-agent/template-matching`,{method:"POST",body:e,signal:t?.signal});return lE.parse(n)}async constructIframeRegex(e,t={}){return this.generator.getIframeRegex(e,{abortSignal:t.signal})}};var Xs=class{constructor(e,t){this.client=e;this.orgId=t}getApiServerUrl(){return this.client.baseUrl}getAppServerUrl(){let e=this.getApiServerUrl();return yc(e)}async acquireCacheLock(e,t){return this.client.acquireCacheLock(e,t)}async createOnDemandScreenshot(e,t,n){let{apiServerUrl:o}=await this.client.uploadOnDemandScreenshot({id:e,screenshot:t.toString("base64"),contentType:n});return{apiServerUrl:o,appServerUrl:`${this.getAppServerUrl()}/api/on-demand-screenshots/${e}`,universalHandle:{id:e,contentType:n}}}async fetchOnDemandScreenshot(e){return this.client.fetchOnDemandScreenshot(e.id)}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){return this.client.fetchIconKnowledgeBase(e)}saveNewIcons(e,t){return this.client.saveNewIcons(e,t)}};import{Faker as $X,en as qX}from"@faker-js/faker";var Js="v1",Zs=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 $X({locale:qX}),this.fakerInstance.seed(e.fakerSeed))}async sendAiGenerate(e){let t=typeof e=="string"?{input:e}:e;return this.httpClient.sendRequest(`/${Js}/tools/ai/generate`,{method:"POST",body:t}).catch(n=>{throw n instanceof En?new Error(n.rawError):new Error(`Failed to send AI generation: ${n.message}`)})}async sendSms(e){return this.httpClient.sendRequest(`/${Js}/tools/sms/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof En?new Error(t.rawError):new Error(`Failed to send sms: ${t.message}`)})}async fetchLatestSms(e){return this.httpClient.sendRequest(`/${Js}/tools/sms/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof En?new Error(t.rawError):t})}async sendEmail(e){return this.httpClient.sendRequest(`/${Js}/tools/email/send`,{method:"POST",body:e}).then(()=>{}).catch(t=>{throw t instanceof En?new Error(t.rawError):new Error(`Failed to send email: ${t.message}`)})}async fetchAllEmails(e){return this.httpClient.sendRequest(`/${Js}/tools/email/fetchAll`,{method:"POST",body:e}).catch(t=>{throw t instanceof En?new Error(t.rawError):new Error(`Failed to fetch all emails: ${t.message}`)})}async fetchLatestEmail(e){return this.httpClient.sendRequest(`/${Js}/tools/email/fetchLatest`,{method:"POST",body:e}).catch(t=>{throw t instanceof En?new Error(t.rawError):new Error(`Failed to fetch latest emails: ${t.message}`)})}};function JN(r,e,t){return fetch(r,{method:"PUT",body:t,headers:{"Content-Type":e}})}var Bp=class{constructor(e){this.client=e}async uploadResultsArchive(e,t){let{uploadUrl:n,id:o}=await this.client.generateTestResultsUploadUrl(),i=await JN(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}};var Qs=class extends Vn{constructor(e){super(e)}async getAndroidElementLocation(e,t){let n={...e,disableCache:t.disableCache,useMemory:t.useMemory,agentConfigVersion:t.agentConfigVersion,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/mobile-agent/locate-element`,{method:"POST",body:n,signal:t.abortSignal});return Ih.parse(o)}async evaluateAndroidAssertion(e,t){let n={...e,disableCache:t.disableCache,useMemory:t.useMemory,agentConfigVersion:t.agentConfigVersion,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/mobile-agent/assertion`,{method:"POST",body:n,signal:t.abortSignal});return Oh.parse(o)}async getAndroidFailureRecoveryPlan(e,t){let n=await this.sendRequest(`/${W}/mobile-agent/failure-recovery-plan`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Lh.parse(n)}async getIosElementLocation(e,t){let n={...e,disableCache:t.disableCache,useMemory:t.useMemory,agentConfigVersion:t.agentConfigVersion,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/ios-agent/locate-element`,{method:"POST",body:n,signal:t.abortSignal});return Ih.parse(o)}async evaluateIosAssertion(e,t){let n={...e,disableCache:t.disableCache,useMemory:t.useMemory,agentConfigVersion:t.agentConfigVersion,loggerTags:t.loggerTags},o=await this.sendRequest(`/${W}/ios-agent/assertion`,{method:"POST",body:n,signal:t.abortSignal});return Oh.parse(o)}async getIosFailureRecoveryPlan(e,t){let n=await this.sendRequest(`/${W}/ios-agent/failure-recovery-plan`,{method:"POST",body:{...e,loggerTags:t.loggerTags},signal:t.abortSignal});return Lh.parse(n)}getVercelAnthropicModelFactory(e){let{logger:t,sessionId:n}=e;return Fp({baseUrl:this.baseUrl,apiKey:this.apiKey,sessionId:n,loggerTags:ye(t)})}};function mi({logger:r,orgId:e,client:t,gitMetadata:n,regenerateCache:o,alwaysSaveCache:i,noCache:a}){return a?new _d:new mb(r,e,t,n,{alwaysSaveCache:i,regenerateCache:o})}var mb=class{constructor(e,t,n,o,i){this.orgId=t;this.client=n;let{regenerateCache:a,alwaysSaveCache:s}=i,{gitBranchName:c,gitProtectedBranches:l}=o;this.cacheHeaders=fc(o),this.readCaches=!a,e.info({options:i,gitBranchName:c,gitProtectedBranches:l},"Cache storage initialization options");let u=c&&l.includes(c);s||!u?this.writeCaches=!0:this.writeCaches=!1}cacheHeaders;readCaches;writeCaches;async saveEntries({entries:e,testId:t,logger:n}){if(!this.writeCaches){n.debug("Skipping cache storage because branch is protected");return}try{await this.client.updateMobileStepCaches({entries:e,testId:t},this.cacheHeaders)}catch(o){n.warn({err:o},"Failed to save mobile step cache entries, continuing...")}}async resolveEntries(e){if(!this.readCaches){e.logger.debug("Skipping cache resolution because of regenerate flag");return}let t=await this.client.getMobileStepCacheForTest({testId:e.testId},this.cacheHeaders),{steps:n}=e.stepLists;n&&PS({steps:n,stepCacheEntries:t,logger:e.logger})}async populateCacheForRun(e){if(!this.readCaches){e.logger.debug("Skipping cache resolution because of regenerate flag");return}let{steps:t}=e.stepLists;if(e.skipFetchingCacheFromStorage||await this.resolveEntries(e),!this.writeCaches){e.logger.info("Skipping mobile cache last used at update because branch is protected");return}let{cachesToSave:n}=await Bn({platform:e.platform,steps:t,cacheCreationParams:{testId:e.testId,orgId:this.orgId}});try{await this.client.updateMobileStepCaches({entries:n,testId:e.testId},this.cacheHeaders)}catch(o){e.logger.warn({err:o},"Failed to update mobile step cache entries, continuing...")}}async getCacheKeyForStep(e){let t=await this.client.getMobileStepCacheForTest({testId:e.testId},this.cacheHeaders);return IS({step:e.step,stepCacheEntries:t,parentStepIdChain:e.parentStepIdChain,logger:e.logger,options:{ignoreCacheValueOnStep:!0}})}};import zp from"path";function KX(r){let e=new ZN,t=zp.join(r,"metadata.json"),n=ls.parse(JSON.parse(pb.readFileSync(t,"utf-8")));e.addLocalFile(t);for(let o of pb.readdirSync(zp.join(r,"runs"))){if(!o.endsWith(".zip"))continue;let i=o.replace(/\.zip$/,""),a=new ZN(zp.join(r,"runs",o));for(let s of a.getEntries())s.isDirectory||e.addFile(zp.join("runs",i,s.entryName),s.getData())}return{runGroupId:n.id,buffer:e.toBuffer()}}async function Hp(r){let{client:e,consoleLogger:t,resultsPath:n}=r;if(!pb.existsSync(n)){t.warn("Results path does not exist, skipping upload.");return}let o=new Bp(e);try{let{runGroupId:i,buffer:a}=KX(n),s=await o.uploadResultsArchive(i,a),c=`${e.getAppUrl()}/run-groups/${s}`;t.success(`Successfully uploaded test results. Once processed, your results can be found at ${c}`);return}catch(i){let a;i instanceof Error?a=i.message:typeof i=="string"?a=i:a="Unknown error",t.error(`Failed to upload test results: ${a}.`);return}}import YX from"adm-zip";import lr from"fs";import dn from"path";var Su=class r{constructor(e){this.filePath=e;lr.rmSync(this.filePath,{recursive:!0,force:!0}),lr.mkdirSync(this.filePath,{recursive:!0})}children=[];streams=[];close(){for(let e of this.children)e.close();for(let e of this.streams)e.end()}cd(e){let t=new r(dn.join(this.filePath,e));return this.children.push(t),t}cwd(){return this.filePath}mkdir(e){lr.mkdirSync(dn.join(this.filePath,e),{recursive:!0})}readFile(e){let t=dn.join(this.filePath,e);if(lr.existsSync(t))return lr.readFileSync(t)}storeFile(e){let{name:t,contents:n}=e,o=dn.join(this.filePath,t);try{lr.writeFileSync(o,n)}catch{}}createFileStream(e){let t=dn.join(this.filePath,e),n=lr.createWriteStream(t);return this.streams.push(n),n}createRunArchive(e){let t=new gb(dn.join(this.filePath,"runs"),e);return this.children.push(t),t}},gb=class{children=[];tempPath;finalPath;constructor(e,t){this.tempPath=dn.join(e,`temp-storage-${t}`),this.finalPath=dn.join(e,`${t}.zip`),lr.rmSync(this.tempPath,{recursive:!0,force:!0}),lr.rmSync(this.finalPath,{recursive:!0,force:!0}),lr.mkdirSync(this.tempPath,{recursive:!0})}readFile(e){let t=dn.join(this.tempPath,e);if(lr.existsSync(t))return lr.readFileSync(t)}mkdir(e){lr.mkdirSync(dn.join(this.tempPath,e),{recursive:!0})}cd(e){let t=new Su(dn.join(this.tempPath,e));return this.children.push(t),t}cwd(){return this.tempPath}storeFile(e){let{name:t,contents:n}=e,o=dn.join(this.tempPath,t);lr.writeFileSync(o,n)}close(){for(let n of this.children)n.close();let e=new YX;e.addLocalFolder(this.tempPath,void 0,n=>n!==".DS_Store");let t=e.toBuffer();lr.writeFileSync(this.finalPath,t),lr.rmSync(this.tempPath,{recursive:!0,force:!0})}};import XX from"adm-zip";import{randomUUID as JX}from"crypto";import Ht from"fs";import tr from"path";function r0(r){try{return Ht.existsSync(r)?JSON.parse(Ht.readFileSync(r,"utf-8")):void 0}catch{return}}function QN(r){return Ht.existsSync(r)?Ht.readFileSync(r,"utf-8").split(`
4607
- `).map(t=>t.trim()).filter(t=>t.length>0):[]}function ZX(r,e){let t=r.attemptIdToAttemptNumber.get(e);if(t)return tr.join(r.inflatedPath,"attempts",t);let n=tr.join(r.inflatedPath,"attempts");if(!Ht.existsSync(n))return;let o=Ht.readdirSync(n,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>i.name);for(let i of o){let a=tr.join(n,i,"metadata.json"),s=r0(a);if(typeof s!="object"||s===null)continue;let c=s.id;if(typeof c=="string"&&c===e)return r.attemptIdToAttemptNumber.set(e,i),tr.join(n,i)}}function e0(r,e,t){let n=tr.join(r,"attempts");if(!Ht.existsSync(n))return;let o=Ht.readdirSync(n,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>i.name);for(let i of o){let a=tr.join(n,i,"assets",`${e}.${t}`);if(Ht.existsSync(a))return a}}var Gp=class{constructor(e,t,n){this.outputDir=e;this.runId=t;this.runAttemptId=n;this.runsDir=tr.join(e,"runs"),this.zipPath=tr.join(this.runsDir,`${t}.zip`)}inflatedByRunId=new Map;zipPath;runsDir;ensureInflatedRun(e){let t=this.inflatedByRunId.get(e);if(t)return t;if(e!==this.runId||!Ht.existsSync(this.zipPath))return;let n=tr.join(this.runsDir,`temp-unzipped-${e}-${JX()}`);Ht.mkdirSync(n,{recursive:!0}),new XX(this.zipPath).extractAllTo(n,!0);let i={runId:e,zipPath:this.zipPath,inflatedPath:n,attemptIdToAttemptNumber:new Map};return this.inflatedByRunId.set(e,i),i}close(){for(let e of this.inflatedByRunId.values())Ht.rmSync(e.inflatedPath,{recursive:!0,force:!0});this.inflatedByRunId.clear()}getAttemptDir(){let e=this.ensureInflatedRun(this.runId);if(e)return ZX(e,this.runAttemptId)}listVideoAssetPaths(){let e=this.getAttemptDir();if(!e)return[];let t=tr.join(e,"assets");return Ht.existsSync(t)?Ht.readdirSync(t,{withFileTypes:!0}).filter(o=>o.isFile()).map(o=>tr.join(t,o.name)).filter(o=>{let i=tr.extname(o).toLowerCase();return i===".webm"||i===".mp4"}):[]}readAttemptAssetText(e,t){let n=this.getAttemptDir();if(!n)return;let o=tr.join(n,"assets",`${e}.${t}`);if(Ht.existsSync(o))try{return Ht.readFileSync(o,"utf-8")}catch{return}}async getConsoleLogsForRunAttempt(e,t,n){if(t!==this.runId||n!==this.runAttemptId)return;let o=this.getAttemptDir();if(!o)return;let i=r0(tr.join(o,"console.json")),a=Yh.safeParse(i);return a.success?a.data:void 0}async getNetworkLogsForRunAttempt(e,t,n){if(t!==this.runId||n!==this.runAttemptId)return;let o=this.getAttemptDir();if(!o)return;let i=tr.join(o,"assets","har-pages.log"),a=tr.join(o,"assets","har-entries.log"),s={};for(let u of QN(i)){let d=dc.safeParse(t0(u));d.success&&(s[d.data.id]=d.data)}let c={},l=QN(a);for(let u=0;u<l.length;u++){let d=l[u],p=mc.safeParse(t0(d));if(!p.success)continue;let m=`${p.data.startedDateTime}-${u}`;c[m]=p.data}if(Object.keys(c).length!==0)return Jh(s,c)}async getHtmlSnapshot(e,t){let n=this.readAttemptAssetText(t,"html");if(n)return n;let o=this.ensureInflatedRun(this.runId);if(!o)return;let i=e0(o.inflatedPath,t,"html");if(i)try{return Ht.readFileSync(i,"utf-8")}catch{return}}async getA11yTreeSnapshot(e,t){let n=this.readAttemptAssetText(t,"xml");if(n)return n;let o=this.ensureInflatedRun(this.runId);if(!o)return;let i=e0(o.inflatedPath,t,"xml");if(i)try{return Ht.readFileSync(i,"utf-8")}catch{return}}async getScreenshot(e,t){if(!this.ensureInflatedRun(this.runId))return;let o=this.getAttemptDir(),i=o?tr.join(o,"assets",`${t}.jpeg`):void 0;if(i)try{return Ht.readFileSync(i)}catch{return}}};function t0(r){try{return JSON.parse(r)}catch{return}}import ba from"fs";import Wp from"fs";import s3 from"open";import fb from"path";import a3 from"express";import QX from"adm-zip";import{Router as e3}from"express";import el from"fs";import yu from"path";function n0(r){let e=e3(),t=yu.join(r,"runs");return e.get("/",async(n,o)=>{try{let i=t3(r);if(!i){o.status(404).json({error:"No run group found"});return}if(!el.existsSync(t)){o.status(404).json({error:"No runs found for run group"});return}let a=r3(t,i),s={...i,id:i.id??"local-run-group",createdAt:i.startedAt,runs:a};o.status(200).json(s)}catch(i){o.status(500).json({error:`Error loading run group: ${i.message}`})}}),e}function t3(r){let e=yu.join(r,"metadata.json");if(!el.existsSync(e))return M.error("Run group metadata file not found"),null;try{let t=el.readFileSync(e,"utf-8");return ls.parse(JSON.parse(t))}catch(t){return M.error({err:t},"Error reading run group metadata"),null}}function r3(r,e){let t=el.readdirSync(r).filter(o=>o.endsWith(".zip")).sort((o,i)=>{let a=el.statSync(yu.join(r,o));return el.statSync(yu.join(r,i)).mtime.getTime()-a.mtime.getTime()}),n=[];for(let o of t){let i=yu.join(r,o),a=o.replace(/\.zip$/i,"");n.push(n3(i,a,e))}return n}function n3(r,e,t){let o=new QX(r).getEntry("metadata.json");if(!o)throw new Error(`No entry found for file ${r}/metadata.json`);try{let i=o.getData().toString("utf-8"),a=JSON.parse(i),s=uR.parse(a);return uP(s,e,{runGroupMetadata:t,runAttempts:[],organizationId:"local"})}catch(i){throw M.error({err:i,zipPath:r},"Error parsing metadata.json for run"),new Error(`Error parsing metadata.json for run ${r}`)}}import{Router as o3}from"express";import o0 from"fs";import jp from"path";function i0(r){let e=o3(),t=jp.join(r,"runs");return e.get("/:filename",(n,o)=>{let i=n.params.filename;if(!i||!i.endsWith(".zip")){o.status(404).send("Not found");return}let a=jp.join(t,i),s=jp.resolve(a),c=jp.resolve(t);if(!s.startsWith(c)){o.status(403).send("Forbidden");return}if(!o0.existsSync(a)){o.status(404).send("File not found");return}try{o.setHeader("Content-Type","application/zip"),o.setHeader("Content-Disposition",`attachment; filename="${i}"`);let l=o0.readFileSync(a);o.send(l)}catch(l){o.status(500).send(`Error reading file: ${l.message}`)}}),e}import{Router as i3}from"express";import hb from"fs";import tl from"path";function a0(r){let e=i3();return e.get("*",(t,n)=>{let o=t.path==="/"?tl.join(r,"index.html"):tl.join(r,t.path),i=tl.resolve(o),a=tl.resolve(r);if(!i.startsWith(a)){n.status(403).send("Forbidden");return}if(!hb.existsSync(o)&&(o=tl.join(r,"index.html"),!hb.existsSync(o))){n.status(404).send("File not found");return}try{let s=tl.extname(o).toLowerCase(),c=pc[s]||"application/octet-stream";n.setHeader("Content-Type",c);let l=hb.readFileSync(o);n.send(l)}catch(s){n.status(500).send(`Error reading file: ${s.message}`)}}),e}async function s0(r,e,t){let n=e??await zo(Ed,"local-run-viewer-server"),o=a3();return o.use((i,a,s)=>{a.setHeader("Access-Control-Allow-Origin","*"),a.setHeader("Cache-Control","no-cache"),s()}),o.use("/api/runs",i0(r)),o.use("/api/run-group",n0(r)),t&&o.use("/",a0(t)),new Promise((i,a)=>{let s=o.listen(n,()=>{let c=`http://localhost:${n}`;i({port:n,url:c,stop:()=>{s.close()}})});s.on("error",c=>{a(c)})})}async function Sb(r){let{staticDir:e,resultsPath:t,runId:n,port:o}=r,i=fb.resolve(t),a=fb.join(i,"runs"),s;if(n){s=`${n.replace(/\.zip$/i,"")}.zip`;let l=fb.join(a,s);if(!Wp.existsSync(l)){let u=[];if(Wp.existsSync(a))for(let d of Wp.readdirSync(a))d.endsWith(".zip")&&u.push(d.replace(/\.zip$/i,""));M.error(`Run not found: ${s} in ${a}`),u.length>0&&M.error(`Available runs: ${u.join(", ")}`),process.exit(1)}}Wp.existsSync(e)||(M.error(`Static frontend files not found at ${e}. Please ensure the CLI is properly built.`),process.exit(1));try{let l=(await s0(i,o,e)).url;M.info(`Run viewer running at ${l}`);let u=new URL(l);s&&u.searchParams.set("zipUrl",`${l}/api/runs/${s}`),await s3(u.toString())}catch(c){M.error(`Failed to start run viewer: ${c.message}`),process.exit(1)}}import tD from"body-parser";import EJ from"cors";import TJ from"dedent";import{Router as p3}from"express";import Vp from"fs";import l3 from"path";var c3=new xm(30,60*1e3),Tb="https://api.momentic.ai",bb,c0,u0=r=>{Tb=r},vb=()=>Tb;var d0=r=>{c0=r},m0=()=>c0,Ir=()=>bb;var rl,Eb,l0,p0=async r=>{if(bb&&rl&&l0)return rl;let e=new Pr({baseUrl:Tb,apiKey:r,logger:M});bb=e;try{let t=await e.getAuthInfo();return rl=t.orgId,Eb=t.userId,l0=r,rl}catch(t){throw new Error(`Error checking API key against server: ${t}`)}},Yn=()=>{if(!rl)throw new Error("Your organization ID is invalid.");return rl},$p=()=>{if(!Eb)throw new Error("Your user ID is invalid.");return Eb};var Ab,yb,g0=(r,e)=>{Ab=r,yb?.abort(),yb=new AbortController;let t=yb.signal,n=[r.configFilePath];r.config.environments?.forEach(o=>{if(!o.envFile)return;let i=l3.resolve(r.rootDir,o.envFile);try{if(Vp.lstatSync(i).isSymbolicLink())return;Vp.existsSync(i)&&n.push(i)}catch(a){M.warn({err:a},`Failed to check if env file ${i} exists`)}});try{u3({filesToWatch:n,revalidator:e,signal:t,project:r})}catch(o){M.error({err:o},"Failed to start config file watchers")}},We=()=>Ab;function u3({filesToWatch:r,revalidator:e,signal:t,project:n}){M.debug("Starting watch on the following files:"),r.forEach(o=>{M.debug(`- ${o}`)}),r.forEach(o=>{let i=async(s,c)=>{s.mtime.getTime()!==c.mtime.getTime()&&(c3.increment("setLocalProject")&&M.warn(`A file change under the ${n.rootDir} directory has caused Momentic to reload its configuration more than 30 times in the last minute. Rapid changes to files may indicate your momentic.config.yaml 'include' glob is incorrect. Please ensure temporary, library, and auto-generated files are not included in Momentic's context.`),Ab=await Promise.resolve(e(n.configFilePath)))};Vp.watchFile(o,{persistent:!1},i);let a=()=>{Vp.unwatchFile(o,i),t.removeEventListener("abort",a)};t.addEventListener("abort",a),process.once("SIGUSR2",()=>{a(),process.kill(process.pid,"SIGUSR2")})})}function ke(r){return function(...e){let t=e[e.length-1],n=r(...e);Promise.resolve(n).catch(t)}}import{hostname as d3}from"os";var m3="0.33.0",fa=ds({app:"desktop-server",hostname:d3(),disableConsoleLogs:!0}).child({cliVersion:m3});(async()=>{try{let r=await du(fa);r.gitBranchName&&fa.addBinding("branch",r.gitBranchName)}catch{}})();var h0=p3();h0.get("/",async(r,e)=>{let t=We(),n=Ir();if(!n){e.status(500).json({message:"API client not initialized"});return}let o=await sn(fa,n,t),i=o?.gitProtectedBranches&&o?.gitBranchName&&o.gitProtectedBranches.includes(o.gitBranchName),{noCache:a,alwaysSaveCache:s}=m0(),c=!a&&(s||!i);e.status(200).json({saveCaches:c,checkedOutBranch:o?.gitBranchName})});var wb=h0;import{Router as g3}from"express";import Ar from"fs";import{globSync as h3}from"glob";import Kt from"path";var Eu=g3();function bu(r){let e=We(),t=Kt.dirname(e.configFilePath);return Kt.join(t,...r)}function f3(r){let e=We(),t=Kt.dirname(e.configFilePath),n=Kt.relative(t,r);return n?n.split(Kt.sep):[]}function S3(r,e){let t=Ar.statSync(r),n=f3(r);return Zh.parse({name:e,absolutePath:r,relativePath:n.join(Kt.sep),pathSegments:n,isDirectory:t.isDirectory(),size:t.size,createdAt:t.birthtime,modifiedAt:t.mtime,accessedAt:t.atime})}Eu.post("/",ke(async(r,e,t)=>{let n;try{n=jA.parse(r.body).pathSegments}catch(d){e.status(400).json({error:`Failed to parse folder read body: ${d}`});return}let o=bu(n);if(!Ar.existsSync(o)){e.status(404).json({error:`Path not found: ${n.join(Kt.sep)}`});return}if(!Ar.statSync(o).isDirectory()){e.status(400).json({error:`Path is not a directory: ${n.join(Kt.sep)}`});return}let a=We(),s=Array.from(a.config.exclude??[]).concat(bd),l=h3("*",{absolute:!1,cwd:o,ignore:s,dotRelative:!1,maxDepth:1,nodir:!1}).map(d=>{let p=Kt.join(o,d);return S3(p,d)}),u={absolutePath:o,pathSegments:n,contents:l};e.status(200).json(u)}));Eu.put("/",ke(async(r,e,t)=>{let n;try{n=WA.parse(r.body).pathSegments}catch(a){e.status(400).json({error:`Failed to parse folder create body: ${a}`});return}let o=bu(n);if(Ar.existsSync(o)){e.status(200).json({success:!0,message:`Folder already exists: ${n.join(Kt.sep)}`,pathSegments:n});return}Ar.mkdirSync(o,{recursive:!0});let i={success:!0,message:`Folder created: ${n.join(Kt.sep)}`,pathSegments:n};e.status(201).json(i)}));Eu.patch("/",ke(async(r,e,t)=>{let n,o;try{let l=VA.parse(r.body);n=l.pathSegments,o=l.newPathSegments}catch(l){e.status(400).json({error:`Failed to parse folder update body: ${l}`});return}let i=bu(n),a=bu(o);if(!Ar.existsSync(i)){e.status(400).json({error:`Folder not found: ${n.join(Kt.sep)}`});return}if(Ar.existsSync(a)){e.status(400).json({error:`Destination already exists: ${o.join(Kt.sep)}`});return}let s=Kt.dirname(a);Ar.existsSync(s)||Ar.mkdirSync(s,{recursive:!0}),Ar.renameSync(i,a);let c={success:!0,message:`Folder moved from ${n.join(Kt.sep)} to ${o.join(Kt.sep)}`,pathSegments:o};e.status(200).json(c)}));Eu.delete("/",ke(async(r,e,t)=>{let n,o=!0;try{let c=$A.parse(r.body);n=c.pathSegments,o=c.recursive??!0}catch(c){e.status(400).json({error:`Failed to parse folder delete body: ${c}`});return}let i=bu(n);if(!Ar.existsSync(i)){e.status(200).json({success:!0,message:`Folder not found: ${n.join(Kt.sep)}`,pathSegments:n});return}if(!Ar.statSync(i).isDirectory()){e.status(400).json({error:`Path is not a directory: ${n.join(Kt.sep)}`});return}if(o)Ar.rmSync(i,{recursive:!0,force:!0});else{if(Ar.readdirSync(i).length>0){e.status(409).json({error:`Cannot delete non-empty directory without recursive flag: ${n.join("/")}`});return}Ar.rmdirSync(i)}let s={success:!0,message:`Folder deleted: ${n.join("/")}`,pathSegments:n};e.status(200).json(s)}));var Rb=Eu;import{Router as y3}from"express";var f0=y3();f0.get("/",async(r,e)=>{let t=We(),n=Ir();if(!n){e.status(500).json({message:"API client not initialized"});return}let o=await sn(fa,n,t);e.status(200).json(o)});var Cb=f0;import vJ from"events";import rD,{Router as AJ}from"express";import wJ from"http";import{cloneDeep as z3}from"lodash-es";import{randomUUID as b3}from"crypto";var E3=3;async function S0(r){let{results:e,fixtures:t,work:n}=r,{logger:o}=t,i=e[e.length-1],a=v3(i,n);if(a)return o.info({failedResult:i,isNotEligible:a},"Skipping failure recovery because of ineligible failure"),{type:"NOT_ELIGIBLE",message:`The failed step is not eligible for failure recovery: ${a}`};o.info({failedResult:i},"Attempting failure recovery"),n.state.failureRecoveryAttempts=(n.state.failureRecoveryAttempts??0)+1;try{return await T3(r)}catch(s){return o.warn({err:s},"Error during failure recovery attempt, continuing..."),null}}async function T3(r){let{fixtures:e,results:t,failedStep:n,nextSteps:o,stepTracer:i,work:a}=r,{controller:s,logger:c}=e,l=i.parentTracer,{testMetadata:u}=r.inputs;if(!t.length)throw new Error("Attempted failure recovery with no failed results");let d=await s.getScreenshotPngString(),p=await s.getEmulatorDomState(),{results:m}=await aP(c,l,t,{numStepsWithScreenshots:8,addIndices:!0,includeBeforeScreenshots:!1}),g=o.map(R=>ea(R)),h=u.description.trim(),f=u?.settings?.ai?.failureRecoveryInstructions?.trim()||void 0,{scenario:y,thoughts:E,instructions:b}=await s.getMobileFailureRecoveryPlan({currentScreenshot:d,failedResults:m,currentScreenXml:p,nextStepsSerialized:g,testDescription:h,customInstructions:f});if(y!=="RECOVERABLE")return c.info({scenario:y,thoughts:E,instructions:b},"Failure recovery is not applicable"),{type:"NOT_ELIGIBLE",message:`Momentic's failure recovery agent determined that this failure is not eligible for recovery: ${E}`};if(!b)throw new Error("Momentic's failure recovery agent did not provide any instructions for recovery");let x={id:b3(),type:"MOBILE_AI_ACTION_STEP",text:b},P,O=a.state.failureRecoveryDisabled;O||(a.state.failureRecoveryDisabled=!0),c.info("executing mobile step list");try{P=await r.executeMobileStepList({...r,fixtures:{...r.fixtures},listParams:{steps:[x,n],containerName:"AI-recovered step list",tracer:l}})}finally{O||(a.state.failureRecoveryDisabled=O)}let T=P.results[0];if(T&&T.type==="MOBILE_AI_ACTION_STEP")if(jS({results:P.results,onPresetAction:R=>{R.aiSuggested=!0},onSimpleStepContainer:R=>{R.aiSuggested=!0}}),P.status==="SUCCESS"){let R=`The following steps were automatically executed by the failure recovery agent. Analysis: ${E}`;return T.message=R,nt.increment("test_event",1,["name:failure_recovery_success","platform:native",`orgId:${r.inputs.orgId}`]),c.info({thoughts:E},"Failure recovery succeeded"),{type:"ATTEMPTED",status:"SUCCESS",result:P,message:R}}else{nt.increment("test_event",1,["name:failure_recovery_failure","platform:native",`orgId:${r.inputs.orgId}`]);let R=`The following steps were unsuccessfully attempted by the failure recovery agent. Analysis: ${E}`;return T.message=R,c.info({thoughts:E},"Failure recovery failed"),{type:"ATTEMPTED",status:"FAILED",result:P,message:R}}return null}function v3(r,e){if(!r)return"There is no failed result";if(r.type!=="MOBILE_PRESET_STEP")return"The failed step is not a preset action";let t=r.message;return t?t.includes("AbortError:")?"The user aborted the test":yT.some(n=>t.includes(n))?"The failed step is an irrecoverable configuration error":(e.state.failureRecoveryAttempts??0)>E3?"Too many failure recovery attempts":"":"There is no error message available on the failed step"}async function y0(r){let e=Date.now(),t=r.fixtures.controller;try{return await A3(r)}catch(n){let o=t.isAborted()||n instanceof DOMException&&n.name==="AbortError";return{...r.moduleParams.step,steps:[],type:"MOBILE_MODULE_STEP",startTime:e,endTime:Date.now(),status:o?"CANCELLED":"FAILED",message:o?"Step cancelled.":`${n}`}}}async function A3({moduleParams:r,...e}){let t=Date.now(),{step:n,stepTracer:o,executeMobileStepList:i}=r,a=await w3({step:n,params:e}),s={};Object.entries(a).forEach(([p,m])=>{s[p]=JSON.stringify(m)});let c={...n,type:"MOBILE_MODULE_STEP",inputs:s,startTime:t,steps:[],endTime:Date.now(),status:"SUCCESS"},l=await o.startSubSteps(),{status:u,results:d}=await i({...e,listParams:{steps:n.steps,containerName:`module ('${n.name}')`,tracer:l}});return c.steps=d,c.status=u,c.endTime=Date.now(),oP({result:c,...nP(d)}),c}async function w3({step:r,params:e}){let t={},{logger:n,controller:o}=e.fixtures;for(let i of r.parameters?.parameterNames??[]){let a=r.inputs?.[i]??r.parameters?.defaultParameters?.[i];if(!a){n.warn({k:i},"No value found for parameter in module");continue}t[i]=await Fn({orgId:e.inputs.orgId,code:a,fragment:!0,logger:n,context:o.context,localTools:o.localCodeEvalTools})}return t}import{randomUUID as b0}from"crypto";import{diff as R3}from"deep-object-diff";import{cloneDeep as C3}from"lodash-es";async function E0({fixtures:r,step:e,inputs:t,stepTracer:n,work:o}){let i=Date.now(),{logger:a,controller:s}=r,c,l="",u,d=s.emulatorSettings?.disableXmlSnapshots??!1;if(!t.interactive){if(o.lastScreenshot)c=o.lastScreenshot.screenshot,l=o.lastScreenshot.snapshotId;else{l=b0();try{c=Buffer.from(await s.getScreenshotBase64(),"base64")}catch(h){a.warn({err:h},"Failed to take before screenshot")}}if(!d)if(o.lastScreenXml)u=o.lastScreenXml.screenXml;else try{u=await s.getEmulatorDomState()}catch(h){a.debug({err:h},"Failed to capture before XML snapshot")}}let p=HS(e.command,a),m=C3(p?.cache??{}),g={...e,status:"SUCCESS",startTime:i,endTime:Date.now()};try{let h=await s.executeCommand({command:e.command});g={...e,status:h.success?"SUCCESS":"FAILED",message:h.message,startTime:i,endTime:Date.now(),data:h.output}}catch(h){h instanceof Error&&h.name==="AbortError"||s.isAborted()?g={...e,status:"CANCELLED",message:"Step cancelled.",startTime:i,endTime:Date.now()}:(a.error({err:h},"Failed to execute preset step"),g={...e,status:"FAILED",message:h instanceof Error?h.message:String(h),startTime:i,endTime:Date.now()})}finally{if(!t.interactive){c&&(g.beforeSnapshot=l,n.attachBeforeScreenshot({snapshotId:l,screenshot:c}),!d&&u&&n.attachBeforeXmlSnapshot({snapshotId:l,xml:u}));let y=b0();try{let E=await s.getScreenshotBase64();g.afterSnapshot=y;let b=Buffer.from(E,"base64");n.attachAfterScreenshot({snapshotId:y,screenshot:b}),o.lastScreenshot={snapshotId:y,screenshot:b}}catch(E){a.warn({err:E},"Failed to take after screenshot"),o.lastScreenshot=void 0}if(!d)try{let E=await s.getEmulatorDomState();n.attachAfterXmlSnapshot({snapshotId:y,xml:E}),o.lastScreenXml={snapshotId:y,screenXml:E}}catch(E){a.debug({err:E},"Failed to capture after XML snapshot"),o.lastScreenXml=void 0}}let h="cache"in e.command?e.command.cache??{}:{};g.status==="FAILED"&&QM({logger:a,step:e,originalMobileCommandCache:p});let f=R3(m,h);f&&Object.keys(f).length>0&&a.info({diffs:es(f)},"Updated cache")}return g}import{streamText as F3}from"ai";import{randomUUID as U3}from"crypto";var qp=class{controller;logger;rootStep;subStepIndex=0;callbacks;finalState=void 0;results=[];constructor(e){let{controller:t,logger:n,callbacks:o,rootStep:i}=e;this.controller=t,this.logger=n,this.callbacks=o,this.rootStep=i}async createAndExecuteStep(e){this.callbacks.onAiActionEvent?.({type:"SUBSTEP_CREATED",rootStep:this.rootStep,step:e});let t=this.subStepIndex++,n=await this.callbacks.executeStep(e,t);return this.results.push(n),n}recordGenericToolCall(e){this.callbacks.onAiActionEvent?.({type:"GENERIC_TOOL_CALLED",toolName:e,rootStep:this.rootStep})}};import{hasToolCall as D3,stepCountIs as k3}from"ai";import T0 from"dedent";var _3=T0`
4607
+ `).map(t=>t.trim()).filter(t=>t.length>0):[]}function ZX(r,e){let t=r.attemptIdToAttemptNumber.get(e);if(t)return tr.join(r.inflatedPath,"attempts",t);let n=tr.join(r.inflatedPath,"attempts");if(!Ht.existsSync(n))return;let o=Ht.readdirSync(n,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>i.name);for(let i of o){let a=tr.join(n,i,"metadata.json"),s=r0(a);if(typeof s!="object"||s===null)continue;let c=s.id;if(typeof c=="string"&&c===e)return r.attemptIdToAttemptNumber.set(e,i),tr.join(n,i)}}function e0(r,e,t){let n=tr.join(r,"attempts");if(!Ht.existsSync(n))return;let o=Ht.readdirSync(n,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>i.name);for(let i of o){let a=tr.join(n,i,"assets",`${e}.${t}`);if(Ht.existsSync(a))return a}}var Gp=class{constructor(e,t,n){this.outputDir=e;this.runId=t;this.runAttemptId=n;this.runsDir=tr.join(e,"runs"),this.zipPath=tr.join(this.runsDir,`${t}.zip`)}inflatedByRunId=new Map;zipPath;runsDir;ensureInflatedRun(e){let t=this.inflatedByRunId.get(e);if(t)return t;if(e!==this.runId||!Ht.existsSync(this.zipPath))return;let n=tr.join(this.runsDir,`temp-unzipped-${e}-${JX()}`);Ht.mkdirSync(n,{recursive:!0}),new XX(this.zipPath).extractAllTo(n,!0);let i={runId:e,zipPath:this.zipPath,inflatedPath:n,attemptIdToAttemptNumber:new Map};return this.inflatedByRunId.set(e,i),i}close(){for(let e of this.inflatedByRunId.values())Ht.rmSync(e.inflatedPath,{recursive:!0,force:!0});this.inflatedByRunId.clear()}getAttemptDir(){let e=this.ensureInflatedRun(this.runId);if(e)return ZX(e,this.runAttemptId)}listVideoAssetPaths(){let e=this.getAttemptDir();if(!e)return[];let t=tr.join(e,"assets");return Ht.existsSync(t)?Ht.readdirSync(t,{withFileTypes:!0}).filter(o=>o.isFile()).map(o=>tr.join(t,o.name)).filter(o=>{let i=tr.extname(o).toLowerCase();return i===".webm"||i===".mp4"}):[]}readAttemptAssetText(e,t){let n=this.getAttemptDir();if(!n)return;let o=tr.join(n,"assets",`${e}.${t}`);if(Ht.existsSync(o))try{return Ht.readFileSync(o,"utf-8")}catch{return}}async getConsoleLogsForRunAttempt(e,t,n){if(t!==this.runId||n!==this.runAttemptId)return;let o=this.getAttemptDir();if(!o)return;let i=r0(tr.join(o,"console.json")),a=Yh.safeParse(i);return a.success?a.data:void 0}async getNetworkLogsForRunAttempt(e,t,n){if(t!==this.runId||n!==this.runAttemptId)return;let o=this.getAttemptDir();if(!o)return;let i=tr.join(o,"assets","har-pages.log"),a=tr.join(o,"assets","har-entries.log"),s={};for(let u of QN(i)){let d=dc.safeParse(t0(u));d.success&&(s[d.data.id]=d.data)}let c={},l=QN(a);for(let u=0;u<l.length;u++){let d=l[u],p=mc.safeParse(t0(d));if(!p.success)continue;let m=`${p.data.startedDateTime}-${u}`;c[m]=p.data}if(Object.keys(c).length!==0)return Jh(s,c)}async getHtmlSnapshot(e,t){let n=this.readAttemptAssetText(t,"html");if(n)return n;let o=this.ensureInflatedRun(this.runId);if(!o)return;let i=e0(o.inflatedPath,t,"html");if(i)try{return Ht.readFileSync(i,"utf-8")}catch{return}}async getA11yTreeSnapshot(e,t){let n=this.readAttemptAssetText(t,"xml");if(n)return n;let o=this.ensureInflatedRun(this.runId);if(!o)return;let i=e0(o.inflatedPath,t,"xml");if(i)try{return Ht.readFileSync(i,"utf-8")}catch{return}}async getScreenshot(e,t){if(!this.ensureInflatedRun(this.runId))return;let o=this.getAttemptDir(),i=o?tr.join(o,"assets",`${t}.jpeg`):void 0;if(i)try{return Ht.readFileSync(i)}catch{return}}};function t0(r){try{return JSON.parse(r)}catch{return}}import ba from"fs";import Wp from"fs";import s3 from"open";import fb from"path";import a3 from"express";import QX from"adm-zip";import{Router as e3}from"express";import el from"fs";import yu from"path";function n0(r){let e=e3(),t=yu.join(r,"runs");return e.get("/",async(n,o)=>{try{let i=t3(r);if(!i){o.status(404).json({error:"No run group found"});return}if(!el.existsSync(t)){o.status(404).json({error:"No runs found for run group"});return}let a=r3(t,i),s={...i,id:i.id??"local-run-group",createdAt:i.startedAt,runs:a};o.status(200).json(s)}catch(i){o.status(500).json({error:`Error loading run group: ${i.message}`})}}),e}function t3(r){let e=yu.join(r,"metadata.json");if(!el.existsSync(e))return M.error("Run group metadata file not found"),null;try{let t=el.readFileSync(e,"utf-8");return ls.parse(JSON.parse(t))}catch(t){return M.error({err:t},"Error reading run group metadata"),null}}function r3(r,e){let t=el.readdirSync(r).filter(o=>o.endsWith(".zip")).sort((o,i)=>{let a=el.statSync(yu.join(r,o));return el.statSync(yu.join(r,i)).mtime.getTime()-a.mtime.getTime()}),n=[];for(let o of t){let i=yu.join(r,o),a=o.replace(/\.zip$/i,"");n.push(n3(i,a,e))}return n}function n3(r,e,t){let o=new QX(r).getEntry("metadata.json");if(!o)throw new Error(`No entry found for file ${r}/metadata.json`);try{let i=o.getData().toString("utf-8"),a=JSON.parse(i),s=uR.parse(a);return uP(s,e,{runGroupMetadata:t,runAttempts:[],organizationId:"local"})}catch(i){throw M.error({err:i,zipPath:r},"Error parsing metadata.json for run"),new Error(`Error parsing metadata.json for run ${r}`)}}import{Router as o3}from"express";import o0 from"fs";import jp from"path";function i0(r){let e=o3(),t=jp.join(r,"runs");return e.get("/:filename",(n,o)=>{let i=n.params.filename;if(!i||!i.endsWith(".zip")){o.status(404).send("Not found");return}let a=jp.join(t,i),s=jp.resolve(a),c=jp.resolve(t);if(!s.startsWith(c)){o.status(403).send("Forbidden");return}if(!o0.existsSync(a)){o.status(404).send("File not found");return}try{o.setHeader("Content-Type","application/zip"),o.setHeader("Content-Disposition",`attachment; filename="${i}"`);let l=o0.readFileSync(a);o.send(l)}catch(l){o.status(500).send(`Error reading file: ${l.message}`)}}),e}import{Router as i3}from"express";import hb from"fs";import tl from"path";function a0(r){let e=i3();return e.get("*",(t,n)=>{let o=t.path==="/"?tl.join(r,"index.html"):tl.join(r,t.path),i=tl.resolve(o),a=tl.resolve(r);if(!i.startsWith(a)){n.status(403).send("Forbidden");return}if(!hb.existsSync(o)&&(o=tl.join(r,"index.html"),!hb.existsSync(o))){n.status(404).send("File not found");return}try{let s=tl.extname(o).toLowerCase(),c=pc[s]||"application/octet-stream";n.setHeader("Content-Type",c);let l=hb.readFileSync(o);n.send(l)}catch(s){n.status(500).send(`Error reading file: ${s.message}`)}}),e}async function s0(r,e,t){let n=e??await zo(Ed,"local-run-viewer-server"),o=a3();return o.use((i,a,s)=>{a.setHeader("Access-Control-Allow-Origin","*"),a.setHeader("Cache-Control","no-cache"),s()}),o.use("/api/runs",i0(r)),o.use("/api/run-group",n0(r)),t&&o.use("/",a0(t)),new Promise((i,a)=>{let s=o.listen(n,()=>{let c=`http://localhost:${n}`;i({port:n,url:c,stop:()=>{s.close()}})});s.on("error",c=>{a(c)})})}async function Sb(r){let{staticDir:e,resultsPath:t,runId:n,port:o}=r,i=fb.resolve(t),a=fb.join(i,"runs"),s;if(n){s=`${n.replace(/\.zip$/i,"")}.zip`;let l=fb.join(a,s);if(!Wp.existsSync(l)){let u=[];if(Wp.existsSync(a))for(let d of Wp.readdirSync(a))d.endsWith(".zip")&&u.push(d.replace(/\.zip$/i,""));M.error(`Run not found: ${s} in ${a}`),u.length>0&&M.error(`Available runs: ${u.join(", ")}`),process.exit(1)}}Wp.existsSync(e)||(M.error(`Static frontend files not found at ${e}. Please ensure the CLI is properly built.`),process.exit(1));try{let l=(await s0(i,o,e)).url;M.info(`Run viewer running at ${l}`);let u=new URL(l);s&&u.searchParams.set("zipUrl",`${l}/api/runs/${s}`),await s3(u.toString())}catch(c){M.error(`Failed to start run viewer: ${c.message}`),process.exit(1)}}import tD from"body-parser";import EJ from"cors";import TJ from"dedent";import{Router as p3}from"express";import Vp from"fs";import l3 from"path";var c3=new xm(30,60*1e3),Tb="https://api.momentic.ai",bb,c0,u0=r=>{Tb=r},vb=()=>Tb;var d0=r=>{c0=r},m0=()=>c0,Ir=()=>bb;var rl,Eb,l0,p0=async r=>{if(bb&&rl&&l0)return rl;let e=new Pr({baseUrl:Tb,apiKey:r,logger:M});bb=e;try{let t=await e.getAuthInfo();return rl=t.orgId,Eb=t.userId,l0=r,rl}catch(t){throw new Error(`Error checking API key against server: ${t}`)}},Yn=()=>{if(!rl)throw new Error("Your organization ID is invalid.");return rl},$p=()=>{if(!Eb)throw new Error("Your user ID is invalid.");return Eb};var Ab,yb,g0=(r,e)=>{Ab=r,yb?.abort(),yb=new AbortController;let t=yb.signal,n=[r.configFilePath];r.config.environments?.forEach(o=>{if(!o.envFile)return;let i=l3.resolve(r.rootDir,o.envFile);try{if(Vp.lstatSync(i).isSymbolicLink())return;Vp.existsSync(i)&&n.push(i)}catch(a){M.warn({err:a},`Failed to check if env file ${i} exists`)}});try{u3({filesToWatch:n,revalidator:e,signal:t,project:r})}catch(o){M.error({err:o},"Failed to start config file watchers")}},We=()=>Ab;function u3({filesToWatch:r,revalidator:e,signal:t,project:n}){M.debug("Starting watch on the following files:"),r.forEach(o=>{M.debug(`- ${o}`)}),r.forEach(o=>{let i=async(s,c)=>{s.mtime.getTime()!==c.mtime.getTime()&&(c3.increment("setLocalProject")&&M.warn(`A file change under the ${n.rootDir} directory has caused Momentic to reload its configuration more than 30 times in the last minute. Rapid changes to files may indicate your momentic.config.yaml 'include' glob is incorrect. Please ensure temporary, library, and auto-generated files are not included in Momentic's context.`),Ab=await Promise.resolve(e(n.configFilePath)))};Vp.watchFile(o,{persistent:!1},i);let a=()=>{Vp.unwatchFile(o,i),t.removeEventListener("abort",a)};t.addEventListener("abort",a),process.once("SIGUSR2",()=>{a(),process.kill(process.pid,"SIGUSR2")})})}function ke(r){return function(...e){let t=e[e.length-1],n=r(...e);Promise.resolve(n).catch(t)}}import{hostname as d3}from"os";var m3="0.33.1",fa=ds({app:"desktop-server",hostname:d3(),disableConsoleLogs:!0}).child({cliVersion:m3});(async()=>{try{let r=await du(fa);r.gitBranchName&&fa.addBinding("branch",r.gitBranchName)}catch{}})();var h0=p3();h0.get("/",async(r,e)=>{let t=We(),n=Ir();if(!n){e.status(500).json({message:"API client not initialized"});return}let o=await sn(fa,n,t),i=o?.gitProtectedBranches&&o?.gitBranchName&&o.gitProtectedBranches.includes(o.gitBranchName),{noCache:a,alwaysSaveCache:s}=m0(),c=!a&&(s||!i);e.status(200).json({saveCaches:c,checkedOutBranch:o?.gitBranchName})});var wb=h0;import{Router as g3}from"express";import Ar from"fs";import{globSync as h3}from"glob";import Kt from"path";var Eu=g3();function bu(r){let e=We(),t=Kt.dirname(e.configFilePath);return Kt.join(t,...r)}function f3(r){let e=We(),t=Kt.dirname(e.configFilePath),n=Kt.relative(t,r);return n?n.split(Kt.sep):[]}function S3(r,e){let t=Ar.statSync(r),n=f3(r);return Zh.parse({name:e,absolutePath:r,relativePath:n.join(Kt.sep),pathSegments:n,isDirectory:t.isDirectory(),size:t.size,createdAt:t.birthtime,modifiedAt:t.mtime,accessedAt:t.atime})}Eu.post("/",ke(async(r,e,t)=>{let n;try{n=jA.parse(r.body).pathSegments}catch(d){e.status(400).json({error:`Failed to parse folder read body: ${d}`});return}let o=bu(n);if(!Ar.existsSync(o)){e.status(404).json({error:`Path not found: ${n.join(Kt.sep)}`});return}if(!Ar.statSync(o).isDirectory()){e.status(400).json({error:`Path is not a directory: ${n.join(Kt.sep)}`});return}let a=We(),s=Array.from(a.config.exclude??[]).concat(bd),l=h3("*",{absolute:!1,cwd:o,ignore:s,dotRelative:!1,maxDepth:1,nodir:!1}).map(d=>{let p=Kt.join(o,d);return S3(p,d)}),u={absolutePath:o,pathSegments:n,contents:l};e.status(200).json(u)}));Eu.put("/",ke(async(r,e,t)=>{let n;try{n=WA.parse(r.body).pathSegments}catch(a){e.status(400).json({error:`Failed to parse folder create body: ${a}`});return}let o=bu(n);if(Ar.existsSync(o)){e.status(200).json({success:!0,message:`Folder already exists: ${n.join(Kt.sep)}`,pathSegments:n});return}Ar.mkdirSync(o,{recursive:!0});let i={success:!0,message:`Folder created: ${n.join(Kt.sep)}`,pathSegments:n};e.status(201).json(i)}));Eu.patch("/",ke(async(r,e,t)=>{let n,o;try{let l=VA.parse(r.body);n=l.pathSegments,o=l.newPathSegments}catch(l){e.status(400).json({error:`Failed to parse folder update body: ${l}`});return}let i=bu(n),a=bu(o);if(!Ar.existsSync(i)){e.status(400).json({error:`Folder not found: ${n.join(Kt.sep)}`});return}if(Ar.existsSync(a)){e.status(400).json({error:`Destination already exists: ${o.join(Kt.sep)}`});return}let s=Kt.dirname(a);Ar.existsSync(s)||Ar.mkdirSync(s,{recursive:!0}),Ar.renameSync(i,a);let c={success:!0,message:`Folder moved from ${n.join(Kt.sep)} to ${o.join(Kt.sep)}`,pathSegments:o};e.status(200).json(c)}));Eu.delete("/",ke(async(r,e,t)=>{let n,o=!0;try{let c=$A.parse(r.body);n=c.pathSegments,o=c.recursive??!0}catch(c){e.status(400).json({error:`Failed to parse folder delete body: ${c}`});return}let i=bu(n);if(!Ar.existsSync(i)){e.status(200).json({success:!0,message:`Folder not found: ${n.join(Kt.sep)}`,pathSegments:n});return}if(!Ar.statSync(i).isDirectory()){e.status(400).json({error:`Path is not a directory: ${n.join(Kt.sep)}`});return}if(o)Ar.rmSync(i,{recursive:!0,force:!0});else{if(Ar.readdirSync(i).length>0){e.status(409).json({error:`Cannot delete non-empty directory without recursive flag: ${n.join("/")}`});return}Ar.rmdirSync(i)}let s={success:!0,message:`Folder deleted: ${n.join("/")}`,pathSegments:n};e.status(200).json(s)}));var Rb=Eu;import{Router as y3}from"express";var f0=y3();f0.get("/",async(r,e)=>{let t=We(),n=Ir();if(!n){e.status(500).json({message:"API client not initialized"});return}let o=await sn(fa,n,t);e.status(200).json(o)});var Cb=f0;import vJ from"events";import rD,{Router as AJ}from"express";import wJ from"http";import{cloneDeep as z3}from"lodash-es";import{randomUUID as b3}from"crypto";var E3=3;async function S0(r){let{results:e,fixtures:t,work:n}=r,{logger:o}=t,i=e[e.length-1],a=v3(i,n);if(a)return o.info({failedResult:i,isNotEligible:a},"Skipping failure recovery because of ineligible failure"),{type:"NOT_ELIGIBLE",message:`The failed step is not eligible for failure recovery: ${a}`};o.info({failedResult:i},"Attempting failure recovery"),n.state.failureRecoveryAttempts=(n.state.failureRecoveryAttempts??0)+1;try{return await T3(r)}catch(s){return o.warn({err:s},"Error during failure recovery attempt, continuing..."),null}}async function T3(r){let{fixtures:e,results:t,failedStep:n,nextSteps:o,stepTracer:i,work:a}=r,{controller:s,logger:c}=e,l=i.parentTracer,{testMetadata:u}=r.inputs;if(!t.length)throw new Error("Attempted failure recovery with no failed results");let d=await s.getScreenshotPngString(),p=await s.getEmulatorDomState(),{results:m}=await aP(c,l,t,{numStepsWithScreenshots:8,addIndices:!0,includeBeforeScreenshots:!1}),g=o.map(R=>ea(R)),h=u.description.trim(),f=u?.settings?.ai?.failureRecoveryInstructions?.trim()||void 0,{scenario:y,thoughts:E,instructions:b}=await s.getMobileFailureRecoveryPlan({currentScreenshot:d,failedResults:m,currentScreenXml:p,nextStepsSerialized:g,testDescription:h,customInstructions:f});if(y!=="RECOVERABLE")return c.info({scenario:y,thoughts:E,instructions:b},"Failure recovery is not applicable"),{type:"NOT_ELIGIBLE",message:`Momentic's failure recovery agent determined that this failure is not eligible for recovery: ${E}`};if(!b)throw new Error("Momentic's failure recovery agent did not provide any instructions for recovery");let x={id:b3(),type:"MOBILE_AI_ACTION_STEP",text:b},P,O=a.state.failureRecoveryDisabled;O||(a.state.failureRecoveryDisabled=!0),c.info("executing mobile step list");try{P=await r.executeMobileStepList({...r,fixtures:{...r.fixtures},listParams:{steps:[x,n],containerName:"AI-recovered step list",tracer:l}})}finally{O||(a.state.failureRecoveryDisabled=O)}let T=P.results[0];if(T&&T.type==="MOBILE_AI_ACTION_STEP")if(jS({results:P.results,onPresetAction:R=>{R.aiSuggested=!0},onSimpleStepContainer:R=>{R.aiSuggested=!0}}),P.status==="SUCCESS"){let R=`The following steps were automatically executed by the failure recovery agent. Analysis: ${E}`;return T.message=R,nt.increment("test_event",1,["name:failure_recovery_success","platform:native",`orgId:${r.inputs.orgId}`]),c.info({thoughts:E},"Failure recovery succeeded"),{type:"ATTEMPTED",status:"SUCCESS",result:P,message:R}}else{nt.increment("test_event",1,["name:failure_recovery_failure","platform:native",`orgId:${r.inputs.orgId}`]);let R=`The following steps were unsuccessfully attempted by the failure recovery agent. Analysis: ${E}`;return T.message=R,c.info({thoughts:E},"Failure recovery failed"),{type:"ATTEMPTED",status:"FAILED",result:P,message:R}}return null}function v3(r,e){if(!r)return"There is no failed result";if(r.type!=="MOBILE_PRESET_STEP")return"The failed step is not a preset action";let t=r.message;return t?t.includes("AbortError:")?"The user aborted the test":yT.some(n=>t.includes(n))?"The failed step is an irrecoverable configuration error":(e.state.failureRecoveryAttempts??0)>E3?"Too many failure recovery attempts":"":"There is no error message available on the failed step"}async function y0(r){let e=Date.now(),t=r.fixtures.controller;try{return await A3(r)}catch(n){let o=t.isAborted()||n instanceof DOMException&&n.name==="AbortError";return{...r.moduleParams.step,steps:[],type:"MOBILE_MODULE_STEP",startTime:e,endTime:Date.now(),status:o?"CANCELLED":"FAILED",message:o?"Step cancelled.":`${n}`}}}async function A3({moduleParams:r,...e}){let t=Date.now(),{step:n,stepTracer:o,executeMobileStepList:i}=r,a=await w3({step:n,params:e}),s={};Object.entries(a).forEach(([p,m])=>{s[p]=JSON.stringify(m)});let c={...n,type:"MOBILE_MODULE_STEP",inputs:s,startTime:t,steps:[],endTime:Date.now(),status:"SUCCESS"},l=await o.startSubSteps(),{status:u,results:d}=await i({...e,listParams:{steps:n.steps,containerName:`module ('${n.name}')`,tracer:l}});return c.steps=d,c.status=u,c.endTime=Date.now(),oP({result:c,...nP(d)}),c}async function w3({step:r,params:e}){let t={},{logger:n,controller:o}=e.fixtures;for(let i of r.parameters?.parameterNames??[]){let a=r.inputs?.[i]??r.parameters?.defaultParameters?.[i];if(!a){n.warn({k:i},"No value found for parameter in module");continue}t[i]=await Fn({orgId:e.inputs.orgId,code:a,fragment:!0,logger:n,context:o.context,localTools:o.localCodeEvalTools})}return t}import{randomUUID as b0}from"crypto";import{diff as R3}from"deep-object-diff";import{cloneDeep as C3}from"lodash-es";async function E0({fixtures:r,step:e,inputs:t,stepTracer:n,work:o}){let i=Date.now(),{logger:a,controller:s}=r,c,l="",u,d=s.emulatorSettings?.disableXmlSnapshots??!1;if(!t.interactive){if(o.lastScreenshot)c=o.lastScreenshot.screenshot,l=o.lastScreenshot.snapshotId;else{l=b0();try{c=Buffer.from(await s.getScreenshotBase64(),"base64")}catch(h){a.warn({err:h},"Failed to take before screenshot")}}if(!d)if(o.lastScreenXml)u=o.lastScreenXml.screenXml;else try{u=await s.getEmulatorDomState()}catch(h){a.debug({err:h},"Failed to capture before XML snapshot")}}let p=HS(e.command,a),m=C3(p?.cache??{}),g={...e,status:"SUCCESS",startTime:i,endTime:Date.now()};try{let h=await s.executeCommand({command:e.command});g={...e,status:h.success?"SUCCESS":"FAILED",message:h.message,startTime:i,endTime:Date.now(),data:h.output}}catch(h){h instanceof Error&&h.name==="AbortError"||s.isAborted()?g={...e,status:"CANCELLED",message:"Step cancelled.",startTime:i,endTime:Date.now()}:(a.error({err:h},"Failed to execute preset step"),g={...e,status:"FAILED",message:h instanceof Error?h.message:String(h),startTime:i,endTime:Date.now()})}finally{if(!t.interactive){c&&(g.beforeSnapshot=l,n.attachBeforeScreenshot({snapshotId:l,screenshot:c}),!d&&u&&n.attachBeforeXmlSnapshot({snapshotId:l,xml:u}));let y=b0();try{let E=await s.getScreenshotBase64();g.afterSnapshot=y;let b=Buffer.from(E,"base64");n.attachAfterScreenshot({snapshotId:y,screenshot:b}),o.lastScreenshot={snapshotId:y,screenshot:b}}catch(E){a.warn({err:E},"Failed to take after screenshot"),o.lastScreenshot=void 0}if(!d)try{let E=await s.getEmulatorDomState();n.attachAfterXmlSnapshot({snapshotId:y,xml:E}),o.lastScreenXml={snapshotId:y,screenXml:E}}catch(E){a.debug({err:E},"Failed to capture after XML snapshot"),o.lastScreenXml=void 0}}let h="cache"in e.command?e.command.cache??{}:{};g.status==="FAILED"&&QM({logger:a,step:e,originalMobileCommandCache:p});let f=R3(m,h);f&&Object.keys(f).length>0&&a.info({diffs:es(f)},"Updated cache")}return g}import{streamText as F3}from"ai";import{randomUUID as U3}from"crypto";var qp=class{controller;logger;rootStep;subStepIndex=0;callbacks;finalState=void 0;results=[];constructor(e){let{controller:t,logger:n,callbacks:o,rootStep:i}=e;this.controller=t,this.logger=n,this.callbacks=o,this.rootStep=i}async createAndExecuteStep(e){this.callbacks.onAiActionEvent?.({type:"SUBSTEP_CREATED",rootStep:this.rootStep,step:e});let t=this.subStepIndex++,n=await this.callbacks.executeStep(e,t);return this.results.push(n),n}recordGenericToolCall(e){this.callbacks.onAiActionEvent?.({type:"GENERIC_TOOL_CALLED",toolName:e,rootStep:this.rootStep})}};import{hasToolCall as D3,stepCountIs as k3}from"ai";import T0 from"dedent";var _3=T0`
4608
4608
  You cannot interact with the user directly. If you feel like you need to ask the user for clarification, or you are stuck, call the "finish" tool with success=false. Never output text without calling a tool.
4609
4609
  `,v0=r=>T0`
4610
4610
  <background>
@@ -4637,7 +4637,7 @@ Momentic users value the following:
4637
4637
  b) There is a loading state that blocks you from proceeding with generation, and you need to wait until the state changes. In this case, you can generate an AI_CHECK step for the anticipated "done" state (e.g. "There is no loading spinner visible"). Unless explicitly specified by the user, you can generate and retry an assertion up to 3 times with a timeout up to 30 seconds each.
4638
4638
  If the max. allowed retries is exceeded, fail the generation cycle by calling "finish".
4639
4639
  </rules>
4640
- `;import{tool as I3}from"ai";import{randomUUID as O3}from"crypto";import L3 from"zod";import{tool as M3}from"ai";import P3 from"zod";var xb="get_emulator_state";var A0=r=>{let e=M3({description:"Get the current state of the emulator (XML + screenshot)",inputSchema:P3.object({}),toModelOutput:t=>t,execute:async()=>{let{controller:t,logger:n,contextManager:o}=r;return o.recordGenericToolCall(xb),n.info("AI action tool called (get_emulator_state)"),_b(t)}});return{name:xb,tool:e}};async function _b(r){let e=await r.getEmulatorDomState(),t=await r.getScreenshotBase64();return{type:"content",value:[{type:"text",text:"<emulatorXml>"},{type:"text",text:e},{type:"text",text:"</emulatorXml>"},{type:"text",text:"<screenshot>"},{type:"media",data:t,mediaType:"image/png"},{type:"text",text:"</screenshot>"}]}}var w0=r=>({name:"create_execute_step",tool:I3({description:"Create and immediately execute a new Momentic step in the Android emulator, returning the result from the step and the state of the emulator after the step finished executing.",inputSchema:L3.object({step:zh}),toModelOutput:t=>t,execute:async({step:t})=>{let{contextManager:n,logger:o,controller:i}=r;o.info({step:t},"AI action tool called (create_execute_step)");let a=dA(t),s={id:O3(),type:"MOBILE_PRESET_STEP",command:a},c=await n.createAndExecuteStep(s);c.status==="SUCCESS"&&i.optionsCopy?.emulator?.waitForStability&&await i.waitForPageSourceStability({reason:"Waiting for stability after executing AI-generated sub-step"});let l={...c,trace:void 0,beforeSnapshot:void 0,afterSnapshot:void 0},u=await _b(i);return{type:"content",value:[{type:"text",text:"<result>"},{type:"text",text:JSON.stringify(l,null,2)},{type:"text",text:"</result>"},{type:"text",text:"<stateAfter>"},...u.value,{type:"text",text:"</stateAfter>"}]}}})});import{tool as N3}from"ai";import Mb from"zod";var R0=r=>{let e=N3({description:"Signal that the AI action has reached a terminal state (either success or failure).",inputSchema:Mb.object({message:Mb.string(),success:Mb.boolean()}),toModelOutput:t=>t,execute:async({message:t,success:n})=>{let{contextManager:o,logger:i}=r;return i.info({message:t,success:n},"AI action tool called (finish)"),o.finalState={message:t,status:n?"SUCCESS":"FAILED"},{type:"content",value:[{type:"text",text:"Done"}]}}});return{name:xu,tool:e}};var C0=[w0,A0,R0];function x0(r){let{logger:e,controller:t,contextManager:n,aiActionSessionId:o}=r,i={};for(let c of C0){let l=c({contextManager:n,logger:e,controller:t});i[l.name]=l.tool}let a=t.generator.getVercelAnthropicModelFactory({logger:e,sessionId:o}),s=c=>{let{messages:l}=c,u=!1;for(let d=l.length-1;d>=0;d--){let p=l[d];for(let m of p.content)if(!(typeof m!="object"||!("type"in m))&&!(m.type!=="tool-result"||m.output.type!=="content")&&!(m.output.value.length<3))for(let g=0;g<m.output.value.length;g++){let h=m.output.value[g];if(h.type==="text"&&h.text.includes("<emulatorXml>"))if(u){let f=m.output.value[g+1];f.type==="text"?f.text="TRUNCATED DUE TO CONVERSATION LENGTH":e.warn({msg:f},"Got unexpected part when truncating emulator state message")}else{u=!0;continue}}}return c};return{model:a("claude-haiku-4-5-20251001"),tools:i,prepareStep:s,stopWhen:[k3(15),D3(xu)],system:v0(!1)}}async function _0(r){let e=Date.now(),{controller:t,logger:n}=r.fixtures;try{return await B3(r)}catch(o){let i=t.isAborted()||o instanceof DOMException&&o.name==="AbortError";return i||n.error({err:o},"Failed to execute mobile AI action"),{...r.aiActionParams.step,steps:[],type:"MOBILE_AI_ACTION_STEP",startTime:e,endTime:Date.now(),status:i?"CANCELLED":"FAILED",message:i?"Step cancelled.":`${o}`}}}async function B3(r){let{platform:e}=r,{step:t,stepTracer:n,executeMobileStepList:o}=r.aiActionParams,{controller:i,logger:a}=r.fixtures,{step:s}=r.callbacks,c=await n.startSubSteps(),l=U3(),u=a.child({stepId:t.id,aiActionSessionId:l}),d=Date.now();if(e!=="ANDROID"||!(i instanceof oi))throw new w("UserConfigurationError","AI action steps are only supported on Android platform.");let p=async(y,E)=>{let b=await o({...r,listParams:{steps:[y],tracer:c,containerName:`AI action sub-step ${E}`}});if(b.results.length!==1)throw new w("InternalWebAgentError","Expected exactly one result from executeMobileStepList");return b.results[0]},m={stepId:t.id,parentStepIdChain:n.getParentStepIdChain()},g=new qp({controller:i,callbacks:{onAiActionEvent:s?.onAiActionEvent,executeStep:p},logger:u,rootStep:m}),h=x0({controller:i,logger:u,contextManager:g,aiActionSessionId:l}),f=F3({...h,messages:[{role:"user",content:t.text}],abortSignal:i.abortSignal});for await(let y of f.fullStream)switch(i.throwIfAborted(),y.type){case"text-delta":s?.onAiActionEvent?.({type:"LLM_TEXT_OUTPUT",text:y.text,rootStep:m})}if(await f.response,i.throwIfAborted(),!g.finalState)throw new w("InternalWebAgentError","The AI agent never reached a final state. This could be because the maximum number of steps was reached.");return{...t,status:g.finalState.status,startTime:d,endTime:Date.now(),message:g.finalState.message,steps:g.results}}var H3=60*60*1e3;async function Tu(r){let{fixtures:e,inputs:t,listParams:n,work:o}=r,{containerName:i,steps:a,tracer:s}=n,{logger:c,controller:l,usageTracker:u}=e,d=s.getParentStepIdChain(),p=[],m,g="SUCCESS",h,{fromStep:f,toStep:y}=t;for(let E=0;E<a.length;E++){let b=a[E];if(b.skipped)continue;if(o.fastForwardingToStep&&f){let R=JSON.stringify(d);if(b.id===f.fromStepId&&R===JSON.stringify(f.parentStepIdChain))o.fastForwardingToStep=!1;else if(!rP({currentStep:b,currentParentChain:d,desiredStepId:f.fromStepId,desiredStepParentChain:f.parentStepIdChain}))continue}let x=0,P=1,O=Date.now();b.retries&&b.retries>0&&(P+=b.retries);let T=[];for(;x<P&&Date.now()-O<H3;){x++;let R=`Executing step index ${E} in ${i} - ${ea(b)}`;x!==1&&(R+=` (attempt ${x})`),c.info({step:b},R);let D=Date.now(),I=await s.startStep({logger:c,step:b,attempt:x,parentStepIdChain:d});u.trackStepExecution(b);let k=z3(b),F=await G3({step:b,stepTracer:I,params:r}),{trace:ee}=await I.finish({parentStepIdChain:d,result:F});if(F.trace=ee,R=`Finished step index ${E} in ${i} - ${ea(b)}`,x!==1&&(R+=` (attempt ${x})`),c.info({step:{id:b.id},trace:F.trace,status:F.status},R),F.status!=="SUCCESS"&&x<P){T.push(F),Date.now()-D<1e3&&await J(1e3-(Date.now()-D));continue}if(T.length>0&&(F.previousAttempts=T),p.push(F),h=await j3({result:F,step:b,originalStep:k,steps:a,currentStepIndex:E,params:r,stepTracer:I,isLastAttempt:x===P,results:p}),F.status!=="SUCCESS"&&h!=="SUCCESS")return g=F.status,m=F,{results:p,status:g,terminalResult:m};if(b.envKey&&l.context.setVariable(b.envKey,F.data),y){let K=JSON.stringify(d);if(b.id===y.toStepId&&K===JSON.stringify(y.parentStepIdChain))return o.shouldStopExecuting=!0,{results:p,status:g,terminalResult:m}}if(o.shouldStopExecuting)return{results:p,status:g,terminalResult:m};break}}return{results:p,status:g,terminalResult:m}}async function G3({step:r,params:e,stepTracer:t}){let{fixtures:n,inputs:o,callbacks:i,work:a}=e,s;switch(r.type){case"MOBILE_PRESET_STEP":{s=await E0({platform:e.platform,fixtures:n,inputs:o,step:r,stepTracer:t,callbacks:i,work:a});break}case"RESOLVED_MOBILE_MODULE":{s=await y0({...e,moduleParams:{step:r,stepTracer:t,executeMobileStepList:Tu}});break}case"MOBILE_AI_ACTION_STEP":{s=await _0({...e,aiActionParams:{step:r,stepTracer:t,executeMobileStepList:Tu}});break}}return s}async function j3({result:r,step:e,originalStep:t,steps:n,currentStepIndex:o,params:i,stepTracer:a,isLastAttempt:s,results:c}){let l,u;if(s&&r.status==="FAILED"&&!i.work.state.failureRecoveryDisabled){let d=await S0({...i,stepTracer:a,step:e,steps:n,currentStepIndex:o,isLastAttempt:s,executeMobileStepList:Tu,failedStep:t,nextSteps:n.slice(o+1),results:c.concat(r)});d&&(d.type==="ATTEMPTED"?(l=d.result.results,u=d.status):d.type==="NOT_ELIGIBLE"&&(r.message=r.message?`${r.message} ${d.message}`:d.message),r.type==="MOBILE_PRESET_STEP"&&(r.failureRecoveryStatus={type:d.type,message:d.message}))}return l&&c.push(...l),u}import{diff as W3}from"deep-object-diff";import{cloneDeep as V3}from"lodash-es";async function nl(r){let{tracer:e,containerName:t}=r,{steps:n,testMetadata:o}=r.inputs,{cacheStorage:i,logger:a}=r.fixtures,s=a.child({testId:r.inputs.testMetadata.id,testName:r.inputs.testName});await i.populateCacheForRun({logger:s,platform:o.platform,testId:o.id,stepLists:{steps:n},skipFetchingCacheFromStorage:r.inputs.interactive});let c=V3(n);s.info({testMetadata:No.parse(o)},"Starting mobile test");let l=await e.startMainStepList(),u=BR(s);s.info({cpu:u?.cpuMetadata,platform:u?.platform},`Starting execution of ${t}`);let{status:d,results:p,terminalResult:m}=await Tu({...r,listParams:{containerName:t,tracer:l,steps:c}});return clearInterval(u?.interval),await $3({steps:n,stepsToExecute:c,logger:s,cacheStorage:i,orgId:r.inputs.orgId,testId:o.id,platform:o.platform}),d==="SUCCESS"?{status:"PASSED",results:p,failureRecoveryDetails:r.work.state.failureRecoveryAttempts?{attempts:r.work.state.failureRecoveryAttempts}:void 0}:d==="CANCELLED"?{status:"CANCELLED",results:p}:{status:"FAILED",results:p,terminalResult:m}}async function $3({steps:r,stepsToExecute:e,logger:t,cacheStorage:n,orgId:o,testId:i,platform:a}){let s=W3(r,e);if(s&&Object.keys(s).length>0){t.info({diffs:es(s)},"Saving mobile step cache entries");let{cachesToSave:c}=await Bn({platform:a,steps:e,cacheCreationParams:{orgId:o,testId:i}});await n.saveEntries({logger:t,testId:i,entries:c})}else t.info("No cache entries to update")}import{Server as rJ}from"socket.io";import{tmpdir as q3}from"os";import M0 from"path";async function P0({socket:r,logger:e,orgId:t,testMetadata:n,globalOrgSettings:o,androidDriverFactory:i,mobileGeneratorFactory:a,browserGeneratorFactory:s,browserEnricherFactory:c,storageFactory:l,localToolsFactory:u,globalStateManager:d,getGitMetadata:p}){let m=r.id,g=await p(),h=r.handshake.query?.fileName,f=h?M0.basename(h,".test.yaml"):"",y=n.id,E=n.settings?.defaultChannel,b=n.settings?.defaultTag;e=e.child({sessionId:m,testId:y,orgId:t,branch:g.gitBranchName});let x=await l(t),P=n.settings?.defaultEnv,O={};P&&(O=(await x.fetchEnvironment(P,e))?.variables??{});let T=rs.parse(O[_i]),R=rs.parse(O[Dl]),D={...o.emulator,...n.settings?.emulator},I=n.settings?.defaultApkFilePath?.trim()||R,k=d.getSession(m);if(k){if(e.info("Reconnecting to existing Android session"),k.local)return r.emit("session",k.metadata),k.softDeleted=!1,k.metadata;throw new Error("Restoring existing remote emulator sessions is not supported. Please reconnect to a new emulator.")}let F;if(D.region==="local"){if(await d.clearSoftDeletedLocalSessions(e),d.hasActiveLocalSession())throw new Error("Another local emulator session is already active. Please close the existing session before creating a new one.");let hi=n.settings?.emulator?.localEmulatorSettings?.avdId?.trim()||T;if(!hi)throw new Error(`AVD ID is required when using a local emulator. Set it on the test (Options \u2192 Emulator \u2192 Local AVD ID) or on the environment via ${_i}.`);F={avdId:hi,apkToInstall:E?{channel:E,tag:b}:void 0,apkFilePath:I}}else F={region:D.region,apkToInstall:E?{channel:E,tag:b}:void 0,osVersion:D.remoteEmulatorSettings?.androidVersion};let ee=Date.now(),{driver:K,cleanup:ge,emulatorName:B,adbPort:j,limbarClient:ue,limbarToken:le,limbarUrl:He,playwrightDevice:ve}=await i({socket:r,logger:e,creationOpts:F}),q=M0.join(q3(),`logcat-logs-${t}-${y}-${m}.txt`),fe=await Pm({driver:K,onLogs:hi=>{r.emit("logcatLogs",hi)},logFilePath:q});e.info({adbPort:j,apkChannel:E,apkTag:b,duration:Date.now()-ee,emulatorName:B},"Android emulator session initiated"),e=e.child({emulator:B});let it=await a(t,e),Ae=await s(t,e),C=await c(t,e),oe=u?await u(t):void 0,pe=new Lo({variablesFromEnvironment:O,envName:P,testName:f}),Br=await oi.init({driver:K,generator:it,logger:e,limbarClient:ue,playwrightDevice:ve,aiSettings:{...o.ai,useMemory:o.ai?.useMemory!==!1,...n.settings?.ai},options:{emulator:{...D,browserSettings:o.browser}},fixtures:{storage:x,browserEnricher:C,browserGenerator:Ae,localCodeEvalTools:oe,testContext:pe},orgId:t,adbPort:j,abortController:new AbortController}),gi=await Br.getViewportBounds();if(!r.connected)throw await Br.cleanup(),await fe(),await ge(),new Error("Socket not connected anymore, not proceeding with Android session setup");let WD=K3({socket:r,testContext:pe}),VD=async()=>{clearInterval(WD);try{await Promise.allSettled([Br.cleanup(),fe(),ge()])}catch(hi){e.warn({err:hi},"Failed to clean up emulator in socket server")}},ie={sessionId:m,testId:y,orgId:t,emulatorName:B,testName:f,limbarUrl:He,limbarToken:le,viewportBounds:gi};return d.registerSession(m,{controller:Br,cleanup:VD,emulatorName:B,local:D.region==="local",metadata:ie,logFilePath:q}),r.emit("session",ie),ie}function K3({socket:r,testContext:e}){return setInterval(()=>{let t=e.toEditorDisplayCopy();r.emit("emulatorState",{context:t})},3e3)}import Kp from"fs/promises";async function I0({socket:r,logger:e,globalStateManager:t,authorization:n}){let o=r.id,i=t.getSession(o);i&&n&&i.logFilePath&&Y3({testId:i.metadata.testId,sessionId:o,logFilePath:i.logFilePath,authorization:n,logger:e}),await t.removeSession(o,e)}async function Y3({testId:r,sessionId:e,logFilePath:t,authorization:n,logger:o}){try{let i;try{i=await Kp.stat(t)}catch{o.debug({logFilePath:t},"No logcat file found to upload");return}if(i.size===0){o.debug({logFilePath:t},"Logcat file is empty, skipping upload"),await Kp.unlink(t);return}let a=new Pr(n),{uploadUrl:s}=await a.generateMobileLogcatUploadUrl({testId:r,sessionId:e}),c=await Kp.readFile(t),l=await fetch(s,{headers:{"Content-Length":c.length.toString(),"Content-Type":"text/plain"},method:"PUT",body:c});if(l.status!==200)throw new Error(`Failed to upload logcat: ${l.status} ${await l.text()}`);o.info({testId:r,sessionId:e},"Logcat file uploaded successfully")}catch(i){o.warn({err:i,testId:r,sessionId:e},"Failed to upload logcat file")}finally{try{await Kp.unlink(t)}catch(i){o.warn({err:i,logFilePath:t},"Failed to delete temp logcat file")}}}var X3=({socket:r,globalStateManager:e})=>async()=>{let t=e.getSession(r.id);if(!t)throw new Error("No active Android session found");t.controller.abort()},O0={event:"cancel",createHandler:X3};var J3=({logger:r,globalStateManager:e,socket:t})=>async(n,o)=>{let i=e.getSession(t.id);if(!i){o({err:"No active Android session found"});return}try{let s=await i.controller.getEmulatorDomState();o({screenXml:s})}catch(a){r.error({err:a},"Error fetching screen XML from the session controller"),o({err:a.message})}},L0={event:"fetchScreenXml",createHandler:J3};var Pb=class{parentTracer;socket;step;orgId;interactionTracer;constructor({step:e,socket:t,parentTracer:n,orgId:o}){this.socket=t,this.parentTracer=n,this.step=e,this.orgId=o,this.interactionTracer=new Xo,rn.initializeRootTracerContext(this.interactionTracer)}attachBeforeScreenshot(){}attachAfterScreenshot(){}attachBeforeXmlSnapshot(){}attachAfterXmlSnapshot(){}recordStepDuration(e){let{durationMs:t,step:n}=e,o=n.type!=="MOBILE_PRESET_STEP"?n.type:n.command.type;nt.distribution("test_step_duration",t,[`type:${o}`,"platform:mobile","executor:editor",`orgId:${this.orgId}`])}async finish(e){this.interactionTracer.finish();let t=this.interactionTracer.getRootSpan(),n={...iR.parse(e),trace:Kh.parse(t)};switch(n.result.status){case"SUCCESS":this.socket.emit("success",n);break;case"FAILED":this.socket.emit("failure",n);break;case"CANCELLED":this.socket.emit("cancelled",n);break}return{trace:t}}getParentStepIdChain(){return this.parentTracer?this.parentTracer?.getParentStepIdChain()??[]:[]}async startSubSteps(){return new ol({parentStep:this.step,socket:this.socket,parentTracer:this,orgId:this.orgId})}},ol=class{parentTracer;parentStep;socket;orgId;constructor({parentStep:e,socket:t,parentTracer:n,orgId:o}){this.parentTracer=n,this.parentStep=e,this.socket=t,this.orgId=o}getParentStepIdChain(){return this.parentStep?[...this.parentTracer?.getParentStepIdChain()??[],this.parentStep.id]:[]}async startStep(e){return this.socket.emit("started",{stepId:e.step.id,parentStepIdChain:e.parentStepIdChain,attempt:e.attempt}),new Pb({step:e.step,parentTracer:this,socket:this.socket,orgId:this.orgId})}async getScreenshot(e){}},Yp=class{constructor(e,t){this.socket=e;this.orgId=t}appendLogs(){}async finish(){this.socket.emit("finished")}async startBeforeStepList(){return new ol({parentStep:null,parentTracer:null,socket:this.socket,orgId:this.orgId})}async startMainStepList(){return new ol({parentStep:null,parentTracer:null,socket:this.socket,orgId:this.orgId})}async startAfterStepList(){return new ol({parentStep:null,parentTracer:null,socket:this.socket,orgId:this.orgId})}};var Z3=({metadata:r,logger:e,globalStateManager:t,socket:n,cacheStorageFactory:o,getGitMetadata:i})=>async(a,s)=>{let c=t.getSession(n.id);if(!c)throw new Error("No active Android session found");if(a.testMetadata.platform!=="ANDROID")throw new Error("Non-android tests aren't supported yet");let l=await i(),u=e.child({testId:a.testMetadata.id,branch:l.gitBranchName}),d=await o(r.orgId,l),p=c.controller;p.resetAbortController();let m=new Yp(n,r.orgId),g=await nl({platform:"ANDROID",work:{fastForwardingToStep:!!a.fromStep,state:{failureRecoveryDisabled:!0,failureRecoveryAttempts:0}},fixtures:{controller:p,logger:u,cacheStorage:d,usageTracker:new ld},containerName:"entire test",inputs:{steps:a.steps,fromStep:a.fromStep,toStep:a.toStep,orgId:r.orgId,testName:r.testName,testMetadata:a.testMetadata,interactive:!0},tracer:m,callbacks:{step:{onAiActionEvent:f=>{n.emit("aiActionEvent",f)}}}});await m.finish();let h={results:yr.array().parse(g.results),status:g.status};s?.(h)},N0={event:"execute",createHandler:Z3};import{debounce as Q3}from"ts-debounce";var eJ=({socket:r,globalStateManager:e,keepSessionAlive:t})=>{let n=Q3(t,3e4,{maxWait:6e4});return async()=>{let o=e.getSession(r.id);if(!o)throw new Error("No active Android session found");o.emulatorName&&(o.local||n(o.emulatorName))}},D0={event:"keepalive",createHandler:eJ};var tJ=({socket:r,globalStateManager:e,logger:t})=>async(n,o)=>{let i=e.getSession(r.id);if(!i){let s="No active Android session found";t.error(s),o?.({success:!1,err:s});return}let a=i.controller;a.abort(),a.resetAbortController(),t.info("Resetting emulator state");try{await a.softReset(),t.info("Emulator reset completed"),o?.({success:!0,message:"Emulator reset successfully"})}catch(s){let c=s instanceof Error?s.message:String(s);t.error({err:s},"Failed to reset emulator"),o?.({success:!1,err:`Failed to reset emulator: ${c}`})}},k0={event:"reset",createHandler:tJ};var F0=[N0,O0,k0,D0,L0];var Xp=class{sessions=new Map;registerSession(e,t){this.sessions.set(e,t)}getSession(e){return this.sessions.get(e)}async clearSoftDeletedLocalSessions(e){for(let t of this.sessions.values())t.softDeleted===!0&&t.local===!0&&await this.removeSession(t.metadata.sessionId,e)}hasActiveLocalSession(){for(let e of this.sessions.values())if(e.local===!0)return!0;return!1}async removeSession(e,t){let n=this.sessions.get(e);if(n)try{await n.cleanup?.(),t.info({sessionId:e,emulatorName:n.emulatorName},"Android emulator cleaned up by removeSession")}catch(o){t.error({err:o},"Error during Android session cleanup")}finally{this.sessions.delete(e)}}async removeAllSessions(e){let t=Array.from(this.sessions.keys());await Promise.all(t.map(n=>this.removeSession(n,e)))}};function U0(r){let{logger:e,baseServer:t,globalStateManager:n,settingsFactory:o,getOrgId:i}=r,a=new rJ(t,{cors:{origin:"*",methods:["GET","POST"]},pingTimeout:15*60*1e3,pingInterval:15*60*1e3,maxHttpBufferSize:1e7,perMessageDeflate:!0,connectionStateRecovery:{maxDisconnectionDuration:60*60*1e3,skipMiddlewares:!0}}),s=async()=>{await n.removeAllSessions(e)};a.on("connection",async l=>{let u=l.id,d=e.child({sessionId:u});d.info({event:"connection",transport:l.conn.transport.name},"Android websocket connection initiated"),l.on("disconnect",async g=>{if(e.info({reason:g},"Disconnect received"),g.includes("namespace disconnect")){await I0({socket:l,globalStateManager:n,logger:d,authorization:r.authorization});return}let h=n.getSession(u);h&&(h.softDeleted=!0)});let p,m;try{let g=l.handshake.query?.testMetadata,h=No.parse(JSON.parse(g??"")),f=h.id,y=await i({testId:f});m=await o(y,e),p=await P0({...r,orgId:y,socket:l,globalStateManager:n,logger:d,globalOrgSettings:m,testMetadata:h})}catch(g){d.error({err:g},"Failed to setup Android connection"),l.emit("error",{message:g instanceof Error?g.message:JSON.stringify(g)}),l.disconnect(!0);return}F0.forEach(g=>c(g,{...r,socket:l,metadata:p,globalOrgSettings:m,logger:d}))});let c=(l,u)=>{let d=l.createHandler(u),p=(...m)=>{l.event!=="keepalive"&&u.logger.debug({event:l.event},`Websocket event (${l.event})`);let g=h=>{u.logger.error({event:l.event,err:h instanceof Error?h:new Error(`${h}`)},"Unhandled exception in socket handler"),u.socket.emit("error",{message:h instanceof Error?h.message:typeof h=="string"?h:JSON.stringify(h)})};try{let h=d.apply(this,m);h&&typeof h.catch=="function"&&h.catch(g)}catch(h){g(h)}};u.socket.on(l.event,p)};return{server:a,dispose:s}}import RJ from"path";var Jp=new Xp;import{Router as oJ}from"express";import{existsSync as iJ}from"fs";import aJ from"path";import{hostname as nJ}from"os";var Ib="0.33.0",Ze=ds({app:"mobile-desktop-server",hostname:nJ(),disableConsoleLogs:!0}).child({cliVersion:Ib});(async()=>{try{let r=await du(Ze);r.gitBranchName&&Ze.addBinding("branch",r.gitBranchName)}catch{}})();var Ob=oJ();Ob.get("/",ke(async(r,e)=>{let t=Ir();if(!t){e.status(500).json({message:"API client not initialized"});return}let n=await t.getAndroidAssets();e.status(200).json(n)}));Ob.post("/upload-url",ke(async(r,e)=>{let t;try{t=QA.parse(r.body)}catch(i){e.status(400).json({error:`Invalid request body: ${i}`});return}let n=Ir();if(!n){e.status(500).json({error:"API client not initialized"});return}let o=aJ.resolve(t.filePath);if(!iJ(o)){e.status(400).json({error:`File not found: ${o}`});return}await Mm({tag:t.tag,channel:t.channel,filePath:o,apiClient:n,logger:Ze}),e.sendStatus(204)}));var B0=Ob;import{Router as cJ}from"express";import{Router as sJ}from"express";import z0 from"fs";import lJ from"path";var il=sJ();async function Zp(r){return(await tL(r,Ze)).map(n=>{let o=r.mobileModules[n.moduleId];if(!o){M.warn(`Found a dangling mobile module with ID ${n.moduleId} that could not be found on disk.`);return}return{...o,content:n}}).filter(n=>n!==void 0)}il.get("/",ke(async(r,e)=>{let t=We(),n=await Zt(t),o=await Zp(n);e.status(200).json(o)}));il.get("/tests-join",ke(async(r,e)=>{let t=We(),n=await Zt(t),o=await Zp(n),i={};for(let s of o)i[s.id]={...s,tests:[]};let a=await Promise.all(Object.values(n.mobileTests).map(async s=>({id:s.id,name:s.name,relativePath:s.relativePath,test:await So(s.fullFilePath,Ze,n)})));for(let{id:s,name:c,relativePath:l,test:u}of a){let d=new Set;switch(u.platform){case"ANDROID":GS({steps:u.steps,onPreset:()=>!1,onModule:p=>(d.add(p.moduleId),!1)});break;case"IOS":break;default:return(m=>{throw new Error("Unhandled platform")})(u)}for(let p of d){let m=i[p];m&&m.tests.push({id:s,name:c,relativePath:l})}}e.status(200).json(i)}));il.get("/:moduleId",ke(async(r,e)=>{if(!r.params.moduleId){e.status(400).json({error:"Missing moduleId in url path."});return}let t=await Zt(We()),n=t.mobileModules[r.params.moduleId];if(!n){e.status(404).json({error:"Mobile module not found."});return}try{let o=await jy(n,t,M);e.json(o)}catch(o){e.status(400).json({err:o})}}));il.patch("/:moduleId/metadata",ke(async(r,e)=>{if(!r.params.moduleId){e.status(400).json({error:"Missing moduleId in url path."});return}let t;try{t=tw.parse(r.body)}catch(i){e.status(400).json({error:`Invalid request body: ${i}`});return}let n=We(),o=await Zt(n);QO({moduleId:r.params.moduleId,patch:t,momenticFiles:o,logger:M,project:n}),e.status(201).json({message:"ok"})}));il.post("/",ke(async(r,e)=>{let t;try{t=rw.parse(r.body)}catch(c){e.status(400).json({error:`Invalid request body: ${c}`});return}try{_o(t.name)}catch(c){e.status(400).json({error:`Invalid module name: ${c}`});return}let n=We(),i=(await Zt(n)).mobileModules;if(Object.values(i).find(c=>c.name===t.name)){e.status(400).json({error:`A mobile module with the name "${t.name}" already exists. Please choose a different name.`});return}let a=lJ.join(n.rootDir,t.folderPath??"");if(!z0.existsSync(a)||!z0.statSync(a).isDirectory()){e.status(400).json({error:`The folder configured for mobile module creation does not exist: ${a}`});return}let s=await eL({...t,folder:a,project:n});e.status(201).json(s)}));var H0=il;var G0=cJ();G0.get("/",ke(async(r,e)=>{let t=We(),n=await Zt(t),o=await Zp(n),i=new Set;n?.mobileTests&&Object.values(n.mobileTests).forEach(l=>{l.labels?.forEach(u=>i.add(u))});let a=Array.from(i).sort(),s=Object.values(n.mobileTests),c={labels:a,modules:o,tests:s};e.status(200).json(c)}));var j0=G0;import{Router as uJ}from"express";var Qp=uJ();Qp.get("/",ke((r,e)=>{let t=HO(We(),Ze);e.status(200).json(t)}));Qp.get("/names",ke((r,e)=>{let n=We().config.environments?.map(o=>o.name)??[];e.status(200).json(n)}));Qp.post("/",ke((r,e)=>{let t;try{t=ew.parse(r.body)}catch(s){e.status(400).json({error:`Invalid request body: ${s}`});return}try{_o(t.name)}catch(s){e.status(400).json({error:`Invalid environment name: ${s}`});return}let n=We();if(n.config.environments?.find(s=>s.name===t.name)){e.status(400).json({error:`An environment with the name "${t.name}" already exists. Please choose a different name.`});return}let i={...n.config,environments:[...n.config.environments??[],{name:t.name}]};n.config=i,Cp(i,n.configFilePath);let a=da(t.name,n,Ze);e.status(201).json(a)}));var W0=Qp;import{Router as dJ}from"express";var V0=dJ();V0.get("/",(r,e)=>{e.status(200).json({userId:$p(),orgId:Yn(),cliVersion:Ib??"0.0.0"})});var $0=V0;import{Router as mJ}from"express";var q0=mJ();q0.get("/",ke(async(r,e)=>{let t=r.query.sessionId;if(!t){e.status(400).json({packages:[]});return}let n=Jp.getSession(t);if(!n?.controller){e.status(200).json({packages:[]});return}try{let a=(await n.controller.executeRawADBCommand("shell pm list packages -3"))?.split(`
4640
+ `;import{tool as I3}from"ai";import{randomUUID as O3}from"crypto";import L3 from"zod";import{tool as M3}from"ai";import P3 from"zod";var xb="get_emulator_state";var A0=r=>{let e=M3({description:"Get the current state of the emulator (XML + screenshot)",inputSchema:P3.object({}),toModelOutput:t=>t,execute:async()=>{let{controller:t,logger:n,contextManager:o}=r;return o.recordGenericToolCall(xb),n.info("AI action tool called (get_emulator_state)"),_b(t)}});return{name:xb,tool:e}};async function _b(r){let e=await r.getEmulatorDomState(),t=await r.getScreenshotBase64();return{type:"content",value:[{type:"text",text:"<emulatorXml>"},{type:"text",text:e},{type:"text",text:"</emulatorXml>"},{type:"text",text:"<screenshot>"},{type:"media",data:t,mediaType:"image/png"},{type:"text",text:"</screenshot>"}]}}var w0=r=>({name:"create_execute_step",tool:I3({description:"Create and immediately execute a new Momentic step in the Android emulator, returning the result from the step and the state of the emulator after the step finished executing.",inputSchema:L3.object({step:zh}),toModelOutput:t=>t,execute:async({step:t})=>{let{contextManager:n,logger:o,controller:i}=r;o.info({step:t},"AI action tool called (create_execute_step)");let a=dA(t),s={id:O3(),type:"MOBILE_PRESET_STEP",command:a},c=await n.createAndExecuteStep(s);c.status==="SUCCESS"&&i.optionsCopy?.emulator?.waitForStability&&await i.waitForPageSourceStability({reason:"Waiting for stability after executing AI-generated sub-step"});let l={...c,trace:void 0,beforeSnapshot:void 0,afterSnapshot:void 0},u=await _b(i);return{type:"content",value:[{type:"text",text:"<result>"},{type:"text",text:JSON.stringify(l,null,2)},{type:"text",text:"</result>"},{type:"text",text:"<stateAfter>"},...u.value,{type:"text",text:"</stateAfter>"}]}}})});import{tool as N3}from"ai";import Mb from"zod";var R0=r=>{let e=N3({description:"Signal that the AI action has reached a terminal state (either success or failure).",inputSchema:Mb.object({message:Mb.string(),success:Mb.boolean()}),toModelOutput:t=>t,execute:async({message:t,success:n})=>{let{contextManager:o,logger:i}=r;return i.info({message:t,success:n},"AI action tool called (finish)"),o.finalState={message:t,status:n?"SUCCESS":"FAILED"},{type:"content",value:[{type:"text",text:"Done"}]}}});return{name:xu,tool:e}};var C0=[w0,A0,R0];function x0(r){let{logger:e,controller:t,contextManager:n,aiActionSessionId:o}=r,i={};for(let c of C0){let l=c({contextManager:n,logger:e,controller:t});i[l.name]=l.tool}let a=t.generator.getVercelAnthropicModelFactory({logger:e,sessionId:o}),s=c=>{let{messages:l}=c,u=!1;for(let d=l.length-1;d>=0;d--){let p=l[d];for(let m of p.content)if(!(typeof m!="object"||!("type"in m))&&!(m.type!=="tool-result"||m.output.type!=="content")&&!(m.output.value.length<3))for(let g=0;g<m.output.value.length;g++){let h=m.output.value[g];if(h.type==="text"&&h.text.includes("<emulatorXml>"))if(u){let f=m.output.value[g+1];f.type==="text"?f.text="TRUNCATED DUE TO CONVERSATION LENGTH":e.warn({msg:f},"Got unexpected part when truncating emulator state message")}else{u=!0;continue}}}return c};return{model:a("claude-haiku-4-5-20251001"),tools:i,prepareStep:s,stopWhen:[k3(15),D3(xu)],system:v0(!1)}}async function _0(r){let e=Date.now(),{controller:t,logger:n}=r.fixtures;try{return await B3(r)}catch(o){let i=t.isAborted()||o instanceof DOMException&&o.name==="AbortError";return i||n.error({err:o},"Failed to execute mobile AI action"),{...r.aiActionParams.step,steps:[],type:"MOBILE_AI_ACTION_STEP",startTime:e,endTime:Date.now(),status:i?"CANCELLED":"FAILED",message:i?"Step cancelled.":`${o}`}}}async function B3(r){let{platform:e}=r,{step:t,stepTracer:n,executeMobileStepList:o}=r.aiActionParams,{controller:i,logger:a}=r.fixtures,{step:s}=r.callbacks,c=await n.startSubSteps(),l=U3(),u=a.child({stepId:t.id,aiActionSessionId:l}),d=Date.now();if(e!=="ANDROID"||!(i instanceof oi))throw new w("UserConfigurationError","AI action steps are only supported on Android platform.");let p=async(y,E)=>{let b=await o({...r,listParams:{steps:[y],tracer:c,containerName:`AI action sub-step ${E}`}});if(b.results.length!==1)throw new w("InternalWebAgentError","Expected exactly one result from executeMobileStepList");return b.results[0]},m={stepId:t.id,parentStepIdChain:n.getParentStepIdChain()},g=new qp({controller:i,callbacks:{onAiActionEvent:s?.onAiActionEvent,executeStep:p},logger:u,rootStep:m}),h=x0({controller:i,logger:u,contextManager:g,aiActionSessionId:l}),f=F3({...h,messages:[{role:"user",content:t.text}],abortSignal:i.abortSignal});for await(let y of f.fullStream)switch(i.throwIfAborted(),y.type){case"text-delta":s?.onAiActionEvent?.({type:"LLM_TEXT_OUTPUT",text:y.text,rootStep:m})}if(await f.response,i.throwIfAborted(),!g.finalState)throw new w("InternalWebAgentError","The AI agent never reached a final state. This could be because the maximum number of steps was reached.");return{...t,status:g.finalState.status,startTime:d,endTime:Date.now(),message:g.finalState.message,steps:g.results}}var H3=60*60*1e3;async function Tu(r){let{fixtures:e,inputs:t,listParams:n,work:o}=r,{containerName:i,steps:a,tracer:s}=n,{logger:c,controller:l,usageTracker:u}=e,d=s.getParentStepIdChain(),p=[],m,g="SUCCESS",h,{fromStep:f,toStep:y}=t;for(let E=0;E<a.length;E++){let b=a[E];if(b.skipped)continue;if(o.fastForwardingToStep&&f){let R=JSON.stringify(d);if(b.id===f.fromStepId&&R===JSON.stringify(f.parentStepIdChain))o.fastForwardingToStep=!1;else if(!rP({currentStep:b,currentParentChain:d,desiredStepId:f.fromStepId,desiredStepParentChain:f.parentStepIdChain}))continue}let x=0,P=1,O=Date.now();b.retries&&b.retries>0&&(P+=b.retries);let T=[];for(;x<P&&Date.now()-O<H3;){x++;let R=`Executing step index ${E} in ${i} - ${ea(b)}`;x!==1&&(R+=` (attempt ${x})`),c.info({step:b},R);let D=Date.now(),I=await s.startStep({logger:c,step:b,attempt:x,parentStepIdChain:d});u.trackStepExecution(b);let k=z3(b),F=await G3({step:b,stepTracer:I,params:r}),{trace:ee}=await I.finish({parentStepIdChain:d,result:F});if(F.trace=ee,R=`Finished step index ${E} in ${i} - ${ea(b)}`,x!==1&&(R+=` (attempt ${x})`),c.info({step:{id:b.id},trace:F.trace,status:F.status},R),F.status!=="SUCCESS"&&x<P){T.push(F),Date.now()-D<1e3&&await J(1e3-(Date.now()-D));continue}if(T.length>0&&(F.previousAttempts=T),p.push(F),h=await j3({result:F,step:b,originalStep:k,steps:a,currentStepIndex:E,params:r,stepTracer:I,isLastAttempt:x===P,results:p}),F.status!=="SUCCESS"&&h!=="SUCCESS")return g=F.status,m=F,{results:p,status:g,terminalResult:m};if(b.envKey&&l.context.setVariable(b.envKey,F.data),y){let K=JSON.stringify(d);if(b.id===y.toStepId&&K===JSON.stringify(y.parentStepIdChain))return o.shouldStopExecuting=!0,{results:p,status:g,terminalResult:m}}if(o.shouldStopExecuting)return{results:p,status:g,terminalResult:m};break}}return{results:p,status:g,terminalResult:m}}async function G3({step:r,params:e,stepTracer:t}){let{fixtures:n,inputs:o,callbacks:i,work:a}=e,s;switch(r.type){case"MOBILE_PRESET_STEP":{s=await E0({platform:e.platform,fixtures:n,inputs:o,step:r,stepTracer:t,callbacks:i,work:a});break}case"RESOLVED_MOBILE_MODULE":{s=await y0({...e,moduleParams:{step:r,stepTracer:t,executeMobileStepList:Tu}});break}case"MOBILE_AI_ACTION_STEP":{s=await _0({...e,aiActionParams:{step:r,stepTracer:t,executeMobileStepList:Tu}});break}}return s}async function j3({result:r,step:e,originalStep:t,steps:n,currentStepIndex:o,params:i,stepTracer:a,isLastAttempt:s,results:c}){let l,u;if(s&&r.status==="FAILED"&&!i.work.state.failureRecoveryDisabled){let d=await S0({...i,stepTracer:a,step:e,steps:n,currentStepIndex:o,isLastAttempt:s,executeMobileStepList:Tu,failedStep:t,nextSteps:n.slice(o+1),results:c.concat(r)});d&&(d.type==="ATTEMPTED"?(l=d.result.results,u=d.status):d.type==="NOT_ELIGIBLE"&&(r.message=r.message?`${r.message} ${d.message}`:d.message),r.type==="MOBILE_PRESET_STEP"&&(r.failureRecoveryStatus={type:d.type,message:d.message}))}return l&&c.push(...l),u}import{diff as W3}from"deep-object-diff";import{cloneDeep as V3}from"lodash-es";async function nl(r){let{tracer:e,containerName:t}=r,{steps:n,testMetadata:o}=r.inputs,{cacheStorage:i,logger:a}=r.fixtures,s=a.child({testId:r.inputs.testMetadata.id,testName:r.inputs.testName});await i.populateCacheForRun({logger:s,platform:o.platform,testId:o.id,stepLists:{steps:n},skipFetchingCacheFromStorage:r.inputs.interactive});let c=V3(n);s.info({testMetadata:No.parse(o)},"Starting mobile test");let l=await e.startMainStepList(),u=BR(s);s.info({cpu:u?.cpuMetadata,platform:u?.platform},`Starting execution of ${t}`);let{status:d,results:p,terminalResult:m}=await Tu({...r,listParams:{containerName:t,tracer:l,steps:c}});return clearInterval(u?.interval),await $3({steps:n,stepsToExecute:c,logger:s,cacheStorage:i,orgId:r.inputs.orgId,testId:o.id,platform:o.platform}),d==="SUCCESS"?{status:"PASSED",results:p,failureRecoveryDetails:r.work.state.failureRecoveryAttempts?{attempts:r.work.state.failureRecoveryAttempts}:void 0}:d==="CANCELLED"?{status:"CANCELLED",results:p}:{status:"FAILED",results:p,terminalResult:m}}async function $3({steps:r,stepsToExecute:e,logger:t,cacheStorage:n,orgId:o,testId:i,platform:a}){let s=W3(r,e);if(s&&Object.keys(s).length>0){t.info({diffs:es(s)},"Saving mobile step cache entries");let{cachesToSave:c}=await Bn({platform:a,steps:e,cacheCreationParams:{orgId:o,testId:i}});await n.saveEntries({logger:t,testId:i,entries:c})}else t.info("No cache entries to update")}import{Server as rJ}from"socket.io";import{tmpdir as q3}from"os";import M0 from"path";async function P0({socket:r,logger:e,orgId:t,testMetadata:n,globalOrgSettings:o,androidDriverFactory:i,mobileGeneratorFactory:a,browserGeneratorFactory:s,browserEnricherFactory:c,storageFactory:l,localToolsFactory:u,globalStateManager:d,getGitMetadata:p}){let m=r.id,g=await p(),h=r.handshake.query?.fileName,f=h?M0.basename(h,".test.yaml"):"",y=n.id,E=n.settings?.defaultChannel,b=n.settings?.defaultTag;e=e.child({sessionId:m,testId:y,orgId:t,branch:g.gitBranchName});let x=await l(t),P=n.settings?.defaultEnv,O={};P&&(O=(await x.fetchEnvironment(P,e))?.variables??{});let T=rs.parse(O[_i]),R=rs.parse(O[Dl]),D={...o.emulator,...n.settings?.emulator},I=n.settings?.defaultApkFilePath?.trim()||R,k=d.getSession(m);if(k){if(e.info("Reconnecting to existing Android session"),k.local)return r.emit("session",k.metadata),k.softDeleted=!1,k.metadata;throw new Error("Restoring existing remote emulator sessions is not supported. Please reconnect to a new emulator.")}let F;if(D.region==="local"){if(await d.clearSoftDeletedLocalSessions(e),d.hasActiveLocalSession())throw new Error("Another local emulator session is already active. Please close the existing session before creating a new one.");let hi=n.settings?.emulator?.localEmulatorSettings?.avdId?.trim()||T;if(!hi)throw new Error(`AVD ID is required when using a local emulator. Set it on the test (Options \u2192 Emulator \u2192 Local AVD ID) or on the environment via ${_i}.`);F={avdId:hi,apkToInstall:E?{channel:E,tag:b}:void 0,apkFilePath:I}}else F={region:D.region,apkToInstall:E?{channel:E,tag:b}:void 0,osVersion:D.remoteEmulatorSettings?.androidVersion};let ee=Date.now(),{driver:K,cleanup:ge,emulatorName:B,adbPort:j,limbarClient:ue,limbarToken:le,limbarUrl:He,playwrightDevice:ve}=await i({socket:r,logger:e,creationOpts:F}),q=M0.join(q3(),`logcat-logs-${t}-${y}-${m}.txt`),fe=await Pm({driver:K,onLogs:hi=>{r.emit("logcatLogs",hi)},logFilePath:q});e.info({adbPort:j,apkChannel:E,apkTag:b,duration:Date.now()-ee,emulatorName:B},"Android emulator session initiated"),e=e.child({emulator:B});let it=await a(t,e),Ae=await s(t,e),C=await c(t,e),oe=u?await u(t):void 0,pe=new Lo({variablesFromEnvironment:O,envName:P,testName:f}),Br=await oi.init({driver:K,generator:it,logger:e,limbarClient:ue,playwrightDevice:ve,aiSettings:{...o.ai,useMemory:o.ai?.useMemory!==!1,...n.settings?.ai},options:{emulator:{...D,browserSettings:o.browser}},fixtures:{storage:x,browserEnricher:C,browserGenerator:Ae,localCodeEvalTools:oe,testContext:pe},orgId:t,adbPort:j,abortController:new AbortController}),gi=await Br.getViewportBounds();if(!r.connected)throw await Br.cleanup(),await fe(),await ge(),new Error("Socket not connected anymore, not proceeding with Android session setup");let WD=K3({socket:r,testContext:pe}),VD=async()=>{clearInterval(WD);try{await Promise.allSettled([Br.cleanup(),fe(),ge()])}catch(hi){e.warn({err:hi},"Failed to clean up emulator in socket server")}},ie={sessionId:m,testId:y,orgId:t,emulatorName:B,testName:f,limbarUrl:He,limbarToken:le,viewportBounds:gi};return d.registerSession(m,{controller:Br,cleanup:VD,emulatorName:B,local:D.region==="local",metadata:ie,logFilePath:q}),r.emit("session",ie),ie}function K3({socket:r,testContext:e}){return setInterval(()=>{let t=e.toEditorDisplayCopy();r.emit("emulatorState",{context:t})},3e3)}import Kp from"fs/promises";async function I0({socket:r,logger:e,globalStateManager:t,authorization:n}){let o=r.id,i=t.getSession(o);i&&n&&i.logFilePath&&Y3({testId:i.metadata.testId,sessionId:o,logFilePath:i.logFilePath,authorization:n,logger:e}),await t.removeSession(o,e)}async function Y3({testId:r,sessionId:e,logFilePath:t,authorization:n,logger:o}){try{let i;try{i=await Kp.stat(t)}catch{o.debug({logFilePath:t},"No logcat file found to upload");return}if(i.size===0){o.debug({logFilePath:t},"Logcat file is empty, skipping upload"),await Kp.unlink(t);return}let a=new Pr(n),{uploadUrl:s}=await a.generateMobileLogcatUploadUrl({testId:r,sessionId:e}),c=await Kp.readFile(t),l=await fetch(s,{headers:{"Content-Length":c.length.toString(),"Content-Type":"text/plain"},method:"PUT",body:c});if(l.status!==200)throw new Error(`Failed to upload logcat: ${l.status} ${await l.text()}`);o.info({testId:r,sessionId:e},"Logcat file uploaded successfully")}catch(i){o.warn({err:i,testId:r,sessionId:e},"Failed to upload logcat file")}finally{try{await Kp.unlink(t)}catch(i){o.warn({err:i,logFilePath:t},"Failed to delete temp logcat file")}}}var X3=({socket:r,globalStateManager:e})=>async()=>{let t=e.getSession(r.id);if(!t)throw new Error("No active Android session found");t.controller.abort()},O0={event:"cancel",createHandler:X3};var J3=({logger:r,globalStateManager:e,socket:t})=>async(n,o)=>{let i=e.getSession(t.id);if(!i){o({err:"No active Android session found"});return}try{let s=await i.controller.getEmulatorDomState();o({screenXml:s})}catch(a){r.error({err:a},"Error fetching screen XML from the session controller"),o({err:a.message})}},L0={event:"fetchScreenXml",createHandler:J3};var Pb=class{parentTracer;socket;step;orgId;interactionTracer;constructor({step:e,socket:t,parentTracer:n,orgId:o}){this.socket=t,this.parentTracer=n,this.step=e,this.orgId=o,this.interactionTracer=new Xo,rn.initializeRootTracerContext(this.interactionTracer)}attachBeforeScreenshot(){}attachAfterScreenshot(){}attachBeforeXmlSnapshot(){}attachAfterXmlSnapshot(){}recordStepDuration(e){let{durationMs:t,step:n}=e,o=n.type!=="MOBILE_PRESET_STEP"?n.type:n.command.type;nt.distribution("test_step_duration",t,[`type:${o}`,"platform:mobile","executor:editor",`orgId:${this.orgId}`])}async finish(e){this.interactionTracer.finish();let t=this.interactionTracer.getRootSpan(),n={...iR.parse(e),trace:Kh.parse(t)};switch(n.result.status){case"SUCCESS":this.socket.emit("success",n);break;case"FAILED":this.socket.emit("failure",n);break;case"CANCELLED":this.socket.emit("cancelled",n);break}return{trace:t}}getParentStepIdChain(){return this.parentTracer?this.parentTracer?.getParentStepIdChain()??[]:[]}async startSubSteps(){return new ol({parentStep:this.step,socket:this.socket,parentTracer:this,orgId:this.orgId})}},ol=class{parentTracer;parentStep;socket;orgId;constructor({parentStep:e,socket:t,parentTracer:n,orgId:o}){this.parentTracer=n,this.parentStep=e,this.socket=t,this.orgId=o}getParentStepIdChain(){return this.parentStep?[...this.parentTracer?.getParentStepIdChain()??[],this.parentStep.id]:[]}async startStep(e){return this.socket.emit("started",{stepId:e.step.id,parentStepIdChain:e.parentStepIdChain,attempt:e.attempt}),new Pb({step:e.step,parentTracer:this,socket:this.socket,orgId:this.orgId})}async getScreenshot(e){}},Yp=class{constructor(e,t){this.socket=e;this.orgId=t}appendLogs(){}async finish(){this.socket.emit("finished")}async startBeforeStepList(){return new ol({parentStep:null,parentTracer:null,socket:this.socket,orgId:this.orgId})}async startMainStepList(){return new ol({parentStep:null,parentTracer:null,socket:this.socket,orgId:this.orgId})}async startAfterStepList(){return new ol({parentStep:null,parentTracer:null,socket:this.socket,orgId:this.orgId})}};var Z3=({metadata:r,logger:e,globalStateManager:t,socket:n,cacheStorageFactory:o,getGitMetadata:i})=>async(a,s)=>{let c=t.getSession(n.id);if(!c)throw new Error("No active Android session found");if(a.testMetadata.platform!=="ANDROID")throw new Error("Non-android tests aren't supported yet");let l=await i(),u=e.child({testId:a.testMetadata.id,branch:l.gitBranchName}),d=await o(r.orgId,l),p=c.controller;p.resetAbortController();let m=new Yp(n,r.orgId),g=await nl({platform:"ANDROID",work:{fastForwardingToStep:!!a.fromStep,state:{failureRecoveryDisabled:!0,failureRecoveryAttempts:0}},fixtures:{controller:p,logger:u,cacheStorage:d,usageTracker:new ld},containerName:"entire test",inputs:{steps:a.steps,fromStep:a.fromStep,toStep:a.toStep,orgId:r.orgId,testName:r.testName,testMetadata:a.testMetadata,interactive:!0},tracer:m,callbacks:{step:{onAiActionEvent:f=>{n.emit("aiActionEvent",f)}}}});await m.finish();let h={results:yr.array().parse(g.results),status:g.status};s?.(h)},N0={event:"execute",createHandler:Z3};import{debounce as Q3}from"ts-debounce";var eJ=({socket:r,globalStateManager:e,keepSessionAlive:t})=>{let n=Q3(t,3e4,{maxWait:6e4});return async()=>{let o=e.getSession(r.id);if(!o)throw new Error("No active Android session found");o.emulatorName&&(o.local||n(o.emulatorName))}},D0={event:"keepalive",createHandler:eJ};var tJ=({socket:r,globalStateManager:e,logger:t})=>async(n,o)=>{let i=e.getSession(r.id);if(!i){let s="No active Android session found";t.error(s),o?.({success:!1,err:s});return}let a=i.controller;a.abort(),a.resetAbortController(),t.info("Resetting emulator state");try{await a.softReset(),t.info("Emulator reset completed"),o?.({success:!0,message:"Emulator reset successfully"})}catch(s){let c=s instanceof Error?s.message:String(s);t.error({err:s},"Failed to reset emulator"),o?.({success:!1,err:`Failed to reset emulator: ${c}`})}},k0={event:"reset",createHandler:tJ};var F0=[N0,O0,k0,D0,L0];var Xp=class{sessions=new Map;registerSession(e,t){this.sessions.set(e,t)}getSession(e){return this.sessions.get(e)}async clearSoftDeletedLocalSessions(e){for(let t of this.sessions.values())t.softDeleted===!0&&t.local===!0&&await this.removeSession(t.metadata.sessionId,e)}hasActiveLocalSession(){for(let e of this.sessions.values())if(e.local===!0)return!0;return!1}async removeSession(e,t){let n=this.sessions.get(e);if(n)try{await n.cleanup?.(),t.info({sessionId:e,emulatorName:n.emulatorName},"Android emulator cleaned up by removeSession")}catch(o){t.error({err:o},"Error during Android session cleanup")}finally{this.sessions.delete(e)}}async removeAllSessions(e){let t=Array.from(this.sessions.keys());await Promise.all(t.map(n=>this.removeSession(n,e)))}};function U0(r){let{logger:e,baseServer:t,globalStateManager:n,settingsFactory:o,getOrgId:i}=r,a=new rJ(t,{cors:{origin:"*",methods:["GET","POST"]},pingTimeout:15*60*1e3,pingInterval:15*60*1e3,maxHttpBufferSize:1e7,perMessageDeflate:!0,connectionStateRecovery:{maxDisconnectionDuration:60*60*1e3,skipMiddlewares:!0}}),s=async()=>{await n.removeAllSessions(e)};a.on("connection",async l=>{let u=l.id,d=e.child({sessionId:u});d.info({event:"connection",transport:l.conn.transport.name},"Android websocket connection initiated"),l.on("disconnect",async g=>{if(e.info({reason:g},"Disconnect received"),g.includes("namespace disconnect")){await I0({socket:l,globalStateManager:n,logger:d,authorization:r.authorization});return}let h=n.getSession(u);h&&(h.softDeleted=!0)});let p,m;try{let g=l.handshake.query?.testMetadata,h=No.parse(JSON.parse(g??"")),f=h.id,y=await i({testId:f});m=await o(y,e),p=await P0({...r,orgId:y,socket:l,globalStateManager:n,logger:d,globalOrgSettings:m,testMetadata:h})}catch(g){d.error({err:g},"Failed to setup Android connection"),l.emit("error",{message:g instanceof Error?g.message:JSON.stringify(g)}),l.disconnect(!0);return}F0.forEach(g=>c(g,{...r,socket:l,metadata:p,globalOrgSettings:m,logger:d}))});let c=(l,u)=>{let d=l.createHandler(u),p=(...m)=>{l.event!=="keepalive"&&u.logger.debug({event:l.event},`Websocket event (${l.event})`);let g=h=>{u.logger.error({event:l.event,err:h instanceof Error?h:new Error(`${h}`)},"Unhandled exception in socket handler"),u.socket.emit("error",{message:h instanceof Error?h.message:typeof h=="string"?h:JSON.stringify(h)})};try{let h=d.apply(this,m);h&&typeof h.catch=="function"&&h.catch(g)}catch(h){g(h)}};u.socket.on(l.event,p)};return{server:a,dispose:s}}import RJ from"path";var Jp=new Xp;import{Router as oJ}from"express";import{existsSync as iJ}from"fs";import aJ from"path";import{hostname as nJ}from"os";var Ib="0.33.1",Ze=ds({app:"mobile-desktop-server",hostname:nJ(),disableConsoleLogs:!0}).child({cliVersion:Ib});(async()=>{try{let r=await du(Ze);r.gitBranchName&&Ze.addBinding("branch",r.gitBranchName)}catch{}})();var Ob=oJ();Ob.get("/",ke(async(r,e)=>{let t=Ir();if(!t){e.status(500).json({message:"API client not initialized"});return}let n=await t.getAndroidAssets();e.status(200).json(n)}));Ob.post("/upload-url",ke(async(r,e)=>{let t;try{t=QA.parse(r.body)}catch(i){e.status(400).json({error:`Invalid request body: ${i}`});return}let n=Ir();if(!n){e.status(500).json({error:"API client not initialized"});return}let o=aJ.resolve(t.filePath);if(!iJ(o)){e.status(400).json({error:`File not found: ${o}`});return}await Mm({tag:t.tag,channel:t.channel,filePath:o,apiClient:n,logger:Ze}),e.sendStatus(204)}));var B0=Ob;import{Router as cJ}from"express";import{Router as sJ}from"express";import z0 from"fs";import lJ from"path";var il=sJ();async function Zp(r){return(await tL(r,Ze)).map(n=>{let o=r.mobileModules[n.moduleId];if(!o){M.warn(`Found a dangling mobile module with ID ${n.moduleId} that could not be found on disk.`);return}return{...o,content:n}}).filter(n=>n!==void 0)}il.get("/",ke(async(r,e)=>{let t=We(),n=await Zt(t),o=await Zp(n);e.status(200).json(o)}));il.get("/tests-join",ke(async(r,e)=>{let t=We(),n=await Zt(t),o=await Zp(n),i={};for(let s of o)i[s.id]={...s,tests:[]};let a=await Promise.all(Object.values(n.mobileTests).map(async s=>({id:s.id,name:s.name,relativePath:s.relativePath,test:await So(s.fullFilePath,Ze,n)})));for(let{id:s,name:c,relativePath:l,test:u}of a){let d=new Set;switch(u.platform){case"ANDROID":GS({steps:u.steps,onPreset:()=>!1,onModule:p=>(d.add(p.moduleId),!1)});break;case"IOS":break;default:return(m=>{throw new Error("Unhandled platform")})(u)}for(let p of d){let m=i[p];m&&m.tests.push({id:s,name:c,relativePath:l})}}e.status(200).json(i)}));il.get("/:moduleId",ke(async(r,e)=>{if(!r.params.moduleId){e.status(400).json({error:"Missing moduleId in url path."});return}let t=await Zt(We()),n=t.mobileModules[r.params.moduleId];if(!n){e.status(404).json({error:"Mobile module not found."});return}try{let o=await jy(n,t,M);e.json(o)}catch(o){e.status(400).json({err:o})}}));il.patch("/:moduleId/metadata",ke(async(r,e)=>{if(!r.params.moduleId){e.status(400).json({error:"Missing moduleId in url path."});return}let t;try{t=tw.parse(r.body)}catch(i){e.status(400).json({error:`Invalid request body: ${i}`});return}let n=We(),o=await Zt(n);QO({moduleId:r.params.moduleId,patch:t,momenticFiles:o,logger:M,project:n}),e.status(201).json({message:"ok"})}));il.post("/",ke(async(r,e)=>{let t;try{t=rw.parse(r.body)}catch(c){e.status(400).json({error:`Invalid request body: ${c}`});return}try{_o(t.name)}catch(c){e.status(400).json({error:`Invalid module name: ${c}`});return}let n=We(),i=(await Zt(n)).mobileModules;if(Object.values(i).find(c=>c.name===t.name)){e.status(400).json({error:`A mobile module with the name "${t.name}" already exists. Please choose a different name.`});return}let a=lJ.join(n.rootDir,t.folderPath??"");if(!z0.existsSync(a)||!z0.statSync(a).isDirectory()){e.status(400).json({error:`The folder configured for mobile module creation does not exist: ${a}`});return}let s=await eL({...t,folder:a,project:n});e.status(201).json(s)}));var H0=il;var G0=cJ();G0.get("/",ke(async(r,e)=>{let t=We(),n=await Zt(t),o=await Zp(n),i=new Set;n?.mobileTests&&Object.values(n.mobileTests).forEach(l=>{l.labels?.forEach(u=>i.add(u))});let a=Array.from(i).sort(),s=Object.values(n.mobileTests),c={labels:a,modules:o,tests:s};e.status(200).json(c)}));var j0=G0;import{Router as uJ}from"express";var Qp=uJ();Qp.get("/",ke((r,e)=>{let t=HO(We(),Ze);e.status(200).json(t)}));Qp.get("/names",ke((r,e)=>{let n=We().config.environments?.map(o=>o.name)??[];e.status(200).json(n)}));Qp.post("/",ke((r,e)=>{let t;try{t=ew.parse(r.body)}catch(s){e.status(400).json({error:`Invalid request body: ${s}`});return}try{_o(t.name)}catch(s){e.status(400).json({error:`Invalid environment name: ${s}`});return}let n=We();if(n.config.environments?.find(s=>s.name===t.name)){e.status(400).json({error:`An environment with the name "${t.name}" already exists. Please choose a different name.`});return}let i={...n.config,environments:[...n.config.environments??[],{name:t.name}]};n.config=i,Cp(i,n.configFilePath);let a=da(t.name,n,Ze);e.status(201).json(a)}));var W0=Qp;import{Router as dJ}from"express";var V0=dJ();V0.get("/",(r,e)=>{e.status(200).json({userId:$p(),orgId:Yn(),cliVersion:Ib??"0.0.0"})});var $0=V0;import{Router as mJ}from"express";var q0=mJ();q0.get("/",ke(async(r,e)=>{let t=r.query.sessionId;if(!t){e.status(400).json({packages:[]});return}let n=Jp.getSession(t);if(!n?.controller){e.status(200).json({packages:[]});return}try{let a=(await n.controller.executeRawADBCommand("shell pm list packages -3"))?.split(`
4641
4641
  `).filter(s=>s.trim().startsWith("package:")).map(s=>s.replace("package:","").trim()).filter(s=>s.length>0&&!s.startsWith("io.appium"))||[];e.status(200).json({packages:a})}catch(o){Ze.error({err:o},"Error fetching installed packages from the session controller"),e.status(200).json({packages:[]})}}));var K0=q0;import{Router as pJ}from"express";var Lb=pJ(),gJ=async({steps:r,cacheStorage:e,stepId:t,parentStepIdChain:n,testId:o})=>{let{result:i}=WS(r,t,n);if(i)return await e.getCacheKeyForStep({logger:Ze,testId:o,parentStepIdChain:n,step:i})};Lb.patch("/",ke(async(r,e)=>{let t=We(),n=Yn(),o=Ir();if(!o){e.status(500).json({error:"API client not initialized"});return}let i;try{i=ow.parse(r.body)}catch(l){e.status(400).json({error:`Invalid request body: ${l}`});return}let a=await sn(Ze,o,t),s=mi({logger:Ze,orgId:n,client:o,gitMetadata:a,regenerateCache:!1,noCache:!1,alwaysSaveCache:!1}),c=await gJ({cacheStorage:s,steps:i.steps,stepId:i.stepId,parentStepIdChain:i.parentStepIdChain,testId:i.testId});if(!c){e.status(400).json({error:"Cache-supporting step not found"});return}await o.updateMobileStepCaches({entries:[{key:c,organizationId:n,value:i.value,testId:i.testId}],testId:i.testId},fc(a)),e.status(204).send()}));Lb.post("/traces",ke(async(r,e)=>{let t=Ir();if(!t){e.status(500).json({error:"API client not initialized"});return}let n;try{n=Cd.parse(r.body)}catch(i){e.status(400).json({error:`Invalid request body: ${i}`});return}let o=await t.getMobileStepCacheMemoryTraces(n);e.status(200).json(o)}));var Y0=Lb;import{Router as hJ}from"express";import Nb from"fs";import pi from"path";import{v4 as fJ}from"uuid";import SJ from"yaml";var al=hJ();al.patch("/:testPath",ke(async(r,e)=>{let t=r.params.testPath;if(!t){e.status(400).json({error:"Missing testPath in path"});return}let n;try{n=JA.parse(r.body)}catch(c){e.status(400).json({error:`Invalid request body: ${c}`});return}if(n.steps===void 0&&n.settings===void 0&&n.labels===void 0){e.status(400).json({error:"At least one of steps, settings, or labels is required"});return}let o=We(),i=t.endsWith(".test.yaml")?t:`${t}.test.yaml`,a=await Zt(o);await nL({filePath:i,steps:n.steps,settings:n.settings,labels:n.labels,folder:o.rootDir,project:o,momenticFiles:a,schemaVersion:xo});let s={message:"ok"};e.status(200).json(s)}));al.post("/",ke((r,e)=>{let t;try{t=XA.parse(r.body)}catch(g){e.status(400).json({error:`Invalid request body: ${g}`});return}let{name:n,description:o,settings:i,pathSegments:a}=t;if(!n||typeof n!="string"){e.status(400).json({error:"Missing or invalid 'name' in body"});return}try{_o(n)}catch(g){e.status(400).json({error:g.message});return}let s=We(),c=pi.join(s.rootDir,...a),{fullPath:l,testId:u}=rL({name:n,description:o,steps:[],settings:i,folder:c}),d=pi.basename(l),p=pi.relative(s.rootDir,l),m={id:u,fileName:d,fullPath:l,relativeFilePath:p};e.status(201).json(m)}));al.get("/:fileName",ke(async(r,e)=>{let t=Ir(),n=Yn(),o=r.params.fileName;if(!o){e.status(400).json({error:"Missing fileName in path"});return}if(!t){e.status(500).json({error:"API client not initialized"});return}let i=o.endsWith(".test.yaml")?o:`${o}.test.yaml`,a=pi.basename(i).replace(".test.yaml",""),s=We(),c=await Zt(s),l=await So(i,Ze,c),u=await sn(Ze,t,s);await mi({logger:Ze,orgId:n,client:t,gitMetadata:u,regenerateCache:!1,noCache:!1,alwaysSaveCache:!1}).resolveEntries({logger:Ze,platform:l.platform,testId:l.id,stepLists:{steps:l.steps}});let p={...l,name:a};e.status(200).json(p)}));al.patch("/:testPath/metadata",ke(async(r,e)=>{let t=r.params.testPath;if(!t){e.status(400).json({error:"Missing testPath in path"});return}let n;try{n=ZA.parse(r.body)}catch(c){e.status(400).json({error:`Invalid request body: ${c}`});return}let o=We(),i=t.endsWith(".test.yaml")?t:`${t}.test.yaml`,s={message:"ok",newRelativeTestPath:oL(i,n,o).newRelativeTestPath};e.status(200).json(s)}));al.post("/:testPath/duplicate",ke(async(r,e)=>{let{testPath:t}=r.params;if(!t){e.status(400).json({error:"Missing testPath in url path."});return}let n;try{n=nw.parse(r.body)}catch(h){e.status(400).json({error:`Invalid request body: ${h}`});return}try{_o(n.name)}catch(h){e.status(400).json({error:h.message});return}let o=We(),i=pi.join(o.rootDir,t);if(!Nb.existsSync(i)){e.status(404).json({error:"Test not found."});return}let a=await Zt(o),s;try{s=await So(i,Ze,a)}catch(h){e.status(400).json({error:h.message});return}let c=fJ(),{stepsToSave:l}=await Bn({...s,createNewCacheIds:!0}),u=po({fileType:Xe.MOBILE_TEST,id:c,schemaVersion:xo,description:s.description,platform:s.platform,settings:s.settings,labels:s.labels,steps:l});CA.parse(u);let d=pi.dirname(i),p=pi.join(d,`${n.name}.test.yaml`);if(Nb.existsSync(p)){e.status(409).send("A test with this name already exists");return}let m=SJ.stringify(u);Nb.writeFileSync(p,m,"utf-8");let g={relativeFilePath:pi.relative(o.rootDir,p)};e.status(201).json(g)}));var X0=al;import{Router as yJ}from"express";var J0=yJ();J0.get("/",ke((r,e)=>{let t=We(),n={ai:t.config.ai,displayRoot:t.config.displayRoot};e.status(200).json(n)}));var Z0=J0;import{Router as bJ}from"express";var Q0=bJ();Q0.post("/traces",ke(async(r,e)=>{let t=Ir();if(!t){e.status(500).json({error:"API client not initialized"});return}let n;try{n=Cd.parse(r.body)}catch(i){e.status(400).json({error:`Invalid request body: ${i}`});return}let o=await t.getWebStepCacheMemoryTraces(n);e.status(200).json(o)}));var eD=Q0;var eg=class extends Xs{constructor(t,n){super(t,n);this.client=t;this.orgId=n}async fetchEnvironment(t,n){let o=We();return da(t,o,M)}};var nD="10mb";async function oD(r){let{serverPort:e,apiKey:t,momenticServerUrl:n,staticDir:o,initialProject:i,driverLogLevel:a,regenerateCache:s,alwaysSaveCache:c,noCache:l}=r;n&&u0(n),d0({noCache:l,alwaysSaveCache:c}),await p0(t);let u=Yn(),d=$p(),p=r.logger.child({orgId:u,userId:d});g0(i,T=>Ws({configFilePath:T}));let m=rD();m.use(EJ()),m.use(tD.json({limit:nD})),m.use(tD.urlencoded({extended:!1,limit:nD}));let g=AJ();if(g.use("/folders",Rb),g.use("/entities",j0),g.use("/identify",$0),g.use("/mobile-tests",X0),g.use("/mobile-modules",H0),g.use("/mobile-cache",Y0),g.use("/web-cache",eD),g.use("/assets",B0),g.use("/git",Cb),g.use("/cache-config",wb),g.use("/environments",W0),g.use("/installed-packages",K0),g.use("/settings",Z0),m.use("/api",g),m.use((T,R,D)=>{M.debug({url:T.url,path:T.path,query:T.query,method:T.method,body:T.body,headers:T.rawHeaders,client:T.ip},"Incoming request on mobile-desktop-server"),R.on("close",()=>{R.statusCode>=400&&(M.error({url:T.url,method:T.method,statusCode:R.statusCode},"Request completed in error on mobile-desktop-server"),Ze.error({url:T.url,method:T.method,statusCode:R.statusCode},"Request completed in error on mobile-desktop-server"))}),D()}),m.use((T,R,D,I)=>{if(T instanceof Error&&T.message.includes("BadRequestError: request aborted")){D.status(400).send("Client disconnected");return}M.error({stack:T.stack,msg:T.message,err:T,url:R.url,method:R.method},"Unhandled exception leading to 500 on mobile-desktop-server"),Ze.error({stack:T.stack,msg:T.message,err:T,url:R.url,method:R.method},"Unhandled exception leading to 500 on mobile-desktop-server"),D.status(500).send(`Internal Server Error: ${T.message}`)}),o){m.use((R,D,I)=>{if(R.path==="/run-viewer"||R.path.startsWith("/run-viewer/"))return D.status(404).send("Not Found");I()});let T=rD.static(o,{setHeaders:R=>{R.setHeader("Cache-Control","no-cache")},redirect:!1});m.use(T),m.use("*",(R,D)=>{D.sendFile(RJ.join(o,"index.html"))})}let h=wJ.createServer(m),f=`http://localhost:${e}`;await new Promise(T=>{try{h.listen(e,()=>{p.info(`Mobile desktop server is running at ${f}`),T()})}catch(R){R.message.includes("EADDRINUSE")?CJ(e):M.error(`An unexpected error occurred while starting the server: ${R.message}`),process.exit(1)}});let E={type:"API_KEY",baseUrl:vb(),apiKey:t,logger:p},b=new Pr(E),x=We(),P={...E,mode:"interactive"},{dispose:O}=U0({baseServer:h,logger:p,authorization:E,globalStateManager:Jp,getOrgId:()=>Yn(),getGitMetadata:async()=>await sn(p,b,x),androidDriverFactory:async({socket:T,logger:R,creationOpts:D})=>{let I=Math.floor(Math.random()*1e4)+4e4,k=await zo(I,"appium");return _m({logger:R,driverLogLevel:a,apiClient:b,creationOpts:D,socket:T,appiumPort:k,sessionId:T.id,orgId:Yn(),callbacks:{onStatusUpdate:F=>{R.info({status:F},"Emulator status update"),T.emit("connectionStatusUpdate",{message:F,type:"info"})},onHeartbeatFailure:()=>{T.emit("connectionStatusUpdate",{message:"Emulator connection lost \u2014 possible ADB tunnel/emulator failure",type:"disconnected"})},onHeartbeatRestored:()=>{T.emit("connectionStatusUpdate",{message:"Emulator connection restored",type:"connected"})},onLimbarConnectionStateChange:F=>{F==="disconnected"?T.emit("connectionStatusUpdate",{message:"Emulator connection lost.",type:"disconnected"}):F==="reconnecting"||F==="connecting"?T.emit("connectionStatusUpdate",{message:"Reconnecting to emulator...",type:F==="reconnecting"?"reconnecting":"connecting"}):F==="connected"&&T.emit("connectionStatusUpdate",{message:"Emulator connection restored",type:"connected"})}}})},mobileGeneratorFactory:async T=>new Qs({baseUrl:vb(),apiKey:t,logger:p,mode:"interactive"}),browserGeneratorFactory:async T=>new ha(x.config.ai?.agentConfig,P),browserEnricherFactory:async T=>new Ys(P,new ha(x.config.ai?.agentConfig,P)),storageFactory:async T=>new eg(b,T),cacheStorageFactory:async(T,R)=>mi({logger:p,orgId:T,client:b,gitMetadata:R,regenerateCache:s,noCache:l,alwaysSaveCache:c}),localToolsFactory:async()=>new Zs({httpClient:b,fakerSeed:x.config.advanced?.fakerConstantSeed?gd:void 0}),keepSessionAlive:T=>b.extendAndroidEmulatorTtl(T),settingsFactory:async()=>({emulator:{},ai:{},browser:{},...x.config})});process.once("SIGUSR2",async()=>{return;try{await O(),await nt.flush()}catch(T){M.error({err:T},"Error during session dispose on SIGUSR2")}try{h.close(()=>{process.kill(process.pid,"SIGUSR2")})}catch{process.kill(process.pid,"SIGUSR2")}}),process.once("SIGTERM",async()=>{let T="SIGTERM in Momentic mobile app received";M.info(T),p.info(T);try{await O(),await nt.flush()}finally{h.close(()=>process.exit(0))}}),process.once("SIGINT",async()=>{M.info("SIGINT in Momentic mobile app received");try{await O(),await nt.flush()}finally{h.close(()=>process.exit(0))}})}vJ.setMaxListeners(25);process.on("warning",r=>{Ze.warn({err:r},`Node warning received on mobile-desktop-server: ${r.message}`)});process.on("uncaughtException",r=>{Ze.error({err:r},"Uncaught exception on mobile-desktop-server"),M.error(`Oh no! The Momentic mobile desktop app encountered a fatal error \u{1F61E}. Error logs: ${r.message}`)});process.on("unhandledRejection",r=>{Ze.error({reason:`${r}`,stack:r?.stack},"Uncaught exception on mobile-desktop-server (promise rejection)"),M.error(`Oh no! The Momentic mobile desktop app encountered an asynchronous error \u{1F61E}. Error logs: ${r}`)});function CJ(r){M.error(TJ`Port ${r} is already in use by another process. Please close the other process and try again.
4642
4642
  Using Bash on MacOS or Linux:
4643
4643
  lsof -t -i :58888 | xargs kill -9
@@ -4647,7 +4647,7 @@ Momentic users value the following:
4647
4647
  `)}import{Readable as A6}from"node:stream";import w6 from"open";import bo,{dirname as R6,resolve as C6}from"path";import{pipeline as x6}from"stream/promises";import{fileURLToPath as iE}from"url";import Db from"fs";import tg from"path";import{cwd as xJ}from"process";async function kb({tests:r,momenticFiles:e,project:t,yes:n,include:o,exclude:i,labels:a,logger:s,quarantinedTestsMetadata:c}){let l=new Set;if(r&&r.length>0){let d=r.some(m=>Db.existsSync(m)),p=xJ();d?(p!==t.rootDir&&s.warn(`The current working directory ('${p}') is different from the project root directory ('${t.rootDir}'). All test path arguments will be resolved relative to the current working directory and only those tests matched by the project inclusion configuration will be ran. To avoid confusion, Momentic strongly recommends running the CLI from the project root directory or using substring filters rather than file paths.`),s.info(`Reading tests from the following local file paths:
4648
4648
  - ${r.join(`
4649
4649
  - `)}
4650
- `),r.forEach(m=>{if(!Db.existsSync(m))throw new Error(`Path '${m}' does not exist.`);let g,h;try{g=Db.statSync(m),h=g.isDirectory()}catch(y){s.warn({err:y},`Skipping path ${m} because it cannot be read`);return}let f=tg.resolve(m);Object.values(e.mobileTests).filter(y=>h?y.fullFilePath.startsWith(f):y.fullFilePath===f).forEach(y=>{l.add(y.fullFilePath)})})):(s.info("The arguments provided don't appear to be valid paths. Treating them as substrings instead... "),Object.values(e.mobileTests).forEach(m=>{r.some(g=>m.relativePath.includes(g))&&l.add(m.fullFilePath)}))}else{!n&&!await Md("No test paths or substrings were provided. Do you want to run all tests?")&&(s.error("Cancelled by user."),process.exit(1));let d=Object.values(e.mobileTests);s.info(`Reading all ${d.length} mobile tests in the project from local disk.`),d.forEach(p=>{l.add(p.fullFilePath)})}for(let d of Array.from(l)){let p=tg.relative(t.rootDir,d);o&&!o.some(m=>new RegExp(m).test(p))&&l.delete(d),i&&i.some(m=>new RegExp(m).test(p))&&l.delete(d)}return(await Promise.all(Array.from(l).map(async d=>{try{let p=tg.relative(t.rootDir,d),m=await So(d,s,e),g=tg.basename(d,".test.yaml");if(m.disabled)return null;if(a&&a.length>0){let f=m.labels||[];if(!a.some(E=>f.includes(E)))return null}let h={id:m.id,name:g,description:m.description,schemaVersion:m.schemaVersion,settings:m.settings,fullFilePath:d,relativeFilePath:p,quarantined:!!c[m.id],quarantinedMetadata:c[m.id],labels:m.labels};switch(m.platform){case"ANDROID":return{...h,platform:"ANDROID",steps:m.steps};case"IOS":return{...h,platform:"IOS",steps:m.steps};default:return(y=>{throw new Error("You missed a case in the switch above")})(m)}}catch(p){s.error(`Failed to read and resolve mobile test at '${d}': ${p}`),process.exit(1)}}))).filter(d=>!!d)}import{InvalidArgumentError as rg,Option as Qe}from"@commander-js/extra-typings";import{z as _J}from"zod";var iD=58890;function sl(r){let e=parseInt(r,10);if(isNaN(e))throw new rg("Not a number.");return e}var Sa=new Qe("--api-key <key>","Momentic API key").env("MOMENTIC_API_KEY").argParser(r=>{if(!r)throw new rg("API key is required.");return r}).makeOptionMandatory(),ng=new Qe("-c, --config <configPath>","Absolute or relative path to a Momentic configuration file."),Fb=new Qe("-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."),ya=new Qe("--server <server>","Momentic server to use.").env("MOMENTIC_SERVER").default("https://api.momentic.ai").argParser(r=>{try{return _J.string().url().parse(r),r}catch{throw new rg("Not a valid URL.")}}),Ub=new Qe("-y, --yes","Skip all confirmation prompts.").env("CI"),Bb=new Qe("--regenerate-cache","Regenerate all caches by starting from an empty cache state. This flag is useful for completely regenerating caches after changing configuration options. Warning: using this option will cause all steps to run without any cached data, resulting in significantly longer execution times."),zb=new Qe("--save-cache","Always save updated step caches after successful test runs. By default, caches are not saved when running on protected branches.").env("CI"),Hb=new Qe("--disable-cache","Disable using step caches completely. Using this option may lead to non-deterministic behavior and significantly longer runtimes.").implies({saveCache:!1}),Gb=new Qe("--tag <tag>","Tag identifier for the asset."),aD=new Qe("--channel <channel>","Channel name for the asset."),jb=new Qe("--channel <channel>","Channel name for the asset.").makeOptionMandatory(),sD=new Qe("--tag <tag>","Tag identifier for the asset.").makeOptionMandatory(),lD=new Qe("--env <env>","Environment to run all tests in (overrides test-level configuration)."),vu="closest",cD=new Qe("--region <region>",`Region to run all tests in (overrides all other configuration). Valid values: ${Object.values(zi).join(", ")}, ${vu}, ${Object.values(Hi).join(", ")}.`),uD=new Qe("--local-avd-id <localAvdId>","Force tests to use a specific local Android Virtual Device (AVD) instead of remote emulators."),dD=new Qe("--local-apk-path <localApkPath>","Path to a local APK file to install when running tests with a local emulator. Overrides remote asset configuration."),mD=new Qe("-p, --parallel <parallel>","The number of tests to run in parallel. Defaults to 1.").argParser(sl),pD=new Qe("--shard-index <shardIndex>","The index of the shard to run tests for. Defaults to 1.").default(1).argParser(r=>{let e=sl(r);if(e<1)throw new rg("Shard index must be greater than 0.");return e}),gD=new Qe("--shard-count <shardCount>","The number of shards that tests are being run on. Defaults to 1.").default(1).argParser(sl),Wb=new Qe("--output-dir <outputDir>","Output directory to store run artifacts such as screenshots, results, and logs."),Vb=new Qe("--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."),$b=new Qe("--exclude <excludePatterns...>","The inverted version of --include: a test that matches any of the provided exclusion patterns will be excluded from running."),hD=new Qe("--upload-results","Upload test results to Momentic Cloud.").default(!1),qb=new Qe("--log-level <logLevel>","Log level for Momentic and dependent services.").choices(["error","warn","info","debug"]),fD=new Qe("--ignore-quarantine","Run all tests even if they are quarantined. This is useful for validating that quarantined tests are fixed before moving them out of quarantine.").implies({skipQuarantined:!1,onlyQuarantined:!1}),SD=new Qe("--timeout-minutes <timeoutMinutes>","Maximum number of minutes to run tests before stopping. When the timeout is reached, tests will stop and current results will be printed.").argParser(sl),yD=new Qe("--reporter <reporter>","Output report files in a standardized format to a local directory.").choices(Object.values(zl)),bD=new Qe("--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.").default("reports"),ED=new Qe("--name <name>","A name to associate with this run for easier identification in the Momentic dashboard.");import{randomUUID as y6}from"crypto";import{existsSync as b6}from"fs";import{dirname as l6}from"path";import{randomUUID as PJ}from"crypto";import{existsSync as IJ,statSync as OJ}from"fs";import TD from"path";import LJ from"zod";async function vD({runTracer:r,metadata:{orgId:e,runId:t},fixtures:{logger:n,apiClient:o,mobileGenerator:i,storage:a,cacheStorage:s,usageTracker:c,browserEnricher:l,browserGenerator:u,localCodeEvalTools:d},inputs:{channel:p,tag:m,project:g,testDefinition:h},env:{envName:f,envVariables:y},settings:{emulatorSettings:E,aiSettings:b},options:{logLevel:x,localAvdId:P,localApkPath:O,region:T}}){let R=Math.floor(Math.random()*1e4)+4e4,D=await zo(R,"appium"),I=Za.or(LJ.literal(vu)).optional().parse(T??E.region),k=I==="local",F;if(k){let q;if(O&&(q=TD.resolve(O),!IJ(q)||!OJ(q).isFile()))throw new Error(`Local APK path "${q}" does not exist. Provide a valid file path via --local-apk-path.`);let fe,it=h.settings?.defaultApkFilePath;if(it){let gi=it.trim();gi&&(fe=gi)}let Ae=typeof y[_i]=="string"?y[_i].trim():void 0,C=typeof y[Dl]=="string"?y[Dl].trim():void 0,oe;C&&(oe=TD.resolve(C));let pe=q??fe??oe,Br=P??E.localEmulatorSettings?.avdId??Ae;if(!Br)throw new Error(`An AVD ID is required when using a local region. Provide --local-avd-id, configure a default local AVD ID on the test's settings, or set the ${_i} key on the environment.`);F={avdId:Br,apkFilePath:pe}}else F={region:I==="closest"?void 0:I,apkToInstall:p?{channel:p,tag:m}:void 0,osVersion:E.remoteEmulatorSettings?.androidVersion??hA};let ee=PJ(),K=n.child({runAttemptId:ee}),ge;try{ge=await _m({apiClient:o,logger:n,driverLogLevel:x,creationOpts:F,callbacks:{onStatusUpdate:q=>{n.debug({status:q},"Emulator status update")},onHeartbeatFailure:()=>{let q="Appium heartbeat connection lost \u2014 possible ADB tunnel/emulator failure";M.warn(q)},onHeartbeatRestored:()=>{let q="Appium heartbeat connection restored";M.info(q)},onLimbarConnectionStateChange:q=>{q==="disconnected"?M.warn("Emulator websocket connection lost. Emulator may be unavailable."):(q==="reconnecting"||q==="connecting")&&M.info("Emulator websocket is reconnecting...")}},appiumPort:D,orgId:e,sessionId:ee})}catch(q){let fe=`Fatal error creating Android driver, failing test run attempt (runId: ${t})`;return n.error({err:q},fe),M.error({err:q},fe),{status:"FAILED",results:[],error:new w("UserConfigurationError",`Fatal error creating Android driver: ${q.message}`)}}let B=await r.startAttempt({emulatorName:ge.emulatorName,runAttemptId:ee});K=K.child(B.loggerBindings||{});let j=await Pm({driver:ge.driver,onLogs:q=>{B.appendLogs(q)}}),ue=new Lo({variablesFromEnvironment:y,envName:f,testName:h.name}),le=await oi.init({driver:ge.driver,generator:i,logger:K,limbarClient:ge.limbarClient,playwrightDevice:ge.playwrightDevice,orgId:e,adbPort:ge.adbPort,options:{emulator:{...E,browserSettings:g.config.browser}},aiSettings:b,fixtures:{storage:a,browserEnricher:l,browserGenerator:u,localCodeEvalTools:d,testContext:ue}}),He;try{He=await nl({platform:"ANDROID",containerName:`android test ${h.name}`,fixtures:{controller:le,logger:K,cacheStorage:s,usageTracker:c},work:{state:{failureRecoveryDisabled:b.failureRecovery===!1,failureRecoveryAttempts:0}},inputs:{testName:h.name,steps:h.steps,orgId:e,testMetadata:h},tracer:B,callbacks:{}})}finally{await j(),await ge.cleanup(),await le.cleanup()}await B.finish({logger:K,results:He.results,status:He.status,assetDetails:{avdId:"avdId"in F?F.avdId:void 0,tag:"apkToInstall"in F?F.apkToInstall?.tag:void 0,channel:"apkToInstall"in F?F.apkToInstall?.channel:void 0}});let ve;if(He.status==="FAILED"&&He.terminalResult){let q=He.terminalResult.message;q?ve=w.fromMessage(q):ve=new w("UnknownError",q||"Unknown failure")}return{...He,error:ve}}import{randomUUID as r6}from"crypto";import{remote as kJ}from"webdriverio";var og="NATIVE_APP";var ig=class{constructor(e){this.driver=e}async executeWebViewScript(e,t,...n){return this.executeInContext(e,async o=>{let i=new Function("...args",`${eu.safariUtilsLibJs}; const userFn = ${t.toString()}; return userFn(momenticFunctions, ...args);`);return o.execute(i,...n)})}async executeInNativeContext(e){return this.executeInContext(og,e)}async executeInContext(e,t){return await this.driver.switchContext(e),await t(this.driver)}};import{createInstanceClient as NJ}from"@limrun/api/ios-client";import{hostname as DJ}from"os";async function AD(r){let{apiClient:e,logger:t,creationOpts:n,logLevel:o,orgId:i,sessionId:a,onConnectionStateChange:s}=r,{token:c,webRtcUrl:l,wdaUrl:u,apiUrl:d,id:p,region:m}=await e.createIosEmulator({...n,hostname:DJ(),sessionId:a});t.info({emulatorName:p,region:m,sessionId:a},"ios instance creation ok");let g=await nt.recordDuration({fn:async()=>await NJ({apiUrl:d,token:c,logLevel:o}),name:"test_event_duration",tags:["name:limbar-client-creation","clientOs:ios",`orgId:${i}`]});return s&&g.onConnectionStateChange(s),{close:()=>{g.disconnect()},limbarToken:c,limbarWebRtcUrl:l,limbarApiUrl:d,limbarWdaUrl:u,emulatorName:p,limbarClient:g}}async function wD({wdaUrl:r,token:e}){try{let t=new AbortController;return setTimeout(()=>t.abort(),3e3),await fetch(r+"/status",{headers:{Authorization:`Bearer ${e}`},signal:t.signal}),!0}catch{return!1}}async function RD({creationOpts:r,apiClient:e,logger:t,driverLogLevel:n,appiumPort:o,orgId:i,sessionId:a,callbacks:s}){let c=Date.now();t.info("Starting ios driver creation");let{onLimbarConnectionStateChange:l}=s,u=[],d=await AD({apiClient:e,logger:t,creationOpts:r,orgId:i,sessionId:a,onConnectionStateChange:l}),p=d.emulatorName;u.push(()=>e.deleteIosEmulator(p),d.close);let m=async()=>{for(let g=u.length-1;g>=0;g-=1)try{await u[g]()}catch(h){if(h instanceof Error&&["ECONNREFUSED","ECONNRESET","UND_ERR_CLOSED"].some(f=>h.message.includes(f)))continue;t.warn({err:h},"Error running cleanup task")}};try{let g=await FJ({logger:t,driverLogLevel:n,appiumPort:o,emulatorStart:c,emulatorCreationParams:d,apiClient:e,creationOpts:r,orgId:i,sessionId:a,callbacks:s});return u.push(g.appiumClose),u.push(async()=>g.driver.deleteSession()),g.driver.getPageSource().catch(()=>{}),{...d,...g,driver:new ig(g.driver),cleanup:m,appiumPort:o}}catch(g){throw await m(),new Error(`Failed to start Appium driver: ${g}`)}}async function FJ({logger:r,driverLogLevel:e="warn",emulatorStart:t,appiumPort:n,emulatorCreationParams:o,callbacks:{onStatusUpdate:i,onLimbarConnectionStateChange:a}}){let s=[],{emulatorName:c,limbarWdaUrl:l,limbarApiUrl:u,limbarToken:d,limbarClient:p}=o,m=Date.now(),{close:g,logFile:h}=await vc({logger:r,logLevel:e,appiumPort:n});await wD({wdaUrl:l,token:d})||(r.debug({emulatorName:c},"WDA is not running on the Limbar iOS emulator"),await p.simctl(["launch","booted","com.facebook.WebDriverAgentRunner.xctrunner"]).wait(),r.debug({emulatorName:c},"WDA launched"));let f={platformName:"iOS","appium:automationName":"XCUITest","appium:noReset":!0,"appium:fullReset":!1,"appium:webDriverAgentUrl":l,"appium:wdaLocalPort":443,"appium:useNewWDA":!1,"appium:usePreinstalledWDA":!0,"appium:newCommandTimeout":3600,"appium:autoWebview":!1,"appium:webviewConnectTimeout":500,"appium:webviewConnectRetries":5,"appium:includeSafariInWebviews":!0,"appium:fullContextList":!1,"appium:additionalWebviewBundleIds":["*"],"appium:waitForQuiescence":!1,"appium:settings":{customSnapshotTimeout:0},"appium:limInstanceApiUrl":u,"appium:limInstanceToken":d,"appium:wdaRequestHeaders":{Authorization:`Bearer ${d}`}},y=Date.now(),E=await kJ({capabilities:f,hostname:"localhost",port:n,path:"/",protocol:"http",logLevel:e}),b=new Map;return E.on("command",P=>{b.set(P.command,Date.now())}),E.on("result",P=>{let O=b.get(P.command);if(!O)return;let T=Date.now()-O;P.result instanceof Error?r.warn({err:P.result,command:P.command,args:P.body,durationMs:T},"Appium cmd failed"):T>1e4&&r.warn({command:P.command,args:P.body,durationMs:T},"Appium cmd took very long"),b.delete(P.command)}),r.info({timings:{emulatorDuration:m-t,appiumDuration:y-m,wdioDuration:Date.now()-y},capabilities:f,emulatorName:c},"Started Appium driver"),{onStatusUpdate:i,driver:E,appiumClose:async()=>{await g(),await Promise.all(s.map(P=>P()))},appiumPort:n,appiumLogFile:h,emulatorName:c}}import{createHash as ZJ}from"crypto";import QJ from"jpeg-js";import{PNG as LD}from"pngjs";import VJ from"@prettier/plugin-xml";import $J from"prettier";import{DOMParser as qJ,XMLSerializer as KJ}from"slimdom";import{reduce as UJ}from"lodash-es";var BJ=new Set(["id","processId","bundleId","type","accessible","index","x","y","width","height"]),zJ=new Set([]),HJ=new Set(["name","label","traits"]),GJ=new Set(["live-region","drawing-order"]),jJ=new Set(["visible","enabled"]);function CD(r){let e={},t=r.tagName,n=UJ(r.attributes,(o,i)=>(o[i.name]=i.value,o),{});for(let[o,i]of Object.entries(n))BJ.has(o)||o==="class"&&t===i||o==="focusable"&&i==="true"&&n.clickable==="true"||zJ.has(o)&&i==="false"||HJ.has(o)&&i===""||jJ.has(o)&&i==="true"||GJ.has(o)&&i==="0"||(e[o]=i);return e.name&&e.label&&e.name===e.label&&delete e.label,e.name&&e.value&&e.name===e.value&&delete e.value,e}function ag(r){let e=r.getAttribute("x"),t=r.getAttribute("y"),n=r.getAttribute("width"),o=r.getAttribute("height");if(e===null||t===null||n===null||o===null)return;let i=parseFloat(e),a=parseFloat(t),s=parseFloat(n),c=parseFloat(o);if(!(isNaN(i)||isNaN(a)||isNaN(s)||isNaN(c)))return[i,a,i+s,a+c]}function Kb(r,e){let[t,n,o,i]=e;r.setAttribute("bounds",`[${t}, ${n}, ${o}, ${i}]`)}function WJ(r){let e=r.match(/\[\s*([-\d.]+)\s*,\s*([-\d.]+)\s*,\s*([-\d.]+)\s*,\s*([-\d.]+)\s*\]/);if(!e)return;let t=parseFloat(e[1]),n=parseFloat(e[2]),o=parseFloat(e[3]),i=parseFloat(e[4]);if(!(isNaN(t)||isNaN(n)||isNaN(o)||isNaN(i)||o<t||i<n))return[t,n,o,i]}function xD(r){let e=r.getAttribute("bounds");if(e)return WJ(e)}function _D(r,e){if(!e)return!0;let t=ag(r);return t?Yb(t,e):!0}function Yb(r,e){if(!e)return!0;let[t,n,o,i]=r;return!(o<e.left||t>e.right||i<e.top||n>e.bottom)}var MD=new Set(["XCUIElementTypeWebView"]);function YJ(r){if(MD.has(r.tagName))return!0;let e=r.getAttribute("name");if(e&&(e.startsWith("TabDocument")||e.startsWith("BrowserView"))){let t=e.match(/UUID=([A-F0-9-]+)/),n=e.match(/WebViewProcessID=(\d+)/);if(t&&n)return!0}return!1}function XJ(r){let e=["android.widget.","android.view.","android.webkit.","android.app.","android.support.","androidx.","com.android.inputmethod."];for(let t of e)if(r.startsWith(t))return r.substring(t.length);return r}function Xb(r,e){let{idCounter:t,idToElement:n}=r,o=t.value++;e.setAttribute("id",String(o)),n.set(o,e)}function Jb(r){if(MD.has(r.tagName))return r.children.length>0?Jb(r.children[0]):void 0;if(r.tagName==="XCUIElementTypeOther"&&r.hasAttribute("name")&&r.hasAttribute("label"))return ag(r);if(r.children.length===1){let e=r.children[0];return Jb(e)}}function PD(r,e,t,n){let{document:o}=t,{parentFrameBounds:i,pruneElementsOutsideBounds:a}=n;if(e.type==="element"){let s=o.createElement(e.role||e.tag);if(e.name&&s.setAttribute("name",e.name),e.description&&s.setAttribute("description",e.description),e.classes&&e.classes.length>0&&s.setAttribute("classes",e.classes.join(" ")),e.attrs)for(let[u,d]of Object.entries(e.attrs))s.setAttribute(u,d);let c=e.boundingRect,l=[i[0]+c.x,i[1]+c.y,i[0]+c.x+c.width,i[1]+c.y+c.height];if(!Yb(l,a))return;Kb(s,l),Xb(t,s),r.appendChild(s);for(let u of e.children)PD(s,u,t,n)}else if(e.type==="text"){let s=o.createElement("text");Xb(t,s),r.appendChild(s);let c=o.createTextNode(e.text);s.appendChild(c)}}function ID(r,e,t,n){let{pruneElementsOutsideBounds:o}=n,{document:i}=t;Xb(t,e);let a=CD(r);for(let[l,u]of Object.entries(a))e.setAttribute(l,u);let s=ag(r);if(s&&Kb(e,s),YJ(r)){let{removeWebviewContent:l,injectedWebviewContent:u}=n;if(l)return;if(u){let d=Jb(r);if(d){PD(e,u,t,{parentFrameBounds:d,pruneElementsOutsideBounds:o});return}}}let c=Array.from(r.childNodes??[]);for(let l of c){let u=l.nodeType;if(u===3){let d=l.nodeValue;d&&d.trim().length>0&&e.appendChild(i.createTextNode(d));continue}if(u===1){let d=l;if(!_D(d,o))continue;let p=i.createElement(XJ(d.tagName));ID(d,p,t,n),e.appendChild(p)}}}async function JJ(r,e,t){let n=r.parseFromString("<AppiumAUT/>","text/xml"),o=new Map,i={document:n,idToElement:o,idCounter:{value:0}},a=n.documentElement;ID(e,a,i,t);let s=new KJ().serializeToString(n),c=await $J.format(s,{parser:"xml",plugins:[VJ],printWidth:120,tabWidth:1,singleAttributePerLine:!1});return{prunedDocument:n,idToElement:o,prunedXml:c}}async function OD(r,e){let t=new qJ,o=t.parseFromString(r,"text/xml").documentElement;if(!o)throw new Error("No root element found in XML");if(o.tagName!=="AppiumAUT")throw new Error("No AppiumAUT element found in XML");let{prunedXml:i,idToElement:a,prunedDocument:s}=await JJ(t,o,e);return{xml:i,idToElement:a,document:s}}var sg=class r{driver;limbarClient;orgId;options;aborter;constructor({driver:e,limbarClient:t,orgId:n,options:o,aborter:i}){this.driver=e,this.limbarClient=t,this.orgId=n,this.options=o,this.aborter=i}static async init({driver:e,limbarClient:t,orgId:n,options:o,aborter:i}){return new r({driver:e,orgId:n,options:o,aborter:i,limbarClient:t})}async getContexts(){let e=await this.driver.executeInNativeContext(async n=>await n.getContexts({})),t=e.filter(n=>n!==og);return{contexts:e.map(n=>n),webviews:t}}async getRawScreenshotBase64(e,t=2){let n=se(),o;for(let i=0;i<t;i++)try{return await n.startAsyncSpan("EMULATOR_READ_STATE",async()=>{let a=await this.limbarClient.screenshot(),s=Buffer.from(a.base64,"base64"),c=QJ.decode(s),l=new LD({width:c.width,height:c.height});return l.data=Buffer.from(c.data),LD.sync.write(l).toString("base64")},{name:"Take screenshot",signal:this.aborter.controller?.signal,timeoutMs:3e3})}catch(a){if(o=a,e.warn({err:a},"Failed to take screenshot"),i===t-1)throw a}throw new w("InternalWebAgentError",`Failed to take screenshot: ${o}`)}async getCurrentScreenshotPngString(e){return`data:image/png;base64,${await this.getRawScreenshotBase64(e,1)}`}async waitForScreenshotStability({logger:e,timeoutMs:t,signal:n,reason:o,tolerancePercent:i=1}){let a=Date.now(),s,c=!1;for(;Date.now()-a<t;){if(n?.throwIfAborted(),!s){s=await this.getRawScreenshotBase64(e);continue}let l=await this.getRawScreenshotBase64(e);if(ps(s,l)<=i){c=!0;break}s=l,await J(250,n)}c||e.warn({purpose:o},"Timed out waiting for screenshot stability")}async waitForPageSourceStability({logger:e,timeoutMs:t,signal:n,reason:o}){await se().startAsyncSpan("WAIT_FOR_PAGE_STABILITY",async i=>{i.attributes.reason=o;let a=Date.now(),s,c,l=!1;for(;Date.now()-a<t;){c&&c<250&&await J(250-c,n),n?.throwIfAborted();let u=Date.now(),d;try{d=await this.limbarClient.elementTree()}catch(m){e.warn({err:m},"Failed to get page source during stability wait"),c=Date.now()-u;continue}let p=ZJ("md5").update(d).digest("hex");if(c=Date.now()-u,s&&s===p){l=!0;break}s=p}l||(i.attributes.timedOut=!0,e.warn({purpose:o},"Timed out waiting for page source stability"))})}async getActiveWebview(){let t=(await this.getContexts()).webviews;if(t.length>1)throw new w("UserInfrastructureError","Multiple active webviews in a single package is currently not supported");return t[0]}async getActiveWebviewContent(){let e=await this.getActiveWebview();if(!e)return;this.throwIfAborted();let t=await this.driver.executeWebViewScript(e,n=>n.dumpA11yTree());if(t)return JSON.parse(t)}async getDomState(e,t){let o=t?.filterOffscreenElements??!0?await this.getViewportBounds():void 0,i=await this.getPageSource();this.throwIfAborted();let a;if(!t?.skipFetchingFullWebviewContent)try{a=await this.getActiveWebviewContent()}catch(c){e.error({err:c},"Could not get webview info to get the nested DOM state")}return this.throwIfAborted(),{graph:await OD(i,{injectedWebviewContent:a,removeWebviewContent:t?.removeWebviewContent,pruneElementsOutsideBounds:o})}}async getPageSource(){return await se().startAsyncSpan("EMULATOR_READ_STATE",()=>this.driver.executeInNativeContext(async n=>n.getPageSource()),{name:"Get iOS page source",signal:this.aborter.controller?.signal})}async getViewportBounds(){let e=await this.driver.executeInNativeContext(async t=>t.getWindowRect());return{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height}}throwIfAborted(){this.aborter.controller?.signal.throwIfAborted()}};function ND({aiResponse:r,description:e,emulatorState:t}){let n=t.graph.idToElement.get(r.id);if(!n)throw new Error(`Could not find node with id: ${r.id}`);let o=xD(n);if(!o)throw new Error(`Could not determine bounds for element with id: ${r.id}, description: ${e}`);return{target:{type:"NATIVE",bounds:o},resolvedNode:n}}var Xn=class{limbarClient;driver;stateManager;generator;fixtures;orgId;aiSettings;aborter;constructor(e){this.stateManager=e.stateManager,this.driver=e.driver,this.limbarClient=e.limbarClient,this.aborter=e.aborter,this.fixtures=e.fixtures,this.orgId=e.orgId,this.generator=e.generator,this.aiSettings=e.aiSettings}async findElement({logger:e,description:t,skipFetchingFullWebviewContent:n=!1,removeWebviewContent:o=!1,useMemory:i=!1,metadata:a}){let s=e.child({...a});await this.stateManager.waitForScreenshotStability({logger:e,timeoutMs:5e3,signal:this.aborter.controller?.signal,reason:"Waiting for stability before locating an element with AI"});let c=await this.stateManager.getDomState(e,{skipFetchingFullWebviewContent:n,removeWebviewContent:o}),l=await this.stateManager.getCurrentScreenshotPngString(e),u;try{u=await this.generator.getIosElementLocation({description:t,screenXml:c.graph.xml,screenshot:l},{logger:s,loggerTags:ye(s),abortSignal:this.aborter.controller?.signal,useMemory:i,agentConfigVersion:this.aiSettings.agentConfig?.["ios-locator"]})}catch(m){throw this.throwIfAborted(),s.error({err:m},"Failed to locate element"),new Error(`ActionFailureError: Failed to locate element: ${m instanceof Error?m.message:m}`)}if(u.id===-1)throw new w("NoMatchingElementError",u.thoughts??"No matching element found");let{target:d,resolvedNode:p}=ND({aiResponse:u,description:t,emulatorState:c});return{resolvedTarget:{...d,resolvedNode:p},thoughts:u.thoughts}}async wrapTargetingAction(e){let{logger:t,action:n,description:o,command:i,cacheIsInvalidAfterResolution:a,skipFetchingFullWebviewContent:s=!1,removeWebviewContent:c=!1}=e,l={commandId:i.id},u=!1,d;i.disableCache&&(t.debug({command:i},"Cache explicitly disabled for command"),u=!0,d=void 0),a&&(u=!0,d=void 0),d&&d?.resolvedDescription!==o&&(t.info({description:o,cacheDescription:d?.resolvedDescription},"Cache description mismatch, clearing it automatically"),u=!0,d=void 0),t.info({description:o,cacheBustedBeforeAction:u},"Prompting AI for a new element location");let p=await this.findElement({logger:t,description:o,skipFetchingFullWebviewContent:s,removeWebviewContent:c,metadata:l}),m=p.thoughts;return{result:await n(p.resolvedTarget),thoughts:m}}constructPerformerParams(){return{limbarClient:this.limbarClient,stateManager:this.stateManager,driver:this.driver,fixtures:this.fixtures,aborter:this.aborter,orgId:this.orgId,generator:this.generator,aiSettings:this.aiSettings}}throwIfAborted(){this.aborter.controller?.signal.throwIfAborted()}get abortSignal(){return this.aborter.controller?.signal}};var lg=class extends Xn{async doPress({name:e,longPress:t}){return this.driver.executeInNativeContext(n=>n.executeScript("mobile: pressButton",[{name:e,isLongPress:t}]))}};function e6(r){let e={relativePosition:r.relativePosition};if(r.doubleTap&&r.longPress)throw new Error("UserConfigurationError: Cannot specify both doubleTap and longPress");return r.doubleTap?{...e,doubleTap:!0,doubleTapDelayMs:r.doubleTapDelayMs}:r.longPress?{...e,longPress:!0,longPressDurationMs:r.longPressDurationMs}:e}var ll=class extends Xn{async tapOnAbsoluteCoordinates(e,t){let n=t.x,o=t.y;if(e.info({x:n,y:o},"Tap at coordinates"),t.longPress){let i=t.longPressDurationMs??2e3;await this.driver.executeInNativeContext(a=>a.tap({x:n,y:o,duration:i}));return}if(t.doubleTap){await this.driver.executeInNativeContext(a=>a.tap({x:n,y:o}));let i=t.doubleTapDelayMs??100;await new Promise(a=>setTimeout(a,i))}await this.driver.executeInNativeContext(i=>i.tap({x:n,y:o}))}async tapOnNativeTarget(e,t,n){let[o,i,a,s]=t.bounds,c=a-o,l=s-i,u=n?.relativePosition?.x??c/2,d=n?.relativePosition?.y??l/2;u=Math.max(0,Math.min(u,c)),d=Math.max(0,Math.min(d,l));let p=o+u,m=i+d;return await this.tapOnAbsoluteCoordinates(e,{x:p,y:m,...n}),{x:p,y:m}}async tapOnTarget({logger:e,target:t,options:n}){if("type"in t&&t.type==="NATIVE")await this.tapOnNativeTarget(e,t,n);else throw new Error("Not implemented yet")}async executeTap({logger:e,command:t}){let n=e6(t);if(t.target.type==="coordinates"){let a=await this.driver.executeInNativeContext(async l=>l.getWindowSize()),s=t.target.xPercent*a.width,c=t.target.yPercent*a.height;return await this.tapOnAbsoluteCoordinates(e,{...n,x:s,y:c}),{success:!0,message:`Tapped at ${s}, ${c}`}}let o=t.target.description,{thoughts:i}=await this.wrapTargetingAction({logger:e,command:t,action:a=>this.tapOnTarget({logger:e,target:a,options:n}),description:o});return{success:!0,message:i}}};var t6=25,cg=class extends Xn{async doType(e,t){if(!t.target){if(t.clearContent)throw new Error("UserConfigurationError: clearing content is only supported when a target is provided to the Type step");return await this.stateManager.waitForScreenshotStability({logger:e,timeoutMs:3e3,signal:this.aborter.controller?.signal,reason:"Waiting for page to stabilize before typing"}),await this.sendKeys(t),{success:!0,message:"Successfully executed type action"}}if(t.target.type!=="description")throw new Error("UserConfigurationError: x/y targets are not supported for the Type step");let{thoughts:n}=await this.wrapTargetingAction({logger:e,command:t,action:async o=>{if("type"in o&&o.type==="NATIVE")await this.doNativeType(e,t,o);else throw new Error("UserConfigurationError: Webview targets are not supported for the Type step on iOS devices")},description:t.target.description});return{success:!0,message:n}}async doNativeType(e,t,n){let o=new ll(this.constructPerformerParams());t.clearContent?(await o.tapOnNativeTarget(e,n,{longPress:!0}),await this.clearContent()):await o.tapOnNativeTarget(e,n),await this.stateManager.waitForScreenshotStability({logger:e,timeoutMs:3e3,signal:this.aborter.controller?.signal,reason:"Waiting for keyboard to appear before typing"}),await this.sendKeys(t)}async sendKeys(e){let t=e.keyPressDelayMs??t6,n=Date.now();for(;Date.now()-n<3e3&&(this.throwIfAborted(),!await this.driver.executeInNativeContext(o=>o.isKeyboardShown()));)await new Promise(o=>setTimeout(o,500));t?await this.driver.executeInNativeContext(async o=>{await o.updateSettings({keyInjectionDelay:t}),await o.keys(e.text),await o.updateSettings({keyInjectionDelay:0})}):await this.driver.executeInNativeContext(async o=>{await o.keys(e.text)})}async clearContent(){await this.clearContentHelper()}async clearContentHelper(){}};var ug=class r extends Xn{emulatorSettings;logger;constructor(e){super(e),this.logger=e.logger,this.emulatorSettings=e.emulatorSettings}static async init({driver:e,logger:t,fixtures:n,orgId:o,options:i,abortController:a,limbarClient:s,generator:c,aiSettings:l}){let u={controller:a},d=i?.emulator??{},p=await sg.init({driver:e,orgId:o,limbarClient:s,options:d,aborter:u}),m=new r({generator:c,aiSettings:l,limbarClient:s,driver:e,stateManager:p,logger:t,fixtures:n,aborter:u,orgId:o,emulatorSettings:d});return await m.initializeSettings(),m}async executeCommand(e){let t=["type","a11yData","thoughts","cache","code"],n;try{n=await _s({obj:e.command,context:this.fixtures.testContext,bannedKeys:t,orgId:this.orgId,logger:this.logger,signal:this.abortSignal,localTools:this.fixtures.localCodeEvalTools})}catch(o){throw this.throwIfAborted(),new Error(`ActionFailureError: Failed to substitute template strings in command: ${o.message}`,{cause:o})}try{return await this.executeCommandHelper(e)}catch(o){throw o.name!=="AbortError"&&this.logger.error({err:o},"Error thrown in action controller"),o}finally{Ms(e.command,n)}}async executeCommandHelper({command:e}){let t=se();switch(e.type){case"TAP":return new ll(this.constructPerformerParams()).executeTap({logger:this.logger,command:e});case"TYPE":return new cg(this.constructPerformerParams()).doType(this.logger,e);case"STATE":{let n=await this.stateManager.getDomState(this.logger),o=await this.stateManager.getContexts();return{output:{xml:n.graph.xml,contexts:o},success:!0}}case"OPEN_APP":return await this.limbarClient.launchApp(e.packageName),{success:!0};case"PRESS":{let n=new lg(this.constructPerformerParams());switch(e.key){case"HOME":await n.doPress({name:"home"});break;case"POWER":await this.driver.executeInNativeContext(o=>o.isLocked())?await this.driver.executeInNativeContext(o=>o.unlock()):await this.driver.executeInNativeContext(o=>o.lock());break}return{success:!0}}case"AI_CHECK":{let o=e.timeoutSecs?e.timeoutSecs*1e3:5e3,i=Bm(o),a=Date.now(),s=0,c,l=!1,u;for(;s<15&&!l;){this.throwIfAborted(),l||c&&c-a>=o&&(l=!0),s!==0&&await J(i,this.abortSignal),c=Date.now();try{let d="",p="";await t.startAsyncSpan("EMULATOR_READ_STATE",async()=>{d=await this.getEmulatorDomState(),p=await this.getScreenshotBase64()},{name:"Get emulator state"});let m=await this.generator.evaluateIosAssertion({assertion:e.assertion,screenXml:d,screenshot:p},{logger:this.logger,loggerTags:ye(this.logger),agentConfigVersion:this.aiSettings.agentConfig?.["ios-assertion"]});if(m.result)return{success:m.result,message:m.thoughts};{let g=`AssertionFailureError: ${m.thoughts}`;u=new Error(g)}}catch(d){this.throwIfAborted(),this.logger.info({err:d},`AI check assert attempt ${s} failed, retrying...`),u=d instanceof Error?d:new Error(`${d}`)}finally{s++}}return{success:!1,message:u?.message}}default:throw new Error(`Unsupported mobile command type: ${e.type}`)}}async getMobileFailureRecoveryPlan(e){return{thoughts:"Failure recovery is not yet supported for iOS.",scenario:"INELIGIBLE",instructions:void 0}}async waitForPageSourceStability(e){return this.stateManager.waitForPageSourceStability({logger:this.logger,timeoutMs:e.timeoutMs??5e3,reason:e.reason,signal:this.aborter.controller?.signal})}async initializeSettings(){}async getScreenshotBase64(){return this.stateManager.getRawScreenshotBase64(this.logger)}async getScreenshotPngString(){return this.stateManager.getCurrentScreenshotPngString(this.logger)}async getEmulatorDomState(){return(await this.stateManager.getDomState(this.logger)).graph.xml}async getViewportBounds(){return this.stateManager.getViewportBounds()}async waitForScreenshotStability(e){return this.stateManager.waitForScreenshotStability({logger:this.logger,timeoutMs:e.timeoutMs??5e3,reason:e.reason,signal:this.aborter.controller?.signal})}resetAbortController(e){this.aborter.controller=e??new AbortController}isAborted(){return this.aborter.controller?.signal.aborted}abort(){this.aborter.controller?.abort()}async cleanup(){}get abortSignal(){return this.aborter.controller?.signal}get context(){return this.fixtures.testContext}get localCodeEvalTools(){return this.fixtures.localCodeEvalTools}};import n6 from"zod";async function DD({runTracer:r,metadata:{orgId:e,runId:t},fixtures:{logger:n,apiClient:o,mobileGenerator:i,storage:a,cacheStorage:s,usageTracker:c,browserEnricher:l,browserGenerator:u,localCodeEvalTools:d},inputs:{project:p,testDefinition:m},env:{envName:g,envVariables:h},settings:{emulatorSettings:f,aiSettings:y},options:{logLevel:E,region:b}}){let x=Math.floor(Math.random()*1e4)+4e4,P=await zo(x,"appium"),O=Za.or(n6.literal(vu)).optional().parse(b??f.region);if(O==="local")throw new Error("Local region is not supported for iOS tests, as we do not support local iOS emulators.");let R={region:O==="closest"?void 0:O},D=r6(),I=n.child({runAttemptId:D}),k;try{k=await RD({apiClient:o,logger:n,driverLogLevel:E,creationOpts:R,callbacks:{onStatusUpdate:j=>{n.debug({status:j},"Emulator status update")},onLimbarConnectionStateChange:j=>{j==="disconnected"?M.warn("Emulator websocket connection lost. Emulator may be unavailable."):(j==="reconnecting"||j==="connecting")&&M.info("Emulator websocket is reconnecting...")}},appiumPort:P,orgId:e,sessionId:D})}catch(j){let ue=`Fatal error creating iOS driver, failing test run attempt (runId: ${t})`;return n.error({err:j},ue),M.error({err:j},ue),{status:"FAILED",results:[],error:new w("UserConfigurationError",`Fatal error creating iOS driver: ${j.message}`)}}let F=await r.startAttempt({emulatorName:k.emulatorName,runAttemptId:D});I=I.child(F.loggerBindings||{});let ee=new Lo({variablesFromEnvironment:h,envName:g,testName:m.name}),K=await ug.init({driver:k.driver,generator:i,logger:I,limbarClient:k.limbarClient,orgId:e,options:{emulator:{...f,browserSettings:p.config.browser}},aiSettings:y,fixtures:{storage:a,browserEnricher:l,browserGenerator:u,localCodeEvalTools:d,testContext:ee}}),ge;try{ge=await nl({platform:"IOS",containerName:`ios test ${m.name}`,fixtures:{controller:K,logger:I,cacheStorage:s,usageTracker:c},work:{state:{failureRecoveryDisabled:y.failureRecovery===!1,failureRecoveryAttempts:0}},inputs:{testName:m.name,steps:m.steps,orgId:e,testMetadata:m},tracer:F,callbacks:{}})}finally{await k.cleanup(),await K.cleanup()}await F.finish({logger:I,results:ge.results,status:ge.status});let B;if(ge.status==="FAILED"&&ge.terminalResult){let j=ge.terminalResult.message;j?B=w.fromMessage(j):B=new w("UnknownError",j||"Unknown failure")}return{...ge,error:B}}import{cloneDeep as o6}from"lodash-es";import{debounce as i6}from"ts-debounce";var Ru="0.33.0";function a6(r){switch(r){case"PASSED":return"SUCCESS";case"FAILED":return"FAILED";case"CANCELLED":return"CANCELLED";case"RUNNING":case"PENDING":case"RETRYING":case"WAITING_FOR_USER":return"RUNNING"}}function s6(r){switch(r){case"SUCCESS":return"PASSED";case"FAILED":return"FAILED";case"CANCELLED":return"CANCELLED";case"RUNNING":return"RUNNING";case"IDLE":return"PENDING"}}var Qb=class{constructor(e,t,n,o,i,a){this.keepalive=e;this.testId=t;this.testName=n;this.diskStorage=o;this.parentTracer=i;this.orgId=a;this.interactionTracer=new Xo,rn.initializeRootTracerContext(this.interactionTracer)}children=[];finished=!1;interactionTracer;getParentStepIdChain(){return[]}recordStepDuration(e){let{durationMs:t,step:n}=e,o=n.type!=="MOBILE_PRESET_STEP"?n.type:n.command.type;nt.distribution("test_step_duration",t,[`type:${o}`,"platform:mobile","executor:cli",`orgId:${this.orgId}`])}attachBeforeScreenshot(e){let{snapshotId:t,screenshot:n}=e;this.diskStorage.storeFile({name:`${Bo}/${t}.jpeg`,contents:n})}attachAfterScreenshot(e){let{snapshotId:t,screenshot:n}=e;this.diskStorage.storeFile({name:`${Bo}/${t}.jpeg`,contents:n})}attachBeforeXmlSnapshot(e){let{snapshotId:t,xml:n}=e;this.diskStorage.storeFile({name:`${Bo}/${t}.xml`,contents:n})}attachAfterXmlSnapshot(e){let{snapshotId:t,xml:n}=e;this.diskStorage.storeFile({name:`${Bo}/${t}.xml`,contents:n})}async finishInternal(e){this.finished||(this.finished=!0,this.interactionTracer.finish(),await Promise.all(this.children.map(t=>t.finish({status:s6(e.status),finishedAt:e.finishedAt}))))}async finish(e){return await this.finishInternal({status:e.result.status,finishedAt:new Date(e.result.endTime)}),{trace:this.interactionTracer.getRootSpan()}}async startSubSteps(){let e=new cl(this.keepalive,this.testId,this.testName,this.diskStorage,this.orgId);return this.children.push(e),e}},cl=class{constructor(e,t,n,o,i){this.keepalive=e;this.testId=t;this.testName=n;this.diskStorage=o;this.orgId=i}children=[];finished=!1;async getScreenshot(e){return this.diskStorage.readFile(`${Bo}/${e}.jpeg`)}getParentStepIdChain(){return[]}async startStep(e){this.keepalive();let t=new Qb(this.keepalive,this.testId,this.testName,this.diskStorage,this,this.orgId);return this.children.push(t),t}async finish(e){this.finished||(this.finished=!0,await Promise.all(this.children.map(t=>t.finishInternal({status:a6(e.status),finishedAt:e.finishedAt}))))}},eE=class{constructor(e,t,n,o,i,a,s){this.keepalive=e;this.testId=t;this.testName=n;this.runAttemptId=o;this.metadata=i;this.diskStorage=a;this.orgId=s;this.diskStorage.mkdir("assets"),this.logStream=this.diskStorage.createFileStream("assets/logs.logcat"),this.resourceUsageStream=this.diskStorage.createFileStream(`${Bo}/resource-usage.ndjson`),this.resourceUsageSampler=UR({keepSamples:!1,onSample:c=>{this.resourceUsageStream.write(`${JSON.stringify(c)}
4650
+ `),r.forEach(m=>{if(!Db.existsSync(m))throw new Error(`Path '${m}' does not exist.`);let g,h;try{g=Db.statSync(m),h=g.isDirectory()}catch(y){s.warn({err:y},`Skipping path ${m} because it cannot be read`);return}let f=tg.resolve(m);Object.values(e.mobileTests).filter(y=>h?y.fullFilePath.startsWith(f):y.fullFilePath===f).forEach(y=>{l.add(y.fullFilePath)})})):(s.info("The arguments provided don't appear to be valid paths. Treating them as substrings instead... "),Object.values(e.mobileTests).forEach(m=>{r.some(g=>m.relativePath.includes(g))&&l.add(m.fullFilePath)}))}else{!n&&!await Md("No test paths or substrings were provided. Do you want to run all tests?")&&(s.error("Cancelled by user."),process.exit(1));let d=Object.values(e.mobileTests);s.info(`Reading all ${d.length} mobile tests in the project from local disk.`),d.forEach(p=>{l.add(p.fullFilePath)})}for(let d of Array.from(l)){let p=tg.relative(t.rootDir,d);o&&!o.some(m=>new RegExp(m).test(p))&&l.delete(d),i&&i.some(m=>new RegExp(m).test(p))&&l.delete(d)}return(await Promise.all(Array.from(l).map(async d=>{try{let p=tg.relative(t.rootDir,d),m=await So(d,s,e),g=tg.basename(d,".test.yaml");if(m.disabled)return null;if(a&&a.length>0){let f=m.labels||[];if(!a.some(E=>f.includes(E)))return null}let h={id:m.id,name:g,description:m.description,schemaVersion:m.schemaVersion,settings:m.settings,fullFilePath:d,relativeFilePath:p,quarantined:!!c[m.id],quarantinedMetadata:c[m.id],labels:m.labels};switch(m.platform){case"ANDROID":return{...h,platform:"ANDROID",steps:m.steps};case"IOS":return{...h,platform:"IOS",steps:m.steps};default:return(y=>{throw new Error("You missed a case in the switch above")})(m)}}catch(p){s.error(`Failed to read and resolve mobile test at '${d}': ${p}`),process.exit(1)}}))).filter(d=>!!d)}import{InvalidArgumentError as rg,Option as Qe}from"@commander-js/extra-typings";import{z as _J}from"zod";var iD=58890;function sl(r){let e=parseInt(r,10);if(isNaN(e))throw new rg("Not a number.");return e}var Sa=new Qe("--api-key <key>","Momentic API key").env("MOMENTIC_API_KEY").argParser(r=>{if(!r)throw new rg("API key is required.");return r}).makeOptionMandatory(),ng=new Qe("-c, --config <configPath>","Absolute or relative path to a Momentic configuration file."),Fb=new Qe("-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."),ya=new Qe("--server <server>","Momentic server to use.").env("MOMENTIC_SERVER").default("https://api.momentic.ai").argParser(r=>{try{return _J.string().url().parse(r),r}catch{throw new rg("Not a valid URL.")}}),Ub=new Qe("-y, --yes","Skip all confirmation prompts.").env("CI"),Bb=new Qe("--regenerate-cache","Regenerate all caches by starting from an empty cache state. This flag is useful for completely regenerating caches after changing configuration options. Warning: using this option will cause all steps to run without any cached data, resulting in significantly longer execution times."),zb=new Qe("--save-cache","Always save updated step caches after successful test runs. By default, caches are not saved when running on protected branches.").env("CI"),Hb=new Qe("--disable-cache","Disable using step caches completely. Using this option may lead to non-deterministic behavior and significantly longer runtimes.").implies({saveCache:!1}),Gb=new Qe("--tag <tag>","Tag identifier for the asset."),aD=new Qe("--channel <channel>","Channel name for the asset."),jb=new Qe("--channel <channel>","Channel name for the asset.").makeOptionMandatory(),sD=new Qe("--tag <tag>","Tag identifier for the asset.").makeOptionMandatory(),lD=new Qe("--env <env>","Environment to run all tests in (overrides test-level configuration)."),vu="closest",cD=new Qe("--region <region>",`Region to run all tests in (overrides all other configuration). Valid values: ${Object.values(zi).join(", ")}, ${vu}, ${Object.values(Hi).join(", ")}.`),uD=new Qe("--local-avd-id <localAvdId>","Force tests to use a specific local Android Virtual Device (AVD) instead of remote emulators."),dD=new Qe("--local-apk-path <localApkPath>","Path to a local APK file to install when running tests with a local emulator. Overrides remote asset configuration."),mD=new Qe("-p, --parallel <parallel>","The number of tests to run in parallel. Defaults to 1.").argParser(sl),pD=new Qe("--shard-index <shardIndex>","The index of the shard to run tests for. Defaults to 1.").default(1).argParser(r=>{let e=sl(r);if(e<1)throw new rg("Shard index must be greater than 0.");return e}),gD=new Qe("--shard-count <shardCount>","The number of shards that tests are being run on. Defaults to 1.").default(1).argParser(sl),Wb=new Qe("--output-dir <outputDir>","Output directory to store run artifacts such as screenshots, results, and logs."),Vb=new Qe("--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."),$b=new Qe("--exclude <excludePatterns...>","The inverted version of --include: a test that matches any of the provided exclusion patterns will be excluded from running."),hD=new Qe("--upload-results","Upload test results to Momentic Cloud.").default(!1),qb=new Qe("--log-level <logLevel>","Log level for Momentic and dependent services.").choices(["error","warn","info","debug"]),fD=new Qe("--ignore-quarantine","Run all tests even if they are quarantined. This is useful for validating that quarantined tests are fixed before moving them out of quarantine.").implies({skipQuarantined:!1,onlyQuarantined:!1}),SD=new Qe("--timeout-minutes <timeoutMinutes>","Maximum number of minutes to run tests before stopping. When the timeout is reached, tests will stop and current results will be printed.").argParser(sl),yD=new Qe("--reporter <reporter>","Output report files in a standardized format to a local directory.").choices(Object.values(zl)),bD=new Qe("--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.").default("reports"),ED=new Qe("--name <name>","A name to associate with this run for easier identification in the Momentic dashboard.");import{randomUUID as y6}from"crypto";import{existsSync as b6}from"fs";import{dirname as l6}from"path";import{randomUUID as PJ}from"crypto";import{existsSync as IJ,statSync as OJ}from"fs";import TD from"path";import LJ from"zod";async function vD({runTracer:r,metadata:{orgId:e,runId:t},fixtures:{logger:n,apiClient:o,mobileGenerator:i,storage:a,cacheStorage:s,usageTracker:c,browserEnricher:l,browserGenerator:u,localCodeEvalTools:d},inputs:{channel:p,tag:m,project:g,testDefinition:h},env:{envName:f,envVariables:y},settings:{emulatorSettings:E,aiSettings:b},options:{logLevel:x,localAvdId:P,localApkPath:O,region:T}}){let R=Math.floor(Math.random()*1e4)+4e4,D=await zo(R,"appium"),I=Za.or(LJ.literal(vu)).optional().parse(T??E.region),k=I==="local",F;if(k){let q;if(O&&(q=TD.resolve(O),!IJ(q)||!OJ(q).isFile()))throw new Error(`Local APK path "${q}" does not exist. Provide a valid file path via --local-apk-path.`);let fe,it=h.settings?.defaultApkFilePath;if(it){let gi=it.trim();gi&&(fe=gi)}let Ae=typeof y[_i]=="string"?y[_i].trim():void 0,C=typeof y[Dl]=="string"?y[Dl].trim():void 0,oe;C&&(oe=TD.resolve(C));let pe=q??fe??oe,Br=P??E.localEmulatorSettings?.avdId??Ae;if(!Br)throw new Error(`An AVD ID is required when using a local region. Provide --local-avd-id, configure a default local AVD ID on the test's settings, or set the ${_i} key on the environment.`);F={avdId:Br,apkFilePath:pe}}else F={region:I==="closest"?void 0:I,apkToInstall:p?{channel:p,tag:m}:void 0,osVersion:E.remoteEmulatorSettings?.androidVersion??hA};let ee=PJ(),K=n.child({runAttemptId:ee}),ge;try{ge=await _m({apiClient:o,logger:n,driverLogLevel:x,creationOpts:F,callbacks:{onStatusUpdate:q=>{n.debug({status:q},"Emulator status update")},onHeartbeatFailure:()=>{let q="Appium heartbeat connection lost \u2014 possible ADB tunnel/emulator failure";M.warn(q)},onHeartbeatRestored:()=>{let q="Appium heartbeat connection restored";M.info(q)},onLimbarConnectionStateChange:q=>{q==="disconnected"?M.warn("Emulator websocket connection lost. Emulator may be unavailable."):(q==="reconnecting"||q==="connecting")&&M.info("Emulator websocket is reconnecting...")}},appiumPort:D,orgId:e,sessionId:ee})}catch(q){let fe=`Fatal error creating Android driver, failing test run attempt (runId: ${t})`;return n.error({err:q},fe),M.error({err:q},fe),{status:"FAILED",results:[],error:new w("UserConfigurationError",`Fatal error creating Android driver: ${q.message}`)}}let B=await r.startAttempt({emulatorName:ge.emulatorName,runAttemptId:ee});K=K.child(B.loggerBindings||{});let j=await Pm({driver:ge.driver,onLogs:q=>{B.appendLogs(q)}}),ue=new Lo({variablesFromEnvironment:y,envName:f,testName:h.name}),le=await oi.init({driver:ge.driver,generator:i,logger:K,limbarClient:ge.limbarClient,playwrightDevice:ge.playwrightDevice,orgId:e,adbPort:ge.adbPort,options:{emulator:{...E,browserSettings:g.config.browser}},aiSettings:b,fixtures:{storage:a,browserEnricher:l,browserGenerator:u,localCodeEvalTools:d,testContext:ue}}),He;try{He=await nl({platform:"ANDROID",containerName:`android test ${h.name}`,fixtures:{controller:le,logger:K,cacheStorage:s,usageTracker:c},work:{state:{failureRecoveryDisabled:b.failureRecovery===!1,failureRecoveryAttempts:0}},inputs:{testName:h.name,steps:h.steps,orgId:e,testMetadata:h},tracer:B,callbacks:{}})}finally{await j(),await ge.cleanup(),await le.cleanup()}await B.finish({logger:K,results:He.results,status:He.status,assetDetails:{avdId:"avdId"in F?F.avdId:void 0,tag:"apkToInstall"in F?F.apkToInstall?.tag:void 0,channel:"apkToInstall"in F?F.apkToInstall?.channel:void 0}});let ve;if(He.status==="FAILED"&&He.terminalResult){let q=He.terminalResult.message;q?ve=w.fromMessage(q):ve=new w("UnknownError",q||"Unknown failure")}return{...He,error:ve}}import{randomUUID as r6}from"crypto";import{remote as kJ}from"webdriverio";var og="NATIVE_APP";var ig=class{constructor(e){this.driver=e}async executeWebViewScript(e,t,...n){return this.executeInContext(e,async o=>{let i=new Function("...args",`${eu.safariUtilsLibJs}; const userFn = ${t.toString()}; return userFn(momenticFunctions, ...args);`);return o.execute(i,...n)})}async executeInNativeContext(e){return this.executeInContext(og,e)}async executeInContext(e,t){return await this.driver.switchContext(e),await t(this.driver)}};import{createInstanceClient as NJ}from"@limrun/api/ios-client";import{hostname as DJ}from"os";async function AD(r){let{apiClient:e,logger:t,creationOpts:n,logLevel:o,orgId:i,sessionId:a,onConnectionStateChange:s}=r,{token:c,webRtcUrl:l,wdaUrl:u,apiUrl:d,id:p,region:m}=await e.createIosEmulator({...n,hostname:DJ(),sessionId:a});t.info({emulatorName:p,region:m,sessionId:a},"ios instance creation ok");let g=await nt.recordDuration({fn:async()=>await NJ({apiUrl:d,token:c,logLevel:o}),name:"test_event_duration",tags:["name:limbar-client-creation","clientOs:ios",`orgId:${i}`]});return s&&g.onConnectionStateChange(s),{close:()=>{g.disconnect()},limbarToken:c,limbarWebRtcUrl:l,limbarApiUrl:d,limbarWdaUrl:u,emulatorName:p,limbarClient:g}}async function wD({wdaUrl:r,token:e}){try{let t=new AbortController;return setTimeout(()=>t.abort(),3e3),await fetch(r+"/status",{headers:{Authorization:`Bearer ${e}`},signal:t.signal}),!0}catch{return!1}}async function RD({creationOpts:r,apiClient:e,logger:t,driverLogLevel:n,appiumPort:o,orgId:i,sessionId:a,callbacks:s}){let c=Date.now();t.info("Starting ios driver creation");let{onLimbarConnectionStateChange:l}=s,u=[],d=await AD({apiClient:e,logger:t,creationOpts:r,orgId:i,sessionId:a,onConnectionStateChange:l}),p=d.emulatorName;u.push(()=>e.deleteIosEmulator(p),d.close);let m=async()=>{for(let g=u.length-1;g>=0;g-=1)try{await u[g]()}catch(h){if(h instanceof Error&&["ECONNREFUSED","ECONNRESET","UND_ERR_CLOSED"].some(f=>h.message.includes(f)))continue;t.warn({err:h},"Error running cleanup task")}};try{let g=await FJ({logger:t,driverLogLevel:n,appiumPort:o,emulatorStart:c,emulatorCreationParams:d,apiClient:e,creationOpts:r,orgId:i,sessionId:a,callbacks:s});return u.push(g.appiumClose),u.push(async()=>g.driver.deleteSession()),g.driver.getPageSource().catch(()=>{}),{...d,...g,driver:new ig(g.driver),cleanup:m,appiumPort:o}}catch(g){throw await m(),new Error(`Failed to start Appium driver: ${g}`)}}async function FJ({logger:r,driverLogLevel:e="warn",emulatorStart:t,appiumPort:n,emulatorCreationParams:o,callbacks:{onStatusUpdate:i,onLimbarConnectionStateChange:a}}){let s=[],{emulatorName:c,limbarWdaUrl:l,limbarApiUrl:u,limbarToken:d,limbarClient:p}=o,m=Date.now(),{close:g,logFile:h}=await vc({logger:r,logLevel:e,appiumPort:n});await wD({wdaUrl:l,token:d})||(r.debug({emulatorName:c},"WDA is not running on the Limbar iOS emulator"),await p.simctl(["launch","booted","com.facebook.WebDriverAgentRunner.xctrunner"]).wait(),r.debug({emulatorName:c},"WDA launched"));let f={platformName:"iOS","appium:automationName":"XCUITest","appium:noReset":!0,"appium:fullReset":!1,"appium:webDriverAgentUrl":l,"appium:wdaLocalPort":443,"appium:useNewWDA":!1,"appium:usePreinstalledWDA":!0,"appium:newCommandTimeout":3600,"appium:autoWebview":!1,"appium:webviewConnectTimeout":500,"appium:webviewConnectRetries":5,"appium:includeSafariInWebviews":!0,"appium:fullContextList":!1,"appium:additionalWebviewBundleIds":["*"],"appium:waitForQuiescence":!1,"appium:settings":{customSnapshotTimeout:0},"appium:limInstanceApiUrl":u,"appium:limInstanceToken":d,"appium:wdaRequestHeaders":{Authorization:`Bearer ${d}`}},y=Date.now(),E=await kJ({capabilities:f,hostname:"localhost",port:n,path:"/",protocol:"http",logLevel:e}),b=new Map;return E.on("command",P=>{b.set(P.command,Date.now())}),E.on("result",P=>{let O=b.get(P.command);if(!O)return;let T=Date.now()-O;P.result instanceof Error?r.warn({err:P.result,command:P.command,args:P.body,durationMs:T},"Appium cmd failed"):T>1e4&&r.warn({command:P.command,args:P.body,durationMs:T},"Appium cmd took very long"),b.delete(P.command)}),r.info({timings:{emulatorDuration:m-t,appiumDuration:y-m,wdioDuration:Date.now()-y},capabilities:f,emulatorName:c},"Started Appium driver"),{onStatusUpdate:i,driver:E,appiumClose:async()=>{await g(),await Promise.all(s.map(P=>P()))},appiumPort:n,appiumLogFile:h,emulatorName:c}}import{createHash as ZJ}from"crypto";import QJ from"jpeg-js";import{PNG as LD}from"pngjs";import VJ from"@prettier/plugin-xml";import $J from"prettier";import{DOMParser as qJ,XMLSerializer as KJ}from"slimdom";import{reduce as UJ}from"lodash-es";var BJ=new Set(["id","processId","bundleId","type","accessible","index","x","y","width","height"]),zJ=new Set([]),HJ=new Set(["name","label","traits"]),GJ=new Set(["live-region","drawing-order"]),jJ=new Set(["visible","enabled"]);function CD(r){let e={},t=r.tagName,n=UJ(r.attributes,(o,i)=>(o[i.name]=i.value,o),{});for(let[o,i]of Object.entries(n))BJ.has(o)||o==="class"&&t===i||o==="focusable"&&i==="true"&&n.clickable==="true"||zJ.has(o)&&i==="false"||HJ.has(o)&&i===""||jJ.has(o)&&i==="true"||GJ.has(o)&&i==="0"||(e[o]=i);return e.name&&e.label&&e.name===e.label&&delete e.label,e.name&&e.value&&e.name===e.value&&delete e.value,e}function ag(r){let e=r.getAttribute("x"),t=r.getAttribute("y"),n=r.getAttribute("width"),o=r.getAttribute("height");if(e===null||t===null||n===null||o===null)return;let i=parseFloat(e),a=parseFloat(t),s=parseFloat(n),c=parseFloat(o);if(!(isNaN(i)||isNaN(a)||isNaN(s)||isNaN(c)))return[i,a,i+s,a+c]}function Kb(r,e){let[t,n,o,i]=e;r.setAttribute("bounds",`[${t}, ${n}, ${o}, ${i}]`)}function WJ(r){let e=r.match(/\[\s*([-\d.]+)\s*,\s*([-\d.]+)\s*,\s*([-\d.]+)\s*,\s*([-\d.]+)\s*\]/);if(!e)return;let t=parseFloat(e[1]),n=parseFloat(e[2]),o=parseFloat(e[3]),i=parseFloat(e[4]);if(!(isNaN(t)||isNaN(n)||isNaN(o)||isNaN(i)||o<t||i<n))return[t,n,o,i]}function xD(r){let e=r.getAttribute("bounds");if(e)return WJ(e)}function _D(r,e){if(!e)return!0;let t=ag(r);return t?Yb(t,e):!0}function Yb(r,e){if(!e)return!0;let[t,n,o,i]=r;return!(o<e.left||t>e.right||i<e.top||n>e.bottom)}var MD=new Set(["XCUIElementTypeWebView"]);function YJ(r){if(MD.has(r.tagName))return!0;let e=r.getAttribute("name");if(e&&(e.startsWith("TabDocument")||e.startsWith("BrowserView"))){let t=e.match(/UUID=([A-F0-9-]+)/),n=e.match(/WebViewProcessID=(\d+)/);if(t&&n)return!0}return!1}function XJ(r){let e=["android.widget.","android.view.","android.webkit.","android.app.","android.support.","androidx.","com.android.inputmethod."];for(let t of e)if(r.startsWith(t))return r.substring(t.length);return r}function Xb(r,e){let{idCounter:t,idToElement:n}=r,o=t.value++;e.setAttribute("id",String(o)),n.set(o,e)}function Jb(r){if(MD.has(r.tagName))return r.children.length>0?Jb(r.children[0]):void 0;if(r.tagName==="XCUIElementTypeOther"&&r.hasAttribute("name")&&r.hasAttribute("label"))return ag(r);if(r.children.length===1){let e=r.children[0];return Jb(e)}}function PD(r,e,t,n){let{document:o}=t,{parentFrameBounds:i,pruneElementsOutsideBounds:a}=n;if(e.type==="element"){let s=o.createElement(e.role||e.tag);if(e.name&&s.setAttribute("name",e.name),e.description&&s.setAttribute("description",e.description),e.classes&&e.classes.length>0&&s.setAttribute("classes",e.classes.join(" ")),e.attrs)for(let[u,d]of Object.entries(e.attrs))s.setAttribute(u,d);let c=e.boundingRect,l=[i[0]+c.x,i[1]+c.y,i[0]+c.x+c.width,i[1]+c.y+c.height];if(!Yb(l,a))return;Kb(s,l),Xb(t,s),r.appendChild(s);for(let u of e.children)PD(s,u,t,n)}else if(e.type==="text"){let s=o.createElement("text");Xb(t,s),r.appendChild(s);let c=o.createTextNode(e.text);s.appendChild(c)}}function ID(r,e,t,n){let{pruneElementsOutsideBounds:o}=n,{document:i}=t;Xb(t,e);let a=CD(r);for(let[l,u]of Object.entries(a))e.setAttribute(l,u);let s=ag(r);if(s&&Kb(e,s),YJ(r)){let{removeWebviewContent:l,injectedWebviewContent:u}=n;if(l)return;if(u){let d=Jb(r);if(d){PD(e,u,t,{parentFrameBounds:d,pruneElementsOutsideBounds:o});return}}}let c=Array.from(r.childNodes??[]);for(let l of c){let u=l.nodeType;if(u===3){let d=l.nodeValue;d&&d.trim().length>0&&e.appendChild(i.createTextNode(d));continue}if(u===1){let d=l;if(!_D(d,o))continue;let p=i.createElement(XJ(d.tagName));ID(d,p,t,n),e.appendChild(p)}}}async function JJ(r,e,t){let n=r.parseFromString("<AppiumAUT/>","text/xml"),o=new Map,i={document:n,idToElement:o,idCounter:{value:0}},a=n.documentElement;ID(e,a,i,t);let s=new KJ().serializeToString(n),c=await $J.format(s,{parser:"xml",plugins:[VJ],printWidth:120,tabWidth:1,singleAttributePerLine:!1});return{prunedDocument:n,idToElement:o,prunedXml:c}}async function OD(r,e){let t=new qJ,o=t.parseFromString(r,"text/xml").documentElement;if(!o)throw new Error("No root element found in XML");if(o.tagName!=="AppiumAUT")throw new Error("No AppiumAUT element found in XML");let{prunedXml:i,idToElement:a,prunedDocument:s}=await JJ(t,o,e);return{xml:i,idToElement:a,document:s}}var sg=class r{driver;limbarClient;orgId;options;aborter;constructor({driver:e,limbarClient:t,orgId:n,options:o,aborter:i}){this.driver=e,this.limbarClient=t,this.orgId=n,this.options=o,this.aborter=i}static async init({driver:e,limbarClient:t,orgId:n,options:o,aborter:i}){return new r({driver:e,orgId:n,options:o,aborter:i,limbarClient:t})}async getContexts(){let e=await this.driver.executeInNativeContext(async n=>await n.getContexts({})),t=e.filter(n=>n!==og);return{contexts:e.map(n=>n),webviews:t}}async getRawScreenshotBase64(e,t=2){let n=se(),o;for(let i=0;i<t;i++)try{return await n.startAsyncSpan("EMULATOR_READ_STATE",async()=>{let a=await this.limbarClient.screenshot(),s=Buffer.from(a.base64,"base64"),c=QJ.decode(s),l=new LD({width:c.width,height:c.height});return l.data=Buffer.from(c.data),LD.sync.write(l).toString("base64")},{name:"Take screenshot",signal:this.aborter.controller?.signal,timeoutMs:3e3})}catch(a){if(o=a,e.warn({err:a},"Failed to take screenshot"),i===t-1)throw a}throw new w("InternalWebAgentError",`Failed to take screenshot: ${o}`)}async getCurrentScreenshotPngString(e){return`data:image/png;base64,${await this.getRawScreenshotBase64(e,1)}`}async waitForScreenshotStability({logger:e,timeoutMs:t,signal:n,reason:o,tolerancePercent:i=1}){let a=Date.now(),s,c=!1;for(;Date.now()-a<t;){if(n?.throwIfAborted(),!s){s=await this.getRawScreenshotBase64(e);continue}let l=await this.getRawScreenshotBase64(e);if(ps(s,l)<=i){c=!0;break}s=l,await J(250,n)}c||e.warn({purpose:o},"Timed out waiting for screenshot stability")}async waitForPageSourceStability({logger:e,timeoutMs:t,signal:n,reason:o}){await se().startAsyncSpan("WAIT_FOR_PAGE_STABILITY",async i=>{i.attributes.reason=o;let a=Date.now(),s,c,l=!1;for(;Date.now()-a<t;){c&&c<250&&await J(250-c,n),n?.throwIfAborted();let u=Date.now(),d;try{d=await this.limbarClient.elementTree()}catch(m){e.warn({err:m},"Failed to get page source during stability wait"),c=Date.now()-u;continue}let p=ZJ("md5").update(d).digest("hex");if(c=Date.now()-u,s&&s===p){l=!0;break}s=p}l||(i.attributes.timedOut=!0,e.warn({purpose:o},"Timed out waiting for page source stability"))})}async getActiveWebview(){let t=(await this.getContexts()).webviews;if(t.length>1)throw new w("UserInfrastructureError","Multiple active webviews in a single package is currently not supported");return t[0]}async getActiveWebviewContent(){let e=await this.getActiveWebview();if(!e)return;this.throwIfAborted();let t=await this.driver.executeWebViewScript(e,n=>n.dumpA11yTree());if(t)return JSON.parse(t)}async getDomState(e,t){let o=t?.filterOffscreenElements??!0?await this.getViewportBounds():void 0,i=await this.getPageSource();this.throwIfAborted();let a;if(!t?.skipFetchingFullWebviewContent)try{a=await this.getActiveWebviewContent()}catch(c){e.error({err:c},"Could not get webview info to get the nested DOM state")}return this.throwIfAborted(),{graph:await OD(i,{injectedWebviewContent:a,removeWebviewContent:t?.removeWebviewContent,pruneElementsOutsideBounds:o})}}async getPageSource(){return await se().startAsyncSpan("EMULATOR_READ_STATE",()=>this.driver.executeInNativeContext(async n=>n.getPageSource()),{name:"Get iOS page source",signal:this.aborter.controller?.signal})}async getViewportBounds(){let e=await this.driver.executeInNativeContext(async t=>t.getWindowRect());return{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height}}throwIfAborted(){this.aborter.controller?.signal.throwIfAborted()}};function ND({aiResponse:r,description:e,emulatorState:t}){let n=t.graph.idToElement.get(r.id);if(!n)throw new Error(`Could not find node with id: ${r.id}`);let o=xD(n);if(!o)throw new Error(`Could not determine bounds for element with id: ${r.id}, description: ${e}`);return{target:{type:"NATIVE",bounds:o},resolvedNode:n}}var Xn=class{limbarClient;driver;stateManager;generator;fixtures;orgId;aiSettings;aborter;constructor(e){this.stateManager=e.stateManager,this.driver=e.driver,this.limbarClient=e.limbarClient,this.aborter=e.aborter,this.fixtures=e.fixtures,this.orgId=e.orgId,this.generator=e.generator,this.aiSettings=e.aiSettings}async findElement({logger:e,description:t,skipFetchingFullWebviewContent:n=!1,removeWebviewContent:o=!1,useMemory:i=!1,metadata:a}){let s=e.child({...a});await this.stateManager.waitForScreenshotStability({logger:e,timeoutMs:5e3,signal:this.aborter.controller?.signal,reason:"Waiting for stability before locating an element with AI"});let c=await this.stateManager.getDomState(e,{skipFetchingFullWebviewContent:n,removeWebviewContent:o}),l=await this.stateManager.getCurrentScreenshotPngString(e),u;try{u=await this.generator.getIosElementLocation({description:t,screenXml:c.graph.xml,screenshot:l},{logger:s,loggerTags:ye(s),abortSignal:this.aborter.controller?.signal,useMemory:i,agentConfigVersion:this.aiSettings.agentConfig?.["ios-locator"]})}catch(m){throw this.throwIfAborted(),s.error({err:m},"Failed to locate element"),new Error(`ActionFailureError: Failed to locate element: ${m instanceof Error?m.message:m}`)}if(u.id===-1)throw new w("NoMatchingElementError",u.thoughts??"No matching element found");let{target:d,resolvedNode:p}=ND({aiResponse:u,description:t,emulatorState:c});return{resolvedTarget:{...d,resolvedNode:p},thoughts:u.thoughts}}async wrapTargetingAction(e){let{logger:t,action:n,description:o,command:i,cacheIsInvalidAfterResolution:a,skipFetchingFullWebviewContent:s=!1,removeWebviewContent:c=!1}=e,l={commandId:i.id},u=!1,d;i.disableCache&&(t.debug({command:i},"Cache explicitly disabled for command"),u=!0,d=void 0),a&&(u=!0,d=void 0),d&&d?.resolvedDescription!==o&&(t.info({description:o,cacheDescription:d?.resolvedDescription},"Cache description mismatch, clearing it automatically"),u=!0,d=void 0),t.info({description:o,cacheBustedBeforeAction:u},"Prompting AI for a new element location");let p=await this.findElement({logger:t,description:o,skipFetchingFullWebviewContent:s,removeWebviewContent:c,metadata:l}),m=p.thoughts;return{result:await n(p.resolvedTarget),thoughts:m}}constructPerformerParams(){return{limbarClient:this.limbarClient,stateManager:this.stateManager,driver:this.driver,fixtures:this.fixtures,aborter:this.aborter,orgId:this.orgId,generator:this.generator,aiSettings:this.aiSettings}}throwIfAborted(){this.aborter.controller?.signal.throwIfAborted()}get abortSignal(){return this.aborter.controller?.signal}};var lg=class extends Xn{async doPress({name:e,longPress:t}){return this.driver.executeInNativeContext(n=>n.executeScript("mobile: pressButton",[{name:e,isLongPress:t}]))}};function e6(r){let e={relativePosition:r.relativePosition};if(r.doubleTap&&r.longPress)throw new Error("UserConfigurationError: Cannot specify both doubleTap and longPress");return r.doubleTap?{...e,doubleTap:!0,doubleTapDelayMs:r.doubleTapDelayMs}:r.longPress?{...e,longPress:!0,longPressDurationMs:r.longPressDurationMs}:e}var ll=class extends Xn{async tapOnAbsoluteCoordinates(e,t){let n=t.x,o=t.y;if(e.info({x:n,y:o},"Tap at coordinates"),t.longPress){let i=t.longPressDurationMs??2e3;await this.driver.executeInNativeContext(a=>a.tap({x:n,y:o,duration:i}));return}if(t.doubleTap){await this.driver.executeInNativeContext(a=>a.tap({x:n,y:o}));let i=t.doubleTapDelayMs??100;await new Promise(a=>setTimeout(a,i))}await this.driver.executeInNativeContext(i=>i.tap({x:n,y:o}))}async tapOnNativeTarget(e,t,n){let[o,i,a,s]=t.bounds,c=a-o,l=s-i,u=n?.relativePosition?.x??c/2,d=n?.relativePosition?.y??l/2;u=Math.max(0,Math.min(u,c)),d=Math.max(0,Math.min(d,l));let p=o+u,m=i+d;return await this.tapOnAbsoluteCoordinates(e,{x:p,y:m,...n}),{x:p,y:m}}async tapOnTarget({logger:e,target:t,options:n}){if("type"in t&&t.type==="NATIVE")await this.tapOnNativeTarget(e,t,n);else throw new Error("Not implemented yet")}async executeTap({logger:e,command:t}){let n=e6(t);if(t.target.type==="coordinates"){let a=await this.driver.executeInNativeContext(async l=>l.getWindowSize()),s=t.target.xPercent*a.width,c=t.target.yPercent*a.height;return await this.tapOnAbsoluteCoordinates(e,{...n,x:s,y:c}),{success:!0,message:`Tapped at ${s}, ${c}`}}let o=t.target.description,{thoughts:i}=await this.wrapTargetingAction({logger:e,command:t,action:a=>this.tapOnTarget({logger:e,target:a,options:n}),description:o});return{success:!0,message:i}}};var t6=25,cg=class extends Xn{async doType(e,t){if(!t.target){if(t.clearContent)throw new Error("UserConfigurationError: clearing content is only supported when a target is provided to the Type step");return await this.stateManager.waitForScreenshotStability({logger:e,timeoutMs:3e3,signal:this.aborter.controller?.signal,reason:"Waiting for page to stabilize before typing"}),await this.sendKeys(t),{success:!0,message:"Successfully executed type action"}}if(t.target.type!=="description")throw new Error("UserConfigurationError: x/y targets are not supported for the Type step");let{thoughts:n}=await this.wrapTargetingAction({logger:e,command:t,action:async o=>{if("type"in o&&o.type==="NATIVE")await this.doNativeType(e,t,o);else throw new Error("UserConfigurationError: Webview targets are not supported for the Type step on iOS devices")},description:t.target.description});return{success:!0,message:n}}async doNativeType(e,t,n){let o=new ll(this.constructPerformerParams());t.clearContent?(await o.tapOnNativeTarget(e,n,{longPress:!0}),await this.clearContent()):await o.tapOnNativeTarget(e,n),await this.stateManager.waitForScreenshotStability({logger:e,timeoutMs:3e3,signal:this.aborter.controller?.signal,reason:"Waiting for keyboard to appear before typing"}),await this.sendKeys(t)}async sendKeys(e){let t=e.keyPressDelayMs??t6,n=Date.now();for(;Date.now()-n<3e3&&(this.throwIfAborted(),!await this.driver.executeInNativeContext(o=>o.isKeyboardShown()));)await new Promise(o=>setTimeout(o,500));t?await this.driver.executeInNativeContext(async o=>{await o.updateSettings({keyInjectionDelay:t}),await o.keys(e.text),await o.updateSettings({keyInjectionDelay:0})}):await this.driver.executeInNativeContext(async o=>{await o.keys(e.text)})}async clearContent(){await this.clearContentHelper()}async clearContentHelper(){}};var ug=class r extends Xn{emulatorSettings;logger;constructor(e){super(e),this.logger=e.logger,this.emulatorSettings=e.emulatorSettings}static async init({driver:e,logger:t,fixtures:n,orgId:o,options:i,abortController:a,limbarClient:s,generator:c,aiSettings:l}){let u={controller:a},d=i?.emulator??{},p=await sg.init({driver:e,orgId:o,limbarClient:s,options:d,aborter:u}),m=new r({generator:c,aiSettings:l,limbarClient:s,driver:e,stateManager:p,logger:t,fixtures:n,aborter:u,orgId:o,emulatorSettings:d});return await m.initializeSettings(),m}async executeCommand(e){let t=["type","a11yData","thoughts","cache","code"],n;try{n=await _s({obj:e.command,context:this.fixtures.testContext,bannedKeys:t,orgId:this.orgId,logger:this.logger,signal:this.abortSignal,localTools:this.fixtures.localCodeEvalTools})}catch(o){throw this.throwIfAborted(),new Error(`ActionFailureError: Failed to substitute template strings in command: ${o.message}`,{cause:o})}try{return await this.executeCommandHelper(e)}catch(o){throw o.name!=="AbortError"&&this.logger.error({err:o},"Error thrown in action controller"),o}finally{Ms(e.command,n)}}async executeCommandHelper({command:e}){let t=se();switch(e.type){case"TAP":return new ll(this.constructPerformerParams()).executeTap({logger:this.logger,command:e});case"TYPE":return new cg(this.constructPerformerParams()).doType(this.logger,e);case"STATE":{let n=await this.stateManager.getDomState(this.logger),o=await this.stateManager.getContexts();return{output:{xml:n.graph.xml,contexts:o},success:!0}}case"OPEN_APP":return await this.limbarClient.launchApp(e.packageName),{success:!0};case"PRESS":{let n=new lg(this.constructPerformerParams());switch(e.key){case"HOME":await n.doPress({name:"home"});break;case"POWER":await this.driver.executeInNativeContext(o=>o.isLocked())?await this.driver.executeInNativeContext(o=>o.unlock()):await this.driver.executeInNativeContext(o=>o.lock());break}return{success:!0}}case"AI_CHECK":{let o=e.timeoutSecs?e.timeoutSecs*1e3:5e3,i=Bm(o),a=Date.now(),s=0,c,l=!1,u;for(;s<15&&!l;){this.throwIfAborted(),l||c&&c-a>=o&&(l=!0),s!==0&&await J(i,this.abortSignal),c=Date.now();try{let d="",p="";await t.startAsyncSpan("EMULATOR_READ_STATE",async()=>{d=await this.getEmulatorDomState(),p=await this.getScreenshotBase64()},{name:"Get emulator state"});let m=await this.generator.evaluateIosAssertion({assertion:e.assertion,screenXml:d,screenshot:p},{logger:this.logger,loggerTags:ye(this.logger),agentConfigVersion:this.aiSettings.agentConfig?.["ios-assertion"]});if(m.result)return{success:m.result,message:m.thoughts};{let g=`AssertionFailureError: ${m.thoughts}`;u=new Error(g)}}catch(d){this.throwIfAborted(),this.logger.info({err:d},`AI check assert attempt ${s} failed, retrying...`),u=d instanceof Error?d:new Error(`${d}`)}finally{s++}}return{success:!1,message:u?.message}}default:throw new Error(`Unsupported mobile command type: ${e.type}`)}}async getMobileFailureRecoveryPlan(e){return{thoughts:"Failure recovery is not yet supported for iOS.",scenario:"INELIGIBLE",instructions:void 0}}async waitForPageSourceStability(e){return this.stateManager.waitForPageSourceStability({logger:this.logger,timeoutMs:e.timeoutMs??5e3,reason:e.reason,signal:this.aborter.controller?.signal})}async initializeSettings(){}async getScreenshotBase64(){return this.stateManager.getRawScreenshotBase64(this.logger)}async getScreenshotPngString(){return this.stateManager.getCurrentScreenshotPngString(this.logger)}async getEmulatorDomState(){return(await this.stateManager.getDomState(this.logger)).graph.xml}async getViewportBounds(){return this.stateManager.getViewportBounds()}async waitForScreenshotStability(e){return this.stateManager.waitForScreenshotStability({logger:this.logger,timeoutMs:e.timeoutMs??5e3,reason:e.reason,signal:this.aborter.controller?.signal})}resetAbortController(e){this.aborter.controller=e??new AbortController}isAborted(){return this.aborter.controller?.signal.aborted}abort(){this.aborter.controller?.abort()}async cleanup(){}get abortSignal(){return this.aborter.controller?.signal}get context(){return this.fixtures.testContext}get localCodeEvalTools(){return this.fixtures.localCodeEvalTools}};import n6 from"zod";async function DD({runTracer:r,metadata:{orgId:e,runId:t},fixtures:{logger:n,apiClient:o,mobileGenerator:i,storage:a,cacheStorage:s,usageTracker:c,browserEnricher:l,browserGenerator:u,localCodeEvalTools:d},inputs:{project:p,testDefinition:m},env:{envName:g,envVariables:h},settings:{emulatorSettings:f,aiSettings:y},options:{logLevel:E,region:b}}){let x=Math.floor(Math.random()*1e4)+4e4,P=await zo(x,"appium"),O=Za.or(n6.literal(vu)).optional().parse(b??f.region);if(O==="local")throw new Error("Local region is not supported for iOS tests, as we do not support local iOS emulators.");let R={region:O==="closest"?void 0:O},D=r6(),I=n.child({runAttemptId:D}),k;try{k=await RD({apiClient:o,logger:n,driverLogLevel:E,creationOpts:R,callbacks:{onStatusUpdate:j=>{n.debug({status:j},"Emulator status update")},onLimbarConnectionStateChange:j=>{j==="disconnected"?M.warn("Emulator websocket connection lost. Emulator may be unavailable."):(j==="reconnecting"||j==="connecting")&&M.info("Emulator websocket is reconnecting...")}},appiumPort:P,orgId:e,sessionId:D})}catch(j){let ue=`Fatal error creating iOS driver, failing test run attempt (runId: ${t})`;return n.error({err:j},ue),M.error({err:j},ue),{status:"FAILED",results:[],error:new w("UserConfigurationError",`Fatal error creating iOS driver: ${j.message}`)}}let F=await r.startAttempt({emulatorName:k.emulatorName,runAttemptId:D});I=I.child(F.loggerBindings||{});let ee=new Lo({variablesFromEnvironment:h,envName:g,testName:m.name}),K=await ug.init({driver:k.driver,generator:i,logger:I,limbarClient:k.limbarClient,orgId:e,options:{emulator:{...f,browserSettings:p.config.browser}},aiSettings:y,fixtures:{storage:a,browserEnricher:l,browserGenerator:u,localCodeEvalTools:d,testContext:ee}}),ge;try{ge=await nl({platform:"IOS",containerName:`ios test ${m.name}`,fixtures:{controller:K,logger:I,cacheStorage:s,usageTracker:c},work:{state:{failureRecoveryDisabled:y.failureRecovery===!1,failureRecoveryAttempts:0}},inputs:{testName:m.name,steps:m.steps,orgId:e,testMetadata:m},tracer:F,callbacks:{}})}finally{await k.cleanup(),await K.cleanup()}await F.finish({logger:I,results:ge.results,status:ge.status});let B;if(ge.status==="FAILED"&&ge.terminalResult){let j=ge.terminalResult.message;j?B=w.fromMessage(j):B=new w("UnknownError",j||"Unknown failure")}return{...ge,error:B}}import{cloneDeep as o6}from"lodash-es";import{debounce as i6}from"ts-debounce";var Ru="0.33.1";function a6(r){switch(r){case"PASSED":return"SUCCESS";case"FAILED":return"FAILED";case"CANCELLED":return"CANCELLED";case"RUNNING":case"PENDING":case"RETRYING":case"WAITING_FOR_USER":return"RUNNING"}}function s6(r){switch(r){case"SUCCESS":return"PASSED";case"FAILED":return"FAILED";case"CANCELLED":return"CANCELLED";case"RUNNING":return"RUNNING";case"IDLE":return"PENDING"}}var Qb=class{constructor(e,t,n,o,i,a){this.keepalive=e;this.testId=t;this.testName=n;this.diskStorage=o;this.parentTracer=i;this.orgId=a;this.interactionTracer=new Xo,rn.initializeRootTracerContext(this.interactionTracer)}children=[];finished=!1;interactionTracer;getParentStepIdChain(){return[]}recordStepDuration(e){let{durationMs:t,step:n}=e,o=n.type!=="MOBILE_PRESET_STEP"?n.type:n.command.type;nt.distribution("test_step_duration",t,[`type:${o}`,"platform:mobile","executor:cli",`orgId:${this.orgId}`])}attachBeforeScreenshot(e){let{snapshotId:t,screenshot:n}=e;this.diskStorage.storeFile({name:`${Bo}/${t}.jpeg`,contents:n})}attachAfterScreenshot(e){let{snapshotId:t,screenshot:n}=e;this.diskStorage.storeFile({name:`${Bo}/${t}.jpeg`,contents:n})}attachBeforeXmlSnapshot(e){let{snapshotId:t,xml:n}=e;this.diskStorage.storeFile({name:`${Bo}/${t}.xml`,contents:n})}attachAfterXmlSnapshot(e){let{snapshotId:t,xml:n}=e;this.diskStorage.storeFile({name:`${Bo}/${t}.xml`,contents:n})}async finishInternal(e){this.finished||(this.finished=!0,this.interactionTracer.finish(),await Promise.all(this.children.map(t=>t.finish({status:s6(e.status),finishedAt:e.finishedAt}))))}async finish(e){return await this.finishInternal({status:e.result.status,finishedAt:new Date(e.result.endTime)}),{trace:this.interactionTracer.getRootSpan()}}async startSubSteps(){let e=new cl(this.keepalive,this.testId,this.testName,this.diskStorage,this.orgId);return this.children.push(e),e}},cl=class{constructor(e,t,n,o,i){this.keepalive=e;this.testId=t;this.testName=n;this.diskStorage=o;this.orgId=i}children=[];finished=!1;async getScreenshot(e){return this.diskStorage.readFile(`${Bo}/${e}.jpeg`)}getParentStepIdChain(){return[]}async startStep(e){this.keepalive();let t=new Qb(this.keepalive,this.testId,this.testName,this.diskStorage,this,this.orgId);return this.children.push(t),t}async finish(e){this.finished||(this.finished=!0,await Promise.all(this.children.map(t=>t.finishInternal({status:a6(e.status),finishedAt:e.finishedAt}))))}},eE=class{constructor(e,t,n,o,i,a,s){this.keepalive=e;this.testId=t;this.testName=n;this.runAttemptId=o;this.metadata=i;this.diskStorage=a;this.orgId=s;this.diskStorage.mkdir("assets"),this.logStream=this.diskStorage.createFileStream("assets/logs.logcat"),this.resourceUsageStream=this.diskStorage.createFileStream(`${Bo}/resource-usage.ndjson`),this.resourceUsageSampler=UR({keepSamples:!1,onSample:c=>{this.resourceUsageStream.write(`${JSON.stringify(c)}
4651
4651
  `)}})}finished=!1;children=[];logStream;resourceUsageStream;resourceUsageSampler;get loggerBindings(){return{runAttemptId:this.runAttemptId}}appendLogs(e){let t=e.join(`
4652
4652
  `);this.logStream.write(t+`
4653
4653
  `)}async finish(e){if(this.finished)return;this.finished=!0;let{logger:t,status:n,results:o,beforeResults:i,afterResults:a}=e,s={...this.metadata,status:n,assetDetails:e.assetDetails,finishedAt:new Date,results:Ld(o,t),beforeResults:i?Ld(i,t):void 0,afterResults:a?Ld(a,t):void 0};await Promise.all(this.children.map(c=>c.finish({status:s.status,finishedAt:s.finishedAt})));try{this.logStream.end()}catch{}try{this.resourceUsageSampler.stop(),this.resourceUsageStream.end()}catch{}this.diskStorage.storeFile({name:"metadata.json",contents:JSON.stringify(s,null,2)})}async startBeforeStepList(){let e=new cl(this.keepalive,this.testId,this.testName,this.diskStorage,this.orgId);return this.children.push(e),e}async startMainStepList(){let e=new cl(this.keepalive,this.testId,this.testName,this.diskStorage,this.orgId);return this.children.push(e),e}async startAfterStepList(){let e=new cl(this.keepalive,this.testId,this.testName,this.diskStorage,this.orgId);return this.children.push(e),e}async getScreenshot(e,t){return this.diskStorage.readFile(`${Bo}/${t}.jpeg`)}},tE=class{constructor(e,t,n,o,i,a,s){this.client=e;this.testId=t;this.testName=n;this.runId=o;this.metadata=i;this.diskStorage=a;this.orgId=s}children=[];finished=!1;get loggerBindings(){return{runId:this.runId}}async finish(e){if(this.finished)return;this.finished=!0;let t={...this.metadata,finishedAt:e.finishedAt||new Date,status:e.status,failureDetails:e.failureDetails,failureReason:e.failureReason,flake:e.isFlake||!1,failureRecoveryDetails:e.failureRecoveryDetails};await Promise.all(this.children.map(n=>n.finish({logger:e.logger,status:t.status,results:[],beforeResults:[],afterResults:[]}))),this.diskStorage.storeFile({name:"metadata.json",contents:JSON.stringify(t,null,2)}),this.diskStorage.close()}async startAttempt(e){let{runAttemptId:t}=e;this.metadata.attempts=this.metadata.attempts+1,this.metadata.status="RUNNING",this.diskStorage.storeFile({name:"metadata.json",contents:JSON.stringify(this.metadata,null,2)});let n=this.diskStorage.cd(`attempts/${this.metadata.attempts}`),o={id:t,schemaVersion:Co,runAttemptSchemaVersion:aR,startedAt:new Date,status:"RUNNING"};n.storeFile({name:"metadata.json",contents:JSON.stringify(o,null,2)});let i=i6(async()=>{await this.client.extendAndroidEmulatorTtl(e.emulatorName)},3e4,{maxWait:6e4}),a=new eE(()=>void i(),this.testId,this.testName,t,o,n,this.orgId);return this.children.push(a),a}},dg=class r{constructor(e,t,n,o,i){this.orgId=e;this.runGroupId=t;this.metadata=n;this.client=o;this.diskStorage=i}children=[];finished=!1;get loggerBindings(){return{orgId:this.orgId,runGroupId:this.runGroupId,branch:this.metadata.gitBranchName}}static async start({orgId:e,runGroupId:t,outputDir:n,client:o,gitMetadata:i,labels:a,suiteName:s}){let c={...i,suiteName:s,id:t,trigger:wr.CLI,startedAt:new Date,status:"RUNNING",cliVersion:Ru,labels:a??[]},l=new Su(n);return l.storeFile({name:"metadata.json",contents:JSON.stringify(c,null,2)}),new r(e,t,c,o,l)}async finish(e){if(this.finished)return;this.finished=!0;let{status:t}=e,n={...this.metadata,status:t,updatedAt:new Date,finishedAt:new Date};await Promise.all(this.children.map(o=>o.finish({logger:e.logger,status:n.status,finishedAt:n.finishedAt}))),this.diskStorage.storeFile({name:"metadata.json",contents:JSON.stringify(n,null,2)})}async startRun(e){let t=this.diskStorage.createRunArchive(e.runId),n={stepsSnapshot:e.originalSteps.steps,runGroupId:this.runGroupId,testId:e.testId,testName:e.testName,testDescription:e.testDescription,directory:e.directory,labels:e.testLabels,trigger:"CLI",status:"RUNNING",environmentName:e.environmentName,cliVersion:Ru,schemaVersion:e.schemaVersion,startedAt:new Date,attempts:0,quarantined:e.quarantined,quarantinedReason:e.quarantinedReason,executionType:Fl(e.platform),aiSettings:e.aiSettings};t.storeFile({name:"metadata.json",contents:JSON.stringify(n,null,2)});let o=new tE(this.client,e.testId,e.testName,e.runId,n,t,this.orgId);return this.children.push(o),o}};function kD(r){return{platform:r.platform,originalSteps:{steps:o6(r.steps),beforeSteps:void 0,afterSteps:void 0}}}async function FD(r){let{inputs:e,fixtures:t,metadata:n}=r,{tracer:o,logger:i}=t,{runId:a}=n,{platform:s,testDefinition:c,project:l}=e,u=new Date,d=await o.startRun({...kD(c),logger:i,testId:c.id,testName:c.name,directory:l6(c.relativeFilePath),runId:a,testDescription:c.description,testLabels:c.labels,schemaVersion:c.schemaVersion,quarantined:c.quarantined,quarantinedReason:c.quarantinedMetadata?.quarantinedReason,aiSettings:l.config.ai}),p=i.child(d.loggerBindings||{}),m=1+(c.settings?.retries??l.config.retries??1);for(let g=0;g<m;g++){let h=new Date,f=await c6({...r,runTracer:d,fixtures:{...t,logger:p},constants:{attemptNumber:g,totalAttempts:m}}),y=new Date;if(f.status!=="FAILED")return await d.finish({logger:p,status:f.status,failureRecoveryDetails:f.failureRecoveryDetails,finishedAt:y}),{...f,testMetadata:c,platformType:Fl(s),steps:c.steps,startedAt:u,lastAttemptStartedAt:h,finishedAt:y,runId:a,attempts:g+1,filePath:c.relativeFilePath,quarantined:c.quarantined,quarantinedMetadata:c.quarantinedMetadata,status:f.status};if(g!==m-1){p.warn("Retrying failed mobile run");continue}p.error("Mobile test failed after all exhausting attempts");let E={failureReason:f.error?.reason,failureDetails:f.error?{errorMessage:f.error.message,errorStack:f.error.stack}:void 0};return await d.finish({logger:p,status:f.status,...E,finishedAt:y}),{...f,testMetadata:c,platformType:Fl(s),steps:c.steps,startedAt:u,lastAttemptStartedAt:h,finishedAt:y,runId:a,...E,attempts:g+1,filePath:c.relativeFilePath,quarantined:c.quarantined,quarantinedMetadata:c.quarantinedMetadata,status:f.status}}throw new Error("This code should not be reachable")}async function c6(r){let{runTracer:e,metadata:t,constants:n,fixtures:o,inputs:i,options:a}=r,{attemptNumber:s,totalAttempts:c}=n,{orgId:l,gitMetadata:u}=t,{apiClient:d,logger:p,usageTracker:m}=o,{testDefinition:g,logUpdate:h,project:f,envOverride:y}=i,{regenerateCache:E,alwaysSaveCache:b,noCache:x}=a;s!==0&&h("RETRY",`attempt ${s}/${c}`);let P={...i.project.config.emulator,...g.settings?.emulator},O={...f.config.ai,useMemory:f.config.ai?.useMemory!==!1,...g.settings?.ai},T=y||g.settings?.defaultEnv,D=(T?da(T,f,p):void 0)?.variables??{},I=mi({logger:p,orgId:l,client:d,gitMetadata:u,regenerateCache:E,alwaysSaveCache:b,noCache:x}),k=new Xs(d,l),F={type:"API_KEY",baseUrl:d.baseUrl,apiKey:d.apiKey,logger:p,mode:"runner"},ee=new Qs(F),K=new ha(O.agentConfig,F),ge=new Ys(F,K),B=new Zs({httpClient:d,fakerSeed:f.config.advanced?.fakerConstantSeed?gd:void 0}),j={orgId:l,runTracer:e,metadata:t,options:a,fixtures:{logger:p,apiClient:d,mobileGenerator:ee,storage:k,cacheStorage:I,usageTracker:m,browserEnricher:ge,browserGenerator:K,localCodeEvalTools:B},env:{envName:T,envVariables:D},settings:{aiSettings:O,emulatorSettings:P}};switch(i.platform){case"ANDROID":return await vD({...j,inputs:i});case"IOS":return await DD({...j,inputs:i})}}import{existsSync as p6,mkdirSync as g6,statSync as h6}from"fs";import f6 from"path";import{z as Iut}from"zod";import u6 from"junit-report-builder";import mg from"path";function UD(r,e){r.property("quarantined","true"),r.property("dd_tags[quarantined]","true"),e.quarantinedReason&&(r.property("quarantined_reason",e.quarantinedReason),r.property("dd_tags[quarantined_reason]",e.quarantinedReason)),e.quarantinedAt&&(r.property("quarantined_at",e.quarantinedAt.toISOString()),r.property("dd_tags[quarantined_at]",e.quarantinedAt.toISOString()))}function d6(r,e){if(e.name(r.testName).className(r.testName).file(mg.relative(".",r.filePath)).property("id",r.testId).property("dd_tags[id]",r.testId),r.labels&&(e.property("labels",r.labels.join(",")),r.labels.forEach(t=>{e.property("dd_tags[label]",t)})),r.baseUrl&&(e.property("base_url",r.baseUrl),e.property("dd_tags[base_url]",r.baseUrl)),r.runId&&(e.property("run_url",`https://app.momentic.ai/runs/${r.runId}`),e.property("dd_tags[run_url]",`https://app.momentic.ai/runs/${r.runId}`)),r.quarantinedMetadata&&UD(e,r.quarantinedMetadata),r.setupFailed&&(e.property("setup_failed","true"),e.property("dd_tags[setup_failed]","true")),r.mainFailed&&(e.property("main_failed","true"),e.property("dd_tags[main_failed]","true")),r.teardownFailed&&(e.property("teardown_failed","true"),e.property("dd_tags[teardown_failed]","true")),r.status==="FAILED"){if(r.failureReason){let t=Mg[r.failureDetails?.classification?.reason||r.failureReason],n=r.failureDetails?.classification?.summary||Bu[r.failureReason];r.runId&&(n+=` Visit https://app.momentic.ai/runs/${r.runId} for more details.`),e.failure(n,t)}r.failureDetails?.errorStack&&e.stacktrace(r.failureDetails.errorStack)}else r.status==="CANCELLED"&&e.skipped();return e.time((r.finishedAt.getTime()-r.lastAttemptStartedAt.getTime())/1e3).property("started_at",r.lastAttemptStartedAt.toISOString()).property("dd_tags[started_at]",r.lastAttemptStartedAt.toISOString()).property("finished_at",r.finishedAt.toISOString()).property("dd_tags[finished_at]",r.finishedAt.toISOString()),e.property("attempts",r.attempts.toString()).property("dd_tags[attempts]",r.attempts.toString()),r.parameters?.envName&&(e.property("environment",r.parameters.envName),e.property("dd_tags[environment]",r.parameters.envName)),r.parameters?.urlOverride&&e.property("url_override",r.parameters.urlOverride),e}function m6(r,e,t){let{suiteId:n,suiteName:o,startedAt:i,finishedAt:a,testsToSkip:s,quarantinedTestsToSkip:c,quarantinedTestsMetadata:l}=e,u=r.testSuite().name(o);n&&u.property("id",n),u.timestamp(i).property("startedAt",i.toISOString()).property("finishedAt",a.toISOString()).time((a.getTime()-i.getTime())/1e3);for(let d of t){let p=u.testCase();d6(d,p)}for(let d of s){let p=u.testCase();p.name(d.name).className(d.name).file(mg.relative(".",d.relativeFilePath)).property("id",d.id),d.baseUrl&&p.property("baseUrl",d.baseUrl),d.labels&&(p.property("labels",d.labels.join(",")),d.labels.forEach(m=>{p.property("dd_tags[label]",m)})),p.skipped()}for(let d of c){let p=u.testCase();p.name(d.name).className(d.name).file(mg.relative(".",d.relativeFilePath)).property("id",d.id);let m=l[d.id];m&&UD(p,m),d.baseUrl&&p.property("baseUrl",d.baseUrl),d.labels&&(p.property("labels",d.labels.join(",")),d.labels.forEach(g=>{p.property("dd_tags[label]",g)})),p.skipped()}return u}function rE(r,e,t){let n=u6.newBuilder();m6(n,e,t),n.writeTo(mg.join(r,`${e.suiteName}.xml`))}function S6(r){return{testName:f6.basename(r.filePath,".test.yaml")||r.filePath.split("/").pop()?.replace(".yaml","")||r.filePath,testId:r.testMetadata.id,filePath:r.filePath,labels:r.testMetadata.labels,baseUrl:void 0,runId:r.runId,quarantined:r.quarantined,quarantinedMetadata:r.quarantinedMetadata,status:r.status,setupFailed:void 0,mainFailed:void 0,teardownFailed:void 0,failureDetails:r.failureDetails,failureReason:r.failureReason,finishedAt:r.finishedAt,lastAttemptStartedAt:r.lastAttemptStartedAt,attempts:r.attempts,parameters:r.parameters}}async function BD({format:r,params:e,runs:t,folder:n}){switch(p6(n)?h6(n).isDirectory()||(M.error(`The specified reporter output directory '${n}' exists on disk but is not a folder. Please move or delete the existing object or specify a different reporter path.`),process.exit(1)):(M.info(`Reporter output directory '${n}' does not exist on disk, creating it now...`),g6(n,{recursive:!0})),r){case"junit":{let o=t.map(S6);rE(n,e,o);return}case"allure":case"allure-json":M.error(`The specified reporter format '${r}' is not supported for mobile tests.`);return;case"playwright-json":M.error(`The specified reporter format '${r}' is not supported for mobile tests.`);return;default:throw new Error(`Unknown reporter format requested: '${r}'`)}}async function zD(r,e,t){if(t)return{};try{return(await e.getQuarantinedTests()).quarantined.reduce((o,i)=>(o[i.testId]={quarantinedAt:i.quarantinedAt,quarantinedReason:i.quarantinedReason},o),{})}catch(n){return r.warn({err:n},"Failed to fetch quarantined tests, proceeding without them."),{}}}async function yo(){try{await Y(Promise.all([SR(),nt.flush()]),{milliseconds:5e3})}catch{}}async function HD(r){let{options:e,fixtures:t,inputs:n,metadata:o}=r,{project:i,apiClient:a,logger:s}=t,{orgId:c,runGroupId:l,gitMetadata:u}=o,{suiteName:d,outputDir:p,parallel:m}=e;b6(p)&&M.warn(`Output directory ${p} already exists, removing before test execution...`);let g=wR({items:n.testDefinitions,shardIndex:e.shardIndex??1,shardCount:e.shardCount??1,sortKey:F=>F.relativeFilePath}),h=new Set;n.testDefinitions.forEach(F=>{F.labels?.forEach(ee=>h.add(ee))});let f=s.child({orgId:c,runGroupId:l,branch:u.gitBranchName}),y=await dg.start({suiteName:d,logger:f,orgId:c,runGroupId:l,outputDir:p,client:a,gitMetadata:u,labels:Array.from(h)}),E=[],b=new Date,x=new Set,P=async()=>E6({runResults:E,startTime:b,ranTests:x,apiClient:a,uploadResults:e.uploadResults??!1,outputDir:p}),O=async F=>{M.warn(`${F} Stopping tests and printing latest results.`),await y.finish({logger:f,status:"CANCELLED"}),await P(),await yo(),process.exit(1)},T=async()=>{await O("SIGINT received.")};process.once("SIGINT",T);let R;if(e.timeoutMinutes!==void 0&&e.timeoutMinutes>0){let F=e.timeoutMinutes*60*1e3;R=setTimeout(()=>{O(`Timeout of ${e.timeoutMinutes} minute(s) reached.`)},F)}let D={};for(let F=0;F<g.length;F++){let ee=Object.values(D);ee.length===m&&await Promise.race(ee.map(B=>B.promise));let K=g[F],ge=`test-${F}`;D[ge]={done:!1,promise:(async({testDefinition:B})=>{x.add(ge);let j=B.relativeFilePath.includes("..")?B.fullFilePath:B.relativeFilePath;Ec({status:"START",testLogRef:j,getRunningTestsCount:()=>x.size,getTotalTestsCount:()=>g.length});let ue=setInterval(()=>Ec({status:"RUN",testLogRef:j,getRunningTestsCount:()=>x.size,getTotalTestsCount:()=>g.length}),5*60*1e3),le=y6(),He=f.child({testId:B.id,runId:le}),ve=new Gm({logger:He,reporter:new Up(a),runType:"mobile-test-run",runId:le,testMetadata:B,suiteMetadata:void 0});try{let q={platform:B.platform,testDefinition:B},fe=await FD({metadata:{...o,runId:le},fixtures:{...t,tracer:y,logger:He,usageTracker:ve},inputs:{...n,...q,project:i,channel:n.channel??B.settings?.defaultChannel,tag:n.tag??B.settings?.defaultTag,logUpdate:(it,Ae)=>Ec({status:it,testLogRef:j,getRunningTestsCount:()=>x.size,getTotalTestsCount:()=>g.length,additionalText:Ae})},options:e});Ec({status:fe.status,testLogRef:j,getRunningTestsCount:()=>x.size,getTotalTestsCount:()=>g.length}),E.push(fe)}catch(q){let fe=`Encountered unexpected fatal error when running test '${B.name}': ${q.message}